Self-hosted container registry access control and audit logging
One self-hosted Docker registry proxy. Scoped credentials, granular access control, pull-through caching, and a full audit trail — for ghcr.io, Docker Hub, ECR, and any V2 registry.
One proxy. Every registry you use.
Configure backend registries once. Drevnix encrypts and stores credentials with AES256-GCM. Developers and CI systems only ever see Drevnix client credentials, never the upstream passwords.
- ✓ ghcr.io (GitHub Container Registry)
- ✓ Docker Hub
- ✓ Amazon ECR
- ✓ Google Artifact Registry / GCR
- ✓ Any Docker Registry V2 instance
Example upstream config
ghcr GitHub Container Registry https://ghcr.io dockerhub Docker Hub https://registry-1.docker.io ecr-prod AWS ECR https://123.dkr.ecr.us-east-1.amazonaws.com Client identities
ci-pipeline-prod GitHub Actions dev-alice Developer contractor-bob Contractor Docker registry scoped credentials for every client
Clients are lightweight identities separate from upstream accounts. Each gets its own scoped credentials, its own permission set, and optionally an expiration date. Revoking a client has no effect on the upstream registry.
- ✓ Passwords hashed (bcrypt) — never recoverable or readable
- ✓ Expired clients receive 401 automatically — no manual cleanup
- ✓ Manage via web portal or REST API
Every client sees exactly what it needs. Nothing else.
Permissions define which repositories a client can pull. Default is deny-all. Wildcards let you scope broadly or narrowly. A single permission covers everything under a namespace.
- ! Wildcards (
*) can only appear at the END of a pattern - ✓ A client can have multiple permission entries
- ✓ Any match grants access — no match returns 403
| Pattern | Allows |
|---|---|
* | Everything — all upstreams, all repositories |
ghcr/* | All repositories on the ghcr upstream |
ghcr/myorg/* | All images under ghcr/myorg/ |
ghcr/myorg/api | Exactly one image on ghcr |
dockerhub/library/nginx | Exactly one image on Docker Hub |
| Variable | Default | Description |
|---|---|---|
CACHE_ENABLED | false | Enable pull-through blob cache |
CACHE_DIR | — | Directory path for cached blobs |
CACHE_MAX_SIZE_BYTES | 10737418240 | Max cache size (10GB default) |
CACHE_ENTRY_TTL_SECONDS | 86400 | Cache entry lifetime (24h) |
CACHE_MIN_HITS_SHORT | 3 | Hits needed in short window to cache |
CACHE_WINDOW_SHORT_SECONDS | 600 | Short admission window (10min) |
CACHE_MIN_HITS_LONG | 10 | Hits needed in long window to cache |
CACHE_WINDOW_LONG_SECONDS | 3600 | Long admission window (1h) |
Pull once. Serve many.
Drevnix is a self-hosted Docker pull caching proxy: image blobs (layers) are written to local disk after the first pull. Subsequent pulls of the same layer skip the upstream entirely — no rate limit hits, no redundant bandwidth.
Only caches a blob after it's requested enough times (configurable windows). Prevents one-off images from filling the cache.
- ✓ Blob-level cache (content-addressed by digest)
- ✓ Configurable max size, TTL, and admission windows
- ✓ Disk usage and cache health visible in admin portal
Know who pulled what, every time.
Every manifest pull attempt is logged with client identity, upstream, repo, tag, status, IP, and UTC timestamp. The docker registry audit log is the compliance foundation of Drevnix: searchable, filterable, and exportable — a complete docker pull audit trail for SOC 2, ISO 27001, and internal security reviews.
- ✓ Client ID — who made the request
- ✓ Upstream ID — which registry was accessed
- ✓ Repository + tag/digest
- ✓ HTTP status (200, 401, 403, 404…)
- ✓ Client IP (respects X-Forwarded-For)
- ✓ UTC timestamp, millisecond precision
| client | upstream | repo | status |
|---|---|---|---|
| ci-pipeline | ghcr | myorg/api:v2.1 | 200 |
| dev-alice | dockerhub | library/nginx:latest | 200 |
| unknown | ghcr | myorg/api:v2.1 | 401 |
| dev-bob | ecr-prod | api-service:stable | 403 |