4 min read

Project: Nginx Proxy Manager for your self hosted web applications

Project: Nginx Proxy Manager for your self hosted web applications
Photo by Kedibone Isaac Makhumisane / Unsplash

Now that you have a website, you may want to make it available over the internet. For that, you'll need to purchase a domain name. You can use stuff like Cloudflare, Namecheap, GoDaddy, Porkbun or others.

For simplicity, I will assume you have a static IP - you can set this as an A record wherever you manage your DNS records. If you have a dynamic IP, you'll need to automate this process - usually by having an agent or a script on a machine updating your A record whenever this changes. I'll also assume you'll be using Cloudflare to manage your DNS records. I don't necessarily recommend Cloudflare, but they have a strong free offering and this post has to end somewhere, so we'll just go with this assumption for now.

So you're the owner of a brand new domain name for your business, blog, project, or maybe you just want to show off your Labubu collection. Congratulations.

At the moment, nothing will really work when trying to access yourdomain.example over the internet - you need to set up an A record for your domain (the external IP of wherever your website is being hosted).

You probably have a router with a built in firewall, so you'll need to make a few changes by opening some ports (80 and/or 443).

I will also assume your router/firewall is able to do port forwarding - you will need to forward port 443 to the IP and port of the machine running Ghost on your LAN.

Don't do that - there is a better way.

Introducing a reverse proxy in your setup will be key for automatic SSL management and eventually expanding your new self hosting hobby. There are quite a few available - Nginx Proxy Manager, Caddy, Traefik - but I'll assume you prefer a GUI for everything and a straightforward way to expose your website to the internet, so we'll go with Nginx Proxy Manager. Personally, I like Caddy for simplicity - but it has a learning curve that is outside of the scope for this post. I've heard excellent things about Traefik.

Creating another stack on Portainer, called nginxproxymanager:

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80' # Public HTTP Port
      - '443:443' # Public HTTPS Port
      - '81:81' # Admin Web Port
      # Add any other Stream port you want to expose
      # - '21:21' # FTP
    environment:
      # Uncomment this if you want to change the location of
      # the SQLite DB file within the container
      DB_SQLITE_FILE: "/data/database.sqlite"
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
    volumes:
      - ${dockerpath}/nginx/data:/data
      - ${dockerpath}/nginx/letsencrypt:/etc/letsencrypt

Do not forget about the environmental variable:

dockerpath=/yourpath/to/yourmappedfolder

Your Nginx Proxy Manager instance will be available on http://localhost:81/login - the default logins are:

Email:    [email protected]
Password: changeme

On your Cloudflare instance, ensure your external IP is set as an A record for your domain. I also recommend you add a CNAME as www (this way, if a user accesses www.yourdomain.com or yourdomain.com, it reaches the same place) - and feel free to use the proxy feature as a layer of security.

Cloudflare supports Let's Encrypt SSL automation, Nginx Proxy Manager can connect to Cloudflare via an API token. You can obtain an API Token by going on your Profile in Cloudflare, and selecting API Tokens - the permissions required will be:

Permissions:
Zone - DNS - Edit
Zone resources:
Include - All zones from an account

You can select just a particular zone for this API token if you intend to have multiple domains with different external IPs on the same account.

Create your token and save it. You will need it later.

Modify your router settings - first, you'll need to open port 443. Then, you'll have to forward this to port 443 on your Docker host. The way to do this will depend on the manufacturer of your network kit- and some may not support port forwarding at all, although most modern routers will support this and make it straightforward.

On your Nginx Proxy Manager instance, navigate to SSL certificates - then tap Add SSL certificate, select Let's Encrypt.

Fill in your domain name - and I'd advise you also add a record for the www subdomain, so your Domain Names field should look like:

www.yourdomain.com, yourdomain.com

Select DNS challenge and select Cloudflare from the drop down list - a text field will auto-populate with an example for an API token. Just replace it with yours. Agree with the terms and conditions and you now should get automated certificates for any subdomain of and your domain.

Access Hosts on your Nginx Proxy Manager instance. Add a proxy host, as below:

Domain names: www.yourdomain.example, yourdomain.example
http <IP of your ghost instance> 2368
Block common exploits

Select the SSL tab - select your SSL certificate from the drop down list and tick Force SSL. Save this.

There is one thing left to do - go back to your Stack for Ghost and replace the ${url} variable value (localhost/ip:2368) with "yourdomain.example".

Your website now has automatic https and automatic renewing SSL certificates behind a reverse proxy and is open to the internet.

Additionally, you can use your reverse proxy for any other browser-based software. Just remember to create a certificate for it and if you want it available over the internet, you'll have to modify some DNS records in your Cloudflare environment.

Automatic SSL certificates are especially useful in the near future, as the lifetime of these certificates is going to be reduced from 398 days (at the time of writing), to 200 days after March 2026, 100 days after March 2027 - then finally 47 days from March 2029.