2025-10-07 10:58:11 -05:00
2025-10-02 11:03:59 -05:00
2025-10-07 10:58:11 -05:00
2025-10-04 21:19:49 -05:00
2025-10-07 10:58:11 -05:00
2025-10-02 20:02:59 -05:00
2025-10-07 10:58:11 -05:00
2025-10-03 15:55:45 -05:00
2025-10-02 11:03:59 -05:00
2025-10-06 21:59:57 -05:00
2025-10-06 17:39:21 -05:00
2025-10-02 11:03:59 -05:00
2025-10-07 10:58:11 -05:00
2025-10-07 10:58:11 -05:00
2025-10-02 11:03:59 -05:00
2025-10-03 15:55:45 -05:00

ATCR - ATProto Container Registry

A container registry that uses the AT Protocol (ATProto) for manifest storage and S3 for blob storage.

Overview

ATCR is an OCI-compliant container registry that integrates with the AT Protocol ecosystem. It stores container image manifests as ATProto records in Personal Data Servers (PDS) while keeping the actual image layers in S3-compatible storage.

Architecture

  • Manifests: Stored as ATProto records in user PDSs (small JSON metadata)
  • Blobs/Layers: Stored in S3 (large binary data)
  • Name Resolution: Supports both ATProto handles and DIDs
    • atcr.io/alice.bsky.social/myimage:latest
    • atcr.io/did:plc:xyz123/myimage:latest

Features

  • OCI Distribution Spec compliant
  • ATProto-native manifest storage
  • S3 blob storage for container layers
  • DID/handle resolution
  • Decentralized manifest ownership

Building

# Build all binaries locally
go build -o atcr-registry ./cmd/registry
go build -o atcr-hold ./cmd/hold
go build -o docker-credential-atcr ./cmd/credential-helper

# Build Docker images
docker build -t atcr.io/registry:latest .
docker build -f Dockerfile.hold -t atcr.io/hold:latest .

Quick Start (Local Testing)

Automated setup:

# Run the test script (handles everything)
./test-local.sh

The script will:

  1. Create necessary directories (/var/lib/atcr/*)
  2. Build all binaries
  3. Start registry and hold service
  4. Show you how to test

Manual setup:

# 1. Create directories
sudo mkdir -p /var/lib/atcr/{blobs,hold,auth}
sudo chown -R $USER:$USER /var/lib/atcr

# 2. Build binaries
go build -o atcr-registry ./cmd/registry
go build -o atcr-hold ./cmd/hold

# 3. Configure environment
cp .env.example .env
# Edit .env - set ATPROTO_HANDLE and HOLD_PUBLIC_URL
export $(cat .env | xargs)

# 4. Start services
# Terminal 1:
./atcr-registry serve config/config.yml
# Terminal 2 (will prompt for OAuth):
./atcr-hold config/hold.yml
# Follow OAuth URL in logs to authorize

# 5. Test with Docker
docker tag alpine:latest localhost:5000/alice/alpine:test
docker push localhost:5000/alice/alpine:test
docker pull localhost:5000/alice/alpine:test

Running

Local Development

Configure environment:

# Copy and edit .env file
cp .env.example .env
# Edit .env with:
# - ATPROTO_HANDLE (your Bluesky handle)
# - HOLD_PUBLIC_URL (e.g., http://127.0.0.1:8080 or https://hold1.atcr.io)
# - HOLD_AUTO_REGISTER=true

# Load environment
export $(cat .env | xargs)

AppView (Registry):

./atcr-registry serve config/config.yml

Hold (Storage Service):

# Starts OAuth flow to register in your PDS
./atcr-hold config/hold.yml
# Follow the OAuth URL in the logs to authorize

Docker

Run with Docker Compose:

docker-compose up -d

Or run containers separately:

AppView (Registry):

docker run -d \
  --name atcr-registry \
  -p 5000:5000 \
  -e ATPROTO_DID=did:plc:your-did \
  -e ATPROTO_ACCESS_TOKEN=your-access-token \
  -e AWS_ACCESS_KEY_ID=your-aws-key \
  -e AWS_SECRET_ACCESS_KEY=your-aws-secret \
  -v $(pwd)/config/config.yml:/etc/atcr/config.yml \
  atcr.io/registry:latest

Hold (Storage Service):

docker run -d \
  --name atcr-hold \
  -p 8080:8080 \
  -e AWS_ACCESS_KEY_ID=your-aws-key \
  -e AWS_SECRET_ACCESS_KEY=your-aws-secret \
  -v $(pwd)/config/hold.yml:/etc/atcr/hold.yml \
  atcr.io/hold:latest

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: atcr-registry
spec:
  replicas: 3
  selector:
    matchLabels:
      app: atcr-registry
  template:
    metadata:
      labels:
        app: atcr-registry
    spec:
      containers:
      - name: registry
        image: atcr.io/registry:latest
        ports:
        - containerPort: 5000
        env:
        - name: ATPROTO_DID
          valueFrom:
            secretKeyRef:
              name: atcr-secrets
              key: did
        - name: ATPROTO_ACCESS_TOKEN
          valueFrom:
            secretKeyRef:
              name: atcr-secrets
              key: access-token
        volumeMounts:
        - name: config
          mountPath: /etc/atcr
      volumes:
      - name: config
        configMap:
          name: atcr-config

Configuration

See config/config.yml for full configuration options.

Key settings:

  • storage.s3: S3 bucket configuration for blob storage
  • middleware.repository: ATProto routing middleware
  • middleware.registry: Name resolution middleware

Usage

Pushing an Image

# Tag your image
docker tag myapp:latest atcr.io/alice/myapp:latest

# Push to ATCR
docker push atcr.io/alice/myapp:latest

Pulling an Image

# Pull from ATCR
docker pull atcr.io/alice/myapp:latest

Development

Project Structure

atcr.io/
├── cmd/registry/          # Main entrypoint
├── pkg/
│   ├── atproto/          # ATProto client and manifest store
│   ├── storage/          # S3 blob store and routing
│   ├── middleware/       # Registry and repository middleware
│   └── server/           # HTTP handlers
├── config/               # Configuration files
└── Dockerfile

Testing

# Run tests
go test ./...

# Run with race detector
go test -race ./...

License

MIT

Contributing

Contributions welcome! Please open an issue or PR.

Description
No description provided
Readme 126 MiB
Languages
Go 88.4%
HTML 8%
Shell 1.2%
JavaScript 1.2%
CSS 0.8%
Other 0.3%