Docker & Container Deployment
Deploying Lioran S3 with Docker Compose is the recommended production path. It packages the server alongside the Caddy reverse proxy for automated TLS certificate provisioning.
1. Production Docker Compose Configuration
The following docker-compose.yml is the canonical production deployment template:
docker-compose.yml
services:
bastion:
image: liorans3/liorans3:pre-alpha
container_name: bastion-server
restart: unless-stopped
init: true
stop_grace_period: 30s
expose:
# Expose port only to internal Docker network; no public host port binding
- "27118"
environment:
# Runtime environment mode: production (default) or development
- BASTION_ENV=${BASTION_ENV:-production}
- BASTION_HOST=0.0.0.0
- BASTION_PORT=27118
- BASTION_DATA_DIR=/data
# Bootstrap Admin Credentials
- BASTION_ADMIN_USERNAME=${BASTION_ADMIN_USERNAME:-admin}
- BASTION_ADMIN_PASSWORD=${BASTION_ADMIN_PASSWORD}
# Domain & Security Configuration
- BASTION_PUBLIC_URL=${BASTION_PUBLIC_URL:-https://${BASTION_DOMAIN:-s3.example.com}}
- BASTION_CORS_ORIGINS=${BASTION_CORS_ORIGINS:-https://${BASTION_DOMAIN:-s3.example.com}}
- BASTION_SIGNING_SECRET=${BASTION_SIGNING_SECRET:-}
- BASTION_MAX_SIGNED_URL_TTL_SECS=${BASTION_MAX_SIGNED_URL_TTL_SECS:-604800}
# Storage & Safety Guardrails
- BASTION_MIN_FREE_SPACE_BYTES=${BASTION_MIN_FREE_SPACE_BYTES:-536870912}
- BASTION_STREAM_CHUNK_KIB=${BASTION_STREAM_CHUNK_KIB:-256}
- BASTION_DURABILITY=${BASTION_DURABILITY:-strict}
volumes:
- bastion-data:/data
networks:
- bastion-net
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "5"
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:27118/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 5s
caddy:
image: caddy:2-alpine
container_name: bastion-caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- BASTION_DOMAIN=${BASTION_DOMAIN:-s3.example.com}
- CADDY_ACME_EMAIL=${CADDY_ACME_EMAIL:-}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
depends_on:
bastion:
condition: service_healthy
networks:
- bastion-net
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "5"
volumes:
bastion-data:
driver: local
caddy-data:
driver: local
caddy-config:
driver: local
networks:
bastion-net:
driver: bridge
2. Deployment Steps
Step 1: Prepare Environment File
Copy .env.production.example to .env:
cp .env.production.example .env
Generate a secure admin password and 64-hex signing secret:
# Generate admin password
openssl rand -base64 24 | tr -d '/+'
# Generate HMAC signing secret
openssl rand -hex 32
Populate .env:
.env
BASTION_DOMAIN=s3.yourdomain.com
BASTION_PUBLIC_URL=https://s3.yourdomain.com
BASTION_ENV=production
BASTION_ADMIN_USERNAME=admin
BASTION_ADMIN_PASSWORD=YourStrongPasswordHere123!
BASTION_SIGNING_SECRET=f4a7c8... # 64 hex characters
BASTION_CORS_ORIGINS=https://s3.yourdomain.com,https://app.yourdomain.com
BASTION_DURABILITY=strict
Step 2: Start the Stack
docker compose up -d
Step 3: Verify Liveness
# Verify container health
docker compose ps
# Check public endpoint
curl -f https://s3.yourdomain.com/health
Expected output:
{
"name": "Lioran Bastion",
"status": "ok",
"version": "0.1.0"
}
3. Container Lifecycle & Graceful Shutdown
stop_grace_period: 30s: Allows in-flight multipart chunk writes and HTTP downloads to finish cleanly before signaling termination.- Signal Handling: The server captures
SIGTERM/SIGINTsignals, flushes active RocksDB handles, syncs open file descriptors, and terminates without data corruption. - Log Rotation: Logs use
json-filewith a 20MB per-file limit and 5-file retention ceiling to prevent filling host disks.