Docker Compose Setup
Deploy Bittery on any Linux server with Docker Compose. The stack includes Caddy for automatic HTTPS via Let's Encrypt.
Quick install
The installer script handles everything — downloading configs, generating secrets, and starting services:
curl -fsSL https://raw.githubusercontent.com/bittery-org/bittery/main/deploy/install.sh | bash
The installer will prompt you for:
- Your domain name (e.g.
bittery.example.com) - Database choice — built-in PostgreSQL or external
- Install directory (default:
~/bittery)
Note
For non-interactive installs, pass flags directly:
bash install.sh --domain bittery.example.com --install-dir /opt/bittery
Manual setup
If you prefer to set things up manually:
Create a directory
mkdir -p ~/bittery && cd ~/bittery
Download the configuration files
curl -fsSL https://raw.githubusercontent.com/bittery-org/bittery/main/deploy/docker/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/bittery-org/bittery/main/deploy/docker/Caddyfile -o Caddyfile
Create an .env file
Generate secrets and configure your domain:
cat > .env << 'EOF'
DOMAIN=bittery.example.com
BITTERY_MODE=self-hosted
JWT_SECRET=$(openssl rand -hex 32)
DB_PASSWORD=$(openssl rand -hex 16)
EOF
Replace bittery.example.com with your actual domain.
Point DNS to your server
Create an A record for your domain pointing to your server's public IP address. Caddy will automatically provision a TLS certificate once DNS propagates.
Start the services
With built-in PostgreSQL:
COMPOSE_PROFILES=builtin-db docker compose up -d
With an external database:
# Add to .env: DATABASE_URL=postgresql://user:pass@host:5432/bittery
docker compose up -d
Verify
docker compose ps
All services should show (healthy). Open https://your-domain.com to create your first account.
Enabling optional services
File storage (MinIO)
Enable S3-compatible storage for file attachments:
# Add to .env
MINIO_ROOT_PASSWORD=your-secure-password
BITTERY_STORAGE_ENDPOINT=http://minio:9000
BITTERY_STORAGE_BUCKET=bittery
BITTERY_STORAGE_ACCESS_KEY_ID=bittery
BITTERY_STORAGE_SECRET_ACCESS_KEY=your-secure-password
COMPOSE_PROFILES=builtin-db,storage docker compose up -d
Cache (Valkey)
Enable Redis-compatible caching for rate limiting and pub/sub:
# Add to .env
REDIS_URL=valkey://valkey:6379
RATE_LIMIT_ADAPTER=auto
RATE_LIMIT_REDIS_URL=valkey://valkey:6379
COMPOSE_PROFILES=builtin-db,cache docker compose up -d
Reverse proxy
The included Caddy configuration routes traffic as follows:
| Path | Service |
|---|---|
/rpc/* | API server |
/sync/* | Real-time sync (SSE) |
/cdn/* | CDN proxy |
/favicon/* | Favicon service |
/healthz | Health check |
| Everything else | Web SPA |
Warning
If you use your own reverse proxy instead of Caddy, make sure to set TRUST_PROXY_MODE appropriately. Valid values are none, cloudflare, or forwarded.
Backups
Database
If using the built-in PostgreSQL, back up the database regularly:
docker compose exec postgres pg_dump -U bittery bittery > backup-$(date +%Y%m%d).sql
Restoring
docker compose exec -T postgres psql -U bittery bittery < backup-20250101.sql
Tip
For production deployments, consider using an external managed PostgreSQL service with automated backups.