Skip to content

Nginx

Nginx is a reverse proxy service. From the perspective of a client (browser), an Nginx server appears to be a standard web server but its behaviour is that of an intermediary, relaying client requests to the web service the client actually wants to reach.

references

default ports

The IOTstack implementation listens on the following ports:

  • 80 the common front end for HTTP-based traffic
  • 443 the common front end for HTTPS-based traffic
  • 81 the administrative interface for Nginx

    these are all "privileged" ports which means you may have trouble deploying this container in a "Docker Desktop" environment.

environment variables

You can expect Nginx to work out of the box without any special configuration. The IOTstack service definition includes these environment variables:

environment:
  - TZ=${TZ:-Etc/UTC}
  - INITIAL_ADMIN_EMAIL=admin@example.com
  - INITIAL_ADMIN_PASSWORD=changeme
  - DISABLE_IPV6=true

Although you can change them if you wish, the email address and password only have effect on first launch, and only up until your first login when you are guided through the process of defining the first user and a (hopefully) stronger password.

Unless you have good reasons for enabling IPv6, it is recommended that you leave it disabled.

reference model

The network model shown in Figure 1 will help you to understand how to configure Nginx.

Figure 1: Network Model
Network reference model

The model consists of two hosts, pi1 and pi2. each of which is running three Docker containers. This model was constructed to show how you would set up Nginx to reach services running under various conditions. All these services could just as easily be running on a single computer and, rather than being hosted on physical computers (eg Raspberry Pi), the hosts could be implemented as a virtual guests in a Proxmox-VE system.

domain name service

You will need a Domain Name System service to make effective use of Nginx. You can use implementations like Pi-hole, BIND9 (Berkeley Internet Name Daemon - the grandparent of all DNS servers) or any other equivalent service. Your DNS service can be native or running in a container. It can be private, public, on-site or off-site.

This document uses the domain your.home.arpa throughout. Substiute your own domain accordingly. This guide assumes a DNS service which can resolve the following resource records:

$ORIGIN your.home.arpa.

pi1           IN  A      192.168.203.60
pi2           IN  A      192.168.203.61

esphome       IN  CNAME  pi1.your.home.arpa.
gitea         IN  CNAME  pi1.your.home.arpa.
grafana       IN  CNAME  pi1.your.home.arpa.
nginx         IN  CNAME  pi1.your.home.arpa.
nodered       IN  CNAME  pi1.your.home.arpa.
pihole        IN  CNAME  pi1.your.home.arpa.

The above list uses BIND9 syntax. In words:

  • all the names in the left-hand column imply your.home.arpa. For example:

    • pi1 implies pi1.your.home.arpa.
  • pi1 and pi2 are actual hosts which are reachable at the associated IP addresses (the "A" means "address"). For example:

    • pi1.your.home.arpa is reachable at 192.168.203.60
  • the remaining names are aliases. That is, when presented with a domain name which maps to a CNAME record, the DNS also looks-up the corresponding A record. For example:

    • esphome.your.home.arpa looks up pi1.your.home.arpa and returns 192.168.203.60

In terms of Pi-hole:

  • for versions 2024.07.0 and earlier, you manage:

    • A records via Local DNS » DNS Records; and
    • CNAME records via Local DNS » CNAME Records
  • for later versions, Settings » Local DNS Records manages both A and CNAME records.

If you use another DNS server you will need to work it out for yourself.

reverse proxy basics

When you type a URL like either of the following into the search bar of your browser:

http://esphome.your.home.arpa
https://esphome.your.home.arpa
  1. The default port of 80 is assumed (for HTTP) or 443 (for HTTPS);
  2. Via the CNAME lookup, the DNS supplies the IP adddress of the host pi1 (192.168.203.60) so your client's system can direct IP datagrams to the host where the Nginx service is running;
  3. The Nginx service listening on port 80 (or 443) on pi1 still sees the original URL of:

    http://esphome.your.home.arpa
    

    and can use the string esphome.your.home.arpa to work out how to redirect the connection to the esphome service which, in this example, is running on the same host and is listening on port 6052.

getting started

Nginx uses port 81 for its administrative interface. To manage Nginx you connect to the host where the Nginx service is running using port 81. For example:

http://pi1.your.home.arpa:81

Login with the default credentials:

  • Email address: admin@example.com
  • Password: changeme

You will be presented with an "Edit User" dialog where you should set the fields according to your requirements. That dialog is followed by a "Change Password" dialog where you enter changeme into the "Current Password" field, then supply a new password of appropriate strength.

See also if you forget your password.

add SSL certificate

Although it is not essential, it is a good idea to provision at least one SSL certificate before you start to use the Nginx reverse proxy manager. This is usually a so-called wildcard certificate, meaning it will authenticate hosts matching *.your.home.arpa. Nginx supports both Let's Encrypt and private self-signed SSL certificates:

Once you have decided on your approach, use Figure 2 as your guide.

