Cover photo

Selfhosting behind a VPN

VPNs, tunneling, and paranoia

So I recently received my Raspberry Pi case fan, making my Pi 4 actually usable without it spiking to 80 degrees Celsius. Hooray!

As a paranoid cypherpunk unfortunately living under an authoritarian government, I have some privacy requirements: only Windscribe, my own devices, and some very select services are allowed to see my IP; and connections between the Pi and my other devices must always be encrypted.

This ruled out Tailscale (although that could be useful especially with the integration with Mullvad as exit nodes) as that poses the risk of leaking my IP address to things linked to my digital identity.

It took me quite a bit of finagling and research to get this setup to work just right. I hope my experiences can save you time even if you don't have an extremely niche use case.

My final setup

I have two VPNs active at once on my devices: Windscribe and Nebula. Windscribe routes my outgoing traffic through their network, while Nebula connects the devices together, somewhat like Tailscale.

On the Windscribe page, I used the config generator to generate me a WireGuard config for a certain location. I simply copied this config to my Raspberry Pi and started the connection with wg-quick (I'm not gonna go into details here, should be trivial enough with a Perplexity search)

Yes, 'Florida Man' is a real VPN location. When companies shitpost as heavily as Windscribe does, that's an instant reputation boost in my book.

Windscribe + Nebula

Nebula requires one always-online server called a lighthouse with a static IP (I believe it may work with dynamic DNS, but untested) in order to direct devices to reach each other. I set it up on my Raspberry Pi and opened up a port on my router to make it reachable from the Internet.

Following the Nebula docs worked out pretty well, got nothing extra to say there.

As Nebula doesn't come with systemd services, I had to write them myself. On my Raspberry Pi, I created a new system user account called nebula, gave it ownership of /etc/nebula/ and set it up as a service:

[Unit]
Description=Nebula Overlay Networking
After=network.target

[Service]
Type=simple
ExecStart=/bin/nebula -config /etc/nebula/config.yaml
Restart=always
RestartSec=10
User=nebula
Group=nebula
AmbientCapabilities=CAP_NET_ADMIN

[Install]
WantedBy=multi-user.target

I did a similar one for my laptop, setting up Nebula as a service that runs after Windscribe starts and making sure to create the necessary user accounts:

[Unit]
Description=Nebula Overlay Networking
After=network.target

[Service]
Type=simple
ExecStart=/bin/nebula -config /etc/nebula/config.yaml
Restart=always
RestartSec=10
User=nebula
Group=nebula
AmbientCapabilities=CAP_NET_ADMIN

[Install]
WantedBy=multi-user.target

Additionally, I had to add my chosen range to Windscribe's split tunneling on my laptop in order to allow connections to go through Nebula. (Why did I use TEST-NET-2 and not the designated CGNAT range? Scroll further)

When I change my Windscribe location, I have to also restart the Nebula service, but aside from that it's perfect.

Android

On my Android, I use a work profile to run Nebula while using the main profile with Windscribe. This bypasses the Android restriction of only one VPN active at a time, so now I can have most of my apps behind Windscribe and the selfhosted apps on Nebula. Nice!

UFW kill switch

It took me a while to get it done, but:

sudo ufw allow ssh
sudo ufw allow 
sudo ufw default deny outgoing

Routing conflict

On my first try, I decided to set Nebula up on the CGNAT range. Too bad Windscribe uses it.

sigh

I had to redo my Nebula network to use TEST-NET-2, which is 198.51.100.0/24. So yeah, double check your ranges.

Windscribe doesn't play well with IPv6

Windscribe doesn't support split tunneling IPv6 ranges unfortunately. (and after I finished setting up Yggdrasil!) That was one of the things that stopped me from using Yggdrasil, the other being the high latency.

Jokes aside, Windscribe is a really good VPN. If you want private VPNs, go for either Mullvad, Windscribe, or Njalla. And if you pick Windscribe, tell em in the Discord that I sent you ;p

Closing remarks

Now I've got the basic networking out of the way, I am finally free to finally get some selfhosted services up.

This journey taught me CIDR notation and a little more about being a sysadmin. It would never have been possible (or at least, would take 10 times more time) without the help of my beloved Claude and Perplexity.

During my research, I came across a list of different projects. I opted for Nebula, but here's a small inexhaustive list of the stuff I came across during my search:

  • Innernet, a mesh network based on CIDRs

  • Headscale, an open source Tailscale control server implementation

  • tinc-boot, a wrapper over tinc, which is a full-mesh, auto-healing VPN system supporting many many OSes

  • A blog post from fmac titled 'Nested WireGuard tunnels to my home'

  • gluetun, a tool for running a VPN (the privacy tool kind, not the access tool kind) inside Docker

  • wireguard-go, a userspace implementation of WireGuard

  • NetBird, a mesh net with a full GUI and centralized access control like Tailscale (actually now that I'm writing this post I think I should've just used this but whatever i've set it up already)

The pleasures of [networking] are pains that become desirable, where sweetness and torment blend, and so [networking] is voluntary insanity, infernal paradise, and celestial hell - in short, harmony of opposite yearnings, sorrowful laughter, soft diamond.

Loading...
highlight
Collect this post to permanently own it.
[object Object] logo
Subscribe to [object Object] and never miss a post.