blumeops/docs/zk/zot.md
Erich Blume b8104d75ad Move zk cards to docs/zk/ for documentation restructuring (#84)
## Summary
- Move all existing zettelkasten cards from `docs/` to `docs/zk/` as a temporary holding area
- Update `zk-docs` mise task to look in the new location
- Add `docs/README.md` explaining the Diataxis-based restructuring plan and target audiences

## Context
This is phase 1 of a multi-phase documentation restructuring effort. The goal is to reorganize docs to follow the Diataxis framework while serving multiple audiences:
1. Erich (owner) - knowledge graph/zk
2. Claude/AI agents - memory and context enrichment
3. New external readers - high-level overview
4. Potential operators/contributors - onboarding
5. Replicators - people wanting to duplicate the approach

## Testing
- [x] Verified `mise run zk-docs` still works with the new path
- [x] Updated obsidian.nvim config (in ~/.config/nvim) to point to new path

## Note
The obsidian.nvim config change is outside this repo but was made as part of this work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/84
2026-02-03 09:13:50 -08:00

3.4 KiB

id aliases tags
zot
zot
container-registry
blumeops

Zot Registry Management Log

Zot is an OCI-native container registry running on Indri, providing:

  1. Pull-through cache for Docker Hub, GHCR, Quay (avoids rate limits)
  2. Private image storage for custom-built containers

Service Details

  • URL: https://registry.ops.eblu.me
  • Local port: 5050
  • Data directory: ~/zot
  • Config: ~/.config/zot/config.json
  • Managed via: mcquack LaunchAgent

Namespace Convention

Path Source
registry.../docker.io/* Cached from Docker Hub
registry.../ghcr.io/* Cached from GHCR
registry.../quay.io/* Cached from Quay
registry.../blumeops/* Private images (yours)

How It Works

Pull-Through Cache (Automatic)

When minikube pulls an image like docker.io/library/nginx:latest:

  1. Containerd checks zot first (via host.minikube.internal:5050)
  2. If zot has it cached, returns immediately
  3. If not, zot fetches from upstream, caches it, returns to k8s

Cached images appear under their original registry path (e.g., docker.io/library/nginx).

Private Images (Manual Push)

Build and push from gilbert using podman:

# Build
podman build -t registry.ops.eblu.me/blumeops/myapp:v1 .

# Push to zot
podman push registry.ops.eblu.me/blumeops/myapp:v1

# Use in k8s manifest
image: registry.ops.eblu.me/blumeops/myapp:v1

Private images go under blumeops/* namespace. Example: the devpi container is at registry.ops.eblu.me/blumeops/devpi:latest.

Security Model

Network access only - no authentication configured. Anyone who can reach zot via Tailscale ACL can push/pull any image. Defense is the tailnet boundary.

Zot supports htpasswd/LDAP/OIDC auth if needed in the future.

Minikube Integration

The minikube cluster uses zot as a registry mirror via containerd configuration. Managed by the ansible minikube role.

From inside minikube, zot is at host.minikube.internal:5050. Containerd tries the mirror first, falls back to upstream if not cached.

Mirrors configured for: registry.ops.eblu.me, docker.io, ghcr.io, quay.io

Useful Commands

# List all cached/pushed images
curl -s http://indri:5050/v2/_catalog | jq

# List tags for an image
curl -s http://indri:5050/v2/blumeops/devpi/tags/list | jq

# Check service status
ssh indri 'launchctl list | grep zot'

# View logs
ssh indri 'tail -f ~/Library/Logs/mcquack.zot.err.log'

Log

2026-01-25

  • Migrated from Tailscale serve to Caddy - now accessible at registry.ops.eblu.me
  • Retired tailscale_serve ansible role (no longer needed)
  • Updated minikube containerd config to use new URL
  • Updated CI workflows and mise tasks
  • Old URL (registry.tail8d86e.ts.net) deprecated

2026-01-21

  • Verified full workflow: podman build on gilbert → push to zot → k8s pull
  • Documented security model (network-only auth via Tailscale ACL)
  • Updated minikube integration: now uses containerd (docker driver) instead of CRI-O (podman driver)
  • Mirror endpoint changed from host.containers.internal:5050 to host.minikube.internal:5050

2026-01-19

  • Integrated with minikube as CRI-O registry mirror
  • All k8s image pulls now go through zot cache automatically

2026-01-18

  • Initial setup for k8s migration Phase 0
  • Configured pull-through cache for Docker Hub, GHCR, Quay
  • Exposed via Tailscale service at registry.tail8d86e.ts.net