Figure 2: Add SSL certificate
Add SSL certificate
  1. Click on the "SSL Certificates" tab 🄰.
  2. Click Add SSL Certificate 🄱 and choose one of the options 🄲.
  3. If you are provisioning a Let's Encrypt certificate:

    • fill in the fields 🄳 and 🄴
    • optionally enable the DNS challenge 🄵
    • agree to the Ts&Cs 🄶 and
    • click Save 🄷.
  4. If you are provisioning a self-signed certificate:

    • provide a name at 🄸 (eg "*.your.home.arpa")
    • click Browse 🄹, then navigate to and select the private key associated with your wildcard certificate
    • click Browse 🄺, then navigate to and select your wildcard certificate
    • in most home networks you won't need to provide an intermediate certificate so you can leave that empty; and
    • click Save 🄻.

adding hosts

Use Figure 3 as your guide.

Figure 3: Add proxy host
Add proxy host
  1. Click on "Hosts" 🄰 and choose "Proxy Hosts" from the menu 🄱.
  2. Click Add Proxy Host 🄲.
  3. The "Details" tab 🄳 should be selected by default but, if not, select it.
  4. In the "Domain Names" field 🄴, type the fully-qualified alias (or "CNAME") name of the service. For example:

    esphome.your.home.arpa
    

    There is a small trick to this. As you type the characters of the domain name, the name will be repeated in a drop-down menu below the field. Once you have finished typing the domain name in the field, click on the completed domain name in the drop-down menu below the field.

  5. Table 1 shows how the "Scheme" 🄵, "Forward Hostname or IP" 🄶 and "Forward Port" fields 🄷 should be completed.

    Table 1: Nginx forwarding
    Nginx forwarding

    The choice of scheme 🄵 depends on whether the service you are trying to provision expects HTTP or HTTPS. In the reference model, only gitea expects HTTPS; all the others expect HTTP.

    The general rules are:

    1. If Nginx is trying to reach itself, use localhost or 127.0.0.1 or the container name (nginx) and the internal (container) port where the administrative GUI is to be found.
    2. Nginx is a non-host-mode Docker container so if it is trying to reach:

      • another non-host-mode service on the same host then use the «containerName» and internal port. The example here is Node-RED.
      • a host-mode or native service on the same host then use the special name host.docker.internal and the host port on which the service is listening. The example here is ESPHome.
      • a service on a different host then use the fully-qualified domain name of that other host plus the external port (if the service is running in a non-host-mode container) or host port (if the service is either native or running in a host-mode container).
  6. In almost all cases, you will want to enable "Websockets Support" 🄸.

  7. Switch to the "SSL" tab 🄹.
  8. The "SSL Certificate" field is a popup menu. Choose the relevant (or only) certificate you provisioned earlier.
  9. If the destination service expects HTTPS traffic (ie the choice you made at 🄵) you can also enable "Force SSL" 🄻 to prevent attempts to use HTTP.
  10. Click Save 🄼.

Each proxy host that you provision appears in the list. You can test connections locally by clicking on the service name in the "Source" column.

container maintenance

You can maintain the Nginx container with normal pull commands:

$ cd ~/IOTstack
$ docker compose pull nginx
$ docker compose up -d nginx
$ docker system prune -f

if you forget your password

If you forget your password, you really only have two choices:

  1. You can erase the persistent store and start from a clean slate; or
  2. You can attempt to replace your lost password with a known value.

To replace your password with a known value:

  1. You will need the whois package:

    $ sudo apt update && sudo apt install -y whois
    
  2. Define the following variables:

    DB="$HOME/IOTstack/volumes/nginx/data/database.sqlite"
    EMAIL="user@domain"
    

    where user@domain is the email address associated with the password you have forgotten. If you have also forgotten the email address, you can recover a list of email addresses by running:

    $ sqlite3 "$DB" "SELECT email FROM user;"
    
  3. The whois package provides the mkpasswd utility, which you will use to generate a hash for your desired password:

    $ HASH=$(mkpasswd -m bcrypt)
    Password: 
    

    Type your desired password at the Password: prompt and press return. The hashed version of your password will be copied to the HASH environment variable.

  4. Run the following command:

    $ sudo sqlite3 "$DB" "UPDATE auth SET secret=\"$HASH\" WHERE user_id=(SELECT id FROM user WHERE email = \"$EMAIL\");"
    
  5. Restart the container:

    $ cd ~/IOTstack
    $ docker compose restart nginx
    

Providing you don't make any mistakes, the database will be updated with the hash corresponding with the desired password you typed in step 3.

starting over from a clean slate

Starting from a clean slate means you lose all the certificates and hosts you have provisioned. You will need to set up everything again from scratch.

Proceed as follows:

$ cd ~/IOTstack
$ docker compose down nginx
$ sudo rm -rf ./volumes/nginx
$ docker compose up -d nginx