When minikube pulls an image, containerd checks zot first. If cached, returns immediately. If not, zot fetches from upstream, caches it, then returns.
Security Model
OIDC authentication via authentik, with API key support for CI. Three-tier access control:
Role
Permissions
Use case
Anonymous
read
Pull images without auth
artifact-workloads group
read, create
CI push (new tags only, no overwrite/delete)
admins group
read, create, update, delete
Break-glass admin access
CI authenticates with a zot API key generated from the zot-ci service account’s OIDC session. The key is stored in the Forgejo Secrets 1Password item (field zot-ci-api) and synced to Forgejo Actions secrets via ansible.
API Key Rotation
The zot-ci API key expires every 90 days. To rotate:
In Authentik admin UI, impersonate the zot-ci user
Visit https://registry.ops.eblu.me — you’ll land on the login page
Click “SIGN IN WITH OIDC” to authenticate as zot-ci
Navigate to https://registry.ops.eblu.me/user/apikey
Generate a new API key, copy it to clipboard
Update 1Password:
set -l NEWKEY (pbpaste); op item edit "Forgejo Secrets" --vault blumeops "zot-ci-api[password]=$NEWKEY"; set -e NEWKEY
The value is briefly visible to other ps-readers on this machine (single-user mac, acceptable tradeoff). The older pbpaste | op item edit ... "field[password]=-" stdin syntax was rejected by op 2.34 as “invalid JSON” — recent op versions treat piped input as a full JSON template.
Sync to Forgejo: mise run provision-indri -- --tags forgejo_actions_secrets