Why I took my server off the public internet

Oct 26, 2026 · 4 min read

It was the announcement of the PHP2Shell vulnerability last week that finally convinced me to take my personal server off the public internet.

For the past six months or so, particularly since Anthropic unveiled its Mythos model in April, cybersecurity experts have been warning of an impending cyber-apocalypse. Well, Black October is here. The discovery of these critical vulnerabilities in PHP, the programming language used by most websites, resulted in many services going dark as they rushed to patch their systems. This high-profile event has been accompanied by reports of other serious security flaws across widely used software. In fact, around 3% of all vulnerabilities recorded in the National Vulnerability Database since 1988 were reported in the past month alone.

For many years now, I have run a personal server to keep files synchronized across my computers, as well as to store my calendars and contacts. I used to run Nextcloud, but now I run OpenCloud and Radicale for a more lightweight experience. I also run Pinepods as a podcast server.

I decided to put it all behind Tailscale, which creates a mesh VPN to directly link your devices together. This means that my server can speak directly to my computers and my phone while blocking all public inbound connections.

The basic setup was extremely straightforward (and free for personal use). The more interesting problem arose when I tried to figure out how difficult it would be to keep my existing domains and subdomains, both because I like the URLs and because I wanted to avoid having to reconfigure the clients using them.

You see, Tailscale provides private DNS names under *.ts.net, which would be painless to use after the initial reconfiguration of all the relevant OpenCloud, CalDAV, and CardDAV endpoints. But like I said, I wanted to keep my old URLs. This turned out to be easy: simply point your public DNS records for your domain to your private IP addresses in your Tailscale network. These addresses are publicly resolvable, but completely meaningless to devices outside your Tailscale network.

I use Caddy as my server’s reverse proxy for forwarding traffic for a given subdomain to the Docker service bound to the relevant port. Caddy is really easy to use and automatically handles HTTPS certificate management…if you allow inbound HTTP traffic.

But I was about to close my server to the public internet. One option was to use the DNS-01 mechanism for automatic renewal, but using this directly within Caddy generally requires a custom Caddy binary built with a DNS-provider-specific plugin, which would be a pain to manage and keep updated. Alternatively, I could move some or all of my DNS to Cloudflare, which would also work, but again, is a bit of a pain if I can’t manage all of my DNS settings from my actual domain registrar.

Instead, I came across Google’s new implementation of the DNS-PERSIST-01 mechanism. It allows an ACME client to validate domain ownership using a persistent DNS TXT record, without updating DNS for every renewal. I added some TXT records at my registrar, used acme.sh to obtain certificates from Google, and configured my existing Caddy installation to serve them. Renewal and deployment of the certificates are automated, with Healthchecks.io monitoring for failures.

There was one small misstep: when I tried visiting my OpenCloud website from my computer, I noticed it was still connecting to the server’s public IP address rather than its private Tailscale address. After rebooting my router to clear its stale DNS cache, I was all set to go, and flipped the switch to close my server to public inbound traffic. My server is invisible to the public internet and visible to my little network of devices. The drums, drums in the deep of my daily SSH logs have fallen silent.

The trade-offs of using Tailscale are only mild inconveniences. Tailscale doesn’t play nicely with other VPNs, especially on the iPhone. It would be nice to occasionally be able to access my websites from other devices, but my central use case has always been to synchronize files between my devices.

I never used my server to share files externally, so the server never needed to be open, really. It was just the default, but the default has become too dangerous in the age of the AI cyber-apocalypse.

Act accordingly.