NGINX Reverse Proxy

Created: 6 Jul 2025.

../../_images/NGINX-Reverse-Proxy.png
  • The NGINX reverse proxy fronts all incoming HTTP & HTTPS requests and forwards these to the appropriate IP addresses that are usually hosted in one of the containers.

  • It also requests and automatically renews the Let’s Encrypt certificate for all incoming HTTPS requests for the two domains we host - thomas-pk.com and philiptk.com

  • The integration with Authelia is such that any container that requires authentication by Authelia, would have its web request forwarded to Authelia. Authelia checks if the request has an active on-going session, if not, the request is sent back to the Authelia login page. If an existing authenticated session already exists, the request is forwarded to the destination container. See Authelia Architecture for more details.

  • The configuration to set this up with the NGINX reverse proxy can be seen in the nginx.conf listing below from line 31 onwards.

nginx.conf

  • Given that there were not many recent (July 2025) examples for the nginx proxy integration with Authelia, I decided to provide the full listing of my NGINX reverse proxy configuration and Authelia configurations for public reference. I’ve managed to get the first basic flow working on the weekend of the 29th of Jun 2025.

  • My reference used for this configuration is based on that found at NGINX Integration with Authelia

nginx.conf reverse proxy configuration file (Created 6 Jul 2025)
  1worker_processes  1;
  2
  3events {
  4  worker_connections  1024;
  5}
  6
  7http {
  8  include           mime.types;
  9  default_type      application/octet-stream;
 10  sendfile          on;
 11  keepalive_timeout 65;
 12
 13  server {
 14    server_name  thomas-pk.com www.thomas-pk.com;
 15
 16    location / {
 17      proxy_pass http://192.168.1.6:80;
 18      proxy_set_header Host $host;
 19      proxy_set_header X-Real-IP $remote_addr;
 20      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 21      proxy_set_header X-Forwarded-Proto $scheme;
 22    }
 23
 24    listen 443 ssl; # managed by Certbot
 25      ssl_certificate /usr/local/etc/letsencrypt/live/philiptk.com-0001/fullchain.pem; # managed by Certbot
 26      ssl_certificate_key /usr/local/etc/letsencrypt/live/philiptk.com-0001/privkey.pem; # managed by Certbot
 27      include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
 28      ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
 29  }
 30
 31  server {
 32    if ($host = login.thomas-pk.com) {
 33      return 301 https://$host$request_uri;
 34    } # managed by Certbot
 35
 36    listen 80;
 37    server_name  login.thomas-pk.com;
 38    return 301 https://$server_name$request_uri;
 39  }
 40
 41  server {
 42    server_name  login.thomas-pk.com;
 43    set $upstream http://192.168.1.21:9091;
 44
 45    location / {
 46      include /usr/local/etc/nginx/snippets/proxy.conf;
 47      proxy_pass $upstream;
 48    }
 49
 50    location = /api/verify {
 51      proxy_pass $upstream;
 52    }
 53
 54    location /api/authz/ {
 55      proxy_pass $upstream;
 56    }
 57
 58    listen 443 ssl; # managed by Certbot
 59      ssl_certificate /usr/local/etc/letsencrypt/live/philiptk.com-0001/fullchain.pem; # managed by Certbot
 60      ssl_certificate_key /usr/local/etc/letsencrypt/live/philiptk.com-0001/privkey.pem; # managed by Certbot
 61      include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
 62      ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
 63  }
 64
 65  server {
 66    if ($host = history.thomas-pk.com) {
 67      return 301 https://$host$request_uri;
 68    } # managed by Certbot
 69
 70    listen 80;
 71    server_name history.thomas-pk.com;
 72    return 301 https://$server_name$request_uri;
 73  }
 74
 75  server {
 76    server_name  history.thomas-pk.com;
 77    include /usr/local/etc/nginx/snippets/authelia-location.conf;
 78    set $upstream http://192.168.1.22;
 79
 80    location / {
 81      include /usr/local/etc/nginx/snippets/proxy.conf;
 82      include /usr/local/etc/nginx/snippets/authelia-authrequest.conf;
 83      proxy_pass $upstream;
 84    }
 85
 86    listen 443 ssl; # managed by Certbot
 87      ssl_certificate /usr/local/etc/letsencrypt/live/philiptk.com-0001/fullchain.pem; # managed by Certbot
 88      ssl_certificate_key /usr/local/etc/letsencrypt/live/philiptk.com-0001/privkey.pem; # managed by Certbot
 89      include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
 90      ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
 91  }
 92
 93  server {
 94    server_name  philiptk.com www.philiptk.com;
 95
 96    location / {
 97      proxy_pass http://192.168.1.15:80;
 98      proxy_set_header Host $host;
 99      proxy_set_header X-Real-IP $remote_addr;
100      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
101      proxy_set_header X-Forwarded-Proto $scheme;
102    }
103
104    listen 443 ssl; # managed by Certbot
105      ssl_certificate /usr/local/etc/letsencrypt/live/philiptk.com-0001/fullchain.pem; # managed by Certbot
106      ssl_certificate_key /usr/local/etc/letsencrypt/live/philiptk.com-0001/privkey.pem; # managed by Certbot
107      include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
108      ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
109  }
110
111  server {
112    server_name cal.philiptk.com;
113    location / {
114      proxy_pass        http://192.168.1.23:5232/;
115      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
116      proxy_set_header  X-Forwarded-Host $host;
117      proxy_set_header  X-Real-IP $remote_addr;
118      proxy_set_header  X-Forwarded-Port $server_port;
119      proxy_set_header  X-Forwarded-Proto $scheme;
120      proxy_set_header  Host $http_host;
121      proxy_pass_header Authorization;
122    }
123
124    listen 443 ssl; # managed by Certbot
125      ssl_certificate /usr/local/etc/letsencrypt/live/philiptk.com-0001/fullchain.pem; # managed by Certbot
126      ssl_certificate_key /usr/local/etc/letsencrypt/live/philiptk.com-0001/privkey.pem; # managed by Certbot
127      include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
128      ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
129  }
130
131  server {
132    if ($host = philiptk.com) {
133      return 301 https://$host$request_uri;
134    } # managed by Certbot
135
136    listen       80;
137    server_name  philiptk.com;
138    return 404; # managed by Certbot
139  }
140
141  server {
142    if ($host = thomas-pk.com) {
143      return 301 https://$host$request_uri;
144    } # managed by Certbot
145
146    listen       80;
147    server_name  thomas-pk.com;
148    return 404; # managed by Certbot
149  }
150
151  server {
152    if ($host = cal.philiptk.com) {
153      return 301 https://$host$request_uri;
154    } # managed by Certbot
155
156    listen 80;
157    server_name cal.philiptk.com;
158    return 404; # managed by Certbot
159  }
160}

