Skip to content

Upgrades and backups

Upgrade a self-hosted SpecsGraph install with Docker Compose, pin image versions, back up Postgres with pg_dump, restore with psql and know what else to keep.

Pin versions and read release notes

The compose file tags every SpecsGraph image with ${SPECSGRAPH_VERSION}, set in .env. Pin it to a release such as 1.0.0 and never use latest: with a moving tag, any docker compose pull can upgrade you without notice, and the web, API and MCP services could end up on different versions.

Before each upgrade, read the notes for every release between your version and the target on the releases page (opens in a new tab). They list new settings, changed defaults and any step you must take by hand. Watch the repository for releases on GitHub so security fixes reach you quickly.

To see which version an install runs, list the images of its services. The tag after the image name is the version, the same value as SPECSGRAPH_VERSION:

Shell
docker compose images web api mcp

Upgrade an install

  1. Back up the database

    Take a fresh backup as shown below. It is your way back if the upgrade goes wrong.

    Shell
    mkdir -p backups
    docker compose exec -T postgres pg_dump -U specsgraph -d specsgraph | gzip > backups/specsgraph-pre-1.1.0.sql.gz
  2. Change the version

    Set SPECSGRAPH_VERSION in .env to the new release.

    Shell
    sed -i 's/^SPECSGRAPH_VERSION=.*/SPECSGRAPH_VERSION=1.1.0/' .env
  3. Pull and restart

    Pull the new images, then let Compose recreate the services that changed.

    Shell
    docker compose pull
    docker compose up -d
  4. Watch the start

    Follow the logs until the api service has applied its migrations and all three services are serving again. Then sign in and open a project to confirm.

    Shell
    docker compose logs -f web api mcp

Database migrations

Schema changes ship inside the images. The api service applies pending migrations when it starts, so there is no separate migration command. If the release notes name a version you must pass through, upgrade to that version first, let it start, then continue.

Roll back

Starting an older image does not undo migrations. To roll back, set SPECSGRAPH_VERSION to the previous version and restore the backup you took before the upgrade, following the restore steps below.

Postgres and Redis images

postgres:16 follows 16.x releases and redis:7 follows 7.x, so docker compose pull brings in their updates within that major version. A new major Postgres version is different: its data directory format changes, so you move with a dump and restore into a fresh volume, not by changing the tag.

Back up Postgres

Postgres holds everything that is not yet in Git and everything that never goes there: the graph, open proposals, review threads, members and personal access token records. Back it up with pg_dump, which works while SpecsGraph is running.

Take a backup

Shell
cd /opt/specsgraph
mkdir -p backups
docker compose exec -T postgres pg_dump -U specsgraph -d specsgraph | gzip > backups/specsgraph-$(date +%F).sql.gz

Schedule backups

Run the backup every night from cron and copy the files off the server, for example to object storage in another location. A backup on the same disk does not survive the loss of that disk. In a crontab, % must be escaped:

crontabText
15 2 * * * cd /opt/specsgraph && docker compose exec -T postgres pg_dump -U specsgraph -d specsgraph | gzip > backups/specsgraph-$(date +\%F).sql.gz

Restore a backup

Stop the SpecsGraph services, recreate the database, load the dump with psql, then start the services again. The restore replaces everything in the database.

Shell
docker compose stop web api mcp
docker compose exec -T postgres dropdb -U specsgraph --if-exists specsgraph
docker compose exec -T postgres createdb -U specsgraph specsgraph
gunzip -c backups/specsgraph-2026-09-24.sql.gz \
  | docker compose exec -T postgres psql -U specsgraph -d specsgraph -v ON_ERROR_STOP=1
docker compose start web api mcp

Tip

Test your restores

A backup you have never restored is a guess. Every few months, restore the latest dump into a scratch install and sign in to check it.

What else to back up

ItemWhy it matters
.envHolds SPECSGRAPH_SECRET_KEY. Without the same key, restored sessions and access tokens stop working.
./secrets/github-app.pemThe GitHub App private key. You can generate a new one in GitHub, so this is a convenience, not a necessity.
docker-compose.yml and CaddyfileYour exact setup, including any changes you made to the examples.

Store copies of .env and the key as carefully as the secrets they are. Redis holds only queues and caches, so it does not need backups. The caddy-data volume is optional too: Caddy requests new certificates if it is lost.

Your spec history is also in Git

Every published change is on your base branch, so the published spec and its full revision history survive even if the database does not. What Git does not hold is work in progress and workspace data: open proposals, review threads, members and personal access token records. Treat the repository as a second copy of the spec, not as a replacement for database backups.

Next steps