Reverse Proxy Notes

Just some notes on reverse proxies. Maybe an agenda.

Table of contents

Often a Reverse Proxy receives INCOMING TCP connections. Typically ngnix binds to one or more ports from the host OS. 80 for HTTP and 443 for HTTP over TLS. Services listening on port 80 are USUALLY redirects to port 443 where a TLS session can be established.

Tools

swag ; fresh-rss

A Reverse Proxy Routes?

It doesn't route in the IP routing sense, but it can make forwarding decisions based on multiple factors. For example, a reverse proxy might direct a connection to a specific back end server if the host header is a specific name: e.g., calendar.domain.tld.

Like routers or firewalls, reverse proxies can enforce IP traffic policy (e.g., source/destination). You can use this to limit traffic to a whitelist of CIDR blocks.  

Old City Bitcoiners nginx.conf

The Old City Bitcoiners is hosted by an nginx reverse proxy. The following configuration is used for the site:

First, we have the global definitions.


events {
    worker_connections  1024;
}

http {
    client_max_body_size 100m;
    server_tokens off;
    
    
    # Needed to allow very long URLs to prevent issues while signing PSBTs
    server_names_hash_bucket_size   128;
    proxy_buffer_size               128k;
    proxy_buffers                   4 256k;
    proxy_busy_buffers_size         256k;
    client_header_buffer_size       500k;
    large_client_header_buffers     4 500k;

    #access_log /var/log/nginx/ghost-access.log;
    #error_log /var/log/nginx/ghost-error.log;

   	#INSERT INDIVIDUAL SERVER BLOCKS HERE
    
}

http://oldcity-bitcoiners.info redirect to https://www.oldcity-bitcoiners.info


    server {
        listen 80;
        listen [::]:80;
        
        server_name oldcity-bitcoiners.info;

        location / {
            # MAY get another redirect at https://domain.tld for www.
            return 301 https://oldcity-bitcoiners.info$request_uri;
        }
    }

http://www.oldcity-bitcoiners.info redirect to https://www.oldcity-bitcoiners.info

# 
    server {
        listen 80;
        listen [::]:80;
        server_name www.oldcity-bitcoiners.info;
        return 301 https://www.oldcity-bitcoiners.info$request_uri;
    }

http://btcpay.oldcity-bitcoiners.info redirect to https://btcpay.oldcity-bitcoiners.info

    server {
        listen 80;
        listen [::]:80;
        server_name btcpay.oldcity-bitcoiners.info donate.oldcity-bitcoiners.info store.oldcity-bitcoiners.info;
        return 301 https://btcpay.oldcity-bitcoiners.info$request_uri;
    }

https://oldcity-bitcoiners.info redirect to https://www.oldcity-bitcoiners.info

    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        ssl_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
        
        server_name oldcity-bitcoiners.info;
        
        # We return a JSON object with name/pubkey mapping per NIP05.
        # https://www.reddit.com/r/nostr/comments/rrzk76/nip05_mapping_usernames_to_dns_domains_by_fiatjaf/sssss
        # TODO I'm not sure about the security of this Access-Control-Allow-Origin. Read up and restrict it if possible.
        location = /.well-known/nostr.json {
            add_header Content-Type application/json;
            add_header Access-Control-Allow-Origin *;
            return 200 '{ "names": { "_": "f5424d002fd0d48fadd6e54879387714c54bfa46535976ff2b385843aaddf8e5" } }';
        }
        
        
        # catch all; send request to www.oldcity-bitcoiners.info
        location / {
            return 301 https://www.oldcity-bitcoiners.info$request_uri;
        }
    }

wss://relay.oldcity-bitcoiners.info server block

The following code block shows the Nostr relay config.

# wss://relay.oldcity-bitcoiners.info server block
server {
    listen 443 ssl;
    
    server_name relay.oldcity-bitcoiners.info;

    ssl_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;

    keepalive_timeout 70;

    location / {
        # redirect all HTTP traffic to btcpay server
        proxy_pass http://nostr-546298:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }
}

https server block for https://btcpay.oldcity-bitcoiners.info donate.oldcity-bitcoiners.info store.oldcity-bitcoiners.info


    # https server block for https://btcpay.oldcity-bitcoiners.info donate.oldcity-bitcoiners.info store.oldcity-bitcoiners.info
    server {
        listen 443 ssl http2;

        ssl_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;

        server_name btcpay.oldcity-bitcoiners.info donate.oldcity-bitcoiners.info store.oldcity-bitcoiners.info;

        # Route everything to the real BTCPay server
        location / {
            # URL of BTCPay Server
            proxy_pass http://10.139.144.10:80;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            # For websockets (used by Ledger hardware wallets)
            proxy_set_header Upgrade $http_upgrade;
        }
    }

Main HTTPS listener for https://www.oldcity-bitcoiners.info with proxy cache

Most things are basically directed here: https://www.oldcity-bitcoiners.info. This server caches requests from the back end ghost container. There's a location block for the /ghost admin interface (TODO: add IP whitelist to RFC1918).


    # set up cache paths for nginx caching
    proxy_cache_path /tmp/546298-en levels=1:2 keys_zone=546298-en:600m max_size=100m inactive=24h;
    
    # Main HTTPS listener for https://www.oldcity-bitcoiners.info
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        ssl_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;

        server_name www.oldcity-bitcoiners.info;

        # Set the crawler policy.
        location = /robots.txt { 
            add_header Content-Type text/plain;
            return 200 "User-Agent: *\nAllow: /\n";
        }
        
        location ~ ^/(ghost/|p/|private/) {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto  $scheme;
            proxy_intercept_errors  on;
            proxy_pass http://ghost-546298-en:2368;
        }

        # Location block to back https://www.oldcity-bitcoiners.info/en or https://www.oldcity-bitcoiners.info/ if english.
        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $http_host;

            proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto  $scheme;
            proxy_intercept_errors  on;
            proxy_pass http://ghost-546298-en:2368;

            # https://stanislas.blog/2019/08/ghost-nginx-cache/ for nginx caching instructions
            # Remove cookies which are useless for anonymous visitor and prevent caching
            proxy_ignore_headers Set-Cookie Cache-Control;
            proxy_hide_header Set-Cookie;

            # Add header for cache status (miss or hit)
            add_header X-Cache-Status $upstream_cache_status;
            proxy_cache 546298-en;

            # Default TTL: 1 day
            proxy_cache_valid 5s;

            # Cache 404 pages for 1h
            proxy_cache_valid 404 1h;

            # use conditional GET requests to refresh the content from origin servers
            proxy_cache_revalidate on;
            proxy_buffering on;

            # Allows starting a background subrequest to update an expired cache item,
            # while a stale cached response is returned to the client.
            proxy_cache_background_update on;

            # Bypass cache for errors
            proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
        }

    }

TLS listener for nextcloud.oldcity-bitcoiners.info


    # TLS listener for nextcloud.oldcity-bitcoiners.info
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        ssl_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/oldcity-bitcoiners.info/live/oldcity-bitcoiners.info/fullchain.pem;

        server_name nextcloud.oldcity-bitcoiners.info;
        
        location / {
            proxy_headers_hash_max_size 512;
            proxy_headers_hash_bucket_size 64;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-NginX-Proxy true;
            
            proxy_pass http://nextcloud-546298-en:80;
        }
                    
        # https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html
        location /.well-known/carddav {
            return 301 $scheme://$host/remote.php/dav;
        }

        location /.well-known/caldav {
            return 301 $scheme://$host/remote.php/dav;
        }
    }

Were these notes useful to you? Consider a tip! All donations go to our monthly crowdfunding goals.

Spread the word

Keep reading