Files
at-container-registry/docs/appview.md
2025-10-24 09:46:20 -05:00

322 lines
12 KiB
Markdown

# ATCR AppView
> The registry frontend component of ATCR (ATProto Container Registry)
## Overview
**AppView** is the frontend server component of ATCR. It serves as the OCI-compliant registry API endpoint and web interface that Docker clients interact with when pushing and pulling container images.
### What AppView Does
AppView is the orchestration layer that:
- **Serves the OCI Distribution API V2** - Compatible with Docker, containerd, podman, and all OCI clients
- **Resolves ATProto identities** - Converts handles (`alice.bsky.social`) and DIDs (`did:plc:xyz123`) to PDS endpoints
- **Routes manifests** - Stores container image manifests as ATProto records in users' Personal Data Servers
- **Routes blobs** - Proxies blob (layer) operations to hold services for S3-compatible storage
- **Provides web UI** - Browse repositories, search images, view tags, track pull counts, manage stars
- **Manages authentication** - Validates OAuth tokens and issues registry JWTs to Docker clients
### The ATCR Ecosystem
AppView is the **frontend** of a multi-component architecture:
1. **AppView** (this component) - Registry API + web interface
2. **[Hold Service](https://atcr.io/r/evan.jarrett.net/atcr-hold)** - Storage backend with embedded PDS for blob storage
3. **Credential Helper** - Client-side tool for ATProto OAuth authentication
**Data flow:**
```
Docker Client → AppView (resolves identity) → User's PDS (stores manifest)
Hold Service (stores blobs in S3/Storj/etc.)
```
Manifests (small JSON metadata) live in users' ATProto PDS, while blobs (large binary layers) live in hold services. AppView orchestrates the routing between these components.
## When to Run Your Own AppView
Most users can simply use **https://atcr.io** - you don't need to run your own AppView.
**Run your own AppView if you want to:**
- Host a private/organizational container registry with ATProto authentication
- Run a public registry for a specific community
- Customize the registry UI or policies
- Maintain full control over registry infrastructure
**Prerequisites:**
- A running [Hold service](https://atcr.io/r/evan.jarrett.net/atcr-hold) (required for blob storage)
- (Optional) Domain name with SSL/TLS certificates for production
- (Optional) Access to ATProto Jetstream for real-time indexing
## Quick Start
### Using Docker Compose
The fastest way to run AppView alongside a Hold service:
```bash
# Clone repository
git clone https://tangled.org/@evan.jarrett.net/at-container-registry
cd atcr
# Copy and configure environment
cp .env.appview.example .env.appview
# Edit .env.appview - set ATCR_DEFAULT_HOLD_DID (see Configuration below)
# Start services
docker-compose up -d
# Verify
curl http://localhost:5000/v2/
```
### Minimal Configuration
At minimum, you must set:
```bash
# Required: Default hold service for blob storage
ATCR_DEFAULT_HOLD_DID=did:web:127.0.0.1:8080
# Recommended for production
ATCR_BASE_URL=https://registry.example.com
ATCR_HTTP_ADDR=:5000
```
See **Configuration Reference** below for all options.
## Configuration Reference
AppView is configured entirely via environment variables. Load them with:
```bash
source .env.appview
./bin/atcr-appview serve
```
Or via Docker Compose (recommended).
### Server Configuration
#### `ATCR_HTTP_ADDR`
- **Default:** `:5000`
- **Description:** HTTP listen address for the registry API and web UI
- **Example:** `:5000`, `:8080`, `0.0.0.0:5000`
#### `ATCR_BASE_URL`
- **Default:** Auto-detected from `ATCR_HTTP_ADDR` (e.g., `http://127.0.0.1:5000`)
- **Description:** Public URL for the AppView service. Used to generate OAuth redirect URIs and JWT realm claims.
- **Development:** Auto-detection works fine (`http://127.0.0.1:5000`)
- **Production:** Set to your public URL (e.g., `https://atcr.example.com`)
- **Example:** `https://atcr.io`, `http://127.0.0.1:5000`
#### `ATCR_SERVICE_NAME`
- **Default:** Derived from `ATCR_BASE_URL` hostname, or `atcr.io`
- **Description:** Service name used for JWT `service` and `issuer` fields. Controls token scope.
- **Example:** `atcr.io`, `registry.example.com`
#### `ATCR_DEBUG_ADDR`
- **Default:** `:5001`
- **Description:** Debug listen address for pprof debugging endpoints
- **Example:** `:5001`, `:6060`
### Storage Configuration
#### `ATCR_DEFAULT_HOLD_DID` ⚠️ REQUIRED
- **Default:** None (required)
- **Description:** DID of the default hold service for blob storage. Used when users don't have their own hold configured in their sailor profile. AppView routes all blob operations to this hold.
- **Format:** `did:web:hostname[:port]`
- **Docker Compose:** `did:web:atcr-hold:8080` (internal Docker network)
- **Local dev:** `did:web:127.0.0.1:8080`
- **Production:** `did:web:hold01.atcr.io`
- **Note:** This hold must be reachable from AppView. To find a hold's DID, visit `https://hold-url/.well-known/did.json`
### Authentication Configuration
#### `ATCR_AUTH_KEY_PATH`
- **Default:** `/var/lib/atcr/auth/private-key.pem`
- **Description:** Path to JWT signing private key (RSA). Auto-generated if missing.
- **Note:** Keep this secure - it signs all registry JWTs issued to Docker clients
#### `ATCR_AUTH_CERT_PATH`
- **Default:** `/var/lib/atcr/auth/private-key.crt`
- **Description:** Path to JWT signing certificate. Auto-generated if missing.
- **Note:** Paired with `ATCR_AUTH_KEY_PATH`
#### `ATCR_TOKEN_EXPIRATION`
- **Default:** `300` (5 minutes)
- **Description:** JWT token expiration in seconds. Registry JWTs are short-lived for security.
- **Recommendation:** Keep between 300-900 seconds (5-15 minutes)
### Web UI Configuration
#### `ATCR_UI_ENABLED`
- **Default:** `true`
- **Description:** Enable the web interface. Set to `false` to run registry API only (no web UI, no database).
- **Use case:** API-only deployments where you don't need the browsing interface
#### `ATCR_UI_DATABASE_PATH`
- **Default:** `/var/lib/atcr/ui.db`
- **Description:** SQLite database path for UI data (OAuth sessions, stars, pull counts, repository metadata)
- **Note:** For multi-instance deployments, use PostgreSQL (see production docs)
### Logging Configuration
#### `ATCR_LOG_LEVEL`
- **Default:** `info`
- **Options:** `debug`, `info`, `warn`, `error`
- **Description:** Log verbosity level
- **Development:** Use `debug` for detailed troubleshooting
- **Production:** Use `info` or `warn`
#### `ATCR_LOG_FORMATTER`
- **Default:** `text`
- **Options:** `text`, `json`
- **Description:** Log output format
- **Production:** Use `json` for structured logging (easier to parse with log aggregators)
### Hold Health Check Configuration
AppView periodically checks if hold services are reachable and caches results to display health indicators in the UI.
#### `ATCR_HEALTH_CHECK_INTERVAL`
- **Default:** `15m`
- **Description:** How often to check health of hold endpoints in the background
- **Format:** Duration string (e.g., `5m`, `15m`, `30m`, `1h`)
- **Recommendation:** 15-30 minutes for production
#### `ATCR_HEALTH_CACHE_TTL`
- **Default:** `15m`
- **Description:** How long to cache health check results before re-checking
- **Format:** Duration string (e.g., `15m`, `30m`, `1h`)
- **Note:** Should be >= `ATCR_HEALTH_CHECK_INTERVAL` for efficiency
### Jetstream Configuration (ATProto Event Streaming)
Jetstream provides real-time indexing of ATProto records (manifests, tags) into the AppView database for the web UI.
#### `JETSTREAM_URL`
- **Default:** `wss://jetstream2.us-west.bsky.network/subscribe`
- **Description:** Jetstream WebSocket URL for real-time ATProto events
- **Note:** Connects to Bluesky's public Jetstream by default
#### `ATCR_BACKFILL_ENABLED`
- **Default:** `false`
- **Description:** Enable periodic sync of historical ATProto records. Set to `true` for production to ensure database completeness.
- **Recommendation:** Enable for production AppView instances
#### `ATCR_RELAY_ENDPOINT`
- **Default:** `https://relay1.us-east.bsky.network`
- **Description:** ATProto relay endpoint for backfill sync API
- **Note:** Used when `ATCR_BACKFILL_ENABLED=true`
#### `ATCR_BACKFILL_INTERVAL`
- **Default:** `1h`
- **Description:** How often to run backfill sync
- **Format:** Duration string (e.g., `30m`, `1h`, `2h`, `24h`)
### Legacy Configuration
#### `TEST_MODE`
- **Default:** `false`
- **Description:** Enable test mode (skips some validations). Do not use in production.
## Web Interface Features
The AppView web UI provides:
- **Home page** - Featured repositories and recent pushes feed
- **Repository pages** - View tags, manifests, pull instructions, health status
- **Search** - Find repositories by owner handle or repository name
- **User profiles** - View a user's repositories and activity
- **Stars** - Favorite repositories (requires OAuth login)
- **Pull counts** - Track image pull statistics
- **Multi-arch support** - Display platform-specific manifests (linux/amd64, linux/arm64)
- **Health indicators** - Real-time hold service reachability status
- **Install scripts** - Host credential helper installation scripts at `/install.sh`
## Deployment Scenarios
### Public Registry (like atcr.io)
Open to all ATProto users:
```bash
# AppView config
ATCR_BASE_URL=https://registry.example.com
ATCR_DEFAULT_HOLD_DID=did:web:hold01.example.com
ATCR_UI_ENABLED=true
ATCR_BACKFILL_ENABLED=true
# Hold config (linked hold service)
HOLD_PUBLIC=true # Allow public pulls
HOLD_ALLOW_ALL_CREW=true # Allow all authenticated users to push
```
### Private Organizational Registry
Restricted to crew members only:
```bash
# AppView config
ATCR_BASE_URL=https://registry.internal.example.com
ATCR_DEFAULT_HOLD_DID=did:web:hold.internal.example.com
ATCR_UI_ENABLED=true
# Hold config (linked hold service)
HOLD_PUBLIC=false # Require auth for pulls
HOLD_ALLOW_ALL_CREW=false # Only owner + explicit crew can push
HOLD_OWNER=did:plc:your-org-did # Organization DID
```
### Development/Testing
Local Docker Compose setup:
```bash
# AppView config
ATCR_HTTP_ADDR=:5000
ATCR_DEFAULT_HOLD_DID=did:web:atcr-hold:8080
ATCR_LOG_LEVEL=debug
# Hold config (linked hold service)
STORAGE_DRIVER=filesystem
STORAGE_ROOT_DIR=/tmp/atcr-hold
HOLD_PUBLIC=true
HOLD_ALLOW_ALL_CREW=true
```
## Production Deployment
For production deployments with:
- Multiple AppView instances (load balancing)
- PostgreSQL database (instead of SQLite)
- SSL/TLS certificates
- Systemd service files
- Log rotation
- Monitoring
See **[deploy/README.md](https://tangled.org/@evan.jarrett.net/at-container-registry/blob/main/deploy/README.md)** for comprehensive production deployment guide.
### Quick Production Checklist
Before going to production:
- [ ] Set `ATCR_BASE_URL` to your public HTTPS URL
- [ ] Set `ATCR_DEFAULT_HOLD_DID` to a production hold service
- [ ] Enable Jetstream backfill (`ATCR_BACKFILL_ENABLED=true`)
- [ ] Use `ATCR_LOG_FORMATTER=json` for structured logging
- [ ] Secure JWT keys (`ATCR_AUTH_KEY_PATH`, `ATCR_AUTH_CERT_PATH`)
- [ ] Configure SSL/TLS termination (nginx/Caddy/Cloudflare)
- [ ] Set up database backups (if using SQLite, consider PostgreSQL)
- [ ] Monitor hold health checks
- [ ] Test OAuth flow end-to-end
- [ ] Verify Docker push/pull works
## Configuration Files Reference
- **[.env.appview.example](https://tangled.org/@evan.jarrett.net/at-container-registry/blob/main/.env.appview.example)** - All available environment variables with documentation
- **[deploy/.env.prod.template](https://tangled.org/@evan.jarrett.net/at-container-registry/blob/main/deploy/.env.prod.template)** - Production configuration template
- **[deploy/README.md](https://tangled.org/@evan.jarrett.net/at-container-registry/blob/main/deploy/README.md)** - Production deployment guide
- **[Hold Service Documentation](https://atcr.io/r/evan.jarrett.net/atcr-hold)** - Storage backend setup