Being hosted on the FreeBSD MiniPC, the above configuration is found in the /usr/local/etc/nginx/nginx.conf location. It is supported by code snippets under the snippets folder containing the following 3 files which are also listed below.

  • proxy.conf

  • authelia-location.conf

  • authelia-authrequest.conf

Snippets

proxy.conf

  • I used the same copy of this snippet as on the Authelia NGINX integration website.

  • The original reference for this file can be found at proxy.conf. The file given below is an exact copy of that on the Authelia website.

snippets/proxy.conf file (Created 6 Jul 2025)
 1## Headers
 2proxy_set_header Host $host;
 3proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
 4proxy_set_header X-Forwarded-Proto $scheme;
 5proxy_set_header X-Forwarded-Host $http_host;
 6proxy_set_header X-Forwarded-URI $request_uri;
 7proxy_set_header X-Forwarded-Ssl on;
 8proxy_set_header X-Forwarded-For $remote_addr;
 9proxy_set_header X-Real-IP $remote_addr;
10
11## Basic Proxy Configuration
12client_body_buffer_size 128k;
13proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead.
14proxy_redirect  http://  $scheme://;
15proxy_http_version 1.1;
16proxy_cache_bypass $cookie_session;
17proxy_no_cache $cookie_session;
18proxy_buffers 64 256k;
19
20## Trusted Proxies Configuration
21## Please read the following documentation before configuring this:
22##     https://www.authelia.com/integration/proxies/nginx/#trusted-proxies
23# set_real_ip_from 10.0.0.0/8;
24# set_real_ip_from 172.16.0.0/12;
25# set_real_ip_from 192.168.0.0/16;
26# set_real_ip_from fc00::/7;
27real_ip_header X-Forwarded-For;
28real_ip_recursive on;
29
30## Advanced Proxy Configuration
31send_timeout 5m;
32proxy_read_timeout 360;
33proxy_send_timeout 360;
34proxy_connect_timeout 360;

