source-gamepanel/INSTALLATION.md

15 KiB

Installation Guide

This guide covers three deployment methods:

  1. Development Setup — for local development
  2. Docker Production — single-command deployment with Docker Compose
  3. Manual Production — step-by-step on Ubuntu 22.04+

Prerequisites

All Methods

  • Git
  • A PostgreSQL 16+ database (or use the included Docker Compose)

Development

  • Node.js 20+ (nodejs.org)
  • pnpm 9.15+ (corepack enable && corepack prepare pnpm@9.15.4 --activate)
  • Rust 1.83+ (rustup.rs)
  • protoc (Protocol Buffers compiler) — required for the daemon's gRPC build
  • Docker — for running PostgreSQL and Redis locally

Docker Production

  • Docker 24+ with Docker Compose v2
  • At least 2 GB RAM and 10 GB disk for the panel itself
  • Additional resources for game servers on daemon nodes

1. Development Setup

1.1 Clone and Install

git clone https://github.com/your-org/source-gamepanel.git
cd source-gamepanel
pnpm install

1.2 Environment Configuration

cp .env.example .env

Edit .env and set at minimum:

# Generate secure secrets:
# node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
JWT_SECRET=<your-64-byte-hex>
JWT_REFRESH_SECRET=<another-64-byte-hex>

# Database (defaults work with docker-compose.dev.yml)
DATABASE_URL=postgresql://gamepanel:gamepanel@localhost:5432/gamepanel

1.3 Start Infrastructure

# Start PostgreSQL + Redis
docker compose -f docker-compose.dev.yml up -d

1.4 Database Setup

# Generate migration files (if schema changed)
pnpm db:generate

# Apply migrations to create all tables
pnpm db:migrate

# Seed admin user and default games
pnpm db:seed

After seeding, you'll have:

  • Admin account: admin@gamepanel.local / admin123
  • Games: Minecraft Java, CS2, Minecraft Bedrock, Terraria, Rust

1.5 Start Development Servers

# Start API (port 3000) + Web (port 5173) via Turborepo
pnpm dev

The web dev server proxies /api and /socket.io requests to the API automatically.

Open http://localhost:5173 in your browser.

1.6 Daemon (Optional)

The Rust daemon manages Docker containers on game server nodes. For development you can run it locally:

# Ensure protoc is installed
protoc --version  # Should show libprotoc 3.x or higher

# If not installed:
# Ubuntu: sudo apt install protobuf-compiler
# macOS: brew install protobuf
# Windows: choco install protoc (or download from GitHub releases)

cd apps/daemon
cargo run

The daemon reads its config from /etc/gamepanel/config.yml or the path in DAEMON_CONFIG env var. For development, it falls back to defaults (API at localhost:3000, dev token).

1.7 Useful Commands

pnpm build            # Build all packages
pnpm lint             # ESLint across all packages
pnpm format           # Prettier format
pnpm format:check     # Check formatting without modifying
pnpm db:studio        # Open Drizzle Studio (visual DB browser)

# Daemon
cd apps/daemon
cargo test            # Run unit tests (3 tests: Minecraft parser, CS2 parser)
cargo clippy          # Rust linter
cargo build --release # Production build

2. Docker Production Deployment

2.1 Prepare Environment

git clone https://github.com/your-org/source-gamepanel.git
cd source-gamepanel

cp .env.example .env

Edit .env with production values:

# REQUIRED — Generate unique secrets for each!
JWT_SECRET=<generate-with-openssl-rand-hex-64>
JWT_REFRESH_SECRET=<generate-another-secret>

# Database
DB_USER=gamepanel
DB_PASSWORD=<strong-random-password>
DB_NAME=gamepanel

# Redis
REDIS_PASSWORD=<strong-random-password>

# Networking
CORS_ORIGIN=https://panel.yourdomain.com
WEB_PORT=80
API_PORT=3000

# Rate limiting
RATE_LIMIT_MAX=100
RATE_LIMIT_WINDOW_MS=60000

2.2 Configure Daemon

Edit daemon-config.yml:

api_url: "http://api:3000"
node_token: "<generate-a-secure-token>"
grpc_port: 50051
data_path: "/var/lib/gamepanel/servers"
backup_path: "/var/lib/gamepanel/backups"
docker:
  socket: "/var/run/docker.sock"
  network: "gamepanel_nw"
  network_subnet: "172.18.0.0/16"

2.3 Build and Start

# Build and start all services
docker compose up -d --build

This starts 5 services:

Service Port Description
postgres 5432 PostgreSQL database
redis 6379 Rate limiting & cache
api 3000 Fastify REST API
web 80 nginx + React SPA
daemon 50051 Rust gRPC daemon

