A container registry that plugs into your own auth.

Self-hostable. OCI-compatible. Built-in cleanup for keep-latest, TTL, and idle tags.

~ login. tag. push.
$echo "$AOCR_TOKEN" | docker login registry.example.com -u "$AOCR_LOGIN" --password-stdin
$docker build -t registry.example.com/team/my-image:main--ttl-7d .
$docker push registry.example.com/team/my-image:main--ttl-7d

What you get

Own the auth boundary. Let the registry own lifecycle.

Pluggable token auth

Point VALIDATION_SERVICE_URL at your auth host and let AOCR validate presented tokens against /api/auth/info.

Built-in cleanup modes

Plain tags stay latest-only. --ttl-* expires by age. --idle-* expires by inactivity.

Mirror-aware provenance

AOCR models pushed, mirrored, and cluster-snapshot artifacts so inventory and retention cover more than direct pushes.

OCI compatible

Works with Docker, Helm, and other OCI-native tooling. Standard clients in, standard pulls and pushes out.

Inventory and ownership model

Manifests and blobs live in S3-compatible storage; PostgreSQL tracks users, repositories, pulls, digests, expiry, and provenance.

Self-hosted by default

Run the stack locally with Docker Compose or deploy with Helm and Ansible, complete with hooks, reaping, and observability.

Wire it up

Standard Docker and Helm commands, with cleanup-aware tags.

Authenticate with a matching identity and push a plain tag that follows keep-latest cleanup
$export AOCR_REGISTRY=registry.example.com
$echo "$AOCR_TOKEN" | docker login "$AOCR_REGISTRY" -u "$AOCR_LOGIN" --password-stdin
$docker build -t "${AOCR_REGISTRY}/team/my-app:main" .
$docker push "${AOCR_REGISTRY}/team/my-app:main"
$docker pull "${AOCR_REGISTRY}/team/my-app:main"

Token-based access

AOCR does not require one specific identity product.

Any auth layer that exposes the auth-info contract below can sit in front of AOCR.

Step 1

Point AOCR at your auth host

Configure VALIDATION_SERVICE_URL to your identity layer. AOCR validates presented tokens by calling your auth host's auth-info endpoint.

If the configured host does not already end with /api/auth/info, AOCR appends that path automatically.

Step 2

Use the token as the password

Docker and Helm clients present Basic auth. The token is the password, and the login name only has to match the validated profile.

AOCR accepts a presented identity that matches externalId, username, or email from the auth-info response.

Step 3

Let AOCR issue the registry JWT

After validation succeeds, AOCR returns a Docker-compatible bearer token so users can push images or Helm charts with normal OCI tooling.

Internal hook secrets, cluster PATs, and other deployment-only credentials stay inside the registry stack.

Validation request

GET https://auth.example.com/api/auth/info
Authorization: Bearer <presented token>

Expected response shape

{
  "user": {
    "id": "user_123",
    "username": "suman",
    "email": "suman@example.com"
  },
  "authProvider": "custom-sso"
}

Identity match rules

Required: user.id

Recommended for human login flows: user.username and/or user.email

Presented login values from docker login -u or the token endpoint account query must match one of those validated fields.

Copyable login flow

$export AOCR_REGISTRY="registry.example.com"
$export AOCR_LOGIN="user@example.com"
$export AOCR_TOKEN="issued-by-your-auth-layer"
$echo "$AOCR_TOKEN" | docker login "$AOCR_REGISTRY" -u "$AOCR_LOGIN" --password-stdin
$docker build -t "${AOCR_REGISTRY}/team/my-app:main--ttl-7d" .
$docker push "${AOCR_REGISTRY}/team/my-app:main--ttl-7d"

Use cases

Built for real workflows, not demos.

Plug AOCR into an existing control plane that already issues user tokens. AOCR only needs the auth-info contract.

Cleanup

Plain tags stay latest. Suffixes opt into TTL or idle expiry.

plain tags

Keep latest

Newest non-suffixed tag survives per repository.

--ttl-7d

Age TTL

Expires seven days after push. Windows from 1h to 365d.

--idle-30d

Idle TTL

Expires only after 30 days without pulls.

provenance

Mirror + snapshot aware

/v1/images exposes pushed, mirror, and cluster-snapshot retention metadata.

Manifest cleanup is automatic. Physical blob reclamation runs through registry garbage collection on its own maintenance schedule.