The Hill90 Homelab
Hill90 is homelab infrastructure on a single Hostinger VPS running AlmaLinux 10. It is the automation that takes a bare VPS to a running, TLS-terminated, observable, Tailscale-secured Docker host — and keeps it there. It is not a single-app host. An AI agent application previously ran here. It was shelved in June 2026 and removed from the repository in July 2026. See Decisions for the record, and the AI Application section for what it was. The infrastructure lives in the jonhill90/Hill90 repository. This site is the narrative layer; the operational depth stays in that repo, beside the code it describes.A personal cloud platform
The organising idea is capability parity with Azure. Jon works with Azure professionally, and each platform service here is the open-source counterpart of a primitive he uses at work — chosen so the concepts, failure modes and operational habits transfer in both directions.
That framing is also the honest answer to why a homelab runs an identity provider at
all. It is not single sign-on for four dashboards — the infrastructure dashboards
deliberately keep local auth behind Tailscale. It is capability parity plus real
multi-user support: family accounts, demo accounts and test accounts, a realm per
consumer, with the AI application as one tenant among several rather than the reason the
platform exists.
The reasoning behind the mapping, and the consequences that follow from it, are recorded
in the Hill90 repository’s
decision records rather
than restated here.
What is missing
The parity is partial, and the gaps are real rather than pending:- No container registry. Nothing corresponds to Azure Container Registry; images come from public registries and GHCR.
- No messaging tier. Nothing corresponds to Service Bus or Event Hubs.
- No object storage. MinIO went with the application teardown and has not returned.
- Keycloak and Postgres are being restored, not running. They are absent from the current stack. Everything on this page under “What runs” is what exists today.
What runs
Ten containers across three stacks.
The edge stack owns all three Docker networks; the other two attach to them as
external. On a fresh host, edge deploys first.
Surfaces
Everything with a dashboard is reachable only over Tailscale (
100.64.0.0/10), enforced
by a Traefik IP-allowlist middleware on top of the host firewall. Only ports 80 and 443
are open publicly.
The stack
- Host — AlmaLinux 10 on a Hostinger VPS
- Runtime — Docker Engine and Docker Compose
- Edge — Traefik v2.11 with Let’s Encrypt, HTTP-01 for public hostnames and DNS-01 for Tailscale-only ones
- Observability — Prometheus, Grafana, Loki, Tempo, plus Promtail, node-exporter and cAdvisor
- Secrets — OpenBao as the intended runtime store, SOPS + age for bootstrap and disaster recovery
- Admin access — Tailscale VPN, SSH by key only
- Provisioning — Ansible playbooks driven by the Hostinger and Tailscale APIs
- CI/CD — GitHub Actions
- DNS — Hostinger DNS API via
scripts/hostinger.sh
The one piece of application code
services/dns-manager is the only application code in the infrastructure repository — a
small Flask webhook implementing Traefik’s httpreq DNS-01 provider against the
Hostinger DNS API. Without it, certificates for Tailscale-only hosts cannot issue, because
those hosts have no public A record for HTTP-01 to validate against. See
Certificates.
Where to go next
Architecture
Network topology, isolation boundaries, and what each service is responsible for.
Local development
Run the whole stack on a Mac with one command. No secrets, no VPS.
Operations
Deploy, rebuild, back up, recover.
Secrets
The vault model, and an honest account of what the vault holds today.