Expose other services through 443 using Nginx+DuckDNS

Tags: #<Tag:0x00007fc3fb4f6bb0> #<Tag:0x00007fc3fb4f6ac0> #<Tag:0x00007fc3fb4f69d0> #<Tag:0x00007fc3fb4f6908>

The DuckDNS plugin allows you to access Home Assistant through https://yourdomain.org/. However exposing other services (such as Grafana, Bitwarden, etc) without having to open another port through the router is tricky. This posts explains how to expose such service to a defined location i.e. https://yourdomain.org/grafana without exposing any additional port and adding SSL for free, even if the service doesn’t support it.

Note: I tried using the Nginx Proxy Manager add-on but it requires exposing additional ports which I didn’t like and it can’t be configured to reuse the DuckDNS certificate from the plugin.

Setting up DuckDNS and Nginx

  1. Setup the DuckDNS plugin following the official guide “Effortless encryption with Let’s Encrypt and DuckDNS”.
  2. Setup the NGINX Home Assistant SSL proxy using the available documentation.
  3. Ensure that Home Assistant can be accessed through https://yourdomain.org

Adding extra endpoints

  1. Make sure the service is running and can be accessed through the internal port without SSL. For Bitwarden you should be able to access http://homeassistant.local:7277/ from the local network, note the http:// (without the s).
  2. In Nginx add-on configuration set customize.active to true, this allows adding extra locations.
  3. Using your preferred file editor edit/create the file /share/nginx_proxy_default.conf with the services you want to expose. This is what I used for Bitwarden:
location /bitwarden {
    proxy_set_header Accept-Encoding "";
    proxy_pass http://homeassistant.local.hass.io:7277/;
    sub_filter "<head>" "<head><base href=\"/bitwarden/\">";
    sub_filter_once on;
    proxy_set_header Host $host;
    proxy_redirect http:// https://;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

More services can be added one after the other, just replace the location, port number and sub_filter accordingly. Obviously, make sure the location is not already in use.
4. Save the file and restart the Nginx add on, check the logs for any errors.

This redirects all incoming traffic from /bitwarden to the internal port. It also adds SSL to secure the connection. One issue with this is that now all the resources in the HTML pages are pointing to the wrong locations. This is corrected with the sub_filter option which modifies the HTML. For the sub_filter to work compression needs to be disabled which is done by clearing Accept-Encoding

Let me know if it was useful!