Skip to content

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.

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 :latest to prevent unexpected container migrations. The current production release is ghcr.io/septian-padli/cubycrate:v0.0.1-alpha.2.
  • Named Volume Binding: Ensure /app/data maps to the dedicated named volume cubycrate_data.
  • Security Settings: Set ENV=production and COOKIE_SECURE=true when 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_data

3. 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 8383 to 127.0.0.1:8383 so 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.

5. First-Run Setup & Administrator Initialization

Section titled “5. First-Run Setup & Administrator Initialization”
  • Initial Bootstrap: Navigate to https://drive.example.com/setup in your browser.
  • Root Administrator: Create the root administrator account with a strong passphrase.
  • Setup Lockout: Verify that once the root account is created, /setup redirects to the login screen and cannot be accessed again.

CubyCrate provides two healthcheck endpoints: GET /health and GET /api/health.

  • Both endpoints execute identical deep verification:
    1. Validates SQLite database connectivity (via db.PingContext).
    2. Probes all configured storage nodes (local directories and remote S3 buckets).
  • Return Codes:
    • Returns 200 OK ({"status":"ok"}) when database and all storage nodes respond.
    • Returns 503 Service Unavailable if the database fails or any configured storage node is offline.
  • 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:

Terminal window
curl -i https://drive.example.com/health

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_data with :ro (read-only) into an ephemeral Alpine container, creates a compressed tarball, and restarts CubyCrate.
#!/usr/bin/env bash
set -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 fails
trap '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:

  1. Review Release Notes: Check the Changelog for breaking changes.
  2. Execute a Cold Backup: Always perform a cold backup before applying image updates.
  3. Update Compose File: Update CUBYCRATE_VERSION or image: tag in compose.yaml.
  4. Pull and Recreate Container:
Terminal window
docker compose pull
docker compose up -d
  1. Verify Status: Monitor logs and inspect the healthcheck:
Terminal window
docker compose logs -f cubycrate
docker compose ps
curl -i http://127.0.0.1:8383/health