DEV Community

Cover image for I Built a Production Platform… Just to Write a Blog
Lennard John
Lennard John

Posted on

I Built a Production Platform… Just to Write a Blog

I just wanted to write a blog.

That’s it.

No scaling requirements. No users. No revenue.
Just a place to write.

So naturally, I built a 3-node Kubernetes cluster on bare metal, automated everything with Terraform and Ansible, added GitOps, monitoring, alerting, and exposed it to the internet using a zero-trust Cloudflare tunnel.

Completely normal.

🤔 Why Over-Engineer Something So Simple?

Because the goal wasn’t the blog.

The goal was to learn how real platforms are built.

Not tutorials. Not “hello world” deployments.
But the actual systems that sit behind production environments.

So I treated this like a real platform:

Fully automated
Reproducible
Observable
Secure by design
⚙️ The One Command That Does Everything

Everything starts with:

docker compose up

That single command:

Provisions infrastructure (Terraform → Proxmox)
Configures the cluster (Ansible → Kubernetes)
Deploys platform services (Ingress, monitoring, GitOps)
Deploys applications (WordPress + MariaDB)
Sets up public access (Cloudflare Tunnel)

About 25 minutes later… the entire platform is live.

No manual steps. No SSH after bootstrap.

🏗️ How It’s Actually Built

At a high level:

Git → CI/CD → Terraform → VMs → Ansible → Kubernetes → Argo CD → Apps
Infrastructure (Terraform)
Creates 3 VMs on Proxmox (1 control plane, 2 workers)
Configures Cloudflare tunnel + DNS
Configuration (Ansible)
Bootstraps Kubernetes using kubeadm
Installs core services (Ingress, storage, networking)
Deploys monitoring and applications
GitOps (Argo CD)
Watches the kubernetes/ directory
Automatically syncs changes to the cluster

After the initial build, I don’t SSH into anything anymore.

Everything is managed through Git.

🔁 GitOps in Action

This is my favourite part.

I change a file in Git → push → and Argo CD updates the cluster automatically.

No kubectl. No manual deploys.

Just Git.

That shift — from “run commands” to “declare desired state” — completely changes how you think about systems.

🔐 Zero Trust (No Open Ports)

Nothing in my home network is exposed directly.

Instead, everything goes through a Cloudflare Tunnel:

User → Cloudflare Edge → Tunnel → Kubernetes Ingress → App
No port forwarding
No public IP exposure
HTTPS handled at the edge

It’s simple, secure, and surprisingly powerful.

📊 Observability (Because Things WILL Break)

I added:

Prometheus (metrics)
Grafana (dashboards)
AlertManager (email alerts)

If:

a pod crashes
a node goes down
memory spikes

I get notified.

Because a platform you can’t observe… is a platform you don’t understand.

💥 What Went Wrong (Important Part)

This didn’t work the first time.

Some of the issues I hit:

Terraform not returning VM IPs (guest agent problems)
Ansible running before infrastructure was ready
Kubernetes probes killing WordPress before it stabilised
Infinite HTTPS redirect loops behind Cloudflare
PVC-related deployment deadlocks

Most of these came down to one thing:

I assumed things would be ready… when they weren’t.

🧠 Biggest Lesson

Stop designing systems that depend on timing.

Start designing systems that converge.

Instead of:

“wait 30 seconds and hope”

Do:

retry until ready
check actual state
design for failure

That shift alone made everything more reliable.

🔁 Reproducibility (This Is the Real Win)

The entire platform can be:

Destroyed
Rebuilt
Moved

Using the same codebase.

That means:

No snowflake servers
No hidden config
No “it only works on my machine”
🎯 What This Project Actually Demonstrates

This isn’t about WordPress.

It demonstrates:

Infrastructure as Code (Terraform)
Configuration as Code (Ansible)
GitOps (Argo CD)
Zero Trust Networking (Cloudflare)
Observability-first design

In other words:

How modern platforms are actually built.

🚀 What’s Next

I’m planning to:

Move this to a Talos-based cluster
Add multi-environment support (dev/staging/prod)
Implement proper secrets management (SOPS or Vault)
Explore multi-cluster deployments
👋 Final Thoughts

Yes — this is overkill for a blog.

But that’s kind of the point.

If you can build something like this for a simple project…
you can build it for something that actually matters.

If you want to check it out:

🌐 https://lennardjohn.org
💻 https://github.com/Lennardj/homelab-blog

I’m Lennard — currently transitioning into DevOps / Platform Engineering.

If you’re on the same journey, feel free to connect 👇

Top comments (0)