phpIPAM in Docker with Nginx reverse-proxy

I have a bit of a problem with this setup serving phpIPAM via Nginx reverse proxy, so I said to share the solution which works for me here maybe will help somebody out there.

I installed phpIPAM as Docker container following the instructions here: https://github.com/phpipam-docker/phpipam-docker.

Using it via plain http was working OK, but I want to use https for a various of reasons. Security is important, but this being a type of home.lab deployment, I wasn’t that concern about somebody “sniffing” on my plain http traffic. The annoying part that I use a Chromium based browser which insist to upgrade the http to https protocol, even when I type the URL with “http://ipam…”

I’ve installed Nginx (on a different machine) did a basic reverse proxy configuration using some self signed certificates. And here the problem started. I will not bore you with all the details, but the redirection was not working well, either it failed all together or the page appear broken with CSS not render correctly and other issues.

Here is what I had to do for a working solution.

On the Docker part (I assume you followed the phpIPAM Docker installation above or you’re familiar with the containerization solution) I had to add the following in the .env file:

 - IPAM_DATABASE_HOST=phpipam-mariadb
 - IPAM_DATABASE_PASS=my_secret_phpipam_pass
 - IPAM_DATABASE_WEBHOST=%
 - TZ=yourtimezone
 - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 - IPAM_TRUST_X_FORWARD=yes
 - IPAM_DISABLE_INSTALLER=1

Not every line above is relevant for solving the reverse proxy issue, but I chose to share all what I have there. The IPAM_TRUST_X_FORWARD is important for this topic.

Below is what I have in the Nginx config file:

server {
    listen 9443 ssl; # Change to whatever port you're using here
    server_name ipam.home.lab; # replace with your domain

    ssl_certificate /etc/ssl/private/ipam.home.lab.crt;
    ssl_certificate_key /etc/ssl/private/ipam.home.lab.key;

    location / {
        proxy_pass http://phpipam-host.home.lab:81; # Replace with your IP / FQDN and port
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;

        # Add WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Optionally, you can add additional configurations like error pages or logging here
}

I haven’t notice yet any issue using the setup / configuration illustrated above. Let me know if you find this information useful.

Nginx reverse proxy and Webmin

Before going into “How” you may wonder “Why” I need a reverse proxy in front of Webmin.

First, and most important, is laziness. Yes, you read it right. I have in my home lab a one page html listing all http(s) resources I have in my IT lab. Instead of typing numerous URLs I just type one and click the needed link. You may argue that I can use browser bookmarks, true, but I use the one html landing page to access various resources.

Second is a bit more realistic (at least professional realistic).

I’m using Sophos XG (home version) to access my home lab and other in-house smart devices when on the road. This product has a very nice User Portal feature where you can add various “bookmarks” to resources accessible via various protocols (rdp, vnc, ssh, http(s)…)

Recently Sophos decided to retire the http(s) bookmark feature “in order to improve security and reduce the potential for cross-site scripting (XSS) exploits”

In my opinion you work on features to improve security and fix issues, you just don’t retire them. If this would be the way, then let’s shutdown electrical grid, stop cars or terminate Internet and we’re all be more secure. But that’s just my opinion…

Anyway, this action leaves a gap in my happiness accessing my home IT resources. Sophos recommend using WAF, which is a good advice from security perspective, but I don’t plan to have 50 redirections (as in DNAT) from my public facing IP address / router to LAN just to access the various URLs I have in my home lab.

I plan to use one port redirection from Internet to a LAN hosted webserver (protected with WAF) and, you guessed, hosting page lisingt my home lab resources (in form of Webpage Links)

For this to properly work I need one just one domain / subdomain with various URI resources (e.g. https://mydomain.com/resouce1 , https://mydomain.com/resource2, etc…), hence the use of a reverse proxy.

Nginx reverse proxy is not something new and it works great in a lot of situations, but it gave me some headache with Webmin. After quite some research, I said let me put together a quick and dirty how-to in case somebody else needed it.

My scenario involves one server with Nginx as reverse proxy (https://mypage.local.lan) and one Webmin server (https://webmin01.local.lan:10000) for this example.

Http protocol is secured with SSL certificates issues by a LAN CA. In case you don’t have secure http, just make sure to replace https with http in the example below.

My Nginx SSL config is very basic at this point:

server {
server_name mypage.local.lan;
listen 443;

root /var/www/html;

ssl on;
ssl_certificate /etc/ssl/private/mypage.local.lan.crt;
ssl_certificate_key /etc/ssl/private/mypage.local.lan.key;
access_log off;
error_log off;
}

Next part is to add the reverse proxy configuration for https://webmin01.local.lan:10000 so it can be access via https://mypage.local.lan/webmin01

  location /webmin01/ {
    proxy_pass      https://webmin01.local.lan:10000/;

    #Proxy Settings
    proxy_set_header   Host             $http_host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

  }

Add the part above just before the closing } in the first Nginx configuration part.

Very important, don’t forget the trailing / after webmin01 in the location /webmin01/ line

This should satisfy the majority of scenarios where a resource is accessed via reverse proxy. However Webmin needs a bit more fine tuning.

Restart your Nginx service after modifying the configuration files.

On my webmin01 server, I needed to modify the following files part of webmin installation (btw, this is on Ubuntu 20.04).

/etc/webmin/miniserv.conf

Add or modify the following parameters:

cookiepath=/webmin01
trust_real_ip=1
logouttimes=

/etc/webmin/config

Add or modify the following parameters:

referers=mypage.local.lan
webprefix=/webmin01
relative_redir=0

Referers needs to list the URL from where the request comes from. This is par of the Webmin security avoid malicious redirects from untrusted locations.

Webprefix is for proper redirection of the response from webmin pages. A word of advice, once you modify this part, you may not be able to access the webmin installation directly (e.g. https://webmin01.home.lan:10000) since the it will expect a /webmin01 part in the URL which of course is not there on the webmin server.

Restart your Webmin service after modifying the configuration files

After the above configuration, I added on my one html page located on https://mypage.local.lan and link called Webmin01 (pointing to https://mypage.local.lan/webmin01).

Once I access that URL resource, I’ll be redirected to the login page of Webmin01 instance.

In case you give it a try, let me know if it works for you

Last but not least, I’ve did quite some research on this topic, but the best information was from the Github user 1985a and the folks at https://github.com/webmin/webmin/issues/420. Thanks a lot!