Server deploymentDocker ComposeNginx / TLS
Release format.hreleaseSHA-256 + Ed25519
Device protectionA/B + rollback3 MiB per slot
On this page

01Production topology#

Deployment boundaries

Nginx terminates TLS and forwards traffic to loopback-bound services. API, Admin, the public website and PostgreSQL are managed through Compose. This documentation is served from a separate static root and needs no API or database credentials.

ComponentCurrent model
ComputeOne Linux host; multi-zone HA was not observed.
DatabasePostgreSQL 17, persistent Docker volume, pg_isready healthcheck.
IngressNginx, separate hostnames, Let’s Encrypt TLS.
Artifact storagePrivate R2; no local-storage fallback in production.
IaC statusCompose, Nginx and shell/systemd configuration are in the repository. A Terraform/Pulumi resource graph is not established.

02Server releases & rollback#

  • Review the source snapshot and configuration; run unit, integration and build checks.
  • Build a versioned image. Schema changes require migration only after backup and compatibility checks.
  • Replace only the intended service; verify API/database/object-storage health and authentication smoke tests.
  • Retain the previous image. Roll it back on failure; database restore is a separate controlled operation, not an ordinary image rollback.

GitHub Actions exists for Tauri desktop bundles. This is not evidence that native SwiftUI, API and firmware releases are all shipped through fully automated production CI/CD. The current release path also includes local tests and operator-controlled deployment.

03Signed release package#

Package contents
Hamroh-X.Y.Z-BNN.hrelease
├── firmware.bin
├── release-metadata.json
├── firmware.sig
├── release-metadata.sig
└── release-notes.txt

The package is a deterministic ZIP with five allowlisted entries and strict size/path constraints. Metadata includes version, build, securityVersion, protocolVersion, hardwareRevision, binarySize, SHA, source commit, build timestamp, provisioning, A/B and rollback flags, and build-evidence hashes.

  • Isolated clean build with ESP-IDF 5.5.2; provisioning is disabled for normal customer firmware.
  • Firmware and canonical metadata receive separate Ed25519 signatures. The private key remains local/offline.
  • The server independently verifies SHA, both signatures, the ESP image header, hardware, build/security and configuration.
  • Path traversal, extra files, symlinks, duplicate entries and conflicting immutable objects are rejected.

04Release lifecycle & targeting#

Explicit lifecycle transitions

A reviewed DRAFT becomes READY. Only ROLLING_OUT releases can be offered as candidates. PAUSED stops new offers but does not remotely undo a transfer already in progress.

INTERNAL requires one explicit compatible target. BETA/STABLE use percentage-based cohorts. Channel, hardware, version, build/security and target checks constrain eligibility. Promoting the same artifact across channels does not change its binary contents.

05Normal customer OTA flow#

From download to boot confirmation

The Desktop verifies the artifact, retains one exclusive USB descriptor and sends no chunks before READY. Firmware writes to the inactive slot. Success depends on post-reboot version/build and VALID confirmation.

StageKey invariant
BEGIN → PREPARING → READYMetadata acceptance and flash preparation have separate timeouts. No byte zero before READY.
TransferBounded chunks/windows, cumulative ACKs, checked offsets, TIOCEXCL and the same FD.
OTA_ENDExact size, SHA and on-device signature checks precede boot-target selection.
PENDING_VERIFYAfter the grace interval, identity and runtime readiness are checked; mark-valid and security commit are diagnosed.
VALID / rollbackCritical failure reasons are retained; ESP-IDF rollback protection remains. Optional touch failure is not an immediate panic.

06Monitoring, backup & recovery#

The health endpoint reports API, PostgreSQL and object-storage state. Authenticated heartbeats retain the latest firmware/build/slot and last-seen values; the default response requests the next heartbeat in 300 seconds. These are observability signals, not SLA measurements.

ControlEvidence status
Health & heartbeatImplemented; production health was inspected.
Log rotationCompose: json-file, 10 MB × 3 files.
Database backuppg_dump script and restore runbook exist. Offsite scheduling, encryption and the latest restore drill are not verified in this snapshot.
RPO / RTONo verified measurements; establish through business requirements and restore exercises.
Silicon securitySecure Boot / flash encryption need separate manufacturing validation; eFuse programming is not part of ordinary deployment.

07Verification evidence & next gates#

The local 1.6.8 Build 53 release verification passed the ESP-IDF clean build, independent signature/SHA verification, 33 package tests, 18 host regression groups and 12 LVGL render cases. The exact ELF fixed serial/handler stack budget was 288 bytes; this is not a physical runtime high-water measurement.

The earlier normal OTA chain has a recorded successful test-device installation. This document does not certify physical acceptance or a new transfer speed for the 1.6.8 image. PTY benchmarks must not be equated with real USB/flash elapsed time.

  • Release gate: separately authorized one-device OTA, power-loss/rollback testing and post-boot heartbeat verification.
  • Operational gate: independent security review, dependency patches, backup/restore drill and measurable RPO/RTO.
  • Scale gate: load testing, shared throttling, database recovery and separated server fault domains.
Sources & evidence

This reference is based on the current source snapshot and read-only infrastructure inspection. Hashes identify the reviewed files; this is not an independent audit opinion.

  • infra/docker-compose.production.yml
  • infra/nginx/hamroh.conf
  • infra/backup-db.sh
  • .github/workflows/desktop-build.yml
  • scripts/prepare_firmware_release.sh
  • packages/release-package/index.js
  • apps/api/src/storage/storage.service.ts
  • apps/api/src/firmware/lifecycle.ts
  • apps/api/src/firmware/rollout.ts
  • components/user_app/user_app.c
  • docs/normal-release-1.6.8.md
  • docs/ota-display-throughput-2026-09-09.md
Download: evidence.json
Next documentArchitecture
Hamroh IO · Technical documentation · 2026-09-10

Search documentation