# ATCR Production Environment Configuration # Copy this file to .env and fill in your values # # Usage: # 1. cp deploy/.env.prod.template .env # 2. Edit .env with your configuration # 3. systemctl restart atcr # # NOTE: This file is loaded by docker-compose.prod.yml # ============================================================================== # Domain Configuration # ============================================================================== # Main AppView domain (registry API + web UI) # REQUIRED: Update with your domain APPVIEW_DOMAIN=atcr.io # Hold service domain (presigned URL generator) # REQUIRED: Update with your domain HOLD_DOMAIN=hold01.atcr.io # ============================================================================== # Hold Service Configuration # ============================================================================== # Your ATProto DID (REQUIRED for hold registration) # Get your DID from: https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=yourhandle.bsky.social # Example: did:plc:abc123xyz789 HOLD_OWNER=did:plc:pddp4xt5lgnv2qsegbzzs4xg # Directory path for embedded PDS carstore (SQLite database) # Default: /var/lib/atcr-hold # If empty, embedded PDS is disabled # # Note: This should be a directory path, NOT a file path # Carstore creates db.sqlite3 inside this directory # # The embedded PDS makes the hold a proper ATProto user with: # - did:web identity (derived from HOLD_DOMAIN) # - DID document at /.well-known/did.json # - XRPC endpoints for crew management # - ATProto blob endpoints (wraps existing presigned URL logic) # # Example: For HOLD_DOMAIN=hold01.atcr.io, the hold becomes did:web:hold01.atcr.io HOLD_DATABASE_DIR=/var/lib/atcr-hold # Path to signing key (auto-generated on first run if missing) # Default: {HOLD_DATABASE_DIR}/signing.key # HOLD_KEY_PATH=/var/lib/atcr-hold/signing.key # Allow public blob reads (pulls) without authentication # - true: Anyone can pull images (read-only) # - false: Only authenticated users can pull # Default: false (private) HOLD_PUBLIC=false # Allow all authenticated users to write to this hold # This setting controls write permissions for authenticated ATCR users # # - true: Any authenticated ATCR user can push images (treat all as crew) # Useful for shared/community holds where you want to allow # multiple users to push without explicit crew membership. # Users must still authenticate via ATProto OAuth. # # - false: Only hold owner and explicit crew members can push (default) # Write access requires io.atcr.hold.crew record in owner's PDS. # Most secure option for production holds. # # Read permissions are controlled by HOLD_PUBLIC (above). # # Security model: # Read: HOLD_PUBLIC=true → anonymous + authenticated users # HOLD_PUBLIC=false → authenticated users only # Write: HOLD_ALLOW_ALL_CREW=true → all authenticated users # HOLD_ALLOW_ALL_CREW=false → owner + crew only (verified via PDS) # # Use cases: # - Public registry: HOLD_PUBLIC=true, HOLD_ALLOW_ALL_CREW=true # - ATProto users only: HOLD_PUBLIC=false, HOLD_ALLOW_ALL_CREW=true # - Private hold (default): HOLD_PUBLIC=false, HOLD_ALLOW_ALL_CREW=false # # Default: false HOLD_ALLOW_ALL_CREW=false # ============================================================================== # S3/UpCloud Object Storage Configuration # ============================================================================== # Storage driver type # Options: s3, filesystem # Default: s3 STORAGE_DRIVER=s3 # S3 Access Credentials # Get these from UpCloud Object Storage console AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= # S3 Region (for distribution S3 driver) # UpCloud regions: us-chi1, us-nyc1, de-fra1, uk-lon1, sg-sin1, etc. # Note: Use AWS_REGION (not S3_REGION) - this is what the hold service expects # Default: us-east-1 AWS_REGION=us-chi1 # S3 Bucket Name # Create this bucket in UpCloud Object Storage # Example: atcr-blobs S3_BUCKET=atcr # S3 Endpoint # Get this from UpCloud Console → Storage → Object Storage → Your bucket → "S3 endpoint" # Format: https://[bucket-id].upcloudobjects.com # Example: https://6vmss.upcloudobjects.com # # NOTE: Use the bucket-specific endpoint, NOT a custom domain # Custom domains break presigned URL generation S3_ENDPOINT=https://6vmss.upcloudobjects.com # S3 Region Endpoint (alternative to S3_ENDPOINT) # Use this if your S3 driver requires region-specific endpoint format # Example: s3.us-chi1.upcloudobjects.com # S3_REGION_ENDPOINT= # ============================================================================== # AppView Configuration # ============================================================================== # JWT token expiration in seconds # Default: 300 (5 minutes) ATCR_TOKEN_EXPIRATION=300 # Enable web UI # Default: true ATCR_UI_ENABLED=true # ============================================================================== # Logging Configuration # ============================================================================== # Log level: debug, info, warn, error # Default: info ATCR_LOG_LEVEL=info # Log formatter: text, json # Default: text ATCR_LOG_FORMATTER=text # ============================================================================== # Jetstream Configuration (ATProto event streaming) # ============================================================================== # Jetstream WebSocket URL for real-time ATProto events # Default: wss://jetstream2.us-west.bsky.network/subscribe JETSTREAM_URL=wss://jetstream2.us-west.bsky.network/subscribe # Enable backfill worker to sync historical records # Default: true (recommended for production) ATCR_BACKFILL_ENABLED=true # ATProto relay endpoint for backfill sync API # Default: https://relay1.us-east.bsky.network ATCR_RELAY_ENDPOINT=https://relay1.us-east.bsky.network # Backfill interval # Examples: 30m, 1h, 2h, 24h # Default: 1h ATCR_BACKFILL_INTERVAL=1h # ============================================================================== # Optional: Filesystem Storage (alternative to S3) # ============================================================================== # If using filesystem storage instead of S3: # 1. Uncomment these lines # 2. Comment out all S3 variables above # 3. Set STORAGE_DRIVER=filesystem # STORAGE_DRIVER=filesystem # STORAGE_ROOT_DIR=/var/lib/atcr/hold # ============================================================================== # Advanced Configuration # ============================================================================== # Override service name (defaults to APPVIEW_DOMAIN) # ATCR_SERVICE_NAME=atcr.io # Debug listen address (optional - for pprof debugging) # ATCR_DEBUG_ADDR=:5001 # ============================================================================== # CHECKLIST # ============================================================================== # # Before starting ATCR, ensure you have: # # ☐ Set APPVIEW_DOMAIN (e.g., atcr.io) # ☐ Set HOLD_DOMAIN (e.g., hold01.atcr.io) # ☐ Set HOLD_OWNER (your ATProto DID) # ☐ Set HOLD_DATABASE_DIR (default: /var/lib/atcr-hold) - enables embedded PDS # ☐ Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY # ☐ Set AWS_REGION (e.g., us-chi1) # ☐ Set S3_BUCKET (created in UpCloud Object Storage) # ☐ Set S3_ENDPOINT (UpCloud endpoint or custom domain) # ☐ Configured DNS records: # - A record: atcr.io → server IP # - A record: hold01.atcr.io → server IP # - CNAME: blobs.atcr.io → [bucket].us-chi1.upcloudobjects.com # ☐ Disabled Cloudflare proxy (gray cloud, not orange) # ☐ Waited for DNS propagation (check with: dig atcr.io) # # After starting: # ☐ Complete hold OAuth registration (run: /opt/atcr/get-hold-oauth.sh) # ☐ Verify hold PDS: curl https://hold01.atcr.io/.well-known/did.json # ☐ Test registry: docker pull atcr.io/test/image # ☐ Monitor logs: /opt/atcr/logs.sh