nginx Configuration for Reverse-Proxy to Different Ports

11 July 2020

About a 1-minute read

This nginx configuration file forwards traffic to different ports on the local host based on the first part of the URL. I used it for proxying traffic to Docker containers on my NAS before setting up a more complex macvlan network with each container on its own IP address.

# Adapted from:

# This mapping enables the HTTP upgrade required for Websockets
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;

# This mapping finds the relevant port for each app (only
# homeassistant in this example) so we can forward port-80
# traffic to it.
map $name $target_port {
  default           $server_port;
  'homeassistant'  	'8123';

server {
  # Here we parse the URL to use the innermost subdomain as the local server name.
  # This regex stores the first non-period characters in a variable called "$name".
  # For example, if we try to access "", $name will contain "test".
  server_name ~^(?<name>[^.]+);

  error_log /var/log/nginx/subdomain.errors;
  access_log /var/log/nginx/subdomain.access;

  listen 80;

  location / {
    # Here we indicate that we want to pass the port-80 traffic
    # to the target service's port, defined in the mapping above.
    proxy_pass http://localhost:$target_port;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # These settings allow Websockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_buffering off;

    # Adding the forwarded-for header allows the apps receiving
    # forwarded traffic to know more about where it came from, instead
    # of seeing only nginx as the client.
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;