How to Deploy a Python Application with Gunicorn and Nginx

Gunicorn is a production-grade WSGI server for running Python web applications (Flask, FastAPI, Django), and pairing it with Nginx as a reverse proxy is the standard deployment pattern for Python apps on a VPS.

Why Not Just Run the Development Server

Frameworks' built-in development servers aren't designed for production traffic — they typically handle one request at a time and lack the robustness needed for real usage. Gunicorn runs multiple worker processes, handling concurrent requests properly.

Prerequisites

  • A working Python application (Flask, FastAPI, or similar)
  • Nginx installed

Step 1 — Install Gunicorn

pip install gunicorn --break-system-packages

Step 2 — Test Gunicorn Directly

gunicorn myapp:app --bind 127.0.0.1:8000

For FastAPI specifically, use the Uvicorn worker class instead:

gunicorn myapp:app -k uvicorn.workers.UvicornWorker --bind 127.0.0.1:8000

Step 3 — Determine the Right Number of Workers

gunicorn myapp:app --workers 4 --bind 127.0.0.1:8000

A common starting formula is (2 x CPU cores) + 1, adjusted based on actual observed performance and memory constraints.

Step 4 — Create a systemd Service

sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Python Application
After=network.target

[Service]
User=deploy
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/venv/bin/gunicorn myapp:app --workers 4 --bind 127.0.0.1:8000
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myapp

Step 5 — Configure Nginx as a Reverse Proxy

server {
    listen 80;
    server_name yourdomain.com;

    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;
    }
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 6 — Add HTTPS

sudo certbot --nginx -d yourdomain.com

Increasing Timeout for Long-Running Requests (Relevant for AI Workloads)

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_read_timeout 300s;
}

AI inference or other long-running operations may exceed Nginx's default proxy timeout, causing premature connection drops — increase this value to match your application's realistic response times.

Viewing Application Logs

sudo journalctl -u myapp -f

Deploying Updates

cd /var/www/myapp
git pull
sudo systemctl restart myapp

Common Errors

502 Bad Gateway — verify Gunicorn is actually running (sudo systemctl status myapp) and bound to the port Nginx expects.

Worker timeout errors in Gunicorn logs — increase Gunicorn's own --timeout flag if requests legitimately take longer than the default 30 seconds (common with AI inference workloads).

Continue Reading

Browse more articles in AI & Machine Learning on a VPS.

  • gunicorn, python deployment, gunicorn nginx, wsgi server
  • 0 Utenti hanno trovato utile questa risposta
Hai trovato utile questa risposta?

Articoli Correlati

VPS Requirements for Running AI and Machine Learning Workloads

Before installing any AI tooling, it's worth understanding what a VPS can and can't realistically...

How to Install Ollama and Run Local LLMs on a VPS

Ollama makes running open-source large language models locally straightforward — handling...

How to Set Up a Private ChatGPT-Style Interface with Open WebUI

Open WebUI provides a familiar, browser-based chat interface for locally-run language models...

How to Install LocalAI as an OpenAI-Compatible API Alternative

LocalAI provides a drop-in, OpenAI-API-compatible endpoint backed by open-source models running...

How to Run Stable Diffusion for AI Image Generation on a VPS

Stable Diffusion generates images from text prompts using an open-source diffusion model. This...