Archive note. Written in March 2021 in Hanoi, for a blog I have since retired, and the earliest post in that blog’s homelab sequence - everything else grew out of it. Prices and products are of their time, and the arrangement itself did not last long: I moved to the Netherlands within about a year, and a VPN hub hosted by a Vietnamese carrier stops being the obvious choice once you live on the other side of the planet from it. What follows chronologically is mining ETH in a homelab.

TL;DR. You want to reach a machine at home from outside. The textbook answer is to forward a port on the ISP modem. On my line that was not available at all - it sat behind carrier-grade NAT, with no public address to forward from - but the argument against it stands even where it is. What does work is renting a VPS - a virtual private server, a small Linux machine rented by the month - and running a VPN on it that everything dials out to. Both designs put a process on the internet where strangers can reach it. The difference is how many, and whose. Forwarding grows one internet-reachable service per forward, some of them on appliance firmware nobody will ever patch. The VPN hub has two, both on a machine you administer: WireGuard, and the SSH you administer it with. That count does not move when the service list grows. The reason this matters is not the first service. It is the fourth.

Concretely: the VPN was WireGuard, deployed with Algo - Ansible scripts from Trail of Bits that stand up a personal WireGuard or IPsec server with hardened defaults - on a virtual machine rented from Viettel IDC - a Vietnamese cloud provider, and the hosting arm of the same carrier that supplied the line at home. Both of those choices do more work in the argument than they look, so they get their own sections.

The network everyone starts with

Home networks are not standardised. Two flats with identical floor plans end up wired differently depending on who lives there. The common shape is an ISP modem and router combo with everything hanging off it: a PC on Ethernet, a laptop and a phone on wifi, maybe a second router or access point bridging a far room.

That is enough for what most people need. Web, streaming, games with low latency. Nothing about it is wrong.

Then one day you want to reach the PC at home while you are not at home, and to do it safely. And you discover that the textbook answer is not on the menu.

The ready-made answers

The hosted remote-desktop tools do this job and do it well:

  • TeamViewer is free only while your use counts as personal, and the moment it decides otherwise you are paying. The figure I had in mind at the time was 24.90 USD. I did not write down whether that was per month or per year, and without that the comparison cannot be made at all: against a monthly licence the VPS at 60 USD a year is about a fifth of the price, and against an annual one it is more than double. I am not going to pick the branch that flatters the decision.
  • AnyDesk is the same shape with fewer features.
  • Chrome Remote Desktop is genuinely free, and it is what I would still point a non-technical person at. It also tries to negotiate a direct peer-to-peer route rather than hauling traffic through Google’s relays, though behind carrier-grade NAT - which my line was - it falls back to relaying, and the signalling goes through Google either way. Its catch is small: it runs in Chrome, so some key combinations never reach the far machine - press Ctrl-W expecting to close a window over there and you close a tab over here.

So I should be straight about the decision, because the cost framing flatters it. Chrome Remote Desktop was free and solved the stated problem. Paying 5 USD a month to escape a hotkey collision would be absurd. What I actually wanted was a general-purpose machine with a public address, which happens to solve remote access as a side effect and then keeps being useful. The remote desktop was the excuse, not the reason.

Buying domestically mattered more than the price did, though the price was competitive anyway - Viettel IDC’s small instances sit where an equivalent DigitalOcean droplet sits. The machine was with the hosting business of the carrier already terminating the line at my flat, so traffic between home and hub stayed inside one national network instead of detouring through Singapore or Frankfurt and back. For a tunnel that every interactive session traverses, that is the difference between a remote desktop feeling local and feeling remote. It is also the part of this design that did not survive moving continents.

Point everything at a VPN running on that VPS and the devices stop being on separate networks. They address each other as though they shared a LAN, which means the built-in remote-desktop protocols - RDP on Windows, VNC elsewhere - work with no product tier involved. Laptop, phone, tablet, all reaching the machines at home.

Worth naming what that does not buy: the VPS is in the path for every packet, always, where Chrome Remote Desktop is in the path only when it cannot get out of it. I traded a company I do not control for a rented box I do, which is an improvement in authority and a regression in hop count.

What is actually running on it

WireGuard, put there by Algo.

