Commit Graph

43 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
b50387a06b fix(auth): record client IP + user-agent on the MFA login paths
/login/mfa and /totp/confirm both hardcoded "ip": "" and omitted user_agent
entirely, while only the password path captured them. admin is forced-TOTP,
so EVERY real admin login took the MFA path — every session row landed
unauditable (who logged in, from where, with what), and the users webui
sessions tab rendered blanks for data it was already asking for.

Factor the extraction into _client_meta(request) (X-Forwarded-For first: nginx
and HAProxy front every login, so request.client.host is only ever the proxy)
and use it on all three paths.

Verified by driving the real /login/mfa handler in-process with
SECUBOX_AUTH_SESSIONS pointed at a temp file: the session row now records
ip=192.168.1.77 (the first XFF hop, not the proxy) and the full user-agent.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-17 10:35:07 +02:00
6b9860a91b feat(auth): webui-toggleable admin-TOTP requirement (default off) + per-user 2FA reset
secubox-auth 1.0.4:
- GET/POST /api/v1/auth/settings (admin-gated) for require_admin_totp,
  persisted to /etc/secubox/auth-runtime.json
- login enforcement via _get_require_admin_totp() (runtime > [auth] config >
  default False); fail-open so a config error never locks admins out
- tests realigned to reachability-first contract + /settings roundtrip;
  fixture isolates config + runtime paths

