Skip to main content
This guide covers upgrading self-hosted Fluxer deployments, including database migrations, configuration changes, and rollback procedures.

Release Channels

Fluxer provides multiple Docker image tags:
TagDescriptionUpdate FrequencyStability
stableProduction releases~MonthlyHigh
latestLatest stable releaseSame as stableHigh
nightlyNightly builds from mainDailyMedium
vX.Y.ZSpecific version (e.g., v1.2.3)Never (pinned)High
edgeBleeding edge (development)On commitLow
For production, use stable or pin to a specific version (e.g., v1.2.3).

Versioning Scheme

Fluxer follows Semantic Versioning:
v1.2.3
│ │ │
│ │ └─ PATCH: Bug fixes, security patches (backward compatible)
│ └─── MINOR: New features (backward compatible)
└───── MAJOR: Breaking changes (may require migration)
  • PATCH (1.2.3 → 1.2.4): Safe to upgrade without downtime
  • MINOR (1.2.3 → 1.3.0): May include new config options (defaults provided)
  • MAJOR (1.2.3 → 2.0.0): Breaking changes, read release notes carefully

Pre-Upgrade Checklist

1

Read Release Notes

Check the changelog for breaking changes:
# View releases
curl -s https://api.github.com/repos/fluxerapp/fluxer/releases/latest | jq
2

Backup Data

Critical: Always backup before upgrading.
# Stop services
docker compose stop

# Backup SQLite database
docker run --rm -v fluxer_fluxer_data:/data \
  -v $(pwd)/backups:/backup alpine \
  tar czf /backup/fluxer-data-$(date +%Y%m%d).tar.gz -C /data .

# Backup Valkey (if persistence enabled)
docker run --rm -v fluxer_valkey_data:/data \
  -v $(pwd)/backups:/backup alpine \
  tar czf /backup/valkey-data-$(date +%Y%m%d).tar.gz -C /data .

# Backup configuration
cp -r config backups/config-$(date +%Y%m%d)
For Cassandra, see Cassandra Backup.
3

Check Disk Space

Ensure sufficient space for new images and migrations:
df -h
docker system df
4

Review Configuration Schema

New versions may add config options. Compare schemas:
# Download new schema
curl -O https://raw.githubusercontent.com/fluxerapp/fluxer/main/packages/config/src/ConfigSchema.json

# Validate your config against new schema
npx ajv validate -s ConfigSchema.json -d config/config.json
5

Plan Downtime Window

Schedule upgrades during low-traffic periods. Typical downtime:
  • PATCH: < 1 minute (container restart)
  • MINOR: 1-5 minutes (may include DB migrations)
  • MAJOR: 5-30 minutes (complex migrations)

Upgrade Procedures

Docker Compose (Monolith)

Standard upgrade process for single-server deployments:
# 1. Pull latest image
docker compose pull fluxer_server

# 2. Stop current container
docker compose stop fluxer_server

# 3. Backup (see checklist above)
# ...

# 4. Start new version
docker compose up -d fluxer_server

# 5. Monitor logs
docker compose logs -f fluxer_server

# 6. Verify health
curl http://localhost:8080/_health
upgrade.sh
#!/bin/bash
set -e

echo "==> Fluxer Upgrade Script"

# Configuration
BACKUP_DIR="./backups/$(date +%Y%m%d-%H%M%S)"
COMPOSE_FILE="compose.yaml"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Step 1: Pull new image
echo "==> Pulling latest image..."
docker compose pull fluxer_server

# Step 2: Stop services
echo "==> Stopping services..."
docker compose stop

# Step 3: Backup data
echo "==> Backing up data..."
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 .

cp -r config "$BACKUP_DIR/config"

echo "==> Backup saved to: $BACKUP_DIR"

# Step 4: Start new version
echo "==> Starting new version..."
docker compose up -d

# Step 5: Wait for health check
echo "==> Waiting for services to be healthy..."
sleep 10

# Step 6: Verify
echo "==> Verifying health..."
if curl -sf http://localhost:8080/_health > /dev/null; then
  echo "✓ Fluxer is healthy"
