- Update dagger.md reference card: new module name, source path, container build types table, container-version function - Update build-container-image.md: container.py as preferred for indri, default.nix for ringtail, navidrome as reference pattern - Update upgrade-dagger.md: uv.lock path (no longer under .dagger/) - Update .dagger/src/blumeops_ci path references across 5 how-to docs - Update container-version-check and pin-container-versions docs - Update mise-tasks reference - Set modified: 2026-04-11 on all changed docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 KiB
| title | modified | tags | ||||
|---|---|---|---|---|---|---|
| Wire CI Registry Auth | 2026-04-11 |
|
Wire CI Registry Auth
How CI pipelines authenticate to the zot registry after OIDC + apikey auth is enabled.
Overview
The zot-ci service account (created in register-zot-oidc-client) belongs to the artifact-workloads group, granting ["read", "create"] permissions — CI can push new tags but cannot overwrite or delete existing ones.
Authentication uses a zot API key generated after the service account's first OIDC login. The key is stored in 1Password (Forgejo Secrets item, field zot-ci-api, in blumeops vault) and synced to Forgejo Actions secrets via the forgejo_actions_secrets ansible role. The key expires every 90 days — see zot#API Key Rotation for the rotation procedure.
Push Paths
Dagger path (Dockerfile containers)
.forgejo/workflows/build-container.yaml passes --registry-password=env:ZOT_CI_API_KEY to the Dagger publish() function, which calls with_registry_auth() before pushing.
Nix/skopeo path (Nix containers)
.forgejo/workflows/build-container-nix.yaml passes --dest-creds=zot-ci:$ZOT_CI_API_KEY to skopeo copy.
Secret Flow
1Password Forgejo Secrets item (field zot-ci-api) → ansible pre_task fetches it → forgejo_actions_secrets role syncs to Forgejo API → both runners (k8s on indri, host on ringtail) access it as ${{ secrets.ZOT_CI_API_KEY }}.
Key Files
| File | Purpose |
|---|---|
src/blumeops/main.py |
publish() accepts optional registry_password |
.forgejo/workflows/build-container.yaml |
Passes API key to Dagger |
.forgejo/workflows/build-container-nix.yaml |
Passes API key to skopeo |
ansible/playbooks/indri.yml |
Pre_task fetches API key from 1Password |
ansible/roles/forgejo_actions_secrets/defaults/main.yml |
Secret entry for ZOT_CI_API_KEY |
Related
- harden-zot-registry — Parent goal
- register-zot-oidc-client — OIDC client registration