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:

PathService
/rpc/*API server
/sync/*Real-time sync (SSE)
/cdn/*CDN proxy
/favicon/*Favicon service
/healthzHealth check
Everything elseWeb 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.