Here's a guide to running an nginx reverse proxy on Unraid with a Let's Encrypt wildcard cert (which can cover the Unraid web gui too), using the official nginx and certbot Docker images.
Other options:
- caddy — popular nginx alternative with built-in automatic Let's Encrypt
- pomerium — all-in-one reverse proxy, SSL, and OAuth-based login (compare to Caddy Security)
- nginx-certbot — parses your nginx configs and manages certbot for you (see the original version of this gist for a script to copy your cert to Unraid)
- swag — used to be called letsencrypt; has other things in it like PHP & fail2ban
Tip: The user script below for updating the Unraid cert can be used by itself if you choose any of these instead (just remove the
docker restart nginx
).
This assumes you have a) a domain pointed at your home network, and b) a DNS server supported by certbot. If not, buy a domain, set up Cloudflare as the nameserver, and use ddns-updater to keep it pointing at your IP. The rest of the guide will assume you're using Cloudflare and that your domain is example.com (change those references as you see them).
For subdomains, create a CNAME pointing *
to the domain (or maybe don't, see "A note about Windows" below...). The DNS tab in Cloudflare should look like this:
Type | Name | Content | Proxy status | TTL |
---|---|---|---|---|
A | example.com | your ip | DNS only | 10 min |
CNAME | * | example.com | DNS only | 1 day |
To use the Let's Encrypt cert for the Unraid web gui as well, your router should be configured to use your domain such that <hostname>.example.com resolves to <hostname>'s IP. (In UniFi, this is under Networks → LAN → Advanced.) You'll also need to go into Unraid's "Management Access" settings and set "Use SSL/TLS" to Yes and "Local TLD" to your domain (e.g. example.com, without the Unraid hostname).
Windows likes to append your domain to DNS lookups. If the external DNS has a wildcard CNAME, sometimes foo.example.com
, which should refer to the local hostname foo
if example.com
is your network domain, instead gets looked up as foo.example.com.example.com
, which resolves via that CNAME to your public IP, which gets port-forwarded via your router to the wrong place, and you get a connection refused. Running ipconfig /flushdns
seems to fix this temporarily (it's possible after rebooting, my router received the DNS request for the Unraid server before its hostname got added to its DNS tables and thus forwarded the lookup to the external DNS, and that response got cached).
What you can do instead is a) add your Unraid's subdomain to the external DNS, pointing it at its internal IP so that it resolves correctly even if it gets looked up wrong; b) avoid the wildcard and explicitly add CNAMEs for each subdomain you're going to reverse proxy; or c) run your own local DNS server in a docker container.
Having lost many hours to this, I suggest (b).
Docker → Add container, toggle "advanced view" in the top-right, and set as follows:
- Name: nginx
- Repository: nginx:alpine
- Docker Hub URL: https://hub.docker.com/_/nginx
- Icon URL: https://i.imgur.com/rNp4MIA.png
- Path: /mnt/user/appdata/nginx/:/etc/nginx/conf.d
- Path: /mnt/user/appdata/letsencrypt/:/etc/letsencrypt
- Port: 8080:80
- Port: 8443:443
Set your router to forward ports 80 and 443 to 8080 and 8443 on the server, respectively (Unraid will need a fixed IP).
If your router for some reason can't map to a different port, or you want nginx to have a separate IP on your network, use the "Custom: br0" network (not to be confused with Docker's default bridge, this is a macvlan using a Linux bridge network that essentially acts like the host and container are plugged into a physical network switch:
docker network ls
).
You should be able to hit up your domain now and see the default nginx page.
Save the Certbot script below to /boot/config/plugins/user.scripts/scripts/certbot/script. Be sure to find & replace all instances of "example.com" and put your email in. Set it to run daily.
For Cloudflare, you'll need to create /mnt/user/appdata/letsencrypt/cloudflare.ini; for other dns providers, change those options and the image name. In any case, see the docs here.
IMPORTANT! The wildcard must come first so that it becomes the cert's CN (common name). This tells Unraid that it should use <hostname>.example.com; otherwise when the system reboots, it tries to redirect to example.com, thinking that's its url, which ends up resolving to the nginx server, which isn't running, and so you can't access the web ui anymore! If this happens to you as it did to me, rm /boot/config/ssl/certs/* && reboot
. Temporarily change --keep-until-expiring
to --force-renewal
to fix the cert after swapping the domains.
Drop the ssl.conf file below in /mnt/user/appdata/nginx (again, replacing "example.com"). Any reverse proxy configs you add now only need to listen to 443 and will get the wildcard cert & redirect from http automatically.
(dhparams.pem can be created using openssl dhparam -out /mnt/user/appdata/letsencrypt/dhparam.pem 4096
, or you can remove that line.)