Skip to main content
This guide covers deploying your Frappe bench to a production environment with proper process management, web server configuration, and security hardening.

Prerequisites

Before setting up production:
  • A production server (Ubuntu 20.04+ or Debian 10+ recommended)
  • Root or sudo access
  • Domain name pointing to your server (for SSL)
  • Existing bench with sites and apps configured
  • At least 2GB RAM (4GB+ recommended)
Production setup significantly changes how your bench operates. Test in a staging environment first.

Understanding Production Setup

Production setup installs and configures:
  • NGINX: Web server and reverse proxy
  • Supervisor or systemd: Process management
  • fail2ban: Intrusion prevention
  • Redis: Configured for production
  • Proper file permissions and security

Setup Production

1
Install prerequisites
2
The setup command will install required dependencies:
3
sudo bench setup production [frappe-user]
4
Replace [frappe-user] with the system user that owns the bench directory (typically your username).
5
Example:
sudo bench setup production ubuntu
6
Confirm the setup
7
You’ll be prompted to confirm NGINX configuration overwrites. Review and confirm.
8
The setup process will:
9
  • Install ansible (if not present)
  • Install and configure fail2ban
  • Install NGINX
  • Install supervisor or configure systemd
  • Generate configuration files
  • Set up symlinks
  • Reload services
  • 10
    Verify services are running
    11
    Check NGINX:
    12
    sudo systemctl status nginx
    
    13
    Check supervisor:
    14
    sudo supervisorctl status
    
    15
    Or for systemd:
    16
    sudo systemctl status frappe-bench-web.target
    

    Production Architecture

    Process Management

    Bench uses either supervisor or systemd to manage processes:

    Supervisor (default)

    Configuration: config/supervisor.conf
    Symlinked to: /etc/supervisor/conf.d/[bench-name].conf
    Manage processes:
    sudo supervisorctl status              # View all processes
    sudo supervisorctl restart all         # Restart all processes
    sudo supervisorctl restart bench-name-web:  # Restart web workers
    

    Systemd

    To use systemd instead of supervisor, set in sites/common_site_config.json:
    {
      "restart_systemd_on_update": true,
      "restart_supervisor_on_update": false
    }
    
    Then regenerate configuration:
    bench setup systemd --user [frappe-user]
    
    Manage with systemd:
    sudo systemctl status frappe-bench-web.target
    sudo systemctl restart frappe-bench-web.target
    

    NGINX Configuration

    Configuration: config/nginx.conf
    Symlinked to: /etc/nginx/conf.d/[bench-name].conf

    Key NGINX features:

    • Serves static assets directly
    • Proxies dynamic requests to Gunicorn
    • WebSocket support for socketio
    • Gzip compression
    • Client body size limits
    • Rate limiting (optional)

    Regenerate NGINX config:

    bench setup nginx
    sudo bench setup reload-nginx
    

    Redis Configuration

    Production uses separate Redis instances:
    • redis-cache: Port 13000 - Session and cache data
    • redis-queue: Port 11000 - Background job queue
    • redis-socketio: Port 13000 - Real-time updates
    Configuration files in: config/redis_*.conf

    Configuring Production

    Enable production features

    Edit sites/common_site_config.json:
    {
      "restart_supervisor_on_update": true,
      "serve_default_site": true,
      "webserver_port": 80,
      "socketio_port": 9000,
      "developer_mode": 0
    }
    

    Auto-restart on updates

    Enable automatic service restart after bench update:
    bench config restart_supervisor_on_update on
    
    For systemd:
    bench config restart_systemd_on_update on
    

    Configure workers

    Worker processes are automatically calculated based on CPU cores. To customize:
    {
      "gunicorn_workers": 4,
      "background_workers": 2
    }
    

    HTTP timeout

    For long-running requests:
    bench config http_timeout 300
    

    Managing Production Bench

    Updating applications

    1
    Backup before updating
    2
    bench backup-all-sites
    
    3
    Run the update
    4
    bench update
    
    5
    This will:
    6
  • Pull latest code for all apps
  • Install updated dependencies
  • Run database migrations
  • Build assets
  • Restart services (if configured)
  • 7
    Selective updates
    8
    Update only code:
    9
    bench update --pull
    
    10
    Only run migrations:
    11
    bench update --patch
    
    12
    Only build assets:
    13
    bench update --build
    
    14
    Update specific app:
    15
    cd apps/erpnext
    git pull
    cd ../..
    bench --site all migrate
    bench build
    bench restart
    

    Restarting services

    Restart all bench services:
    bench restart
    
    This is equivalent to:
    sudo supervisorctl restart all
    
    Or with systemd:
    sudo systemctl restart frappe-bench-web.target
    sudo systemctl restart frappe-bench-workers.target
    

    Monitoring logs

    Supervisor logs:
    sudo tail -f /var/log/supervisor/supervisord.log
    
    Bench logs:
    tail -f logs/bench.log
    tail -f logs/web.error.log
    
    NGINX logs:
    sudo tail -f /var/log/nginx/access.log
    sudo tail -f /var/log/nginx/error.log
    

    Site maintenance

    Put site in maintenance mode:
    bench --site mysite.com set-maintenance-mode on
    
    Take it back online:
    bench --site mysite.com set-maintenance-mode off
    

    Security Hardening

    Firewall setup

    Configure firewall to allow only necessary ports:
    bench setup firewall --ssh_port 22
    
    This blocks all ports except 22 (SSH), 80 (HTTP), and 443 (HTTPS).
    Ensure SSH is working before enabling the firewall to avoid being locked out.

    Change SSH port

    bench setup ssh-port 2222
    

    fail2ban configuration

    fail2ban is automatically installed with production setup. Configure NGINX jail:
    bench setup fail2ban --maxretry 6 --bantime 600
    
    Parameters:
    • --maxretry: Number of failures before ban (default: 6)
    • --bantime: Ban duration in seconds (default: 600)
    • --findtime: Time window for counting failures (default: 600)

    Disable developer mode

    Ensure developer mode is off for all sites:
    bench --site all set-config developer_mode 0
    

    Set up sudoers

    Allow bench commands without password (already done in production setup):
    sudo bench setup sudoers [frappe-user]
    

    Backup Strategy

    Automated backups

    Set up automatic daily backups:
    bench setup backups
    
    This adds a cron job for daily backups at 6 AM.

    Manual backups

    Backup single site:
    bench --site mysite.com backup
    
    Backup with files:
    bench --site mysite.com backup --with-files
    
    Backup all sites:
    bench backup-all-sites
    
    Backup location: sites/[sitename]/private/backups/

    Restore from backup

    bench --site mysite.com restore /path/to/backup.sql.gz
    

    Performance Optimization

    Enable rate limiting

    Edit sites/common_site_config.json:
    {
      "allow_rate_limiting": true
    }
    
    Regenerate NGINX config:
    bench setup nginx
    sudo bench setup reload-nginx
    

    Configure caching

    Enable Redis caching in site config:
    {
      "enable_redis_keys_gc": true,
      "redis_cache_ttl": 86400
    }
    

    Optimize database

    Regularly optimize MariaDB tables:
    bench --site mysite.com mariadb
    
    Then run:
    OPTIMIZE TABLE `tabDocType`;
    

    Disabling Production

    To revert to development mode:
    bench disable-production
    
    This removes:
    • NGINX configuration symlinks
    • Supervisor configuration symlinks
    • Reloads services
    Then you can use bench start for development.

    Production Checklist

    1
    Pre-deployment
    2
  • Test all functionality in staging
  • Back up existing data
  • Configure domain DNS
  • Review common_site_config.json
  • Disable developer mode
  • 3
    During deployment
    4
  • Run sudo bench setup production [user]
  • Set up SSL certificates (see SSL Setup)
  • Enable multitenancy if needed
  • Configure automated backups
  • Set up firewall
  • Configure fail2ban
  • 5
    Post-deployment
    6
  • Test all sites are accessible
  • Verify SSL certificates
  • Check supervisor/systemd status
  • Monitor logs for errors
  • Test backup and restore
  • Document deployment process
  • Next Steps

    Build docs developers (and LLMs) love