How you will run it.
Three supported paths, all rootless, all described by one service matrix. The commands below are placeholders for the shape of the thing — the real ones land with the first release.
Choose a runtime
Podman ≥ 5 with Quadlet
The reference path. Quadlet turns container units into systemd units, so the instance starts with the machine, restarts under systemd's rules and runs entirely in your user session.
# planned — not available yet mkdir -p ~/.config/containers/systemd curl -LO https://github.com/greluc/Home-Inventory/releases/latest/download/homeinv-quadlet.tar.gz tar -xzf homeinv-quadlet.tar.gz -C ~/.config/containers/systemd cp homeinv.env.example ~/.config/homeinv/homeinv.env # set HOMEINV_* systemctl --user daemon-reload systemctl --user start homeinv-minimal.target loginctl enable-linger "$USER" # survive a logout
- ·Generated from deploy/services.yaml — never hand-edited
- ·Rootless by construction: no daemon, no root, no bind mounts
- ·The migration service runs once per start, before the api unit
Docker with Compose v2, rootless
An equal path, not a fallback. Same images, same environment keys, same limits — Docker must be installed in rootless mode; the rootful daemon is unsupported.
# planned — not available yet curl -LO https://github.com/greluc/Home-Inventory/releases/latest/download/compose.yaml curl -LO https://github.com/greluc/Home-Inventory/releases/latest/download/.env.example cp .env.example .env # set HOMEINV_* docker compose up -d docker compose logs -f homeinv-migration
- ·Generated from the same service matrix; a hand-written deviation fails CI
- ·Named volumes only — a bind mount would reintroduce host ownership
- ·Published ports come from the web service alone; everything else is internal
Kubernetes with Helm
Hand-written rather than generated, and validated against the matrix: same services, same environment keys, same limits. Tested in CI against kind with the restricted PodSecurity profile and user namespaces.
# planned — not available yet helm repo add home-inv https://greluc.github.io/Home-Inventory/charts helm repo update helm show values home-inv/home-inv > values.yaml # then edit helm install home-inv home-inv/home-inv -f values.yaml -n home-inv --create-namespace
- ·Arrives with stage 2 — the two container runtimes carry operation first
- ·The chart disciplines statelessness: api and worker hold nothing on disk
- ·PostgreSQL, OpenSearch and RabbitMQ are yours to provide or to run in-cluster
Rootless, without exception
No supported path runs a container daemon or a container as root on the host. That is not a hardening preference — it is why the application listens on 8080 and why there is not a single bind mount in the deployment directory.
One source, three renderings
deploy/services.yaml is edited; the Quadlet units and compose.yaml are generated from it, and a hand-written deviation fails the drift check. The Helm chart is too different in shape to generate, so it is validated against the same matrix instead.
Before you start
| What | Requirement |
|---|---|
| Container runtime | Podman ≥ 5 with Quadlet, or Docker with Compose v2 — rootless in both cases |
| Kubernetes | A cluster with the restricted PodSecurity profile and user namespaces |
| Database | PostgreSQL 18 — row-level security, JSONB, uuidv7() |
| Distributions | Debian ≥ 13 · Ubuntu ≥ 26.04 LTS · Fedora ≥ 43 · RHEL, CentOS Stream, Rocky, Alma ≥ 9.5 resp. ≥ 10 |
| Network | One hostname with TLS. The web service is the ingress and the only one that publishes a port |
| Media | A volume for the BlobStore. No bind mounts — anywhere |
| Outbound | Only the egress proxy may leave the deployment; in the smallest profile with exactly one allowlist entry, for the virus signatures |
What you will be running
Ten services, not one container| Service | Role | From stage |
|---|---|---|
| web | The ingress: serves the PWA and the CSP headers — the only published port | 0 |
| api | The REST and GraphQL surface, stateless | 0 |
| migration | A one-shot service; no long-running process holds DDL rights | 0 |
| postgres | PostgreSQL 18 with row-level security | 0 |
| blobstore | The filesystem BlobStore as its own service, so api and worker stay stateless | 0 |
| clamav | The mandatory malware scan, fail-closed | 0 |
| egress-proxy | The only way out, with an allowlist per segment | 0 |
| worker | Events, background runs, housekeeping | 1 |
| rabbitmq | Quorum queues for the transactional outbox | 1 |
| opensearch | The derived read model for search and facets | 1 |
The stage column says when a service first appears. A stage-0 installation runs seven of them; OpenSearch and RabbitMQ arrive with stage 1, when there is something to index and something to queue.
Get told when it is installable
There is no mailing list and no newsletter. Watch the repository's releases — that is the same signal the author gets.