79 lines
10 KiB
Markdown
79 lines
10 KiB
Markdown
# QSfera Production Readiness
|
|
|
|
Date: 2026-06-08.
|
|
|
|
## Benchmarks Used
|
|
|
|
- Google Photos Android backup: automatic photo/video backup, selected device folders, backup status, mobile-data limits, roaming controls, and battery optimization guidance.
|
|
Source: https://support.google.com/photos/answer/6193313?co=GENIE.Platform%3DAndroid&hl=en
|
|
- Google Drive Android offline files and sharing roles.
|
|
Sources: https://support.google.com/drive/answer/2375012?co=GENIE.Platform%3DAndroid&hl=en and https://support.google.com/drive/answer/2494822?co=GENIE.Platform%3DAndroid&hl=en
|
|
- Google storage quota behavior across Drive and Photos.
|
|
Source: https://support.google.com/drive/answer/9312312?hl=en
|
|
- Google Drive for desktop: tray entry, multi-account sign-in, sync status, notifications, offline files, pause/resume sync, adding folders, and stream/mirror model.
|
|
Sources: https://support.google.com/drive/answer/10838124?co=GENIE.Platform%3DDesktop&hl=en-fm and https://support.google.com/drive/answer/13401938?hl=en
|
|
- Yandex Disk Android auto-upload setup, account choice, network choice, source folders, and uploaded/not-uploaded indicators.
|
|
Source: https://yandex.com/support/yandex-360/customers/disk/app/android/en/autoupload/setup
|
|
- Yandex Disk mobile link sharing controls: view-only, disable downloads, password, expiration, and organization-only links.
|
|
Source: https://yandex.com/support/yandex-360/customers/disk/app/android/en/actions/share
|
|
- Yandex Disk desktop: Windows/macOS desktop app, selective sync, auto-save folders, automatic update, autorun, and sleep-prevention behavior during sync.
|
|
Sources: https://www.yandex.com/support/yandex-360/customers/disk/web/en/desktop, https://www.yandex.com/support/yandex-360/customers/disk/desktop/windows/en/reserve-copy, and https://yandex.com/support/yandex-360/customers/disk/desktop/windows/en/installation
|
|
|
|
## 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.6` with `versionCode` `34`.
|
|
- 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.6`/`34` was published to Argus as `qsfera-mobile` on 2026-06-08. Public manifest and latest download both report SHA-256 `921f2dad21aa85991a30ab5e7792f79c32f87ba5bb14188185ff2e6a438b4428`.
|
|
- 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.
|
|
- 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`.
|
|
|
|
## 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`, and loopback port `127.0.0.1:9200`.
|
|
- 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 `bf2c78ad-7a26-459c-93f9-42b54c039279`, version `1.3.6`, channel `stable`, platform `android`, package kind `apk`, `androidVersionCode` `34`, package size `12217032`, and SHA-256 `921f2dad21aa85991a30ab5e7792f79c32f87ba5bb14188185ff2e6a438b4428`.
|
|
- Independent download verification of `https://argus.kusoft.xyz/api/apps/qsfera-mobile/download/latest?platform=android&channel=stable` produced a `12217032` byte APK with the same SHA-256 `921f2dad21aa85991a30ab5e7792f79c32f87ba5bb14188185ff2e6a438b4428`.
|
|
- 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.6`/`34` 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.6`.
|
|
|
|
## 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 `1.3.6` 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.6` 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, no-video-over-mobile-data, and no-roaming options.
|
|
- Store auto-upload sync cursors per source folder rather than one timestamp for all folders.
|
|
- Add production monitoring runbook and compose verification for metrics, tracing, alerts, backups, and restore drills.
|
|
- Move Docker build cache and/or Docker data-root planning for the Pi to `/mnt/data`, or add documented retention, so future server image rebuilds cannot fill the root filesystem again.
|
|
- Verify sharing controls against Google Drive and Yandex Disk expectations: link expiration, password, disable downloads, organization-only access, and role inheritance.
|