619 lines
14 KiB
Markdown
619 lines
14 KiB
Markdown
# Production Deployment Guide
|
|
|
|
This guide walks you through deploying the Faction War Dispatch Bot to a production server.
|
|
|
|
## Table of Contents
|
|
1. [Security Considerations](#security-considerations)
|
|
2. [Server Requirements](#server-requirements)
|
|
3. [Installation Steps](#installation-steps)
|
|
4. [SSL/HTTPS Setup](#sslhttps-setup)
|
|
5. [Free Domain Setup](#free-domain-setup)
|
|
6. [Systemd Service Setup](#systemd-service-setup)
|
|
7. [Firewall Configuration](#firewall-configuration)
|
|
8. [Monitoring & Maintenance](#monitoring--maintenance)
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
### Critical Security Steps (DO BEFORE DEPLOYMENT!)
|
|
|
|
1. **Change Default Secrets**
|
|
```bash
|
|
# Generate a strong random password
|
|
openssl rand -base64 32
|
|
|
|
# Generate a strong JWT secret
|
|
openssl rand -hex 64
|
|
```
|
|
|
|
2. **Never Commit Secrets to Git**
|
|
- Use `.env` file for secrets (already in `.gitignore`)
|
|
- Or use the Settings page to configure via web UI
|
|
- Keep `data/config.json` out of version control (already in `.gitignore`)
|
|
|
|
3. **HTTPS is REQUIRED**
|
|
- JWT tokens and passwords are transmitted over the network
|
|
- Without HTTPS, credentials can be intercepted
|
|
- See [SSL/HTTPS Setup](#sslhttps-setup) below
|
|
|
|
4. **Firewall Configuration**
|
|
- Only expose port 443 (HTTPS) or 80 (HTTP - redirects to HTTPS)
|
|
- Block port 8000 from external access (use reverse proxy)
|
|
- See [Firewall Configuration](#firewall-configuration) below
|
|
|
|
5. **Keep Dependencies Updated**
|
|
```bash
|
|
pip install --upgrade -r requirements.txt
|
|
```
|
|
|
|
6. **Backup Your Data**
|
|
- Backup the `data/` directory regularly
|
|
- Contains group assignments, Discord mappings, and config
|
|
|
|
---
|
|
|
|
## Server Requirements
|
|
|
|
### Minimum Specs
|
|
- **OS**: Ubuntu 20.04+ / Debian 11+ (or any Linux distribution)
|
|
- **RAM**: 512MB minimum, 1GB recommended
|
|
- **CPU**: 1 core minimum
|
|
- **Storage**: 5GB minimum
|
|
- **Network**: Static IP or dynamic DNS
|
|
|
|
### Required Software
|
|
- Python 3.11+
|
|
- Nginx (reverse proxy)
|
|
- Certbot (for SSL certificates)
|
|
- systemd (process management)
|
|
|
|
---
|
|
|
|
## Installation Steps
|
|
|
|
### 1. Initial Server Setup
|
|
|
|
```bash
|
|
# Update system packages
|
|
sudo apt update && sudo apt upgrade -y
|
|
|
|
# Install required packages
|
|
sudo apt install -y python3 python3-pip python3-venv nginx certbot python3-certbot-nginx git
|
|
|
|
# Create a service user for the application (no password by default)
|
|
sudo adduser --disabled-password --gecos "" --home /opt/faction-war factionwar
|
|
|
|
# Optional: Set a password if you need to log in as this user
|
|
# sudo passwd factionwar
|
|
```
|
|
|
|
### 2. Clone and Setup Application
|
|
|
|
```bash
|
|
# Create application directory
|
|
sudo mkdir -p /opt/faction-war
|
|
cd /opt/faction-war
|
|
|
|
# Clone the repository
|
|
sudo git clone https://git.jerick.xyz/jerick/faction_war_dispatch_bot.git app
|
|
|
|
# Set ownership to the service user
|
|
sudo chown -R factionwar:factionwar app
|
|
|
|
# Work as the application user
|
|
cd app
|
|
sudo -u factionwar python3 -m venv venv
|
|
|
|
# Install dependencies as the application user
|
|
sudo -u factionwar venv/bin/pip install -r requirements.txt
|
|
```
|
|
|
|
**Note**: The `factionwar` user is created without a password. To work as this user:
|
|
- Use: `sudo -u factionwar bash`
|
|
- Or set a password: `sudo passwd factionwar` and then: `sudo su - factionwar`
|
|
|
|
### 3. Configure Environment Variables
|
|
|
|
```bash
|
|
# Create .env file from example
|
|
cp .env.example .env
|
|
|
|
# Edit .env with your actual values
|
|
nano .env
|
|
```
|
|
|
|
**Important .env values to set:**
|
|
```bash
|
|
# Generate strong random values for these:
|
|
AUTH_PASSWORD=<generate-with: openssl rand -base64 32>
|
|
JWT_SECRET=<generate-with: openssl rand -hex 64>
|
|
|
|
# Add your API keys:
|
|
TORN_API_KEY=<your-torn-api-key>
|
|
FFSCOUTER_KEY=<your-ffscouter-key>
|
|
DISCORD_TOKEN=<your-discord-bot-token>
|
|
ALLOWED_CHANNEL_ID=<your-discord-channel-id>
|
|
```
|
|
|
|
### 4. Create Data Directory
|
|
|
|
```bash
|
|
# Create data directory for persistent storage
|
|
mkdir -p /opt/faction-war/app/data
|
|
chown -R factionwar:factionwar /opt/faction-war/app/data
|
|
chmod 700 /opt/faction-war/app/data # Restrict access to sensitive data
|
|
```
|
|
|
|
---
|
|
|
|
## SSL/HTTPS Setup
|
|
|
|
### Option 1: Using Let's Encrypt (Recommended - Free SSL)
|
|
|
|
```bash
|
|
# Install Certbot
|
|
sudo apt install certbot python3-certbot-nginx -y
|
|
|
|
# Get SSL certificate (replace with your domain)
|
|
sudo certbot --nginx -d yourdomain.com
|
|
|
|
# Certbot will automatically configure Nginx for HTTPS
|
|
# Follow the prompts to set up automatic renewal
|
|
```
|
|
|
|
### Option 2: Self-Signed Certificate (Development Only)
|
|
|
|
```bash
|
|
# Generate self-signed certificate (NOT for production)
|
|
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
|
-keyout /etc/ssl/private/nginx-selfsigned.key \
|
|
-out /etc/ssl/certs/nginx-selfsigned.crt
|
|
```
|
|
|
|
---
|
|
|
|
## Free Domain Setup
|
|
|
|
### Option 1: Free Subdomain Services
|
|
|
|
1. **DuckDNS** (https://www.duckdns.org)
|
|
- Completely free
|
|
- Provides `yourdomain.duckdns.org`
|
|
- Supports dynamic DNS updates
|
|
|
|
```bash
|
|
# Install DuckDNS updater
|
|
mkdir -p /opt/duckdns
|
|
cd /opt/duckdns
|
|
echo "echo url=\"https://www.duckdns.org/update?domains=YOURDOMAIN&token=YOUR-TOKEN&ip=\" | curl -k -o ~/duckdns/duck.log -K -" > duck.sh
|
|
chmod 700 duck.sh
|
|
|
|
# Add to crontab for auto-updates
|
|
crontab -e
|
|
# Add: */5 * * * * /opt/duckdns/duck.sh >/dev/null 2>&1
|
|
```
|
|
|
|
2. **FreeDNS** (https://freedns.afraid.org)
|
|
- Free subdomain or use their domains
|
|
- More domain options than DuckDNS
|
|
|
|
3. **No-IP** (https://www.noip.com)
|
|
- Free tier available
|
|
- Dynamic DNS client included
|
|
|
|
### Option 2: Cloudflare (Free Tier)
|
|
|
|
If you own a domain:
|
|
1. Transfer DNS to Cloudflare (free)
|
|
2. Get free SSL certificate
|
|
3. DDoS protection included
|
|
4. CDN included
|
|
|
|
---
|
|
|
|
## Nginx Reverse Proxy Configuration
|
|
|
|
Create Nginx configuration:
|
|
|
|
```bash
|
|
sudo nano /etc/nginx/sites-available/faction-war
|
|
```
|
|
|
|
**Configuration file:**
|
|
|
|
```nginx
|
|
# HTTP - Redirect to HTTPS
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name yourdomain.com; # Replace with your domain
|
|
|
|
# Redirect all HTTP to HTTPS
|
|
return 301 https://$server_name$request_uri;
|
|
}
|
|
|
|
# HTTPS - Main Application
|
|
server {
|
|
listen 443 ssl http2;
|
|
listen [::]:443 ssl http2;
|
|
server_name yourdomain.com; # Replace with your domain
|
|
|
|
# SSL Configuration (managed by Certbot)
|
|
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
|
|
|
# Security Headers
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
|
|
# Logging
|
|
access_log /var/log/nginx/faction-war-access.log;
|
|
error_log /var/log/nginx/faction-war-error.log;
|
|
|
|
# Proxy settings
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
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;
|
|
|
|
# WebSocket support (if needed in future)
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# Timeouts
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 60s;
|
|
proxy_read_timeout 60s;
|
|
}
|
|
|
|
# Static files (optional optimization)
|
|
location /static/ {
|
|
alias /opt/faction-war/app/static/;
|
|
expires 1d;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
}
|
|
```
|
|
|
|
**Enable the site:**
|
|
|
|
```bash
|
|
# Create symbolic link
|
|
sudo ln -s /etc/nginx/sites-available/faction-war /etc/nginx/sites-enabled/
|
|
|
|
# Test configuration
|
|
sudo nginx -t
|
|
|
|
# Reload Nginx
|
|
sudo systemctl reload nginx
|
|
```
|
|
|
|
---
|
|
|
|
## Systemd Service Setup
|
|
|
|
Create a systemd service to run the bot automatically:
|
|
|
|
```bash
|
|
sudo nano /etc/systemd/system/faction-war.service
|
|
```
|
|
|
|
**Service file:**
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=Faction War Dispatch Bot
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=factionwar
|
|
Group=factionwar
|
|
WorkingDirectory=/opt/faction-war/app
|
|
Environment="PATH=/opt/faction-war/app/venv/bin"
|
|
ExecStart=/opt/faction-war/app/venv/bin/python main.py
|
|
|
|
# Restart policy
|
|
Restart=always
|
|
RestartSec=10
|
|
|
|
# Security hardening
|
|
NoNewPrivileges=true
|
|
PrivateTmp=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
ReadWritePaths=/opt/faction-war/app/data
|
|
|
|
# Logging
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=faction-war
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
**Enable and start the service:**
|
|
|
|
```bash
|
|
# Reload systemd
|
|
sudo systemctl daemon-reload
|
|
|
|
# Enable service to start on boot
|
|
sudo systemctl enable faction-war
|
|
|
|
# Start the service
|
|
sudo systemctl start faction-war
|
|
|
|
# Check status
|
|
sudo systemctl status faction-war
|
|
|
|
# View logs
|
|
sudo journalctl -u faction-war -f
|
|
```
|
|
|
|
---
|
|
|
|
## Firewall Configuration
|
|
|
|
### Using UFW (Ubuntu/Debian)
|
|
|
|
```bash
|
|
# Install UFW
|
|
sudo apt install ufw -y
|
|
|
|
# Default policies
|
|
sudo ufw default deny incoming
|
|
sudo ufw default allow outgoing
|
|
|
|
# Allow SSH (IMPORTANT - don't lock yourself out!)
|
|
sudo ufw allow ssh
|
|
|
|
# Allow HTTP and HTTPS
|
|
sudo ufw allow 80/tcp
|
|
sudo ufw allow 443/tcp
|
|
|
|
# Enable firewall
|
|
sudo ufw enable
|
|
|
|
# Check status
|
|
sudo ufw status verbose
|
|
```
|
|
|
|
**Important:** Do NOT allow port 8000 externally. The application runs on port 8000 internally, but should only be accessible via Nginx reverse proxy on ports 80/443.
|
|
|
|
---
|
|
|
|
## Monitoring & Maintenance
|
|
|
|
### Log Files
|
|
|
|
```bash
|
|
# Application logs
|
|
sudo journalctl -u faction-war -f
|
|
|
|
# Nginx access logs
|
|
sudo tail -f /var/log/nginx/faction-war-access.log
|
|
|
|
# Nginx error logs
|
|
sudo tail -f /var/log/nginx/faction-war-error.log
|
|
```
|
|
|
|
### Health Checks
|
|
|
|
```bash
|
|
# Check if service is running
|
|
sudo systemctl status faction-war
|
|
|
|
# Check if Nginx is running
|
|
sudo systemctl status nginx
|
|
|
|
# Test application response
|
|
curl -I https://yourdomain.com
|
|
```
|
|
|
|
### Backup Strategy
|
|
|
|
```bash
|
|
# Create backup script
|
|
sudo nano /opt/faction-war/backup.sh
|
|
```
|
|
|
|
**Backup script:**
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
BACKUP_DIR="/opt/faction-war/backups"
|
|
DATE=$(date +%Y%m%d_%H%M%S)
|
|
APP_DIR="/opt/faction-war/app"
|
|
|
|
mkdir -p $BACKUP_DIR
|
|
|
|
# Backup data directory
|
|
tar -czf $BACKUP_DIR/data_backup_$DATE.tar.gz -C $APP_DIR data/
|
|
|
|
# Keep only last 7 days of backups
|
|
find $BACKUP_DIR -name "data_backup_*.tar.gz" -mtime +7 -delete
|
|
|
|
echo "Backup completed: data_backup_$DATE.tar.gz"
|
|
```
|
|
|
|
```bash
|
|
# Make executable
|
|
sudo chmod +x /opt/faction-war/backup.sh
|
|
|
|
# Add to cron for daily backups
|
|
sudo crontab -e
|
|
# Add: 0 2 * * * /opt/faction-war/backup.sh
|
|
```
|
|
|
|
### Updates
|
|
|
|
```bash
|
|
# Stop the service
|
|
sudo systemctl stop faction-war
|
|
|
|
# Update code
|
|
cd /opt/faction-war/app
|
|
sudo -u factionwar git pull
|
|
|
|
# Update dependencies
|
|
sudo -u factionwar /opt/faction-war/app/venv/bin/pip install --upgrade -r requirements.txt
|
|
|
|
# Restart service
|
|
sudo systemctl start faction-war
|
|
|
|
# Check status
|
|
sudo systemctl status faction-war
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Service Won't Start
|
|
|
|
```bash
|
|
# Check logs for errors
|
|
sudo journalctl -u faction-war -n 50 --no-pager
|
|
|
|
# Check Python errors
|
|
sudo -u factionwar /opt/faction-war/app/venv/bin/python /opt/faction-war/app/main.py
|
|
```
|
|
|
|
### Nginx 502 Bad Gateway
|
|
|
|
```bash
|
|
# Check if application is running
|
|
sudo systemctl status faction-war
|
|
|
|
# Check if application is listening on port 8000
|
|
sudo netstat -tlnp | grep 8000
|
|
|
|
# Check Nginx error logs
|
|
sudo tail -f /var/log/nginx/faction-war-error.log
|
|
```
|
|
|
|
### SSL Certificate Issues
|
|
|
|
```bash
|
|
# Renew certificate manually
|
|
sudo certbot renew
|
|
|
|
# Test auto-renewal
|
|
sudo certbot renew --dry-run
|
|
```
|
|
|
|
### Permission Issues
|
|
|
|
```bash
|
|
# Fix data directory permissions
|
|
sudo chown -R factionwar:factionwar /opt/faction-war/app/data
|
|
sudo chmod 700 /opt/faction-war/app/data
|
|
```
|
|
|
|
---
|
|
|
|
## Security Checklist
|
|
|
|
Before going live, verify:
|
|
|
|
- [ ] Strong AUTH_PASSWORD set in .env or Settings page
|
|
- [ ] Strong JWT_SECRET set in .env or Settings page
|
|
- [ ] SSL certificate installed and working (HTTPS)
|
|
- [ ] Firewall configured (only ports 22, 80, 443 open)
|
|
- [ ] Port 8000 NOT accessible from outside
|
|
- [ ] .env file has restricted permissions (chmod 600)
|
|
- [ ] data/ directory has restricted permissions (chmod 700)
|
|
- [ ] Automatic SSL renewal configured
|
|
- [ ] Backup script configured and tested
|
|
- [ ] Monitoring/logging configured
|
|
- [ ] Git repository does NOT contain secrets
|
|
- [ ] Default passwords changed
|
|
|
|
---
|
|
|
|
## Performance Tuning (Optional)
|
|
|
|
### Uvicorn with Multiple Workers
|
|
|
|
Edit `/etc/systemd/system/faction-war.service`:
|
|
|
|
```ini
|
|
ExecStart=/opt/faction-war/app/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000 --workers 2
|
|
```
|
|
|
|
### Redis for Session Storage (Future Enhancement)
|
|
|
|
For better session management across multiple workers, consider adding Redis:
|
|
|
|
```bash
|
|
sudo apt install redis-server -y
|
|
pip install redis
|
|
```
|
|
|
|
---
|
|
|
|
## Quick Start Summary
|
|
|
|
```bash
|
|
# 1. Server setup
|
|
sudo apt update && sudo apt install -y python3 python3-venv nginx certbot python3-certbot-nginx git
|
|
|
|
# 2. Create user and clone repository
|
|
sudo adduser --disabled-password --gecos "" --home /opt/faction-war factionwar
|
|
sudo mkdir -p /opt/faction-war
|
|
cd /opt/faction-war
|
|
sudo git clone https://git.jerick.xyz/jerick/faction_war_dispatch_bot.git app
|
|
sudo chown -R factionwar:factionwar app
|
|
cd app
|
|
|
|
# 3. Install dependencies
|
|
sudo -u factionwar python3 -m venv venv
|
|
sudo -u factionwar venv/bin/pip install -r requirements.txt
|
|
|
|
# 4. Configure
|
|
sudo -u factionwar cp .env.example .env
|
|
sudo -u factionwar nano .env # Set your secrets and API keys
|
|
|
|
# 5. Setup SSL
|
|
sudo certbot --nginx -d yourdomain.com
|
|
|
|
# 6. Configure Nginx (use config from above)
|
|
sudo nano /etc/nginx/sites-available/faction-war
|
|
sudo ln -s /etc/nginx/sites-available/faction-war /etc/nginx/sites-enabled/
|
|
sudo nginx -t && sudo systemctl reload nginx
|
|
|
|
# 7. Setup systemd service (use config from above)
|
|
sudo nano /etc/systemd/system/faction-war.service
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable faction-war
|
|
sudo systemctl start faction-war
|
|
|
|
# 8. Configure firewall
|
|
sudo ufw allow ssh && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
|
|
sudo ufw enable
|
|
|
|
# 9. Done! Visit https://yourdomain.com
|
|
```
|
|
|
|
---
|
|
|
|
## Getting Help
|
|
|
|
If you encounter issues:
|
|
|
|
1. Check logs: `sudo journalctl -u faction-war -f`
|
|
2. Check Nginx logs: `sudo tail -f /var/log/nginx/faction-war-error.log`
|
|
3. Test the application directly: `curl http://127.0.0.1:8000`
|
|
4. Verify firewall: `sudo ufw status`
|
|
5. Test SSL: `curl -I https://yourdomain.com`
|