SkillByAIOpen interactive version →

Lesson 9 / 25

Proxying to Application Servers: Node, Python and PHP

Connect NGINX to common application runtimes over HTTP, Unix sockets and FastCGI.

Different protocols for different runtimes

Most modern runtimes speak HTTP, so NGINX simply proxies to them: Node.js and Go services, Java (Spring Boot), and Python apps served by Gunicorn or Uvicorn. For services on the same machine, a Unix domain socket (proxy_pass http://unix:/run/gunicorn.sock;) avoids TCP overhead and keeps the app unreachable from the network. PHP commonly runs under PHP-FPM, which speaks FastCGI: use fastcgi_pass with the standard fastcgi_params and set SCRIPT_FILENAME correctly, and serve only files that exist, to avoid executing arbitrary uploaded files as PHP. Python applications using uWSGI can use uwsgi_pass, and gRPC services use grpc_pass over HTTP/2. Whatever the runtime, let NGINX serve static assets directly and pass only dynamic requests to the application.

Gunicorn over a Unix socket and PHP-FPM via FastCGI

Static files are served by NGINX; only dynamic requests reach the runtime.

# Python (Gunicorn/Uvicorn) on a Unix socket
server {
    listen 80;
    server_name py.example.com;
    location /static/ { alias /srv/app/static/; }
    location / {
        proxy_pass http://unix:/run/gunicorn.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# PHP via PHP-FPM
server {
    listen 80;
    server_name php.example.com;
    root /var/www/php-site/public;
    index index.php;
    location / { try_files $uri $uri/ /index.php?$query_string; }
    location ~ \.php$ {
        try_files $uri =404;                       # never run non-existent scripts
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }
}

Do not execute uploads

Uploaded files must never be executed by PHP-FPM or any interpreter. Store uploads outside the web root or in a location that serves them only as static files, and keep the try_files $uri =404; guard.

Quick check: Which directive connects NGINX to PHP-FPM?

  • proxy_pass
  • grpc_pass
  • fastcgi_pass
  • uwsgi_pass
Answer

fastcgi_pass — PHP-FPM speaks FastCGI, so NGINX uses fastcgi_pass.