Skip to content

Package formats ​

OpenArtifact serves many package formats natively, each on the URL its client expects, behind one permission model.

URL conventions ​

Replace HOST with your server (for example http://localhost:8080) and REPO with the repository name (^[a-zA-Z0-9_-]{1,100}$).

  • Every repository is served under /repos/REPO/....
  • Maven, sbt, Ivy and raw are served under a format prefix: /repos/maven/REPO, /repos/sbt/REPO, /repos/ivy/REPO, /repos/raw/REPO. Repositories named like these prefixes are not reachable by the generic URL.
  • Docker / OCI is the exception: the registry API is at HOST/v2/, and the first path segment after /v2/ is the repository name (details).
  • Set BASE_URL (baseUrl) to the externally visible URL: npm tarball URLs, Helm index.yaml, PyPI JSON, the Cargo config.json and the Terraform download URLs are built from it.

Format matrix ​

Format id is the format value used when creating a repository. Hosted repositories support upload for every format; proxy and group are limited as shown (details: hosted, proxy, group).

FormatFormat idClient URLTypesUploadPage
MavenmavenHOST/repos/maven/REPOhosted, proxy, groupPUT per file (mvn deploy)maven
sbtsbtHOST/repos/sbt/REPOhosted, proxy, groupPUT per file (sbt publish)ivy-sbt
IvyivyHOST/repos/ivy/REPOhosted, proxy, groupPUT per file (ivy:publish)ivy-sbt
Terraform / OpenTofuterraformregistry host HOST, source HOST/REPO/... (discovery at /.well-known/terraform.json)hosted, proxy, groupPUT /_api/modules/MODULE/SYSTEM/VERSION, PUT /_api/providers/TYPE/VERSION/OS/ARCH (relative to HOST/repos/REPO)terraform
RawrawHOST/repos/raw/REPO/<path>hosted, proxy, groupPUT <path> (curl -T)raw
npmnpmHOST/repos/REPO/hosted, proxy, groupnpm publish (PUT /<pkg>)npm
PyPIpypiHOST/repos/REPO/simple/hosted, proxy, grouptwine upload to HOST/repos/REPO/legacy/pypi
Docker / OCIdockerHOST/v2/ (image HOST/REPO[/image])hosted, proxy, groupdocker pushdocker
HelmhelmHOST/repos/REPO/ (index.yaml, charts/)hosted, proxy, groupPOST /charts (raw chart .tgz)helm
Debian (APT)debHOST/repos/REPO/ (dists/, pool/)hosted, proxy, groupPOST /api/v1/repositories/REPO/debs (multipart)debian
RPM (YUM/DNF)rpmHOST/repos/REPO/ (repodata/repomd.xml, Packages/)hosted, proxy, groupPOST /api/v1/repositories/REPO/packages (multipart)rpm
Arch Linux (pacman)pacmanHOST/repos/REPO/os/<arch> (<name>.db, packages)hosted, proxy, groupPUT /os/<arch>/<pkg>.pkg.tar.zst (+ .sig)pacman
Go modulesgoGOPROXY=HOST/repos/REPOhosted, proxy, groupPUT <module>/@v/<version> (module zip)go
Cargocargosparse+HOST/repos/REPO/index/hosted, proxy, groupcargo publish (PUT /api/v1/crates/new)cargo
NuGetnugetHOST/repos/REPO/v3/index.jsonhosted, proxy, groupdotnet nuget push (PUT /v3/package)nuget
RubyGemsrubygemsHOST/repos/REPO/hosted, proxy, groupgem push (POST /api/v1/gems)rubygems
CondacondaHOST/repos/REPO/<platform>/repodata.jsonhosted, proxy, groupPOST /<platform> with X-Filenameconda
Alpine (apk)apkHOST/repos/REPO/<branch>/<repo> (<arch>/APKINDEX.tar.gz)hosted, proxy, groupPUT <branch>/<repo>/<arch>/<name>-<version>.apk or POST /api/v1/repositories/REPO/apks (multipart)apk
Conan (1.x and 2)conanHOST/repos/REPO/ (v2/conans/..., v1/conans/...)hosted, proxy, groupconan uploadconan

Arch Linux (pacman) is uploaded with a PUT of the package file to HOST/repos/REPO/os/<arch>/<file>; its .db/.files databases are generated. A pacman proxy mirrors an Arch mirror root (details).

Debian and RPM have no upload route under /repos/REPO/: they are uploaded through the REST endpoints under /api/v1/repositories/REPO/. POST or PUT to HOST/repos/REPO/upload of such a repository answers 404 and names the endpoint to use.

Proxy repositories exist for these formats (Maven, sbt, Ivy, npm, PyPI, Helm, Go, Cargo, NuGet, RubyGems, Debian, RPM, Docker and raw); group repositories for the same formats. Creating any other combination is rejected with 400 validation_failed. Proxy and group repositories are read-only: writes answer 405.

Authentication ​

Authentication is required unless allowAnonymousRead is enabled or the repository is marked public (anonymous read only; writes always need a token). Package clients authenticate with an API token: Authorization: Bearer <TOKEN>, or HTTP Basic with the token as the password (any username). Account passwords are accepted only by the web UI login. Create tokens as described in authentication; what a token may do is governed by RBAC.

Read requests map to the read action and writes (PUT, POST, PATCH, DELETE) to write on the repository. The Debian/RPM REST upload endpoints under /api/v1/repositories/REPO/{debs,packages,comps} are authorized the same way, against the repository.

Behaviour shared by all formats ​

  • Blobs are content-addressed by SHA-256 and deduplicated across repositories; a blob is removed from storage only when no package references it.
  • Deletes are soft by default: the artifact, version or tag moves to the trash (404 on the native protocol, absent from listings, search and generated indexes) and can be restored until its retention expires. A repository can enable immutable_releases to block deleting or overwriting released versions.
  • Hosted repositories of raw, Maven, npm, Docker, Helm, PyPI, Cargo, Go and NuGet can be replicated between instances (federation).
  • Uploads emit artifact.uploaded and deletes artifact.deleted webhook events (webhooks).
  • Storage quotas are enforced on upload for every hosted format; proxy caches are not metered (quotas).
  • A repository with a license policy whose action is block rejects an upload whose declared license is denied (403, code LICENSE_BLOCKED). The license is read from the package metadata; Conan, Go, Terraform and raw uploads carry none and are not checked.
  • Client setup renders the snippets for every client with your own server URL and repository name. Client snippets in the web UI and in the MCP repository tool come from internal/clientsetup (UI counterpart: web/src/lib/installCommands.ts). Where this documentation differs from those snippets (Go format id), the page says so.

Free software under the AGPL-3.0-or-later.