Self-Hosting
The DUUMBI registry ships as a single Docker image. It uses SQLite for metadata and the local filesystem for module archives — no external databases or services required.
Prerequisites
Section titled “Prerequisites”- Docker and Docker Compose v2+
- (Optional) A reverse proxy for TLS — Caddy, nginx, or Traefik
Quick start
Section titled “Quick start”# Generate a JWT secret (required)export JWT_SECRET=$(openssl rand -hex 32)
# Start the registrydocker compose up -dThe registry is now available at http://localhost:8080. Verify:
curl http://localhost:8080/health# okUsers can register at http://localhost:8080/register and manage API tokens at /settings/tokens.
Configuration
Section titled “Configuration”All configuration is via environment variables:
| Variable | Default | Description |
|---|---|---|
DUUMBI_PORT | 8080 | Server listen port |
DUUMBI_DB | registry.db | SQLite database path |
DUUMBI_STORAGE | storage | Module archive directory |
RUST_LOG | duumbi_registry=info | Log level (tracing) |
AUTH_MODE | local_password | Auth mode: local_password or github_oauth |
JWT_SECRET | — | Required. Secret for signing session tokens |
BASE_URL | http://localhost:8080 | Public URL (used in OAuth callbacks) |
GITHUB_CLIENT_ID | — | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET | — | GitHub OAuth app client secret |
docker-compose.yml example
Section titled “docker-compose.yml example”services: registry: build: . ports: - "9090:8080" volumes: - ./my-data:/data environment: - JWT_SECRET=${JWT_SECRET} - RUST_LOG=duumbi_registry=debug,tower_http=debugTLS with a reverse proxy
Section titled “TLS with a reverse proxy”In production, place a reverse proxy in front of the registry for TLS termination.
Caddy example
Section titled “Caddy example”registry.mycompany.com { reverse_proxy localhost:8080}Caddy automatically provisions Let’s Encrypt certificates.
nginx example
Section titled “nginx example”server { listen 443 ssl; server_name registry.mycompany.com;
ssl_certificate /etc/letsencrypt/live/registry.mycompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.mycompany.com/privkey.pem;
location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; }}Data persistence
Section titled “Data persistence”All data is stored under /data in the container:
/data/registry.db— SQLite database (modules, versions, users, tokens)/data/modules/—.tar.gzarchives organized as@scope/name/version.tar.gz
The default docker-compose.yml uses a named volume (registry-data) that persists across container restarts and rebuilds.
Backup and restore
Section titled “Backup and restore”# Backupdocker compose exec registry cp /data/registry.db /data/registry.db.bakdocker compose cp registry:/data ./backup
# Restoredocker compose downdocker compose cp ./backup/. registry:/datadocker compose up -dGitHub OAuth setup
Section titled “GitHub OAuth setup”To use GitHub OAuth instead of local passwords:
- Create a GitHub OAuth App at github.com/settings/developers
- Set the callback URL to
https://your-registry.example.com/auth/github/callback - Configure the environment variables:
AUTH_MODE=github_oauthGITHUB_CLIENT_ID=your_client_idGITHUB_CLIENT_SECRET=your_client_secretJWT_SECRET=$(openssl rand -hex 32)BASE_URL=https://your-registry.example.comWith GitHub OAuth enabled, users sign in via “Sign in with GitHub” on the web UI. The CLI supports a device code flow for headless authentication — see Authentication.
Client configuration
Section titled “Client configuration”On the DUUMBI client side, point your project at the private registry:
# Add registryduumbi registry add company https://registry.mycompany.com
# Authenticateduumbi registry login company --token duu_your_token_here
# Use modules from the private registryduumbi deps add @company/my-moduleOr edit .duumbi/config.toml directly:
[registries]company = "https://registry.mycompany.com"
[dependencies]"@company/my-module" = { version = "1.0.0", registry = "company" }