Case study · Infrastructure strategy

Migrating Cloud to On-Premises

We moved our own services out of the public cloud and onto hardware we run ourselves. Databases, build runners and internal tools now sit on local machines, and the public side of the business runs on one $10/month VPS with Cloudflare Tunnel in front.

01 · The problem

Cloud bills that outgrow the work

Cloud-first habits spread even a simple system across managed databases, serverless functions, container groups and load balancers. Each piece has its own bill and its own settings to look after.

For many teams the monthly cloud bill grows faster than the value the system delivers. We wanted our data and compute back on hardware we own, while keeping public sites fast and reachable from anywhere.

02 · What we did

Local hardware with a small public edge

The heavy work, including databases, builds, monitoring and task runners, runs on self-hosted machines on our local network.

Public sites sit behind a single small VPS and Cloudflare. Requests that need the private stack travel through Cloudflare Tunnel and a ZeroTier private network, so the local machines never open a port to the internet.

Results

$10/moFor the whole public footprint: one VPS with 2 cores and 4 GB of RAM.
0Inbound ports opened on the local network.
LocalDatabases and business data stay on our own machines.
Self-hostedGit, code review and deployments run on our own Gitea.

Why it matters for leaders

Managed cloud promises scaling without effort. In practice, many companies pay for capacity they never use, need staff certified in one vendor's services, and find it hard to leave once their data is there.

Keeping data and heavy workloads on local hardware, with the cloud used only as a thin public edge, gives a company direct ownership of its databases and settings. The money that used to go on cloud bills can fund product work instead.

For technical readers

How the setup works

The rest of this page covers the network path, deployments and the hardware.

Hybrid on-premises architecture

Public edge $10/month VPS Hono and Nginx proxy SQLite edge cache Static sites and portals Cloudflare Tunnel and ZeroTier no open ports Private local stack Mac Mini and Pi CM5 PostgreSQL and SQLite Gitea and runners Monitoring and task runners

How it runs day to day

A small public attack surface

Databases and API settings live on the local network. The public VPS only serves static pages and proxies, so there is far less exposed to the internet.

Cloudflare Tunnel instead of open ports

The cloudflared agent on each local host makes an outbound connection to Cloudflare, which forwards public requests to it. Nothing on the local firewall has to be opened.

The same setup locally and in production

Developers run the same services on the same kind of machine that production uses, so there are fewer surprises when a change goes live.

Self-hosted Gitea

Code review, repositories and deployment automation run on our own Gitea instance. Pushes trigger self-hosted runners that deploy to systemd services on the local hosts.

Technical details

Architecture
Local-first stack with a small cloud edge proxy
Public edge
$10/month VPS (2 cores, 4 GB RAM) running Hono and Nginx
Tunnelling
Cloudflare Tunnel (cloudflared), ZeroTier private network
Local hardware
Raspberry Pi CM4/CM5 for IoT work; Mac Mini M4/M5 for the company's second brain
Databases
SQLite at the edge; PostgreSQL as the local system of record
Deployments
Self-hosted Gitea with webhook triggers and local runners
Languages
TypeScript and Rust

Further reading

Cloud savings

Want to spend less on cloud hosting?

We can help you cut cloud costs, move to a local-first setup or build a secure hybrid infrastructure for your team.