16 KiB
id, type, title, domain, repo, status, owner, topic_slug, created, updated, planning_priority, planning_order, state_hub_workstream_id
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | planning_priority | planning_order | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| RAIL-AP-WP-0001 | workplan | Enable Gitea Container Registry for Cluster Image Publishing | railiance | railiance-apps | archived | railiance | railiance | 2026-05-15 | 2026-06-05 | high | 1 | 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.Makefiletargetgitea-deploy— applies the Gitea Helm release.Makefiletargetgitea-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.mdstates that Gitea Helm values are owned here and that Gitea is the active git hosting platform for Railiance and Custodian repos.railiance-apps/Makefiledeploys Gitea viahelm/gitea-values.sops.yamlinto thegiteanamespace.helm/gitea-values.sops.yamlcurrently contains Gitea app config sections such asserver,database,cache,session, andqueue, but no visible unencrypted package-registry section.CUST-WP-0011recorded Docker login/push receiving HTTP 404 from/v2/. Runtime inspection found no[packages]section in the live Giteaapp.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-platformtask before changing S3 resources. - If
/v2/routing requires ingress-controller or NodePort changes, pause and create or link arailiance-clustertask 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
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.inifor[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
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:
[packages]
ENABLED = true
LIMIT_SIZE_CONTAINER = -1
Also verify repository package units are not globally disabled:
[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: truegitea.config.packages.LIMIT_SIZE_CONTAINER: -1gitea.config.repository.DISABLED_REPO_UNITS: ""gitea.config.server.ROOT_URL: "https://gitea.coulomb.social/"
- Updated
make gitea-deployto 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 pulledgitea.coulomb.social/coulomb/state-hub:6186a99. - No decrypted Helm values or secret material were committed.
T03 — Ensure /v2/ reaches the Gitea registry handler
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
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:
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 tegwickusing theGITEA_API_TOKENenv (token owned by usertegwick, Bernd Worsch). - Pushed
gitea.coulomb.social/coulomb/state-hub:6186a99and:latestfrom the locally builtstate-hub:localimage. - Image digest:
sha256:039d29654ccb3754c6ecdbe497c6364bbd8452edcdcb7fa937dd9debf5b734ff. - Cluster-side pull verified via
kubectl run sh-pull-test --image=gitea.coulomb.social/coulomb/state-hub:6186a99: pod reachedRunningin ~5s, image size 106 MB, noimagePullSecretrequired (coulomborg packages are public by default). - The same token + workflow was independently exercised pushing
vergabe-teilnahme:483a4dfunderRAILIANCE-WP-0002-T03— confirming the registry is fully usable for any S5 workload.
T05 — Document registry handoff for State Hub deployment
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
imagePullSecretname or creation command if private. - Link back to
CUST-WP-0011and 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
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-platformworkplan 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/packagesin the Gitea pod. /datais backed by PVCdefault/gitea-shared-storage, 10 GiB,local-path,RWO./data/packageswas about 798.5 MiB after the State Hub and Vergabe Teilnahme image pushes.- The live cluster reported no Kubernetes
CronJobbackup 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
defaultas revisionssh.helm.release.v1.gitea.v1throughv6. - Live deployment labels report chart
gitea-12.5.0, app version1.25.4, imagedocker.gitea.com/gitea:1.25.4-rootless. - Live Gitea service is
default/gitea, typeNodePort, port3000:32166/TCP. default/giteapod app.ini has serverROOT_URL = http://gitea.coulomb.social,SSH_DOMAIN = gitea.coulomb.social, andDOMAIN = gitea.coulomb.social.- No
[packages]section was found in the inspected live app.ini output, but the application handler is active: pod-local/v2/andhttp://92.205.130.254:32166/v2/both returned OCI registry401 UnauthorizedwithDocker-Distribution-Api-Version: registry/2.0. http://gitea.coulomb.social/v2/andhttps://gitea.coulomb.social/v2/returned generic404, so the immediate blocker is public hostname routing. A secondary cleanup is updatingROOT_URLtohttps://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.yamlwas 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:
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 onlygitea.coulomb.social/v2*to the existingdefault/giteaservice. - Added
make gitea-ingress-deploy. - Updated Makefile variables so the default Gitea namespace matches the live
release namespace
default; this avoids accidentally deploying a parallelgiteanamespace release while the live release remains indefault. - Applied the ingress to the live cluster.
- Cert-manager issued
default/gitea-tls. http://gitea.coulomb.social/v2/now returns401 UnauthorizedwithDocker-Distribution-Api-Version: registry/2.0.https://gitea.coulomb.social/v2/now returns401 UnauthorizedwithDocker-Distribution-Api-Version: registry/2.0and 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
imagePullSecretcommand are documented indocs/gitea-container-registry.md. - This links back to
CUST-WP-0011, whose local image provenance isstate-hub:local.
T06 findings:
- Live Gitea package data is expected to use the existing
/datamount backed by PVCdefault/gitea-shared-storage(10Gi,local-path) unless package storage is separately configured later. - No Kubernetes
CronJobbackup resources were present in the live cluster inventory. Backup coverage forgitea-shared-storageneeds operator confirmation or arailiance-platformfollow-up before publishing many tags.
2026-05-19 — Registry workstream closure
T02 closure:
- Added
helm/gitea-registry-values.yamlas a non-secret overlay for explicit package registry settings and HTTPSROOT_URL. - Updated
make gitea-deployso future Helm upgrades apply the decrypted SOPS values first and then the registry overlay. sopsandhelmwere 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
CronJobbackup resources in the live cluster. - Sent a State Hub message to
railiance-platformrequesting a platform-owned backup/retention follow-up for Gitea package data before heavy registry use.
Completion Criteria
This workplan is complete when:
- Gitea's container registry is enabled through governed Helm values.
/v2/is reachable at the chosen registry host.state-hub:localhas been pushed as<gitea-host>/coulomb/state-hub:<tag>.- The pushed image can be pulled from the Railiance cluster runtime.
- 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.