[GH-ISSUE #1708] Access Lists: support for dynamic IP-Addresses #1271

Open
opened 2026-02-26 06:36:29 +03:00 by kerem · 33 comments
Owner

Originally created by @kernel-panic-enjoyer on GitHub (Dec 30, 2021).
Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1708

Is your feature request related to a problem? Please describe.

I use the access list feature to restrict access to a subdomain to devices from my home network. Since my ISP does not assign IP addresses statically, I have to log into the webinterface every so often and replace my old IP address with my new one.

Describe the solution you'd like

I have a dynamic dns record that is kept up-to-date with my home IP address. I would like to use this dynamic dns entry for the access list. I imagine that the proxy manager periodically resolves the domain and then replaces the ip address in this access list accordingly.

Describe alternatives you've considered

I dont really see an alternative to my proposal. Will update this issue if a better solution comes to my mind.

Originally created by @kernel-panic-enjoyer on GitHub (Dec 30, 2021). Original GitHub issue: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1708 <!-- Are you in the right place? - If you are looking for support on how to get your upstream server forwarding, please consider asking the community on Reddit. - If you are writing code changes to contribute and need to ask about the internals of the software, Gitter is the best place to ask. - If you think you found a bug with NPM (not Nginx, or your upstream server or MySql) then you are in the *right place.* --> **Is your feature request related to a problem? Please describe.** <!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --> I use the access list feature to restrict access to a subdomain to devices from my home network. Since my ISP does not assign IP addresses statically, I have to log into the webinterface every so often and replace my old IP address with my new one. **Describe the solution you'd like** <!-- A clear and concise description of what you want to happen. --> I have a dynamic dns record that is kept up-to-date with my home IP address. I would like to use this dynamic dns entry for the access list. I imagine that the proxy manager periodically resolves the domain and then replaces the ip address in this access list accordingly. **Describe alternatives you've considered** <!-- A clear and concise description of any alternative solutions or features you've considered. --> I dont really see an alternative to my proposal. Will update this issue if a better solution comes to my mind. <!-- **Additional context** --> <!-- Add any other context or screenshots about the feature request here. -->
Author
Owner

@devantler commented on GitHub (Jan 7, 2022):

I would really like this as well. I think the approach presented by Mike from WPBullet would work really well if containerized.

https://guides.wp-bullet.com/auto-whitelist-multiple-dynamic-dns-addresses-for-nginx-security/

The variables the script relies on could be written to a file or environment variables, and later be retrieved by the script that could run as a cron job.

The Access List could be extended so either an IP address is given or a domain is given. Entering a domain should extend the list of domains the script would whitelist.

<!-- gh-comment-id:1007786065 --> @devantler commented on GitHub (Jan 7, 2022): I would really like this as well. I think the approach presented by Mike from WPBullet would work really well if containerized. https://guides.wp-bullet.com/auto-whitelist-multiple-dynamic-dns-addresses-for-nginx-security/ The variables the script relies on could be written to a file or environment variables, and later be retrieved by the script that could run as a cron job. The Access List could be extended so either an IP address is given or a domain is given. Entering a domain should extend the list of domains the script would whitelist.
Author
Owner

@vtmocanu commented on GitHub (May 5, 2022):

I'm in the same situation, did you find any workarounds for this?

<!-- gh-comment-id:1118277620 --> @vtmocanu commented on GitHub (May 5, 2022): I'm in the same situation, did you find any workarounds for this?
Author
Owner

@pxlfrk commented on GitHub (Jan 1, 2023):

+1

<!-- gh-comment-id:1368507049 --> @pxlfrk commented on GitHub (Jan 1, 2023): +1
Author
Owner

@threehappypenguins commented on GitHub (Jan 19, 2023):

+1

<!-- gh-comment-id:1397460786 --> @threehappypenguins commented on GitHub (Jan 19, 2023): +1
Author
Owner

@threehappypenguins commented on GitHub (Jan 19, 2023):

Is there any way for me to finagle this to work with npm running in docker?

<!-- gh-comment-id:1397462210 --> @threehappypenguins commented on GitHub (Jan 19, 2023): > Is there any way for me to finagle this to work with npm running in docker?
Author
Owner

@threehappypenguins commented on GitHub (Jan 19, 2023):

I did some finagling, and I have it working, but it requires modifying the docker container and adding a script. The downside, of course, is that you have to re-modify the container when you update. But I figure that doing this is better than the unpredictability of having your IP address change and then having to manually change it right when you needed access to your site. I did the following:

# find container ID
sudo docker ps

#enter container shell
sudo docker exec -it <mycontainer> bash

# install dependencies
apt update
apt install nano
apt install dnsutils

# create your script as per Mike from WPBullet and paste into the .sh file
mkdir /scripts
nano /scripts/nginx-dynamic-multiple.sh
#save and exit

# make script executable
chmod +x /scripts/nginx-dynamic-multiple.sh

# test script
bash /scripts/nginx-dynamic-multiple.sh
cat /etc/nginx/conf.d/dynamicips

The cat command showed my IP so the script worked for that purpose. In Nginx Proxy Manager, I navigated to Hosts > Edit > Advanced and in Custom Nginx Configuration I pasted:

location = / {
	include /etc/nginx/conf.d/dynamicips;
	deny all;
}

This adds to a conf file in (the docker container) /data/nginx/proxy_host/4.conf and for me, specifically /data/nginx/proxy_host/4.conf.

The problem is, when I go to my site (from my added IP address), I get 403 Forbidden. Checked the error log (again, within the docker container): tail -100 /data/logs/proxy-host-4_error.log (log path was defined in /data/nginx/proxy_host/4.conf:

access forbidden by rule, client: 192.168.1.1, server: my.server.com, request: "GET / HTTP/2.0", host: "my.server.com"

I also had the same issue with the address 10.6.0.2 if I went outside my LAN (data on my phone) and connected to my home via OpenVPN. This is because I am trying to connect to it from within the same network my machine (with NPM and my site) is on.

So I modified my Custom Nginx Configuration in NPM to:

location = / {
	include /etc/nginx/conf.d/dynamicips;
	allow 192.168.1.1;
	allow 10.6.0.2;
	deny all;
}

I don't have any way to test this currently, but I think all of this will work properly if I connect to one of the LANs for one of the public IPs in the list. All I have left to do is create a cron job to keep the IP addresses updated.

Edit: I wanted to add that I changed the script a little (copied from someone who commented on the page with the script) so that if a host is unreachable, it doesn't crash the nginx. This is the section that I changed:

#create an array of the dynamic IPs
if [ ! -f /etc/nginx/conf.d/dynamicips ]; then
        for DNS in "${DDNS[@]}"
        do
                IP="$(dig x +short ${DDNS[$i]})"
                if [ "$IP" != "" ]; then
                        echo "allow $IP;" >> /etc/nginx/conf.d/dynamicips
                fi
        done
fi
<!-- gh-comment-id:1397633769 --> @threehappypenguins commented on GitHub (Jan 19, 2023): I did some finagling, and I have it working, but it requires modifying the docker container and adding a [script](https://guides.wp-bullet.com/auto-whitelist-multiple-dynamic-dns-addresses-for-nginx-security/). The downside, of course, is that you have to re-modify the container when you update. But I figure that doing this is better than the unpredictability of having your IP address change and then having to manually change it right when you needed access to your site. I did the following: ``` # find container ID sudo docker ps #enter container shell sudo docker exec -it <mycontainer> bash # install dependencies apt update apt install nano apt install dnsutils # create your script as per Mike from WPBullet and paste into the .sh file mkdir /scripts nano /scripts/nginx-dynamic-multiple.sh #save and exit # make script executable chmod +x /scripts/nginx-dynamic-multiple.sh # test script bash /scripts/nginx-dynamic-multiple.sh cat /etc/nginx/conf.d/dynamicips ``` The cat command showed my IP so the script worked for that purpose. In Nginx Proxy Manager, I navigated to _Hosts > Edit > Advanced_ and in _Custom Nginx Configuration_ I pasted: ``` location = / { include /etc/nginx/conf.d/dynamicips; deny all; } ``` This adds to a conf file in (the docker container) `/data/nginx/proxy_host/4.conf` and for me, specifically `/data/nginx/proxy_host/4.conf`. The problem is, when I go to my site (from my added IP address), I get _403 Forbidden_. Checked the error log (again, within the docker container): tail -100 /data/logs/proxy-host-4_error.log (log path was defined in `/data/nginx/proxy_host/4.conf`: `access forbidden by rule, client: 192.168.1.1, server: my.server.com, request: "GET / HTTP/2.0", host: "my.server.com"` I also had the same issue with the address 10.6.0.2 if I went outside my LAN (data on my phone) and connected to my home via OpenVPN. This is because I am trying to connect to it from within the same network my machine (with NPM and my site) is on. So I modified my Custom Nginx Configuration in NPM to: ``` location = / { include /etc/nginx/conf.d/dynamicips; allow 192.168.1.1; allow 10.6.0.2; deny all; } ``` I don't have any way to test this currently, but I _think_ all of this will work properly if I connect to one of the LANs for one of the public IPs in the list. All I have left to do is create a cron job to keep the IP addresses updated. Edit: I wanted to add that I changed the script a little (copied from someone who commented on the page with the script) so that if a host is unreachable, it doesn't crash the nginx. This is the section that I changed: ``` #create an array of the dynamic IPs if [ ! -f /etc/nginx/conf.d/dynamicips ]; then for DNS in "${DDNS[@]}" do IP="$(dig x +short ${DDNS[$i]})" if [ "$IP" != "" ]; then echo "allow $IP;" >> /etc/nginx/conf.d/dynamicips fi done fi ```
Author
Owner

@pxlfrk commented on GitHub (Jan 19, 2023):

Nice work! Thank you for that! What do others think, is there any chance to see this in the final build as optional feature? You may start a Pull Request, so that others can review your changes directly.

<!-- gh-comment-id:1397713524 --> @pxlfrk commented on GitHub (Jan 19, 2023): Nice work! Thank you for that! What do others think, is there any chance to see this in the final build as optional feature? You may start a Pull Request, so that others can review your changes directly.
Author
Owner

@threehappypenguins commented on GitHub (Jan 19, 2023):

You may start a Pull Request, so that others can review your changes directly.

I hope this isn't a dumb question, but wouldn't I need a more complete solution to start a pull request? Like, we would need a GUI solution added so that users can perhaps add their DDNS address in Access Lists > Add Access List > Access and there would be the addition of typing in a DDNS and not just IP address or CIDR. I'm new to the whole PR thing. lol

<!-- gh-comment-id:1397722826 --> @threehappypenguins commented on GitHub (Jan 19, 2023): > You may start a Pull Request, so that others can review your changes directly. I hope this isn't a dumb question, but wouldn't I need a more complete solution to start a pull request? Like, we would need a GUI solution added so that users can perhaps add their DDNS address in Access Lists > Add Access List > Access and there would be the addition of typing in a DDNS and not just IP address or CIDR. I'm new to the whole PR thing. lol
Author
Owner

@mczeus commented on GitHub (Jan 20, 2023):

@threehappypenguins
great workaround, it works for what I have tested so far.
But a crontab is still needed!?!

crontab -e
*/10 * * * * /bin/bash /scripts/nginx-dynamic-multiple.sh
/etc/init.d/cron start

But after restarting the container, it's gone again. How can I make this permanent?

Should be included in the release.
great big thx

<!-- gh-comment-id:1398448270 --> @mczeus commented on GitHub (Jan 20, 2023): @threehappypenguins great workaround, it works for what I have tested so far. But a crontab is still needed!?! crontab -e */10 * * * * /bin/bash /scripts/nginx-dynamic-multiple.sh /etc/init.d/cron start But after restarting the container, it's gone again. How can I make this permanent? Should be included in the release. great big thx
Author
Owner

@threehappypenguins commented on GitHub (Jan 20, 2023):

I don't have enough coding experience so I'm hoping someone can maybe poke around a little more and find a way to implement this. Here are my observations so far:

When you create an Access List, /internal/access-list.js creates an empty file called 1 in the folder /data/access. Any other access lists created will receive the name 2, then 3, etc (even if you delete the old list first). It writes the IP address (that you enter in the Access List for allow) to the mysql database (as evidenced by the binary file, /data/mysql/aria_log.00000001).

Then, if you apply your access list to a host, it writes the IP address(es) to a conf file in /data/nginx/proxy_host (in my case, /data/nginx/proxy_host/4.conf), the same file Custom Nginx Configuration writes to, but a different location = / {} section. It's right under the Custom Nginx Configuration location section. It will go from (my IP redacted):

  location / {

    







    
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_http_version 1.1;
    

    # Proxy!
    include conf.d/include/proxy.conf;
  }

to:

  location / {

    
    

    # Access Rules
    allow <mypublicipaddress>;
    deny all;

    # Access checks must...
    
    satisfy all;
    

    







    
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;
    proxy_http_version 1.1;
    

    # Proxy!
    include conf.d/include/proxy.conf;
  }

I'm thinking that maybe somehow add the ability to access a DDNS in the access list, and it will trigger the script (with placeholders/variables in place of the actual IP addresses), and those IP addresses could then be saved to the mysql database, ready to be added to the /data/nginx/proxy_host .conf file like the other IP addresses. The script could be set to run every so often, but then there would need to be a way to periodically check to see if the IP addresses change in order for them to be updated in the database, then applied to the .conf file.

OR, maybe we could have everything function as normal where the script writes to a file, and if the access list is applied to the host, it writes that line include /etc/nginx/conf.d/dynamicips; to the .conf file.

Just thinking out loud here.

<!-- gh-comment-id:1398568816 --> @threehappypenguins commented on GitHub (Jan 20, 2023): I don't have enough coding experience so I'm hoping someone can maybe poke around a little more and find a way to implement this. Here are my observations so far: When you create an Access List, `/internal/access-list.js` creates an empty file called `1` in the folder `/data/access`. Any other access lists created will receive the name `2`, then `3`, etc (even if you delete the old list first). It writes the IP address (that you enter in the Access List for allow) to the mysql database (as evidenced by the binary file, `/data/mysql/aria_log.00000001`). Then, if you apply your access list to a host, it writes the IP address(es) to a conf file in `/data/nginx/proxy_host` (in my case, /data/nginx/proxy_host/4.conf), the same file Custom Nginx Configuration writes to, but a different `location = / {}` section. It's right under the Custom Nginx Configuration location section. It will go from (my IP redacted): ``` location / { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_http_version 1.1; # Proxy! include conf.d/include/proxy.conf; } ``` to: ``` location / { # Access Rules allow <mypublicipaddress>; deny all; # Access checks must... satisfy all; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_http_version 1.1; # Proxy! include conf.d/include/proxy.conf; } ``` I'm thinking that maybe somehow add the ability to access a DDNS in the access list, and it will trigger the script (with placeholders/variables in place of the actual IP addresses), and those IP addresses could then be saved to the mysql database, ready to be added to the `/data/nginx/proxy_host` .conf file like the other IP addresses. The script could be set to run every so often, but then there would need to be a way to periodically check to see if the IP addresses change in order for them to be updated in the database, then applied to the .conf file. OR, maybe we could have everything function as normal where the script writes to a file, and if the access list is applied to the host, it writes that line `include /etc/nginx/conf.d/dynamicips;` to the .conf file. Just thinking out loud here.
Author
Owner

@threehappypenguins commented on GitHub (Jan 22, 2023):

I just wanted to give an update not that add a CIDR like 192.168.1.1/24. When I would try to connect from one of the public IP addresses in my dynamicips list, it was forbidden, despite being in the list. nginx -t showed the error:

nginx: [warn] low address bits of 192.168.1.1/24 are meaningless in /data/nginx/proxy_host/4.conf:58

So I removed the /24 from the end, and I could connect just fine.

<!-- gh-comment-id:1399559783 --> @threehappypenguins commented on GitHub (Jan 22, 2023): I just wanted to give an update not that add a CIDR like 192.168.1.1/24. When I would try to connect from one of the public IP addresses in my dynamicips list, it was forbidden, despite being in the list. `nginx -t` showed the error: `nginx: [warn] low address bits of 192.168.1.1/24 are meaningless in /data/nginx/proxy_host/4.conf:58` So I removed the /24 from the end, and I could connect just fine.
Author
Owner

@mczeus commented on GitHub (Jan 26, 2023):

I noticed when the IP changes. You also have to save again in Custom Nginx Configuration so that it applies the change of the new IP

<!-- gh-comment-id:1404895659 --> @mczeus commented on GitHub (Jan 26, 2023): I noticed when the IP changes. You also have to save again in Custom Nginx Configuration so that it applies the change of the new IP
Author
Owner

@threehappypenguins commented on GitHub (Feb 2, 2023):

Something else I noticed, if you do an update of your container, then you get a connection refused error in the browser when trying to open the npm management page. Looking at the npm logs from portainer, I noticed:

❯ Enabling IPV6 in hosts: /data/nginx
  ❯ /data/nginx/proxy_host/18.conf
  ❯ /data/nginx/proxy_host/4.conf
  ❯ /data/nginx/proxy_host/16.conf
  ❯ /data/nginx/default_host/site.conf
nginx: [emerg] open() "/etc/nginx/conf.d/dynamicips" failed (2: No such file or directory) in /data/nginx/proxy_host/4.conf:58

So what happens is the dynamicips file disappears upon update, and because the Custom Nginx Configuration is still there (calling on to include a file that doesn't exist), it causes the npm site not to load. So I had to go into the docker container shell, and I commented out the location / section that shows up when you add to Custom Nginx Configuration. After I saved, I was able to log into the npm site. Then I deleted the Custom Nginx Configuration, and had to start over with all the steps I outlined above (creation of the script, etc).

<!-- gh-comment-id:1413040134 --> @threehappypenguins commented on GitHub (Feb 2, 2023): Something else I noticed, if you do an update of your container, then you get a connection refused error in the browser when trying to open the npm management page. Looking at the npm logs from portainer, I noticed: ``` ❯ Enabling IPV6 in hosts: /data/nginx ❯ /data/nginx/proxy_host/18.conf ❯ /data/nginx/proxy_host/4.conf ❯ /data/nginx/proxy_host/16.conf ❯ /data/nginx/default_host/site.conf nginx: [emerg] open() "/etc/nginx/conf.d/dynamicips" failed (2: No such file or directory) in /data/nginx/proxy_host/4.conf:58 ``` So what happens is the dynamicips file disappears upon update, and because the Custom Nginx Configuration is still there (calling on to include a file that doesn't exist), it causes the npm site not to load. So I had to go into the docker container shell, and I commented out the location / section that shows up when you add to Custom Nginx Configuration. After I saved, I was able to log into the npm site. Then I deleted the Custom Nginx Configuration, and had to start over with all the steps I outlined above (creation of the script, etc).
Author
Owner

@firefart commented on GitHub (Feb 20, 2023):

I developed a little auth helper that handles this usecase with http_auth_request_module: https://github.com/firefart/nginxreverseauth

It's a go binary you need to run next to nginx that will handle reverse dns lookups. Maybe you can also make use of this in NginxProxyManager

<!-- gh-comment-id:1437515902 --> @firefart commented on GitHub (Feb 20, 2023): I developed a little auth helper that handles this usecase with `http_auth_request_module`: https://github.com/firefart/nginxreverseauth It's a go binary you need to run next to nginx that will handle reverse dns lookups. Maybe you can also make use of this in NginxProxyManager
Author
Owner

@threehappypenguins commented on GitHub (Feb 20, 2023):

I developed a little auth helper that handles this usecase with http_auth_request_module: https://github.com/firefart/nginxreverseauth

It's a go binary you need to run next to nginx that will handle reverse dns lookups. Maybe you can also make use of this in NginxProxyManager

Can you explain how we implement this? I don't really understand what to do with it... like, do we install it within the docker container or something?

<!-- gh-comment-id:1437605215 --> @threehappypenguins commented on GitHub (Feb 20, 2023): > I developed a little auth helper that handles this usecase with `http_auth_request_module`: https://github.com/firefart/nginxreverseauth > > It's a go binary you need to run next to nginx that will handle reverse dns lookups. Maybe you can also make use of this in NginxProxyManager Can you explain how we implement this? I don't really understand what to do with it... like, do we install it within the docker container or something?
Author
Owner

@firefart commented on GitHub (Feb 20, 2023):

Can you explain how we implement this? I don't really understand what to do with it... like, do we install it within the docker container or something?

you need to run it in a seperate (not exposed to the internet) container but it all boils down if you can configure the http_auth_request_module directive in nginx proxy manager. I only use this helper in a plain nginx setup but I thought it might be also helpful here.

<!-- gh-comment-id:1437623368 --> @firefart commented on GitHub (Feb 20, 2023): > Can you explain how we implement this? I don't really understand what to do with it... like, do we install it within the docker container or something? you need to run it in a seperate (not exposed to the internet) container but it all boils down if you can configure the `http_auth_request_module` directive in nginx proxy manager. I only use this helper in a plain nginx setup but I thought it might be also helpful here.
Author
Owner

@rbullers commented on GitHub (May 7, 2023):

I've created a fork of NPM that builds the hack from @threehappypenguins here into a docker image that lets you pass your DDNS hosts as an environment variable. The script has been added to a cron schedule also, which checks every 60s for a change to the IP and outputs if there was an update or not to var/log/cron

More info on the repo here

<!-- gh-comment-id:1537533615 --> @rbullers commented on GitHub (May 7, 2023): I've created a fork of NPM that builds the hack from @threehappypenguins [here](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1708#issuecomment-1397633769) into a docker image that lets you pass your DDNS hosts as an environment variable. The script has been added to a cron schedule also, which checks every 60s for a change to the IP and outputs if there was an update or not to var/log/cron More info on the repo [here](https://github.com/rbullers/nginx-proxy-manager)
Author
Owner

@threehappypenguins commented on GitHub (May 7, 2023):

Awesome! I'm gonna take a look! Thanks!

<!-- gh-comment-id:1537534149 --> @threehappypenguins commented on GitHub (May 7, 2023): > Awesome! I'm gonna take a look! Thanks!
Author
Owner

@mczeus commented on GitHub (May 11, 2023):

@rbullers
Thank you very much for that.
I have tested this. It can be a small error in the description?

"127.0.0.1;"

should be

"allow 127.0.0.1;"

right?
I'll keep testing
thanks

<!-- gh-comment-id:1544483423 --> @mczeus commented on GitHub (May 11, 2023): @rbullers Thank you very much for that. I have tested this. It can be a small error in the description? "127.0.0.1;" should be "allow 127.0.0.1;" right? I'll keep testing thanks
Author
Owner

@rbullers commented on GitHub (May 11, 2023):

@mczeus Yes you're right - I've amended the error, thanks for pointing it out.

<!-- gh-comment-id:1544499718 --> @rbullers commented on GitHub (May 11, 2023): @mczeus Yes you're right - I've amended the error, thanks for pointing it out.
Author
Owner

@efnats commented on GitHub (Jul 29, 2023):

I've created a fork of NPM that builds the hack from @threehappypenguins here into a docker image that lets you pass your DDNS hosts as an environment variable. The script has been added to a cron schedule also, which checks every 60s for a change to the IP and outputs if there was an update or not to var/log/cron

More info on the repo here

rbullers this is great!! Would you mind doing a pull request to https://github.com/NginxProxyManager/nginx-proxy-manager ?

<!-- gh-comment-id:1656661299 --> @efnats commented on GitHub (Jul 29, 2023): > I've created a fork of NPM that builds the hack from @threehappypenguins [here](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1708#issuecomment-1397633769) into a docker image that lets you pass your DDNS hosts as an environment variable. The script has been added to a cron schedule also, which checks every 60s for a change to the IP and outputs if there was an update or not to var/log/cron > > More info on the repo [here](https://github.com/rbullers/nginx-proxy-manager) rbullers this is great!! Would you mind doing a pull request to https://github.com/NginxProxyManager/nginx-proxy-manager ?
Author
Owner

@vari commented on GitHub (Dec 3, 2023):

I created a PR which lets you use the NPM web UI to directly specify dynamic host names in the access list address field (using ddns:subdomain.ddnsdomain.com to specify use the IP of subdomain.ddnsdomain.com).

It automatically handles recreating host config & nginx reloading whenever the IP changes (by default it polls every 1 hour, but this can be configured via the DDNS_UPDATE_INTERVAL env variable - set it to the desired interval in seconds).

Since its integrated to nginx proxy manager backend server, it is much easier to use than specifying a list of domains via env var and having to go in to Custom Nginx Configuration of each proxy host and entering the custom include code. Additionally, if you ever change the domain in the access list, it will automatically resolve the new domain's IP and update each host that uses the access list. (Plus no need to edit the compose file to add/remove/modify domains :) ).

Unfortunately the CI build job is down, so there is no easy to use image with the changes to try it out. If you want to try it out, you can follow the manual steps in my PR comment.
The easiest way to test/use the changes is to use jc21/nginx-proxy-manager:github-pr-3364 as the image for your nginx proxy manager container.

E.g. in your docker compose file, replace:
image: 'jc21/nginx-proxy-manager:latest'
with
image: 'jc21/nginx-proxy-manager:github-pr-3364'

<!-- gh-comment-id:1837320651 --> @vari commented on GitHub (Dec 3, 2023): I created a PR which lets you use the NPM web UI to directly specify dynamic host names in the access list address field (using `ddns:subdomain.ddnsdomain.com` to specify use the IP of `subdomain.ddnsdomain.com`). It automatically handles recreating host config & nginx reloading whenever the IP changes (by default it polls every 1 hour, but this can be configured via the `DDNS_UPDATE_INTERVAL` env variable - set it to the desired interval in seconds). Since its integrated to nginx proxy manager backend server, it is much easier to use than specifying a list of domains via env var and having to go in to `Custom Nginx Configuration` of each proxy host and entering the custom include code. Additionally, if you ever change the domain in the access list, it will automatically resolve the new domain's IP and update each host that uses the access list. (Plus no need to edit the compose file to add/remove/modify domains :) ). ~~Unfortunately the CI build job is down, so there is no easy to use image with the changes to try it out. If you want to try it out, you can follow the manual steps in my [PR comment](https://github.com/NginxProxyManager/nginx-proxy-manager/pull/3364#issuecomment-1837318277).~~ The easiest way to test/use the changes is to use jc21/nginx-proxy-manager:github-pr-3364 as the image for your nginx proxy manager container. E.g. in your docker compose file, replace: `image: 'jc21/nginx-proxy-manager:latest'` with `image: 'jc21/nginx-proxy-manager:github-pr-3364'`
Author
Owner

@threehappypenguins commented on GitHub (Feb 6, 2024):

I created a PR which lets you use the NPM web UI to directly specify dynamic host names in the access list address field (using ddns:subdomain.ddnsdomain.com to specify use the IP of subdomain.ddnsdomain.com).

It automatically handles recreating host config & nginx reloading whenever the IP changes (by default it polls every 1 hour, but this can be configured via the DDNS_UPDATE_INTERVAL env variable - set it to the desired interval in seconds).

Since its integrated to nginx proxy manager backend server, it is much easier to use than specifying a list of domains via env var and having to go in to Custom Nginx Configuration of each proxy host and entering the custom include code. Additionally, if you ever change the domain in the access list, it will automatically resolve the new domain's IP and update each host that uses the access list. (Plus no need to edit the compose file to add/remove/modify domains :) ).

Unfortunately the CI build job is down, so there is no easy to use image with the changes to try it out. If you want to try it out, you can follow the manual steps in my PR comment.

Thank you! I'm really late in trying this out, but I just did, and it works great!

<!-- gh-comment-id:1930235488 --> @threehappypenguins commented on GitHub (Feb 6, 2024): > I created a PR which lets you use the NPM web UI to directly specify dynamic host names in the access list address field (using `ddns:subdomain.ddnsdomain.com` to specify use the IP of `subdomain.ddnsdomain.com`). > > It automatically handles recreating host config & nginx reloading whenever the IP changes (by default it polls every 1 hour, but this can be configured via the `DDNS_UPDATE_INTERVAL` env variable - set it to the desired interval in seconds). > > Since its integrated to nginx proxy manager backend server, it is much easier to use than specifying a list of domains via env var and having to go in to `Custom Nginx Configuration` of each proxy host and entering the custom include code. Additionally, if you ever change the domain in the access list, it will automatically resolve the new domain's IP and update each host that uses the access list. (Plus no need to edit the compose file to add/remove/modify domains :) ). > > Unfortunately the CI build job is down, so there is no easy to use image with the changes to try it out. If you want to try it out, you can follow the manual steps in my [PR comment](https://github.com/NginxProxyManager/nginx-proxy-manager/pull/3364#issuecomment-1837318277). Thank you! I'm really late in trying this out, but I just did, and it works great!
Author
Owner

@vari commented on GitHub (Feb 6, 2024):

Thank you! I'm really late in trying this out, but I just did, and it works great!

Glad you found it useful!

<!-- gh-comment-id:1930293366 --> @vari commented on GitHub (Feb 6, 2024): > Thank you! I'm really late in trying this out, but I just did, and it works great! Glad you found it useful!
Author
Owner

@virtualdj commented on GitHub (Feb 6, 2024):

@vari Hoping it will be merged on main as well!

<!-- gh-comment-id:1930353379 --> @virtualdj commented on GitHub (Feb 6, 2024): @vari Hoping it will be merged on main as well!
Author
Owner

@jimmyjules153 commented on GitHub (Mar 3, 2024):

Hey all <3

I had a hard crack at doing this with a cron+script and got something fairly simple in place. I'm running docker with Nginx Proxy Manager and wanted to update my access control lists to my dynamic DNS IP address, since I don't have a static IP. This is so I can lock down my proxy hosts to only be accessible from my WAN address with the inbuilt Nginx proxy manager access lists. I didn't want to use a fork because i wanted to make sure i was always running the latest version of NPM for security reasons.

My nginx host configs are located at '/apps/nginxproxy/data/nginx/proxy_host/'. My docker volumes for NPM are mounted on the host at this folder location for easy access. Your location for this will more than likely be different, but if you can find your nginxproxymanager folder, the configs for your hosts should be in the 'data/nginx/proxy_host/' subfolders.

The below script does the following:

WAN IP Retrieval:
It fetches the current WAN IP using curl and stores it in the WAN_IP variable.

Previous IP Check:
It checks if a file named wan_ip.txt exists in the /home/user/scripts/nginx/ directory.
If the file exists, it reads the stored IP into the OLD_WAN_IP variable.
If the file doesn't exist, it creates the file and stores the current WAN IP in it.

WAN IP Change Detection:
It compares the newly obtained WAN_IP with the OLD_WAN_IP.
If they are the same, it logs a message and exits without further action.

WAN IP Update:
If the IP has changed, it logs a message and updates the wan_ip.txt file with the new IP.
It then uses sed to modify all configuration files in the /apps/nginxproxy/data/nginx/proxy_host/ directory.

Configuration File Modification:
The sed command searches for lines starting with "allow" (^\s*allow).
If found, it replaces the entire line with allow $WAN_IP/32; (with the extra leading spaces for keeping formatting nice in the file).

Reload nginx proxy manager configuration
Reloads NPM config, without restarting NPM so there's no downtime

`#!/bin/bash
date +"%Y-%m-%d_%H:%M:%S" >> /home/user/scripts/nginx/log.txt
#Get the current WAN IP address
WAN_IP=$(curl -s https://icanhazip.com)

#check if the WAN IP file exists, create it with the WAN IP if not.
if test -f /home/user/scripts/nginx/wan_ip.txt; then
OLD_WAN_IP=cat /home/user/scripts/nginx/wan_ip.txt
else
echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt
fi

if [ "$WAN_IP" == "$OLD_WAN_IP" ]; then
echo "WAN IP has not changed since last run." >> /home/user/scripts/nginx/log.txt
else
echo "WAN IP has changed! Updating nginx configs..." >> /home/user/scripts/nginx/log.txt
echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt
sed -i "/^\sallow/c\ allow $WAN_IP/32;" /apps/nginxproxy/data/nginx/proxy_host/.conf
fi

docker exec nginxproxy-app-1 /bin/bash -c "/usr/sbin/nginx -s reload"`

This solved my issues and now I won't get locked out of my Nginx proxy manager hosted sites from my ACL's every time my WAN IP changes..!! Also this won't get wiped out of NPM happens to release an update. I hope this helps someone else 💜

I'll keep an eye out for replies so if you have questions shoot them through and i'll answer if I can help 😊

<!-- gh-comment-id:1975058359 --> @jimmyjules153 commented on GitHub (Mar 3, 2024): Hey all <3 I had a hard crack at doing this with a cron+script and got something fairly simple in place. I'm running docker with Nginx Proxy Manager and wanted to update my access control lists to my dynamic DNS IP address, since I don't have a static IP. This is so I can lock down my proxy hosts to only be accessible from my WAN address with the inbuilt Nginx proxy manager access lists. I didn't want to use a fork because i wanted to make sure i was always running the latest version of NPM for security reasons. My nginx host configs are located at '/apps/nginxproxy/data/nginx/proxy_host/'. My docker volumes for NPM are mounted on the host at this folder location for easy access. Your location for this will more than likely be different, but if you can find your nginxproxymanager folder, the configs for your hosts should be in the 'data/nginx/proxy_host/' subfolders. The below script does the following: **WAN IP Retrieval:** It fetches the current WAN IP using curl and stores it in the WAN_IP variable. **Previous IP Check:** It checks if a file named wan_ip.txt exists in the /home/user/scripts/nginx/ directory. If the file exists, it reads the stored IP into the OLD_WAN_IP variable. If the file doesn't exist, it creates the file and stores the current WAN IP in it. **WAN IP Change Detection:** It compares the newly obtained WAN_IP with the OLD_WAN_IP. If they are the same, it logs a message and exits without further action. **WAN IP Update:** If the IP has changed, it logs a message and updates the wan_ip.txt file with the new IP. It then uses sed to modify all configuration files in the /apps/nginxproxy/data/nginx/proxy_host/ directory. **Configuration File Modification:** The sed command searches for lines starting with "allow" (^\s*allow). If found, it replaces the entire line with allow $WAN_IP/32; (with the extra leading spaces for keeping formatting nice in the file). **Reload nginx proxy manager configuration** Reloads NPM config, without restarting NPM so there's no downtime `#!/bin/bash date +"%Y-%m-%d_%H:%M:%S" >> /home/user/scripts/nginx/log.txt #Get the current WAN IP address WAN_IP=$(curl -s https://icanhazip.com) #check if the WAN IP file exists, create it with the WAN IP if not. if test -f /home/user/scripts/nginx/wan_ip.txt; then OLD_WAN_IP=`cat /home/user/scripts/nginx/wan_ip.txt` else echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt fi if [ "$WAN_IP" == "$OLD_WAN_IP" ]; then echo "WAN IP has not changed since last run." >> /home/user/scripts/nginx/log.txt else echo "WAN IP has changed! Updating nginx configs..." >> /home/user/scripts/nginx/log.txt echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt sed -i "/^\s*allow/c\ allow $WAN_IP/32;" /apps/nginxproxy/data/nginx/proxy_host/*.conf fi docker exec nginxproxy-app-1 /bin/bash -c "/usr/sbin/nginx -s reload"` This solved my issues and now I won't get locked out of my Nginx proxy manager hosted sites from my ACL's every time my WAN IP changes..!! Also this won't get wiped out of NPM happens to release an update. I hope this helps someone else 💜 I'll keep an eye out for replies so if you have questions shoot them through and i'll answer if I can help 😊
Author
Owner

@TwoPlayer commented on GitHub (Apr 10, 2024):

Hey all <3

I had a hard crack at doing this with a cron+script and got something fairly simple in place. I'm running docker with Nginx Proxy Manager and wanted to update my access control lists to my dynamic DNS IP address, since I don't have a static IP. This is so I can lock down my proxy hosts to only be accessible from my WAN address with the inbuilt Nginx proxy manager access lists. I didn't want to use a fork because i wanted to make sure i was always running the latest version of NPM for security reasons.

My nginx host configs are located at '/apps/nginxproxy/data/nginx/proxy_host/'. My docker volumes for NPM are mounted on the host at this folder location for easy access. Your location for this will more than likely be different, but if you can find your nginxproxymanager folder, the configs for your hosts should be in the 'data/nginx/proxy_host/' subfolders.

The below script does the following:

WAN IP Retrieval: It fetches the current WAN IP using curl and stores it in the WAN_IP variable.

Previous IP Check: It checks if a file named wan_ip.txt exists in the /home/user/scripts/nginx/ directory. If the file exists, it reads the stored IP into the OLD_WAN_IP variable. If the file doesn't exist, it creates the file and stores the current WAN IP in it.

WAN IP Change Detection: It compares the newly obtained WAN_IP with the OLD_WAN_IP. If they are the same, it logs a message and exits without further action.

WAN IP Update: If the IP has changed, it logs a message and updates the wan_ip.txt file with the new IP. It then uses sed to modify all configuration files in the /apps/nginxproxy/data/nginx/proxy_host/ directory.

Configuration File Modification: The sed command searches for lines starting with "allow" (^\s*allow). If found, it replaces the entire line with allow $WAN_IP/32; (with the extra leading spaces for keeping formatting nice in the file).

Reload nginx proxy manager configuration Reloads NPM config, without restarting NPM so there's no downtime

`#!/bin/bash date +"%Y-%m-%d_%H:%M:%S" >> /home/user/scripts/nginx/log.txt #Get the current WAN IP address WAN_IP=$(curl -s https://icanhazip.com)

#check if the WAN IP file exists, create it with the WAN IP if not. if test -f /home/user/scripts/nginx/wan_ip.txt; then OLD_WAN_IP=cat /home/user/scripts/nginx/wan_ip.txt else echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt fi

if [ "$WAN_IP" == "$OLD_WAN_IP" ]; then echo "WAN IP has not changed since last run." >> /home/user/scripts/nginx/log.txt else echo "WAN IP has changed! Updating nginx configs..." >> /home/user/scripts/nginx/log.txt echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt sed -i "/^\s_allow/c\ allow $WAN_IP/32;" /apps/nginxproxy/data/nginx/proxy_host/_.conf fi

docker exec nginxproxy-app-1 /bin/bash -c "/usr/sbin/nginx -s reload"`

This solved my issues and now I won't get locked out of my Nginx proxy manager hosted sites from my ACL's every time my WAN IP changes..!! Also this won't get wiped out of NPM happens to release an update. I hope this helps someone else 💜

I'll keep an eye out for replies so if you have questions shoot them through and i'll answer if I can help 😊

Hey, I try to implement your script, but it won't change the line in the config. Could it be, that the format of the sed command was messed up, because of markdown? Could you maybe provide the script in a code bracket so with three backticks (```) instead of one? 😊

<!-- gh-comment-id:2046967686 --> @TwoPlayer commented on GitHub (Apr 10, 2024): > Hey all <3 > > I had a hard crack at doing this with a cron+script and got something fairly simple in place. I'm running docker with Nginx Proxy Manager and wanted to update my access control lists to my dynamic DNS IP address, since I don't have a static IP. This is so I can lock down my proxy hosts to only be accessible from my WAN address with the inbuilt Nginx proxy manager access lists. I didn't want to use a fork because i wanted to make sure i was always running the latest version of NPM for security reasons. > > My nginx host configs are located at '/apps/nginxproxy/data/nginx/proxy_host/'. My docker volumes for NPM are mounted on the host at this folder location for easy access. Your location for this will more than likely be different, but if you can find your nginxproxymanager folder, the configs for your hosts should be in the 'data/nginx/proxy_host/' subfolders. > > The below script does the following: > > **WAN IP Retrieval:** It fetches the current WAN IP using curl and stores it in the WAN_IP variable. > > **Previous IP Check:** It checks if a file named wan_ip.txt exists in the /home/user/scripts/nginx/ directory. If the file exists, it reads the stored IP into the OLD_WAN_IP variable. If the file doesn't exist, it creates the file and stores the current WAN IP in it. > > **WAN IP Change Detection:** It compares the newly obtained WAN_IP with the OLD_WAN_IP. If they are the same, it logs a message and exits without further action. > > **WAN IP Update:** If the IP has changed, it logs a message and updates the wan_ip.txt file with the new IP. It then uses sed to modify all configuration files in the /apps/nginxproxy/data/nginx/proxy_host/ directory. > > **Configuration File Modification:** The sed command searches for lines starting with "allow" (^\s*allow). If found, it replaces the entire line with allow $WAN_IP/32; (with the extra leading spaces for keeping formatting nice in the file). > > **Reload nginx proxy manager configuration** Reloads NPM config, without restarting NPM so there's no downtime > > `#!/bin/bash date +"%Y-%m-%d_%H:%M:%S" >> /home/user/scripts/nginx/log.txt #Get the current WAN IP address WAN_IP=$(curl -s https://icanhazip.com) > > #check if the WAN IP file exists, create it with the WAN IP if not. if test -f /home/user/scripts/nginx/wan_ip.txt; then OLD_WAN_IP=`cat /home/user/scripts/nginx/wan_ip.txt` else echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt fi > > if [ "$WAN_IP" == "$OLD_WAN_IP" ]; then echo "WAN IP has not changed since last run." >> /home/user/scripts/nginx/log.txt else echo "WAN IP has changed! Updating nginx configs..." >> /home/user/scripts/nginx/log.txt echo $WAN_IP > /home/user/scripts/nginx/wan_ip.txt sed -i "/^\s_allow/c\ allow $WAN_IP/32;" /apps/nginxproxy/data/nginx/proxy_host/_.conf fi > > docker exec nginxproxy-app-1 /bin/bash -c "/usr/sbin/nginx -s reload"` > > This solved my issues and now I won't get locked out of my Nginx proxy manager hosted sites from my ACL's every time my WAN IP changes..!! Also this won't get wiped out of NPM happens to release an update. I hope this helps someone else 💜 > > I'll keep an eye out for replies so if you have questions shoot them through and i'll answer if I can help 😊 Hey, I try to implement your script, but it won't change the line in the config. Could it be, that the format of the sed command was messed up, because of markdown? Could you maybe provide the script in a code bracket so with three backticks (```) instead of one? 😊
Author
Owner

@spacecake commented on GitHub (Oct 6, 2024):

I give it a shot to scratch my itch with NPM on this topic which I was having, it might help you with this issue.
You might check the script I made for this: docker_npm_wan_update.sh.

<!-- gh-comment-id:2395482174 --> @spacecake commented on GitHub (Oct 6, 2024): I give it a shot to scratch my itch with NPM on this topic which I was having, it might help you with this issue. You might check the script I made for this: [docker_npm_wan_update.sh](https://github.com/spacecake/docker_scripts/tree/main#docker_npm_wan_updatesh).
Author
Owner

@github-actions[bot] commented on GitHub (Apr 13, 2025):

Issue is now considered stale. If you want to keep it open, please comment 👍

<!-- gh-comment-id:2799553513 --> @github-actions[bot] commented on GitHub (Apr 13, 2025): Issue is now considered stale. If you want to keep it open, please comment :+1:
Author
Owner

@virtualdj commented on GitHub (Apr 13, 2025):

I'm still interested in this feature.

<!-- gh-comment-id:2799883635 --> @virtualdj commented on GitHub (Apr 13, 2025): I'm still interested in this feature.
Author
Owner

@edbanshee commented on GitHub (May 2, 2025):

Has this never been added oficially? It's such a necesary feature

<!-- gh-comment-id:2847750938 --> @edbanshee commented on GitHub (May 2, 2025): Has this never been added oficially? It's such a necesary feature
Author
Owner

@YuriMB commented on GitHub (Jul 1, 2025):

I'm also waiting for this feature

<!-- gh-comment-id:3022734271 --> @YuriMB commented on GitHub (Jul 1, 2025): I'm also waiting for this feature
Author
Owner

@spacecake commented on GitHub (Aug 26, 2025):

FYI the script works as a charm 10+ months now: script.
Although I moved to Tailscale, this feature if not implemented, for me its moving in the direction to be outdated.

<!-- gh-comment-id:3223609207 --> @spacecake commented on GitHub (Aug 26, 2025): FYI the script works as a charm 10+ months now: [script](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1708#issuecomment-2395482174). Although I moved to Tailscale, this feature if not implemented, for me its moving in the direction to be outdated.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/nginx-proxy-manager-NginxProxyManager#1271
No description provided.