Part 2 of 6
No open port: how my phone reaches Paperless
Pulling an invoice out of my own archive from anywhere, with not a single port open on the router, and measuring whether everything really is encrypted.
Picture this. The washing machine gives up just before the warranty runs out, and I’m at the service desk of a hardware store. The first question comes, as it always does: do you have the invoice? Not on paper, obviously. I type paperless.home.example on my phone, and a second later there it is, straight from my document archive at home.
To the person behind the counter, that’s just a phone showing an invoice. To me it holds the question this part is about. My router at home lets nobody in from outside; there’s no open door, or in the jargon, no open port. So how does a request from a hardware store make it all the way home? And who gets to read it on the way?
A quick reminder of where we are. In part 1 I described my homelab as a house. A single computer, pve1, runs lots of virtual machines, or VMs, which are walled-off computers inside the computer, and every service lives in one of its own. This part is about the front door, the doorbell and the reception desk, called network & access on the map. I already rushed down this path once in part 1. This time we’ll go slowly, stop at every station, and finish with a measurement that shows whether “everything is encrypted” is actually true.
A network on top of the network
The first station is the one you never see. My phone is on mobile data or some Wi-Fi, my servers sit behind the Fritz!Box router at home, and the internet lies in between. For the two to talk as if they were in the same room, there’s NetBird.
NetBird lays a private network over the internet, known as an overlay network. The easiest way to picture it is as a set of private tunnels only my own devices may drive through. The tunnels are built by a technology called WireGuard. It encrypts every connection between two devices with keys of their own, so anyone watching from outside sees gibberish. Every device in this network is called a peer and gets an address of its own inside it, its NetBird address. My phone is a peer, and so are my laptop, pve1 and every VM that runs a service.
For peers to find each other they need a go-between, the NetBird server. I run it myself, on a small rented server at the hosting company Hetzner. It’s the only part with open doors, and its job is modest. It knows who belongs and who may talk to whom, and it helps two peers find each other. Both sides build the tunnel itself from the inside out, which is why the router at home never has to open a door. If they can’t find a direct path, a relay, a sort of transfer station on the same server, passes the data along, still encrypted.
The picture shows that split. At the top is the NetBird server, which only hands out who may reach whom. Below it is the phone on the road, in the middle my home behind the Fritz!Box, and at the very bottom the backup server, which also lives at Hetzner.
Who may talk to whom
The boxes in the picture carry names like mobile or lan-servers. Those are groups, and NetBird uses them to decide who may talk to whom. Four are enough for me:
| Group | Who | Allowed |
|---|---|---|
mobile | laptop and phone | everything in the three home groups |
lan-servers | pve1 and all service VMs | everything in the three home groups |
lan-infra | NetBird gateway and the Raspberry Pi | everything in the three home groups |
remote-servers | backup server at Hetzner | a few ports only |
I never sort new services in by hand. When a new VM is set up for the first time, it joins with a setup key, a one-time key that drops it into the right group automatically, plus into a DNS group, which we’ll get to in a moment.
The two members of lan-infra deserve a sentence. The NetBird gateway is a crossing point through which the phone can also reach devices on the home network that aren’t peers themselves. When I’m away it also works as an exit node, a way out through which all my internet traffic goes home first and then onwards. The Raspberry Pi, a small computer the size of a credit card, is its fallback.
A name needs an address
The phone is on the private network now, but paperless.home.example on its own gets it nowhere, because computers find each other by address, not by name. Translating one into the other is the job of a DNS server, the phone book of the network. Mine is AdGuard Home in the VM dns-01, a DNS server that also filters out ads and trackers on the side.
How does the phone know to ask AdGuard? NetBird tells it. Every peer in the DNS group gets a rule that boils down to “ask AdGuard”. The second entry is a copy of AdGuard on the Pi, so names still resolve while dns-01 restarts.
What AdGuard answers is almost boring. For my services it holds exactly one entry, a placeholder rule called a wildcard. Every name ending in .home.example points to the same NetBird address, the one belonging to the VM proxy-01, which is the subject of the next section. Paperless, Nextcloud, Immich: the answer is always the same. A new service therefore never needs a change to the phone book.
There’s one rule here that I learned the hard way, though.
From practice: Before the move I had pushed the “ask AdGuard” rule to the group
All, meaning every peer. It also hit peers that couldn’t reach AdGuard. In that case NetBird sets only its own resolver, with no fallback, and the machine in question was left unable to look up any names. Since then every peer belongs to exactly one DNS group, and the AdGuard machines themselves ask a public DNS server.
The proxy
So every name leads to the same address. Waiting there is the reverse proxy, or just the proxy. It works like the reception desk in an office building. Every visitor checks in there, the receptionist reads whom they want to see and takes them there. In the same way, the proxy accepts every request, recognises the service from the name and hands it to the right VM. In my case it’s a program called Nginx Proxy Manager in the VM proxy-01, and it’s the only way in.
The proxy always lists the VMs behind it by their NetBird address, never by name, for two reasons. One is that this sends the stretch from the proxy to the service through a WireGuard tunnel too; I’ll come back to that when we measure. The other is a bad experience with a different proxy. There, names as targets had caused sporadic error pages with the number 502, because the proxy sometimes translated the name into an unreachable IPv6 address and sometimes not at all.
The padlock in the browser
Between phone and proxy the browser speaks HTTPS, the encrypted language of websites that gives you the padlock in the address bar. Without the padlock, my moment at the service desk would start with a warning page.
For the padlock the proxy needs a certificate, a kind of ID card that proves to the browser it’s talking to the right server. Mine comes from Let’s Encrypt, a free ID office for the web. I have a single one covering every name under *.home.example, a so-called wildcard certificate.
Before Let’s Encrypt issues an ID card, it checks that I really own the domain. The usual check knocks on my server from outside, which is exactly what can’t work here. With the second option, the DNS-01 check, I instead place a check record in the public phone book of my domain, which is kept at Hetzner. All it takes is an API token, a key that lets a program change entries there. No server has to be reachable.
That’s every station. The picture shows the whole path from the hardware store as a sequence. The participants stand along the top, and the arrows follow time from top to bottom.
Two doors
Only a peer on the private network gets as far as the proxy. That’s the first door. The second is signing in to the service itself. For Nextcloud and Immich that’s handled by Authentik in the VM auth-01. Authentik is a single sign-on service, one central login much like “Sign in with Google”, except it runs in my home. The services consult it through a standard called OpenID Connect. Each service has a group, and only its members may sign in.
I don’t click the setup together in the web interface. A small Python script does it through Authentik’s programming interface, which turns a new service into one entry in a list. It wasn’t entirely smooth. Since Authentik 2026.x there’s a field called grant_types, which sets the ways a service is allowed to sign in. If the script doesn’t set it, it stays empty, and every sign-in fails with a message that tells you nothing. Authentik also has to trust NetBird’s address range as a proxy. Otherwise it writes http instead of https into the sender details it hands to services, the issuer, and the services reject it.
And on my home network? Measured
Which brings us to the second question from the start: who can read along? On the road that’s quickly answered, since the WireGuard tunnel sits between phone and proxy. The more interesting stretch is the one people tend to forget, between the services at home, on the local network or LAN.
Because the proxy reaches every service at its NetBird address, that traffic runs through WireGuard tunnels too, even when both VMs sit on the same computer. It costs no detour, because two peers on the same network find each other directly. NetBird will show you this if you ask (shortened):
paperless-01.peers.<netbird-domain>:
Connection type: P2P
ICE candidate (Local/Remote): host/host
P2P with host/host means the data goes straight across the home network rather than through the transfer station on the internet. It should still be encrypted. That’s easy to claim, so I measured it.
On a network, data travels in small pieces called packets, and each one carries the door it’s headed for, its port, like an address on an envelope. Paperless takes requests on port 8000. While the proxy sent six requests to Paperless, I recorded every packet on the network connection of the Paperless VM on pve1, which is called a packet capture. A little over 1,100 packets came by in 14 seconds. Not one of them carried port 8000. All I saw were WireGuard packets on port 51820, in other words the encrypted tunnels.
I prefer measuring to believing for a reason. Once, the signposts in my network told me one thing while the traffic was doing another.
From practice: In September Paperless was “sometimes unreachable”. The service ran the whole time, the routing tables, the signposts for packets, looked right every time I checked, and NetBird reported nothing. The culprit was an old fixed route on the Fritz!Box into NetBird’s address range. Now and then the Fritz!Box sent a hint for single destinations, an ICMP redirect in the jargon, which roughly says “better take this route”, and the proxy followed it. For a short while exactly one address then bypassed the tunnel. Because the proxy kept that in a cache rather than in the table, every check came back clean. The old route is gone, and the proxy now ignores those hints.
Every path, one by one
The capture covers one path. For the full picture I wrote down every path my data travels and what protects it. A few of them belong to later parts, such as the backups at Hetzner. For now only the colour matters: green is NetBird, blue is encrypted another way, red is unencrypted.
Here are the same paths as a table. TLS is the same encryption that sits behind the padlock in the browser.
| Path | Protection |
|---|---|
| Phone or laptop → proxy | NetBird (WireGuard), with HTTPS and the wildcard certificate inside |
| Proxy → service VM | NetBird (WireGuard), with HTTP inside |
| Paperless and Open WebUI → language model on the workstation | NetBird (WireGuard) |
pve1 → Proxmox Backup Server at Hetzner | TLS over the internet; pve1 encrypts the chunks before uploading them |
| Docker VMs → S3 (compose-backup) | HTTPS; contents and file names additionally encrypted with rclone crypt |
TrueNAS ↔ scanner, Paperless, pve1, Home Assistant | NFS and SMB in plain text on the LAN |
The last row is the honest exception. TrueNAS is my file server on the home network, and NFS and SMB are the languages other devices use to reach its shared folders. TrueNAS isn’t a NetBird peer yet. The inbox folder the scanner writes into for Paperless, the Proxmox share and the Home Assistant backups all use its home network address, and anyone capturing there could read scanned documents. Bringing TrueNAS into the NetBird network is the next step.
Back at the service desk
So the invoice on my phone has come a well-guarded way. The NetBird server only brokered the tunnel, the phone book gives the same answer for every service, and behind the proxy with its ID card there’s another tunnel all the way to the Paperless VM. Nobody reads along on the road, and nobody at home either, as long as the path doesn’t run through TrueNAS.
If this part left me with one habit, it’s measuring. “Everything is encrypted” is a claim, and a capture in the right place takes a minute. It confirms the rule and shows you the exception. And when a fault hits only single destinations, and only sometimes, these days I look in the caches before I look at the settings.
One question has nothing to do with networks. That washing machine invoice was a sheet of paper once. How does a sheet like that become a document I can find in a second, standing in a hardware store? That’s where part 3 picks up.