An automated bridge between Docker container labels and Nginx Proxy Manager (NPM). This agent monitors the Docker daemon for container lifecycle events and automatically manages proxy hosts in your NPM instance based on container labels.
- Zero-Touch Configuration: Manage your reverse proxy directly from your
docker-compose.yml. - Automatic SSL: Support for automated Let's Encrypt certificates via NPM.
- Smart Port Detection: Automatically resolves whether
npm.proxy.portis a container-internal port or a host-mapped port, and picks the correct upstream (host gateway IP + host port, or container IP + internal port). - Self-Healing: Automatically cleans up proxy hosts when containers are removed.
- Lightweight: Built on Alpine Linux with minimal footprint.
- Monitoring Dashboard: Simple built-in dashboard for status overview at
http://localhost:8080.
graph LR
subgraph "Docker Host"
A[Application Container] -- Label: npm.proxy.host --> B(Port Resolution)
B -.-> C[NPM Docker Agent]
end
C -- API Request --> D[Nginx Proxy Manager]
D -- Proxy Traffic --> A
- Nginx Proxy Manager: A running instance of Nginx Proxy Manager.
- Docker Socket Access: The agent needs read access to
/var/run/docker.sock.
| Variable | Description | Required | Default |
|---|---|---|---|
NPM_API_BASE_URL |
Base URL of your NPM instance (e.g., https://npm.example.com) |
Yes | — |
NPM_API_USER |
Admin email for NPM | Yes | — |
NPM_API_PASSWORD |
Admin password for NPM | Yes | — |
NPM_DEFAULT_LE_EMAIL |
Default email for Let's Encrypt certificates | No | — |
NPM_DEFAULT_FORWARD_HOST |
Override forward host for all containers | No | Auto-detected |
DOCKER_HOST |
Remote Docker daemon endpoint (e.g. tcp://host:2375) |
No | Unix socket |
| Label | Description | Default |
|---|---|---|
npm.proxy.host |
Comma-separated domains (e.g., app.example.com) |
Required |
npm.proxy.port |
Port — container-internal or host-mapped (auto-detected) | 80 |
npm.proxy.scheme |
Protocol (http or https) |
http |
npm.proxy.ssl |
Force SSL & request Let's Encrypt cert (true/false) |
true |
npm.proxy.forward_host |
Override forward host for this container | Auto-detected |
npm.proxy.port accepts either the container-internal port or the host-mapped port — the agent inspects Docker's port mapping table and figures out which one it is:
| Scenario | Label | Upstream used by NPM |
|---|---|---|
Container port 80 mapped to host 8089 |
npm.proxy.port=80 |
<host-gateway>:8089 |
Container port 80 mapped to host 8089 |
npm.proxy.port=8089 |
<host-gateway>:8089 |
| No host port mapping (same Docker network) | npm.proxy.port=80 |
<container-ip>:80 |
When a host port mapping is detected and no explicit forward_host is set, the agent uses the Docker network gateway IP (the host's IP as seen from inside the container) so NPM can reach the service via the host.
Run the agent standalone, pointing it at an existing NPM instance:
docker run -d \
--name npm-agent \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-p 8080:8080 \
-e NPM_API_BASE_URL=http://npm.example.com:81 \
-e NPM_API_USER=admin@example.com \
-e NPM_API_PASSWORD=changeme \
-e NPM_DEFAULT_LE_EMAIL=admin@example.com \
ghcr.io/rokreativa/npm-agent:latestNote: If the Docker socket is permission-denied, add
--user rootto the command.
This example runs Nginx Proxy Manager, the agent, and a proxied application together:
services:
# Nginx Proxy Manager
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: npm
restart: unless-stopped
ports:
- '80:80'
- '443:443'
- '81:81'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
# NPM Docker Agent
npm-agent:
image: ghcr.io/rokreativa/npm-agent:latest
container_name: npm-agent
restart: unless-stopped
depends_on:
- npm
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "8080:8080" # Optional: dashboard
environment:
- NPM_API_BASE_URL=http://npm:81
- NPM_API_USER=admin@example.com
- NPM_API_PASSWORD=changeme
- NPM_DEFAULT_LE_EMAIL=admin@example.com
# Example Application (Automatically Proxied)
whoami:
image: traefik/whoami
container_name: whoami
ports:
- "8089:80" # host:8089 -> container:80
labels:
- "npm.proxy.host=whoami.example.com"
- "npm.proxy.port=80" # container-internal port; agent resolves to host:8089 automatically
- "npm.proxy.ssl=true"If you see PermissionError: [Errno 13] Permission denied, the agent can't access the Docker socket. Fix options:
Option A — Run as root (simplest):
npm-agent:
user: rootor with docker run:
docker run --user root ...Option B — Add the Docker group GID:
# Find the GID of the docker socket group
stat -c '%g' /var/run/docker.socknpm-agent:
user: "1000:999" # Replace 999 with your docker GID- Socket Access: Mount the Docker socket as read-only (
:ro). - Non-Root: The container defaults to a non-privileged user; use
user: rootonly if needed. - Network: Ensure the agent can reach both the Docker socket and the NPM API.
This project is licensed under the MIT License - see the LICENSE file for details.