Skip to main content

Your First Private Registry

Set up a registry with user authentication and access control policies.

What You'll Learn

By the end of this tutorial, you will:

  • Create a user with password authentication
  • Configure an access control policy
  • Test authenticated push and pull operations

Prerequisites

  • Completed the Quickstart tutorial
  • Angos binary available

Step 1: Generate a Password Hash

Angos uses Argon2 for secure password hashing. Generate a hash for your user:

./angos argon

When prompted, enter a password. The tool outputs an Argon2 hash:

Input Password:
$argon2id$v=19$m=19456,t=2,p=1$...

Copy this hash for the next step.

Step 2: Configure Authentication

Update your config.toml to add a user identity:

[server]
bind_address = "0.0.0.0"
port = 5000

[blob_store.fs]
root_dir = "./registry-data"

[repository."test"]

[auth.identity.alice]
username = "alice"
password = "$argon2id$v=19$m=19456,t=2,p=1$..." # Paste your hash here

Step 3: Add an Access Control Policy

Add a global access policy that requires authentication:

[global.access_policy]
default_allow = false
rules = [
"identity.username != null"
]

Your complete config.toml should now look like:

[server]
bind_address = "0.0.0.0"
port = 5000

[blob_store.fs]
root_dir = "./registry-data"

[auth.identity.alice]
username = "alice"
password = "$argon2id$v=19$m=19456,t=2,p=1$..."

[global.access_policy]
default_allow = false
rules = [
"identity.username != null"
]

[repository."test"]

Step 4: Configure Docker for Insecure Registry

Since this tutorial uses HTTP (no TLS), configure Docker to allow insecure connections.

Edit or create /etc/docker/daemon.json:

{
"insecure-registries": ["localhost:5000"]
}

Then restart Docker:

# Linux
sudo systemctl restart docker

# macOS (Docker Desktop)
# Restart Docker Desktop from the menu bar

Step 5: Start the Registry

./angos -c config.toml server

Step 6: Test Anonymous Access (Should Fail)

Try to push without authentication:

docker tag alpine:latest localhost:5000/test/alpine:latest
docker push localhost:5000/test/alpine:latest

You should see an authentication error:

unauthorized: Access denied

Step 7: Login and Push

Login with your credentials:

docker login localhost:5000 -u alice

Enter your password when prompted. Now push the image:

docker push localhost:5000/test/alpine:latest

The push should succeed.

Step 8: Verify the Configuration

You can also verify using curl:

# Without auth (should fail)
curl http://localhost:5000/v2/

# With auth (should succeed)
curl -u alice:yourpassword http://localhost:5000/v2/

Understanding the Policy

The access policy uses CEL (Common Expression Language):

rules = [
"identity.username != null"
]

This rule allows access when identity.username is not empty, meaning the user has authenticated with valid credentials.

What's Next?

Now that you have a private registry, you can:

Reference