Reverse Proxies
Nginx

NOTE: This page is marked "earlydoc", or "early documentation", which means it might be brief, or contain information about parts of the app that are under heavy development. If you encounter issues with instructions found here, please check out the support page for options.

How to add Nginx as a reverse proxy

ℹ️

The following commands are tailored for Ubuntu/Debian systems. If you're using a different Linux distribution, you may need to adjust package management commands accordingly (e.g., yum for CentOS, brew for macOS).

Install Nginx:

sudo apt update && sudo apt install nginx -y
sudo systemctl start nginx && sudo systemctl enable nginx

Install Certbot for SSL:

sudo apt update && sudo apt install python3-certbot-nginx -y

Create the Webroot Directory:

sudo mkdir -p /var/www/certbot/.well-known/acme-challenge && sudo chown -R www-data:www-data /var/www/certbot

Create a temporary Nginx config for creating SSL certificates

💡

Make sure to change subdomain.domain.tld to your actual subdomain and ensure that it is pointed to your server's IP address.

Edit the file /etc/nginx/sites-available/subdomain.domain.tld (e.g., use sudo nano /etc/nginx/sites-available/subdomain.domain.tld if you're using nano).

    server {
        listen 80;
        listen [::]:80;  # IPv6 support
        server_name <subdomain.domain.tld>;  # CHANGE HERE
 
        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
 
        location / {
            return 301 https://$host$request_uri;
        }
 
        # Hide NGINX version for security reasons
        server_tokens off;
    }
sudo ln -s /etc/nginx/sites-available/<subdomain.domain.tld> /etc/nginx/sites-enabled/

Obtain SSL Certificates Using Webroot method:

sudo certbot certonly --webroot -w /var/www/certbot -d <subdomain.domain.tld> --email your-email@example.com --agree-tos --no-eff-email

Edit the Nginx config:

Edit the file /etc/nginx/sites-available/subdomain.domain.tld (e.g., use sudo nano /etc/nginx/sites-available/subdomain.domain.tld if you're using nano). Copy your config from here:

# HTTP -> HTTPS Redirection
server {
    listen 80;
    listen [::]:80;  # IPv6 support
    server_name <subdomain.domain.tld>;  # CHANGE HERE
 
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
 
    location / {
        return 301 https://$host$request_uri;
    }
 
    # Hide NGINX version for security reasons
    server_tokens off;
}
 
# HTTPS Configuration
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;  # Enable HTTP/2 and IPv6 support if you need
    server_name <subdomain.domain.tld>; # CHANGE HERE
 
    # Hide NGINX version
    server_tokens off;
 
    # SSL Certificates
    ssl_certificate /etc/letsencrypt/live/<subdomain.domain.tld>/fullchain.pem;  # CHANGE HERE
    ssl_certificate_key /etc/letsencrypt/live/<subdomain.domain.tld>/privkey.pem;  # CHANGE HERE
    ssl_trusted_certificate /etc/letsencrypt/live/<subdomain.domain.tld>/chain.pem;  # CHANGE HERE
 
    # Security: Stronger SSL Configuration
    ssl_session_cache shared:SSL:10m;  # Cache SSL sessions
    ssl_session_timeout 1d;  # Set session timeout to 1 day
    ssl_session_tickets off;  # Disable SSL session tickets
 
    # Use only modern SSL/TLS protocols (disables older insecure ones)
    ssl_protocols TLSv1.2 TLSv1.3;
 
    # Configure SSL ciphers (strong encryption algorithms)
    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;
    ssl_prefer_server_ciphers off;  # Allow clients to prefer their ciphers
 
    # Diffie-Hellman parameter for Perfect Forward Secrecy (PFS)
    ssl_dhparam /etc/ssl/certs/dhparam.pem;  # Generate with `sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048`
 
    # OCSP Stapling for improved SSL/TLS performance
    ssl_stapling on;
    ssl_stapling_verify on;
 
    # DNS resolver for OCSP
    resolver 1.1.1.1 1.0.0.1 valid=300s;
    resolver_timeout 5s;
 
    # some HTTP Security Headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;  # HSTS
    add_header X-Frame-Options "SAMEORIGIN" always;  # Prevent Clickjacking
    add_header X-Content-Type-Options "nosniff" always;  # Prevent MIME-type sniffing
    add_header X-XSS-Protection "1; mode=block" always;  # XSS Protection
    add_header Referrer-Policy "no-referrer" always;  # Better privacy control
    add_header Permissions-Policy "geolocation=(self), microphone=(), camera=()" always;  # Limit browser permissions
 
    # Reverse Proxy to Postiz application
    location / {
        proxy_pass http://localhost:5000;
        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;
        proxy_set_header X-Forwarded-Proto $scheme;
 
        # WebSocket Support
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
 
    # Disable directory listing for security
    autoindex off;
 
    # Enable Gzip compression for better performance
    gzip on;
    gzip_comp_level 6;
    gzip_min_length 1100;
    gzip_buffers 4 32k;
    gzip_proxied any;
    gzip_types text/plain text/css text/javascript application/json application/xml image/svg+xml;
 
    # Optional Access/Error Logging
    access_log /var/log/nginx/<subdomain.domain.tld>.log; # CHANGE HERE
    error_log /var/log/nginx/<subdomain.domain.tld>.log; # CHANGE HERE
}

Generate DH Parameters:

(Needed if you are using the "robust" nginx config option)

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Test your Nginx configuration:

sudo nginx -t

Automatic reload Nginx when SSL Certificates are renewed:

echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh && sudo chmod a+x /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh

Reload Nginx

sudo systemctl reload nginx

Vuola!

Your Nginx reverse proxy is now running, securely serving your Postiz instance at your subdomain.domain.tld. 🎉