How-to guide

Use your own registry

A snapshot is a standard OCI 1.1 artifact, so any OCI registry stores it: GHCR, Docker Hub, Amazon ECR, Harbor, or a registry on your laptop.

Log in

warmctl reads Docker's credentials, so docker login is all it needs:

bash
# GitHub Container Registry: a token with write:packages
$ echo $GITHUB_TOKEN | docker login ghcr.io -u YOUR_USER --password-stdin
# Amazon ECR
$ aws ecr get-login-password | docker login 123456789012.dkr.ecr.us-east-1.amazonaws.com -u AWS --password-stdin
# Harbor, Docker Hub and the rest
$ docker login harbor.acme.internal

Push and pull

bash
$ warmctl push /snaps/qwen3-8b ghcr.io/acme/qwen3-8b
$ warmctl images oci://ghcr.io/acme/qwen3-8b   # its platform tags
$ warmctl up ghcr.io/acme/qwen3-8b

Push the same model built on other GPUs to the same repository: each lands under its platform tag and in latest, and up picks the one for the host. Name a tag (ghcr.io/acme/qwen3-8b:1xh100-80gb-sxm-580.173.02) to skip that choice.

Serve your models by short name

Make your namespace the default registry, and warmctl up qwen3-8b means your copy:

/etc/warmctl/config.yaml
registry: ghcr.io/acme

To list your models in warmctl catalog, publish a catalog file to the namespace with warmctl catalog --publish catalog.yaml; it becomes ghcr.io/acme/catalog:latest.

Registry quirks

CaseWhat to do
Amazon ECRCreate the repository before the first push: ECR does not create it on push.
Size limitsA registry that refuses a blob as too large (HTTP 413) gets 64 MiB chunks from then on, automatically. --chunk-size 64MiB asks for chunks up front.
Plain HTTPA local registry without TLS: --plain-http.
Slow or rate-limited--concurrency sets how many blobs move at once; the default is 64.
Interrupted pullRun it again: pieces already checked are kept and hashed instead of downloaded.

See also