Docker Deployment
Deploy Retrospend on your own server using Docker Compose. This is the recommended and officially supported self-hosting method.
Prerequisites
- • Docker Engine 24+ and Docker Compose v2 installed
- • A server or VPS with at least 1 GB RAM (2 GB+ recommended if using local Ollama)
- • A domain name pointed at your server (for HTTPS via a reverse proxy)
- • Ports 80 and 443 available (if using Caddy or Nginx for TLS)
AI import is optional
Setup
Step 1: Create your .env file
Create a .env file in your deployment directory:
# Generate with: openssl rand -base64 32
AUTH_SECRET=""
PUBLIC_URL="https://your-domain.com"
# Database
POSTGRES_PASSWORD="changeme"
POSTGRES_USER="postgres"
POSTGRES_DB_NAME="retrospend"
# Worker
WORKER_API_KEY="your-worker-api-key"
# AI Import - pick one:
# Option A: OpenRouter (external, recommended for most users)
# OPENROUTER_API_KEY=""
# OPENROUTER_MODEL="qwen/qwen-2.5-7b-instruct"
# Option B: Local Ollama (see docker-compose.local-ai.yml)
# LLM_MODEL="qwen2.5:7b"
# Optional: email notifications
# SMTP_HOST=""
# SMTP_PORT=587
# SMTP_USER=""
# SMTP_PASSWORD=""
# EMAIL_FROM="Retrospend <[email protected]>"
# UNSUBSCRIBE_SECRET="" # Generate with: openssl rand -base64 32Generate strong secrets
openssl rand -base64 32 for each secret value. Never reuse secrets across services.Step 2: Choose your docker-compose.yml
Pick the variant that matches your setup:
Uses OpenRouter for AI-powered bank import. Requires an API key but no GPU. The free tier is sufficient for most personal use.
services:
retrospend:
image: synzeit/retrospend:latest
container_name: retrospend
restart: unless-stopped
environment:
AUTH_SECRET: ${AUTH_SECRET}
DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB_NAME}"
PUBLIC_URL: "https://your-domain.com"
WORKER_API_KEY: ${WORKER_API_KEY}
SIDECAR_URL: "http://sidecar:8080"
ports:
- "1997:1997"
volumes:
- uploads:/data/uploads
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
container_name: retrospend-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
sidecar:
image: synzeit/retrospend-sidecar:latest
container_name: retrospend-sidecar
restart: unless-stopped
environment:
DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB_NAME}"
WORKER_API_KEY: ${WORKER_API_KEY}
LOG_LEVEL: "info"
BACKUP_DIR: "/backups"
BACKUP_RETENTION_DAYS: "${BACKUP_RETENTION_DAYS:-30}"
BACKUP_CRON: "${BACKUP_CRON:-0 3 * * *}"
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
OPENROUTER_MODEL: ${OPENROUTER_MODEL:-qwen/qwen-2.5-7b-instruct}
ENRICH_BATCH_SIZE: "${ENRICH_BATCH_SIZE:-20}"
ENRICH_CONCURRENCY: "${ENRICH_CONCURRENCY:-3}"
PDF_CONCURRENCY: "${PDF_CONCURRENCY:-3}"
volumes:
- backup_data:/backups
- sidecar_data:/app/data
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
uploads:
sidecar_data:
backup_data:Step 3: Start the stack
docker compose up -dThe first start will pull images and run database migrations automatically. Check logs with:
docker compose logs -f retrospendStep 4: Access your instance
Retrospend listens on port 1997. You can access it directly at http://your-server:1997 or put it behind a reverse proxy for HTTPS. See the Reverse Proxy guide for Nginx and Caddy configuration.
Services Overview
| Service | Image | Purpose |
|---|---|---|
| retrospend | synzeit/retrospend | Main web app (Next.js) |
| postgres | postgres:16-alpine | Primary database |
| sidecar | synzeit/retrospend-sidecar | Background jobs + AI bank import |
| ollama | ollama/ollama | Local LLM (optional) |
Data Persistence
All data is stored in named Docker volumes: postgres_data for the database and uploads for uploaded files (avatars, project images, receipts). Back these up regularly, as they contain all your financial data.
# Backup PostgreSQL
docker exec retrospend-postgres pg_dump -U postgres retrospend > backup.sql
# List volumes
docker volume ls | grep retrospendFirst User & Registration
On a fresh instance, navigate to /signup to create your account. The first registered user can be promoted to admin from the admin panel at /admin.
Note