Skip to content

Container registry

Every Codebahn instance ships an OCI container registry at your instance host. Build an image in CI and push it to codebahn.net/<owner>/<image>, then pull it from a deploy target, a Kubernetes cluster, or another workflow. Images live on EU object storage, with no US vendor in the data path.

To publish images from CI, follow Publish container images. To pull them, follow Consume container images. This page is the reference.

Every image is private. There is no public or anonymous pull, on any plan. A pull always needs a credential that can read the owning user or org. This matches the rest of Codebahn: tenant data is never browsable without auth.

The registry is the most-used surface and the one we support directly. The same instance also exposes other package formats (npm, Maven, NuGet, RubyGems, and more) through Forgejo’s package API; those are available but best-effort. See the Forgejo packages docs for their usage.

PartValue
Registry hostcodebahn.net
Image pathcodebahn.net/<owner>/<image>
Ownera user or org you belong to

The host carries a dot, so Docker treats it as a registry rather than a Docker Hub shortname. codebahn.net/acme/api:1.4.0 is an org image; codebahn.net/alice/tool:latest is a user image.

In Codebahn CI, a job authenticates to its own owner’s registry with the built-in ${{ github.token }}, so there is nothing to create or store. It can push and pull its own owner’s images; a fork pull request gets neither. See Publish container images for the workflow.

Everywhere else (a workstation, an external CI system, a deploy target, or pushing across owners) log in with a username and a personal access token (PAT), not your password. Scope the token to what it needs:

TaskToken scope
Pullread:package
Pushwrite:package
Delete a versiondelete:package
Terminal window
echo "$CODEBAHN_TOKEN" | docker login codebahn.net -u "$USERNAME" --password-stdin

--password-stdin keeps the token out of your shell history and the process list. For an unattended consumer or publisher, use a dedicated machine user rather than a personal account; see Publish container images.

Image layers count against your plan’s storage quota, the same pool as repositories and LFS. See Limits for the caps.

Two things to know about how container storage is counted:

  • Layers are stored once but counted per reference. Object storage deduplicates identical layers by content hash, so pushing the same base layer to five tags stores it once. Quota counts each reference, so that layer counts five times against your quota. Reuse tags and prune old ones to keep the number down.
  • Untagged manifests are pruned automatically. A daily cleanup removes manifests and blobs left unreferenced for more than 24 hours, so overwriting :latest does not leak storage forever. You can also set per-owner cleanup rules in the package settings; see the Forgejo cleanup rules docs.

Blobs are stored on Scaleway Object Storage in the EU (fr-par), encrypted at rest. Pulls are served directly from object storage over a short-lived signed link after your credential is checked, so large images do not bottleneck on the instance. No image data leaves the EU, and no US vendor sits in the path.