Files
codex 4a7e907be7
CI / tests-and-images (pull_request) Successful in 3m12s
Runner smoke test / runner-smoke (pull_request) Successful in 2s
Clarify Windows validation evidence
2026-10-31 01:02:08 +03:00

4.5 KiB

Backup and restore

Current status

The owner requires that a complete production archive never be written to the VPS, even temporarily. The reviewed implementation in PR #59 streams stopped Compose state directly from the root receiver to the owner's Windows client; the client stores it only under D:\Dev\akyldash\.backups. The VPS retains only a secret-free identity (backup ID, size, archive and manifest hashes, manifest) in root-owned release state. The Windows rerun passed 12 synthetic client checks, 8 protocol checks, and a disposable real-NTFS private owner-ACL fixture. The production D: path, SSH connection, VPS installation, and full production backup remain unverified. There is no verified production backup, so production deployment remains blocked.

External backup flow

  • The release receiver takes the shared deployment lock and stops the stack.
  • It streams a tar/gzip archive through a bounded binary SSH session. It does not create a local archive or temporary full-size copy on the VPS.
  • The Windows receiver requires the exact D: repository, a real NTFS path, restrictive ACLs, and the exact /.backups/ rule in that checkout's local .git/info/exclude. Before SSH connects, it also requires at least 100 GiB plus 1 MiB of free D: space, matching the protocol's maximum archive size. The ACL owner and every allowed full-control entry must be the current user, SYSTEM, or local Administrators; other and deny entries fail closed. It writes into a private staging directory, checks the stream size and SHA-256, verifies the archive and manifest, then publishes the complete backup directory without overwriting an existing ID. It checks the published ACL before acknowledging; on failure it removes only the same verified staging directory, and refuses cleanup if its identity or contents have changed.
  • Only after Windows confirms the stored archive identity does the VPS proceed with image cutover. If backup transport or verification fails, it attempts to restart the previous services and records a recovery journal if restart fails.
  • Rollback first challenges Windows with the root-pinned previous backup identity. Windows verifies the local archive and streams it back; the VPS compares its exact size and SHA-256 before stopping services. Rollback then creates a fresh external backup of the current state before changing image references. It restores images only, never application data or OpenSearch state.

Windows PowerShell is the intended client. The Windows checks exercised the destination and ACL rules, including a disposable real-NTFS private owner-ACL fixture. The actual production D: destination and SSH path remain unverified. An owner must separately test archive restore on an isolated target before relying on this path. Do not restore over production as a test.

Backup contents and limits

The existing infra/backup/archive.py manifest records the Git revision, deployment-file hashes, image references and IDs, and the components included in the archive: application data, OpenSearch, Caddy data/configuration, production.env, and the review secret. Secret-bearing files and SQLite files are archived with restrictive modes. The archive verifier rejects unsafe members and checks SQLite integrity. SSH encrypts archive bytes in transit. The destination contains secrets and private keys; D: encryption at rest (for example, BitLocker) has not been verified. This PR adds no client-side encryption or signing, so the owner must verify storage encryption and retain the restrictive ACLs before using it.

The external protocol caps control frames at 64 KiB, chunks at 1 MiB, and the archive at 100 GiB. SSH provides transport encryption and server host-key verification. The receiver uses a fixed SSH command and does not accept a caller-supplied path or shell command. It relies on the existing owner SSH configuration; no key, host entry, sudo rule, or VPS setting is added here.

Restore

Use infra/backup/archive.py restore only with an archive already present in a protected owner-controlled location, and target a new staging directory on an isolated recovery host. Review recovery and deployment first. This PR does not perform or authorize a production restore, data migration, or VPS operation. Keep the previous external archive until the owner has verified the replacement and explicitly approved its retention period.

The former /var/backups/akyldash create/verify procedure is superseded and must not be used for a full production archive on the VPS.