Algo is worth naming rather than leaving as “a VPN”, because half of what makes this design defensible is which server you expose. It is Ansible, run from your own laptop against a fresh cloud instance, and its opinions are the point. It declines to install OpenVPN or Tor. It drops legacy cipher suites and protocols - no L2TP, no IKEv1, no RSA. It does not put its security on TLS. Users are declared in a config file before deployment and each one gets a generated WireGuard config and a QR code, so adding a phone is scanning a square rather than editing anything on the server. It builds on an Ubuntu LTS - long-term support, the flavour that receives five years of security patches - with unattended security upgrades switched on.

The WireGuard part matters more than the automation. WireGuard does not reply to packets that fail authentication, so it offers no banner, no version, and no handshake to anyone who cannot already prove they belong.

That is worth stating carefully rather than as a magic trick. A scanner still learns something: a UDP port that returns silence while the rest of the host returns port-unreachable is a fingerprint, and anyone looking for WireGuard will recognise it. What it does not get is an identified service to look up in a vulnerability database. Compare that with a forwarded port, where the thing behind it answers, names itself, and frequently gives its version. The listener exists and is findable; it just refuses to introduce itself.

It is also small. WireGuard’s kernel implementation is a few thousand lines against the hundreds of thousands in the IPsec and OpenVPN stacks, and that ratio is the whole reason it is possible to feel relaxed about running one on a public address.

The port forward, and why I did not

The obvious objection: run the VPN server at home behind the ISP modem, forward one port to it, save the 5 USD. If the address changes, dynamic DNS gives you a free name that tracks it. People do this and it works.

Be precise about what a forward actually does, because I was sloppy about this for years. It is a translation rule on the modem, not a service running there. The modem listens for nothing; it rewrites the destination and hands the packet to a machine on the inside. The exposed process is on that machine.

Which is the part that matters. Some of those machines you patch: the VMs, the PC. Some you cannot. A camera appliance runs whatever firmware its vendor last felt like shipping, and no update you can apply will change that. The forward makes it reachable from the entire internet, and the modem in the middle is a device you did not choose and do not administer, so you cannot even put a useful rule in front of it.

So the exposure is not “a listener on the ISP’s box”. It is one internet-reachable service per forward, spread across machines of mixed provenance, some of which will never receive another update. That is the argument, and it is the reason I would still do this somewhere that hands out a routable address without being asked.

There was a second reason, and in my flat it was decisive: there was no address to forward from. The line sat behind carrier-grade NAT, CGNAT for short. The ISP hands out a private address on the WAN side of your modem and shares one real public address among a great many subscribers. Nothing outside can address your line, because your line has no address of its own.

That is worth separating from the usual advice, because dynamic DNS is normally offered as the answer to “my IP changes” and people reach for it here too. It does not help. Dynamic DNS keeps a name pointed at an address that is yours but moves. Under CGNAT the address is not yours at any moment, and pointing a name at the carrier’s shared address sends strangers to the carrier, not to you. The modem will still show you a port-forwarding page. It will still accept the rule. The rule will do nothing.

Outbound connections work fine under CGNAT - that is the whole point of it - so a tunnel dialled outward to something with a real address was the only shape available anyway. The security argument is why I would choose it; the NAT is why I could not have chosen otherwise.

Since I already owned a domain, I bought the VPS and pointed a DNS record at it through Cloudflare, so I had a name rather than an address to remember. That is all Cloudflare is doing here - a VPN is not HTTP and does not travel through a caching proxy.

Then it happens again

Here is the part that changes the arithmetic, and the reason this post exists.

You put up a security camera. Its recorder wants to be reachable so the phone app can see the feed, so you forward a port. Fine - one.

A few days later you want to host something at home, a blog perhaps. A VM, another port. Two.

Then home automation: the garage door, the water heater, the lights. Another VM, another port. Three.

Then the several hundred gigabytes of material on the PC that you want to watch from outside the house. Four.

The list does not terminate. Each addition, alone, is one small hole and a reasonable trade. Together they are a steadily growing inbound attack surface on hardware you do not control, assembled one defensible decision at a time. That is what makes it dangerous: no single step feels like the wrong call.

Two honest caveats before the conclusion.

The count grows only if you let it. Three of those four services speak HTTP. One reverse proxy - a single web server that accepts every request and forwards it to whichever internal service the hostname belongs to - on one VM fronts all of them behind a single port, and now the growth is in proxy configuration rather than in forwarded ports. That is a real answer to the problem and it is what many people do. It also leaves you one internet-facing listener on a VM you patch - which, as the next section admits, is exactly where the VPN hub lands. The two designs are closer relatives than this post originally implied.

Not everything can join a VPN. The camera is the first example in the escalation above, and a camera appliance almost certainly cannot run a VPN client, nor can most home-automation hubs. Those devices never join the tunnel. They stay on the LAN and speak to nothing outside it; what joins the tunnel are the clients, and the tunnel gives those clients a route onto the LAN where the appliances already live.

That route does not appear by itself, and this is the step Algo does not do for you. Out of the box it builds a road-warrior server: clients dial in and reach the internet, not each other’s home networks. To reach the camera you need one always-on machine at home to be a peer as well, carrying the LAN prefix in its allowed addresses and routing for the subnet, with the matching prefix configured on the client side. A machine that is already running anyway is the natural choice, which is the recurring theme of this entire homelab. The appliance still does not participate, which is fortunate, because it cannot.

What the hub actually buys

The VPN hub does not remove the internet-facing listener. It has at least one: the VPN server itself, on a public address, which is the whole point of it being reachable.

I spent this entire post arguing against internet-facing services, so let me state the real claim rather than the flattering one. The gain is not zero exposure, and it is not even down to one: Algo leaves SSH running, because that is how you administer the box. Call it two, of which one is silent and the other is the conventional hardened thing everybody already runs.

The gain is that the count stops tracking the service list. Four reachable services across machines of mixed provenance become two on a single box I chose, administer, and can patch the day a fix ships. The fifth service adds none, and neither does the tenth.

Where the internet-facing listener lives, in two designsBoth designs expose something to the internet; the diagram is about how many things, and whose hardware runs them. Red marks a path reachable from the internet, not a box. Left: the internet reaches the ISP modem, which runs no service of its own and only rewrites destinations, handing each forwarded port to a machine behind it. Every service the owner adds - camera, blog, home automation, media - needs its own forward, so the number of internet-reachable services grows with the list. Two of those machines are the owner's VMs and get patched; the camera runs vendor firmware that will not be updated again. Right: the internet reaches one machine, the rented virtual server, running WireGuard and the SSH used to administer it. WireGuard does not answer packets that fail authentication, so it offers a scanner no banner and no version to look up. The ISP modem forwards nothing; the home network and any device away from home both dial outward to that hub and meet on it. Adding a fifth service leaves that count unchanged. The single red arrow on the right is the honest admission that the exposure moved rather than vanished.One reachable service per forwardthe modem translates; the service runs behind itinternetISP modem4 forwards, no listenercamerabloghome automediathe camera runs vendor firmware you cannot patchthe VMs are yours; the appliance never gets another updateno single one of these feels like the wrong callTwo listeners, and they are yoursthe count does not move when the list growsinternetVPS: WireGuard + SSHWireGuard names nothinglaptop, phoneaway from homeISP modem0 ports forwardedhome LANthe four, and the nextgreen dials outward; nothing at home accepts a connectionappliances never join the tunnel - the clients do, and reach themThe hub does not remove the exposure. It relocates and caps it.A growing set of reachable services, some unpatchable, becomes a fixed two on a box you administer.

What it costs, stated plainly

Three bills come with this that the 5 USD does not cover.

You now run a server. The modem was condemned for being unpatchable; the replacement is patchable and therefore must be patched. Algo takes the worst of that away by building on an Ubuntu LTS with unattended upgrades on by default, which is more maintenance than most home routers ever receive. It does not take all of it away: unattended upgrades cover distribution packages, not the day that support window closes and the whole instance needs rebuilding. A VPN server abandoned across that boundary is worse than the port forward it replaced.

It is a single point of failure. A forwarded port fails one service at a time. A hub fails everything at once, including the route you would use to get back in and fix it. That is a genuinely worse failure mode and the only mitigation is a second way in, which costs either money or the exact exposure you were avoiding.

Everything transits the rented box. Including, if you go through with the media plan, video. On the cheapest instance available, which comes with the bandwidth allowance you would expect at that price. Watching something in bed never needed the tunnel - that traffic is local - but watching it from elsewhere does, and that is where this design meets its limit.

What this actually was

I wrote it as a log of my own decisions, so that when something broke months later I would know where to look, and on the chance it helped somebody circling the same choice.

Reading it back, it is the load-bearing one. Once every machine at home sits on one private network that outside devices can join, the questions stop being about connectivity and start being about capacity: what else could run here, which box should run it, and what happens when one of them dies. That is a homelab. It started as an argument about 5 USD and a port.