mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 08:30:29 +00:00
did:plc Identity Support (pkg/hold/pds/did.go, pkg/hold/config.go, pkg/hold/server.go) The big feature — holds can now use did:plc identities instead of only did:web. This adds: - LoadOrCreateDID() — resolves hold DID by priority: config DID > did.txt on disk > create new - CreatePLCIdentity() — builds a genesis operation, signs with rotation key, submits to PLC directory - EnsurePLCCurrent() — on boot, compares local signing key + URL against PLC directory and auto-updates if they've drifted (requires rotation key) - New config fields: did_method (web/plc), did, plc_directory_url, rotation_key_path - GenerateDIDDocument() now uses the stored DID instead of always deriving did:web from URL - NewHoldServer wired up to call LoadOrCreateDID instead of GenerateDIDFromURL CAR Export/Import (pkg/hold/pds/export.go, pkg/hold/pds/import.go, cmd/hold/repo.go) New CLI subcommands for repo backup/restore: - atcr-hold repo export — streams the hold's repo as a CAR file to stdout - atcr-hold repo import <file>... — reads CAR files, upserts all records in a single atomic commit. Uses a bulkImportRecords method that opens a delta session, checks each record for create vs update, commits once, and fires repo events. - openHoldPDS() helper to spin up a HoldPDS from config for offline CLI operations Admin UI Fixes (pkg/hold/admin/) - Logout changed from GET to POST — nav template now uses a <form method=POST> instead of an <a> link (prevents CSRF on logout) - Removed return_to parameter from login flow — simplified redirect logic, auth middleware now redirects to /admin/auth/login without query params Config/Deploy - config-hold.example.yaml and deploy/upcloud/configs/hold.yaml.tmpl updated with the four new did:plc config fields - go.mod / go.sum — added github.com/did-method-plc/go-didplc dependency
174 lines
5.6 KiB
Markdown
174 lines
5.6 KiB
Markdown
# ATCR - ATProto Container Registry
|
|
|
|
## https://atcr.io
|
|
|
|
An OCI-compliant container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
|
|
|
|
## What is ATCR?
|
|
|
|
ATCR integrates container registries with the AT Protocol ecosystem. Container image manifests are stored as ATProto records in your Personal Data Server (PDS), while layers are stored in S3-compatible storage.
|
|
|
|
**Image names use your ATProto identity:**
|
|
```
|
|
atcr.io/alice.bsky.social/myapp:latest
|
|
atcr.io/did:plc:xyz123/myapp:latest
|
|
```
|
|
|
|
## Architecture
|
|
|
|
**Three components:**
|
|
|
|
1. **AppView** - Registry API + web UI
|
|
- Serves OCI Distribution API (Docker push/pull)
|
|
- Resolves handles/DIDs to PDS endpoints
|
|
- Routes manifests to user's PDS, blobs to hold services
|
|
- Web interface for browsing/search
|
|
|
|
2. **Hold Service** - Storage service with embedded PDS (optional BYOS)
|
|
- Each hold has a full ATProto PDS for access control (captain + crew records)
|
|
- Identified by did:web (e.g., `did:web:hold01.atcr.io`)
|
|
- Generates presigned URLs for S3/Storj/Minio/etc.
|
|
- Users can deploy their own storage and control access via crew membership
|
|
|
|
3. **Credential Helper** - Client authentication
|
|
- ATProto OAuth (DPoP handled transparently)
|
|
- Automatic authentication on first push/pull
|
|
|
|
**Storage model:**
|
|
- Manifests → ATProto records in user's PDS (small JSON, includes `holdDid` reference)
|
|
- Blobs → Hold services via XRPC multipart upload (large binaries, stored in S3/etc.)
|
|
- AppView uses service tokens to communicate with holds on behalf of users
|
|
|
|
## Features
|
|
|
|
- ✅ **OCI-compliant** - Works with Docker, containerd, podman
|
|
- ✅ **Decentralized** - You own your manifest data via your PDS
|
|
- ✅ **ATProto OAuth** - Secure authentication (DPoP-compliant)
|
|
- ✅ **BYOS** - Deploy your own storage service
|
|
- ✅ **Web UI** - Browse, search, star repositories
|
|
- ✅ **Multi-backend** - S3, Storj, Minio, Azure, GCS, filesystem
|
|
|
|
## Quick Start
|
|
|
|
### Using the Registry
|
|
|
|
**1. Install credential helper:**
|
|
```bash
|
|
curl -fsSL https://atcr.io/install.sh | bash
|
|
```
|
|
|
|
**2. Configure Docker** (add to `~/.docker/config.json`):
|
|
```json
|
|
{
|
|
"credHelpers": {
|
|
"atcr.io": "atcr"
|
|
}
|
|
}
|
|
```
|
|
|
|
**3. Push/pull images:**
|
|
```bash
|
|
docker tag myapp:latest atcr.io/yourhandle/myapp:latest
|
|
docker push atcr.io/yourhandle/myapp:latest # Authenticates automatically
|
|
docker pull atcr.io/yourhandle/myapp:latest
|
|
```
|
|
|
|
See **[INSTALLATION.md](./INSTALLATION.md)** for detailed installation instructions.
|
|
|
|
### Running Your Own AppView
|
|
|
|
```bash
|
|
# Build
|
|
go build -o bin/atcr-appview ./cmd/appview
|
|
|
|
# Generate a config file with all defaults
|
|
./bin/atcr-appview config init config-appview.yaml
|
|
# Edit config-appview.yaml — set server.default_hold_did at minimum
|
|
|
|
# Run
|
|
./bin/atcr-appview serve --config config-appview.yaml
|
|
```
|
|
|
|
**Using Docker:**
|
|
```bash
|
|
docker build -f Dockerfile.appview -t atcr-appview:latest .
|
|
docker run -d -p 5000:5000 \
|
|
-v ./config-appview.yaml:/config.yaml:ro \
|
|
-v atcr-data:/var/lib/atcr \
|
|
atcr-appview:latest serve --config /config.yaml
|
|
```
|
|
|
|
See **[deploy/README.md](./deploy/README.md)** for production deployment.
|
|
|
|
### Running Your Own Hold (BYOS Storage)
|
|
|
|
See **[docs/hold.md](./docs/hold.md)** for deploying your own storage backend.
|
|
|
|
## Development
|
|
|
|
### Building from Source
|
|
|
|
```bash
|
|
# Build all binaries
|
|
go build -o bin/atcr-appview ./cmd/appview
|
|
go build -o bin/atcr-hold ./cmd/hold
|
|
go build -o bin/docker-credential-atcr ./cmd/credential-helper
|
|
|
|
# Run tests
|
|
go test ./...
|
|
go test -race ./...
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
cmd/
|
|
├── appview/ # Registry server + web UI
|
|
├── hold/ # Storage service (BYOS)
|
|
├── credential-helper/ # Docker credential helper
|
|
├── oauth-helper/ # OAuth debug tool
|
|
├── healthcheck/ # HTTP health check (for Docker)
|
|
├── db-migrate/ # SQLite → libsql migration
|
|
├── usage-report/ # Hold storage usage report
|
|
├── record-query/ # Query ATProto relay by collection
|
|
└── s3-test/ # S3 connectivity test
|
|
|
|
pkg/
|
|
├── appview/
|
|
│ ├── db/ # SQLite database (migrations, queries, stores)
|
|
│ ├── handlers/ # HTTP handlers (home, repo, search, auth, settings)
|
|
│ ├── holdhealth/ # Hold service health checker
|
|
│ ├── jetstream/ # ATProto Jetstream consumer
|
|
│ ├── middleware/ # Auth & registry middleware
|
|
│ ├── ogcard/ # OpenGraph image generation
|
|
│ ├── readme/ # Repository README fetcher
|
|
│ ├── routes/ # HTTP route registration
|
|
│ ├── storage/ # Storage routing (blob proxy, manifest store)
|
|
│ ├── public/ # Static assets (JS, CSS, install scripts)
|
|
│ └── templates/ # HTML templates
|
|
├── atproto/ # ATProto client, records, manifest/tag stores
|
|
├── auth/
|
|
│ ├── oauth/ # OAuth client, refresher, storage
|
|
│ ├── token/ # JWT issuer, validator, claims
|
|
│ └── holdlocal/ # Local hold authorization
|
|
├── config/ # Config marshaling (commented YAML)
|
|
├── hold/
|
|
│ ├── admin/ # Admin web UI
|
|
│ ├── billing/ # Stripe billing integration
|
|
│ ├── db/ # Vendored carstore (go-libsql)
|
|
│ ├── gc/ # Garbage collection
|
|
│ ├── oci/ # OCI upload endpoints
|
|
│ ├── pds/ # Embedded PDS (DID, captain, crew, stats, scans)
|
|
│ └── quota/ # Storage quotas
|
|
├── logging/ # Structured logging + remote shipping
|
|
└── s3/ # S3 client utilities
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|
|
|
|
## Contributing
|
|
|
|
Contributions welcome! Please open an issue or PR.
|