Semaphor

Upgrading

Safely upgrade your Semaphor self-hosted deployment

Overview

When you upgrade Semaphor, database schema changes are applied automatically on container startup. This guide covers how to upgrade safely, back up your data, and roll back if needed.

Key principles:

  • All three services (api-service, data-service, data-service-sidecar) must run the same version
  • Schema migrations run on the first startup after pulling new images
  • Always back up your data before upgrading

Semaphor applies schema changes automatically when the container starts. Some upgrades include destructive changes (table or column removals) that cannot be undone without a backup. Always back up before upgrading.

Check Your Current Version

docker-compose logs api-service | grep "Semaphor v"

Development / Testing (Embedded Database)

If you're using the default embedded PostgreSQL (no DATABASE_URL configured), your data is stored in the semaphor-data Docker volume. This volume persists across container restarts and image upgrades — pulling a new image does not wipe your data.

Quick Upgrade

For test or evaluation environments where data loss is acceptable:

docker-compose pull
docker-compose up -d

Safe Upgrade (Preserve Data)

For development environments where you want to keep your data:

1. Back up the Docker volume:

mkdir -p backups
 
# Stop services for a consistent backup
docker-compose stop
 
# Back up the data volume
docker run --rm \
  -v semaphor-data:/data:ro \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/semaphor-backup-$(date +%Y%m%d).tar.gz -C /data .
 
# Back up your configuration
cp semaphor.env backups/semaphor.env.$(date +%Y%m%d)

2. Pull new images:

Use a specific version tag rather than latest:

# Update your docker-compose.yml to pin the version, then:
docker-compose pull

3. Start services:

docker-compose up -d

Schema changes are applied automatically during startup.

4. Verify the upgrade:

# Check for the upgrade message and any errors
docker-compose logs api-service | grep -i "upgrade\|schema\|error\|Semaphor v"
 
# Verify health
curl http://localhost:3000/api/health

Rollback (Embedded Database)

If something goes wrong after upgrading:

# Stop services
docker-compose down
 
# Remove the current data volume
docker volume rm semaphor-data
 
# Recreate the volume and restore from backup
docker volume create semaphor-data
docker run --rm \
  -v semaphor-data:/data \
  -v $(pwd)/backups:/backup \
  alpine sh -c 'cd /data && tar xzf /backup/semaphor-backup-YYYYMMDD.tar.gz'
 
# Restore your configuration
cp backups/semaphor.env.YYYYMMDD semaphor.env
 
# Update docker-compose.yml to use the previous version, then:
docker-compose up -d

Replace YYYYMMDD with your backup date.


Production (External Database)

If you're using an external PostgreSQL (DATABASE_URL is configured), the same automatic schema sync applies — but you have more control over backups and can test upgrades in a staging environment first.

Production upgrades require a database backup. Schema changes are applied automatically on startup and may include destructive changes (dropped tables or columns). Without a backup, these changes cannot be reversed.

Pre-Upgrade Checklist

Before upgrading a production deployment:

  1. Take a full database backup (see below)
  2. Back up your configuration (semaphor.env, docker-compose.yml)
  3. Review the Release Notes for your target version to check for breaking schema changes
  4. Test the upgrade in a staging environment first if possible
  5. Pin all 3 services to the same version tag — never mix versions

Step-by-Step Upgrade

1. Back up your database:

# Using pg_dump with custom format (supports selective restore)
pg_dump -Fc -f semaphor-backup-$(date +%Y%m%d).dump "YOUR_DATABASE_URL"
 
# Or using plain SQL format
pg_dump -f semaphor-backup-$(date +%Y%m%d).sql "YOUR_DATABASE_URL"

2. Back up your configuration:

cp semaphor.env semaphor.env.bak
cp docker-compose.yml docker-compose.yml.bak

3. Update to the new version:

Edit docker-compose.yml to use specific version tags:

services:
  api-service:
    image: semaphorstack/api-service:0.1.200  # Pin to target version
  data-service:
    image: semaphorstack/data-service:0.1.200
  data-service-sidecar:
    image: semaphorstack/data-service-sidecar:0.1.200

4. Pull and restart:

docker-compose pull
docker-compose up -d

5. Monitor the upgrade:

# Watch startup logs for the UPGRADING banner and any errors
docker-compose logs -f api-service

You should see output like:

==================================================================
  UPGRADING Semaphor: 0.1.195 -> 0.1.200
  Ensure you have a backup of your data before proceeding.
  Database schema changes will be applied automatically.
==================================================================

6. Verify health:

curl http://localhost:3000/api/health

Rollback (External Database)

If the upgrade causes issues:

1. Stop services:

docker-compose down

2. Restore your database:

# Drop and recreate the database, then restore
pg_restore -d "YOUR_DATABASE_URL" --clean --if-exists semaphor-backup-YYYYMMDD.dump
 
# Or if you used plain SQL format:
psql "YOUR_DATABASE_URL" < semaphor-backup-YYYYMMDD.sql

3. Revert to the previous version:

# Restore your previous docker-compose.yml
cp docker-compose.yml.bak docker-compose.yml
 
docker-compose pull
docker-compose up -d

How Schema Migrations Work

Understanding how Semaphor handles database changes helps you plan upgrades with confidence.

Automatic Schema Sync

On every container startup, the API service compares the expected database schema (bundled in the Docker image) against the actual database and applies any differences. This process:

  • Adds new tables and columns automatically
  • Removes tables and columns that are no longer in the schema
  • Runs before the application starts accepting requests

Schema changes are applied on the first startup after pulling new images. Restarting the same version does not re-apply changes.

When Data Loss Can Occur

Most upgrades only add new tables or columns — these are non-destructive. However, some upgrades may include:

  • Column removals: Data in removed columns is permanently deleted
  • Table removals: All data in removed tables is permanently deleted
  • Column type changes: May cause data truncation or conversion

These destructive changes are documented in the Release Notes for each version.


Version Pinning

For production deployments, always pin to specific version tags instead of using latest:

services:
  api-service:
    image: semaphorstack/api-service:0.1.200
  data-service:
    image: semaphorstack/data-service:0.1.200
  data-service-sidecar:
    image: semaphorstack/data-service-sidecar:0.1.200

This ensures:

  • All services run the same version
  • Upgrades only happen when you explicitly change the version
  • You can roll back to a known-good version

Troubleshooting

Schema sync failed on startup

Check the API service logs for error messages:

docker-compose logs api-service | grep -i "error\|schema\|migration"

If schema sync fails, the container will exit. Restore from your backup and contact support.

Container won't start after upgrade

  1. Check logs: docker-compose logs api-service
  2. Verify all 3 services use the same version tag
  3. If the error is license-related, check that your license key is still valid
  4. Restore from backup and try the previous version

Checking which version is running

# From container logs
docker-compose logs api-service | grep "Semaphor v"
 
# From the Docker image tag
docker-compose images

Support

If you encounter issues during an upgrade: