Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions content/en/docs/next/marketplace/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: "Application Marketplace"
linkTitle: "Marketplace"
description: "Extend the Cozystack application catalog with external repositories using the PackageSource model and the cozypkg CLI."
weight: 48
---

The Cozystack marketplace lets an administrator extend the built-in application catalog with applications published in external repositories. Once a repository is connected to a cluster, its applications appear in the same dashboard catalog and behave like the standard managed applications platform users already know.

A repository is a self-contained, versioned bundle published as an OCI artifact. It is authored and validated with the `cozypkg` CLI, connected to a cluster with a single command (or from the dashboard), and, optionally, listed in a community index so operators can discover it.

{{% note %}}

The marketplace is built on the `PackageSource` model, a different and newer mechanism than the Git-and-HelmRelease bootstrap described in [Adding External Applications]({{% ref "/docs/next/applications/external" %}}). The two can coexist on a cluster; new repositories should use the marketplace model.

{{% /note %}}

## How it works

A marketplace repository ships one or more `PackageSource` resources. Each `PackageSource` declares variants and components; a component is a Helm chart plus, for user-installable applications, an `ApplicationDefinition` that registers the application with the Cozystack API and dashboard.

The lifecycle has two sides:

- **Publishing** turns a repository into an OCI artifact: `cozypkg init` scaffolds it, `cozypkg validate` lints it offline, and `cozypkg push` bundles the `packages/` tree into a single versioned artifact in any OCI registry.
- **Connecting** registers that artifact on a cluster: `cozypkg tap` (or the dashboard) creates a Flux `OCIRepository` and materializes the repository's `PackageSource` resources. `cozypkg add` then installs individual applications from the connected repository, and they show up in the catalog.

## Key objects

| Object | Group | Role |
| --- | --- | --- |
| `PackageSource` | `cozystack.io/v1alpha1` | Declares a repository's variants and components. |
| `ApplicationDefinition` | `cozystack.io/v1alpha1` | Registers a component as a user-installable application in the API and dashboard. |
| `Tap` | `core.cozystack.io/v1alpha1` | Virtual resource backing the dashboard "Repositories" view: connect, list, and disconnect repositories. |
| `OCIRepository` | `source.toolkit.fluxcd.io/v1` | Flux source Cozystack creates for a connected repository's artifact. |

A connected repository keeps its own declared `PackageSource` name. If that name (or an application it registers) would collide with a core component, the connect is rejected, so an external package can never shadow an official one.

## Trust model

Connecting a third-party repository runs its charts in your management cluster, so connect only sources you trust.

