# 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 non-root user for the application (recommended) sudo adduser --system --group --home /opt/faction-war factionwar ``` ### 2. Clone and Setup Application ```bash # Switch to the application user sudo su - factionwar # Clone the repository (or upload files via SCP/SFTP) cd /opt/faction-war git clone app cd app # Create Python virtual environment python3 -m venv venv source venv/bin/activate # Install dependencies pip install -r requirements.txt ``` ### 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= JWT_SECRET= # Add your API keys: TORN_API_KEY= FFSCOUTER_KEY= DISCORD_TOKEN= ALLOWED_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 # 2. Clone and install cd /opt && sudo mkdir faction-war && cd faction-war git clone app && cd app python3 -m venv venv && source venv/bin/activate pip install -r requirements.txt # 3. Configure cp .env.example .env nano .env # Set your secrets and API keys # 4. Setup SSL sudo certbot --nginx -d yourdomain.com # 5. 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 # 6. 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 # 7. Configure firewall sudo ufw allow ssh && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp sudo ufw enable # 8. 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`