As I want to host all services under my HomeLab server, Nginx Proxy is needed. Due to some limitations of my old approach using letsencrypt-nginx-proxy-companion, I decided to use Nginx Proxy Manager which has beautiful and secure admin interface.

You can easily assign your official domain to your home using DigitalOcean DNS or using Duckdns DNS.

My HomeLab setup:

  • Router: 192.168.11.1 - running OpenWrt
  • Server: 192.168.11.20 - ClearLinux VM, running docker deamon. I will put most of the running containers inside this VM.

Router Configuration

OpenWrt is my favourite router OS, so I build and maintain using ArchLinux docker container and add needed packages for my build.

Nginx Proxy uses port 80 (web browsing) and port 443 (SSL), thus I need to open respective ports and point to 192.168.11.120

# /etc/config/firewall

config redirect
	option target 'DNAT'
	option src 'wan'
	option dest 'lan'
	option proto 'tcp'
	option src_dport '80'
	option dest_port '80'
	option name 'HomeLab-Nginx-80'
	option dest_ip '192.168.11.20'

config redirect
	option target 'DNAT'
	option src 'wan'
	option dest 'lan'
	option proto 'tcp'
	option src_dport '443'
	option dest_port '443'
	option name 'HomeLab-Nginx-443'
	option dest_ip '192.168.11.20'

Nginx Proxy Manager configuration

You need to install docker and docker-compose, pls follow the official Docker getting started. For my ClearLinux, it is very straight forward:

# Install docker daemon and docker-compose
sudo swupd bundle-add containers-basic
sudo swupd bundle-add docker-compose

# Enable and start docker service
sudo systemctl enable docker
sudo systemctl start docker

# Add current user to docker group, so you can run all docker commands from user space
sudo gpasswd -a $USER docker


# Verify docker is running
docker info

To easily manage other containers running in same host, I need to create a bridge network named nginx-network, so Nginx Proxy can talk to them.

docker network create nginx-network

Let's start to create Nginx Proxy Manager container.

1) Create config file config.json with below information - this is the config for the database. I used the DB name instead of its alias as if other containers use the same alias, Nginx Proxy Manager can't talk to the database.

{
  "database": {
    "engine": "mysql",
    "host": "nginx-proxy-manager-db",
    "name": "npm",
    "user": "npm",
    "password": "npm",
    "port": 3306
 }

2) Create a docker-compose.yml in same folder with config.json with several docker volumes and use created bridge network nginx-network.

version: "3"
services:
  app:
    image: jc21/nginx-proxy-manager:2
    container_name: nginx-proxy-manager
    restart: always
    ports:
      # Public HTTP Port:
      - '80:80'
      # Public HTTPS Port:
      - '443:443'
      # Admin Web Port:
      - '81:81'
    environment:
      # Uncomment this if IPv6 is not enabled on your host
      DISABLE_IPV6: 'true'
    volumes:
      # Make sure this config.json file exists as per instructions above:
      - ./config.json:/app/config/production.json
      - data:/data
      - letsencrypt:/etc/letsencrypt
    depends_on:
      - db
    networks:
      - nginx-proxy
  db:
    image: jc21/mariadb-aria:10.4
    container_name: nginx-proxy-manager-db
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 'npm'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm'
    volumes:
      - mysql:/var/lib/mysql
    networks:
      - nginx-proxy
volumes:
  mysql:
  data:
  letsencrypt:
# Connect to existing nginx-network: `docker network create nginx-network`
networks:
  nginx-proxy:
    external:
      name: nginx-network

Then,

docker-compose up -d

Now you can goto the web console at: http://192.168.11.20:81

How to configure other containers with Nginx Proxy Manager

As I am using user-defined bridge network nginx-network, so all containers in nginx-network can communicate with each other by container name or container network alias. In addition, all container ports are exposed to its internl network, so no port mapping is needed, unless you want container of other host to talk to. Container network alias needs to be identical, otherwise app container could talk to wrong db container.

For the safety, I set and use container_name for communication between containers.

Take example of my pi-hole, in order to expose web https://dns.bacnh.com to this container, I have 3 parameters:

  • Domain Names: dns.bacnh.com
  • Forward hostname: pihole - this is the container name
  • Forward port: 80 - this is container port - exposed by default to all containers inside nginx-network

Inside Nginx Proxy Manager, just add to respective fields:

To enable SSL, go to SSL tab, request new SSL Certificate:

Now I can see my web at: https://dns.bacnh.com/admin/index.php

The same principle can be applied for containers on other host as well. You can discover other Nginx Proxy Manager features like Redirection Hosts, Streams, 404 Hosts.

Good luck!