authelia-location.conf

  • This file is also mostly the same as that on the NGINX Integration page for Authelia, except for the first line where I specify the IP address for my Authelia server.

  • The original reference for this file can be found at authelia-location.conf. The file given below is an exact copy of that on the Authelia website.

snippets/authelia-location.conf file (Created 6 Jul 2025)
 1set $upstream_authelia http://192.168.1.21:9091/api/authz/auth-request;
 2
 3## Virtual endpoint created by nginx to forward auth requests.
 4location /internal/authelia/authz {
 5    ## Essential Proxy Configuration
 6    internal;
 7    proxy_pass $upstream_authelia;
 8
 9    ## Headers
10    ## The headers starting with X-* are required.
11    proxy_set_header X-Original-Method $request_method;
12    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
13    proxy_set_header X-Forwarded-For $remote_addr;
14    proxy_set_header Content-Length "";
15    proxy_set_header Connection "";
16
17    ## Basic Proxy Configuration
18    proxy_pass_request_body off;
19    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
20    proxy_redirect http:// $scheme://;
21    proxy_http_version 1.1;
22    proxy_cache_bypass $cookie_session;
23    proxy_no_cache $cookie_session;
24    proxy_buffers 4 32k;
25    client_body_buffer_size 128k;
26
27    ## Advanced Proxy Configuration
28    send_timeout 5m;
29    proxy_read_timeout 240;
30    proxy_send_timeout 240;
31    proxy_connect_timeout 240;
32}

authelia-authrequest.conf

The original reference for this file can be found at authelia-authrequest.conf. The file given below is an exact copy of that on the Authelia website.

snippets/authelia-authrequest.conf file (Created 6 Jul 2025)
 1## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
 2auth_request /internal/authelia/authz;
 3
 4## Save the upstream metadata response headers from Authelia to variables.
 5auth_request_set $user $upstream_http_remote_user;
 6auth_request_set $groups $upstream_http_remote_groups;
 7auth_request_set $name $upstream_http_remote_name;
 8auth_request_set $email $upstream_http_remote_email;
 9
10## Inject the metadata response headers from the variables into the request made to the backend.
11proxy_set_header Remote-User $user;
12proxy_set_header Remote-Groups $groups;
13proxy_set_header Remote-Email $email;
14proxy_set_header Remote-Name $name;
15
16## Configure the redirection when the authz failure occurs. Lines starting with 'Modern Method' and 'Legacy Method'
17## should be commented / uncommented as pairs. The modern method uses the session cookies configuration's authelia_url
18## value to determine the redirection URL here. It's much simpler and compatible with the mutli-cookie domain easily.
19
20## Modern Method: Set the $redirection_url to the Location header of the response to the Authz endpoint.
21auth_request_set $redirection_url $upstream_http_location;
22
23## Modern Method: When there is a 401 response code from the authz endpoint redirect to the $redirection_url.
24error_page 401 =302 $redirection_url;
25
26## Legacy Method: Set $target_url to the original requested URL.
27## This requires http_set_misc module, replace 'set_escape_uri' with 'set' if you don't have this module.
28# set_escape_uri $target_url $scheme://$http_host$request_uri;
29
30## Legacy Method: When there is a 401 response code from the authz endpoint redirect to the portal with the 'rd'
31## URL parameter set to $target_url. This requires users update 'auth.example.com/' with their external authelia URL.
32# error_page 401 =302 https://auth.example.com/?rd=$target_url;