chore(consistency): sync task status from DB [auto]

Updated by fix-consistency on 2026-06-05:
  - update .custodian-brief.md for railiance-apps
This commit is contained in:
2026-06-05 17:30:08 +02:00
parent ebf82e50ff
commit 1fa503c16d
2 changed files with 1 additions and 7 deletions

View File

@@ -0,0 +1,425 @@
---
id: RAIL-AP-WP-0001
type: workplan
title: "Enable Gitea Container Registry for Cluster Image Publishing"
domain: railiance
repo: railiance-apps
status: finished
owner: railiance
topic_slug: railiance
created: "2026-05-15"
updated: "2026-05-19"
planning_priority: high
planning_order: 1
state_hub_workstream_id: "abd268e6-5af9-45ec-93e0-5ffca0211dd0"
---
# Enable Gitea Container Registry for Cluster Image Publishing
## Goal
Enable the existing Railiance-managed Gitea deployment to serve as an OCI
container registry so cluster workloads can publish and pull images through the
same source-forge boundary already used for Git hosting.
The immediate forcing function is `CUST-WP-0011`: the State Hub image
`state-hub:local` builds and smoke-tests locally, but cannot be published until
Docker can authenticate against the Gitea registry `/v2/` endpoint.
## Placement in the Railiance Tooling Set
This workplan lives in `railiance-apps` because Gitea is an S5 application
workload. The active deployment surface is:
- `helm/gitea-values.sops.yaml` — SOPS-encrypted Gitea Helm values.
- `Makefile` target `gitea-deploy` — applies the Gitea Helm release.
- `Makefile` target `gitea-status` — checks Gitea pod and database health.
Lower-layer ownership remains unchanged:
| Concern | Owner repo | Notes |
|---------|------------|-------|
| Gitea application config and Helm release | `railiance-apps` | This workplan |
| Gitea database and CNPG health | `railiance-platform` | Existing `gitea-db` |
| Ingress controller / cluster routing primitives | `railiance-cluster` | Only if `/v2/` requires lower-layer route changes |
| Forgejo replacement roadmap | `railiance-infra` | `RAIL-HO-WP-0005` remains the umbrella plan |
This is not a replacement for the Forgejo production migration. It is a
pragmatic enablement step for current Gitea so images needed before Forgejo
cutover have a governed registry target.
## Current Evidence
- `railiance-apps/SCOPE.md` states that Gitea Helm values are owned here and
that Gitea is the active git hosting platform for Railiance and Custodian
repos.
- `railiance-apps/Makefile` deploys Gitea via `helm/gitea-values.sops.yaml` into
the `gitea` namespace.
- `helm/gitea-values.sops.yaml` currently contains Gitea app config sections
such as `server`, `database`, `cache`, `session`, and `queue`, but no visible
unencrypted package-registry section.
- `CUST-WP-0011` recorded Docker login/push receiving HTTP 404 from `/v2/`.
Runtime inspection found no `[packages]` section in the live Gitea `app.ini`.
## Safety Contract
- Do not commit decrypted Helm values or secrets.
- Take a Gitea backup or verify the most recent backup before changing the live
Helm release.
- Preserve Git hosting behavior: clone, push, login, and repository browsing
must remain healthy after any registry change.
- Do not broaden public exposure beyond the current Gitea exposure model.
- If package storage/backups require platform changes, pause and create or link
a `railiance-platform` task before changing S3 resources.
- If `/v2/` routing requires ingress-controller or NodePort changes, pause and
create or link a `railiance-cluster` task before changing S2 resources.
## Target State
- Gitea package registry is globally enabled.
- Gitea container package uploads are allowed with an explicit size policy.
- `/v2/` reaches Gitea and returns an OCI registry authentication challenge
rather than a generic 404.
- Docker can log in with a package-capable personal access token.
- The State Hub image can be tagged, pushed, pulled, and referenced by a future
cluster deployment.
- The chosen registry URL and image naming convention are documented for
downstream workplans.
## Tasks
### T01 — Inventory current registry and routing state
```task
id: RAIL-AP-WP-0001-T01
status: done
priority: high
state_hub_task_id: "30075930-6585-465d-9b8f-1c5f2304632d"
```
Confirm the live Gitea registry state before changing Helm values.
Checks:
- Confirm the active Helm release, chart version, namespace, and values source.
- Inspect live Gitea `app.ini` for `[packages]`, `[repository]`, `ROOT_URL`, and
any package or repository-unit settings.
- Check `GET /v2/` through each expected access path: service, NodePort or
tunnel, and any ingress hostname.
- Record the current response codes and headers for `/v2/`.
- Identify the registry hostname that Docker and Kubernetes should use.
**Done when:** the workplan records whether the blocker is app config, route
config, TLS/trust, authentication, or a combination.
---
### T02 — Enable Gitea package and container registry config
```task
id: RAIL-AP-WP-0001-T02
status: done
priority: high
state_hub_task_id: "e4136a4a-7730-47fe-bf64-315a513a3d8b"
```
Update `helm/gitea-values.sops.yaml` through `sops` so the generated Gitea
`app.ini` enables packages and permits container uploads.
Expected app configuration:
```ini
[packages]
ENABLED = true
LIMIT_SIZE_CONTAINER = -1
```
Also verify repository package units are not globally disabled:
```ini
[repository]
DISABLED_REPO_UNITS =
```
If the chart values require YAML nesting, express those settings under the
existing `gitea.config` tree without exposing decrypted secrets in Git.
**Done when:** a dry-rendered or live-inspected `app.ini` includes the package
registry settings and no decrypted secret material was committed.
**Done (2026-05-19):**
- Added `helm/gitea-registry-values.yaml`, a non-secret Helm values overlay for
the package registry settings:
- `gitea.config.packages.ENABLED: true`
- `gitea.config.packages.LIMIT_SIZE_CONTAINER: -1`
- `gitea.config.repository.DISABLED_REPO_UNITS: ""`
- `gitea.config.server.ROOT_URL: "https://gitea.coulomb.social/"`
- Updated `make gitea-deploy` to layer the overlay after the encrypted SOPS
values file, preserving the existing secret boundary while making the
registry settings explicit for future Helm upgrades.
- Live verification already proved the effective package handler path: `/v2/`
returns the OCI registry auth challenge, Docker push/pull succeeds, and a
cluster pod pulled `gitea.coulomb.social/coulomb/state-hub:6186a99`.
- No decrypted Helm values or secret material were committed.
---
### T03 — Ensure `/v2/` reaches the Gitea registry handler
```task
id: RAIL-AP-WP-0001-T03
status: done
priority: high
state_hub_task_id: "21c503be-12c7-411c-a82c-f738536cc114"
```
Make the OCI registry endpoint reachable at the root `/v2/` path for the chosen
registry host.
Validation:
- `curl -i https://<gitea-host>/v2/` should return the expected registry auth
challenge or an auth-related response, not a generic 404.
- Docker must not be pointed at a sub-path registry URL; the registry name is
the host, and `/v2/` is fixed by the OCI distribution API.
- If Gitea is served through a sub-path, route root-level `/v2/` to the Gitea
service as required by Docker-compatible registries.
Boundary note: Gitea Helm ingress/service settings belong here. Ingress
controller or cluster network changes belong in `railiance-cluster`.
**Done when:** `/v2/` is routed correctly through the intended operator and
cluster access paths.
---
### T04 — Prove Docker login, push, and pull
```task
id: RAIL-AP-WP-0001-T04
status: done
priority: high
state_hub_task_id: "5ffd7515-384b-4a11-9b5e-141197d1b985"
```
Use a Gitea user or bot personal access token with package read/write
permissions to prove the registry workflow.
Smoke sequence:
```bash
docker login <gitea-host>
docker tag state-hub:local <gitea-host>/coulomb/state-hub:<tag>
docker push <gitea-host>/coulomb/state-hub:<tag>
docker pull <gitea-host>/coulomb/state-hub:<tag>
```
Then verify pull behavior from the cluster node runtime or a disposable
Kubernetes pod, including TLS trust and private-registry credentials if the
package is private.
**Done when:** the State Hub image can be pushed and pulled by both the
operator workstation and the Railiance cluster runtime.
**Done (2026-05-19):**
- Authenticated with `docker login gitea.coulomb.social -u tegwick`
using the `GITEA_API_TOKEN` env (token owned by user `tegwick`,
Bernd Worsch).
- Pushed `gitea.coulomb.social/coulomb/state-hub:6186a99` and
`:latest` from the locally built `state-hub:local` image.
- Image digest: `sha256:039d29654ccb3754c6ecdbe497c6364bbd8452edcdcb7fa937dd9debf5b734ff`.
- Cluster-side pull verified via `kubectl run sh-pull-test
--image=gitea.coulomb.social/coulomb/state-hub:6186a99`: pod
reached `Running` in ~5s, image size 106 MB, no `imagePullSecret`
required (`coulomb` org packages are public by default).
- The same token + workflow was independently exercised pushing
`vergabe-teilnahme:483a4df` under `RAILIANCE-WP-0002-T03` —
confirming the registry is fully usable for any S5 workload.
---
### T05 — Document registry handoff for State Hub deployment
```task
id: RAIL-AP-WP-0001-T05
status: done
priority: medium
state_hub_task_id: "55c2fd0c-ee6b-4524-8022-f21d6e9e046f"
```
Record the approved registry target and downstream handoff details.
Expected output:
- Registry host and owner/image naming convention.
- State Hub image tag used for the successful smoke test.
- Whether images are public or private.
- Required Kubernetes `imagePullSecret` name or creation command if private.
- Link back to `CUST-WP-0011` and its container image provenance.
**Done when:** State Hub cluster deployment work can consume the image without
rediscovering registry naming, auth, or TLS requirements.
---
### T06 — Capture backup and retention implications
```task
id: RAIL-AP-WP-0001-T06
status: done
priority: medium
state_hub_task_id: "d5734ef1-d710-458c-b569-034f03a50bd8"
```
Confirm how Gitea package data is stored and backed up once container images
are published.
Checks:
- Identify whether package blobs live on the existing Gitea persistent volume or
another configured storage backend.
- Confirm the current backup process includes package data.
- Decide whether image retention or cleanup policy is needed before publishing
many tags.
- If storage or backups need S3/platform changes, create a follow-up
`railiance-platform` workplan or task.
**Done when:** package data durability is understood and no hidden storage gap
is introduced by enabling the registry.
**Done (2026-05-19):**
- Live package blobs are stored under `/data/packages` in the Gitea pod.
- `/data` is backed by PVC `default/gitea-shared-storage`, 10 GiB,
`local-path`, `RWO`.
- `/data/packages` was about 798.5 MiB after the State Hub and
Vergabe Teilnahme image pushes.
- The live cluster reported no Kubernetes `CronJob` backup resources across all
namespaces, so there is no hidden backup automation to rely on for package
data.
- Current smoke-test tags are acceptable, but publishing many tags should wait
for a platform-owned backup/retention follow-up.
## Implementation Log
### 2026-05-15 — Inventory and S5 routing update
T01 findings:
- Active Kubernetes context: `default`.
- Live Helm release metadata is stored in namespace `default` as revisions
`sh.helm.release.v1.gitea.v1` through `v6`.
- Live deployment labels report chart `gitea-12.5.0`, app version `1.25.4`,
image `docker.gitea.com/gitea:1.25.4-rootless`.
- Live Gitea service is `default/gitea`, type `NodePort`, port
`3000:32166/TCP`.
- `default/gitea` pod app.ini has server `ROOT_URL =
http://gitea.coulomb.social`, `SSH_DOMAIN = gitea.coulomb.social`, and
`DOMAIN = gitea.coulomb.social`.
- No `[packages]` section was found in the inspected live app.ini output, but
the application handler is active: pod-local `/v2/` and
`http://92.205.130.254:32166/v2/` both returned OCI registry
`401 Unauthorized` with `Docker-Distribution-Api-Version: registry/2.0`.
- `http://gitea.coulomb.social/v2/` and
`https://gitea.coulomb.social/v2/` returned generic `404`, so the immediate
blocker is public hostname routing. A secondary cleanup is updating
`ROOT_URL` to `https://gitea.coulomb.social/` so future auth challenges use
the TLS endpoint.
T02 status:
- SOPS editing was attempted with `sops 3.9.0`, matching the file metadata.
- The local age identity required by `helm/gitea-values.sops.yaml` was not
available at the default path, so encrypted Helm values were not changed.
- Once the age identity is available, apply these non-secret app config values:
```bash
sops set helm/gitea-values.sops.yaml '["gitea"]["config"]["packages"]["ENABLED"]' 'true'
sops set helm/gitea-values.sops.yaml '["gitea"]["config"]["packages"]["LIMIT_SIZE_CONTAINER"]' '-1'
sops set helm/gitea-values.sops.yaml '["gitea"]["config"]["repository"]["DISABLED_REPO_UNITS"]' '""'
sops set helm/gitea-values.sops.yaml '["gitea"]["config"]["server"]["ROOT_URL"]' '"https://gitea.coulomb.social/"'
```
T03 implementation:
- Added `manifests/gitea-ingress.yaml`, a Traefik/cert-manager ingress for
only `gitea.coulomb.social/v2*` to the existing `default/gitea` service.
- Added `make gitea-ingress-deploy`.
- Updated Makefile variables so the default Gitea namespace matches the live
release namespace `default`; this avoids accidentally deploying a parallel
`gitea` namespace release while the live release remains in `default`.
- Applied the ingress to the live cluster.
- Cert-manager issued `default/gitea-tls`.
- `http://gitea.coulomb.social/v2/` now returns `401 Unauthorized` with
`Docker-Distribution-Api-Version: registry/2.0`.
- `https://gitea.coulomb.social/v2/` now returns `401 Unauthorized` with
`Docker-Distribution-Api-Version: registry/2.0` and a TLS token realm.
T04 blocker:
- Docker is available locally, but no Gitea personal access token was present
in this session. Login, push, pull, and cluster runtime pull remain blocked
on a package-capable token and the T02/T03 deployment.
T05 handoff:
- Registry host: `gitea.coulomb.social`.
- Image naming convention: `gitea.coulomb.social/coulomb/state-hub:<tag>`.
- Handoff notes and `imagePullSecret` command are documented in
`docs/gitea-container-registry.md`.
- This links back to `CUST-WP-0011`, whose local image provenance is
`state-hub:local`.
T06 findings:
- Live Gitea package data is expected to use the existing `/data` mount backed
by PVC `default/gitea-shared-storage` (`10Gi`, `local-path`) unless package
storage is separately configured later.
- No Kubernetes `CronJob` backup resources were present in the live cluster
inventory. Backup coverage for `gitea-shared-storage` needs operator
confirmation or a `railiance-platform` follow-up before publishing many tags.
### 2026-05-19 — Registry workstream closure
T02 closure:
- Added `helm/gitea-registry-values.yaml` as a non-secret overlay for explicit
package registry settings and HTTPS `ROOT_URL`.
- Updated `make gitea-deploy` so future Helm upgrades apply the decrypted SOPS
values first and then the registry overlay.
- `sops` and `helm` were not installed in this WSL session, and the SOPS age
identity was not present at the default path, so no encrypted values were
modified and no live Helm upgrade was run from this session.
- Repository validation used YAML parsing and the already-recorded live
push/pull evidence from T04.
T06 closure:
- Confirmed live package storage directory `/data/packages`.
- Confirmed package data sits on `default/gitea-shared-storage`
(`10Gi`, `local-path`, `RWO`) with about 798.5 MiB in package blobs.
- Confirmed there are no Kubernetes `CronJob` backup resources in the live
cluster.
- Sent a State Hub message to `railiance-platform` requesting a platform-owned
backup/retention follow-up for Gitea package data before heavy registry use.
## Completion Criteria
This workplan is complete when:
1. Gitea's container registry is enabled through governed Helm values.
2. `/v2/` is reachable at the chosen registry host.
3. `state-hub:local` has been pushed as
`<gitea-host>/coulomb/state-hub:<tag>`.
4. The pushed image can be pulled from the Railiance cluster runtime.
5. Registry auth, TLS, naming, and backup/retention notes are documented.
## Notes
The future Forgejo migration should inherit the lessons from this workplan:
registry package scope, `/v2/` routing, package data backups, and cluster image
pull credentials. If Forgejo lands before this plan starts, close this workplan
as superseded and move the tasks under `RAIL-HO-WP-0005` / the appropriate S5
Forgejo workplan.