# Proxying to Application Servers: Node, Python and PHP — Nginx

Source: https://www.skillbyai.com/en/nginx/p-apps

> 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.

```nginx
# 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.

**Quiz:** Which directive connects NGINX to PHP-FPM?

- [ ] proxy_pass
- [ ] grpc_pass
- [x] fastcgi_pass
- [ ] uwsgi_pass

*Answer:* fastcgi_pass. PHP-FPM speaks FastCGI, so NGINX uses fastcgi_pass.
