Production Docker Deployment Checklist for CubyCrate
This checklist is an operational runbook for deploying, securing, and maintaining CubyCrate in production environments using Docker Compose. It outlines hardware requirements, volume retention invariants, reverse proxy hardening, and cold backup workflows.
1. Host & Engine Prerequisites
Section titled “1. Host & Engine Prerequisites”Before deploying the container, verify that the host operating system and Docker environment meet the baseline requirements:
- Host Kernel: Linux kernel 5.4 or later (Ubuntu 22.04+, Debian 12+, RHEL 9+, or Alpine 3.19+).
- Docker Engine: Version 24.0 or newer.
- Docker Compose: Compose V2 version 2.20 or newer (
docker compose version). - Hardware Architecture: Supported official multi-architecture images:
linux/amd64(standard x86_64 servers)linux/arm64(AWS Graviton, Raspberry Pi 4/5, Ampere Altra, Apple Silicon)
- System Resources:
- Minimum 512 MB RAM (CubyCrate baseline idle footprint is 30–50 MB).
- 1 CPU core is sufficient for small to medium teams.
- Sufficient storage space on the host volume for database files and local uploads.
2. Production Docker Compose Configuration
Section titled “2. Production Docker Compose Configuration”- Image Pinning: Pin the exact release tag rather than
:latestto prevent unexpected container migrations. The current production release isghcr.io/septian-padli/cubycrate:v0.0.1-alpha.2. - Named Volume Binding: Ensure
/app/datamaps to the dedicated named volumecubycrate_data. - Security Settings: Set
ENV=productionandCOOKIE_SECURE=truewhen running behind TLS.
Below is the verified production compose.yaml specification:
services: cubycrate: image: ghcr.io/septian-padli/cubycrate:v0.0.1-alpha.2 container_name: cubycrate restart: unless-stopped ports: - "127.0.0.1:8383:8383" environment: - ENV=production - PORT=8383 - COOKIE_SECURE=true - TRUST_PROXY=true - DATA_DIR_PATH=/app/data - CUBYCRATE_STORAGE_CLEANUP_DRY_RUN=true volumes: - cubycrate_data:/app/data healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:8383/health || exit 1"] interval: 30s timeout: 5s retries: 3 start_period: 15s
volumes: cubycrate_data: name: cubycrate_data3. Volume Persistence Invariants & Hazard Warnings
Section titled “3. Volume Persistence Invariants & Hazard Warnings”All persistent state in CubyCrate is consolidated within /app/data:
| Directory / File | Contents & Purpose |
|---|---|
/app/data/db/cubycrate.db |
Embedded SQLite database file containing all file metadata, users, and shares |
/app/data/db/cubycrate.db-wal |
Write-Ahead Log journal containing uncommitted or active transactions |
/app/data/secrets/master.key |
256-bit AES-GCM master key used to encrypt S3 storage node credentials |
/app/data/secrets/jwt.key |
Session signing key for authenticated JSON Web Tokens |
/app/data/storage/default/ |
Default local storage pool for uploaded files |
/app/data/temp/tus/ |
Staging area for chunked in-flight TUS resumable uploads |
4. Reverse Proxy Hardening & TLS Termination
Section titled “4. Reverse Proxy Hardening & TLS Termination”Never expose port 8383 directly to the public internet. Always route traffic through a hardened reverse proxy with TLS termination.
- TLS Certificate: Automatic or manual SSL/TLS certificate configured for your domain.
- Port Isolation: Bind container port
8383to127.0.0.1:8383so only the local reverse proxy can connect. - Unbuffered Server-Sent Events (SSE): CubyCrate broadcasts real-time file updates across clients using SSE at
/api/v1/events. Reverse proxies must disable response buffering for this path. - Request Body Limits: Set the reverse proxy client body limit to match your desired maximum single-file upload size (e.g., 10 GB or 50 GB).
drive.example.com { reverse_proxy 127.0.0.1:8383 { flush_interval -1 }}Caddy automatically manages TLS certificates via Let’s Encrypt / ZeroSSL and disables buffering with flush_interval -1.
server { listen 443 ssl http2; server_name drive.example.com;
ssl_certificate /etc/letsencrypt/live/drive.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/drive.example.com/privkey.pem;
# Allow large file uploads client_max_body_size 25G;
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
location / { proxy_pass http://127.0.0.1:8383; proxy_http_version 1.1; proxy_read_timeout 600s; proxy_send_timeout 600s; }
# Crucial: Unbuffered SSE for real-time events location /api/v1/events { proxy_pass http://127.0.0.1:8383; proxy_buffering off; proxy_cache off; proxy_read_timeout 24h; }}5. First-Run Setup & Administrator Initialization
Section titled “5. First-Run Setup & Administrator Initialization”- Initial Bootstrap: Navigate to
https://drive.example.com/setupin your browser. - Root Administrator: Create the root administrator account with a strong passphrase.
- Setup Lockout: Verify that once the root account is created,
/setupredirects to the login screen and cannot be accessed again.
6. Health Probing & Operational Metrics
Section titled “6. Health Probing & Operational Metrics”CubyCrate provides two healthcheck endpoints: GET /health and GET /api/health.
- Both endpoints execute identical deep verification:
- Validates SQLite database connectivity (via
db.PingContext). - Probes all configured storage nodes (local directories and remote S3 buckets).
- Validates SQLite database connectivity (via
- Return Codes:
- Returns
200 OK({"status":"ok"}) when database and all storage nodes respond. - Returns
503 Service Unavailableif the database fails or any configured storage node is offline.
- Returns
- Container Status: When a storage node goes offline, Docker marks the container as
unhealthy, alerting uptime monitors and automated orchestration agents.
Test the endpoint manually:
curl -i https://drive.example.com/health7. Automated Cold Volume Backup Runbook
Section titled “7. Automated Cold Volume Backup Runbook”To back up CubyCrate safely without risking SQLite WAL corruption or partial file writes:
- Script Implementation: Set up a cron job or scheduled task running a cold volume backup.
- Read-Only Mount: The backup script stops the container briefly, mounts
cubycrate_datawith:ro(read-only) into an ephemeral Alpine container, creates a compressed tarball, and restarts CubyCrate.
#!/usr/bin/env bashset -Eeuo pipefail
BACKUP_DIR="/var/backups/cubycrate"mkdir -p "${BACKUP_DIR}"
BACKUP_FILE="${BACKUP_DIR}/cubycrate-$(date +%Y%m%d-%H%M%S).tar.gz"
echo "Stopping CubyCrate container..."docker compose stop cubycrate
# Ensure container restarts even if tar failstrap 'docker compose start cubycrate' EXIT
echo "Archiving cubycrate_data volume..."docker run --rm \ -v cubycrate_data:/source_data:ro \ -v "${BACKUP_DIR}:/backup_dest" \ alpine:latest \ tar -czf "/backup_dest/$(basename "${BACKUP_FILE}")" -C /source_data .
echo "Verifying backup archive..."tar -tzf "${BACKUP_FILE}" > /dev/null
echo "Cold backup successful: ${BACKUP_FILE}"8. Zero-Downtime Upgrade & Rollback Lifecycle
Section titled “8. Zero-Downtime Upgrade & Rollback Lifecycle”When upgrading to a new release:
- Review Release Notes: Check the Changelog for breaking changes.
- Execute a Cold Backup: Always perform a cold backup before applying image updates.
- Update Compose File: Update
CUBYCRATE_VERSIONorimage:tag incompose.yaml. - Pull and Recreate Container:
docker compose pulldocker compose up -d- Verify Status: Monitor logs and inspect the healthcheck:
docker compose logs -f cubycratedocker compose pscurl -i http://127.0.0.1:8383/healthNext Steps
Section titled “Next Steps”- Configuration Reference: Detailed environment variable explanations.
- Backup & Disaster Recovery: Full restoration runbooks.
- Operational Diagnostics: Troubleshooting reverse proxies, permissions, and database locks.

