Commit graph

24 commits

Author SHA1 Message Date
Mitchell R
7d81891b0e
fix(version): derive server version from git at Docker build time
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).
2026-05-21 16:02:21 +02:00
Mitchell R
8e75ed379d
feat(nodered): install Dashboard 2.0 + auto-sync on entities page
- Bake @flowfuse/node-red-dashboard into Node-RED Docker image
- Fire-and-forget syncDashboardsFromNodered() on GET /admin/entities
  so dashboard tabs appear without manual sync button click
2026-05-21 12:05:12 +02:00
Mitchell R
3d5e27bdfb
fix(release): surface build versions 2026-05-21 08:51:41 +02:00
Mitchell R
411d9900a9
chore: target latest-stable everywhere — Debian Trixie + gtk4 v4_14
- CI workflow container: debian:trixie-slim (was bookworm-slim)
- Server image base: node:23-trixie-slim (was bookworm-slim)
- Kiosk Cargo.toml: gtk4 features v4_14 (was v4_8) — matches Trixie's
  stock gtk 4.14 without backports juggling
- setup-pi-kiosk.sh header: Trixie+ target (was Bookworm+)

Glibc matches across Pi OS Trixie, Coolify host (Trixie), CI build
container — no symbol drift at runtime.
2026-05-19 04:21:14 +02:00
Mitchell R
fa4c1684a3
fix(deploy+kiosk): server healthcheck wget, nodered spider, cloud discovery
- 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.
2026-05-19 04:15:25 +02:00
Mitchell R
a523e678c7
fix(nodered): base is Alpine — use apk + su-exec, not apt + gosu 2026-05-19 04:06:36 +02:00
Mitchell R
eb1ac8245a
fix(nodered): install gosu, swap su-exec → gosu (debian base, not alpine) 2026-05-19 04:04:53 +02:00
Mitchell R
f087fdc056
fix(nodered): entrypoint runs as root to fix stale /data state, drops to node-red via su-exec
Previous deploy left /data/settings.js as a DIRECTORY (Docker auto-mkdir
from a failed bind mount earlier). cp from non-root user then failed
'Permission denied' writing inside it.

Entrypoint now:
- Detects + rm -rf the stale directory
- Seeds /data/settings.js from /usr/src/bf-settings.js
- Chowns /data to node-red
- exec su-exec node-red:node-red to drop privileges before npm start
2026-05-19 04:00:58 +02:00
Mitchell R
7baa1a07f9
fix(nodered): seed /data/settings.js via entrypoint wrapper
The /data named volume hides anything Dockerfile COPYs into /data, so
the previous CMD override pointing at /usr/src/bf-settings.js didn't
help — Node-RED's launch script still looks for /data/settings.js by
default, which doesn't exist after the volume overlays.

Solution: entrypoint wrapper copies /usr/src/bf-settings.js to
/data/settings.js on first boot when missing, then exec's npm start.
Subsequent boots keep the user-edited version in the volume.
2026-05-19 03:57:42 +02:00
Mitchell R
c8fa5d95a2
fix(deploy): bake configs into images — no host bind mounts
Coolify deployments don't always carry the full source tree on disk
at the bind-mount source path. Mounting a missing file lets Docker
auto-create a directory at the target, which then fails to mount over
the file the image expects.

Fix: bake config files into the images themselves:
- Dockerfile.server COPYs deploy/docker/sec-config.yaml → /app/server/.
  Env vars (BF_*) still override at runtime per env-overrides.ts.
- New Dockerfile.angie wraps nginx:alpine + baked betterframe.docker.conf.
- Dockerfile.nodered COPYs nodered-settings.js to /usr/src/bf-settings.js
  (outside the /data volume) and uses --settings to point at it.

Compose drops the three bind mounts; volumes are now strictly
runtime state (DB + secrets, Node-RED flows). Users who want a
different sec-config still get full control via env overrides or
Coolify's Storage UI.
2026-05-18 12:18:46 +02:00
Mitchell R
a7abef1bba
fix(deploy): move docker-compose.yml to repo root
Coolify passes --project-directory <repo-root> so relative paths in
compose resolved from there, not from the compose file's directory.
context: ../.. then climbed to / and lstat /deploy failed.

Moving compose to repo root makes every relative path
project-dir-relative regardless of who's invoking compose. Local
'docker compose up' from repo root and Coolify's
--project-directory + -f both resolve identically.

Coolify users: update the resource's compose path to 'docker-compose.yml'
(was 'deploy/docker/docker-compose.yml'). Existing named volumes carry
over since the named: directive keeps them.
2026-05-18 12:05:09 +02:00
Mitchell R
f3c5504b4f
feat(deploy): env-overridable volume names + host port for Coolify
BF_DATA_VOLUME_NAME, NODERED_DATA_VOLUME_NAME, BF_HOST_PORT keep the
compose public while letting per-deployment specifics (host paths,
multiple staging/prod instances on one host, alternate edge ports)
land in Coolify's env tab. Defaults preserve current behaviour.
2026-05-18 11:50:51 +02:00
Mitchell R
17f8c7ce02 feat(server): generic MQTT telemetry bridge (off by default) 2026-05-14 07:46:56 +02:00
Mitchell R
d1fd128ea0 feat(server): env-var overrides for sec-config keys + docker healthchecks 2026-05-14 07:33:10 +02:00
Mitchell R
122509de0d feat(nodered): auto-provision bf-server-config on boot
Server mints a dedicated admin API key on first boot (persisted plaintext
encrypted in setup_state.extras) and POSTs a bf-server-config node into
Node-RED's flow graph via /nrdp/flows. Idempotent — skips if any
bf-server-config already exists, so user-owned configs win.

