Files
QSfera/PRODUCTION_READINESS.md
T
2026-06-09 21:26:17 +03:00

13 KiB

QSfera Production Readiness

Date: 2026-06-08.

Benchmarks Used

Completed In This Pass

  • Android release builds now fail fast when release signing variables are missing, so unsigned release artifacts cannot be published by accident.
  • Android version was raised to 1.3.7 with versionCode 35.
  • Android now has QSfera-specific Argus publishing scripts: local upload-keystore generation, signed APK staging, APK metadata verification, debug-certificate rejection, and Argus upload.
  • Android 1.3.7/35 was published to Argus as qsfera-mobile on 2026-06-08. Public manifest and latest download both report SHA-256 c9c044c1332f8d973c64502ad2e3227ad92398101e7354ce9dbe7f708e7e693b.
  • Android auto-upload source paths are normalized and new/first source folders start from timestamp 0, so existing media is eligible for initial backup.
  • Android auto-upload validates persisted read permission and DocumentFile.canRead() before scanning SAF folders.
  • Android immediate auto-upload scheduling no longer blocks the caller while waiting for WorkManager state.
  • Android new auto-upload configurations default to Wi-Fi-only transfers for photos and videos.
  • Android auto-upload now exposes a no-roaming control for photo and video backup, stores it in Room schema version 50, and maps mobile backup without roaming to WorkManager NetworkType.NOT_ROAMING.
  • Server qsfera_full compose files now require explicit admin, Keycloak, and S3/MinIO secrets instead of demo defaults.
  • Server qsfera_full/env.production.example provides a tracked production-safe starting point with TLS validation enabled and demo users disabled.
  • Server qsfera_full/validate-production-env.sh checks production .env invariants before compose validation: TLS validation enabled, demo users disabled, pinned production image, required domains, required secrets, and no public-production MinIO.
  • Server now has a Raspberry Pi 5 Docker path matching the Ikar/Argus deployment style: Server/docker-compose.rpi5.yml, Server/.env.example, and Server/docs/raspberry-pi-5-docker.md.
  • Server Docker builds now accept explicit production metadata for QSFERA_VERSION, QSFERA_EDITION, and QSFERA_BUILD_DATE, and the Raspberry Pi 5 compose path defaults to pinned image qsfera-cloud-server:7.0.0-rpi5-stable.
  • Windows/Desktop update channel defaults now match the build channel: stable builds default to stable, beta builds default to beta.
  • Windows/Desktop CI now validates production release invariants before Windows packaging and requires signing variables for stable tag releases.
  • Windows/Desktop now has a configured HTTPS update feed at https://qsfera.kusoft.xyz/desktop/updates/stable.xml; the feed returned HTTP 200 on 2026-06-08 and contains the XML elements parsed by Desktop/src/gui/updater/updateinfo.cpp.
  • Added scripts/verify-production-state.ps1 as a repeatable live production endpoint gate for the public server status, Android Argus manifest/download, and Desktop update feed.
  • scripts/verify-production-state.ps1 -VerifyAndroidDownload passed on 2026-06-08: server edition=stable/productversion=7.0.0, Android 1.3.7/35, downloaded APK size 12220848, APK SHA-256 c9c044c1332f8d973c64502ad2e3227ad92398101e7354ce9dbe7f708e7e693b, and valid Desktop no-update feed.
  • Added Server/scripts/verify-rpi-production.sh, declared a loopback-only Pi metrics port in Server/docker-compose.rpi5.yml, and expanded the Raspberry Pi Docker runbook with local/public status checks, container/image checks, Prometheus metrics verification, backup/restore drill steps, and Docker data-root/retention planning.
  • Added systemd monitoring units for the Pi: Server/systemd/qsfera-rpi-production-check.service, Server/systemd/qsfera-rpi-production-check.timer, Server/systemd/qsfera-rpi-production-check-alert@.service, Server/systemd/rpi-production-check.env.example, plus installer Server/scripts/install-rpi-production-monitoring.sh and alert helper Server/scripts/alert-rpi-production-check-failure.sh.
  • Deployed the Pi metrics/checker update on 2026-06-09. Before upload, /mnt/data/qsfera/cloud-server/src/docker-compose.rpi5.yml was backed up to /mnt/data/qsfera/backups/docker-compose.rpi5.yml-20260609-181614.bak; docker compose -f docker-compose.rpi5.yml up -d recreated and started qsfera-cloud-server; docker compose ps reported loopback ports 127.0.0.1:9200->9200/tcp and 127.0.0.1:9205->9205/tcp.
  • Server/scripts/verify-rpi-production.sh passed on the Pi on 2026-06-09 with PUBLIC_STATUS_URL=https://qsfera.kusoft.xyz/status.php and REQUIRE_METRICS=true: image qsfera-cloud-server:7.0.0-rpi5-stable, container running/healthy, Docker root /mnt/data/docker, root free space 43.0 GiB, data free space 851.5 GiB, local and public status stable/7.0.0, and Prometheus metrics reachable.
  • Deployed the Pi systemd monitoring timer on 2026-06-09. systemd-analyze verify for the three installed unit files returned exit 0; systemctl is-enabled qsfera-rpi-production-check.timer returned enabled; systemctl is-active qsfera-rpi-production-check.timer returned active; systemctl show qsfera-rpi-production-check.service returned Result=success, ExecMainStatus=0, ActiveState=inactive; and journalctl -u qsfera-rpi-production-check.service recorded QSfera Raspberry Pi production verification passed: 0 warning(s).

