Package Registries
A registry is a private place to store what you build, hosted on your own servers: Docker images, npm packages, Python packages, static websites, or simply files. Your usual tools (docker, npm, pip, twine, curl) talk to it exactly like they talk to Docker Hub, npmjs or PyPI, except everything stays in your cluster.
Registries are also what CI/CD pushes its builds to, and where Cloud Functions get their code from.
Before you start
- Registries live in the Constellation section, so Constellation must be enabled.
- It is recommended to create an Object Storage first. A registry stored in it is available from every node and survives losing one. Without it, a registry can use a folder on a single server, which is perfectly fine for a one-server setup.
- Each registry answers on its own hostname (for example
docker.mydomain.com). Like any other URL, that hostname must point to your server.
Where to find it
Go to Constellation > Registries. The page has three tabs: the list of your registries, Monitoring and Events.
The list shows, for each registry, its type, its status, where it is stored, how much space it uses, its URL (with an Internal or Public chip) and how many nodes are serving it. Click a row to open the registry.
Creating a registry
Click Create.
- Registry name: 3 to 27 lower-case letters and digits (for example
images,npm,sites). - What does this registry hold?: the type of the registry. It cannot be changed later, but you can create as many registries as you want.
- Docker: container images, pushed and pulled with
docker. - npm: npm packages, published with
npm publishand installed withnpm install. - PyPI: Python packages, published with
twine,uvorpoetry, installed withpip. - Generic: any file, organised as package / version / file. Installers, archives, models, build outputs...
- Static site: websites uploaded as a zip, each served on its own URL, with versions and instant rollback.
- Docker: container images, pushed and pulled with
- URL: the hostname of the registry. Cosmos suggests one from the name, and checks it like it does for your other URLs. A Static site registry has no URL of its own: each site gets one.
- Constellation-only: when enabled, the registry only answers from inside your Constellation. Otherwise it is reachable from the internet (a token is still needed to push).
- Allow anonymous pulls: lets anyone who can reach the registry download from it without a token. Handy combined with Constellation-only, so your own servers can pull freely while the outside world cannot reach it at all.
- Where should the blobs live?: Managed object storage (recommended), then pick your Object Storage, or Local folder on this node. A local folder lives on one server: only that server can serve the registry, and the data is only as safe as that server.
The Advanced section is fine on its defaults:
- Use an external S3 bucket instead: store the registry in a bucket at an outside provider (endpoint, bucket, region and keys).
- Folder / Bucket: choose the folder or bucket name instead of letting Cosmos generate one.
- Quota (GiB): the maximum size of the registry. Empty means unlimited. When the quota is reached, uploads are refused and downloads keep working.
- Serving node tags: only the nodes carrying all these tags serve the registry. Empty, the default, means every node. The dialog tells you how many nodes match.
Click Create. Cosmos creates the registry and shows you a first deploy token, with the command to log in with it.
Copy the token now: it is only ever shown once.
Deploy tokens
A deploy token is the password your tools use to talk to the registry. Open the registry and go to the Deploy tokens tab to manage them.
Click Mint a token:
- Token name: what it is for (
laptop,github-actions...). - Pull and Push: what the token can do. Pull downloads, Push uploads and deletes. A token for a server that only needs to download should only have Pull.
- Expires: Never, or from 7 days to a year.
The token is displayed once, together with a ready-to-paste snippet. The list then shows each token with its scopes, its expiry and when it was last used. Revoke disables a token within seconds, everywhere.
A token only works on its own registry. You will also see tokens that Cosmos creates for itself, named ci-... for CI/CD projects and function-... for Cloud Functions: they are managed for you.
In the examples below, the token is in the COSMOS_REGISTRY_TOKEN environment variable. The Overview tab of each registry shows the same commands with your real hostname already filled in.
Docker
Log in once (any username works, the password is the token), then push and pull as usual. The image name starts with the hostname of the registry:
echo "$COSMOS_REGISTRY_TOKEN" | docker login docker.mydomain.com -u cosmos --password-stdin
docker tag myapp:latest docker.mydomain.com/myapp:1.0.0
docker push docker.mydomain.com/myapp:1.0.0
docker pull docker.mydomain.com/myapp:1.0.0
You can organise images in folders if you like (docker.mydomain.com/team/myapp:1.0.0).
Using your images in ServApps and deployments
Use the full image name (docker.mydomain.com/myapp:1.0.0) in your ServApp or in the compose of a deployment. For the nodes to be allowed to pull it, pick one of:
- Images built by CI/CD need nothing: the nodes pull them with the project's own token.
- Enable Allow anonymous pulls together with Constellation-only on the registry: your nodes pull freely, nobody else can reach it.
- Or run
docker loginon each node with a Pull token.
npm
The simplest setup is to give your packages a scope (@mycompany/...) and send only that scope to your registry, so public packages keep coming from npmjs. In the .npmrc of your project, or of your home folder:
@mycompany:registry=https://npm.mydomain.com/
//npm.mydomain.com/:_authToken=${COSMOS_REGISTRY_TOKEN}
Then use npm normally:
npm publish # from a package named @mycompany/something
npm install @mycompany/something
Tags (npm dist-tag), npm deprecate and npm unpublish work too. A version that already exists cannot be published again: bump the version.
PyPI
Publish with twine, using __token__ as the username and the token as the password:
twine upload --repository-url https://pypi.mydomain.com/ \
-u __token__ -p "$COSMOS_REGISTRY_TOKEN" dist/*
With uv: uv publish --publish-url https://pypi.mydomain.com/.
Install with pip. Use --extra-index-url so that public packages still come from PyPI:
pip install --extra-index-url \
"https://__token__:${COSMOS_REGISTRY_TOKEN}@pypi.mydomain.com/simple/" mypackage
Generic files
A generic registry stores any file under package/version/file. Upload with a simple curl:
curl -fsS -T ./app-1.0.0.tar.gz \
-H "Authorization: Bearer $COSMOS_REGISTRY_TOKEN" \
https://files.mydomain.com/app/1.0.0/app-1.0.0.tar.gz
And download:
# a given file
curl -fsSLO -H "Authorization: Bearer $COSMOS_REGISTRY_TOKEN" \
https://files.mydomain.com/app/1.0.0/app-1.0.0.tar.gz
# whatever the newest version contains
curl -fsSLO -H "Authorization: Bearer $COSMOS_REGISTRY_TOKEN" \
https://files.mydomain.com/app/latest/download
latest can be used anywhere a version goes, and always points to the newest version. When a version holds several files, download needs to know which one: .../app/latest/download/app-1.0.0.tar.gz.
Opening https://files.mydomain.com/, .../app or .../app/1.0.0 lists the packages, versions and files. A DELETE on the same addresses removes a file, a version or a whole package.
You can also upload from the interface: in the Contents tab, New package (or Upload on an existing one), choose a name, a version and your files. A file that already exists in a version is never overwritten: publish a new version instead.
Static sites
A static site registry hosts websites made of plain files: the output of a React, Vue, Astro or Hugo build, a documentation site, a landing page. Each site has its own URL, and every upload is kept as a deployment you can come back to.
From the interface
Open the registry, go to the Contents tab and click New site:
- Site name: lower-case letters, digits and
-. - Choose a zip: a zip of your site, with
index.htmlat its root (or inside a single folder, as produced by zipping yourdistfolder). - Version: a name for this deployment. Leave empty to use the current date and time.
- Serve this deployment right away: ticked by default. Untick it to upload now and go live later.
- Site URL: the hostname of the site.
- Single-page application: on by default. Unknown addresses fall back to
index.html, which is what applications with their own router expect. Turn it off for classic sites, to get a real "not found" error instead. - Constellation-only and Serving node tags: same as for a registry.
Each site then lists its deployments, one of them marked Live, the others Staged. Activate on any deployment makes it the live one instantly. This is also how you roll back: activate the previous one. Upload adds a new deployment, Route settings changes the URL and the options above, and the download icon gives you back the zip of any deployment.
From your terminal or your CI
Uploads go through the address of your Cosmos server, with a token of the registry:
zip -r dist.zip ./dist
curl -fsSL -X POST \
-H "Authorization: Bearer $COSMOS_REGISTRY_TOKEN" \
-F "file=@dist.zip" \
"https://cosmos.mydomain.com/cosmos/api/constellation/registries/sites/sites/blog/versions?version=1.4.0"
Here the registry is named sites and the site blog. The deployment goes live right away; add &activate=false to only stage it. The first upload of a new site can set its URL with &host=blog.mydomain.com. Each site shows this command, filled in, under Deploy from CI.
If your code lives in a git repository, CI/CD does all of this for you on every push.
Browsing and cleaning up
The Contents tab shows everything the registry holds, whatever its type: images with their tags and layers, packages with their versions and files, each with its size and date. Every file has a Download button, and you can delete a package, an image or a single version from there.
Deleting frees the space at the next garbage collection. It runs by itself every night, and can be started by hand with Run garbage collection (the broom icon in the list, or the Usage and garbage collection card). To stay safe with uploads in progress, it never removes anything younger than 24 hours.
Settings
The Settings tab lets you change the URL, Constellation-only, Allow anonymous pulls, the Serving node tags and the Quota at any time. If you change the hostname, remember to update your tools.
Behind the scenes a registry is exposed through a normal Cosmos URL: the URL tab gives you its SmartShield and the other usual options.
Monitoring and events
The Overview tab shows the space used, the number of packages and versions, and the pulls and pushes. The Monitoring tab graphs the stored size and the traffic over time, and Events keeps the history: pushes, deletions, garbage collections, tokens created and revoked, and failed logins. The page-level tabs show the same for all your registries.
Deleting a registry
Use the Danger zone tab. The registry stops answering immediately. By default the stored data is kept in its bucket or folder; tick Also delete every stored blob to erase it for good.
Before deleting a registry, check that no CI/CD project or function still uses it.