Signature verification happens at **publication** time, not at connect time. `cozypkg tap` and the dashboard connect flow validate an artifact's structure but do not verify its cosign signature. The verification points are the community index CI gate, which pins each release to the entry's recorded cosign identity, and, optionally, Flux `OCIRepository` verification at pull time. See [Publishing a Repository]({{% ref "/docs/next/marketplace/publishing" %}}#the-community-index) for details.

## Where to go next

- [Publishing a Repository]({{% ref "/docs/next/marketplace/publishing" %}}): scaffold, validate, push, and list a repository in the community index.
- [Connecting a Repository]({{% ref "/docs/next/marketplace/connecting" %}}): discover, connect, install, and disconnect repositories on a cluster.
- [`cozypkg` Reference]({{% ref "/docs/next/marketplace/cozypkg" %}}): every command and flag.
104 changes: 104 additions & 0 deletions content/en/docs/next/marketplace/connecting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
title: "Connecting a Repository"
linkTitle: "Connecting"
description: "Discover, connect, install from, and disconnect external application repositories on a Cozystack cluster."
weight: 20
---

This guide is for **operators**: cluster administrators who connect external repositories and install their applications. It covers discovering repositories, connecting them from the CLI or the dashboard, installing applications, and disconnecting.

For the publisher side (packaging and pushing a repository), see [Publishing a Repository]({{% ref "/docs/next/marketplace/publishing" %}}).

## Prerequisites

- The `cozypkg` CLI and a kubeconfig for the target cluster. Creating cluster-scoped resources requires cluster-admin.
- Cozystack with the marketplace enabled on the management cluster.

{{% warning %}}

Connecting a repository runs its charts in your management cluster. Connect only sources you trust, or repositories listed in a curated index whose gate verifies signatures. See the [Trust model]({{% ref "/docs/next/marketplace" %}}#trust-model).

{{% /warning %}}

## Discover repositories

`cozypkg search` queries the community index and lists matching repositories without connecting them. Point it at an index with `--index` or the `COZYPKG_INDEX` environment variable (a local directory or an `oci://` reference):

```bash
export COZYPKG_INDEX=oci://ghcr.io/cozystack/packages-index:latest
cozypkg search database
```

## Connect from the CLI

`cozypkg tap` registers a published repository. It creates a Flux `OCIRepository` pointing at the artifact and materializes the `PackageSource` resources the artifact carries under their declared names. If a name (or an application it registers) would collide with a core component or another connected repository, the tap is rejected instead of overwriting it, so an external package cannot shadow an official one. Nothing is installed yet:

```bash
cozypkg tap oci://ghcr.io/acme/hello:v1.0.0
```

Tapping is idempotent. Use `--tag` to override the tag in the reference, and `--skip-validate` to skip validating the artifact structure before tapping (not recommended).

If the repository is listed in an index, you can tap it by its short name and let the index resolve the reference:

```bash
cozypkg tap acme.hello --index "$COZYPKG_INDEX"
```

### Private repositories

For a private registry, pre-create a pull-credential `Secret` in the `cozy-system` namespace and point the tap at it with `--secret`. Cozystack attaches it as the `OCIRepository`'s `secretRef`:

```bash
kubectl create secret docker-registry acme-pull \
--namespace cozy-system \
--docker-server=ghcr.io \
--docker-username=<user> \
--docker-password=<token>

cozypkg tap oci://ghcr.io/acme/hello:v1.0.0 --secret acme-pull
```

## Connect from the dashboard

The dashboard "Repositories" view is backed by the `Tap` resource and covers the same flow without the CLI. Open it from the sidebar, choose **Connect**, and provide the `oci://` reference and, for a private repository, the name of a pull-credential `Secret` in `cozy-system`. Connected repositories are listed with their status; a tapped repository still connecting or blocked by a name collision shows its message there, and tapped repositories can be disconnected from the same view.

## Install applications

Once a repository is connected, install an application from it with `cozypkg add`, naming the materialized `PackageSource`. A tapped repository keeps its own declared name, so run `cozypkg list` first to see the exact name to use:

```bash
cozypkg list
cozypkg add acme.hello
```

`cozypkg add` installs the `PackageSource` and its dependencies. If a component is privileged, it asks for confirmation first; pass `--allow-privileged` to install privileged components without the interactive prompt.

Installed applications appear in the dashboard catalog alongside the built-in ones, and platform users deploy them the same way.

## List what is connected and installed

`cozypkg list` shows connected `PackageSource` resources; `--installed` shows installed `Package` resources instead, and `--components` breaks components onto separate lines:

```bash
cozypkg list
cozypkg list --installed
```

## Disconnect

Disconnecting has two independent steps, mirroring the two connect steps.

Remove installed applications with `cozypkg del`. This deletes the `Package` and its resources but leaves the connected source in place:

```bash
cozypkg del acme.hello
```

Then remove the source itself with `cozypkg untap`. This deletes the tapped `PackageSource` (identified by its marketplace-tap marker, not a name prefix) and its Flux source, and refuses official sources. Already-installed `Package` resources are left untouched, so untap warns if any remain; pass `--yes` to untap anyway:

```bash
cozypkg untap acme.hello
```

From the dashboard, disconnecting a tapped repository in the "Repositories" view removes the `PackageSource` and its Flux source in one step; it does not remove already-installed applications.
156 changes: 156 additions & 0 deletions content/en/docs/next/marketplace/cozypkg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
title: "cozypkg Reference"
linkTitle: "cozypkg Reference"
description: "Command and flag reference for the cozypkg marketplace CLI."
weight: 30
---

`cozypkg` is the CLI for authoring, publishing, and managing Cozystack marketplace repositories. This page is a reference for its commands; for task-oriented walkthroughs see [Publishing a Repository]({{% ref "/docs/next/marketplace/publishing" %}}) and [Connecting a Repository]({{% ref "/docs/next/marketplace/connecting" %}}).

Commands that create or read cluster resources accept `--kubeconfig` and otherwise fall back to `~/.kube/config` or the `KUBECONFIG` environment variable. Creating cluster-scoped resources requires cluster-admin.

## Environment variables

- `COZYPKG_INDEX`: default index location for `search` and short-name `tap`. A local directory or an `oci://` reference. Overridden by `--index`.

## Authoring and publishing

### `cozypkg init [directory]`

Scaffold a new repository built around the `PackageSource` model: a `PackageSource` with one variant and a paired app / `-rd` component, ready to validate and push. The generated tree passes `cozypkg validate` as-is.

| Flag | Description |
| --- | --- |
| `--app <label>` | Name of the sample app/component, an RFC-1123 label (default `myapp`). |
| `--name <name>` | `PackageSource` name (defaults to `example.<app>`). Any name is allowed; a clash with a core component is caught at tap time, not here. |

```bash
cozypkg init --app hello --name acme.hello ./hello-repo
```

### `cozypkg validate <repository-path-or-oci-ref>`

Validate a repository offline, the same way publication would, without installing anything. Decodes every `PackageSource` and `ApplicationDefinition`, resolves component and library paths to charts, checks that chart references match a component, resolves `dependsOn`, and flags privileged components. Accepts a local path or an `oci://` reference (pulled with the `flux` CLI first).

| Flag | Description |
| --- | --- |
| `--helm-lint` | Run `helm lint` on every component chart (requires the `helm` binary). |
| `--known-source <name>` | `PackageSource` name that `dependsOn` entries may reference without being defined in the repository (repeatable). |
| `--require-signature` | Require a valid keyless cosign signature on the OCI artifact (needs the `cosign` binary and an `oci://` reference). |
| `--certificate-identity <id>` | Expected cosign certificate identity for `--require-signature`. |
| `--certificate-oidc-issuer <url>` | Expected cosign certificate OIDC issuer for `--require-signature`. |

```bash
cozypkg validate ./hello-repo --helm-lint
```

### `cozypkg push <oci-ref>`

Validate the repository and push its `packages/` tree as a single versioned OCI artifact using the `flux` CLI, the same artifact shape the platform and `cozypkg tap` consume. Source URL and revision are derived from git when not given.

| Flag | Description |
| --- | --- |
| `--path <dir>` | Path to the repository root, which must contain `packages/` (default `.`). |
| `--source <url>` | Source URL recorded in the artifact (defaults to the git origin remote). |
| `--revision <rev>` | Revision recorded in the artifact (defaults to `git describe:sha`). |
| `--reproducible` | Pass `--reproducible` to `flux` for deterministic artifact metadata. |
| `--helm-lint` | Also run `helm lint` during pre-push validation. |
| `--skip-validate` | Skip pre-push validation (not recommended). |

```bash
cozypkg push oci://ghcr.io/acme/hello:v1.0.0 --path ./hello-repo
```

## Discovery and connection

### `cozypkg search [term]`

Search the community package index and list matching repositories without connecting them.

| Flag | Description |
| --- | --- |
| `--index <location>` | Index location: a local directory or an `oci://` reference (defaults to `COZYPKG_INDEX`). |

```bash
cozypkg search database --index oci://ghcr.io/cozystack/packages-index:latest
```

### `cozypkg tap <oci-ref>`

Register an external repository: create a Flux `OCIRepository` for the artifact and materialize the `PackageSource` resources it carries under their declared names. A name that collides with a core component (or another tap) is rejected rather than overwritten. Nothing is installed until `cozypkg add`. Tapping is idempotent and validates the artifact's structure but does not verify its cosign signature.

| Flag | Description |
| --- | --- |
| `--tag <tag>` | OCI tag to tap (overrides a tag in the reference; defaults to latest). |
| `--secret <name>` | Name of a pull-credential `Secret` in `cozy-system` for a private repository. |
| `--index <location>` | Index location for resolving a short name (local dir or `oci://`; defaults to `COZYPKG_INDEX`). |
| `--skip-validate` | Skip validating the artifact before tapping. |
| `--kubeconfig <path>` | Path to kubeconfig file. |

```bash
cozypkg tap oci://ghcr.io/acme/hello:v1.0.0
```

### `cozypkg untap <packagesource-name>`

Remove a tapped `PackageSource` and its Flux source. Only tapped sources (marked with the marketplace-tap label) can be untapped; official sources are refused. Already-installed `Package` resources are left untouched.

| Flag | Description |
| --- | --- |
| `--yes` | Untap even if a `Package` from this source is still installed. |
| `--kubeconfig <path>` | Path to kubeconfig file. |

```bash
cozypkg untap acme.hello
```

## Installing and inspecting

### `cozypkg add [package]...`

Install a `PackageSource` and its dependencies interactively. Packages can be given as arguments or read from files with `-f`.

| Flag | Description |
| --- | --- |
| `--allow-privileged` | Install privileged components without an interactive confirmation. |
| `-f, --file <path>` | Read packages from a file or directory (repeatable). |
| `--kubeconfig <path>` | Path to kubeconfig file. |

```bash
cozypkg add acme.hello
```

### `cozypkg del [package]...`

Delete `Package` resources. Packages can be given as arguments or read from files with `-f`.

| Flag | Description |
| --- | --- |
| `-f, --file <path>` | Read packages from a file or directory (repeatable). |
| `--kubeconfig <path>` | Path to kubeconfig file. |

```bash
cozypkg del acme.hello
```

### `cozypkg list`

List `PackageSource` or `Package` resources in table format.

| Flag | Description |
| --- | --- |
| `-i, --installed` | List installed `Package` resources instead of `PackageSource` resources. |
| `--components` | Show components on separate lines. |
| `--kubeconfig <path>` | Path to kubeconfig file. |

```bash
cozypkg list --installed
```

### `cozypkg dot`

Generate the dependency graph of `PackageSource` resources in Graphviz DOT format.

```bash
cozypkg dot | dot -Tsvg > packages.svg
```
Loading
Loading