Work / Cloud-Native Platform Engineering

OpenHost

A cloud-native platform for deploying and operating open-source applications through automated Kubernetes infrastructure.

Role
Founder & Platform Engineer
Timeline
Ongoing
Primary Impact
12+ services provisioned & operated on Kubernetes
Technology
Node.js, TypeScript, MongoDB, Redis, BullMQ, Socket.IO, Docker, Kubernetes, FluxCD, GitOps
01 — The Problem

Deploying a self-hosted application well requires provisioning compute, generating manifests, wiring ingress and TLS, and reconciling that state continuously — work most small teams repeat by hand for every tenant, every time.

Manual provisioning does not scale past a handful of tenants, and doing it synchronously inside an HTTP request creates fragile, non-resumable deployments with no clear audit trail of what state the cluster is actually supposed to be in.

02 — My Role
Victor's Responsibilities
Designed the full system architecture end-to-end
Implemented the Node.js/TypeScript API and worker layer
Built the GitOps manifest generation and Git integration
Configured Kubernetes, FluxCD, and reconciliation
Implemented real-time status via Socket.IO
Scope

Sole engineer and founder — architecture, backend implementation, infrastructure automation, and operations were designed and built independently.

03 — System Constraints
Solo engineering effort — no dedicated infrastructure team
Self-hosted Kubernetes cluster with limited compute budget
Deployments needed to survive process restarts and partial failures
Real-time visibility required without polling-heavy architecture
Tenant isolation needed without a full multi-cluster setup
04 — Architecture

The API accepts a request and persists desired state to MongoDB. A queued job hands the work to a provisioning worker, which generates Kubernetes manifests and pushes them to a Git repository. FluxCD reconciles the cluster continuously against that repository — the source of truth is Git, not any single running process.

Socket.IO streams job and reconciliation status back to the client in real time.

CLIENT
Provisioning request initiated
NODE.JS API
Validates and accepts request
MONGODB PLATFORM STATE
Desired state persisted
REDIS / BULLMQ QUEUE
Job queued for processing
PROVISIONING WORKER
Generates Kubernetes manifests
GITOPS REPOSITORY
Manifests committed as source of truth
FLUXCD
Reconciles cluster against Git
KUBERNETES CLUSTER
Workload deployed and healthy
05 — Request & Data Flow
01
Client submits an application provisioning request to the Node.js API.
02
API validates the request and writes desired state to MongoDB.
03
A provisioning job is queued in Redis via BullMQ.
04
A worker picks up the job, generates Kubernetes manifests, and commits them to Git.
05
FluxCD reconciles the cluster; status streams back to the client over Socket.IO.
06 — Key Engineering Decisions

Why Asynchronous Jobs?

Provisioning involves multiple slow, failure-prone steps. Running them inside an HTTP request ties deployment reliability to a single request lifetime — a queue lets work be retried, inspected, and resumed independently of any client connection.

Why GitOps?

Git gives desired state a version history, a diff, and a rollback path for free. FluxCD reconciling against Git means the cluster is always being pulled back toward a known-good, auditable state rather than drifting from imperative commands.

Why Redis and BullMQ?

BullMQ provides retries, backoff, and job status out of the box on top of Redis, which was already in the stack for caching — avoiding a heavier message broker for a workload that is bursty rather than constant.

Why Socket.IO?

Provisioning can take seconds to minutes. Clients need live status — queued, working, reconciling, healthy — without polling an endpoint repeatedly; a persistent socket connection made that status feel immediate.

07 — Hard Problems
Failed queue jobs left tenants in a partially-provisioned state until idempotent retries were built in.
Kubernetes reconciliation loops occasionally fought with manually-applied test resources during early development.
File permission mismatches between the worker container and mounted Git credentials blocked early manifest commits.
DNS resolution for newly-provisioned tenant subdomains lagged reconciliation, requiring a readiness check before marking deployments healthy.
TLS certificate issuance raced ahead of ingress creation on first deploys, needing an explicit dependency order.
Ingress routing conflicts surfaced when multiple tenants shared a wildcard domain during load testing.
08 — Outcome
12+
Services deployed and operated on Kubernetes
100%
Deployments provisioned through GitOps, no manual kubectl apply
Async
Provisioning fully decoupled from the request/response cycle
09 — What I Learned

Reconciliation loops are more resilient than imperative deploy scripts — when Git is the source of truth, a failed or interrupted deployment self-heals on the next reconcile instead of requiring manual recovery.

The hardest part of building OpenHost wasn't Kubernetes — it was designing state that could be safely inspected, retried, and reasoned about by someone other than the process that created it.

← All WorkDiscuss This System