New admin-http config 'selfUrl' (defaults to http://127.0.0.1:18080)
tells Node-RED how to reach the BF server. Docker compose sets it to
http://server:18080 so requests stay inside the compose network.
2026-05-13 03:09:25 +02:00
Mitchell R
44b0268def fix: nodered settings.js nodesDir → /usr/src/betterframe-nodes
Node-RED only scans userDir/node_modules by default. Setting
nodesDir explicitly tells it to also scan our baked-in path,
which survives the /data volume mount.
2026-05-13 02:00:40 +02:00
Mitchell R
896934ae84 feat: bake BF Node-RED nodes into nodered Docker image
- New deploy/docker/Dockerfile.nodered extends nodered/node-red,
  npm-installs the workspace nodered/ package into
  /usr/src/node-red/node_modules so bf-* nodes auto-load on boot.
- docker-compose nodered service switched from public image to
  this build context. Rebuilding (--build) picks up node changes.
2026-05-13 01:57:26 +02:00
Mitchell R
b83782b8e0 feat: Node-RED custom nodes + dashboard entity type
Node-RED nodes (nodered/):
- bf-config: shared server URL + admin API key
- bf-event-in: filter kiosk events by topic glob
- bf-layout-switch: POST display layout-switch
- bf-power: kiosk wake/standby
- bf-fan: kiosk fan control
- bf-cameras: query camera list
- Drag-droppable from Node-RED palette

Server:
- Admin Bearer API key auth on /admin/* (NodeRED can call admin API)
- GET /api/admin/cameras for bf-cameras node
- Dashboard entity type:
  - entities.type CHECK adds 'dashboard'
  - entities.dashboard_id column
  - shared/nodered-bridge.ts listDashboards() polls /nrdp/flows
  - Bundle resolves dashboard entity → web cell at /dash/<id>
  - POST /admin/entities/sync-dashboards mirrors Node-RED tabs
  - EntitiesPage shows Dashboards section + Sync button
  - EntityEditPage for dashboard: read-only + "Open in Node-RED"
  - No create/delete from BF UI — managed in Node-RED
- sec-config: noderedUrl on admin-http (was already on api-http)
2026-05-13 01:47:53 +02:00
Mitchell R
766db445c4 fix: Dockerfile npm run build + htmx for layout switch buttons
- Dockerfile.server: RUN npm run build during builder stage so the
  image ships pre-compiled lib/ + bsb-plugin.json. Runtime image also
  installs ffmpeg (for camera snapshot endpoint).
- DisplayEditPage Show buttons + Switch dropdown now use hx-post
  with hx-swap=none — no page reload, just fires the command.
2026-05-13 01:32:25 +02:00
Mitchell R
820e0a5945
fix(proxy): split Node-RED route surfaces
Route backend, kiosk ingest, kiosk dashboards, and public Node-RED HTTP-in separately. Keep Node-RED editor under admin auth and attach kiosk auth when kiosk loads protected dashboard URLs.
2026-05-11 10:44:45 +02:00
Mitchell R
02412169a0
fix(deploy): make Docker the service runtime
Remove host daemon deployment for server, proxy, and Node-RED so Node-RED is only reachable through the Compose proxy boundary.
2026-05-11 10:08:33 +02:00
Mitchell R
96d7cc45ba
fix(deploy): require proxied local services
Bind native backend services and Node-RED to loopback so Angie remains the public auth boundary. Keep Docker on an internal compose network and stop kiosk fallback to a layout when display default is none.
2026-05-11 09:51:00 +02:00
Mitchell R
b3c17a9d53
fix(deploy): gate proxied runtime routes 2026-05-11 08:57:55 +02:00
Mitchell R
cbb1683c5d feat: deployment artifacts + CEC relay + auth-check endpoint
Deployment (deploy/):
- systemd units for server (system) and kiosk (user session)
- Angie/nginx proxy config — routes admin, api, ws, node-red
- Dockerfile + docker-compose for containerized deployment
- deploy/README.md with install instructions

Auth:
- /api/admin/_check endpoint for proxy auth_request subrequest
- Returns 200 if admin session valid, 401/403 otherwise
- Sets X-BetterFrame-User header for upstream

CEC (Pi5 HDMI control):
- kiosk/src/cec.rs wraps cec-ctl subprocess
- Standby/wake/active-source commands
- WS message types "standby" / "wake" dispatched to CEC
- Admin UI: Wake/Standby buttons on kiosk edit page
- Server sendToKiosk via coordinator
2026-05-10 22:45:56 +02:00