Every repository has one format, chosen when it's created; the format can't change later. A space lists the formats its repositories may use. This page compares the formats; each has its own page with setup, commands and limits.
| Format | Ecosystem | Works with | Proxy presets |
|---|---|---|---|
| Maven | Java, Kotlin, Scala and other JVM languages | mvn, Gradle, sbt, Ivy and any Maven 2 client | Maven Central |
| npm | JavaScript and TypeScript (Node.js, browsers) | npm, pnpm, Yarn, Bun | npm public registry |
| PyPI | Python | pip, uv, Poetry, PDM, Pipenv; twine, Hatch, Flit to publish | Python Package Index |
| Go | Go modules | the go command (go get, go mod download, builds) | Go module proxy (proxy.golang.org) |
| Helm | Kubernetes charts (classic chart repositories) | helm, the helm-push (cm-push) plugin, Argo CD, Flux | Bitnami Helm charts |
| NuGet | .NET (C#, F#, VB) | dotnet, Visual Studio, Rider, nuget.exe | nuget.org |
| Cargo | Rust crates (and Rust toolchains through raw repositories) | cargo 1.68 or later; rustup through a raw repository | crates.io; Rust toolchains (raw) |
| APT | Debian and Ubuntu packages (.deb, source packages) | apt, apt-get, apt-cache, apt-file, apt-get source | Debian, Debian security, Ubuntu |
| YUM | RPM packages (Rocky, Alma, RHEL, Fedora, openSUSE) | dnf, yum, microdnf, zypper | Rocky Linux 9 BaseOS and AppStream, EPEL 9 |
| Terraform | Terraform and OpenTofu providers and modules | terraform, tofu (init, the network mirror) | Terraform Registry, OpenTofu Registry |
| Hugging Face | Machine learning models, datasets and Spaces | huggingface_hub, the hf command, transformers, datasets, diffusers | Hugging Face Hub |
| Git LFS | Large files of git repositories hosted anywhere | git with git-lfs 3.x | — (any LFS server as an upstream) |
| Composer | PHP packages | composer 2 | Packagist |
| RubyGems | Ruby gems | gem and Bundler | RubyGems.org |
| Conda | Conda packages: Python, R, C and C++ libraries and tools, built for each platform | conda, mamba and micromamba, pixi; rattler-build or curl to publish | conda-forge, Bioconda; the conda, micromamba and pixi installers (raw) |
| Conan | C and C++ packages: recipes with their binaries for each configuration | conan 2 (install, upload, list, search, remove) | ConanCenter |
| Docker | Container images and other OCI artifacts | docker, BuildKit, containerd, Helm, ORAS, crane, skopeo, cosign | Docker Hub |
| Raw | Any file | curl, wget, browsers, scripts | — |
| Vibe artifacts | Projects AI coding tools push: check-ins with files, milestones and screenshots (Enterprise) | HTTP (curl, an AI coding tool) | — (hosted only) |
1. Client versions
The oldest client of each format that works with Depotex, and why older ones don't. Newer clients always work: Depotex follows each format's current protocol, and answers older clients in the forms they understand where the format allows it.
| Format | Oldest client | What it depends on | Checked with |
|---|---|---|---|
| Maven | Maven 2, Gradle, sbt, Ivy | The Maven 2 layout and maven-metadata.xml (Maven 2 and Maven 3 snapshot forms); SHA-1, MD5, SHA-256 and SHA-512 checksum files | Maven 2.2.1 and 3.9 |
| npm | Any npm, pnpm, Yarn or Bun to install; npm 9 for npm login | Full and abbreviated package documents (each client gets the one it asks for). npm login signs in through the browser, npm's default since npm 9; with older npm, put an API token in .npmrc | npm 2 (Node.js 4), 6, 10 and 11; Yarn 1; pnpm 10 |
| PyPI | Any pip; pip 9 to respect Requires-Python | The HTML Simple API for every client, the JSON form (PEP 691) and metadata files (PEP 658) for clients that ask; Twine's upload API | pip 8.1, 9.0 and 26; Twine; uv 0.9 and 0.11 |
| Go | Go 1.13 | The module proxy protocol (GOPROXY) and the checksum database, both on by default since Go 1.13 | Go 1.13, 1.26 and 1.27 |
| Helm | Helm 3 | Classic chart repositories (index.yaml). OCI charts (oci://) need Helm 3.8 and go in a Docker repository | Helm 3.0, 3.12 and 3.19 |
| NuGet | nuget.exe 3, Visual Studio 2015, any dotnet | The v3 feed only (no v2 OData feed). SemVer 2.0.0 versions are shown from NuGet 4.3; older clients see the other versions (details) | nuget.exe 3.5 and 7.9 (Mono); dotnet SDK 3.1, 7 and 9 |
| Cargo | cargo 1.68; cargo 1.74 for spaces that need signing in | The sparse index (no git index). Cargo sends credentials for downloads only from 1.74 (registry authentication): cargo 1.68 to 1.73 read public spaces only | cargo 1.68, 1.74 and 1.99 |
| APT | apt 1.2 (Ubuntu 16.04, Debian 9 and later) | .sources files with Signed-By, xz and gzip indexes, by-hash, SHA-256. An imported ed25519 signing key needs gpgv 2.1 or later, which Debian 8 and Ubuntu 16.04 don't have; generated keys are RSA. Ubuntu 16.04 reads only the binary key (public.gpg) | apt 1.2 (Ubuntu 16.04), 2.0 (Ubuntu 20.04), 2.6 (Debian 12), 3.0 (Debian 13) |
| YUM | yum 3 (EL 7), dnf, microdnf, zypper | XML repodata with SHA-256 checksums, gzip-compressed (no zstd, which yum 3 can't read); repomd.xml.asc for repo_gpgcheck. dnf5 needs the credentials in the gpgkey= address for a private space (details) | yum 3.4 (CentOS 7, Amazon Linux 2), dnf 4 (Rocky Linux 8 and 9), dnf5 (Fedora 44), zypper (openSUSE Leap 15.6) |
| Terraform | Terraform 0.13; any OpenTofu | Source addresses with a host (0.13), CLI host blocks for providers, the network mirror (0.13.2); terraform login (0.12.21); TF_TOKEN_… variables (1.2) | Terraform 0.13, 1.0, 1.7 and 1.13; OpenTofu 1.10 |
| Hugging Face | huggingface_hub with HF_ENDPOINT to download; 0.11 to upload | The Hub's HTTP API, with commits in the NDJSON form huggingface_hub sends from 0.11 (0.10 and older can download only). The hf command comes with huggingface_hub 0.34; older versions have huggingface-cli. git clone of a model isn't supported | huggingface_hub 0.10 (download), 0.11 and 2.2 |
| Git LFS | git-lfs 2.0 | The batch API with basic transfers, and the locking API (git lfs lock, lfs.locksverify) | git-lfs 2.0, 2.13 and 3.7 |
| Composer | Composer 2.0 | The Composer 2 metadata (metadata-url); Composer 1 finds no packages | Composer 2.0 and 2.10 |
| RubyGems | RubyGems 3.1 and Bundler 2.1 (Ruby 2.7) | The compact index (versions, info/), which Bundler and gem 3.2.3 or later resolve from; older gem versions read the specs files. RubyGems 3.1's gem install can't install a gem that has only platform builds (Bundler on the same Ruby can). No dependency API, which RubyGems.org retired too | RubyGems 3.1, 3.4, 3.5 and 4.0 with Bundler 2.1, 2.4, 2.5 and 4.0 (Ruby 2.7, 3.2, 3.3 and 4.0) |
| Conda | conda 4.12, micromamba 1.5, pixi | Plain repodata.json (conda 4.12), repodata.json.zst (conda 24 and later) and sharded repodata (conda 26.5 or later, micromamba 2, pixi), all generated for every channel. conda 26.5 and 26.6 don't send a channel address's credentials with the shard request and read repodata.json.zst instead (details). Uploads are HTTP PUTs (rattler-build, curl) | conda 4.12, 24.11, 26.5, 26.7 and 26.9; micromamba 1.5 and 2.9; pixi 0.83; rattler-build 0.77 (upload) |
| Conan | Conan 2.0 | The Conan 2 REST API with revisions; Conan 1 isn't tested and may not work (details) | Conan 2.0.17 and 2.33.0 |
| Docker | Docker 1.10; any current OCI tool | Image manifest schema 2 and OCI: schema 1 (Docker 1.9 and older) isn't accepted. Clients that can't read multi-platform images get the linux/amd64 image of a tag | Docker 20.10 and 29 |
| Raw | Any HTTP client | GET, HEAD, PUT and DELETE; byte ranges and If-Range to resume | curl |
Checked with lists the client versions Depotex's own tests run against a server: each in its own container, publishing and installing over HTTPS. Where the oldest client is older than the oldest checked, it follows from what each client version added to its protocol (Docker engines before 20.10 don't run on current test machines).
2. What each format supports
| Maven | npm | PyPI | Go | Helm | NuGet | Cargo | APT | YUM | Docker | Raw | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Hosted repositories (every tier) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Proxy repositories (Pro) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Groups and the universal URL (every tier) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Groups route uploads by | Package and release/snapshot | Package | Project and version | Module and release/pre-release | Chart and release/pre-release | Package ID and release/pre-release | Crate and release/pre-release | Package and version | Package | Image | Path |
| Proxy another Depotex over a Depotex link (Enterprise) | ✓ | Not yet | ✓ | Not yet | ✓ | ✓ | ✓ | ✓ | ✓ | Not yet | ✓ |
| What counts as a version | groupId:artifactId version | Package version | Project release | Module version | Chart version | Package version | Crate version | Package version (without the epoch) | Package version-release | Image tag | Each file (no version) |
| Publish once by default | No | Always (npm rule) | Yes | Yes | Yes | Yes | Yes | Yes | Yes | No | No |
| Dependencies in the browser | From the POM | From package.json | From Requires-Dist, with extras | — | — | — | From the crate's metadata | — | — | — | — |
| Signatures and SBOMs in the browser | .asc, SBOM files | Provenance | PEP 740 attestations | — | .prov files stored and served | — | — | Indexes signed with the repository's key | Repodata signed with the repository's key; package signatures checked against trusted keys | Referrers and build attestations | SBOM files |
The formats added later, in the same terms:
| Terraform | Hugging Face | Git LFS | Composer | |
|---|---|---|---|---|
| Hosted, proxy (Pro) and group repositories | ✓ | ✓ | ✓ | ✓ |
| Groups route uploads by | Provider or module, and release/pre-release | To the group's write member | Object | Package and version |
| Proxy another Depotex over a Depotex link (Enterprise) | ✓ | ✓ | ✓ | ✓ |
| What counts as a version | Provider or module version | Commit | Each object | Package version |
| Publish once by default | Yes | Commits are new versions | Objects never change | Always |
| Dependencies in the browser | — | — | — | From composer.json (require, require-dev) |
| Signatures | SHA256SUMS signed with the repository's key | — | — | — |
RubyGems, Conda and Conan, added after those, in the same terms:
| RubyGems | Conda | Conan | |
|---|---|---|---|
| Hosted, proxy (Pro) and group repositories | ✓ | ✓ | ✓ |
| Groups route uploads by | Gem and release/pre-release | Package and release/pre-release | Recipe and release/pre-release |
| Proxy another Depotex over a Depotex link (Enterprise) | ✓ | ✓ | ✓ |
| What counts as a version | Gem version (a file per platform) | Package version (its builds, one per platform and file) | Recipe version (its revisions and their binaries) |
| Publish once by default | Always | Always (the same file again is accepted) | Revisions never change; a version takes new revisions |
| Dependencies in the browser | From the gemspec (runtime and development) | From the newest build (depends, constrains) | The newest revision's requirements from its recipe, and what its binaries were built with |
| Signatures | Attestations from gem push --attestation; signed gems marked | — | — (each revision is checked against its manifest) |
| SBOMs Depotex makes (Pro) | From the gemspec's runtime dependencies | From depends; packages from public channels' proxies also read with Syft | — (C/C++ packages show as not covered) |
3. What every format has in common
- Address: https://<depotex>/repository/<space>/<repository>/, except Docker, which uses <depotex>/<space>/<repository>/<image>. The repository's page shows its address and setup snippets.
- Credentials: an API token (Profile → API tokens) as the password or as the user name with an empty password, or as a Bearer token (NuGet: as the API key; Cargo and gem push: the token alone; Bundler: the user name and token, or the token alone; conda: in ~/.netrc; micromamba and pixi: as a Bearer token in their auth files; Conan: conan remote login with the token as the password; see Use a token). Public spaces need none while anonymous access is on.
- Permissions: Read to download, Publish for new files, Overwrite to replace or change, Delete to remove, set by space roles, repository roles and content selectors (see Spaces).
- Policies: upload rules, cleanup, storage quotas, quarantine and the block list work on every format's versions.
- Storage: each distinct file content is stored once, checked nightly by integrity checks, and counted toward the space's quota.
- Browse: every format's versions show in the artifact browser, with checksums, commands and the format's own metadata.
- Safety: metadata, SBOMs and attestations are read with size, depth and time limits; content that breaks them quarantines its version.
4. Uploading files with one form
In the web app, choose Upload in the sidebar to pick any hosted repository you may publish to, across your spaces (search by name, filter by format), and upload to it on the same page. Or open a hosted repository and choose Upload (shown when you may publish there and its format takes uploads). Drop files or choose them, fill in what the dialog asks for, and Upload: a progress bar shows while the files are sent, then each file's result: stored, replaced, in quarantine, or refused with the reason. In raw and YUM repositories, Upload files in the Browse tab uploads into the folder you're looking at.
Besides each format's own tools, hosted repositories can take files as one form upload, the way the web app uploads them. Depotex reads what it needs from the files and asks only for what they can't say; when a value you give disagrees with the file, the file is refused rather than stored under the wrong name.
| Format | Files | Values you may give | Where files go |
|---|---|---|---|
| Raw | Any | directory (optional) | <directory>/<file name> |
| Maven | One version's files: main artifact, -sources/-javadoc and other classifiers, signatures, its POM (*.pom or pom.xml) | groupId, artifactId, version, packaging, generatePom (default true): needed only when neither a POM nor the jar's pom.properties names them | The Maven layout; classifiers come from names like lib-2.0-sources.jar. The POM is stored last; with generatePom a minimal one is made when the version has none |
| npm | Package .tgz (npm pack) | tag (default latest) | As npm publish (name, version and details from package.json) |
| PyPI | Wheels and sdists (.whl, .tar.gz, .zip) | — | As twine upload; keep the file names your build tool made |
| Cargo | .crate (cargo package) | — | As cargo publish, with dependencies, features and README read from the crate |
| Go | Module .zip | — | <module>/@v/<version>.zip and its go.mod; module and version from the zip |
| NuGet | .nupkg | — | As dotnet nuget push stores it (ID and version from the package) |
| Helm | Chart .tgz, provenance .tgz.prov | — | <name>-<version>.tgz from Chart.yaml; a provenance file must be named after its chart |
| YUM | .rpm | directory: required when the repository's repodata is deeper than its root | <directory>/<file name> |
| APT | .deb, .udeb | distribution (comma-separated; default stable), component (default main) | The pool, by the package's control file |
| Composer | Package .zip | version, when composer.json names none | As PUT packages/upload/<name>/<version>, the name from composer.json |
| RubyGems | .gem (gem build), several at once | — | As gem push (POST api/v1/gems): name, version and platform from the gemspec |
| Conda | .conda, .tar.bz2 (several at once) | — | <platform>/<file name>, the platform folder from the package's info/index.json |
| Conan | —: upload with conan upload, which sends a revision's files and then its manifest | — | — |
Docker, Terraform, Hugging Face and Git LFS repositories keep their own tools.
curl -f -H "Authorization: Bearer $DEPOTEX_TOKEN" \
-F directory=tools/1.4 -F file=@app.zip -F file=@app.zip.asc \
https://depotex.example.com/api/uploads/my-space/files
- Send the form's values first, then the files, each in a field named file. GET /api/spaces/<space>/repositories/<repository>/upload-form tells whether you can upload there, which values the format takes, and the size and file-count limits. GET /api/upload-repositories lists the hosted repositories you can upload to, across spaces (q, format, space, and cursor for the next page; a page can hold fewer than limit while hasNext is true).
- The answer lists each file: stored, overwritten, or refused with the reason (for example no permission to overwrite, or a publish-once repository). Files are stored one after another; a refused file doesn't undo the others.
- The same rules apply as for the format's own tools: Publish and Overwrite permissions per path, the repository's publishing setting and size limit, the space's upload rules and quota, quarantine, and the audit log, which records these uploads as made from the web (via: web).
- Hosted repositories only; every licence tier.
While a request runs, its files wait on the server's disk. Settings for the server:
| Variable | Default | What it does |
|---|---|---|
| WEB_UPLOAD_MAX_FILES | 100 | Most files in one upload (1–10000) |
| WEB_UPLOAD_TEMP_DIR | the system's temporary folder | Where files wait during the upload; needs free space for the largest upload |
Large uploads pass through your reverse proxy or ingress: raise its request body limit (nginx client_max_body_size, ingress proxy-body-size) and timeouts, as for package-manager uploads.
5. Choosing a type
- Hosted for what your teams build and publish.
- Proxy for public packages: builds keep working when the public registry is down or removes a package, and every package passes your quarantine and block list.
- Combine hosted and proxy repositories of a format in a group, so each tool needs one address for both.
Repository types show with neutral icons in Depotex, not the ecosystems' logos: those logos are their owners' trademarks.