Skip to main content
Docker Compose provides the quickest way to self-host Brainbox on a single server. This setup includes PostgreSQL, Redis (Valkey), MinIO, and the Brainbox application.

Prerequisites

  • Docker 20.10+ and Docker Compose 2.0+
  • 4 GB RAM minimum (8 GB recommended)
  • 20 GB free disk space (plus space for user data)
  • Linux, macOS, or Windows with WSL2
Docker Desktop includes Docker Compose. On Linux servers, install both docker and docker-compose-plugin from your package manager.

Quick Start

1

Clone the repository

git clone https://github.com/brainbox/brainbox.git
cd brainbox/hosting/docker
2

Create environment file

cp .env.example .env
Edit .env and set secure passwords:
# PostgreSQL Configuration
POSTGRES_USER=colanode_user
POSTGRES_PASSWORD=your_secure_postgres_password  # CHANGE THIS
POSTGRES_DB=colanode_db

# Redis (Valkey) Configuration
VALKEY_PASSWORD=your_secure_valkey_password      # CHANGE THIS

# MinIO (S3) Configuration
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=your_secure_minio_password   # CHANGE THIS

# Server Configuration
NODE_ENV=production
SERVER_MODE=standalone
ACCOUNT_VERIFICATION_TYPE=automatic  # automatic | manual | email
Always change the default passwords before starting the services. Use strong, randomly generated passwords for production deployments.
3

Update image tags (optional)

If you want to use a specific version instead of latest, edit docker-compose.yaml:
server:
  image: ghcr.io/your-username/brainbox-server:v1.0.0  # Specify version

web:
  image: ghcr.io/your-username/brainbox-web:v1.0.0     # Specify version
4

Start the services

docker compose up -d
This will start all services in the background:
  • PostgreSQL (port 5432)
  • Valkey/Redis (port 6379)
  • MinIO (ports 9000, 9001)
  • Brainbox Server (port 3000)
  • Brainbox Web (port 4000)
5

Access the application

Open your browser and navigate to:
The first startup may take 1-2 minutes while the database initializes and migrations run.

Docker Compose Configuration

The complete docker-compose.yaml includes five services:

Services Overview

version: '3.8'

services:
  postgres:
    image: ghcr.io/your-username/brainbox-postgresql:17
    container_name: brainbox_postgres
    restart: always
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-colanode_user}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgrespass123}
      POSTGRES_DB: ${POSTGRES_DB:-colanode_db}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - '5432:5432'
    networks:
      - brainbox_network

  valkey:
    image: valkey/valkey:8.1
    container_name: brainbox_valkey
    restart: always
    command:
      [
        'valkey-server',
        '--requirepass',
        '${VALKEY_PASSWORD:-your_valkey_password}',
      ]
    volumes:
      - valkey_data:/data
    ports:
      - '6379:6379'
    networks:
      - brainbox_network

  minio:
    image: minio/minio:RELEASE.2025-04-08T15-41-24Z
    container_name: brainbox_minio
    restart: always
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-your_minio_password}
      MINIO_BROWSER: 'on'
      MINIO_DOMAIN: minio
      MINIO_ADDRESS: ':9000'
      MINIO_CONSOLE_ADDRESS: ':9001'
    volumes:
      - minio_data:/data
    ports:
      - '9000:9000'
      - '9001:9001'
    entrypoint: sh
    command: -c 'mkdir -p /data/brainbox && minio server /data --address ":9000" --console-address ":9001"'
    networks:
      - brainbox_network

  server:
    image: ghcr.io/your-username/brainbox-server:latest
    container_name: brainbox_server
    restart: always
    environment:
      NODE_ENV: ${NODE_ENV:-production}
      SERVER_MODE: ${SERVER_MODE:-standalone}
      POSTGRES_URL: postgres://${POSTGRES_USER:-colanode_user}:${POSTGRES_PASSWORD:-postgrespass123}@postgres:5432/${POSTGRES_DB:-colanode_db}
      REDIS_URL: redis://:${VALKEY_PASSWORD:-your_valkey_password}@valkey:6379/0
      STORAGE_S3_ENDPOINT: http://minio:9000
      STORAGE_S3_ACCESS_KEY: ${MINIO_ROOT_USER:-minioadmin}
      STORAGE_S3_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-your_minio_password}
      STORAGE_S3_BUCKET: brainbox
      STORAGE_S3_REGION: us-east-1
      STORAGE_S3_FORCE_PATH_STYLE: 'true'
      ACCOUNT_VERIFICATION_TYPE: ${ACCOUNT_VERIFICATION_TYPE:-automatic}
    depends_on:
      - postgres
      - valkey
      - minio
    ports:
      - '3000:3000'
    networks:
      - brainbox_network

  web:
    image: ghcr.io/your-username/brainbox-web:latest
    container_name: brainbox_web
    restart: always
    environment:
      VITE_SERVER_URL: http://server:3000/config
    depends_on:
      - server
    ports:
      - '4000:80'
    networks:
      - brainbox_network

