NginxProxyManager / NginxProxyManager/nginx-proxy-manager
Stale/missing nginx config files after editing existing Proxy Hosts, despite DB and UI reporting correct state
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 34.2k
- Forks
- 3.9k
- Avg merge
- 21h 12m
- Merged PRs (30d)
- 20
Description
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
After editing an existing Proxy Host's fields (e.g. Forward Hostname/IP, Forward Port) via the Admin UI, the change is correctly saved to the database (confirmed via direct MySQL query) and the UI reflects the new value. The API also reports "nginx_online": true, "nginx_err": null" for the host. However, the actual generated nginx config file on disk (/data/nginx/proxy_host/<id>.conf) is not regenerated and silently retains the old, stale values from before the edit. This results in nginx serving traffic to the wrong backend, even though every layer of the application (database, API response, admin UI) reports the host as correctly configured and online.
In one case, this also occurred after deleting and re-adding Custom Locations on a host, which left a duplicate location block in the generated config, causing nginx to fail config validation (nginx: [emerg] duplicate location "/admin") — visible only via the API's meta.nginx_err field, not the UI.
In another case, the config file was missing entirely for a host that was created and enabled in the database.
Workaround found: Issuing a PUT request to /api/nginx/proxy-hosts/<id> with the host's existing full data (effectively a no-op save via the API) forces NPM to correctly regenerate the on-disk config file.
Nginx Proxy Manager Version
2.15.1 (build 76f09db6)
To Reproduce
Steps to reproduce the behavior:
- Have an existing, working Proxy Host (in our case, originally created prior to migrating the underlying database from SQLite to MySQL/MariaDB)
- Edit the host's Forward Hostname/IP and/or Forward Port via the Admin UI, and click Save
- Confirm via direct database query that the new value was saved correctly
- Check the generated config file at
/data/nginx/proxy_host/<id>.confinside the container's/datavolume - Observe that the
set $server "...";line (and/orserver_name) still contains the old, pre-edit value - Attempt to access the proxied domain — observe a 502 Bad Gateway, or a TLS "unrecognized name" error if the
server_nameitself is stale
Separately reproducible:
- On a Proxy Host with Custom Locations, delete all existing locations and save
- Re-add the same location paths (e.g.
/admin) and save - Check
meta.nginx_errvia GET/api/nginx/proxy-hosts/<id>— observenginx: [emerg] duplicate location "/admin"even though the UI shows no error and the host appears "Online"
Expected behavior
Editing a Proxy Host's fields and saving should always regenerate the on-disk nginx config file to match the database, and the on-disk config should never silently diverge from what the database and UI report. If config generation or nginx validation fails, this should be surfaced clearly to the user, not just exposed via an undocumented meta.nginx_err API field while the UI shows "Online."
Screenshots
N/A (text/log-based bug, see logs below)
Operating System
- Ubuntu Server (VM), Docker 28.3.3, Docker Compose v2.39.1, x86_64
- Raspberry Pi 3B running DietPi, Docker 29.6.0, Docker Compose v5.2.0, ARM64 (same bug reproduced independently on this host as well, ruling out architecture-specific cause)
Additional context
- This environment uses NPM in a 2-node setup sharing a single MariaDB database (
yobasystems/alpine-mariadb:latest) for high-availability, with Keepalived managing a floating VIP between the two nodes. The original install long predates the MariaDB migration (was running on SQLite since Jan 2024). - All affected proxy hosts were created prior to the SQLite→MariaDB migration and had a field edited post-migration. We have not yet been able to confirm whether the bug also reproduces on hosts created fresh under MySQL/MariaDB from the start — this may be a relevant factor for reproduction.
- Example of the stale config (host serving Home Assistant): database
forward_hostcorrectly showed192.168.1.15, but the generated config file containedset $server "192.168.1.51";— an entirely different, unrelated IP (the NPM host's own address) — despite no error being shown anywhere in the UI. - Forcing a
PUTto/api/nginx/proxy-hosts/<id>with unchanged data reliably regenerates the config correctly and resolves the issue, suggesting the bug is isolated to whatever code path the UI's "Save" button triggers versus the full API update path, or possibly a caching/timing issue in the config-generation worker.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Admin UI save path and the PUT /api/nginx/proxy-hosts/ endpoint, then compare how each triggers generation of /data/nginx/proxy_host/.conf. Reproduce with an edited Proxy Host and custom locations, checking the file and meta.nginx_err; done means saved values regenerate reliably and validation failures are surfaced clearly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, mariadb, nginx, typescript
- Domain
- backend, devops, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100