All runtime config now flows exclusively through BSB plugin config
(this.config.*) or shared module parameters. No more env var overrides.
Changes:
- Delete shared/env-overrides.ts (envStr/envBool/envInt helpers)
- version.ts: remove env var chain, keep only .bf-version file + "dev"
- firmware.ts: replace BF_FIRMWARE_SIGNING_KEY env with config.signingKeyPem
parameter, remove tryParsePrivateKey helper
- secrets.ts: replace process.env.CREDENTIALS_DIRECTORY with
config.systemdCredsDir
- mqtt-bridge.ts: accept MqttConfig object instead of reading process.env
- service-store: replace envStr calls with this.config.*, build pgUrl from
config fields, add pgPoolMax config
- pg-adapter.ts: accept poolMax constructor param instead of env var
- service-admin-http: add firmwareSigningKey, firmwareImportApiKey,
otaImportApiKey, systemdCredsDir config fields; pass to shared modules
- middleware.ts: replace tokenMatchesEnv with tokenMatchesExpected using
deps.firmwareImportApiKey/otaImportApiKey
- service-api-http: add mqttUrl/mqttUsername/mqttPassword/mqttTopicPrefix
config fields; pass to initMqttBridge
- service-coordinator-ws: replace envStr calls with this.config.*
- sec-config.yaml: add all new config fields with sensible defaults
- docker-compose.coolify.yml: remove all BF_* env vars from server service
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PG 18 uses major-version-specific subdirs under /var/lib/postgresql.
Old mount at /var/lib/postgresql/data breaks pg_upgrade compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cloud cameras are now a distinct type ('cloud') managed entirely by
sync. Bidirectional: cameras added in vendor cloud appear automatically,
removed cameras get deleted. Cloud cameras and their entities are
read-only in admin UI — no manual editing.
- Camera type CHECK widened to include 'cloud'
- New columns: cloud_account_id, cloud_vendor_camera_id,
cloud_stream_url, cloud_stream_type
- Repo: upsertCloudCamera, deleteCloudCamerasNotIn,
listCloudCamerasByAccount
- Sync replaces import: full reconciliation per account
- Hik-Connect: fetch HLS preview URLs via previewURLs endpoint
- Tuya: fetch stream URLs during sync (not just on demand)
- Kiosk API: GET /api/kiosk/cameras/:id/stream returns fresh
relay URL from vendor (session-based URLs expire)
- Cloud cameras show read-only detail page with cloud badge
- Coolify compose: postgres 18 as default, BF_DB=postgres,
server depends_on postgres healthy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BF_DB=postgres + BF_PG_URL activates the PgAdapter path. Service-store
detects driver, creates PgAdapter with connection pool, runs
TENANT_MIGRATIONS from migrations-pg.ts, tracks version in
schema_migrations table.
docker-compose.coolify.yml gains a postgres service (postgres:17-alpine)
behind the "postgres" profile — disabled by default. Set BF_DB=postgres
in Coolify env to activate. Server env auto-constructs BF_PG_URL from
BF_PG_USER/PASSWORD/DB vars.
SQLite remains default — no change for existing deployments.
Coolify pulls from GitHub and runs docker compose build — no guaranteed
env vars like SOURCE_COMMIT. Previous approach relied on ARG/ENV
passthrough that silently defaulted to "dev".
Fix: install git in the builder stage, COPY .git into context, run
git describe --tags --always to derive the version, write it to
/app/server/.bf-version. version.ts reads this file as a fallback
between env vars and the "dev" literal.
Chain: BF_SERVER_VERSION env → BF_BUILD_VERSION env → .bf-version file
→ COOLIFY_GIT_COMMIT env → SOURCE_COMMIT env → "dev".
Also: fix .gitignore for rauc-signing/ (was under wrong path).
- server Dockerfile installs wget — bookworm-slim doesn't include it
by default, so the healthcheck CMD silently failed → Coolify marked
the container unhealthy.
- nodered healthcheck swapped to /nrdp/ (always 200 when runtime up)
via wget --spider; previous /nrdp/auth/login returned non-2xx when
adminAuth disabled.
- start_period bumped to 90s for nodered's flow load on smaller hosts.
- Kiosk discovery: cloud fallback now frame-eu.betterportal.net per
the managed-fleet endpoint.