Deploying Python Applications with uWSGI and Nginx
Nginx Installation and Compilation
First, ensure the build environment and necessary libraries are present on the system. The following sequence installs developmant tools, downloads the PCRE library required for regex support, and compiles Nginx from source with SSL and status monitoring modules enabled.
# Install build dependencies
yum install -y gcc make zlib-devel openssl-devel pcre-devel
# Download and compile PCRE
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.45.tar.gz
tar -xzf pcre-8.45.tar.gz -C /usr/local/src/
cd /usr/local/src/pcre-8.45
./configure
make && make install
# Download and compile Nginx
wget http://nginx.org/download/nginx-1.22.0.tar.gz
tar -xzf nginx-1.22.0.tar.gz
cd nginx-1.22.0
./configure \
--prefix=/opt/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-pcre=/usr/local/src/pcre-8.45
make && make install
# Verify installation
/opt/nginx/sbin/nginx -v
# Create a dedicated system user for the service
groupadd deploy
useradd -g deploy -s /sbin/nologin deploy
Configuring Nginx
The main configuration file defines the user context, worker processes, and connection handling methods. The epoll method is recommended for high-performance Linux systems.
# /opt/nginx/conf/nginx.conf
user deploy deploy;
worker_processes 4;
error_log /opt/nginx/logs/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 2048;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
# Serve static files directly
location /static/ {
alias /var/www/app/static/;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
}
}
For specific application routing, a separate configuration block is used to pass traffic to the uWSGI socket or set up a reverse proxy with proper CORS headers.
# /opt/nginx/conf.d/app.conf
server {
listen 80;
server_name api.example.com;
# Timeout settings for long-running processes
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
location /api/v1 {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi_app.sock;
}
location /dashboard/proxy {
rewrite ^/dashboard/proxy/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8080;
# Standard Proxy Headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# CORS Configuration
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
}
}
uWSGI Configuration
The uWSGI application server is configured via an INI file. This setup specifies the Python environment, the WSGI entry point, and process management settings. It utilizes a Unix socket for communication with Nginx.
# /var/www/app/uwsgi.ini
[uwsgi]
# Socket communication
socket = /tmp/uwsgi_app.sock
chmod-socket = 666
# Python Environment
chdir = /var/www/app
module = wsgi:app
home = /var/www/app/venv
py-autoreload = 2
# Process Management
master = true
processes = 4
threads = 2
enable-threads = true
# Logging
pidfile = /var/run/uwsgi_app.pid
daemonize = /var/log/uwsgi_app.log
buffer-size = 65536
# Permissions
uid = deploy
gid = deploy
To manage the uWSGI service, use the following commands:
# Start the service
uwsgi --ini /var/www/app/uwsgi.ini
# Graceful reload
uwsgi --reload /var/run/uwsgi_app.pid
Database Configuration
For database connectivity, ensure the root user is configured with a secure password and native password authentication.
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'StrongPassword';
FLUSH PRIVILEGES;
Advanced Nginx Setup for WebSockets and Proxies
This configuration demonstrates handling WebSocket connections (e.g., for Socket.io) and increased buffer sizes for large payloads.
server {
listen 80;
server_name websocket.example.com;
# Buffer Sizes
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
location /socket.io {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi_app.sock;
# WebSocket upgrade headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}