631 lines
15 KiB
Markdown
631 lines
15 KiB
Markdown
# 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=<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
|
|
|
|
```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=<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`:
|
|
|
|
```yaml
|
|
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
|
|
|
|
```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:<your-password>@localhost:5432/gamepanel pnpm db:migrate
|
|
DATABASE_URL=postgresql://gamepanel:<your-password>@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
|
|
# <!DOCTYPE html>...
|
|
```
|
|
|
|
### 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: "<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)
|
|
- 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 |
|