Serving Internal Website Securely Using Private VPN From Home

For some time I had the need to expose my private knowledge base - implemented using Emacs Org Mode - securely over internet the so that I can access it anywhere.
I considered setting up a password protected website at my ISP, but decided against it.
Instead, I decided to go for a fun but slightly overengineered solution and serving the website from home, using a Raspberry Pi server. Finally I’ve found a valid reason to have a home server and lab with a purpose.
tailscale ("Fast, seamless device connectivity — no hardware, no firewall rules, no wasted time.") is a fantastic way to set up a secure VPN mesh network, with a great free plan. The Raspberry Pi home server and my other devices, such as PC, iPad, and Android phone became part of my own meshed VPN. The web pages are served using nginx from the Raspberry Pi and exposed through tailscale. As a bonus, the Raspberry Pi can be used as an exit node from my devices should I have the need for a VPN connection from somewhere, and do not have any alternatives.
The website is still created and updated manually from the Org Mode files using Emacs Lisp by connecting remotely to the Raspberry Pi and running the script from the terminal.
There is one major pain point with Emacs: it is challenging to freeze package versions so that they are reproducible across across different environments. The most used package manager always downloads the latest version of a package given a specific Emacs version. Additionally, there is usually just one Emacs version available in Linux distrubtion package repositories, and they usually differ across distributions. The one available in the Raspberry Pi repository was slightly too old and not compatible with the packages Emacs used on my Ubuntu and Manjaro machines. I did look into and consider other package managers that implement version freezing. However, the easiest solution was to install a more recent version of Emacs from the Snap Store on the Raspberry Pi.
I expected that this would result in a long blog post with lots of setup and configuration details to be documented. But no, everything mostly just worked and was easy to set up.
I ordered the Raspberry Pi from RaspberryPi.dk. They have great starter kits for newbies like me that make sure you don’t choose incompatible components.
This is what I ordered:
Raspberry Pi 5 - 16 GB
32GB Micro SD – Class A2 – Raspberry Pi OS
Official Raspberry Pi 27W USB-C Power supply
512GB M.2 SSD NVMe – Raspbery Pi
Raspberry Pi M.2 HAT+ for Raspberry Pi 5
KKSB Tall Case for Raspberry Pi 5
Raspberry Pi 5 Active Cooler
Official Raspberry Pi Micro HDMI to HDMI-adapter
Assembling this went fine, the only thing I couldn’t figure out was whether the GPIO pins were supposed to extend through the M.2 Hat or not, and which spacers I should choose. Now they are - if anything - terminated by the M.2 hat.