A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
atcr.io
docker
container
atproto
go
1# ATCR Hold Service Configuration
2# Generated with defaults — edit as needed.
3
4# Configuration format version.
5version: "0.1"
6# Log level: debug, info, warn, error.
7log_level: info
8# Remote log shipping settings.
9log_shipper:
10 # Log shipping backend: "victoria", "opensearch", or "loki". Empty disables shipping.
11 backend: ""
12 # Remote log service endpoint, e.g. "http://victorialogs:9428".
13 url: ""
14 # Number of log entries to buffer before flushing to the remote service.
15 batch_size: 100
16 # Maximum time between flushes, even if batch is not full.
17 flush_interval: 5s
18 # Basic auth username for the log service (optional).
19 username: ""
20 # Basic auth password for the log service (optional).
21 password: ""
22# S3-compatible blob storage settings.
23storage:
24 # S3-compatible access key (AWS, Storj, Minio, UpCloud).
25 access_key: ""
26 # S3-compatible secret key.
27 secret_key: ""
28 # S3 region, e.g. "us-east-1". Used for request signing.
29 region: us-east-1
30 # S3 bucket for blob storage (REQUIRED). Must already exist.
31 bucket: ""
32 # Custom S3 endpoint for non-AWS providers (e.g. "https://gateway.storjshare.io").
33 endpoint: ""
34 # CDN pull zone URL for downloads. When set, presigned GET/HEAD URLs use this host instead of the S3 endpoint. Uploads and API calls still use the S3 endpoint.
35 pull_zone: ""
36# HTTP server and identity settings.
37server:
38 # Listen address, e.g. ":8080" or "0.0.0.0:8080".
39 addr: :8080
40 # Externally reachable URL used for did:web identity (REQUIRED), e.g. "https://hold.example.com".
41 public_url: ""
42 # Allow unauthenticated blob reads. If false, readers need crew membership.
43 public: false
44 # DID of successor hold for migration. Appview redirects all requests to the successor.
45 successor: ""
46 # Use localhost for OAuth redirects during development.
47 test_mode: false
48 # Request crawl from this relay on startup to make the embedded PDS discoverable.
49 relay_endpoint: ""
50 # DID of the appview this hold is managed by (e.g. did:web:atcr.io). Resolved via did:web for URL and public key.
51 appview_did: did:web:172.28.0.2%3A5000
52 # Read timeout for HTTP requests.
53 read_timeout: 5m0s
54 # Write timeout for HTTP requests.
55 write_timeout: 5m0s
56# Auto-registration and bootstrap settings.
57registration:
58 # DID of the hold captain. If set, auto-creates captain and profile records on startup.
59 owner_did: ""
60 # Create a wildcard crew record allowing any authenticated user to join.
61 allow_all_crew: false
62 # URL to fetch avatar image from during bootstrap.
63 profile_avatar_url: https://atcr.io/web-app-manifest-192x192.png
64 # Bluesky profile display name. Synced on every startup.
65 profile_display_name: Cargo Hold
66 # Bluesky profile description. Synced on every startup.
67 profile_description: ahoy from the cargo hold
68 # Post to Bluesky when users push images. Synced to captain record on startup.
69 enable_bluesky_posts: false
70 # Deployment region, auto-detected from cloud metadata or S3 config.
71 region: ""
72# Embedded PDS database settings.
73database:
74 # Directory for the embedded PDS database (carstore + SQLite).
75 path: /var/lib/atcr-hold
76 # PDS signing key path. Defaults to {database.path}/signing.key.
77 key_path: ""
78 # DID method: 'web' (default, derived from public_url) or 'plc' (registered with PLC directory).
79 did_method: web
80 # Explicit DID for this hold. If set with did_method 'plc', adopts this identity instead of creating new. Use for recovery/migration.
81 did: ""
82 # PLC directory URL. Only used when did_method is 'plc'. Default: https://plc.directory
83 plc_directory_url: https://plc.directory
84 # Rotation key for did:plc in multibase format (starting with 'z'). Generate with: goat key generate. Supports K-256 and P-256 curves. Controls DID identity (separate from signing key).
85 rotation_key: ""
86 # libSQL sync URL (libsql://...). Works with Turso cloud, Bunny DB, or self-hosted libsql-server. Leave empty for local-only SQLite.
87 libsql_sync_url: ""
88 # Auth token for libSQL sync. Required if libsql_sync_url is set.
89 libsql_auth_token: ""
90 # How often to sync with remote libSQL server. Default: 60s.
91 libsql_sync_interval: 1m0s
92# Admin panel settings.
93admin:
94 # Enable the web-based admin panel for crew and storage management.
95 enabled: true
96# Garbage collection settings.
97gc:
98 # Enable nightly garbage collection of orphaned blobs and records.
99 enabled: false
100# Storage quota tiers. Empty disables quota enforcement.
101quota:
102 # Quota tiers ordered by rank (lowest to highest). Position determines rank.
103 tiers:
104 - # Tier name used as the key for crew assignments.
105 name: free
106 # Storage quota limit (e.g. "5GB", "50GB", "1TB").
107 quota: 5GB
108 # Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
109 scan_on_push: false
110 - # Tier name used as the key for crew assignments.
111 name: deckhand
112 # Storage quota limit (e.g. "5GB", "50GB", "1TB").
113 quota: 5GB
114 # Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
115 scan_on_push: false
116 - # Tier name used as the key for crew assignments.
117 name: bosun
118 # Storage quota limit (e.g. "5GB", "50GB", "1TB").
119 quota: 50GB
120 # Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
121 scan_on_push: true
122 - # Tier name used as the key for crew assignments.
123 name: quartermaster
124 # Storage quota limit (e.g. "5GB", "50GB", "1TB").
125 quota: 100GB
126 # Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
127 scan_on_push: true
128 # Default tier assignment for new crew members.
129 defaults:
130 # Tier assigned to new crew members who don't have an explicit tier.
131 new_crew_tier: deckhand
132# Vulnerability scanner settings. Empty disables scanning.
133scanner:
134 # Shared secret for scanner WebSocket auth. Empty disables scanning.
135 secret: ""
136 # Minimum interval between re-scans of the same manifest. When set, the hold proactively scans manifests when the scanner is idle. Default: 168h (7 days). Set to 0 to disable.
137 rescan_interval: 168h0m0s