2.4 Initialize Database

# Run migrations
docker compose exec api node -e "
  import('drizzle-kit').then(m => console.log('Use drizzle-kit migrate'))
"

# Or use the pnpm scripts with the container's DATABASE_URL
docker compose exec api sh -c 'cd /app && node apps/api/dist/index.js'

For the initial setup, the easiest approach is:

# Run migrations from your host machine pointed at the Docker PostgreSQL
DATABASE_URL=postgresql://gamepanel:<your-password>@localhost:5432/gamepanel pnpm db:migrate
DATABASE_URL=postgresql://gamepanel:<your-password>@localhost:5432/gamepanel pnpm db:seed

2.5 Verify

# Check all services are healthy
docker compose ps

# Test API health
curl http://localhost:3000/api/health
# {"status":"ok","timestamp":"2025-..."}

# Test web
curl -s http://localhost | head -5
# <!DOCTYPE html>...

2.6 Monitoring

# View logs
docker compose logs -f api
docker compose logs -f daemon
docker compose logs -f web

# Restart a service
docker compose restart api

# Update to latest
git pull
docker compose up -d --build

3. Manual Production Setup (Ubuntu 22.04+)

3.1 System Dependencies

sudo apt update && sudo apt upgrade -y

# Node.js 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# pnpm
corepack enable
corepack prepare pnpm@9.15.4 --activate

# PostgreSQL 16
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo apt install -y postgresql-16

# Redis
sudo apt install -y redis-server

# Docker (for game containers)
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER

# Rust (for daemon)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# protoc (for gRPC)
sudo apt install -y protobuf-compiler

# nginx (reverse proxy)
sudo apt install -y nginx certbot python3-certbot-nginx

3.2 Database Setup

sudo -u postgres psql << 'EOF'
CREATE USER gamepanel WITH PASSWORD 'your-strong-password';
CREATE DATABASE gamepanel OWNER gamepanel;
GRANT ALL PRIVILEGES ON DATABASE gamepanel TO gamepanel;
EOF

3.3 Redis Configuration

sudo sed -i 's/# requirepass foobared/requirepass your-redis-password/' /etc/redis/redis.conf
sudo systemctl restart redis-server

3.4 Application Setup

# Clone
cd /opt
sudo git clone https://github.com/your-org/source-gamepanel.git
sudo chown -R $USER:$USER source-gamepanel
cd source-gamepanel

# Install
pnpm install

# Environment
cp .env.example .env
nano .env  # Set all production values

# Build
pnpm build

# Database
pnpm db:migrate
pnpm db:seed

# Build daemon
cd apps/daemon
cargo build --release
sudo cp target/release/gamepanel-daemon /usr/local/bin/

3.5 Daemon Configuration

sudo mkdir -p /etc/gamepanel /var/lib/gamepanel/{servers,backups}

sudo tee /etc/gamepanel/config.yml << 'EOF'
api_url: "http://127.0.0.1:3000"
node_token: "generate-a-secure-token-here"
grpc_port: 50051
data_path: "/var/lib/gamepanel/servers"
backup_path: "/var/lib/gamepanel/backups"
docker:
  socket: "/var/run/docker.sock"
  network: "gamepanel_nw"
  network_subnet: "172.18.0.0/16"
EOF

3.6 Systemd Services

API Service:

sudo tee /etc/systemd/system/gamepanel-api.service << 'EOF'
[Unit]
Description=GamePanel API
After=network.target postgresql.service redis-server.service
Requires=postgresql.service

[Service]
Type=simple
User=gamepanel
WorkingDirectory=/opt/source-gamepanel
ExecStart=/usr/bin/node apps/api/dist/index.js
Restart=always
RestartSec=5
EnvironmentFile=/opt/source-gamepanel/.env
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
EOF

Daemon Service:

sudo tee /etc/systemd/system/gamepanel-daemon.service << 'EOF'
[Unit]
Description=GamePanel Daemon
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
ExecStart=/usr/local/bin/gamepanel-daemon
Restart=always
RestartSec=5
Environment=DAEMON_CONFIG=/etc/gamepanel/config.yml
Environment=RUST_LOG=info

[Install]
WantedBy=multi-user.target
EOF

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now gamepanel-api
sudo systemctl enable --now gamepanel-daemon

3.7 Web Build + nginx

# Build the SPA
cd /opt/source-gamepanel/apps/web
pnpm build  # outputs to dist/

