You are viewing documentation for Cozystack next, which is currently in beta. For the latest stable version, see the v1.6 documentation.
Publishing a Repository
This guide is for publishers: developers who package applications and make them available to Cozystack clusters. It covers scaffolding a repository, validating it offline, pushing it as an OCI artifact, and, optionally, listing it in the community index.
For the operator side (connecting a published repository to a cluster), see Connecting a Repository.
Prerequisites
- The
cozypkgCLI; see Install cozypkg. - The
fluxCLI, whichcozypkg pushuses to build and push the OCI artifact. git, and a checkout with anoriginremote, if you wantpushto record the artifact’s provenance for you. See Push for the alternative.- Access to an OCI registry you can push to (for example GitHub Container Registry).
helmon yourPATHif you want--helm-lintto runhelm linton the charts.cosignon yourPATHif you use--require-signature; validation stops without it.
Scaffold a repository
cozypkg init writes a complete repository skeleton that passes validation as-is:
cozypkg init --app hello --name acme.hello ./hello-repo
--appis the RFC-1123 name of the sample application component (defaultmyapp).--nameis thePackageSourcename (defaults toexample.<app>).
PackageSource name must be a valid Kubernetes object name (lowercase, no underscores), and it must not start with a reserved prefix: cozystack. is the platform’s own namespace and community. is reserved, so cozypkg init and cozypkg validate both refuse those two prefixes. The Kubernetes-name rule is yours to keep: neither command checks it, so a name carrying an underscore or a capital gets all the way to the cluster before the apiserver turns it down. Beyond that the name is yours to choose; use your organization as a prefix, for example acme.hello. The real anti-shadowing boundary is on the cluster: a tapped repository keeps its declared name, and a clash with a core component is rejected at connect time (see
Connecting a Repository).Repository layout
The scaffold produces the layout that validation and the platform expect:
packages/
core/platform/sources/hello.yaml # PackageSource: variants and components
apps/hello/ # application Helm chart
Chart.yaml
values.yaml
templates/configmap.yaml
system/hello-rd/ # ApplicationDefinition registration
Chart.yaml
templates/cozyrd.yaml
cozyrds/hello.yaml
README.md
The PackageSource ties the two components together:
apiVersion: cozystack.io/v1alpha1
kind: PackageSource
metadata:
name: acme.hello
spec:
sourceRef:
kind: OCIRepository
name: hello-packages
namespace: cozy-system
path: /
variants:
- name: default
components:
- name: hello
path: apps/hello
- name: hello-rd
path: system/hello-rd
install:
namespace: cozy-system
packages/apps/hellois the application chart that templates the user-facing resources.packages/system/hello-rdis a paired chart whosecozyrds/asset carries theApplicationDefinitionthat registers the application in the API and dashboard. ItschartRefnames the app component’s assembled artifact by its concrete name.
Replace the placeholder chart in packages/apps/hello/templates/ with your application’s real resources, and add more components or variants to the PackageSource as needed.
Validate
cozypkg validate lints a repository the same way publication would, without touching a cluster. Run it against a local checkout:
cozypkg validate ./hello-repo
Validation decodes every PackageSource and ApplicationDefinition, resolves each component and library path to a chart directory, checks that each ApplicationDefinition chart reference matches a component, resolves dependsOn entries, and flags privileged components.
Useful flags:
--helm-lintadditionally runshelm linton every component chart (requires thehelmbinary).--known-source <name>allows adependsOnentry to reference aPackageSourcethat lives outside this repository (repeatable).--require-signature, with--certificate-identityand--certificate-oidc-issuer, verifies a keyless cosign signature on a publishedoci://artifact. This is what the community index gate runs; see The community index.
You can also validate an already-published artifact by passing an oci:// reference instead of a path; cozypkg pulls it with the flux CLI first.
Push
cozypkg push bundles the repository’s packages/ tree into a single versioned OCI artifact, the same artifact shape the platform and cozypkg tap consume. The repository is validated first (unless you pass --skip-validate), so a validation error aborts the push before anything is published:
cozypkg push oci://ghcr.io/acme/hello:v1.0.0 --path ./hello-repo
The source URL and revision recorded in the artifact come from git: the origin remote and git describe of the directory being pushed. cozypkg init writes files and stops there, so a freshly scaffolded directory has neither, and push refuses rather than publish an artifact with no provenance. Either commit the scaffold and give it an origin remote, or pass --source and --revision yourself:
cozypkg push oci://ghcr.io/acme/hello:v1.0.0 --path ./hello-repo \
--source https://github.com/acme/hello \
--revision v1.0.0
Mind the case in between: git searches upwards, so a scaffold sitting inside an unrelated checkout picks up that repository’s remote and revision and records them as this artifact’s provenance. Pass --reproducible for deterministic artifact metadata.
The community index
The community index is a standalone repository (cozystack/packages-index) that lets operators discover published repositories with cozypkg search. It is planned: the repository is not published yet, and today only the scaffold under hack/packages-index/ ships. It is metadata only: it records where packages live and who owns them. Artifacts stay in ordinary OCI registries; nothing is hosted in the index.
To list a repository, add one metadata file under entries/:
name: acme.hello
ociRef: oci://ghcr.io/acme/hello
version: v1.0.0
description: A friendly sample application
maintainer: Acme <maintainers@example.com>
homepage: https://example.com/hello
tags:
- sample
signing:
identity: https://github.com/acme/hello/.github/workflows/release.yaml@refs/heads/main
issuer: https://token.actions.githubusercontent.com
Leave the tag off ociRef. Both the index gate and a short-name cozypkg tap build the reference as <ociRef>:<version>, so a tag baked into ociRef yields one carrying two of them, and nothing resolves it.
Two-lane merge policy
Following the model of krew-index, submissions take one of two lanes:
- Auto lane. A change that leaves the security-relevant fields untouched (
ociRef,maintainer, andsigning.identity/signing.issuer) auto-merges once the new artifact validates and is signed by the entry’s recorded cosign identity. A routineversion,description,homepage, ortagsedit takes this lane, keeping the “new release of a listed package” path fast. - Review lane. A new entry, or any change to
ociRef,maintainer, orsigning, is security-relevant and requires maintainer review before merge.
Signing
Cosign verification is mandatory on the index gate for both lanes. The trust anchor is the entry’s recorded signing.identity, so a version bump fails if the new artifact is not signed by the originally approved identity. Sign your artifacts with keyless cosign from your release workflow, and record the workflow identity and OIDC issuer in the entry’s signing block.