6.6 KiB
id, type, title, domain, repo, status, owner, topic_slug, created, updated, capability_request_id, state_hub_workstream_id
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | capability_request_id | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|---|
| KEY-WP-0002 | workplan | KeyCape Container Image — Build & Publish to Gitea OCI Registry | netkingdom | key-cape | done | netkingdom | netkingdom | 2026-03-22 | 2026-03-21 | c8843c7a-460a-47a2-b45a-b8d3940f9aa2 |
KEY-WP-0002 — KeyCape Container Image — Build & Publish to Gitea OCI Registry
Problem
KeyCape has a Dockerfile but no automated build pipeline and no published
image. Other services (k3s deployments, local dev) that need to run KeyCape
must build locally from source. There is no versioned artefact to reference
in Helm charts or manifests.
The capability request for this work was originally misrouted to railiance. It belongs here: KeyCape owns its own image.
Goal
Produce a versioned OCI image for KeyCape, published to the Gitea container
registry on CoulombCore (92.205.130.254:32166), triggered automatically on
every merge to main and on semver tags (v*).
Gitea OCI registry endpoint: 92.205.130.254:32166
Image name: 92.205.130.254:32166/coulomb/key-cape
Why Gitea, not GHCR? The net-kingdom cluster is self-hosted. Keeping images in Gitea (also self-hosted on CoulombCore) avoids any external registry dependency and keeps image pulls within the cluster network. GHCR is a future option once public distribution is needed.
Design
Image naming & tagging
| Trigger | Tags applied |
|---|---|
push to main |
latest, main-<short-sha> |
tag v1.2.3 |
1.2.3, 1.2, 1, latest |
Build
Multi-stage Dockerfile already present — no changes needed to the build itself. The image builds to a distroless static binary (~10 MB).
Registry auth
Gitea issues a personal access token (or machine account token) with
write:packages scope. Stored as Gitea Actions secret REGISTRY_TOKEN;
username stored as REGISTRY_USER.
For local make push, credentials are passed via docker login before
the push target runs.
Makefile targets
IMAGE_REGISTRY ?= 92.205.130.254:32166
IMAGE_REPO ?= coulomb/key-cape
IMAGE_TAG ?= latest
IMAGE := $(IMAGE_REGISTRY)/$(IMAGE_REPO):$(IMAGE_TAG)
image:
docker build -t $(IMAGE) .
push: image
docker push $(IMAGE)
image-tag:
docker tag $(IMAGE) $(IMAGE_REGISTRY)/$(IMAGE_REPO):$(IMAGE_TAG)
Gitea Actions workflow
.gitea/workflows/image.yaml — triggers on push to main and on v* tags:
- Checkout
- Set up Docker Buildx
- Login to
92.205.130.254:32166using secrets - Build and push with metadata-action tags
- (Optional) sign with cosign if available
k3s insecure registry
Gitea runs over plain HTTP on port 32166 (NodePort). k3s must be configured to treat this endpoint as an insecure registry so image pulls work from within the cluster:
# /etc/rancher/k3s/registries.yaml (on CoulombCore)
mirrors:
"92.205.130.254:32166":
endpoint:
- "http://92.205.130.254:32166"
k3s picks this up on restart (or SIGHUP). Worker nodes (if any) need the same file.
Tasks
T01 — Makefile: image, push, image-tag targets
id: KEY-WP-0002-T01
status: done
priority: high
state_hub_task_id: "749472fc-edb9-4948-9ebc-58d5f38327ee"
Add image, push, and image-tag targets to Makefile with
IMAGE_REGISTRY, IMAGE_REPO, IMAGE_TAG variables defaulting to the
Gitea endpoint and coulomb/key-cape:latest.
Gate: make image builds successfully locally; IMAGE_TAG=dev make image
produces a differently-tagged image.
T02 — Gitea Actions workflow
id: KEY-WP-0002-T02
status: done
priority: high
state_hub_task_id: "8ecf18cc-a3bb-4ede-a09c-fcd0d26d7f9d"
Create .gitea/workflows/image.yaml:
- Trigger:
pushtomain,pushtags matchingv* - Runner:
act_runnerlabel (orubuntu-latestif configured) - Steps: checkout → docker buildx → login → build+push
- Tags via
docker/metadata-action:lateston main, semver on tags
Secrets required (document in README.md under "CI"):
REGISTRY_USER— Gitea username or machine accountREGISTRY_TOKEN— Gitea personal access token withwrite:packages
Gate: workflow file is syntactically valid; documented in README.
T03 — k3s insecure registry config on CoulombCore
id: KEY-WP-0002-T03
status: done
priority: high
state_hub_task_id: "2dde67f9-944f-418d-a2e9-7367bc556425"
On CoulombCore, create/update /etc/rancher/k3s/registries.yaml to add
the Gitea NodePort as an HTTP mirror. Restart k3s (or send SIGHUP) and
verify crictl pull 92.205.130.254:32166/coulomb/key-cape:latest works.
Gate: image pull from within the cluster succeeds without TLS errors.
T04 — Create Gitea machine account & token
id: KEY-WP-0002-T04
status: done
priority: medium
state_hub_task_id: "25775e10-3164-4adb-9c41-835c86fde5f8"
In Gitea (http://92.205.130.254:32166), create a machine account
ci-netkingdom (or reuse an existing service account) with access to
the netkingdom organisation. Generate a token with write:packages
scope and store it in:
- Gitea Actions secrets on the
key-caperepo:REGISTRY_USER,REGISTRY_TOKEN - The net-kingdom credential store (SOPS-encrypted) under
credentials/gitea-ci-token.enc.yaml
Gate: docker login 92.205.130.254:32166 succeeds with the token;
secret is in the credential store.
T05 — Smoke test: push and pull a dev image
id: KEY-WP-0002-T05
status: done
priority: medium
state_hub_task_id: "0f6ab38f-6d34-41af-9180-f19c687947b5"
Manually trigger a build-and-push:
docker login 92.205.130.254:32166
IMAGE_TAG=dev make push
Then verify the image is pullable from CoulombCore:
# on CoulombCore
crictl pull 92.205.130.254:32166/coulomb/key-cape:dev
Gate: pull succeeds; image is listed in Gitea -> Packages -> coulomb/key-cape.
T06 — Update README with registry & CI docs
id: KEY-WP-0002-T06
status: done
priority: low
state_hub_task_id: "946cd34d-94da-4fa9-a781-ed36f6c827a3"
Add a "Container Image" section to README.md documenting:
- Registry URL and image name
- How to pull (
docker pull 92.205.130.254:32166/coulomb/key-cape:latest) - How to build and push locally (Makefile targets)
- CI secrets required for the Actions workflow
Gate: README section present and accurate.
Done Criteria
make imageandmake pushwork locally.gitea/workflows/image.yamlpresent and documented- k3s can pull the image from Gitea without TLS errors
- Machine account token stored in credential store
- Smoke test:
devimage pushed and pulled successfully - README updated