# Copy to nginx
sudo mkdir -p /var/www/gamepanel
sudo cp -r dist/* /var/www/gamepanel/

nginx site config:

sudo tee /etc/nginx/sites-available/gamepanel << 'EOF'
server {
    listen 80;
    server_name panel.yourdomain.com;
    root /var/www/gamepanel;
    index index.html;

    # Gzip
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;

    # API proxy
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Socket.IO
    location /socket.io/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

    # Static assets
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # SPA fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}
EOF

sudo ln -sf /etc/nginx/sites-available/gamepanel /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

3.8 TLS with Let's Encrypt

sudo certbot --nginx -d panel.yourdomain.com

Certbot will automatically configure nginx for HTTPS and set up auto-renewal.

3.9 Firewall

sudo ufw allow 22/tcp      # SSH
sudo ufw allow 80/tcp      # HTTP
sudo ufw allow 443/tcp     # HTTPS
sudo ufw allow 50051/tcp   # gRPC (daemon)
# Open game server port ranges as needed:
sudo ufw allow 25565/tcp   # Minecraft
sudo ufw allow 27015/tcp   # CS2
sudo ufw enable

Post-Installation

First Login

  1. Open your panel URL in a browser
  2. Login with: admin@gamepanel.local / admin123
  3. Immediately change the admin password via account settings

Create Your First Server

  1. Create an Organization — Click "New Organization" on the home page
  2. Add a Node — Go to Nodes, add your daemon node (FQDN + ports)
  3. Add Allocations — Assign IP:port pairs to the node
  4. Create a Server — Use the creation wizard: pick a game, node, and resources
  5. Start the Server — Use the power controls on the console page

Adding a Remote Daemon Node

On the remote machine:

# Install Docker
curl -fsSL https://get.docker.com | sh

# Install the daemon binary
scp user@panel-server:/usr/local/bin/gamepanel-daemon /usr/local/bin/

# Configure
mkdir -p /etc/gamepanel /var/lib/gamepanel/{servers,backups}

cat > /etc/gamepanel/config.yml << EOF
api_url: "https://panel.yourdomain.com"
node_token: "<token-from-panel>"
grpc_port: 50051
EOF

# Create systemd service (same as above)
# Start it
systemctl enable --now gamepanel-daemon

Then add the node in the panel with the remote machine's FQDN.


Troubleshooting

API won't start

  • Check DATABASE_URL is correct and PostgreSQL is running
  • Ensure migrations have been applied: pnpm db:migrate
  • Check logs: journalctl -u gamepanel-api -f or docker compose logs api

Daemon can't connect

  • Verify api_url in daemon config points to the API
  • Check node_token matches what's stored in the panel's nodes table
  • Ensure the daemon's gRPC port (50051) is open

Web shows blank page

  • Build the SPA: pnpm --filter @source/web build
  • Check nginx config: sudo nginx -t
  • Verify API proxy is working: curl http://localhost:3000/api/health

Docker permission denied

  • Ensure the daemon user is in the docker group: usermod -aG docker <user>
  • Or run the daemon with appropriate privileges

protoc not found (daemon build)


Updating

Docker

cd /opt/source-gamepanel
git pull
docker compose up -d --build

Manual

cd /opt/source-gamepanel
git pull
pnpm install
pnpm build
pnpm db:migrate

# Rebuild daemon
cd apps/daemon && cargo build --release
sudo cp target/release/gamepanel-daemon /usr/local/bin/

# Rebuild web
cd ../web && pnpm build
sudo cp -r dist/* /var/www/gamepanel/

# Restart services
sudo systemctl restart gamepanel-api gamepanel-daemon
sudo systemctl reload nginx

Environment Variables Reference

Variable Default Description
DATABASE_URL PostgreSQL connection string
DB_USER gamepanel PostgreSQL username (Docker)
DB_PASSWORD gamepanel PostgreSQL password (Docker)
DB_NAME gamepanel Database name (Docker)
DB_PORT 5432 PostgreSQL exposed port
REDIS_URL Redis connection string
REDIS_PASSWORD gamepanel Redis password
PORT 3000 API listen port
HOST 0.0.0.0 API listen host
NODE_ENV development Environment mode
JWT_SECRET Required. Access token signing key
JWT_REFRESH_SECRET Required. Refresh token signing key
CORS_ORIGIN http://localhost:5173 Allowed CORS origin
RATE_LIMIT_MAX 100 Max requests per window
RATE_LIMIT_WINDOW_MS 60000 Rate limit window (ms)
WEB_PORT 80 Web nginx exposed port
API_PORT 3000 API exposed port (Docker)
DAEMON_CONFIG /etc/gamepanel/config.yml Daemon config file path
DAEMON_GRPC_PORT 50051 Daemon gRPC exposed port