Skip to content

Nginx Proxy Manager

Nginx Proxy Manager is a free, open-source proxy manager that provides a user-friendly interface for managing proxy hosts with integrated Let’s Encrypt SSL certificates. It simplifies web service management through an intuitive interface, eliminating the need for manual configuration of files or SSL certificates.

The project runs as a Docker container and requires only a database for operation.

Preparation

Docker network

First, create a Docker network to eliminate the need for exposing ports for individual services. Only ports 80 and 443 are typically required for the proxy manager.

Terminal window
sudo docker network create proxy-network

Create directory

Terminal window
mkdir -p nginx-proxy-manager/{certs,data,db}
cd nginx-proxy-manager
touch .env docker-compose.yml

Environment variables

Some environment variables are needed to configure the proxy manager.

Terminal window
bash -c 'echo "DB_USER=npm" >> .env'
bash -c 'echo "DB_NAME=npm" >> .env'
bash -c 'echo "DB_PWD=$(openssl rand -base64 32)" >> .env'
bash -c 'echo "DB_ROOT_PWD=$(openssl rand -base64 32)" >> .env'

Installation

The installation is done via Docker Compose.

.../nginx-proxy-manager/docker-compose.yml
networks:
proxy-network:
external: true
internal:
external: false
services:
npm-app:
image: "jc21/nginx-proxy-manager"
container_name: npm-app
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
environment:
DB_MYSQL_HOST: "npm-db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: $DB_USER
DB_MYSQL_NAME: $DB_NAME
DB_MYSQL_PASSWORD: $DB_PWD
DISABLE_IPV6: "true"
networks:
- proxy-network
- internal
volumes:
- ./data:/data
- ./certs:/etc/letsencrypt
npm-db:
image: "jc21/mariadb-aria"
# image: "yobasystems/alpine-mariadb:10.4.17-arm32v7"
container_name: npm-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: $DB_ROOT_PWD
MYSQL_DATABASE: $DB_NAME
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PWD
networks:
- internal
volumes:
- ./db:/var/lib/mysql
Terminal window
sudo docker compose up -d

Proxy-Host

The GUI should be available under the ip-address of the server and port 81.

Username: admin@example.com
Password: changeme

If you have a domain routed to the server, you can create the first proxy host. You can buy an externaldomain on Netcup from € 5 a year. A .com-Domain costs nearly € 14 a year. (affiliate link)

Proxy Host

Now you should be able to access the Nginx Proxy Manager dashboard under the domain you entered.

Access List

Maybe you should not allow worldwide access for some services. For this purpose there is the Access List function.

Access List

With the access list as shown on the image only access from private network is allowed.

10.0.0.0/8
127.0.0.1/8
172.16.0.0/12
192.168.0.0/16

SSL

After creating a proxy host, you can also request a Letsencrypt certificate for it via the interface.

Port publish

If the proxy host provides a connection to the Nginx proxy manager, the port publishing of port 81 is no longer needed, the docker-compose.yml can be adjusted.

.../nginx-proxy-manager/docker-compose.yml
networks:
proxy-network:
external: true
internal:
external: false
services:
npm-app:
image: "jc21/nginx-proxy-manager"
container_name: npm-app
restart: unless-stopped
ports:
- "80:80"
- "443:443"
# - "81:81"
environment:
DB_MYSQL_HOST: "npm-db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: $DB_USER
DB_MYSQL_NAME: $DB_NAME
DB_MYSQL_PASSWORD: $DB_PWD
DISABLE_IPV6: "true"
networks:
- proxy-network
- internal
volumes:
- ./data:/data
- ./certs:/etc/letsencrypt
npm-db:
image: "jc21/mariadb-aria"
# image: "yobasystems/alpine-mariadb:10.4.17-arm32v7"
container_name: npm-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: $DB_ROOT_PWD
MYSQL_DATABASE: $DB_NAME
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PWD
networks:
- internal
volumes:
- ./db:/var/lib/mysql
Terminal window
sudo docker compose down && sudo docker compose up -d

Beispieldienst

You can connect another host with a proxy host. In this example we will set up a web server.

Terminal window
mkdir homepage
cd homepage
mkdir html
touch html/index.html
touch docker-compose.yml
.../homepage/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>Homepage</title>
</head>
<body>
<h1>Homepage</h1>
<p>Dies ist eine Homepage.</p>
</body>
</html>
.../homepage/docker-compose.yml
networks:
proxy-network:
external: true
### SERVICE ###
services:
homepage:
container_name: homepage
image: nginx:latest
restart: unless-stopped
networks:
- proxy-network
security_opt:
- no-new-privileges:true
volumes:
- /html:/usr/share/nginx/html:ro
Terminal window
sudo docker compose up -d

Now you have to configure a new proxy host in Nginx Proxy Manager with the hostname homepage and port 80.

You can enter the new site under homepage.domain.de.

Update

Thanks to Docker and Docker Compose, updating is easy.

Terminal window
sudo docker compose pull
sudo docker compose down
sudo docker compose up -d