The docker run command was truncated, missing the image reference. This caused a bash syntax error (unexpected do token) when the for loop was parsed as part of the docker run arguments.
NORA
The artifact registry that grows with you. Starts with docker run, scales to enterprise.
docker run -d -p 4000:4000 -v nora-data:/data ghcr.io/getnora-io/nora:latest
Open http://localhost:4000/ui/ — your registry is ready.
Why NORA
- Zero-config — single 32 MB binary, no database, no dependencies.
docker runand it works. - Production-tested — Docker (+ Helm OCI), Maven, npm, PyPI, Cargo, Go, Raw. Used in real CI/CD with ArgoCD, Buildx cache, and air-gapped environments.
- Secure by default — OpenSSF Scorecard, signed releases, SBOM, fuzz testing, 460+ tests.
32 MB binary | < 100 MB RAM | 3s startup | 7 registries
Used in production at DevIT Academy since January 2026 for Docker images, Maven artifacts, and npm packages.
Supported Registries
| Registry | Mount Point | Upstream Proxy | Auth |
|---|---|---|---|
| Docker Registry v2 | /v2/ |
Docker Hub, GHCR, any OCI, Helm OCI | ✓ |
| Maven | /maven2/ |
Maven Central, custom | proxy-only |
| npm | /npm/ |
npmjs.org, custom | ✓ |
| Cargo | /cargo/ |
— | ✓ |
| PyPI | /simple/ |
pypi.org, custom | ✓ |
| Go Modules | /go/ |
proxy.golang.org, custom | ✓ |
| Raw files | /raw/ |
— | ✓ |
Helm charts work via the Docker/OCI endpoint —
helm push/pullwith--plain-httpor behind TLS reverse proxy.
Quick Start
Docker (Recommended)
docker run -d -p 4000:4000 -v nora-data:/data ghcr.io/getnora-io/nora:latest
Binary
curl -fsSL https://github.com/getnora-io/nora/releases/latest/download/nora-linux-amd64 -o nora
chmod +x nora && ./nora
From Source
cargo install nora-registry
nora
Usage
Docker Images
docker tag myapp:latest localhost:4000/myapp:latest
docker push localhost:4000/myapp:latest
docker pull localhost:4000/myapp:latest
Maven
<!-- settings.xml -->
<server>
<id>nora</id>
<url>http://localhost:4000/maven2/</url>
</server>
npm
npm config set registry http://localhost:4000/npm/
npm publish
Go Modules
GOPROXY=http://localhost:4000/go go get golang.org/x/text@latest
Features
- Web UI — dashboard with search, browse, i18n (EN/RU)
- Proxy & Cache — transparent proxy to upstream registries with local cache
- Mirror CLI — offline sync for air-gapped environments (
nora mirror) - Backup & Restore —
nora backup/nora restore - Migration —
nora migrate --from local --to s3 - S3 Storage — MinIO, AWS S3, any S3-compatible backend
- Prometheus Metrics —
/metricsendpoint - Health Checks —
/health,/readyfor Kubernetes probes - Swagger UI —
/api-docsfor API exploration - Rate Limiting — configurable per-endpoint rate limits
- FSTEC Builds — Astra Linux SE and RED OS images in every release
Authentication
NORA supports Basic Auth (htpasswd) and revocable API tokens with RBAC.
# Create htpasswd file
htpasswd -cbB users.htpasswd admin yourpassword
# Start with auth enabled
docker run -d -p 4000:4000 \
-v nora-data:/data \
-v ./users.htpasswd:/data/users.htpasswd \
-e NORA_AUTH_ENABLED=true \
ghcr.io/getnora-io/nora:latest
| Role | Pull/Read | Push/Write | Delete/Admin |
|---|---|---|---|
read |
Yes | No | No |
write |
Yes | Yes | No |
admin |
Yes | Yes | Yes |
See Authentication guide for token management, Docker login, and CI/CD integration.
Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
NORA_HOST |
127.0.0.1 | Bind address |
NORA_PORT |
4000 | Port |
NORA_STORAGE_MODE |
local | local or s3 |
NORA_AUTH_ENABLED |
false | Enable authentication |
NORA_DOCKER_UPSTREAMS |
https://registry-1.docker.io |
Docker upstreams (url|user:pass,...) |
NORA_LOG_LEVEL |
info | Log level: trace, debug, info, warn, error |
NORA_LOG_FORMAT |
text | Log format: text (human) or json (structured) |
NORA_PUBLIC_URL |
— | Public URL for rewriting artifact links |
| See full configuration reference for all options. |
config.toml
[server]
host = "0.0.0.0"
port = 4000
[storage]
mode = "local"
path = "data/storage"
[auth]
enabled = false
htpasswd_file = "users.htpasswd"
[docker]
proxy_timeout = 60
[[docker.upstreams]]
url = "https://registry-1.docker.io"
[go]
proxy = "https://proxy.golang.org"
CLI Commands
nora # Start server
nora serve # Start server (explicit)
nora backup -o backup.tar.gz
nora restore -i backup.tar.gz
nora migrate --from local --to s3
nora mirror # Sync packages for offline use
Endpoints
| URL | Description |
|---|---|
/ui/ |
Web UI |
/api-docs |
Swagger UI |
/health |
Health check |
/ready |
Readiness probe |
/metrics |
Prometheus metrics |
/v2/ |
Docker Registry |
/maven2/ |
Maven |
/npm/ |
npm |
/cargo/ |
Cargo |
/simple/ |
PyPI |
/go/ |
Go Modules |
TLS / HTTPS
NORA serves plain HTTP. Use a reverse proxy for TLS:
registry.example.com {
reverse_proxy localhost:4000
}
See TLS / HTTPS guide for Nginx, Traefik, and custom CA setup.
Performance
| Metric | NORA | Nexus | JFrog |
|---|---|---|---|
| Startup | < 3s | 30-60s | 30-60s |
| Memory | < 100 MB | 2-4 GB | 2-4 GB |
| Image Size | 32 MB | 600+ MB | 1+ GB |
See how NORA compares to other registries
Roadmap
- Mirror CLI — offline sync for air-gapped environments
- OIDC / Workload Identity — zero-secret auth for GitHub Actions, GitLab CI
- Online Garbage Collection — non-blocking cleanup without registry downtime
- Retention Policies — declarative rules: keep last N tags, delete older than X days
- Image Signing — cosign verification and policy enforcement
See CHANGELOG.md for release history.
Security & Trust
- Signed releases — every release is signed with cosign
- SBOM — SPDX + CycloneDX in every release
- Fuzz testing — cargo-fuzz + ClusterFuzzLite
- Blob verification — SHA256 digest validation on every upload
- Non-root containers — all images run as non-root
- Security headers — CSP, X-Frame-Options, nosniff
See SECURITY.md for vulnerability reporting.
Author
Created and maintained by DevITWay
- Website: getnora.dev
- Telegram: @getnora
- GitHub: @devitway
Contributing
NORA welcomes contributions! See CONTRIBUTING.md for guidelines.
License
MIT License — see LICENSE
Copyright (c) 2026 DevITWay
