A Helm chart that runs Ubiquiti's UniFi OS Server in Kubernetes — letting you self-host the UniFi Network application (the controller for switches, APs, gateways, etc.) without buying a UniFi Console. This is the successor to the standalone Network Application that Ubiquiti previously offered.
UniFi OS Server does not support UniFi Protect (cameras), Access, Talk, or Connect — those still require a UniFi Console.
The upstream runtime model (systemd managing ~15 tightly coupled services) is
kept intact. PostgreSQL and RabbitMQ are exposed as explicit, replaceable
dependencies (bundled subcharts or external instances). MongoDB runs embedded
inside the container via the bundled mongodb.service — it is hardcoded by
UniFi and cannot be externalized.
Warning — this project is experimental and not suitable for production yet. There's a lot of AI work I don't have time to verify all of.
Installer binary
└─ Podman container
└─ systemd
├─ unifi-core (Node.js — platform API)
├─ unifi (Java — Network controller)
├─ ulp-go (Go — identity platform)
├─ nginx (reverse proxy / TLS)
├─ postgresql (embedded)
├─ mongodb (embedded)
├─ rabbitmq + epmd (embedded)
└─ 7 more identity/agent services …
Helm release
├─ StatefulSet (single container, upstream systemd startup)
│ └─ unifi-os image (unifi-core, unifi, ulp-go, nginx, identity services,
│ mongodb — embedded, not externalized)
├─ PostgreSQL (CloudNativePG subchart or external)
└─ RabbitMQ (CloudPirates subchart or external)
This chart is built on HULL, which means
almost every Kubernetes object (services, routes, secrets, env vars, resource limits,
etc.) is defined as data in charts/unifi-os/values.yaml under hull.objects. You can override
or extend any object in your own values file without forking the chart. Values
that need Helm template logic use the _HT! prefix for inline Go Helm templates.
| Path | Purpose |
|---|---|
| Dockerfile | Extracts the upstream OCI image and repackages it as a standard Docker image. |
| Makefile | Build/push the image, extract configs, dump systemd maps. |
| Chart.yaml | Helm chart definition (app version 5.1.21) with subchart dependencies. |
| values.yaml | Primary chart values — StatefulSet, services, secrets, Gateway API routes. |
| values.env.example.yaml | Environment-specific overrides (registry, passwords, hostnames). |
| SERVICES.md | Reference for every UniFi OS service, its role, and dependencies. |
| DATABASE.md | PostgreSQL setup — bundled CNPG and external, credential options. |
| TLS.md | TLS certificate options — self-signed, existing secret, cert-manager. |
charts/unifi-os/templates/ |
HULL entrypoint, helpers, and Postgres override secrets. |
scripts/ |
Extraction utilities for reverse-engineering the upstream image. |
- Kubernetes
- Helm 3+
- CloudNativePG operator if using the bundled PostgreSQL subchart (
postgres.enabled: true) - cert-manager if using
unifi.tls.certManager.enabled: true(optional but recommended)
cp values.env.example.yaml values.env.yamlSet credentials for PostgreSQL and RabbitMQ. The recommended approach is
existingSecretPrefix for PostgreSQL (no plaintext in Helm values) — see
DATABASE.md for full details. Minimal plaintext example:
global:
postgres:
connection:
password: "your-pg-password"
rabbitmq:
connection:
password: "your-rabbit-password"
erlangCookie: "your-erlang-cookie"helm repo add unifi-os https://connorsapps.github.io/unifi-os-helm
helm repo update
helm upgrade -n unifi --create-namespace unifi unifi-os/unifi-os --install \
-f values.env.yamlThe chart includes opt-in support for:
-
Automated backups via unifi-backup — runs as a CronJob using a local UniFi OS admin account.
-
Prometheus metrics via unpoller — scrapes UniFi OS and exposes metrics for Prometheus. Three auth options:
API key (recommended, UniFi OS 4+) — generate at Settings > Admins & Users > (your user) > API Key:
unifiExporter: enabled: true config: apiKey: "your-api-key"
Username + password — create a local Viewer user at Settings > Admins & Users > Add Admin > Local Access Only:
unifiExporter: enabled: true config: username: "metrics" password: "change-me"
Pre-existing Secret — secret must contain a
passwordkey, anapi-keykey, or both; whichever is non-empty is used (api-key takes priority):unifiExporter: enabled: true config: username: "metrics" # required when using password auth existingSecret: name: "my-unifi-exporter-secret" passwordKey: password # default apiKeyKey: api-key # default
Additional collection options (all default to
false):Field What it collects saveEventsClient connect/disconnect and network events saveAlarmsSecurity and network alarms saveAnomaliesDetected network anomalies saveIdsDevice ID-to-name label mappings hashPiiHash MAC addresses and client names (privacy/compliance) -
TLS certificate management via cert-manager — issues and rotates the certificate used by UniFi's internal nginx, with optional Gateway API
BackendTLSPolicyfor re-encrypted backend traffic. See TLS.md.
All are disabled by default. See values.env.example.yaml and the relevant sections in values.yaml to enable them.
This project is not affiliated with, endorsed by, or sponsored by Ubiquiti Inc. "UniFi" and "UniFi OS" are trademarks of Ubiquiti Inc. This repository is independent community work for self-hosting purposes. Use at your own risk. There's some AI ducktape holding this project together.