else
  echo "✗ Health check failed!"
  exit 1
fi

# Step 7: Clean up old images
echo "==> Cleaning up old images..."
docker image prune -f

echo "==> Upgrade complete!"
Make executable and run:
chmod +x upgrade.sh
./upgrade.sh

Kubernetes (Microservices)

Rolling update with zero downtime:
# 1. Update image tag in deployment
kubectl set image deployment/fluxer-api \
  api=ghcr.io/fluxerapp/fluxer-api:v1.3.0

# 2. Monitor rollout
kubectl rollout status deployment/fluxer-api

# 3. Verify pods are running
kubectl get pods -l app=fluxer-api

# 4. Check logs
kubectl logs -l app=fluxer-api --tail=100
For automated rollback:
# If issues occur, rollback
kubectl rollout undo deployment/fluxer-api

Database Migrations

Fluxer runs migrations automatically on startup. Monitor logs for migration status:
docker compose logs fluxer_server | grep -i migration
Example output:
[INFO] Running database migrations...
[INFO] Applied migration: 001_add_thread_support.sql
[INFO] Applied migration: 002_add_user_badges.sql
[INFO] Migrations complete (2 applied, 0 skipped)
Manual intervention required if you see:
[ERROR] Migration failed: 003_schema_change.sql
[ERROR] Reason: duplicate column name
Check the migration troubleshooting section.

Configuration Updates

New versions may introduce config options. Fluxer provides defaults, but you should review:

1. Check for New Options

