Skip to content

docs/ops: define and exercise panel database, Kubernetes state, and key recovery #728

Open

Description

@Baylem

Production recovery needs a tested procedure that distinguishes panel SQL state from Kubernetes workload state. A game-volume backup cannot reconstruct users, role bindings, audit history, or standalone cluster credentials.

Priority: Medium; production-readiness follow-up. Evidence: static inspection of upstream 04e41075cafc4c1a99bcb3723b0a8745ee810957 (2026-10-16). The failure scenarios below have not been reproduced in a running cluster.

Existing behavior to preserve

  • docs/architecture.md:67 assigns desired workload reconciliation to Kubernetes CRs and the operator.
  • api/cmd/management.go:19 uses Kubernetes management storage in combined mode and SQL-backed management storage in standalone mode.
  • api/internal/controlplane/store.go:45 requires the original encryption key for existing standalone credentials and rejects missing/wrong keys.
  • docs/standalone-panel.md:67 already documents database/WAL backup, separate key custody, and restoration permissions. This issue requests a broader recovery contract and drill, not replacement of that guidance.
  • docs/install.md:871 describes upgrade validation, which is distinct from disaster recovery.

Recommended fix

Document an explicit backup inventory and recovery order for both modes:

  1. SQL database: users, role bindings, sessions/shares, configuration, audit state, and standalone management rows. For PostgreSQL, define an external backup/PITR and failover integration; for SQLite, retain a consistent snapshot or stopped-copy procedure rather than copying only the live database file.
  2. Kubernetes state: CRDs, GameServer/Module/Backup objects, relevant Secrets, and the cluster's own recovery procedure.
  3. Workload data: primary and other persistent volumes, storage-class constraints, and Restic/CSI recovery dependencies.
  4. Keys: separately protected standalone encryption key and relevant certificate/credential recovery. Retain the key versions required by retained database backups.

Define operator-selected RPO/RTO targets and demonstrate them; do not promise a universal target in chart defaults. After restoring old SQL state, reconcile authorization and revoked credentials against the intended recovery point. Invalidate restored sessions/share links when the recovery policy requires it. Validate workload identity/UID associations before granting access; do not infer ownership from pod names.

Acceptance criteria

  • Runbooks cover database outage, database loss, original-key loss, and restoring SQL while game pods continue running.
  • A drill restores users/permissions, registrations, and credential-backed operations with the correct key, and fails closed with a wrong key.
  • Recovery does not recreate or delete live games just to reconstruct the panel.
  • The documentation identifies which data cannot be recovered from a game backup and records measured RPO/RTO for the drill fixture.
  • Recovery steps preserve audit evidence and explicitly handle stale authorization/session state.

Related: #629 introduced standalone storage and #707 covers PostgreSQL operation/migration. This is a recovery follow-up to those capabilities.

Activity

  1. ValgulNecron commented on Oct 20, 2026

    @ValgulNecron
    Collaborator

    Thanks. Part of this is already covered: docs/standalone-panel.md ("Storage and recovery") documents DB and WAL backup, separate key custody and key rotation. What's missing is a runbook for database loss and key loss, an exercised recovery drill, and RPO/RTO targets. Two reference fixes: #707 is the PostgreSQL-backed e2e test PR, not an operations/migration PR, and the standalone storage PR is #630, not #629.

    Go ahead with a PR that adds:

    • A recovery runbook building on docs/standalone-panel.md: database loss, encryption-key loss, restoring the SQL database while game pods keep running, and how the panel database and Kubernetes state are brought back in line.
    • An automated end-to-end recovery drill in CI that follows that runbook: back up, destroy, restore, verify the panel serves correctly, and record the measured RPO and RTO. Please add it as an e2e test under test/e2e/ and register it in test/e2e/buckets.sh, following the existing e2e conventions (parallel-safe, unique names, login rate-limit budget).
    • A wrong-key case in the drill: restoring with the wrong management key must fail closed with the existing "management encryption key is missing" style error (api/internal/controlplane/store.go:119), never serve partially decrypted data.
  2. Baylem commented on Oct 25, 2026

    @Baylem
    MemberAuthor

    Covered by #770. The runbook builds on the existing standalone guidance and covers database loss, original-key loss, SQL/Kubernetes reconciliation, stale authorization and recovery while games continue running. It sets operator-selected RPO/RTO targets and explains the limits of the SQLite drill and external PostgreSQL recovery.

    The registered recovery E2E bucket backs up, destroys and restores the private panel, checks users, permissions, encrypted cluster dispatch, sessions and shares, preserves audit evidence, and records measured recovery-point age and recovery time. Its wrong-key probe must exit without serving HTTP and uses a positive control. Recovery uses --panel-key-provisioned to prevent replacement-key generation.

    The references are corrected in the runbook: standalone storage is #630, and #707 is PostgreSQL-backed E2E coverage. The latest helper corrections are in 41eea08; local source compilation passed, with runtime measurements left to CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions