Complete guide for deploying CheckTick in production with SSL, nginx, and security hardening.
Production Checklist
Before deploying to production:
- [ ] Domain name configured with DNS pointing to your server
- [ ] SSL certificate ready (Let's Encrypt recommended)
- [ ] Email service configured and tested
- [ ] Secure passwords generated for database and Django
- [ ] Firewall configured (ports 80, 443)
- [ ] Backup strategy planned
SSL and Nginx Setup
For production deployments, use nginx as a reverse proxy for SSL termination and static file serving.
1. Download Nginx Configuration
# Download nginx compose overlay
curl -O https://raw.githubusercontent.com/eatyourpeas/checktick/main/docker-compose.nginx.yml
# Create nginx directory
mkdir -p nginx
cd nginx
# Download nginx configuration
curl -O https://raw.githubusercontent.com/eatyourpeas/checktick/main/nginx/nginx.conf
cd ..
2. Get SSL Certificate
Option A: Let's Encrypt (Recommended)
# Install certbot
sudo apt-get update
sudo apt-get install certbot
# Stop any services using ports 80/443
docker compose down
# Get certificate
sudo certbot certonly --standalone \
-d yourdomain.com \
-d www.yourdomain.com
# Copy certificates
sudo mkdir -p nginx/ssl
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem nginx/ssl/
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem nginx/ssl/
sudo chmod 644 nginx/ssl/fullchain.pem
sudo chmod 600 nginx/ssl/privkey.pem
Option B: Existing Certificate
# Copy your certificates
mkdir -p nginx/ssl
cp /path/to/fullchain.pem nginx/ssl/
cp /path/to/privkey.pem nginx/ssl/
chmod 644 nginx/ssl/fullchain.pem
chmod 600 nginx/ssl/privkey.pem
3. Configure Your Domain
Edit nginx/nginx.conf and replace yourdomain.com:
sed -i 's/yourdomain.com/your-actual-domain.com/g' nginx/nginx.conf
Or manually edit:
server_name your-actual-domain.com www.your-actual-domain.com;
4. Update Environment Variables
Edit .env:
ALLOWED_HOSTS=your-actual-domain.com,www.your-actual-domain.com
CSRF_TRUSTED_ORIGINS=https://your-actual-domain.com,https://www.your-actual-domain.com
SECURE_SSL_REDIRECT=True
5. Start with Nginx
# Start both base and nginx services
docker compose -f docker-compose.registry.yml -f docker-compose.nginx.yml up -d
# Verify nginx is running
docker compose ps nginx
# Check nginx configuration
docker compose exec nginx nginx -t
# View logs
docker compose logs nginx
6. Set Up Auto-Renewal
For Let's Encrypt certificates:
# Test renewal
sudo certbot renew --dry-run
# Add to crontab
(crontab -l 2>/dev/null; echo "0 0 1 * * certbot renew --quiet && cp /etc/letsencrypt/live/yourdomain.com/*.pem /path/to/checktick/nginx/ssl/ && docker compose restart nginx") | crontab -
Security Hardening
Change Default Database Password
In .env:
# Generate secure password
openssl rand -base64 32
# Update in .env
POSTGRES_PASSWORD=your-generated-password
DATABASE_URL=postgresql://checktick:your-generated-password@db:5432/checktick
Enable CAPTCHA
Prevent spam signups:
- Get free keys from hCaptcha
- Add to
.env:
HCAPTCHA_SITEKEY=your-site-key
HCAPTCHA_SECRET=your-secret-key
Configure Email Sending Limits
In nginx/nginx.conf, rate limits are already configured:
# Signup/login: 5 requests per minute
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
# General API: 10 requests per second
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
Adjust these values based on your needs.
Firewall Configuration
# Allow SSH (if you're using it)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
# Check status
sudo ufw status
Regular Updates
# Update CheckTick
docker compose pull
docker compose up -d
# Update system packages
sudo apt-get update
sudo apt-get upgrade
Performance Optimization
Increase Workers
For better performance with multiple users, increase Gunicorn workers:
Edit docker-compose.registry.yml and override the CMD:
services:
web:
command: >
sh -c "python manage.py migrate --noinput &&
python manage.py collectstatic --noinput &&
gunicorn checktick_app.wsgi:application
--bind 0.0.0.0:8000
--workers 8
--timeout 120"
Workers calculation: (2 ร CPU cores) + 1
Enable Database Connection Pooling
For high-traffic deployments, add to .env:
# Connection pooling (requires pgbouncer)
DATABASE_URL=postgresql://checktick:password@pgbouncer:6432/checktick
Static File Caching
Nginx already configures aggressive caching for static files:
location /static/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
Monitoring
Health Checks
CheckTick includes a health check endpoint:
# Check application health
curl http://localhost:8000/api/health
# Expected response: 200 OK
Container Logs
# View all logs
docker compose logs
# Follow web logs
docker compose logs -f web
# View nginx access logs
docker compose logs nginx | grep -v health
Database Monitoring
# Check database size
docker compose exec db psql -U checktick -c "SELECT pg_size_pretty(pg_database_size('checktick'));"
# Active connections
docker compose exec db psql -U checktick -c "SELECT count(*) FROM pg_stat_activity;"
Scaling Considerations
Multiple Web Servers
For high availability, run multiple web containers behind a load balancer:
services:
web:
deploy:
replicas: 3
External Database
For production, use a managed database service. See Database Options.
Redis for Caching
Future enhancement - not currently required but can improve performance.
Troubleshooting Production Issues
502 Bad Gateway
# Check web container is running
docker compose ps web
# Check web logs
docker compose logs web
# Restart web container
docker compose restart web
SSL Certificate Issues
# Verify certificate files exist
ls -la nginx/ssl/
# Check nginx configuration
docker compose exec nginx nginx -t
# View nginx error log
docker compose logs nginx | grep error
High Memory Usage
# Check container memory
docker stats
# Restart services to free memory
docker compose restart
Slow Performance
- Check worker count matches CPU cores
- Monitor database connections
- Review nginx rate limits
- Consider external database for high traffic
Production Environment Variables
Required for production:
# Security
SECRET_KEY=<long-random-string>
DEBUG=False
SECURE_SSL_REDIRECT=True
# Hosts
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
# Database
POSTGRES_PASSWORD=<secure-password>
# Email (required for user management)
EMAIL_HOST=<smtp-server>
EMAIL_HOST_USER=<username>
EMAIL_HOST_PASSWORD=<password>
DEFAULT_FROM_EMAIL=<from-address>
Optional but recommended:
# Spam protection
HCAPTCHA_SITEKEY=<key>
HCAPTCHA_SECRET=<secret>
# SSO (for organization encryption features)
OIDC_RP_CLIENT_ID_GOOGLE=<id>
OIDC_RP_CLIENT_SECRET_GOOGLE=<secret>
Next Steps
- Database Options - External managed databases
- Backup Strategy - Protect your data
- Configuration - Customize your instance