Webserver behind VPN

I don't want my Hugo site to be public so the idea is to have it running on a private network and control access by who has VPN access. The steps as far as I can tell are:

  1. Install a VPN
  2. Allow external access to the VPN
  3. Get the webserver to listen on the VPN
  4. Give users access to the VPN
  5. Create a domain name and allow a user with VPN credentials to reach the website

1. Install a VPN

This is by far the easiest part by using pivpn

curl -L https://install.pivpn.io | bash

During install you can choose Wireguard and/or OpenVPN, I initially chose Wireguard which works very smoothly together with the iOS or Android apps. Config can be done by scanning a QR code from the app but needs more manual work when more than one client is needed so I switched to OpenVPN which also has nice apps but configuration via uploading a file is a bit more clunky.

2. Allow external access to the VPN server

This involves forwarding port 1194/UDP to the LAN IP of the box running the webserver which in my case also runs pihole and unbound and hence lighttpd is the default web server.

3. Get the webserver to listen on the VPN

Normally one would edit /etc/lighttpd/lighttpd.conf but this config file is supplied by the pi-hole install and will be overwritten when updating pi-hole so /etc/lighttpd/external.conf needs to have the lines below added (by default the file exists but is empty). The first line allows me to access the webserver from the LAN and the second one from the VPN.

server.bind = "192.168.xxx.xxx"          # LAN IP
$SERVER["socket"] == "10.xxx.xxx.1" {}   # VPN IP

4. Give users access

This is simple as well from the command line, for each new client type

pivpn add

will ask for a sudo password, the client name and then create a file called clientname.ovpn in the ~/ovpns directory which it will also create if needed. These files have to be made available to the respective clients and installed in the OpenVPN app.

5. Reaching the website

I created a domain name with noip and then forwarded port 80/TCP to the LAN IP of the webserver.

Previous Post Next Post