Docs / Web Servers / How to Deploy with Gunicorn and Systemd

How to Deploy with Gunicorn and Systemd

By Admin · Mar 1, 2026 · Updated Apr 23, 2026 · 27 views · 2 min read

How to Deploy with Gunicorn and Systemd

Gunicorn is a production-grade WSGI HTTP server for Python web applications. Combined with systemd, it provides reliable process management for Python apps on your Breeze server.

Installing Gunicorn

cd /home/user/myapp
python3 -m venv venv
source venv/bin/activate
pip install gunicorn flask  # or django, fastapi, etc.

Testing Gunicorn Manually

# For Flask
gunicorn --bind 0.0.0.0:8000 --workers 4 "app:create_app()"

# For Django
gunicorn --bind 0.0.0.0:8000 --workers 4 myproject.wsgi:application

Creating a Systemd Service

Create /etc/systemd/system/myapp.service:

[Unit]
Description=My Python Application
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/home/user/myapp
Environment="PATH=/home/user/myapp/venv/bin"
ExecStart=/home/user/myapp/venv/bin/gunicorn \
    --workers 4 \
    --worker-class gthread \
    --threads 2 \
    --bind unix:/run/myapp.sock \
    --access-logfile /var/log/myapp/access.log \
    --error-logfile /var/log/myapp/error.log \
    "app:create_app()"
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Enabling and Managing the Service

sudo mkdir -p /var/log/myapp
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp

Worker Tuning Guidelines

  • Workers — set to (2 * CPU cores) + 1 for CPU-bound apps
  • Threads — use gthread worker class for I/O-bound workloads
  • Timeout — set --timeout 120 for long-running requests
  • Graceful reloadsystemctl reload myapp sends HUP signal for zero-downtime

Was this article helpful?