14 KiB
Production Deployment Guide
This guide walks you through deploying the Faction War Dispatch Bot to a production server.
Table of Contents
- Security Considerations
- Server Requirements
- Installation Steps
- SSL/HTTPS Setup
- Free Domain Setup
- Systemd Service Setup
- Firewall Configuration
- Monitoring & Maintenance
Security Considerations
Critical Security Steps (DO BEFORE DEPLOYMENT!)
-
Change Default Secrets
# Generate a strong random password openssl rand -base64 32 # Generate a strong JWT secret openssl rand -hex 64 -
Never Commit Secrets to Git
- Use
.envfile for secrets (already in.gitignore) - Or use the Settings page to configure via web UI
- Keep
data/config.jsonout of version control (already in.gitignore)
- Use
-
HTTPS is REQUIRED
- JWT tokens and passwords are transmitted over the network
- Without HTTPS, credentials can be intercepted
- See SSL/HTTPS Setup below
-
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 below
-
Keep Dependencies Updated
pip install --upgrade -r requirements.txt -
Backup Your Data
- Backup the
data/directory regularly - Contains group assignments, Discord mappings, and config
- Backup the
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
# 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
# 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 factionwarand then:sudo su - factionwar
3. Configure Environment Variables
# Create .env file from example
cp .env.example .env
# Edit .env with your actual values
nano .env
Important .env values to set:
# 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
# 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)
# 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)
# 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
-
DuckDNS (https://www.duckdns.org)
- Completely free
- Provides
yourdomain.duckdns.org - Supports dynamic DNS updates
# 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 -
FreeDNS (https://freedns.afraid.org)
- Free subdomain or use their domains
- More domain options than DuckDNS
-
No-IP (https://www.noip.com)
- Free tier available
- Dynamic DNS client included
Option 2: Cloudflare (Free Tier)
If you own a domain:
- Transfer DNS to Cloudflare (free)
- Get free SSL certificate
- DDoS protection included
- CDN included
Nginx Reverse Proxy Configuration
Create Nginx configuration:
sudo nano /etc/nginx/sites-available/faction-war
Configuration file:
# 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:
# 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:
sudo nano /etc/systemd/system/faction-war.service
Service file:
[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:
# 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)
# 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
# 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
# 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
# Create backup script
sudo nano /opt/faction-war/backup.sh
Backup script:
#!/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"
# 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
# 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
# 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
# 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
# Renew certificate manually
sudo certbot renew
# Test auto-renewal
sudo certbot renew --dry-run
Permission Issues
# 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:
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:
sudo apt install redis-server -y
pip install redis
Quick Start Summary
# 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:
- Check logs:
sudo journalctl -u faction-war -f - Check Nginx logs:
sudo tail -f /var/log/nginx/faction-war-error.log - Test the application directly:
curl http://127.0.0.1:8000 - Verify firewall:
sudo ufw status - Test SSL:
curl -I https://yourdomain.com