# 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](https://nodejs.org)) - **pnpm** 9.15+ (`corepack enable && corepack prepare pnpm@9.15.4 --activate`) - **Rust** 1.83+ ([rustup.rs](https://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 ```bash git clone https://github.com/your-org/source-gamepanel.git cd source-gamepanel pnpm install ``` ### 1.2 Environment Configuration ```bash cp .env.example .env ``` Edit `.env` and set at minimum: ```env # Generate secure secrets: # node -e "console.log(require('crypto').randomBytes(64).toString('hex'))" JWT_SECRET= JWT_REFRESH_SECRET= # Database (defaults work with docker-compose.dev.yml) DATABASE_URL=postgresql://gamepanel:gamepanel@localhost:5432/gamepanel ``` ### 1.3 Start Infrastructure ```bash # Start PostgreSQL + Redis docker compose -f docker-compose.dev.yml up -d ``` ### 1.4 Database Setup ```bash # 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 ```bash # 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: ```bash # 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 ```bash 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 ```bash git clone https://github.com/your-org/source-gamepanel.git cd source-gamepanel cp .env.example .env ``` Edit `.env` with production values: ```env # REQUIRED — Generate unique secrets for each! JWT_SECRET= JWT_REFRESH_SECRET= # Database DB_USER=gamepanel DB_PASSWORD= DB_NAME=gamepanel # Redis REDIS_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`: ```yaml api_url: "http://api:3000" node_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 ```bash # 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 ```bash # 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: ```bash # Run migrations from your host machine pointed at the Docker PostgreSQL DATABASE_URL=postgresql://gamepanel:@localhost:5432/gamepanel pnpm db:migrate DATABASE_URL=postgresql://gamepanel:@localhost:5432/gamepanel pnpm db:seed ``` ### 2.5 Verify ```bash # 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 # ... ``` ### 2.6 Monitoring ```bash # 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 ```bash 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 ```bash 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 ```bash sudo sed -i 's/# requirepass foobared/requirepass your-redis-password/' /etc/redis/redis.conf sudo systemctl restart redis-server ``` ### 3.4 Application Setup ```bash # 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 ```bash 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:** ```bash 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:** ```bash 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:** ```bash sudo systemctl daemon-reload sudo systemctl enable --now gamepanel-api sudo systemctl enable --now gamepanel-daemon ``` ### 3.7 Web Build + nginx ```bash # 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:** ```bash 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 ```bash sudo certbot --nginx -d panel.yourdomain.com ``` Certbot will automatically configure nginx for HTTPS and set up auto-renewal. ### 3.9 Firewall ```bash 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: ```bash # 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: "" 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 ` - Or run the daemon with appropriate privileges ### protoc not found (daemon build) - Ubuntu: `sudo apt install protobuf-compiler` - macOS: `brew install protobuf` - Or download from [github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases) --- ## Updating ### Docker ```bash cd /opt/source-gamepanel git pull docker compose up -d --build ``` ### Manual ```bash 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 |