Homebox
A home inventory for what you own and where it lives.
Homebox (source) is a small, single-binary inventory app built for households rather than warehouses: items with a location and labels, purchase and warranty details, photos and attached documents. It ships as one container with an embedded SQLite database, which is exactly why it gets neither a Postgres cluster nor a public route here — it is an internal, low-write tool.
Alternatives considered
Cloud Hosted
| Tool | Open Source | Free Tier | Notes |
|---|---|---|---|
| Sortly | No | Limited | Inventory SaaS with a small free plan, paid beyond |
Self Hosted
| Tool | Open Source | Full Features | Notes |
|---|---|---|---|
| Grocy | Yes | Yes | Household ERP centred on groceries and chores; inventory is one module of many |
| InvenTree | Yes | Yes | Parts and stock management, built for makers and small manufacturing |
| Snipe-IT | Yes | Yes | IT asset management with check-in/out; heavy for a household |
Installation
Architecture
- Deployment: Single
homeboxdeployment in thehomeboxnamespace,Recreatestrategy,HBOX_MODE=production - Image:
ghcr.io/sysadminsmedia/homebox, the-rootlessvariant (digest-pinned) - Storage: Longhorn PVC (
homebox, 1Gi,longhorn-encrypted) on/dataholding the SQLite database together with item photos and attachments;/tmpis an emptyDir. Deliberately no CNPG cluster for a small single-pod app - Networking: ClusterIP service on port 7745, HTTPRoute via the internal gateway on
homebox.int.kueber.eu;HBOX_OPTIONS_TRUST_PROXYmakes the app trust the gateway's TLS termination, without it Homebox sees plain HTTP and builds a wrong OIDC redirect - Email: outbound mail through the shared email component — the
HBOX_MAILER_*variables read the allinkl SMTP credentials
Security
- The rootless image runs as uid 65532; the uid is pinned numerically because the image declares its
USERby name and the kubelet cannot verify a named user againstrunAsNonRoot.readOnlyRootFilesystem: true,allowPrivilegeEscalation: false, all capabilities dropped,fsGroupso the root-owned Longhorn mount is writable, no service-account token — the pod passes the restricted policies without any exception - Ingress only from the internal gateway's Envoy pods, so nothing here is reachable from the public internet, only from the home LAN and the NetBird mesh
- Explicit egress on 587 and 465 to the internet for SMTP, RFC1918 excluded; the shared gateway-egress rule stays for the Keycloak issuer
- The API-key pepper lives in the SOPS-encrypted
homeboxsecret; the OIDC client secret comes fromworkspace-outputs, minted by the workspace that owns the Keycloak client tier-2priority class, 25m / 64Mi requested, 128Mi limit
Updates
Managed by Renovate. The image is digest-pinned.
Data Management
- PVC:
homebox(1Gi, Longhorn-encrypted), annotatedk8up.io/backup: "true" - Backups: k8up
Schedules to Hetzner and Backblaze (workload-talos-homebox-*) via restic. This is a file-level copy of a live SQLite file; a snapshot taken mid-write could in theory be inconsistent, which is accepted for a low-write app
User Management
Login is in-app OIDC against Keycloak, client homebox in the kueber.eu realm, created by the app's workspace (spec.oidc, not gated) with the callback /api/v1/users/login/oidc/callback on the internal hostname; there is no gateway SecurityPolicy. Local accounts exist alongside: HBOX_OPTIONS_ALLOW_REGISTRATION ships as true so the first accounts can be created and is meant to be flipped to false afterwards — OIDC logins are unaffected by that flag, and the open signup is only ever LAN- or mesh-reachable. API keys are hashed with the HBOX_AUTH_API_KEY_PEPPER from the SOPS secret.
Configuration Management
All settings are HBOX_* env vars in the talos patch and the email component's patch; secrets come from the SOPS-encrypted homebox secret and the synced SMTP credentials.
Usage
Sign in with the Keycloak account, create locations and labels, then add items with their purchase details, photos and receipts. Warranty and maintenance information hangs off the item.
Cluster-specific deviations from the above live in the per-cluster README — see k8s/apps/homebox/talos/README.md.
Cluster Deployment
homebox
Deviations from the standard app pattern:
- In-app OIDC instead of a gateway SecurityPolicy — the patch wires
HBOX_OIDC_ENABLED=trueagainst the Keycloak clienthomebox, which the TofuWorkspace creates (workspace/patch-oidc.yaml, not gated) and whose secret arrives inworkspace-outputs, so login happens inside Homebox and the internal route carries no Envoy OIDC policy.HBOX_OPTIONS_ALLOW_REGISTRATIONships astrueso the first SSO users can create their account, and must be flipped tofalseafterwards. Internal ingress only, so the open signup is LAN/VPN-reachable at worst. - SQLite instead of CNPG — deliberately no database cluster for a small
single-pod app; the SQLite file lives with the attachments on the 1Gi
homeboxPVC. k8up backs the PVC up file-level; a snapshot taken during a write could in theory be inconsistent, accepted for a low-write app. - Rootless image variant (
-rootlesstag, uid 65532) so the pod passes the restricted policies without a custom securityContext dance.
- Image:
ghcr.io/sysadminsmedia/homebox:0.26.2-rootless@sha256:a41a3081ac724a2f4955b71b9294bd916b0e92035e4ea8438e84def74f4ae692
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app.kubernetes.io/name: homebox
name: homebox
namespace: homebox
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app.kubernetes.io/name: homebox
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: homebox
spec:
automountServiceAccountToken: false
containers:
- env:
- name: HBOX_OPTIONS_ALLOW_REGISTRATION
value: 'true'
- name: HBOX_OPTIONS_TRUST_PROXY
value: 'true'
- name: HBOX_OIDC_ENABLED
value: 'true'
- name: HBOX_OIDC_ISSUER_URL
value: https://keycloak.web.kueber.eu/realms/kueber.eu
- name: HBOX_OIDC_CLIENT_ID
value: homebox
- name: HBOX_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
key: client-secret
name: workspace-outputs
- name: HBOX_AUTH_API_KEY_PEPPER
valueFrom:
secretKeyRef:
key: HBOX_AUTH_API_KEY_PEPPER
name: homebox
- name: HBOX_MAILER_HOST
valueFrom:
secretKeyRef:
key: host
name: allinkl-smtp-credentials
- name: HBOX_MAILER_PORT
valueFrom:
secretKeyRef:
key: port
name: allinkl-smtp-credentials
- name: HBOX_MAILER_USERNAME
valueFrom:
secretKeyRef:
key: username
name: allinkl-smtp-credentials
- name: HBOX_MAILER_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: allinkl-smtp-credentials
- name: HBOX_MAILER_FROM
valueFrom:
secretKeyRef:
key: from
name: allinkl-smtp-credentials
- name: HBOX_MODE
value: production
image: ghcr.io/sysadminsmedia/homebox:0.26.2-rootless@sha256:a41a3081ac724a2f4955b71b9294bd916b0e92035e4ea8438e84def74f4ae692
livenessProbe:
failureThreshold: 3
httpGet:
path: /api/v1/status
port: 7745
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
name: homebox
ports:
- containerPort: 7745
name: web
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /api/v1/status
port: 7745
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
resources:
limits:
memory: 128Mi
requests:
cpu: 25m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
startupProbe:
failureThreshold: 3
httpGet:
path: /api/v1/status
port: 7745
initialDelaySeconds: 15
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
volumeMounts:
- mountPath: /data
name: homebox-data
- mountPath: /tmp
name: tmp
priorityClassName: tier-2
securityContext:
fsGroup: 65532
runAsGroup: 65532
runAsUser: 65532
volumes:
- name: homebox-data
persistentVolumeClaim:
claimName: homebox
- emptyDir: {}
name: tmp