Deploying Python Applications with Nginx
This guide walks through setting up a Python web application with Nginx as a reverse proxy server.
1. Introduction
Nginx is a popular web server that can act as a reverse proxy for Python web applications. This setup is highly efficient and scalable for production environments.
Architecture Overview
Client Request → Nginx → WSGI Server (Gunicorn/uWSGI) → Python Application2. Prerequisites
- A server with Ubuntu/Debian (instructions can be adapted for other distributions)
- Python 3.8+ installed
- A Python web application (Flask/Django/FastAPI)
- Root or sudo access
3. Installing Nginx
# Update package lists
sudo apt update
# Install Nginx
sudo apt install nginx -y
# Start Nginx and enable it to start on boot
sudo systemctl start nginx
sudo systemctl enable nginx
# Check status
sudo systemctl status nginx4. Setting Up Your Python Application
Create a Sample Flask Application
# Install virtualenv if not installed
pip install virtualenv
# Create and activate virtual environment
mkdir -p /var/www/myapp
cd /var/www/myapp
virtualenv venv
source venv/bin/activate
# Install Flask and Gunicorn
pip install flask gunicornCreate a sample application (app.py):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello from Python running behind Nginx!"
if __name__ == "__main__":
app.run(host='0.0.0.0')Testing the Application Locally
# Test with Flask's development server
python app.py
# Test with Gunicorn
gunicorn --bind 127.0.0.1:8000 app:app5. Configuring Gunicorn as a Service
Create a systemd service file:
sudo nano /etc/systemd/system/myapp.serviceAdd the following content:
[Unit]
Description=Gunicorn instance to serve myapp
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
ExecStart=/var/www/myapp/venv/bin/gunicorn --workers 3 --bind unix:myapp.sock -m 007 app:app
[Install]
WantedBy=multi-user.targetStart and enable the service:
# Change ownership
sudo chown -R www-data:www-data /var/www/myapp
# Start and enable service
sudo systemctl start myapp
sudo systemctl enable myapp
sudo systemctl status myapp6. Configuring Nginx
Create a new Nginx configuration file:
sudo nano /etc/nginx/sites-available/myappAdd the following content:
server {
listen 80;
server_name your_domain.com www.your_domain.com;
location / {
include proxy_params;
proxy_pass http://unix:/var/www/myapp/myapp.sock;
}
location /static/ {
alias /var/www/myapp/static/;
}
}Enable the site and test the configuration:
# Create symbolic link
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled
# Test Nginx configuration
sudo nginx -t
# Restart Nginx
sudo systemctl restart nginx7. Setting Up SSL with Let's Encrypt
# Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# Obtain SSL certificate
sudo certbot --nginx -d your_domain.com -d www.your_domain.com
# Test auto-renewal
sudo certbot renew --dry-run8. Optimizing Nginx Configuration
Edit your Nginx configuration for better performance:
server {
listen 80;
server_name your_domain.com www.your_domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name your_domain.com www.your_domain.com;
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# Enable HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
# Other security headers
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
# Enable gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Application proxy
location / {
proxy_pass http://unix:/var/www/myapp/myapp.sock;
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;
}
location /static/ {
alias /var/www/myapp/static/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
}9. Logging and Monitoring
Configure logging for your application:
# View Nginx logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
# View Gunicorn logs
sudo journalctl -u myapp10. Load Balancing Multiple Application Instances
For high-traffic applications, configure multiple Gunicorn instances:
upstream myapp_servers {
server unix:/var/www/myapp/myapp1.sock;
server unix:/var/www/myapp/myapp2.sock;
server unix:/var/www/myapp/myapp3.sock;
}
server {
listen 443 ssl http2;
server_name your_domain.com;
# SSL configuration...
location / {
proxy_pass http://myapp_servers;
# Other proxy settings...
}
}11. Django-Specific Configuration
For Django applications, include these additional settings:
location /static/ {
alias /var/www/myapp/static/;
expires 30d;
}
location /media/ {
alias /var/www/myapp/media/;
expires 30d;
}And run the collectstatic command:
python manage.py collectstaticConclusion
You've successfully deployed a Python application with Nginx as a reverse proxy. This setup provides excellent performance, scalability, and security for production environments.
For more advanced configurations, consider exploring:
- Rate limiting
- WebSocket support
- Advanced caching strategies
- Integration with CDNs