Personal project
Home OS · Self-Hosted Household Platform
A single-VPS platform — a Laravel/Octane hub for a household's money, assets, and family life — behind one Caddy edge and one Authentik login, alongside a dozen self-hosted services.
One VPS · a dozen services · one edge, one SSO · no Kafka, by design
The problem
A household runs on scattered state: money in one app, car service history in a glovebox, appliance warranties in an email, the kids’ vaccination schedule in a clinic’s paper booklet, document scans in a phone’s camera roll. Nothing nudges you before a registration lapses or a warranty expires. I already ran a mature finance app — Masareef — and didn’t want to rebuild it. I wanted one owned place that unified everything else, ran on infrastructure I control, and spoke both my languages.
What I built
Home OS is the hub of a self-hosted platform running on a single VPS. It’s a Laravel + Inertia/React app served by FrankenPHP + Octane out of a multi-stage image, bilingual Arabic/English with full RTL, and animated with Framer Motion (reduced-motion aware). The hub gives you a “today” dashboard, assets & upkeep (vehicles, appliances, and reminders by date or mileage), a family section (people, the Jordan national immunization schedule, growth and milestones), a month calendar, and a launcher into the rest of the platform.
The load-bearing decisions:
-
One edge, one identity. A shared Caddy edge terminates TLS and reverse-proxies every service under
*.laithlabs.com; Authentik is the OIDC identity provider, so a single login covers the hub and the fleet — SearXNG, for instance, is gated behind Authentik forward-auth. No service publishes a public port; only the edge reaches them. -
Integration over rebuild. Rather than re-implement finance, the hub joins Masareef’s Docker network to read its Postgres and call its API. A vehicle maintenance cost posts straight through as a finance expense — and that sync is idempotent by a stable key and degrades to a
Pendingstate when Masareef is unreachable, so a network blip is a retry, never a silent double-charge or a lost record. Documents live in Paperless-ngx (OCR, AR/EN); the hub keeps only the link and expiry metadata that drives the reminders. -
A fleet, curated. Vaultwarden, an Outline wiki, Technitium DNS (ad-blocking + DoH), SearXNG, Reactive Resume, Mealie, Umami analytics, Uptime-Kuma — each is a compose file plus a Caddy snippet, most behind SSO, all fronted by the same edge.
-
Household-scale by design. Deliberately no Kafka, no CDC, no microservice sprawl. My MT Sync work is where that machinery earns its place — at hundreds of millions of records. A two-person household is not that; the Laravel scheduler running a morning digest and reminder dispatch is the entire “event system,” and that restraint is the point.
The result
A dozen services run live today behind one edge and one login, and the hub runs the household day to day — finances, upkeep, and family life in one place, in two languages, on infrastructure I own. The interesting part isn’t any single feature; it’s that a household platform can be genuinely useful without being over-engineered, and that knowing when not to reach for Kafka is the same judgment as knowing when to.