Upgrades

Upgrades

Upgrade Tindra by pulling the target image and recreating the application container. Migrations run before the HTTP server starts, so allow time for schema changes and backfills as well as process startup.

Before upgrading

  1. Record the running version and image tag or digest, then read the target release notes.
  2. Back up Postgres and DATA_DIR, including source maps, using the backup guide. Keep the configuration and matching image version with your recovery records.
  3. Test the upgrade against a restored copy of your data where possible. Index creation and telemetry backfills can take longer on a large database.
  4. Review the authentication, storage, and retention changes below, particularly if upgrading from a build before the September 2026 changes.

Docker Compose

Keep this setting on the application service:

services:
  tindra:
    stop_grace_period: 75s

After selecting the image version in docker-compose.yml:

docker compose pull tindra
docker compose up -d tindra
docker compose logs --tail=100 tindra

Pulling only the application service avoids upgrading Postgres as a side effect. Check for successful migration/startup messages and request /healthz before returning traffic. With the default host port:

curl --fail http://127.0.0.1:8080/healthz

This confirms that the HTTP server is responding; also sign in and verify telemetry ingestion. /healthz is not a comprehensive database or ingestion-health check. Downtime depends on outstanding work, schema changes, and data volume rather than a fixed sub-second promise.

Authentication and account access

New SSO users now require a matching valid invitation and verified provider email. Existing linked identities still resolve to their accounts. Microsoft requires a concrete tenant UUID and explicit linking where a verified-email claim is unavailable.

Before enabling or upgrading SSO, make sure the administrator account exists and has the correct provider link. Use administrative SSO linking when needed. A provider's failed discovery or incomplete configuration does not restore local password access: configured SSO policy also disables password invitation acceptance and password-reset redemption.

SSO users now follow local MFA requirements. Enrolled users verify TOTP after SSO login; unenrolled users must enroll when REQUIRE_MFA=true. Keep access to the server or an authenticated administrator for MFA recovery. Password changes revoke prior sessions and pending login/reset credentials; administrator-issued reset links also clear the local authenticator. See User Management.

Compose and persistent storage

The production Compose example now requires a nonempty POSTGRES_PASSWORD and does not publish Postgres on a host port. When adopting it, preserve the password of an existing database; changing the environment variable does not rotate a password already stored by Postgres.

The runtime checks that DATA_DIR is writable. New image storage is owned by UID/GID 65532, but existing volumes and bind mounts keep their old ownership. Correct their permissions before restart if needed, and preserve that ownership on restores.

The 75-second stop grace period allows HTTP shutdown and bounded queue draining. Ingestion retries use in-memory queues, so forced termination may lose pending data. Do not assume an accepted request means every item has already been stored.

Networking

Private/internal uptime destinations are blocked by default. If you intentionally monitor private services, set UPTIME_ALLOW_PRIVATE_IPS=true and recreate the container. Alert webhooks and passthrough requests use the separate WEBHOOK_ALLOW_PRIVATE_IPS setting. Source-code enrichment always blocks private destinations.

Review TRUSTED_PROXIES against the actual proxy chain. Client-address detection now walks forwarded hops from the nearest proxy toward the first untrusted address, and rejects malformed supplied chains. This can change the IP recorded in audit logs and used for rate limiting.

Retention and history

RETENTION_DAYS=0 disables general age cleanup only. LOG_ROW_LIMIT, TX_ROW_LIMIT, and the independent profile retention/storage settings still apply. Existing data over these limits can be removed after startup.

Cleanup runs immediately and normally repeats hourly; a pass that reaches its deletion budget schedules another pass after five minutes. These are periodic cleanup policies, so rows or bytes can temporarily exceed their limits.

Completed cron check-ins now follow general age retention using completion time, or receipt time for legacy records. Running check-ins and monitor summaries remain, so a monitor can still show its current state after older history is gone. Transaction cleanup also deletes child spans. Retention does not recreate data when you later increase a limit.

Checking the current version

Open Settings > Overview to see the running version and commit. Startup logs also report them. Record the deployed image tag or digest before replacing the container.

Zero-downtime upgrades

Running two application containers does not by itself guarantee a zero-downtime upgrade. They share schema changes, and the application runs background workers as well as HTTP handlers. Before attempting a rolling deployment, verify mixed-version schema compatibility, shared file access, and background-worker behavior for that release.

For a standard single-instance deployment, plan a maintenance window and resume traffic after migrations and startup checks complete.

Manual migrations

SKIP_AUTO_MIGRATE=true is an advanced option for deployments that run migrations as a separate step. Run the target image's migrations before starting it with traffic enabled:

docker compose run --rm --no-deps --entrypoint /tindra tindra migrate

This assumes Postgres is already running and Compose points to the target image and correct database. Some migrations run in explicit batches and may take time. If one fails, inspect the migration error and database state before retrying; forcing a migration version changes bookkeeping and is not a substitute for completing or repairing the schema change.

Rollback

Keep production images pinned to a release tag or digest you have validated. Tindra does not automatically undo migrations when you start an older image.

If an upgrade fails, stop the new application and determine whether the old image is compatible with the resulting schema. If compatibility is uncertain or a migration partially applied, restore the pre-upgrade database and matching data-directory backup, then start the recorded old image. A restore discards data received after that backup, so choose the recovery point deliberately.

Release notes

Check the GitHub releases page for the target version's changelog before upgrading. Match these instructions to the version you deploy, especially for authentication and retention behavior changes.

Monitor ingestion health

Use Ingestion Monitoring for authenticated Prometheus scrapes, queue and write metrics, and a recovery checklist when accepted data is not appearing. Pending in-memory data is not part of a database backup.