Skip to main content

Upgrading

Upgrading Planeon means moving your PLANEON_VERSION forward, applying any new migrations, and rolling the services onto the new images. The order below is not a suggestion — each step depends on the one before it, and skipping or reordering them is how deployments end up serving traffic against a schema they don't understand.

The order (never reorder)

  1. Back up. See Backup and restore — take a fresh database dump, and confirm your SECRETS_MASTER_KEY and .env are backed up alongside it. Do this before touching anything else; it's your only way back if the upgrade goes wrong.

  2. Bump PLANEON_VERSION in .env to the release you're upgrading to.

  3. Pull the new images:

    docker compose pull
  4. Apply migrations explicitly:

    docker compose run --rm migrate
  5. Gate: confirm the schema is current before rolling anything.

    docker compose run --rm migrate status

    Every migration must report Applied. Do not proceed to step 6 until it does — re-run step 4 and check again if anything is pending.

  6. Roll the services:

    docker compose up -d

    This recreates the five version-pinned services — api, worker, gateway, guacd, and web — on the new images (postgres and redis are untouched; caddy runs a fixed upstream caddy:2-alpine image, so a PLANEON_VERSION bump does not recreate it — it only changes if you edit its own image or config; migrate stays a one-shot that doesn't run as part of up).

    Live desktop sessions drop during the upgrade

    Recreating guacd tears down its process, which terminates every live desktop connection tunnelled through it (RDP, VNC, SSH). Expect active sessions to disconnect during the upgrade window; users reconnect once the new guacd is up. Schedule the upgrade accordingly, or drain sessions first if a hard cutover isn't acceptable.

Why this order

The api and worker each embed the newest migration version they expect at build time, and each refuses to report ready — /readyz returns 503 naming migrations — until the database schema is at or above that version (see Observability → Readiness semantics). Migrating before rolling the service images means the schema is already current by the time the new containers start, so there's no window where a freshly rolled service sits not ready waiting on a migration you haven't run yet — and no window where a load balancer or orchestrator routes traffic to a container that isn't actually ready to serve it.

Migrations are also never applied automatically by api or worker at startup, upgrade or otherwise. That's a deliberate platform invariant, not an oversight: it keeps schema changes visible and auditable as a distinct, observable step, and it avoids multiple replicas racing to migrate the same database concurrently. You run docker compose run --rm migrate yourself, every time, and the migrate status gate is how you confirm it actually happened before you move on.

Rollback

Planeon's migrations are roll-forward only — there are no down-migrations in production, and applied migration files are append-only (CI rejects a pull request that edits or deletes one). There is no migrate down step to reach for.

If an upgrade needs to be undone, roll back by restoring your pre-upgrade backup: stop the services, restore the database dump you took in step 1 (see Backup and restore → Restore procedure), and redeploy the previous PLANEON_VERSION. This is exactly why the backup in step 1 above is not optional — it's the only rollback path.

Multi-worker deployments

If you run more than one worker replica (docker compose up -d --scale worker=N), upgrading them is safe with no special coordination. Each worker's job leases carry a deadline; if a worker is stopped mid-upgrade while holding a lease, any surviving worker reclaims the expired lease once it passes and requeues the job for another worker to pick up (handlers are idempotent, so a retry from the start is always safe) — jobs are never silently dropped, and row-level locking (FOR UPDATE SKIP LOCKED) keeps two workers from ever running the same job twice. You can upgrade worker replicas one at a time or all together with the same docker compose up -d in step 6.