# Compare your config with the template
diff config/config.json \
  <(curl -s https://raw.githubusercontent.com/fluxerapp/fluxer/main/config/config.production.template.json)

2. Add New Options (if desired)

Example: New telemetry section added in v1.3.0:
{
  "telemetry": {
    "enabled": false,
    "otlp_endpoint": ""
  }
}
Defaults are used if not specified, so adding is optional unless you want to enable the feature.

3. Handle Deprecated Options

Release notes will warn about deprecated config. Example:
v2.0.0:
  BREAKING: Removed `services.queue.data_dir`
  Use `services.queue.storage_backend` instead:
  
  Before:
    "queue": { "data_dir": "./data/queue" }
  
  After:
    "queue": { 
      "storage_backend": "filesystem",
      "filesystem": { "path": "./data/queue" }
    }
Update your config before upgrading to avoid startup failures.

Rollback Procedures

If an upgrade fails, rollback to the previous version:

Docker Compose Rollback

# 1. Stop current (broken) version
docker compose stop fluxer_server

# 2. Restore previous image
docker tag ghcr.io/fluxerapp/fluxer-server:v1.2.3 \
  ghcr.io/fluxerapp/fluxer-server:stable

# Or pull specific version
docker pull ghcr.io/fluxerapp/fluxer-server:v1.2.3
docker tag ghcr.io/fluxerapp/fluxer-server:v1.2.3 \
  ghcr.io/fluxerapp/fluxer-server:stable

# 3. Restore data backup (if database was corrupted)
BACKUP_FILE="backups/20260304-120000/fluxer_data.tar.gz"

docker run --rm -v fluxer_fluxer_data:/data \
  -v $(pwd):/backup alpine \
  sh -c "rm -rf /data/* && tar xzf /backup/$BACKUP_FILE -C /data"

# 4. Restart with old version
docker compose up -d fluxer_server

# 5. Verify
curl http://localhost:8080/_health

Kubernetes Rollback

# Automatic rollback to previous revision
kubectl rollout undo deployment/fluxer-api

# Or rollback to specific revision
kubectl rollout history deployment/fluxer-api
kubectl rollout undo deployment/fluxer-api --to-revision=5

Migration Troubleshooting

Symptom: Migration hangs or times outCause: Large database, slow disk I/OSolution:
  1. Increase timeout:
    {
      "database": {
        "migration_timeout_ms": 300000  // 5 minutes
      }
    }
    
  2. Run migration manually:
    docker exec fluxer_server node -e '
      const db = require("./packages/database");
      db.runMigrations({ timeout: 600000 });
    '
    
Symptom: Error: column "xyz" already existsCause: Migration was partially applied or run twiceSolution:
  1. Check migration status:
    docker exec fluxer_server sqlite3 /data/fluxer.db \
      "SELECT * FROM migrations;"
    
  2. Mark migration as complete (if it actually is):
    docker exec fluxer_server sqlite3 /data/fluxer.db \
      "INSERT INTO migrations (version, applied_at) \
       VALUES ('003_schema_change', datetime('now'));"
    
  3. Or manually fix schema and rerun.
Symptom: InvalidRequest: Keyspace 'fluxer' already existsCause: Migration tried to recreate existing keyspaceSolution:Cassandra migrations are idempotent. Check if schema is actually up-to-date:
docker exec cassandra cqlsh -e "DESCRIBE KEYSPACE fluxer;"
If schema matches the migration, mark as applied in migration tracker.

Version-Specific Upgrade Notes

Upgrading to v2.0.0 (Hypothetical)

This is a major version with breaking changes.
Breaking Changes:
  1. Configuration Schema Overhaul
    • services.queue.data_dir removed, use services.queue.storage_backend
    • auth.session_secret split into auth.sudo_mode_secret and auth.connection_initiation_secret
  2. Database Schema Changes
    • New threads table for message threading
    • messages table adds thread_id column (nullable for backward compat)
  3. API Changes
    • /api/v1/guilds/:id/channels now requires VIEW_CHANNEL permission (previously no auth)
    • Removed deprecated /api/v1/users/me/settings endpoint (use /api/v1/users/@me/settings)
Migration Steps:
# 1. Update config (see above breaking changes)
vim config/config.json

# 2. Validate config against new schema
npx ajv validate \
  -s https://raw.githubusercontent.com/fluxerapp/fluxer/v2.0.0/packages/config/src/ConfigSchema.json \
  -d config/config.json

# 3. Backup (critical!)
./backup.sh

# 4. Pull v2.0.0
docker compose pull fluxer_server:v2.0.0

# 5. Upgrade
docker compose up -d

# 6. Monitor logs for migration completion
docker compose logs -f fluxer_server | grep migration

# 7. Test functionality
# - Create a channel
# - Send messages
# - Create a thread
# - Test voice channels

Best Practices

Pin Versions

Use specific version tags in production:
fluxer_server:
  image: ghcr.io/fluxerapp/fluxer-server:v1.2.3
Not:
fluxer_server:
  image: ghcr.io/fluxerapp/fluxer-server:stable

Test Upgrades

Test upgrades in a staging environment:
  1. Clone production config
  2. Restore database backup to staging
  3. Run upgrade on staging
  4. Validate functionality
  5. If successful, upgrade production

Subscribe to Releases

Get notified of new releases:

Scheduled Maintenance

Set a regular upgrade cadence:
  • PATCH: Weekly or as needed (security)
  • MINOR: Monthly
  • MAJOR: Quarterly (or when ready)
Avoid falling too far behind to ease upgrades.

Upgrade Notifications

Fluxer can notify admins of available updates:
config.json
{
  "instance": {
    "update_notifications": true,
    "update_check_interval_hours": 24
  },
  "alerts": {
    "webhook_url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
  }
}
Admins will see a banner in the admin panel when updates are available.

Getting Help

If you encounter issues during an upgrade:
  1. Check the changelog: github.com/fluxerapp/fluxer/releases
  2. Search existing issues: github.com/fluxerapp/fluxer/issues
  3. Ask the community: Community server
  4. Email support: [email protected]
Include in your report:
  • Current version (e.g., v1.2.3)
  • Target version (e.g., v1.3.0)
  • Deployment mode (monolith vs microservices)
  • Database backend (SQLite vs Cassandra)
  • Relevant log excerpts

Next Steps

Quick Start

Return to the quick start guide

Configuration

Review configuration options

Scaling

Plan for growth and scaling

Architecture

Understand the system design

Build docs developers (and LLMs) love