Holger — guide (the whole workflow)
Class:
guide· audience: a techie standing holger up end-to-end. The what is indesign.md; the why inreasoning.md. Per-function how-tos:registry-guide·serve-guide·storage-guide·auth-guide·agent-guide·embed-guide.
f0 — one session, internet-side to airgap
The end-to-end shape of using holger crosses several functions. One pass:
- Pack (internet side). Run the agent to pull the packages you need and bundle them into one signed
.znippy— seeagent-guide. - Carry. Move the
.znippyacross the boundary on USB/optical. No cable crosses. - Serve (secure side). Point a
Repositoryinholger.ronat the archive, runholger-server, and stockcargo/pip/dockerclients fetch out of it — seeserve-guideand the deploy how-to below. - Lock the door. Before exposing a write path, turn on auth + RBAC — see
auth-guide. - Or embed it. Instead of a server, link
holger-server-liband drive a registry in-process — seeembed-guide.
Deploy holger (Helm or raw k8s / Talos)
Build the image
docker build -f distribution/Dockerfile -t holger.rs/nordisk/holger:3.1.1 .
Two-stage: rust:1.96-slim builder → distroless/cc-debian12:nonroot runtime (uid 65532). Entrypoint holger-server start --config /etc/holger/holger.ron; exposes 50051 (gRPC) and 8081 (HTTP gateway).
Option 1 — Helm (recommended)
# dev: NodePort, 5Gi local-path, no auth, :latest
helm install holger deploy/helm/holger -n holger --create-namespace \
-f deploy/helm/holger/values-dev.yaml
# prod: LoadBalancer + Ingress, 200Gi CSI, OIDC auth, pinned tag
helm install holger deploy/helm/holger -n holger --create-namespace \
-f deploy/helm/holger/values-prod.yaml
Key values.yaml knobs:
| knob | default | note |
replicaCount |
1 |
keep at 1 — RWO volume |
image.repository / image.tag |
holger.rs/nordisk/holger (Holger serves its own images) / appVersion |
container |
service.type |
ClusterIP |
NodePort (dev) / LoadBalancer (prod) |
service.grpcPort / httpPort |
50051 / 8081 |
|
storage.size / storageClassName |
50Gi / local-path |
override class for prod CSI |
auth.enabled / auth.mtlsCaCert |
false / "" |
mounts the CA secret |
ingress.enabled / ingress.host |
false / holger.example.com |
HTTP gateway |
config.ron |
example helm-dev repo |
the full RON graph |
Option 2 — raw manifests
kubectl apply -f deploy/k8s/
kubectl -n holger wait --for=condition=Ready pod -l app=holger --timeout=120s
Applies: namespace, deployment (1 replica, Recreate, readonly rootfs, dropped caps, probes), service (+ service-nodeport overlay), pvc (50Gi RWO local-path), configmap (the holger.ron), secret (mTLS CA).
Talos specifics (deploy/k8s/TALOS.md)
- No default StorageClass — the PVC stays
Pendinguntil you installlocal-path-provisioner(dev, needs a machine-configextraMountspatch) or a real CSI (OpenEBS Mayastor / democratic-csi) for prod. - No cloud LoadBalancer — use MetalLB (VIP on the LAN) or the NodePort overlay (30051 gRPC / 30081 HTTP on every node).
- Single replica — writable repos live on one RWO volume; scale-out needs RWX storage. Snapshot the PVC for backups.
Smoke test
kubectl -n holger port-forward svc/holger 8081:8081 &
curl http://localhost:8081/healthz # → ok
helm repo add dev http://localhost:8081/helm-dev
curl -X POST http://localhost:8081/helm-dev/api/charts --data-binary @mychart-0.1.0.tgz
Install / uninstall holger as a service (systemd, either scope)
holger-server install add # user unit (no root), state in ~/.holger
sudo holger-server install add # system unit as the `holger` user, /home/holger/.holger
holger-server install status # active?
holger-server install render # dry-run: print the unit that would be written
Same lifecycle through the Skidbladnir ship: holger-server service {install,start,stop,status,health,uninstall}.
Uninstalling — it nukes the data and keeps the keys
holger-server install remove # stop + remove the unit; data KEPT
holger-server install remove --purge # + erase the data. SSH KEY + TOKEN KEPT.
--purge erases the scope's data tree — archives, audit log, autogen holger.ron, caches, registry state (and in system scope the staged /usr/local/bin/holger-server). It never touches:
.ssh— the deploy key registered on your private git remotes,- a stored
token, - the
holgerservice account and its/home/holgerhome (system scope), because the home holds the key and the account owns it.
That is the suite-wide law: uninstalling the software nukes all data but keeps the ssh keys. A reinstall reuses the same identity with nothing to re-register. The purge root follows the scope actually in use (~/.holger vs /home/holger), and every delete goes through skidbladnir::systemd::guarded_remove_dir_all, which refuses .ssh, a real user's home, a system directory, and a symlink out of the tree.
To destroy the identity too, ask for it by name:
holger-server install remove --purge --wipe-identity # DESTROYS the deploy key + token
--wipe-identity is refused without --purge. It is irreversible: the key registered on the git remotes is gone, and a reinstall generates a new key you must register on every remote before holger can pull again.
The output says which of the two happened — KEPT : … identity item(s) — byte-intact or DESTROYED : … --wipe-identity — and a purge that found nothing to erase says so instead of claiming success.
Verify holger (the test matrix)
- UI:
cargo test -p holger-server-ui --features gui— view-model + look + robot-UI. - CLI/agent:
cargo test -p holger-agent-cli. - Matrix:
cargo test -p xtask --test holger_matrix(light) /-- --ignored(heavy: build + boot the mannequin daemon). Ornornir test run holger. - Bench:
nornir bench run holger(holger vs Nexus vs Artifactory, fair hardware, over the real package protocol).
See testing-guide for the full grid.