Nginx Reverse Proxy Configuration
Basic Reverse Proxy Setup
Create Configuration File
# Create new site configuration
sudo nano /etc/nginx/sites-available/domain.com
# Or for conf.d directory
sudo nano /etc/nginx/conf.d/domain.com.confBasic Configuration
# Define upstream server
upstream project_upstream {
server 127.0.0.1:3000;
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name domain.com www.domain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS with proxy
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domain.com www.domain.com;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://project_upstream;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}Multiple Upstream Servers (Load Balancing)
# Define upstream with multiple servers
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
}
}Proxy with Caching
Configure Cache Path
# At top level of nginx.conf (outside server block)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;
upstream project_upstream {
server 127.0.0.1:3000;
}
server {
listen 443 ssl http2;
server_name domain.com;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
# Cache static files
location ~* ^.+\.(js|css|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ {
proxy_cache STATIC;
proxy_pass http://project_upstream;
proxy_cache_valid 200 7d;
proxy_ignore_headers Cache-Control;
expires 7d;
}
# Proxy everything else
location / {
proxy_pass http://project_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Node.js Application Proxy
upstream nodejs {
server 127.0.0.1:3000;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://nodejs;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}Next.js / Nuxt.js Cache Configuration
# Cache configuration for Next.js
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=NEXT:10m inactive=7d use_temp_path=off;
upstream nextjs_upstream {
server 127.0.0.1:3000;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Cache Next.js static files
location /_next/static {
proxy_cache NEXT;
proxy_pass http://nextjs_upstream;
proxy_cache_valid 200 7d;
proxy_ignore_headers Cache-Control;
}
# Cache public static files
location /static {
proxy_cache NEXT;
proxy_pass http://nextjs_upstream;
proxy_cache_valid 200 60m;
proxy_ignore_headers Cache-Control;
}
# Proxy all other requests
location / {
proxy_pass http://nextjs_upstream;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Python Application (Flask/Django)
upstream python_app {
server 127.0.0.1:5000;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
client_max_body_size 100M;
location / {
proxy_pass http://python_app;
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;
proxy_read_timeout 90;
}
# Serve static files directly
location /static {
alias /var/www/app/static;
expires 30d;
}
}WebSocket Configuration
# For applications requiring WebSocket support
upstream websocket_backend {
server 127.0.0.1:3000;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://websocket_backend;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400;
}
}Multiple Applications
upstream app1 {
server 127.0.0.1:3000;
}
upstream app2 {
server 127.0.0.1:3001;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Route to app1
location /app1 {
proxy_pass http://app1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Route to app2
location /app2 {
proxy_pass http://app2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Default location
location / {
proxy_pass http://app1;
}
}Enable Configuration
# Create symlink to enable site
sudo ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginxSecurity Headers
server {
listen 443 ssl http2;
server_name example.com;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
location / {
proxy_pass http://upstream;
}
}Debugging
# View Nginx error log
tail -f /var/log/nginx/error.log
# Check upstream status
# Add to location block for debugging:
# error_page 502 503 504 /5xx.html;
# View active connections
ss -an | grep ESTABLISHED
# Test proxy connection
curl -v http://127.0.0.1:30001. Create new domain
cd /etc/nginx/sites-availablesudo nano domain.comproxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;
upstream project_upstream {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name domain.com;
rewrite ^(.*) https://domain.com$1 permanent;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
root /usr/share/nginx/html/project;
ssl on;
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
server_name domain.com;
server_tokens off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
location / {
proxy_pass http://project_upstream;
}
}
{% hint style=“info” %} Change domain.com, port, project dir to your project info. {% endhint %}
2. Cache file for nuxtjs - nextjs
location /_next/static {
proxy_cache STATIC;
proxy_pass http://project_upstream;
}
location /static {
proxy_cache STATIC;
proxy_ignore_headers Cache-Control;
proxy_cache_valid 60m;
proxy_pass http://project_upstream;
}
location / {
proxy_pass http://project_upstream;
}