Install
Guides

Repositories

Create local, remote and virtual repositories, and set their limits, cleanup, holds and trash.

Classes

ClassWhat it does
LocalStores what you deploy.
RemoteProxies an upstream registry and caches what it fetches.
VirtualServes several repositories at one URL, resolving from its members in order.

Create a repository in Repositories → New repository, or in YAML with relic apply -f (see Resources). Relic stores each content once per SHA-256, so copies and moves take no extra storage.

Remote repositories

A remote repository fetches a file from its upstream on first request and then serves it from the cache. Metadata (npm packuments, PyPI pages, maven-metadata.xml) is fetched again after the metadata cache period.

  • Checksums. A fetched file must match the checksum its upstream publishes (X-Checksum-* headers, a Maven .sha1, npm's dist.shasum, a PyPI #sha256=). A mismatch is not stored. Package managers get 502; the Relic API answers unavailable (503 over REST and on /api/v1/files/).
  • Missing files. An upstream 404 or 410 is remembered for 30 minutes (Remember upstream misses; missedRetrievalCachePeriodSecs in the JFrog® Artifactory®-compatible API). 0 asks every time.
  • Failures. 429, 502, 503, 504 and dropped connections are tried three times, honouring Retry-After. DNS and certificate errors are not retried. Package managers get 502 and the Relic API unavailable; the failure is not remembered. Relic's own failures answer 500 with Cache-Control: no-store.
  • Cooldown. Cooldown (days) hides npm and PyPI versions published upstream more recently than that, and refuses their files with 403. Other formats ignore it.
  • Version selection. npm packuments and PyPI pages leave out versions that are cooling down, in the malicious package catalog, quarantined or blocked by a watch. npm's latest tag moves to the newest version left.
  • One fetch. Concurrent requests for the same file fetch it once per replica.

In YAML, a remote repository's settings go under remote:

apiVersion: relic.build/v1
kind: Repository
metadata:
  name: npm-remote
spec:
  class: remote
  format: npm
  remote:
    url: https://registry.npmjs.org
    cooldownDays: 7
    quarantine: true
Form fieldremote fieldEffect
Upstream URLurlThe upstream registry.
Upstream username, Upstream password or tokenusername, passwordUpstream credentials, never in the URL. The password is never shown again; an update without one keeps it while the URL's scheme, host and port stay the same.
Package index URLindexUrlThe upstream's index when it is not at url (PyPI, a NuGet v3 feed).
Metadata cache (seconds)cachePeriodSecondsDefault (0): 2 hours.
Upstream timeout (ms)timeoutMillisecondsDefault (0): 15 seconds.
Remember upstream misses (seconds)missedRetrievalCachePeriodSecondsDefault: 1800.
Cooldown (days)cooldownDaysSee Cooldown.
QuarantinequarantineHold cached files until Relic Scan finds them not malicious or an administrator releases them.
OfflineofflineServe only the cache; never contact the upstream.
Do not cachedisableCacheFetch every download from the upstream and keep nothing.

Virtual repositories

In YAML, a virtual repository's settings go under virtual:

apiVersion: relic.build/v1
kind: Repository
metadata:
  name: npm
spec:
  class: virtual
  format: npm
  virtual:
    members: [npm-local, npm-remote]
    deployTo: npm-local
    localOnlyPatterns: ["@acme/*"]
Form fieldvirtual fieldEffect
Members, in resolution ordermembersRepositories of the same format; Maven, Gradle, Ivy and sbt mix. A deleted repository leaves the virtual repositories it was in.
Default deployment repositorydeployToThe local member that receives uploads. Without one, uploads are refused.
Local-only nameslocalOnlyPatternsSee Dependency confusion.

Dependency confusion

A public package named like an internal one can be installed through a virtual repository that proxies the public registry. List internal names as Ant patterns under Local-only names (localOnlyPatterns): @acme/* (npm scope), com/acme (Maven group), acme-* (PyPI), github.com/acme/** (Go). Matching names resolve only from local members, never from a remote, even in a nested virtual repository. Patterns are case-sensitive, except for PyPI, which normalizes names (Acme_* equals acme-*).

Client URLs

relic package setup <client> <repository> writes these URLs into a client's configuration. Set me up in the UI shows the configuration for the common clients and curl commands.

FormatURL
npm, yarn, pnpmhttps://relic.example.com/npm/<repo>/
PyPIhttps://relic.example.com/pypi/<repo>/simple
Maven, Gradlehttps://relic.example.com/maven/<repo>, https://relic.example.com/gradle/<repo>
Gohttps://relic.example.com/go/<repo>
NuGethttps://relic.example.com/nuget/<repo>/index.json (V2: https://relic.example.com/nuget/<repo>)
RubyGemshttps://relic.example.com/gems/<repo>/
Cargosparse+https://relic.example.com/cargo/<repo>/index/
Conanhttps://relic.example.com/conan/<repo>
Helmhttps://relic.example.com/helm/<repo>
Terraformhttps://relic.example.com/terraform/<repo>/providers/; modules as relic.example.com/<repo>__<namespace>/<name>/<provider>
Hugging FaceHF_ENDPOINT=https://relic.example.com/huggingface/<repo>
Nixhttps://relic.example.com/nix/<repo>
Git LFSlfs.url = https://relic.example.com/lfs/<repo>
Debian, Alpinehttps://relic.example.com/debian/<repo>, https://relic.example.com/alpine/<repo>
RPMhttps://relic.example.com/rpm/<repo>
Docker, OCI, Helm OCIrelic.example.com/<repo>/<image>

Browsing

Find by name searches the whole repository. An item's tabs:

TabShows
GeneralPath, URL, checksums and downloads.
PropertiesEditable properties.
Security, SBOMScan results.
BuildsBuilds that produced or used the file.
PermissionsFor administrators: who has which access, and which permission grants it.
Archive, ViewArchive entries; text files.
Package tabsnpm, PyPI, Helm, Docker and Maven details.

Limits

A local repository can limit what it accepts:

apiVersion: relic.build/v1
kind: Repository
metadata:
  name: libs-local
spec:
  class: local
  format: maven
  maxUploadSize: 1073741824     # 1 GiB
  maxStorage: 536870912000      # 500 GiB
SettingEffect
maxUploadSizeThe largest file, in bytes; larger uploads fail with 413. RELIC_MAX_UPLOAD_SIZE sets a server-wide limit; the lower one applies.
immutableRefuse replacing a file with other content, so container tags cannot move. Re-uploading the same content succeeds.
maxStorageThe quota in bytes. A deploy, copy or move past it fails with 413. A file in two repositories counts in both. relic get repository shows the current usedBytes.

Cleanup policies

A cleanup policy moves old or unused items of local repositories to the trash can, daily. Define policies on the Cleanup policies page or with relic apply:

apiVersion: relic.build/v1
kind: CleanupPolicy
metadata:
  name: old-app-versions
spec:
  enabled: true
  repositories: [libs-local]
  pathPattern: org/app/*
  olderThanDays: 90
  keepLatest: 5
SettingEffect
repositoriesThe local repositories covered.
pathPatternAnt pattern of items to consider: org/app/* takes the version folders of org/app, **/*.tgz every tarball. Empty is **. A folder moves with its contents.
olderThanDaysOnly items created more than this many days ago.
notDownloadedDaysOnly items not downloaded for this many days, or never downloaded and older.
keepLatestKeep this many newest matched items per folder.

A policy needs at least one of the last three. Files Relic generates, such as maven-metadata.xml, and held items are never selected. A policy whose last repository is deleted is disabled until it names one again.

Preview what a policy selects, limited to what you may read:

relic cleanup preview old-app-versions

Run it now:

relic cleanup run old-app-versions

A held item, or folder with its contents, cannot be deleted, moved, overwritten or cleaned up, and its repository cannot be deleted. Administrators place and release holds.

Place a hold:

relic hold add libs-local/org/app/1.4.0 --reason "audit 2026-14"

List the holds:

relic hold list

Release a hold:

relic hold remove libs-local/org/app/1.4.0

Trash can

A deleted item moves to the auto-trashcan repository for 14 days (RELIC_TRASH_RETENTION). Administrators restore or purge it in Administration → Trash can or the Relic API. Deleting a whole repository is permanent.

A folder with more than 100 items moves in several transactions of up to 100 items each, so other uploads and deletes go through while it moves. It shows up as a trash entry once all of it has moved. If the delete fails partway, the files already moved stay in the trash repository and the rest stays in place; deleting the folder again finishes the move.

List the newest 50 entries and the total:

relic api trash

List the next 50:

relic api 'trash?page=2'

Restore one item:

relic api /api/relic.v1.TrashService/RestoreTrash -d '{"path": "libs-local/org/app/1.0/app-1.0.jar"}'

A restore fails if a file has since been deployed at the same path. Delete that file first, or restore elsewhere with toRepository and toPath.

Empty the trash can:

relic api /api/relic.v1.TrashService/EmptyTrash -d '{}'

Replication

Replication pushes a local repository to another server, pulls from one, or keeps two in sync (federated). It runs on a schedule; push with onChange and federated replication also run after each change. Configure it in Administration → Replication or with a Replication resource (see Replication).