This needs : dockerhost
Compatible with NPM 2.17+ (jc21/nginx-proxy-manager:latest).
Custom rules (kept on purpose):
real_ip_header X-Forwarded-For(patched at start — required behind Cloudflare)- XFF chain via
$realip_remote_addrmap (client, <edge>) - GeoIP2 request headers to upstream
- Stock
$forward_host/$x_forwarded_*from current image (not a frozen fullnginx.confmount)
git clone https://github.com/ariadata/dc-nginxproxymanager.git nginx-proxy-manager
cd nginx-proxy-manager
# optional: rm -rf .git
# edit .env if needed
docker compose pullbash init.sh
docker compose up -dBy default Compose uses its own project network — no docker network create needed.
Optional shared external network (other stacks on the same bridge):
docker network create nginx-proxy-managerThen uncomment the networks: blocks in docker-compose.yml.
http://YOUR-IP:8181
On a fresh install, current NPM versions open a setup screen — you create the admin user yourself (no built-in default login anymore).
Older NPM used to ship with:
- User:
admin@example.com - Pass:
changeme
Done!
├── docker-compose.yml
├── .env
├── init.sh
├── update-geolite-db.sh
├── data/ # created by init.sh — mutable NPM state
├── letsencrypt/
└── configs/
├── proxy.conf # only full-file override (GeoIP + custom XFF)
├── scripts/entrypoint.sh # patches real_ip_header on stock nginx.conf
├── custom/ # → /data/nginx/custom
│ ├── root_top.conf # load_module geoip2
│ ├── events.conf
│ ├── http_top.conf # geoip2{} + includes
│ ├── xff-map.conf
│ └── cloudflare-extra.conf # optional; NPM also fetches CF ranges
└── geoip2/ # → /data/nginx/geoip2 (*.mmdb)
| Piece | Approach |
|---|---|
nginx.conf |
not mounted — image stock + 1-line real_ip_header patch in entrypoint |
| GeoIP modules | configs/custom/root_top.conf (official NPM hook) |
| GeoIP DBs / hooks | separate mounts under configs/ (not mixed into mutable data/) |
proxy.conf |
mounted — only way to add GeoIP/$custom_proxy_add_x_forwarded_for inside location / |
Refresh GeoIP DBs:
bash update-geolite-db.sh
docker compose exec nginx-proxy-manager nginx -s reloadfor being behind another nginx, use these in parent nginx config
proxy_ssl_name $host;
proxy_ssl_server_name on;Get Client Real IP by Header:
x-real-ip
(and X-Forwarded-For chain — first address is the client when recursive real_ip is configured downstream)
Added Headers for GeoIP2:
HTTP_GEOIP2_COUNTRY_CODE
HTTP_GEOIP2_COUNTRY_NAME
HTTP_GEOIP2_CITY_NAME
HTTP_GEOIP2_ASN_CODE
HTTP_GEOIP2_IP_ADDRESS
# Links:
https://download.maxmind.com/app/geoip_download
https://github.com/PrxyHunter/GeoLite2/releases/latest
https://cdn.jsdelivr.net/npm/geolite2-country/
https://cdn.jsdelivr.net/npm/geolite2-city/
https://cdn.jsdelivr.net/npm/geolite2-asn/