Running your own server infrastructure is satisfying in a way that renting someone else's isn't. For years a single modest cloud instance has hosted all my personal projects, from small utility services to my Magic: The Gathering cube analyzer.

But kingdoms, even digital ones, can get crowded.

As I built and deployed more applications, each on its own subdomain, I started to see the warning signs. Memory usage was steadily climbing. The server, once a spacious home, was starting to feel like a tiny studio apartment with too much furniture. I was approaching a classic engineering crossroads: the dreaded resource bottleneck.

The Crossroads: To Scale Up or To Scale Out?

When your server starts to sweat, the industry playbook presents two standard options.

The Vertical Path: More Money, Less Fun The first option is to scale vertically. This is the brute-force solution: you open your cloud provider's dashboard, slide a lever, and pay more money for a bigger, more powerful instance. It's simple, effective, and completely soulless. It solves the problem by throwing money at it, a solution that offers zero intellectual satisfaction. Where's the challenge in that?

The Horizontal Path: Maybe Overkill The second option is to scale horizontally. This is the "real" engineer's answer for large-scale systems. You spin up multiple servers and put a load balancer in front of them to distribute traffic. It's the right pattern at scale, and for a personal project with minimal traffic it's hiring a symphony orchestra to play "Happy Birthday." The complexity is wildly out of proportion to the problem.

I rejected both paths. Both options felt... uninspired. They were correct, sensible, corporate solutions. But this is my personal lab, a place for experimentation and ingenuity. Surely, there had to be a more creative path.

My eyes fell upon a Raspberry Pi 5 sitting on a shelf in my closet. I kid you not it was sitting right there. The answer, staring back at me. This device is a powerhouse in miniature, with a multi-core ARM processor and gigabytes of RAM, nowadays doing little more than gathering dust. Meanwhile, my high-availability cloud server was gasping for memory. The juxtaposition was too perfect to ignore.

And then, a third, slightly unhinged idea began to form. What if I could make them work together?

Digging Secret Tunnels

The challenge was obvious: how do you get a public cloud server to safely delegate tasks to a private machine sitting behind a home router, without exposing your home network to the entire internet? The answer, it turns out, is to think in reverse.

You don't have the cloud server call the Pi. You have the Pi call the cloud server.

That's a Reverse SSH Tunnel: a persistent, outbound-only connection that the private machine opens and keeps open.

How it works:

  1. When the Raspberry Pi boots up, I can have it automatically initiate a secure SSH connection out to my public cloud server. It essentially tells the server, "Hey, I'm here and ready for work. Here's a secret, secure hotline you can use to talk back to me."
  2. Because the connection is established from the inside out, my home router never has to accept an inbound connection from the internet. There is no forwarded port on my home network for a scanner to find, which is the specific property I was after: the externally exposed surface of my home network doesn't change at all.
  3. My public server can now act as a smart "switchboard operator." It receives all public traffic as usual, but its Nginx configuration has a special rule: "If a request comes in for a resource-intensive task, don't handle it yourself. Instead, forward it down the secret hotline to the Pi."
  4. The Pi receives the request, does the heavy lifting with its ample RAM and CPU, and sends the result back up the tunnel.

From the outside, none of this is visible. You talk to a public cloud server, and you have no idea your request took a detour through my closet.

Three trust regions -- internet, cloud VPS, home network -- separated by a full-height band marking the home router. The request path runs left to right: client, to nginx on the VPS, to a loopback tunnel port, across the router band to nginx on the Pi, to the application. A dashed arrow beneath runs the other way, from the Pi out to the VPS loopback port, labelled: autossh dials out from home and holds the tunnel open. A separate arrow arriving from the internet stops dead at the router band with a cross drawn through it.
The direction of the dashed arrow is the entire design. Traffic flows left to right; the only connection anyone initiates goes right to left.

Where the Trust Actually Lives

I want to be careful about what that buys, because "no inbound port on my home network" is a real property and it is not a synonym for "secure."

What the design removes is one specific risk: an internet-reachable listener sitting on my home network, waiting to be found by whatever is scanning the IPv4 space this week. That was the thing I didn't want, and it's genuinely gone. My router's inbound posture is identical before and after this project.

What the design doesn't remove is the tunnel. The Pi holds a credential that authenticates it to the VPS, and in exchange the VPS holds a live socket that reaches into my closet. That's a trust path, and it points inward. Three things carry the weight now:

  • The VPS is inside my home network's threat model. Anybody who gets root on the cloud box inherits a pre-authenticated pipe to the Pi without going near my router. The tunnel doesn't open a new door from the internet; it opens one from the machine at the far end, and that machine is the one exposed to the internet.
  • The SSH credential is the perimeter. Whatever the tunnel account can do on the Pi is what a compromised VPS can do on the Pi. That argues for a dedicated key-only account with no shell, rather than reusing a login I already had -- which is a configuration decision, not a property the architecture gives me for free.
  • The bind address decides who can use the tunnel. A remote forward bound to 0.0.0.0 on the VPS republishes my closet service to the entire internet on that port, which is precisely the thing this design exists to avoid. Bound to loopback, only the VPS's own Nginx can reach it. Same tunnel, same diagram, completely different exposure -- and nothing about "reverse SSH" picks the safe one for you.

So the accurate version of the claim is narrower than the one I wanted to make. This architecture relocates the externally exposed surface onto a machine that was already exposed and already maintained for that job, and it means a mistake in my home network config is no longer internet-facing. It doesn't mean there's nothing left to protect. It means there's one thing left to protect, and I know which one it is.

Making Sure Water is Flowing Through the Tunnel

Making this a reality required orchestrating a few key components:

  • autossh: A utility that wraps the standard SSH tunnel command and ensures it is persistent. If the connection ever drops due to a network blip, autossh automatically re-establishes it.
  • systemd: The standard Linux service manager. I wrote a simple service file on the Pi that ensures the autossh tunnel starts automatically on boot and is kept alive.
  • Nginx (The Switchboard): The Nginx instance on the public server was configured to proxy requests for specific subdomains to the local end of the tunnel. The Nginx instance on the Pi was configured to receive requests from the tunnel and route them to the correct local application.

The result is a genuine hybrid: the small latency-sensitive services stay on the cloud instance, and the memory-hungry ones that nobody notices being a second slower run in my closet.

Takeaways

It costs less than the bigger instance would have, and I learned considerably more than I would have from moving a slider.

The honest caveat: I've added a dependency on my home internet and a Pi that is, structurally, in a closet. For services where that matters I left them on the cloud box. Knowing which workloads can tolerate your closet is most of the design.

My metrics dashboard is already giving me ideas for the sequel.