Alternative Registries
Overview
Section titled “Overview”Publishing Rust crates to alternative registries beyond crates.io for private packages, enterprise distribution, or specialized ecosystems.
Why Alternative Registries? (explanation)
Section titled “Why Alternative Registries? (explanation)”This section is rationale; the registry catalog and configuration tables below are the reference content.
- Private packages - Keep proprietary code internal
- Enterprise control - Host on internal infrastructure
- Faster builds - Geographic proximity, caching
- Compliance - Meet regulatory requirements
- Mirrors - Reduce dependency on crates.io
Registry Options
Section titled “Registry Options”1. Cloudsmith (Hosted SaaS)
Section titled “1. Cloudsmith (Hosted SaaS)”Best for: Commercial projects, easy setup
[registries.cloudsmith]index = "sparse+https://dl.cloudsmith.io/basic/USER/REPO/cargo/index/"token = "Bearer YOUR_TOKEN"Publish:
cargo publish --registry cloudsmithFeatures:
- Hosted solution (no infrastructure)
- Multiple package formats (npm, Maven, Docker)
- CDN distribution
- Access control and auditing
- Free tier available
Setup:
- Sign up at https://cloudsmith.io/
- Create Rust/Cargo repository
- Get API token from account settings
- Configure
.cargo/config.toml
2. Artifactory (JFrog)
Section titled “2. Artifactory (JFrog)”Best for: Enterprise with existing JFrog infrastructure
[registries.artifactory]index = "sparse+https://artifactory.company.com/artifactory/api/cargo/cargo-local/index/"Publish:
# Set credentialscargo login --registry artifactory
cargo publish --registry artifactoryFeatures:
- Enterprise-grade security
- Advanced access control
- Vulnerability scanning
- Build promotion
- High availability
Setup:
- Install/access Artifactory instance
- Create Cargo repository
- Configure authentication
- Set up replication (optional)
3. Freight (Self-Hosted)
Section titled “3. Freight (Self-Hosted)”Best for: Complete control, on-premise hosting
[registries.freight]index = "sparse+https://registry.company.com/index/"Publish:
cargo publish --registry freightFeatures:
- Open-source (MIT)
- Self-hosted
- S3-compatible storage
- PostgreSQL backend
- Docker deployment
Setup:
# Docker Composedocker-compose up -d
# Configure registryfreight init --storage s3://bucket/path
# Add usersfreight user add username --adminLinks: https://github.com/tantaman/freight
4. Kellnr (Self-Hosted)
Section titled “4. Kellnr (Self-Hosted)”Best for: Simple self-hosted option, small teams
[registries.kellnr]index = "sparse+https://kellnr.company.com/api/v1/crates"Publish:
cargo publish --registry kellnrFeatures:
- Written in Rust
- Simple deployment (single binary)
- Web UI
- Local cache/mirror
- Lightweight
Setup:
# Download binarywget https://github.com/kellnr/kellnr/releases/latest/download/kellnr
# Run./kellnr --port 8080Links: https://kellnr.io/
5. Romt (Read-Only Mirror)
Section titled “5. Romt (Read-Only Mirror)”Best for: Offline/air-gapped environments
# Download full crates.io mirrorromt download --crates --index
# Serve locallyromt serveConfigure:
[source.crates-io]replace-with = "romt-mirror"
[source.romt-mirror]registry = "sparse+http://localhost:8000/index/"Features:
- Complete crates.io mirror
- Offline development
- Air-gapped networks
- Bandwidth savings
Links: https://github.com/drmikehenry/romt
6. Shipyard (Self-Hosted)
Section titled “6. Shipyard (Self-Hosted)”Best for: Kubernetes-native deployments
[registries.shipyard]index = "sparse+https://shipyard.k8s.company.com/index/"Deploy:
apiVersion: apps/v1kind: Deploymentmetadata: name: shipyardspec: replicas: 3 template: spec: containers: - name: shipyard image: shipyard/server:latest env: - name: STORAGE_BACKEND value: s3Features:
- Kubernetes-native
- Horizontal scaling
- Cloud storage backends
- High availability
Configuration
Section titled “Configuration”Global Config
Section titled “Global Config”~/.cargo/config.toml:
# Define registries[registries.company]index = "sparse+https://registry.company.com/index/"token = "Bearer YOUR_TOKEN"
[registries.staging]index = "sparse+https://staging-registry.company.com/index/"
# Set default registry[registry]default = "company"
# Configure crates.io as backup[source.crates-io]registry = "https://github.com/rust-lang/crates.io-index"Project Config
Section titled “Project Config”.cargo/config.toml:
[registries.internal]index = "sparse+https://internal.company.com/index/"
# Publish to internal registry by default[registry]default = "internal"
# Allow dependencies from multiple registries[source.crates-io]registry = "https://github.com/rust-lang/crates.io-index"Dependency Sources
Section titled “Dependency Sources”[dependencies]# From crates.io (default)serde = "1.0"
# From alternative registryinternal-lib = { version = "0.1", registry = "company" }
# From Gitcustom = { git = "https://github.com/user/custom.git" }
# From local pathdev-tool = { path = "../dev-tool" }Publishing Workflow
Section titled “Publishing Workflow”Manual Publishing
Section titled “Manual Publishing”# Login to registrycargo login --registry company
# Publishcargo publish --registry company
# Verifycargo search --registry company my-crateCI/CD Publishing
Section titled “CI/CD Publishing”GitHub Actions:
- name: Publish to internal registry env: CARGO_REGISTRIES_COMPANY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | cargo publish --registry company --token $CARGO_REGISTRIES_COMPANY_TOKENEnvironment Variables:
export CARGO_REGISTRIES_COMPANY_TOKEN="your-token"cargo publish --registry companyRegistry Mirror/Cache
Section titled “Registry Mirror/Cache”Use Case: Reduce crates.io Load
Section titled “Use Case: Reduce crates.io Load”[source.crates-io]replace-with = "company-mirror"
[source.company-mirror]registry = "sparse+https://mirror.company.com/crates.io/"Benefits:
- Faster builds (geographic proximity)
- Reduced external bandwidth
- Continued access during crates.io outages
- Compliance with network policies
Implement Mirror
Section titled “Implement Mirror”With Romt:
# Sync crates.io dailyromt download --crates --index --update
# Serve via nginx/apacheromt serve --host 0.0.0.0 --port 8080With Cloudsmith:
- Configure upstream proxy
- Automatic caching
- CDN distribution
Security Considerations
Section titled “Security Considerations”1. Authentication
Section titled “1. Authentication”# Token-based[registries.secure]index = "sparse+https://registry.company.com/index/"token = "Bearer YOUR_TOKEN"
# Credential provider[registries.secure]credential-provider = "cargo:token"2. TLS/HTTPS
Section titled “2. TLS/HTTPS”# Enforce HTTPS[registries.company]index = "sparse+https://registry.company.com/index/" # ✅
# Never use HTTP for sensitive dataindex = "sparse+http://registry.company.com/index/" # ❌3. Access Control
Section titled “3. Access Control”Most registries support:
- User authentication
- Team-based permissions
- Read/write separation
- IP allowlists
- Audit logging
4. Package Signing
Section titled “4. Package Signing”# Sign packagecargo package --sign
# Verify signaturecargo verify my-crate-0.1.0.crateMigration Strategies
Section titled “Migration Strategies”From crates.io to Private Registry
Section titled “From crates.io to Private Registry”Phase 1: Parallel Publishing
# Publish to bothcargo publish # crates.iocargo publish --registry company # privatePhase 2: Update Dependencies
[dependencies]my-crate = { version = "0.2", registry = "company" }Phase 3: Deprecate Public
- Archive crates.io package
- Update README with migration notice
From Private to Public
Section titled “From Private to Public”Checklist:
- Remove proprietary code
- Add proper licensing
- Security review
- Documentation
- CI/CD for crates.io
Troubleshooting
Section titled “Troubleshooting”Authentication Fails
Section titled “Authentication Fails”# Check tokencargo login --registry company
# DebugCARGO_LOG=cargo::ops::registry=trace cargo publish --registry companyIndex Not Found
Section titled “Index Not Found”# Verify index URLcurl https://registry.company.com/index/
# Check networkping registry.company.comSlow Publish
Section titled “Slow Publish”# Check package sizecargo package --list | wc -l
# Exclude unnecessary files# .cargo/config.toml[package]exclude = [ "tests/fixtures/*", "*.tmp",]Cost Comparison
Section titled “Cost Comparison”| Registry | Hosting | Cost | Best For |
|---|---|---|---|
| crates.io | Public | Free | Open source |
| Cloudsmith | SaaS | $50+/mo | Commercial |
| Artifactory | Self/Cloud | $$$$ | Enterprise |
| Kellnr | Self-hosted | Free | Small teams |
| Freight | Self-hosted | Free | Control freaks |
| Romt | Self-hosted | Free | Air-gapped |
Best Practices
Section titled “Best Practices”- Use sparse index - Faster than git index
- Mirror crates.io - Reduce external dependencies
- Automate publishing - CI/CD integration
- Version carefully - Follow semver strictly
- Document privately - Internal registry docs
- Test thoroughly - Before publishing
- Backup regularly - Registry data