Fixed 403: Forbidden - accessing WebAdmin behind Nginx Proxy Manager (docker)


I did a search here on the forums and the Goog but have been drawing blanks.

I'm new to OLS and am migrating away from long-time httpd use (I build from source, but 2.5.x is still limited to openssl and quic:http/3 won't be implemented into openssl until v3.3, we hope... And QuicTLS, even with my efforts to compat its 3.0.5 to openssl 3.0.x has left problems still). I've been running OLS for a couple days.

Many failed attempts to fix cyberpanel for EL8/EL9 resulted in nonfunctioning installs at best, and I'm not willing to rebase to newbuntu or spedian, if for no other reason than I absolutely despite apt and ufw. Give me fail2ban, dnf, and firewalld please. And anaconda is just cleaner, imo. Anyways....

I decided to use and then in-place ols 1.8.1 over top. Though I do have lsphp8.2 installed, my built-from-source lsphp8.3 is the primary. I've been building it for a long time and went through the effort of replicating compile flags/switches, structure, shared module building, and stole the lsphp8.3 configs from remi. I also have installed lsmcd. Currently I'm running on top of AlmaLinux 9.4 with epel's mainline kernel 6.9.3. Aside from using source-built php8.3 and imagemagick zeroconf portable, all libraries are from appstream, baseos, or epel (not testing).

I run Nginx Proxy Manager docker-compose by jc21 as a reverse proxy. This has always worked fine on httpd. I have changed the default admin port to 7788. I have a proxy host config set up on a subdomain to proxy to ``. I've tried by enabling secure=1 in admin_httpd.comf as well and changing the forward schema to https. I have force SSL enabled with automatic letsencrypt certs, and have tried with both http/2 support on and off. I have created an access list with Accept Any and Pass Auth to Host enabled (though WebAdmin doesn't use http spec auth type).

Now my issue: when I attempt to access the WebAdmin using the proxy subdomain, I always get a 403 Forbidden error with subheading "openresty" which is usually a 403 presented by NPM itself. `` is my user-defined docker network for NPM, with `` as the gateway. It does also expose directly via host networking for ports 80 and 443.

I run the http listener in port 8228 and https listener set to 8338. Using the forward host pointer as `` or ``. I can access my other vhosts and all responses come from OLS. it's only the WebAdmin that is giving me 403.

For testing, I opened 7788/tcp on firewalld and am able to connect to the WebAdmin using both `http://public.ip:7788` and `https://public.ip:7788`.

lshttpd is running as nobody:nobody currently. In my NPM letsencrypt cert directory, I chown -R root:nobody the directory the certs are stored in and they are chmod'd to 0640 (owner-rw, group-r), and the certs seem to be working fine that way in the vhost configs.

I also did `firewall-cmd --zone=docker --app-port=7788/tcp` but still error 403.

*NOTE: I solved the issue and am still going to post this, along with my answer as a reply, in case anyone else runs into this issue. :)
My solution:

My user-defined docker bridge network, docknet, is assigned to my npm docker, making the gateway between npm and host services.

Firewalld has numerous zones, and that zone's ruleset applies to interfaces assigned to them. The docker zone is automatically created when installing docker-ce, and docker initialized bridge networks are automatically added to the zone. However, user defined bridge networks are not added automatically. docknet is the name I defined for my bridge network. Using a user-defined network ensures that it always starts with the same subnet and gateway, so that my proxy host config files don't break if the gateway address changes.

I ran
firewall-cmd --zone=docker --add-interface=docknet --permanent && firewall-cmd --reload
(I had already added the WebAdmin port to the docker zone). I tried again and am now about to access the lshttpd WebAdmin with my NPM reverse proxy host configuration.

So if you use a dockerized reverse proxy in front of lshttpd AND a user-defined docker bridge network AND firewalld, you need to manually add that bridge network interface to the docker zone and open the proper port on that zone in order for packets to pass from the docker bridge network to lshttpd running on the host.