Skip to main content
This guide walks you through deploying a complete Fluxer instance using Docker Compose. You’ll have a working installation with messaging, search, and optional voice/video support.

Prerequisites

Docker & Docker Compose

Docker Engine 24.0+ and Docker Compose v2.20+

Domain Name

A domain pointing to your server (e.g., chat.example.com)
1

Install Docker

If you don’t have Docker installed:
# Ubuntu/Debian
curl -fsSL https://get.docker.com | sh

# Add your user to docker group
sudo usermod -aG docker $USER
newgrp docker

Step 1: Download Fluxer

Clone the Fluxer repository or download the compose file:
mkdir fluxer && cd fluxer
curl -O https://raw.githubusercontent.com/fluxerapp/fluxer/main/compose.yaml
curl -O https://raw.githubusercontent.com/fluxerapp/fluxer/main/config/config.production.template.json

Step 2: Create Configuration

Create a config directory and configuration file:
mkdir -p config
cp config.production.template.json config/config.json
Edit config/config.json with your settings:
config/config.json
{
  "$schema": "../packages/config/src/ConfigSchema.json",
  "env": "production",
  "domain": {
    "base_domain": "chat.example.com",  // Your domain
    "public_scheme": "https",
    "public_port": 443
  },
  "database": {
    "backend": "sqlite",
    "sqlite_path": "./data/fluxer.db"
  },
  "internal": {
    "kv": "redis://valkey:6379/0",
    "kv_mode": "standalone"
  },
  "s3": {
    "access_key_id": "YOUR_S3_ACCESS_KEY",
    "secret_access_key": "YOUR_S3_SECRET_KEY",
    "endpoint": "http://127.0.0.1:8080/s3"
  },
  "services": {
    "server": {
      "port": 8080,
      "host": "0.0.0.0"
    },
    "media_proxy": {
      "secret_key": "GENERATE_A_64_CHAR_HEX_SECRET"
    },
    "admin": {
      "secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET",
      "oauth_client_secret": "GENERATE_A_64_CHAR_HEX_SECRET"
    },
    "marketing": {
      "enabled": true,
      "secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET"
    },
    "gateway": {
      "port": 8082,
      "admin_reload_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
      "media_proxy_endpoint": "http://127.0.0.1:8080/media"
    }
  },
  "auth": {
    "sudo_mode_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
    "connection_initiation_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
    "vapid": {
      "public_key": "YOUR_VAPID_PUBLIC_KEY",
      "private_key": "YOUR_VAPID_PRIVATE_KEY"
    }
  },
  "integrations": {
    "search": {
      "engine": "meilisearch",
      "url": "http://meilisearch:7700",
      "api_key": "YOUR_MEILISEARCH_API_KEY"
    }
  }
}
Use these commands to generate secure random secrets:
# Generate 64-character hex secrets
openssl rand -hex 32

# Generate VAPID keys for push notifications
npx web-push generate-vapid-keys
Replace all GENERATE_A_64_CHAR_HEX_SECRET placeholders with unique values.

Step 3: Review Docker Compose File

The provided compose.yaml includes these services:
compose.yaml
services:
  valkey:
    image: valkey/valkey:8.0.6-alpine
    container_name: valkey
    restart: unless-stopped
    command: ['valkey-server', '--appendonly', 'yes', '--save', '60', '1']
    volumes:
      - valkey_data:/data
    healthcheck:
      test: ['CMD', 'valkey-cli', 'ping']
      interval: 10s
      timeout: 5s
      retries: 5

  fluxer_server:
    image: ghcr.io/fluxerapp/fluxer-server:stable
    container_name: fluxer_server
    restart: unless-stopped
    init: true
    environment:
      FLUXER_CONFIG: /usr/src/app/config/config.json
      NODE_ENV: production
    ports:
      - '8080:8080'
    depends_on:
      valkey:
        condition: service_healthy
    volumes:
      - ./config:/usr/src/app/config:ro
      - fluxer_data:/usr/src/app/data
    healthcheck:
      test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:8080/_health || exit 1']
      interval: 15s
      timeout: 5s
      retries: 5

  meilisearch:
    image: getmeili/meilisearch:v1.14
    container_name: meilisearch
    profiles: ['search']
    restart: unless-stopped
    environment:
      MEILI_ENV: production
      MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
    ports:
      - '7700:7700'
    volumes:
      - meilisearch_data:/meili_data