volumes:
  postgres_data:
  valkey_data:
  minio_data:

networks:
  brainbox_network:
    driver: bridge

Service Details

ServiceContainer NamePort(s)Purpose
postgresbrainbox_postgres5432PostgreSQL database with pgvector
valkeybrainbox_valkey6379Redis-compatible cache & queue
miniobrainbox_minio9000, 9001S3-compatible object storage
serverbrainbox_server3000Brainbox API server
webbrainbox_web4000 (→ 80)Brainbox web interface (nginx)

Managing Services

View logs

# All services
docker compose logs -f

# Specific service
docker compose logs -f server
docker compose logs -f postgres

Check service status

docker compose ps

Stop services

docker compose stop

Start services

docker compose start

Restart services

# All services
docker compose restart

# Specific service
docker compose restart server

Stop and remove containers

docker compose down
This preserves data volumes. To remove data as well, use:
docker compose down -v
This will delete all PostgreSQL data, Redis cache, and MinIO files.

Updating Brainbox

1

Pull the latest images

docker compose pull
2

Restart services with new images

docker compose up -d
Docker Compose will recreate containers using the updated images while preserving your data.
3

Verify the update

docker compose logs -f server
Check for successful startup and any migration messages.

Database Access

Connect to PostgreSQL for debugging or maintenance:
# Using docker exec
docker exec -it brainbox_postgres psql -U colanode_user -d colanode_db

# Or specify from .env
docker exec -it brainbox_postgres psql -U $POSTGRES_USER -d $POSTGRES_DB
Common PostgreSQL commands:
-- List all tables
\dt

-- Check database size
SELECT pg_size_pretty(pg_database_size('colanode_db'));

-- List users
\du

-- Exit
\q

Optional: SMTP Email Server

For email-based account verification and notifications, uncomment the SMTP service:
services:
  # ... other services ...

  smtp:
    image: axllent/mailpit:v1.24.1
    container_name: brainbox_smtp
    restart: always
    ports:
      - '1025:1025'  # SMTP port
      - '8025:8025'  # Web UI
    networks:
      - brainbox_network
Then configure the server to use it by adding to your .env:
SMTP_ENABLED=true
SMTP_HOST=smtp
SMTP_PORT=1025
SMTP_EMAIL_FROM=noreply@brainbox.local
SMTP_EMAIL_FROM_NAME=Brainbox
Access Mailpit web UI at http://localhost:8025 to view sent emails.

Production Deployment

For production environments, consider these additional steps:

1. Use a reverse proxy

server {
    listen 80;
    server_name brainbox.example.com;
    
    # Redirect to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name brainbox.example.com;
    
    ssl_certificate /etc/ssl/certs/brainbox.crt;
    ssl_certificate_key /etc/ssl/private/brainbox.key;
    
    location / {
        proxy_pass http://localhost:4000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # WebSocket support
    location /socket.io/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

2. Restrict port exposure

Edit docker-compose.yaml to only expose the web port:
services:
  postgres:
    # Remove or comment out ports section
    # ports:
    #   - '5432:5432'
  
  valkey:
    # Remove or comment out ports section
    # ports:
    #   - '6379:6379'
  
  server:
    # Remove or comment out ports section
    # ports:
    #   - '3000:3000'
Only expose port 4000 (web) or use a reverse proxy.

3. Enable PostgreSQL SSL

For production, enable SSL connections to PostgreSQL. See Configuration.

4. Set up automated backups

#!/bin/bash
# backup.sh - Daily PostgreSQL backup

BACKUP_DIR="/backups/brainbox"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

docker exec brainbox_postgres pg_dump -U colanode_user colanode_db | \
  gzip > "$BACKUP_DIR/brainbox_$DATE.sql.gz"

# Keep only last 30 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
Add to crontab:
0 2 * * * /path/to/backup.sh

Next Steps

Configuration

Customize environment variables and settings

Troubleshooting

Resolve common deployment issues

Build docs developers (and LLMs) love