Nginx Proxy Manager does not respect HTTP/HTTPS proxy environment variables for outbound requests
Closed this issue · 6 comments
Checklist
- Have you pulled and found the error with
jc21/nginx-proxy-manager:latestdocker image?- ✅ Yes
- Are you sure you're not using someone else's docker image?
- ✅ Yes
- Have you searched for similar issues (both open and closed)?
- ✅ Yes
Describe the bug
When running Nginx Proxy Manager inside a corporate network where all outbound HTTP/HTTPS traffic must go through an HTTP proxy, the application fails to fetch external resources (like IP ranges or Let's Encrypt endpoints), even though the container itself can access the internet via the proxy.
Inside the container, curl http://google.com works perfectly using the http_proxy and https_proxy environment variables, but the backend process fails when fetching IP ranges:
[11/4/2025] [8:20:47 PM] [IP Ranges] › ℹ info Fetching [https://ip-ranges.amazonaws.com/ip-ranges.json](https://ip-ranges.amazonaws.com/ip-ranges.json)
[11/4/2025] [8:23:03 PM] [IP Ranges] › ✖ fatal
This suggests that the internal HTTP client used by NPM does not honor standard proxy environment variables (http_proxy, https_proxy, etc.).
Nginx Proxy Manager Version
jc21/nginx-proxy-manager:latest (pulled November 2025)
To Reproduce
Steps to reproduce:
- Deploy the following minimal
docker-compose.ymlinside a corporate network that requires proxy for outbound traffic:
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
environment:
TZ: "Australia/Brisbane"
http_proxy: "http://my-enterprise-proxy.com:3128"
https_proxy: "http://my-enterprise-proxy.com:3128"
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt-
Start the container:
docker compose up -d
-
Observe container logs with:
docker logs -f app
-
Notice that:
curlworks inside the container (docker exec -it app curl http://google.com)- But NPM fails when fetching IP ranges or other external URLs.
Expected behavior
Nginx Proxy Manager should respect system proxy environment variables (http_proxy, https_proxy, no_proxy) for all outbound HTTP/HTTPS requests made by its backend (e.g. when fetching IP ranges or interacting with Let's Encrypt).
Alternatively, an explicit configuration option (ENV variable or config file entry) could be added to define a corporate proxy for NPM’s backend.
Screenshots
Log excerpt showing the failure:
[11/4/2025] [8:20:47 PM] [Global ] › ℹ info IP Ranges fetch is enabled
[11/4/2025] [8:20:47 PM] [IP Ranges] › ℹ info Fetching IP Ranges from online services...
[11/4/2025] [8:20:47 PM] [IP Ranges] › ℹ info Fetching https://ip-ranges.amazonaws.com/ip-ranges.json
[11/4/2025] [8:23:03 PM] [IP Ranges] › ✖ fatal
Operating System
- Host OS: Debian 12
- Docker version 28.5.1, build e180ab8
- Deployment: Docker Compose
- Environment: Corporate network (HTTP proxy mandatory for outbound traffic)
Additional context
- Inside the container, all standard tools (
curl,wget,apt) successfully use the configured proxy. - Only NPM’s internal backend fails to use it.
- This prevents NPM from fetching IP ranges and renewing Let's Encrypt certificates.
- It would be very helpful if the backend automatically respected
HTTP_PROXY,HTTPS_PROXY, andNO_PROXYenv variables, like most CLI tools and HTTP clients.
Is there any SSL inspection by the firewall? You may need to either install the root certificate for it or create exceptions.
Hmm yeah nodejs doesn't come with this support out of the box. It might be easier to ask for an HTTPS_PROXY env var alone and use that. I'll take a look
Ok that was easier than expected. It will be fixed in 2.13.1.
For your reference, the protocols and env vars supported are listed in this package.
I've only tested with Squid myself, but works as expected.
Just tested the fix (commit 4cb85f6) behind my proxy and it works great
app-1 | [11/5/2025] [10:08:33 AM] [Global ] › ℹ info Using Sqlite: /data/database.sqlite
app-1 | [11/5/2025] [10:08:34 AM] [Migrate ] › ℹ info Current database version: none
app-1 | [11/5/2025] [10:08:34 AM] [Setup ] › ℹ info Logrotate Timer initialized
app-1 | [11/5/2025] [10:08:34 AM] [Setup ] › ℹ info Logrotate completed.
app-1 | [11/5/2025] [10:08:34 AM] [Global ] › ℹ info IP Ranges fetch is enabled
app-1 | [11/5/2025] [10:08:34 AM] [IP Ranges] › ℹ info Fetching IP Ranges from online services...
app-1 | [11/5/2025] [10:08:34 AM] [IP Ranges] › ℹ info Fetching https://ip-ranges.amazonaws.com/ip-ranges.json
app-1 | [11/5/2025] [10:08:35 AM] [IP Ranges] › ℹ info Fetching https://www.cloudflare.com/ips-v4
app-1 | [11/5/2025] [10:08:35 AM] [IP Ranges] › ℹ info Fetching https://www.cloudflare.com/ips-v6
app-1 | [11/5/2025] [10:08:35 AM] [SSL ] › ℹ info Let's Encrypt Renewal Timer initialized
app-1 | [11/5/2025] [10:08:35 AM] [SSL ] › ℹ info Renewing SSL certs expiring within 30 days ...
app-1 | [11/5/2025] [10:08:35 AM] [IP Ranges] › ℹ info IP Ranges Renewal Timer initialized
app-1 | [11/5/2025] [10:08:35 AM] [Global ] › ℹ info Backend PID 181 listening on port 3000 ...
app-1 | [11/5/2025] [10:08:35 AM] [SSL ] › ℹ info Completed SSL cert renew processIP ranges are now fetched successfully, no more errors.
Huge thanks @jc21 for the quick response and patch !!
For anyone looking at this later, here’s what my compose.yaml looks like:
services:
app:
image: npm-proxy:proxy-fix
restart: unless-stopped
environment:
TZ: "Europe/Paris"
HTTP_PROXY: "http://my-enterprise-proxy.com:3128"
HTTPS_PROXY: "http://my-enterprise-proxy.com:3128"
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt