An enterprise-grade, open-source artifact registry supporting 45+ package formats. Built with Rust.
Documentation | Demo | Website
- 45+ Package Formats - Native protocol support for Maven, PyPI, NPM, Docker/OCI, Cargo, Go, Helm, and 38 more
- WASM Plugin System - Extend with custom format handlers via WebAssembly (WIT-based, Wasmtime runtime)
- Security Scanning - Automated vulnerability detection with Trivy and Grype, policy engine, quarantine workflow
- Hardened Containers - All images built on DISA STIG-approved Red Hat UBI 9 base images, non-root execution, no shell or package manager in runtime
- Borg Replication - Recursive peer mesh with swarm-based artifact distribution and P2P transfers
- Full-Text Search - OpenSearch-powered search across all repositories and artifacts
- Multi-Auth - JWT, OpenID Connect, LDAP, SAML 2.0, and API token support
- Artifactory Migration - Built-in tooling to migrate repositories, artifacts, and permissions from JFrog Artifactory
- Artifact Signing - GPG and RSA signing integrated into Debian, RPM, Alpine, and Conda handlers
graph LR
Client["CLI / Package Manager / Frontend"]
Backend["Backend<br/>Rust Β· Axum<br/>45+ format handlers"]
DB[(PostgreSQL 16)]
Storage["Storage<br/>Filesystem / S3"]
Meili["OpenSearch<br/>Full-text search"]
Trivy["Trivy<br/>Container & FS scanning"]
Grype["Grype<br/>Dependency scanning"]
OpenSCAP["OpenSCAP<br/>Compliance scanning"]
Peer1["Peer Instance"]
Peer2["Peer Instance"]
Client --> Backend
Backend --> DB
Backend --> Storage
Backend --> Meili
Backend --> Trivy
Backend --> Grype
Backend --> OpenSCAP
Backend <-->|Borg Replication| Peer1
Backend <-->|Borg Replication| Peer2
Peer1 <-->|P2P Mesh| Peer2
The backend follows a layered architecture with a middleware pipeline processing every request.
flowchart TD
REQ["HTTP Request"] --> MW["Middleware Pipeline"]
subgraph MW["Middleware"]
direction LR
CORS["CORS"] --> AUTH["Auth<br/>JWT Β· OIDC Β· LDAP<br/>SAML Β· API Key"]
AUTH --> RL["Rate Limiter"]
RL --> TRACE["Tracing<br/>+ Metrics"]
TRACE --> DEMO["Demo Mode<br/>Guard"]
end
MW --> ROUTER["Router<br/>50+ route groups"]
subgraph HANDLERS["Handler Layer"]
FMT["Format Handlers<br/>Maven Β· PyPI Β· NPM<br/>Docker Β· 41 more"]
CORE["Core Handlers<br/>Repos Β· Artifacts<br/>Users Β· Auth"]
ADV["Advanced Handlers<br/>Security Β· Plugins<br/>Peers Β· Migration"]
end
ROUTER --> HANDLERS
subgraph SERVICES["Service Layer"]
direction LR
ART["Artifact<br/>Service"]
REPO["Repository<br/>Service"]
SCAN["Scanner<br/>Service"]
PLUG["Plugin<br/>Service"]
SEARCH["Search<br/>Service"]
end
HANDLERS --> SERVICES
subgraph DATA["Data Layer"]
direction LR
PG[(PostgreSQL)]
FS["Storage<br/>FS / S3"]
MS["Meilisearch"]
SC["Trivy / Grype / OpenSCAP"]
end
SERVICES --> DATA
45+ formats organized by ecosystem. Each has a native protocol handler that speaks the package manager's wire protocol.
| Format | Aliases | Ecosystem |
|---|---|---|
| Maven | Gradle | Java, Kotlin, Scala |
| NPM | Yarn, Bower, pnpm | JavaScript, TypeScript |
| PyPI | Poetry, Conda | Python |
| NuGet | Chocolatey, PowerShell | .NET, C# |
| Cargo | Rust | |
| Go | Go modules | |
| RubyGems | Ruby | |
| Hex | Elixir, Erlang | |
| Composer | PHP | |
| Pub | Dart, Flutter | |
| CocoaPods | iOS, macOS | |
| Swift | Swift Package Manager | |
| CRAN | R | |
| SBT | Ivy | Scala, Java |
| Format | Aliases | Ecosystem |
|---|---|---|
| Docker / OCI | Podman, Buildx, ORAS, WASM OCI, Helm OCI | Container images |
| Helm | Kubernetes charts | |
| Terraform | OpenTofu | Infrastructure modules |
| Vagrant | VM boxes |
| Format | Ecosystem |
|---|---|
| RPM | RHEL, Fedora, CentOS |
| Debian | Ubuntu, Debian |
| Alpine | Alpine Linux (APK) |
| Conda | Conda channels |
| OPKG | OpenWrt, embedded Linux |
| Format | Ecosystem |
|---|---|
| Chef | Chef Supermarket |
| Puppet | Puppet Forge |
| Ansible | Ansible Galaxy |
| Format | Ecosystem |
|---|---|
| HuggingFace | Models, datasets |
| ML Model | Generic ML artifacts |
| Format | Aliases | Ecosystem |
|---|---|---|
| VS Code | Extension marketplace (VS Code, Cursor, Windsurf, Kiro) | |
| JetBrains | Plugin repository |
| Format | Ecosystem |
|---|---|
| Protobuf / BSR | Buf Schema Registry, Connect RPC |
| Format | Ecosystem |
|---|---|
| Conan | C, C++ |
| Git LFS | Large file storage |
| Bazel | Bazel modules |
| P2 | Eclipse plugins |
| Generic | Any file type |
Custom formats can be added via the WASM plugin system.
Every artifact upload is automatically scanned for known vulnerabilities.
flowchart LR
UP["Artifact<br/>Upload"] --> HASH{"SHA-256<br/>Dedup"}
HASH -->|New artifact| T["Trivy<br/>FS Scanner"]
HASH -->|New artifact| G["Grype<br/>Dependency Scanner"]
HASH -->|Already scanned| CACHE["Cached<br/>Results"]
T --> SCORE["Vulnerability<br/>Score A-F"]
G --> SCORE
CACHE --> SCORE
SCORE --> POL{"Policy<br/>Engine"}
POL -->|Pass| OK["Stored"]
POL -->|Fail| Q["Quarantined"]
- Dual scanner - Trivy for filesystem/container analysis, Grype for dependency trees
- Scoring - A through F grades based on finding severity and count
- Policies - Configurable rules that block or quarantine artifacts
- Signing - GPG/RSA signing for Debian, RPM, Alpine, and Conda packages
Recursive peer-to-peer replication where every node is a full Artifact Keeper instance. No thin caches β each peer runs the same stack and can serve as an origin for other peers.
graph TD
P1["Peer<br/>US-West"]
P2["Peer<br/>EU-Central"]
P3["Peer<br/>AP-Southeast"]
P4["Peer<br/>US-East"]
P1 <-->|"Chunked Transfer"| P2
P1 <-->|"Chunked Transfer"| P4
P2 <-->|"Chunked Transfer"| P3
P3 <-->|"Chunked Transfer"| P4
P1 <-->|"P2P Mesh"| P3
P2 <-->|"P2P Mesh"| P4
- Recursive peers - Every peer is a full instance (backend, DB, storage) that can originate replication to other peers
- Swarm-based distribution - Artifacts replicate across the mesh based on demand
- Chunked transfers - Large artifacts split for reliable delivery over unstable links
- Network-aware scheduling - Bandwidth and latency profiling for optimal routing
Extend Artifact Keeper with custom format handlers compiled to WebAssembly.
- WIT-based interface - Plugins implement a well-defined
FormatHandlercontract - Wasmtime runtime - Sandboxed execution with fuel-based CPU limits and memory caps
- Hot reload - Install, enable, disable, and reload plugins without restart
- Sources - Load from Git repositories or ZIP uploads
Get running in 5 minutes with Docker Compose: Quickstart Guide
- Quickstart β Get running in 5 minutes
- Installation β Docker Compose, Windows Service (beta), or build from source
- Configuration β Environment variables reference
- Package Formats β All 45+ supported formats
- Docker Deployment β Production setup guide
artifact-keeper/
βββ backend/ # Rust backend (Axum, SQLx, 6,400+ unit tests)
β βββ src/
β β βββ api/ # Handlers, middleware, routes
β β βββ formats/ # 45+ format handler implementations
β β βββ services/ # Business logic (68 services)
β β βββ models/ # Data models (21 types)
β β βββ storage/ # FS and S3 backends
β βββ migrations/ # 69 PostgreSQL migrations
βββ edge/ # Peer replication service (Rust)
βββ scripts/ # Test runners, native client tests, stress tests
βββ .github/ # CI/CD workflows
| Layer | Choice | Why |
|---|---|---|
| Backend language | Rust | Memory safety, performance, strong type system |
| Web framework | Axum | Tower middleware ecosystem, async-first |
| Database | PostgreSQL 16 | JSONB for metadata, mature ecosystem |
| Search | OpenSearch | Fast full-text search, easy to operate |
| Security scanning | Trivy + Grype + OpenSCAP | Complementary coverage, industry standard |
| Plugin runtime | Wasmtime | Sandboxed, portable, WIT contract system |
| Storage | Filesystem / S3 | Simple default, cloud-ready upgrade path |
Seven GitHub Actions workflows handle testing, publishing, and deployment.
flowchart TD
subgraph TRIGGER["Triggers"]
PUSH["Push / PR<br/>to main"]
TAG["Tag v*"]
CRON["Daily 2 AM UTC"]
SITE_PUSH["Push to site/**"]
end
subgraph CI["ci.yml β Every Push/PR"]
direction TB
LINT["π¦ Lint Rust<br/>fmt + clippy"]
UNIT["π§ͺ Unit Tests<br/>cargo test --lib"]
INTEG["π Integration Tests<br/>+ PostgreSQL<br/>(main push only)"]
SMOKE["π₯ Smoke E2E<br/>PyPI Β· npm Β· Cargo<br/>docker-compose.test.yml"]
AUDIT["π Security Audit<br/>cargo audit"]
CI_OK["β
CI Complete"]
LINT --> UNIT
LINT --> INTEG
UNIT --> SMOKE
SMOKE --> CI_OK
AUDIT --> CI_OK
end
subgraph DOCKER["docker-publish.yml β Push to main / tags"]
direction TB
BE_BUILD["Backend<br/>amd64 + arm64"]
OS_BUILD["OpenSCAP<br/>amd64 + arm64"]
BE_MERGE["Multi-Arch<br/>Manifest"]
OS_MERGE["Multi-Arch<br/>Manifest"]
BE_BUILD --> BE_MERGE
OS_BUILD --> OS_MERGE
end
subgraph E2E["e2e.yml β Manual / called by release"]
direction TB
PKI["π Setup PKI<br/>TLS + GPG"]
NATIVE["π¦ Native Client Tests<br/>10 formats"]
STRESS["π₯ Stress Tests<br/>100 concurrent uploads"]
FAILURE["π₯ Failure Tests<br/>crash Β· db Β· storage"]
PKI --> NATIVE
NATIVE --> STRESS
NATIVE --> FAILURE
end
subgraph RELEASE["release.yml β Tags v*"]
direction TB
E2E_GATE["π¦ E2E Gate<br/>all formats + stress + failure"]
BINARIES["π¦ Build Binaries<br/>linux + macOS<br/>amd64 + arm64"]
GH_RELEASE["π GitHub Release<br/>binaries + checksums"]
E2E_GATE --> BINARIES
BINARIES --> GH_RELEASE
end
subgraph NIGHTLY["scheduled-tests.yml β Daily"]
direction TB
NIGHTLY_E2E["π Nightly Smoke E2E"]
DEP_CHECK["π Dependency Check"]
SEC_SCAN["π Security Scan"]
end
subgraph SITE["site.yml"]
PAGES["π Build + Deploy<br/>GitHub Pages"]
end
subgraph AMI["ami-build.yml"]
PACKER["π₯οΈ Packer Build AMI"]
end
PUSH --> CI
PUSH --> DOCKER
TAG --> RELEASE
TAG --> DOCKER
CRON --> NIGHTLY
SITE_PUSH --> SITE
GH_RELEASE -.->|"on release published"| AMI
classDef trigger fill:#6f42c1,color:#fff,stroke:#6f42c1
classDef ci fill:#2ea44f,color:#fff,stroke:#2ea44f
classDef docker fill:#0969da,color:#fff,stroke:#0969da
classDef release fill:#d97706,color:#fff,stroke:#d97706
class PUSH,TAG,CRON,SITE_PUSH trigger
class LINT,UNIT,INTEG,SMOKE,AUDIT,CI_OK ci
class BE_BUILD,OS_BUILD,BE_MERGE,OS_MERGE docker
class E2E_GATE,BINARIES,GH_RELEASE release
| Workflow | Trigger | What It Does |
|---|---|---|
| ci.yml | Every push/PR | Lint, unit tests, integration tests, smoke E2E (PyPI, npm, Cargo) |
| docker-publish.yml | Push to main, tags | Multi-arch Docker images (backend + OpenSCAP) to ghcr.io |
| e2e.yml | Manual or called by release | Full E2E: 10 native client formats, stress, failure injection |
| release.yml | Tags v* |
E2E gate, cross-platform binaries, GitHub Release |
| scheduled-tests.yml | Daily 2 AM UTC | Nightly smoke E2E, dependency check, security scan |
| site.yml | Push to site/** |
Build and deploy docs to GitHub Pages |
| ami-build.yml | On release published | Bake AWS AMI with Packer |
Thank you to our sponsors for supporting ongoing development of Artifact Keeper.
![]() Ash A. |
![]() Gabriel Rodriguez |
Become a sponsor to support the project and get your name listed here.
We welcome contributions! See CONTRIBUTING.md for guidelines.
Have questions or ideas? Join the conversation in GitHub Discussions.
MIT License - see LICENSE for details.
Built with Rust. "JFrog" and "Artifactory" are trademarks of JFrog Ltd. Artifact Keeper is not affiliated with or endorsed by JFrog.