Raspberry Pi 5 Check

  • Pi target checked on 2026-06-08: 192.168.0.185 reports aarch64, 64-bit Debian 13, Docker 29.4.3, Docker Compose v5.1.3, and Docker server architecture aarch64.
  • Before stable-image deployment, the old Pi server was running as local/dev image qsfera-cloud-server:rpi5-local; public /status.php reported edition: dev and productversion: 7.0.0.
  • The Pi server now runs through /mnt/data/qsfera/cloud-server/src/docker-compose.rpi5.yml with pinned image qsfera-cloud-server:7.0.0-rpi5-stable, bind-mounted config/data under /mnt/data/qsfera/cloud-server, loopback backend port 127.0.0.1:9200, loopback metrics port 127.0.0.1:9205, and Docker root /mnt/data/docker.
  • Before switching the Pi server to compose, config/data were backed up to /mnt/data/qsfera/backups/cloud-server-before-compose-20260608-200921.tar.gz. The archive was created with sudo tar, had size 213M, and tar -tzf completed successfully.
  • Before switching to the stable image, config/data were backed up to /mnt/data/qsfera/backups/cloud-server-before-stable-image-20260608-201536.tar.gz. The archive had size 213M, and tar -tzf completed successfully.
  • docker run --rm --entrypoint /usr/bin/qsfera qsfera-cloud-server:7.0.0-rpi5-stable version --skip-services returned Version: 7.0.0, Edition: stable, and Compiled: 2026-06-08 00:00:00 +0000 UTC.
  • After deployment, docker compose ps reported qsfera-cloud-server as Up and healthy; docker inspect reported IMAGE=qsfera-cloud-server:7.0.0-rpi5-stable HEALTH=healthy.
  • Local https://127.0.0.1:9200/status.php and public https://qsfera.kusoft.xyz/status.php both returned edition: stable and productversion: 7.0.0; the public request returned HTTP 200.
  • After Docker builder cache cleanup and the stable deployment, /dev/mmcblk0p2 reported 57G size, 12G used, 43G available, 21% use. /mnt/data reported 916G size, 18G used, 852G available, 3% use.

Android Argus Publication Check

  • Current public Argus manifest for https://argus.kusoft.xyz/api/apps/qsfera-mobile/manifest?platform=android&channel=stable reports release id 677fa0bc-07f8-4981-b7fe-98d6de283cb8, version 1.3.7, channel stable, platform android, package kind apk, androidVersionCode 35, package size 12220848, and SHA-256 c9c044c1332f8d973c64502ad2e3227ad92398101e7354ce9dbe7f708e7e693b.
  • Independent download verification of https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable produced a 12220848 byte APK with the same SHA-256 c9c044c1332f8d973c64502ad2e3227ad92398101e7354ce9dbe7f708e7e693b.
  • The previously published 1.3.5/33 APK matched Argus SHA-256 b7d5bdcb49527c00983a15849252fa42189dee4287754803c46cf2f32e2130f3, but apksigner reported CN=Android Debug with certificate SHA-256 b86d745cecb01ca24bda03092fe94ca7801678513b97edd1175bcabfdea4e941.
  • The new 1.3.7/35 APK is signed by CN=QSfera Argus Upload, O=QSfera, C=RU with certificate SHA-256 ea5c304c78ee333f6586f54c933d986c1f865da9c4e3595f8fe0df274c1ab877.
  • AppUpdateManager validates downloaded APK package name, greater versionCode, Argus androidVersionCode, and signer digest against the installed app signature. Because of that local code path, devices that installed debug-signed 1.3.5 should be treated as needing reinstall or an explicit migration plan before they can move to the production-signed 1.3.7.

Remaining P0

  • Back up the gitignored Android release signing files created under Android/signing/ and Android/argus-signing.local.properties in a secure external secret store. Without this key material, future in-place Android updates from the production-signed 1.3.7 cannot be signed with the same certificate.
  • Provide CI/Argus signing secrets derived from the same release key: QSFERA_RELEASE_KEYSTORE, QSFERA_RELEASE_KEYSTORE_PASSWORD, QSFERA_RELEASE_KEY_ALIAS, and QSFERA_RELEASE_KEY_PASSWORD.
  • Decide the rollout policy for any devices that installed the debug-signed Argus 1.3.5 APK. The production-signed 1.3.7 APK is the correct current release, but installed debug-signed clients will not satisfy the app's own signer-digest check for an in-place update.
  • Fill production domains, ACME email, admin passwords, Keycloak passwords, and storage secrets from a secret manager. Do not commit real values.
  • Run ./validate-production-env.sh .env and then docker compose config for Server/devtools/deployments/qsfera_full with a filled production .env; Docker CLI is not available in this local environment, so compose rendering is not locally verified.
  • Provide real Windows signing secrets in CI: QSFERA_DESKTOP_SIGN_PACKAGE=True and QSFERA_DESKTOP_CODESIGN_CERTIFICATE with the Craft-compatible signing certificate reference.
  • Publish the first signed Windows MSI and update https://qsfera.kusoft.xyz/desktop/updates/stable.xml from the current no-update XML to a concrete <version>, <versionstring>, and HTTPS .msi <downloadurl>.

Remaining P1

  • Add Google Photos-style backup status UX: overall status, per-item status, queued/paused/permanent-failure states, and low-storage messaging.
  • Add mobile-data controls comparable to Google Photos/Yandex Disk beyond the Wi-Fi-only default: mobile-data limit and no-video-over-mobile-data options.
  • Store auto-upload sync cursors per source folder rather than one timestamp for all folders.
  • Configure QSFERA_ALERT_WEBHOOK_URL in /etc/qsfera/rpi-production-check.env if off-host alert delivery is required; the installed failure service currently logs through systemd-cat and journal without an external endpoint.
  • Verify sharing controls against Google Drive and Yandex Disk expectations: link expiration, password, disable downloads, organization-only access, and role inheritance.