Putting login panels behind a VPN

While I was at the 39th Chaos Communication Congress (39c3) with friends this year, I finally got to do something that was on my to-do list for quite some time:

Set up mail for my domain!

At first I was considering hacking something together. In the end I decided to just use dockerized mailcow (for my own sanity’s sake). This turned out to work pretty well, there was just one thing that I felt slightly uneasy about: Mailcow’s login panel being exposed by default. Specifically /admin and /domainadmin.

Yes, I did change the admin users name, set up a reasonably secure password, 2FA (you know the drill). But it still is extra attack surface in the end. Compromising on a tiny bit of convenience (namely having to be connected to your own VPN, to make any changes via mailcows web UI) is a good tradeoff for that little bit of protection gained in my opinion.

Nginx config:

    < ... >
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name mail.ni9.de;

        < SSL cert stuff here... >

        location ^~ /admin {
            allow 10.11.12.0/24;
            allow fd42:cafe::/64;
            deny all;
            proxy_pass http://127.0.0.1:8888;
            < Proxy header stuff >
        }

        location ^~ /domainadmin {
            allow 10.11.12.0/24;
            allow fd42:cafe::/64;
            deny all;
            proxy_pass http://127.0.0.1:8888;
            < Proxy header stuff >
        }

        location / {
            proxy_pass      http://127.0.0.1:8888;
            proxy_buffering off;
            < Proxy header stuff >
        }
    }
    < ... >