Commit Graph

32 Commits

Author SHA1 Message Date
b6ab518e2a release: bump minor on the 87 modules converted to Wants=secubox-core (Phase 2)
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-19 09:08:22 +02:00
2ec7cef1b2 feat(profiles): Phase 2 — Requires=secubox-core → Wants= on all units (remove hard cascade)
secubox-core.service is a Type=oneshot (mkdir+chown) that RemainAfterExit=yes. A hard
Requires= on ~108 units cascade-stops them all if core is restarted/fails (e.g. a
secubox-core package upgrade) — a thundering-herd outage. After= keeps the ordering;
Wants= keeps the soft dependency without the cascade. Prereq for mass native apply
(Phase 3). Scaffolds (new-module.sh/new-package.sh) updated so future units use Wants=.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-19 09:06:54 +02:00
238637e09a release(webui): bump 127 arch:all packages for hybrid-dark reskin bake-in 2026-07-10 09:07:42 +02:00
3197f866e4 feat(webui): fleet reskin — apply hybrid-dark cyan overlay to all 116 crt-light panels
Add /shared/hybrid-dark.css: a shared overlay that remaps the design tokens
(consumed by crt-light.css, sidebar-light.css and every module's inline styles)
to the cyan hybrid-dark palette from /certs/ + /wireguard/. body.hybrid-dark
(specificity 0,1,1) beats :root and inline :root, so one token remap flips the
whole tree — no per-panel rewrite. Each panel gains the overlay <link> + the
hybrid-dark body class (2-line additive swap; crt-light.css kept as base).
See .claude/WEBUI-PANEL-GUIDELINES.md.

Panels with fully bespoke styles (certs/wireguard/users/nac already hybrid;
~14 non-crt-light custom panels) are untouched.
2026-07-10 08:40:10 +02:00
CyberMind
e4a9c8e452
fix(peertube): stop webui login loop — getToken() reads sbx_token (#810) (#811)
The PeerTube dashboard bounced to /login.html?redirect=/peertube/ and looped after
a successful login. getToken() read localStorage 'jwt_token' || 'token' — keys the
canonical login.html never writes. login.html (and every other module webui: waf,
soc, crowdsec, metrics, shared sidebar.js) uses 'sbx_token'. So PeerTube always sent
an empty Authorization → API 401 → api()'s 401 handler redirected to login → login
stored sbx_token → back to /peertube/ → getToken() read jwt_token (empty) → 401 → loop.

Pre-existing divergence (present in the May-28 backup); not caused by #798. Same class
as the cookies webui drift (#749). Fix: read sbx_token first, keep the legacy keys as
fallback. Applied live on the board to unblock.

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-07-04 18:15:25 +02:00
CyberMind
4a6b853785
fix(peertube): drain admin-ops results to a separate dir (fixes start-limit loop, #798) (#804)
* fix(peertube): drain admin-ops results to a separate dir (fixes start-limit loop, ref #798)

The root peertube-ops.path watches OPS_DIR with DirectoryNotEmpty=. process-ops
wrote each <id>.result.json back into OPS_DIR, so the directory was never empty
after draining a request → the .path re-triggered peertube-ops.service in a tight
loop until systemd killed it with start-limit-hit, after which the mechanism died
after the first op.

Write results to a dedicated /run/secubox/peertube/results/ instead; process-ops
rm's the request, leaving OPS_DIR empty so the watcher goes idle. The API's
_read_op_result now polls RESULTS_DIR. tmpfiles + postinst create the dir
(0750 secubox:secubox); peertubectl honors SECUBOX_PEERTUBE_RESULTS_DIR.

test_process_ops.sh asserts results land in results/ and OPS_DIR is empty after
draining (regression guard); test_ops_api monkeypatches both dirs.

Verified live on gk2: two consecutive pings drain cleanly, NRestarts=0, no
start-limit-hit, results root:secubox 0640 (secubox-readable).

* fix(peertube): upgrade CWD must be peertube-latest/scripts + surface the error (ref #798)

The webui upgrade button failed with a generic "upgrade script failed" and no detail.
Two bugs in cmd_upgrade:

1. Wrong CWD. PeerTube's v8 shim peertube-latest/scripts/upgrade.sh execs
   `../dist/scripts/upgrade.sh` relative to CWD, and that dist script runs
   `node -e "require('js-yaml')…"` whose resolution is also CWD-relative. Running from
   `cd /var/www/peertube` made `../dist` → /var/www/dist (missing) → "cannot open
   ../dist/scripts/upgrade.sh"; a neutral CWD instead fails "Cannot find module
   'js-yaml'". Fix: cd /var/www/peertube/peertube-latest/scripts (../dist resolves,
   and require() walks up to peertube-latest/node_modules).

2. Error was discarded to /dev/null, so the result only said "upgrade script failed".
   Now capture to /run/secubox/peertube/upgrade-<id>.log and fold the last lines into
   the error detail.

Verified live: with the corrected CWD, 8.2.0 → 8.2.2 upgraded cleanly (download + deps
+ migrations), service restarted, /api/v1/config 200, serverVersion 8.2.2.

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-07-04 18:15:21 +02:00
CyberMind
10e1bc8ff4
PeerTube WebUI: admin reset-password + version check/upgrade (#800)
Some checks are pending
License Headers / check (push) Waiting to run
* docs(spec): PeerTube WebUI admin ops — reset-password + version check/upgrade (ref #798)

* docs(plan): PeerTube WebUI admin ops implementation plan (ref #798)

* feat(peertube): API ops spool plumbing + require_admin (ref #798)

* feat(peertube): spool→root ops mechanism (process-ops + path/service) (ref #798)

* feat(peertube): reset admin password button (lockout-safe, spool→root) (ref #798)

* fix(peertube): admin-secret chown to real secubox user + WebUI error field (ref #798)

* feat(peertube): version check (installed vs latest GitHub release) (ref #798)

* feat(peertube): one-click upgrade with pre-backup + rollback (spool→root) (ref #798)

* fix(peertube): require_admin store lookup + op-name align + result group-readable (whole-branch review, ref #798)

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-07-04 10:12:08 +02:00
CyberMind
82b0522c5b
Aggregator résilience: sweep async (243 handlers) + threadpool 80 (#738) (#739)
* perf(aggregator): async-sweep — 243 blocking route handlers async def→def (#738)

Mounted in the aggregator's single event loop, an 'async def' route handler
that runs blocking code (subprocess/journalctl/openssl/argon2) freezes the
WHOLE loop -> aggregator.sock Connection refused -> 502 board-wide.

Deterministic AST codemod (scripts/async-sweep.py) converts route handlers
that (a) are decorated with an HTTP verb, (b) contain a known blocking call,
(c) have NO await/async-with/async-for/yield, (d) are never used as a
coroutine elsewhere -> plain 'def'. Starlette then runs them in the AnyIO
threadpool, so the blocking call no longer stalls the gateway. await/stream/
websocket handlers are left untouched. Every file py_compile-checked.

243 handlers across 56 modules (system 17, qos 13, netdiag/hexo 12, hub 11...).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* perf(aggregator): raise AnyIO threadpool to 80 tokens (#738)

The async-sweep moves ~243 blocking handlers to the threadpool. With ~110
modules in one process, the default 40-token pool can queue head-of-line under
concurrent blocking load. Raise to 80 on startup (best-effort, never breaks
boot).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* perf(hub): double-buffer status cache + emojized health page (#738)

Navbar status (menu + health-batch) is now a strict double-buffer cache:
- request handlers NEVER compute on the request path — they return the current
  snapshot instantly (or a 'warming' placeholder), so the sidebar's polling can
  no longer serialize behind a ~3s systemctl walk and starve the loop;
- the background refresher is kicked from the request path (_ensure_bg) because
  mounted sub-apps receive neither startup nor @app.middleware events under the
  aggregator — the previous lazy-start middleware never fired there;
- snapshots are built complete then swapped atomically, so the dashboard never
  shows partial/bad counts.

Served by the dedicated secubox-hub process (:8001, isolated loop) the navbar
stays <50ms and holds 200 under 25+ concurrent polls where the aggregator-
mounted copy wedged (000). health.js: 🟢🟡🔴 emoji status indicators.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* style(hub): render health status emoji cleanly (neutralize .led dot) (#738)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* perf(sidebar): kill per-module health storm, use batch endpoint (#738)

The navbar refreshed LEDs by firing ONE /api/v1/<module>/health request per
module — ~119 requests every 30s, in batches of 8 — straight at the aggregator's
single shared event loop. Combined with the in-process module mount this is a
prime driver of the recurring board-wide 502 wedge (user-identified).

checkAllHealth + refreshStaleHealth now call /api/v1/hub/public/health-batch
ONCE (served by the dedicated, double-buffered hub process) and populate every
module's LED from that single response. 119 reqs/cycle -> 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:06:15 +02:00
c01f10c474 docs(wiki): refonte 126 modules — snapshots WebUI déterministes + READMEs 4 langues (ref #742)
Capture des 126 dashboards authentifiés (JWT minté serveur, injection localStorage)
avec attente de COMPLÉTION d'affichage déterministe (sentinelles de chargement
purgées + réseau calmé, plafond --delay) au lieu d'un sleep fixe. 126/126 OK.

- capture-screenshots.py: _wait_content_ready déterministe, mode --token (bypass
  login), goto domcontentloaded (plus de stall networkidle sur dashboards live)
- generate-docs.py: 23 modules jusqu'ici non documentés ajoutés (descriptions
  réelles depuis debian/control, EN/FR/DE/ZH), licence MIT→LicenseRef-CMSD-1.0,
  images wiki en URL raw.githubusercontent absolue (relatif = 404 sur GitHub wiki)
- 126 snapshots + thumbnails régénérés
- 126 READMEs paquet succincts + pages wiki MODULES/CATEGORIES ×4 langues

Gap modules documentés vs découverts: 23 → 0.
2026-06-26 10:14:14 +02:00
6b7d7f8607 fix(#623): shared /run|/var/lib|/var/cache|/etc/secubox parents stay 1777/0755 in all postinsts
Systemic clobber: the scaffold boilerplate (install -d -m 750 /var/lib/secubox,
/run/secubox) put restrictive modes on SHARED parents in ~56 module postinsts,
reverting them to 0750 on every install/upgrade and breaking traversal for
non-secubox daemons (kbin/toolbox 500). Empirically confirmed install -d -m only
modes the final component, so /parent/leaf forms are harmless — only bare-parent
targets were rewritten. Multi-arg lines (incl. ones making /var/lib world-writable
1777) split per-parent: /run/secubox=1777 root:root, /var/lib|cache|etc=0755
secubox:secubox; module-private leaves keep 0750. Scaffold + PATTERNS.md fixed so
new packages don't reintroduce it.
2026-06-18 10:32:58 +02:00
c2990f4d98 feat(peertube,avatar): privilege-separated cookie install via root path-unit (closes #407)
Replaces the sudo-from-dashboard approach (which required dropping
NoNewPrivileges) with a CSPN-clean design: unprivileged dashboards spool the
cookies, a root systemd .path watches + installs them.

- secubox-peertube: ship peertube-cookie-install.{path,service} (root oneshot
  runs `peertubectl set-youtube-cookies` + rm's the spool); postinst enables
  the .path; /import/cookies now just writes the spool (no sudo) → "queued";
  restore NoNewPrivileges=true; drop the sudoers file + sudo dep.
- secubox-avatar: _apply_youtube writes the spool (no sudo) → "queued"; keeps
  NoNewPrivileges. poke success keys on cookies; po_token stays experimental.
2026-05-28 12:36:56 +02:00
2ae8879d5b fix(peertube): ship dashboard-API route to secubox-routes.d (the active include) (ref #388)
webui.conf includes /etc/nginx/secubox-routes.d/*.conf, NOT secubox.d/. The
rework shipped only to secubox.d/, so on upgrade dpkg removed the old
secubox-routes.d/peertube.conf → /api/v1/peertube/ 404/unrouted → dashboard
tile red + cookie-relay POST failed. Ship to both dirs (mirror grafana).
2026-05-28 11:22:27 +02:00
1861980329 fix(peertube): don't reset /etc/secubox perms in postinst (broke TOTP login)
The postinst's `install -d -o root -g root -m 755 /etc/secubox` reset the dir
secubox-core owns as secubox:secubox 0750, so the users-engine could no longer
create its atomic-save temp file → TOTP verification crashed with
PermissionError → all logins rejected. Guard: only create /etc/secubox as a
fallback if missing, never reset an existing dir. (ref #388)
2026-05-28 11:16:31 +02:00
3fdb12b9b1 feat(peertube): cookie-intake endpoint for the WebExtension relay (ref #388, #401)
Lets the SecuBox Companion extension install YouTube cookies with one click.

- api/main.py: POST /import/cookies (require_jwt) — accepts the Netscape
  cookies body, spools to /run/secubox/peertube-yt-cookies.txt, then escalates
  via a single narrowly-scoped sudoers rule to `peertubectl set-youtube-cookies`
  (installs into the LXC, enables import cookies, restarts PeerTube).
- debian/secubox-peertube.sudoers: secubox → NOPASSWD exactly
  `peertubectl set-youtube-cookies /run/secubox/peertube-yt-cookies.txt`.
- service unit: drop NoNewPrivileges (would block sudo); documented why.
- rules: install sudoers 0440; control: Depends sudo.
Deployed + verified on gk2 (route 401s unauth, sudoers scoped, secubox can
spool, NoNewPrivileges=no).
2026-05-28 11:09:08 +02:00
602298b664 feat(peertube): peertubectl set-youtube-cookies for yt-dlp YouTube import (ref #388)
YouTube hard-blocks server IPs ("Sign in to confirm you're not a bot") — no
yt-dlp version or player_client bypass works (tested); cookies from a logged-in
browser are the only reliable fix. New verb installs a Netscape cookies.txt into
the LXC at storage/tmp-persistent/youtube-cookies.txt (where PeerTube's
wrapWithCookiesOptions reads it), enables import.videos.http.cookies.enabled,
and restarts. Operator: export cookies.txt → scp to board →
`peertubectl set-youtube-cookies cookies.txt`.
2026-05-28 10:17:04 +02:00
83bd6cda82 fix(peertube): derive dashboard running-state from HTTP reachability (ref #388)
The dashboard runs as the unprivileged 'secubox' user, which can't read the
root-owned LXC via lxc-info (reports 'absent'), making the webui wrongly show
the Install banner for a running instance. Trust http_reachable as the primary
running signal; fall back to lxc_state only when unreachable.
2026-05-28 09:11:00 +02:00
5e52598cf6 feat(peertube): native-LXC deployment + dashboard correction + URL import (ref #388, supersedes #390)
Aligns the package with what's actually deployed on gk2 (validated live at
https://peertube.gk2.secubox.in/, upload confirmed) and adds yt-dlp URL import.

- lib/peertube/install-lxc.sh (NEW): idempotent native PeerTube install in a
  dedicated Debian LXC (10.100.0.120 on br-lxc), mirroring grafana/yacy. Bakes
  in every fix from the live bring-up: Node 22 via signed NodeSource repo (8.x
  needs >=22, no curl|bash); pnpm with MSGPACKR_NATIVE_ACCELERATION_DISABLED=1
  (arm64); debian.common.conf template (postgres-15 needs it); bind mounts
  /data/peertube/{storage,config,postgres,redis} chown'd to LXC root UID;
  production.yaml patch (listen 0.0.0.0:9000, https/hostname/443, secret, db,
  admin email, import.videos.http.enabled=true); captures first-boot root
  password to /etc/secubox/secrets/peertube-admin.
- sbin/peertubectl (NEW): install/status/start/stop/restart/logs/reload.
- conf/peertube.nginx.conf (folds #390, port corrected to LXC :9000 not the
  stale 127.0.0.1:9001 Docker-on-host plan): public vhost :9080 -> 10.100.0.120
  :9000, 8G uploads, 7d streaming timeouts, WS, ACME; WAF-bypass (gitea pattern).
- api/main.py: talk to the native instance over HTTP at <lxc_ip>:<http_port>
  with Host: <public_hostname> header (PeerTube 403s on raw-IP Host) instead of
  podman/docker exec; status reports real LXC state + reachability; /container/*
  drive the LXC via peertubectl; NEW POST /import + GET /imports.
- www/peertube/index.html: new "Import" tab (URL + channel + privacy + recent
  imports); status/labels/links corrected for native-LXC.
- debian/control + service: reframe Docker/Podman -> native-LXC; drop
  Wants=podman/docker. conf/peertube.toml.example (NEW). README + changelog 1.1.0.
2026-05-28 08:17:59 +02:00
754485140b feat(peertube): rework to align with SecuBox conventions, make installable (closes #388)
secubox-peertube 1.0.0 had been removed from gk2 and could not be
cleanly reinstalled: hardcoded /srv/peertube path (predates #319),
service unit blocked from starting by ConditionPathExists, broken
Requires=secubox-runtime.service, root user with ExecStartPost
chmod hacks, postinst didn't tolerate masked units, no /data
migration block.

Reworked to current SecuBox patterns (mirror gitea/wazuh):

  api/main.py — default data_path /srv/peertube → /data/peertube
  (5 hardcoded fallbacks updated in lockstep, Pydantic model
  default updated, top-level DEFAULT_CONFIG updated).

  debian/secubox-peertube.service — drop ConditionPathExists gate
  so the API daemon is always reachable to serve the dashboard
  (the heavy PeerTube container is still operator-deployed on
  demand via the dashboard); User=root → User=secubox + Group=
  secubox; replace ExecStartPost chmod/chown hacks with
  RuntimeDirectory=secubox + RuntimeDirectoryPreserve=yes +
  RuntimeDirectoryMode=0775 + UMask=0000 (mass-redeploy safety);
  drop the broken Requires=secubox-runtime.service (no such
  service); reorder Wants= to podman.service docker.service;
  add ReadWritePaths covering /run/secubox /var/lib/secubox
  /etc/secubox /var/log/secubox /data/peertube.

  debian/postinst — add #319 /data migration block (mirror gitea
  pattern from aba60ae3); wrap systemctl enable in is-enabled
  != masked check (per wazuh fix 63284497) so a deliberately
  masked unit no longer fails the postinst; drop the hardcoded
  /srv/peertube/{storage,config,data} mkdir (the API creates
  these on first container/install so PeerTube's UID/GID can own
  them); nginx reload guarded by `nginx -t`.

  debian/control — Description rewritten with cross-references
  to the other federated/streaming/media SecuBox packages
  (matrix, jitsi, jellyfin, gotosocial, simplex); Recommends
  reordered to podman first (smaller, distro-native), docker.io
  second; explicit note that the API daemon is lightweight and
  always reachable while the container is operator-deployed.

Verified on gk2 (root@192.168.1.200):
  - apt install podman secubox-peertube_1.0.1-1~bookworm1_all.deb
    succeeded.
  - systemctl is-active secubox-peertube → active
  - /run/secubox/peertube.sock created srw-rw-rw- secubox:secubox
    (no ExecStartPost chmod hacks needed)
  - curl --unix-socket /run/secubox/peertube.sock http://x/health
    → {"status":"ok","module":"deb"}
  - podman 4.3.1 installed and ready for container/install when
    operator triggers it via dashboard
  - /data/peertube preserved (existing symlink /srv/peertube →
    /data/peertube intact)

Not done in this rework (out of scope per issue):
  - Actually installing the PeerTube container on gk2 (1G RAM
    free, operator's call).
  - peertubectl LXC controller — package is Docker/Podman-based
    by design.
  - Frontend rewrite (1154-LOC dashboard stays as-is).
  - Adding to secubox-full/-lite metapackages.
2026-05-27 11:34:12 +02:00
CyberMind
5e93c73600
feat(navbar): consolidate to 6 charter categories + fix dropped menu entries (closes #306) (#307)
The hub's `_compute_menu_sync()` drops menu entries lacking an `id`
field. 6+ packages (lyrion, yacy, zigbee, rustdesk, grafana, authelia)
shipped a different schema (`title/url/section/module`) so they NEVER
appeared in the navbar. Plus the existing CATEGORY_META declared 12
sections (dashboard/security/network/system/core/users/services/
privacy/monitoring/publishing/apps/admin), not the 6 SecuBox charter
modules.

Changes:
* All 121 packages/secubox-*/menu.d/*.json normalised to the canonical
  schema (id, name, path, category, icon, order, description). Legacy
  schema aliases (title/url/module/section) preserved as fallbacks then
  dropped from the file.
* Each menu entry's category remapped to one of the 6 charter modules:
  AUTH (auth/users/identity/zkp/nac/openclaw),
  WALL (crowdsec/waf/mitmproxy/hardening/threat-* /cve-triage/...),
  BOOT (kernel-build/eye-remote/master-link/droplet/cloner/backup/...),
  MIND (ai-gateway/mcp-server/grafana/ndpid/netifyd/glances/...),
  ROOT (system/hub/portal/console/admin/vault/vm/rtty/...),
  MESH (wireguard/dns/tor/matrix/gitea/nextcloud/mail/lyrion/yacy/
        zigbee/dns-provider/rustdesk/... — all network + comms apps).
* secubox-hub v1.4.0 — CATEGORY_META rewritten with the 6 charter
  modules carrying their official color from DESIGN-CHARTER.md and
  the complementary-pair order. DEFAULT_MENU fallback remapped too.
* secubox-zigbee v2.5.3 — www/zigbee/index.html rewritten with the
  canonical SecuBox scaffold (body display:flex, sidebar 220px fixed,
  .main reserving 48px for the global-menu-bar). MESH palette.

Browser side: operators need to clear localStorage sbx_menu_cache (or
hard-refresh after the 1h TTL) to see the new sections after deploy.

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-05-21 10:03:05 +02:00
CyberMind
99fc829b45
fix(web): rewrite stale /portal/login.html -> /login.html (closes #222) (#223)
PR #169 moved login.html out of secubox-hub to /usr/share/secubox/www/
under secubox-portal's ownership, but 67 source files across the
package set still redirected to /portal/login.html which no longer
exists on disk. nginx fell back to /index.html (hub root) on every
hit, whose checkAuth() bounced back to /portal/login.html, producing
an infinite "Redirecting to login..." loop with no way for any user
to authenticate.

sed -i 's|/portal/login\.html|/login.html|g' across all packages/*/www
sources (82 occurrences). The two prior partial fixes that triggered
this investigation (bcc6a781, 464e3379) only covered a subset and
missed the kiosk root checkAuth in secubox-hub/www/index.html plus
65 module index.html files.

Verified: grep -rl '/portal/login\.html' packages/ | grep -v /debian/
returns empty.

Discovered while testing the firstboot v2-schema+argon2 chain end-to-end
in a VBox amd64 boot of CI run 26082003883 (the #218 image build fix)
— firstboot now works, users.json gets a valid argon2 hash for
admin/secubox, the portal API runs, but the login UI is unreachable
because of this dangling URL.

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-05-19 11:44:43 +02:00
bd7dda0c6f feat(secubox): complete meta-script generator Tasks 14-17
Task 14: Arch Profiles
- Add profiles/arch/arm64.yaml and profiles/arch/amd64.yaml
- Add ResolveWithArch() to merger for base → arch → tier chain
- Add tests for arch profile resolution

Task 15: Package secubox.yaml for All Packages
- Add scripts/generate-secubox-yaml.py generator script
- Generate 131 debian/secubox.yaml files with:
  - Category detection (security, network, system, etc.)
  - Tier assignment (all, lite, standard, pro)
  - API socket and UI path detection

Task 16: APT Repository Setup
- Add apt/conf/ reprepro configuration (multi-arch arm64/amd64)
- Add apt/hooks/lintian-check pre-publish validation
- Add scripts/apt-publish.sh and scripts/apt-sync.sh
- Add apt/README.md documentation

Task 17: CI Integration
- Add .github/workflows/build-secubox-cli.yml
- Build for linux-amd64 and linux-arm64
- Version injection via ldflags
- GitHub releases on tag push

Code Quality Fixes (Tasks 10-13):
- Add atomic writes for OTA boot control files (0600 perms)
- Fix NVME device extraction (nvme0n1p2 → nvme0n1)
- Add scanner.Err() checks in hardware detection
- Fix URL injection validation in fetch command
- Add proper cleanup on checksum failures

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-11 05:32:29 +02:00
68e7763fc3 docs: Add Eye Remote Multigadget skill and wiki
- Add /multigadget skill covering autorun, storage, round UI, tooling
- Add Eye-Remote-Multigadget.md unified wiki hub
- Add Build-System.md to wiki with build documentation
- Add AI-BUILD-PROMPT.md for GPT/Gemini assistance
- Update sidebar and home page with new links
- Update WIP.md with #70 and #71 done

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-10 09:12:42 +02:00
e2989322f4 feat(api): Add /health endpoint to 53 modules
Auto-generated health check endpoints for sidebar status:
- Returns {status: "ok", module: "name"}
- Public endpoint (no auth required)
- Used by sidebar.js for LED status display

Added via scripts/add-health-endpoints.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-09 10:40:05 +02:00
abc1f82d2d fix(services): Use portable uvicorn invocation in systemd units
Changed /usr/local/bin/uvicorn to /usr/bin/python3 -m uvicorn
for compatibility across different Python installation methods.

Also fixed JWT auth import in eye-remote boot_media router.

Affected: 31 service files across 30 packages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 17:02:08 +02:00
65a30011f4 fix(services): Add LogsDirectory and fix menu icons
- Add LogsDirectory=secubox to systemd services for proper logging
- Fix systemd service security sandboxing (remove PrivateTmp issues)
- Replace text icons with emojis in menu.d JSON files
- Fixes navbar display issues (overlapping text from icon names)

Services updated:
- secubox-system, secubox-hub, secubox-portal, secubox-watchdog
- ~70 other services with LogsDirectory directive

Menu icons fixed:
- ipblock, interceptor, cookies, dns-provider, homeassistant, etc.
- Changed from text strings to emojis for proper sidebar display

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-20 08:59:19 +02:00
de77a1aa4e feat(build): Add modular build system and fix package dependencies
Build System:
- Add image/lib/common.sh with shared build functions
- Add profiles for vm-x64, x64-live, rpi400, espressobin-v7
- Add BUILD-SYSTEM.md documentation
- Add splash screens (boot.png, tui-splash.sh, kiosk-loading.sh)
- Add Plymouth theme for boot splash

Package Dependencies:
- Fix python3-uvicorn -> python3-uvicorn | python3-pip
- Fix python3-fastapi -> python3-fastapi | python3-pip
- Fix python3-httpx -> python3-httpx | python3-pip
- Allows packages to install when pip-provided deps are used

Documentation:
- Add Build-System.md wiki page
- Update _Sidebar.md with build system links
- Add VM-Testing.md improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-10 17:31:24 +02:00
aa41893d4b feat: Complete Phase 8, 9, 10 - all modules done
Phase 8 (Applications): 21 modules complete
- jitsi, gotosocial, peertube, hexo, webradio, voip, simplex, torrent, newsbin

Phase 9 (System Tools): 22 modules complete
- Added READMEs for vault, cloner, vm, rtty, reporter, turn, smtp-relay

Phase 10 (Security Extensions): 10 modules complete
- Created secubox-netifyd package (DPI daemon)
- Added README for secubox-wazuh

Infrastructure fixes:
- Fixed uvicorn path in 29 service files (/usr/bin → /usr/local/bin)
- Fixed smtp-relay debian/control (Section: mail, added msmtp alternative)
- Added MODULE-COMPLIANCE.md with formal design rules
- Updated CLAUDE.md to reference compliance requirements

Total: 125 packages, all phases complete

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-08 14:46:58 +02:00
7ead1ff77f fix: Slipstream path + conditional service startup
1. Fix slipstream path: Look for packages in output/ not just output/debs/
   - build-image.sh and build-live-usb.sh now check both locations
   - 73 packages now properly detected and installed

2. Add ConditionPathExists to 22 optional services:
   - Services only start if /etc/secubox/<module>/enabled exists
   - Prevents boot failures when backend apps aren't installed
   - Affected: ollama, jellyfin, zigbee, lyrion, localai, hexo,
     peertube, newsbin, webradio, gotosocial, torrent, domoticz,
     simplex, photoprism, homeassistant, matrix, jitsi, voip,
     magicmirror, mmpm, jabber, redroid

3. Add explicit parted/fdisk install in live USB build
   - Ensures disk tools available for secubox-install

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-06 19:50:11 +02:00
ce28d53918 feat(phase8): Complete all 21 Application modules
New modules created (13):
- secubox-hexo: Static blog generator (Hexo)
- secubox-webradio: Internet radio streaming
- secubox-torrent: BitTorrent client (Transmission)
- secubox-newsbin: Usenet downloader (SABnzbd)
- secubox-domoticz: Home automation
- secubox-gotosocial: Fediverse/ActivityPub server
- secubox-simplex: SimpleX secure messaging
- secubox-photoprism: Photo management
- secubox-homeassistant: IoT/Home automation hub
- secubox-matrix: Matrix chat server (Synapse)
- secubox-jitsi: Video conferencing
- secubox-peertube: Video platform
- secubox-voip: VoIP/PBX (Asterisk/FreePBX)

All modules include:
- FastAPI backend with JWT authentication
- P31 Phosphor light theme frontend
- Docker/Podman container management
- Debian packaging (control, rules, postinst, prerm)
- nginx reverse proxy config
- systemd service unit
- Menu integration

Total packages: 85 (was 72)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-04 10:04:25 +02:00
2d2870d8a9 fix(systemd): Add RuntimeDirectory for /run/secubox socket support
- Add RuntimeDirectory=secubox to all services using ProtectSystem
- Change ProtectSystem=strict to ProtectSystem=full for compatibility
- Add systemd overrides in build script for cached packages
- Create tmpfiles.d entry for /run/secubox

This fixes the namespace issue where services couldn't create sockets
in /run/secubox due to ProtectSystem=strict mount namespacing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-03 08:54:19 +02:00
14a50e42e7 fix(peertube): Correct JS syntax error (async def -> async function)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 10:22:40 +01:00
491b2aaea1 feat(phase8): Add PeerTube federated video platform
- LXC-based PeerTube container with PostgreSQL, Redis, Node.js, ffmpeg
- FastAPI backend for install, user, video management
- Web UI with stats grid, videos/users/logs tabs
- Systemd service on Unix socket

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 10:21:03 +01:00