secubox-users 1.4.3:
- Admin 2FA ON/OFF toolbar toggle wired to auth /settings
- per-user Reset 2FA button (POST /user/<u>/totp/disable), enrolled-only

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-11 06:52:56 +02:00
9b5d0b1719 fix(auth): login failed on undefined _SESSIONS_FILE (dunder vs single-underscore mismatch)
Sessions file defined as __SESSIONS_FILE but referenced as _SESSIONS_FILE in
every handler -> NameError on session save/load, so valid logins failed and
/status 500d. Normalised all refs to _SESSIONS_FILE. Verified: login endpoint
returns proper JSON (401 on bad creds), sessions persist.
2026-07-11 06:05:46 +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
2fb445b577
feat(auth): configurable forced admin TOTP enrollment (ref #778) (#781)
secubox-auth forced every role=admin account without TOTP into enrollment on
login, returning no session — blocking operators who want password-only admin
login (e.g. a freshly reset admin on a satellite node).

Gate the forced enrollment on [auth] require_admin_totp (default true, secure/
CSPN). Set false in /etc/secubox/secubox.conf for password-only admin login.
Fail-secure: any get_config error keeps enrollment mandatory.

- packages/secubox-auth/api/main.py: config-gated enrollment branch
- secubox.conf.example: document require_admin_totp under [auth]
- tests: session-when-disabled + fail-secure-on-config-error

Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
2026-07-03 06:51:43 +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
260f0f5d6d fix(auth): ntp_health falls back to timedatectl when chronyc absent (ref #498)
Admin login UI was permanently flagging "Clock not synced" with the
warning "TOTP window widened to ±60s" even when the system clock was
correctly synced. Cause : ntp_health.probe() only knew how to read
chrony, but SecuBox boxes ship systemd-timesyncd by default ; chrony
is the operator-opt-in alternative. On a stock install the probe
caught FileNotFoundError, returned `synced: False`, and the
recommended_totp_window() widened to ±60s on EVERY login.

Added a chrony → timedatectl fallback chain :

  1. Try `chronyc -n tracking` (chrony users).
  2. Fall through to `timedatectl show` reading NTP +
     NTPSynchronized properties (timesyncd users).
  3. Only return the synthetic error if BOTH commands are missing.

The response now carries an extra `source` field
("chrony" / "timedatectl") so the operator can see which backend
answered the probe.
2026-06-08 09:49:51 +02:00
1e988af546 feat(core,auth): SSO-lite session cookie accepted by require_jwt + set on login (ref #400)
Fixes "re-authentication everywhere despite being logged into the webui".

- secubox-core auth.py: require_jwt now accepts the parent-domain session
  cookie (secubox_session) as well as the Bearer token (additive — existing
  Bearer clients unchanged). Exposes set_session_cookie() publicly.
- secubox-auth main.py: emit the session cookie on every login-success path
  (direct, post-MFA, post-TOTP-enrollment) so one SecuBox login (incl. TOTP)
  drops a cookie that authenticates all module APIs without re-prompting.

Cookie is HttpOnly + Secure + SameSite=Lax (CSRF-mitigated). Set
api.sso_cookie_domain=".gk2.secubox.in" for cross-subdomain SSO.
Authelia vhost cutover (lyrion/zigbee) is a separate later step.
2026-05-28 11:31:38 +02:00
24000d67ea fix(services): add RuntimeDirectoryPreserve=yes to 96 secubox-* units
Hub + portal stayed `inactive (dead)` on real-hardware boot. The
journal error was `Failed to set up mount namespacing: /run/systemd/
unit-root/run/secubox: No such file or directory` at the NAMESPACE
step. Root cause: 96 services declare `RuntimeDirectory=secubox`
without the matching `RuntimeDirectoryPreserve=yes`. When any of them
stops (including any of the LXC-backed services that fail their
health probe and Restart=on-failure for a few cycles), systemd
removes /run/secubox on the way out. The next service with the same
RuntimeDirectory= that tries to namespace its inputs hits the gap
and falls into 226/NAMESPACE failure — Restart hammers a few times,
then the unit goes failed-permanent.

Earlier fmrelay + sentinelle units got the fix individually
(v2.12.0/v2.12.3 era). Now applied to all 96 remaining units in a
single sweep via:

  sed -i '/^RuntimeDirectory=secubox/a RuntimeDirectoryPreserve=yes' "$f"

No version bumps in changelog — `dpkg -i --force-depends` in the
live-USB slipstream picks up the new .deb regardless of version
number.
2026-05-26 09:50:22 +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
d0a63d49b5 fix(auth+users): /auth/status → /preflight (avoid route collision); engine TOTP window parameter; postinst chmod for writes (ref #120)
- Rename GET /auth/status → /auth/preflight (public) to stop shadowing the
  JWT-protected legacy /auth/status (dashboard voucher/session counts)
- Engine.verify_totp_for_user gains window parameter; _verify_totp_ntp_aware
  now delegates to the engine (atomic write via _save + audit hook)
- postinst: /etc/secubox 0750→0770, users.json 640→660 (group-write for atomic tempfile+rename)
- Add replay-refusal assertion to test_totp_widened_window_accepts_drifted_code
- Update login.html: loadStatus→loadPreflight, /api/v1/auth/status→/preflight

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:55:21 +02:00
ec14cb9dce feat(auth+hub): rename /auth/health to /auth/status; wire QR PNG + banner in login UI (ref #120)
- secubox-auth: new endpoint moved to /auth/status to avoid clashing with
  the existing /auth/health liveness check used by the sidebar.
  Distinct semantics: /health = "is the service up?",
  /status = "is auth healthy? (NTP, identity store source)".
- login.html: renders the server-side QR PNG (data: URI) so the user
  scans instead of copy-pasting. Manual entry stays available under a
  collapsible details block.
- login.html: fetches /auth/status on load and surfaces a red banner when
  NTP is desynced (with the widened TOTP window) or identity-store is in
  fallback mode.
- Live-verified on gk2: /auth/status returns the correct shape
  (chronyc absent on this board -> window=2 unknown branch, as expected).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:38:50 +02:00
d72269bc63 feat(auth): offline-mode hardening — server-side QR + NTP-aware TOTP window + /auth/health (ref #120)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 10:35:03 +02:00
10d3272ddd fix(auth+users): production-discovered bugs from live deploy on gk2 (ref #120)
usersctl: parents[3] indexing crashed when run from /usr/sbin/usersctl
(production has only 2 parents). Wrapped path resolution in try/except
so the script still works in-tree AND when installed.

main.py: nginx strips /api/v1/auth/ prefix before forwarding to the auth
socket, so the canonical external URL /api/v1/auth/login was being
routed to FastAPI's /login — but _login_router was mounted under /auth,
producing 404. Now mounted under BOTH '' (canonical) and /auth (legacy
doubled-URL compat). Tests still pass under the /auth prefix.

Live verified on https://admin.gk2.secubox.in:
- empty password -> setup_token (200)
- wrong password -> 401 "Aucun mot de passe local"
- unknown user -> 401 "Identifiants incorrects" (same body, no enum)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 10:14:32 +02:00
5c1d1d852d feat(users): debian deps + postinst migrates + seeds admin + hostname (ref #120) 2026-05-13 09:58:19 +02:00
4b4dfc9b5f fix(auth): consolidate sessions/audit file constants, harden _DATA_DIR.mkdir, fix pytest.ini footgun (ref #120)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:25:08 +02:00
a8abe9737b fix(auth): startup() no longer clobbers session callback; document per-dir test invocation (ref #120)
- Remove set_session_callback(_handle_session_event) from startup() — it was
  overwriting the Task 13 _on_session_event registration (which uses jwt.jti)
  with the legacy handler (which used secrets.token_hex(8)), breaking jti-keyed
  session lookup in _session_validator.
- Fix comment on module-load set_session_callback registration (line 167).
- Add pytest.ini at worktree root: documents the api/ vs api/ namespace collision
  that prevents combined cross-dir collection; enforces per-directory test runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:18:47 +02:00
92e22cd48d feat(auth): branching /auth/login + MFA + TOTP enrol + set-password (ref #120)
- Add PendingStore (JSON+TTL) for in-progress TOTP enrollment secrets
- Inject _users_api package loader (importlib) to side-step api/ name collision
- Register _session_validator, _on_session_event, _revoke_sessions callbacks
- POST /auth/login now branches: setup / mfa-challenge / totp-enroll / access
- POST /auth/login/mfa: verifies TOTP code or backup code, issues full JWT
- POST /auth/totp/enroll: generates secret, stores in PendingStore, returns URI
- POST /auth/totp/confirm: verifies code, calls engine.enroll_totp, returns JWT
- POST /auth/set-password: handles set-password scope and full-JWT change
- Mount _login_router before auth_router so /auth/login override wins
- Fix conftest sys.path order so secubox-auth/api takes priority for auth tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 09:08:56 +02:00
bedc6fda45 fix(tests): drop tests/__init__.py to allow cross-dir pytest collection; exist_ok in auth_data_dir (ref #120) 2026-05-13 08:21:09 +02:00
5fad5600d4 test: scaffold test dirs + conftest for auth rework (ref #120) 2026-05-13 08:16:55 +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
fb5c33eadc feat(auth): Add session event logging for login attempts
- Added session callback mechanism in secubox_core.auth
- Login events (success/failure) now emit to registered callback
- secubox-auth module records sessions in JSON file
- Fixed login.html endpoint URLs and JSON parsing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-09 06:17:49 +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
34b51bbf8e feat: Implement 6-Module Design System across all UI components
Complete UI design compliance update based on SecuBox Charte Graphique:

Design System:
- Add design-tokens.css with 6-module color system (BOOT/AUTH/ROOT/MIND/MESH/WALL)
- Update crt-light.css, crt-system.css for light/dark theme tokens
- Update sidebar.css, sidebar-light.css with module accent colors
- Refactor crt-components.js web components to use CSS variables

Module CSS Updates (35 files):
- All module CSS files now import design-tokens.css
- Replace hardcoded P31 Phosphor colors with CSS variables
- Add shared symlinks from each package to hub shared assets

UI Components:
- Redesign login.html with 6-module design system
- Update hub index.html dashboard with design tokens
- Remove legacy P31 color variables

System Branding:
- Add /etc/issue, /etc/issue.net, /etc/motd with 6-module branding
- Create Plymouth boot splash theme (secubox + secubox-text)
- Add generate-plymouth-assets.sh for theme image generation

Tools:
- Add update-css-design-tokens.py for batch CSS updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-08 18:29:36 +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
659cbb9303 feat(api): Add repo scan-local and IoT Guard Cast debug module
secubox-repo:
- Add /scan-local endpoint to import local .deb packages
- Add /scan-local/preview for dry-run package discovery
- Fix success detection for repoctl ANSI output
- Fix _update_stats to use dict format for distributions
- Make summary endpoint handle both list and dict formats

secubox-iot-guard:
- Add Google Cast/Chromecast debug module
- Add /cast/devices endpoint to find Cast devices via ARP/mDNS
- Add /cast/diagnose/{ip} for full diagnostic (CrowdSec, Suricata, DNS, nftables)
- Add /cast/whitelist/{ip} to apply whitelist rules
- Add /cast/capture/{ip} for packet capture debugging
- Add /cast/config/nftables and /cast/config/unbound for config generation
- Support Google OUI detection and Cast domain whitelisting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-28 05:57:38 +01:00
913f6c3bfb Fix body class and menu duplicates across all modules
- Changed body class from "crt-body crt-scanlines" to "crt-light" on all pages
- Fixed portal menu to point to /portal/ instead of /c3box/
- Removed c3box/portal duplicate in menu
- All pages now start with light theme, sidebar.js handles theme switching

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 07:11:59 +01:00
cbe7e4ac3a Add CRT light theme across all UI modules
- Create crt-light.css with lighter P31 phosphor colors
- Create sidebar-light.css matching light theme
- Update 49 HTML files to use light theme CSS
- Add apply-light-theme.py script for automated theme application

Theme changes:
- Background: #050803 (dark) -> #e8f5e9 (mint green)
- Cards: #080d05 -> #c8e6c9 (pale green)
- P31 peak: #33ff66 -> #00dd44 (darker for contrast)
- Font: JetBrains Mono / Courier Prime

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-25 08:55:45 +01:00
a4fa81d349 Add complete package READMEs and multilingual wiki documentation
- Generate README.md for all 45 secubox-* packages with screenshots
- Add multilingual wiki pages (EN, FR, DE, ZH) documenting 47 modules
- Add generate-docs.py tool for documentation generation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-24 15:31:34 +01:00
e3ef51ba8b Apply CRT P31 Phosphor theme to all 38 module UIs
Converted all SecuBox module frontends to CRT design system:
- P31 Phosphor color palette (green phosphor with amber accents)
- Bloom text-shadow effects on headers and active elements
- Monospace Courier Prime typography throughout
- Dark tube glass backgrounds (#050803, #080d05)
- CRT overlays (scanlines, vignette via body classes)

Updated components across all modules:
- Buttons: CRT border glow on hover
- Cards: Inset shadows, ghost borders
- Tables: Amber headers, green data rows
- Badges: Phosphor glow variants
- Modals: Dark backdrop, dim border
- Tabs: Uppercase with letter-spacing
- Forms: Dark inputs with focus glow

Each module now includes:
- crt-system.css (design tokens)
- crt-engine.js (typewriter, audio, toasts)
- Courier Prime font preconnect
- body.crt-body.crt-scanlines classes

Modules updated (38):
auth, backup, c3box, cdn, crowdsec, dns, dpi, droplet,
exposure, gitea, haproxy, hardening, hub, mail, mail-lxc,
mediaflow, metablogizer, mitmproxy, nac, netdata, netmodes,
nextcloud, portal, publish, qos, repo, streamforge, streamlit,
system, tor, traffic, users, vhost, waf, watchdog, webmail,
webmail-lxc, wireguard

Added: scripts/apply-crt-theme.py for future theme updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-23 18:56:11 +01:00
1868fa2d8c feat(mail): Debian LXC containers for Postfix/Dovecot/Roundcube
Mail Server LXC (mailserverctl v2.1.0):
- Switch from Alpine to Debian bookworm via debootstrap
- Host networking (lxc.net.0.type = none)
- Postfix + Dovecot with virtual mailbox support
- User management via mailctl (add/list/remove)
- DKIM key generation

Roundcube Webmail LXC (roundcubectl v1.4.0):
- Debian bookworm with roundcube package
- SQLite backend, port 8027
- PHP-FPM 8.2 + nginx
- Three-fold commands (components, access)

Also includes:
- Three-fold architecture for 6 modules
- Maintainer update to Gerald KERMA
- Authentication fixes (JWT secret, redirect paths)
- 4 new modules (c3box, gitea, nextcloud, portal)
- WIP.md updated with session progress

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-22 10:40:00 +01:00
f3d117987b fix: prerm scripts preserve nginx configs on upgrade + auth fixes
- Fix all 19 prerm scripts to only remove nginx config on actual
  package removal, not during upgrades. This prevents API routing
  failures after package updates.

- Fix uptime parsing in hub dashboard API - use int(float(...)) to
  handle decimal values from /proc/uptime

- Fix portal login.html to store JWT token to localStorage (sbx_token
  and secubox_token) for API authentication

- Fix hub logout function to clear both token names and redirect to
  login page

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-21 21:07:14 +01:00
7c42a80baf feat: modular nginx config + hub roadmap + new modules
Nginx architecture:
- Modular config: each module installs /etc/nginx/secubox.d/<module>.conf
- Auto-register on install, auto-remove on purge
- Main config includes from secubox.d/*.conf
- 27 module snippets for dynamic component management

Hub enhancements:
- Add roadmap widget showing migration progress (84% complete)
- Add /api/v1/hub/roadmap endpoint with category breakdown
- Shared sidebar.css for consistent styling across modules

New modules:
- secubox-portal: JWT authentication, session management
- secubox-dns: DNS server management
- secubox-mail: Mail server (Postfix) management
- secubox-webmail: Roundcube webmail
- secubox-users: User account management
- secubox-publish: Content publishing
- secubox-waf: Web Application Firewall
- secubox-mail-lxc: Mail LXC container
- secubox-webmail-lxc: Webmail LXC container

Debian packaging:
- All modules updated with modular nginx support
- postinst: creates secubox.d/, reloads nginx
- prerm: removes snippet, reloads nginx
- rules: installs nginx/<module>.conf

Scripts:
- new-package.sh: generates modular nginx files for new modules
- retrofit-nginx-modular.sh: updates existing packages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-21 20:34:01 +01:00
065560326d fix: complete CSS variables and add module scaffold skill
- Add missing --cyan, --yellow, --purple CSS vars to metablogizer,
  streamlit, streamforge, haproxy, vhost frontends
- Create /module skill for scaffolding new SecuBox modules
- Add new-module.sh script with complete package template
- Clean up debian build artifacts from git
- Update .gitignore for debian build dirs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-21 18:27:21 +01:00
8c8681276f Add dynamic menu system with menu.d JSON definitions
- Add /menu endpoint to secubox-hub for centralized menu management
- Create menu.d/*.json files for all 18 modules with category/order
- Update frontend sidebar to dynamically load menu from API
- Show module status (installed/active) with status dots
- Menu auto-discovers modules when packages are installed/removed

Categories: Dashboard, Security, Network, Monitoring, Publishing, Apps

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-21 16:42:49 +01:00
bf1babb37c Initial commit: SecuBox-DEB migration from OpenWrt to Debian
Includes all package APIs with public dashboard endpoints:
- secubox-system: System Hub with /info, /resources, /security
- secubox-crowdsec: CrowdSec dashboard with /status, /hub, /metrics, actions
- secubox-wireguard: WireGuard VPN with /interfaces, /peers, start/stop
- secubox-netdata: Monitoring with /stats, /processes, /alerts

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