volumes:
  valkey_data:
  fluxer_data:
  meilisearch_data:
The meilisearch service uses Docker profiles. Enable it with --profile search when starting.

Step 4: Set Environment Variables

Create a .env file for secrets:
.env
# Meilisearch master key (used for search API)
MEILI_MASTER_KEY=your-secure-meilisearch-master-key-min-16-chars

# Optional: Override default ports
FLUXER_HTTP_PORT=8080
MEILI_PORT=7700

Step 5: Start Fluxer

Start the core services:
# Start Fluxer without search
docker compose up -d

# Or start with search enabled
docker compose --profile search up -d
Check service health:
docker compose ps
docker compose logs -f fluxer_server
You should see “Server listening on http://0.0.0.0:8080” in the logs.

Step 6: Configure Reverse Proxy

Fluxer requires a reverse proxy with TLS termination. Here’s an example Nginx configuration:
/etc/nginx/sites-available/fluxer
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name chat.example.com;

    ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;

    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # Headers
    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;

    # Increase timeouts for long-polling
    proxy_read_timeout 3600;
    proxy_send_timeout 3600;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}
Caddyfile
chat.example.com {
    reverse_proxy localhost:8080
}

Step 7: Access Your Instance

Navigate to https://chat.example.com in your browser. You should see the Fluxer registration page.
1

Create Admin Account

Register the first user account. This becomes the instance administrator.
2

Access Admin Panel

Visit https://chat.example.com/admin to configure instance settings.
3

Create a Community

Set up your first community (guild) and invite users.

Optional: Enable Voice & Video

To enable voice and video calls, you need to set up LiveKit:
# Add LiveKit to compose.yaml with the voice profile
docker compose --profile voice up -d
Create config/livekit.yaml:
config/livekit.yaml
port: 7880

keys:
  '<your-api-key>': '<your-api-secret>'

rtc:
  tcp_port: 7881

turn:
  enabled: true
  udp_port: 3478

room:
  auto_create: true
  max_participants: 100
  empty_timeout: 300
Update your config.json to enable voice:
"integrations": {
  "voice": {
    "enabled": true,
    "api_key": "<your-api-key>",
    "api_secret": "<your-api-secret>",
    "url": "wss://chat.example.com/livekit",
    "webhook_url": "https://chat.example.com/api/webhooks/livekit"
  }
}
LiveKit requires UDP ports 3478, 7881, and 50000-50100 to be accessible from the internet. Configure your firewall accordingly.
See the Voice Setup Guide for detailed LiveKit configuration.

Maintenance

Backups

Back up these critical directories:
# Backup script
#!/bin/bash
BACKUP_DIR="/backup/fluxer-$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# Stop containers
docker compose stop

# Backup volumes
docker run --rm -v fluxer_fluxer_data:/data \
  -v $BACKUP_DIR:/backup alpine \
  tar czf /backup/fluxer_data.tar.gz -C /data .

docker run --rm -v fluxer_valkey_data:/data \
  -v $BACKUP_DIR:/backup alpine \
  tar czf /backup/valkey_data.tar.gz -C /data .

# Restart containers
docker compose start

Updates

# Pull latest images
docker compose pull

# Recreate containers
docker compose up -d

# Clean up old images
docker image prune -f

Logs

# View all logs
docker compose logs -f

# View specific service
docker compose logs -f fluxer_server

# Export logs
docker compose logs --no-color > fluxer-logs-$(date +%Y%m%d).txt

Troubleshooting

Check if the container is running and healthy:
docker compose ps
docker compose logs fluxer_server
Verify the health endpoint:
curl http://localhost:8080/_health
The SQLite database is created automatically on first run. Check permissions:
docker compose exec fluxer_server ls -la /usr/src/app/data/
If needed, reset the database:
docker compose down -v  # Warning: deletes all data
docker compose up -d
Ensure Meilisearch is running and configured:
docker compose --profile search ps meilisearch
curl http://localhost:7700/health
Verify the API key in config.json matches MEILI_MASTER_KEY in .env.
Adjust Node.js memory limits:
fluxer_server:
  environment:
    NODE_OPTIONS: "--max-old-space-size=4096"  # 4GB limit

Next Steps

Configuration

Explore all configuration options and advanced settings

Architecture

Understand Fluxer’s system components and design

Voice Setup

Configure LiveKit for voice and video calls

Scaling

Scale to thousands of concurrent users

Build docs developers (and LLMs) love