Upgrades

To upgrade self-hosted Stategraph, run a newer tag of the Stategraph container. It migrates its databases at start, with no separate migration step.

Pick a version

The releases page lists versions and notes. In production, pin a version tag, not latest:

services:
  server:
    image: ghcr.io/stategraph/stategraph-server:2.5.7

Then:

  • Docker Compose: docker compose pull and docker compose up -d
  • Kubernetes: set stategraph.image.tag and run helm upgrade
  • Amazon ECS: set stategraph_image and run terraform apply
  • Google Cloud Run: mirror the new tag into Artifact Registry, update image: in the service definition, and redeploy

Releases follow semantic versioning. For the CLI and images, see Releases.

Boot-time migrations

At each start, Stategraph migrates the stategraph database, then serves requests. With Orchestration on, it also migrates the terrateam database, in parallel and with no order dependency.

  • Stategraph checks that the applied migrations are a prefix of its own list. If they differ, it exits non-zero and applies nothing on top.
  • Each migration commits by itself, so an interrupted run leaves a consistent prefix, never a partial migration.
  • Replicas that migrate at the same time are safe: primary keys guard the bookkeeping rows. The loser of the race fails with a visible duplicate-key error, retries at restart, and never applies a migration twice.
  • /health/ready answers 502 until Stategraph has migrated and serves, so a load balancer or readiness probe keeps traffic on the old containers. /health/live answers 200 as soon as Stategraph listens on port 8080. See Health checks.
  • After a failed Orchestration migration, Stategraph waits 30 seconds before it retries, so retries come at a steady interval with the error in the log.
  • A failed Stategraph server restarts every few seconds. In Docker Compose, the container waits for a healthy PostgreSQL through depends_on.
  • With Orchestration on, the stategraph migration also drops and rebuilds the postgres_fdw bridge to terrateam at each start. On managed PostgreSQL, this needs superuser rights: see Enable Orchestration.

Rolling replacement

At stop, Stategraph refuses new requests, finishes those in progress, then shuts down, within a 60 second grace period. Give the container that period: stop_grace_period: 60s in Compose, stopTimeout of 60 on ECS, or terminationGracePeriodSeconds: 60 on the pod. Stopping it sooner cuts requests short.

For zero downtime, run several replicas and let readiness control traffic. Set the same STATEGRAPH_OAUTH_COOKIE_SECRET on each, so that sessions survive.

Behavior changes to check

Read the release notes of the versions that you skip. These changes affect running self-hosted deployments:

  • 2.5.7: The container sets TERRAT_SESSION_COOKIE_NAME=terrat_session, so the Orchestration session cookie no longer collides with the console session cookie. A deployment that replaces the whole container environment must keep it, or a VCS OAuth callback signs console users out.
  • 2.5.6: Orchestration does not start when GITHUB_APP_ID is set without GITHUB_WEBHOOK_SECRET, and no longer accepts unsigned webhook events. A running deployment with GitHub credentials and no secret stops starting Orchestration until you set one. Only the container log shows the failure.
  • 2.5.2: The self-hosted setup wizard image moved to ghcr.io/stategraph/orchestration-setup.
  • 2.5.2: The users API renamed /api/v1/users/toggle-admin to /api/v1/users/set-instance-admin and the is_admin fields to is_instance_admin, and added is_tenant_admin. Update API clients that create or delete users.

Verify an image

Released images have a Sigstore keyless signature and a SLSA build provenance attestation. The signing certificate records the repository, release workflow, and source commit. Check it with cosign before you run a new tag:

cosign verify \
  --certificate-identity-regexp '^https://github\.com/stategraph/mono/\.github/workflows/release\.yml@' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/stategraph/stategraph-server:2.5.7

Read the provenance with the same identity:

cosign verify-attestation --type slsaprovenance1 \
  --certificate-identity-regexp '^https://github\.com/stategraph/mono/\.github/workflows/release\.yml@' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/stategraph/stategraph-server:2.5.7 \
  | jq -r .payload | base64 -d | jq .predicate

The predicate names the builder, the source commit, and the workflow run that built the image.

  • latest resolves to the same digest as its version, so both tags check the same signature.
  • The per-arch tags <version>-amd64 and <version>-arm64 have their own signature and provenance, and both commands accept them with the same identity flags.
  • The CLI image, ghcr.io/stategraph/stategraph, verifies the same way.
  • Tags before 2.5.2 have no signature, and cosign verify fails for them.

Next steps