chore: initial commit for main
This commit is contained in:
+630
@@ -0,0 +1,630 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user