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) + 1for CPU-bound apps - Threads — use
gthreadworker class for I/O-bound workloads - Timeout — set
--timeout 120for long-running requests - Graceful reload —
systemctl reload myappsends HUP signal for zero-downtime