* docs(spec): Health banner live panel design (ref #92) Three public banner sections sharing one polling/CORS pipeline: - VisitorOrigin: nft set seen_src + GeoLite2-ASN.mmdb, threshold-gated rollup, raw IPs discarded before persistence - LiveHosts: HAProxy admin socket, 60 x 1-min ring buffer over req_tot deltas, hostname-heuristic frontend filter - CertStatus: scan /etc/letsencrypt/live + cryptography parse, classify valid / expiring_soon / expiring_critical / expired Each section fails independently; section hidden on enabled=false, empty entries, or fetch error. All three endpoints are unauthenticated, CORS-open, Cache-Control max-age=300. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(plan): Health banner live panel implementation plan (ref #92) 14-task TDD plan: tests scaffold -> config helpers -> three aggregators (visitor-origin / live-hosts / cert-status) -> FastAPI lifespan wiring -> nftables ruleset -> geoipupdate timer -> debian packaging -> banner v1.3.0 -> README + tracking docs -> full-suite verification + PR. Also reconciles spec with codebase conventions: service user is 'secubox' (not 'secubox-metrics'); config lives in /etc/secubox/secubox.conf, not a separate metrics.toml. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(metrics): Scaffold pytest layout for new aggregators (ref #92) Adds tests/__init__.py and conftest.py that wire packages/secubox-metrics/api and the repo-wide common/ onto sys.path so individual aggregator modules can be imported in isolation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(core): Add visitor_origin / live_hosts / cert_status config helpers (ref #92) Three new section helpers in secubox_core.config that merge defaults with operator-supplied TOML overrides. Each section defaults to enabled=false so the live-panel aggregators stay quiet on systems that haven't opted in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(metrics): Use tmp_path fixture + drop unused import (ref #92) Switches the config-helper tests from a hard-coded /tmp path to pytest's tmp_path fixture, matching the pattern in packages/secubox-haproxy/tests/. Removes the now-unused 'from unittest.mock import patch' line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(metrics): VisitorOrigin aggregator (ref #92) Pure-Python aggregator that polls the nft seen_src set, resolves ASNs via GeoLite2 mmdb, and emits a threshold-gated top-N rollup. Private/loopback IPs are skipped at lookup time; raw IPs never leave the function scope; the threshold gate runs before persistence so the cache file never contains attributable counts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(metrics): VisitorOrigin code-review followups (ref #92) - mmdb auto-reopen on mtime change (Important): close + reopen when stat reports a different mtime; previously _mmdb_mtime was dead state. - _read_nft_set defensive parse (Important): guard against {elem: str} shapes to prevent a latent TypeError. - current() returns a defensive copy (Minor): no more by-reference leak of internal state. - Drop unused ip_address import and unused monkeypatch parameter (Minor). - Tighten tiebreak test to assert ASN order, not just count order (Minor). - Add test for mtime-based reopen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(metrics): Pin VisitorOrigin error-path behaviour (ref #92) Regression tests for refresh_once: disabled config, missing mmdb, and nft subprocess failure must all yield a non-throwing degraded payload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(metrics): LiveHosts aggregator with 60x1-min ring buffer (ref #92) Reads HAProxy admin socket via raw AF_UNIX, parses 'show stat' CSV, filters internal frontends (leading underscore or no dot), ring-buffers per-frontend deltas over 60 minutes, and emits a top-N hostname rollup. Counter-reset detection (cur < prev) yields a fresh-baseline bucket instead of a negative delta. current() returns a defensive copy mirroring the VisitorOrigin fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(metrics): Pin LiveHosts CSV parser + missing-socket paths (ref #92) Tests the show-stat CSV parser against the real HAProxy column order and asserts that an absent admin socket returns a degraded payload rather than raising. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(metrics): CertStatus aggregator (ref #92) Scans /etc/letsencrypt/live for cert.pem files, classifies each by days remaining (valid / expiring_soon / expiring_critical / expired) using the operator's warn_days/critical_days thresholds, and emits a summary + soonest next-renewal host. A single corrupt PEM never kills the scan. Days remaining computed with math.ceil so a cert expiring in 2.99d reports 3d, consistent with certbot/renewal tooling expectations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(metrics): correct expired boundary when using math.ceil (ref #92) math.ceil maps any cert that expired within the last 24 h to days=0, which the previous `days < 0` guard treated as expiring_critical instead of expired. Changing the guard to `days <= 0` closes the gap: with ceil, days=0 means actual remaining time is in (-86400, 0] — i.e. already past or exactly at expiry — so classifying it as expired is correct. All four existing tests continue to pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(metrics): Wire three live-panel aggregators into FastAPI lifespan (ref #92) Adds the three asyncio background tasks under a single lifespan and exposes their current() payloads on /api/v1/metrics/{visitor-origin,live-hosts,cert-status} with a 5-min Cache-Control. Endpoints stay unauthenticated by design — the aggregators only emit threshold-gated, hostname-only data. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(metrics): Await cancelled lifespan tasks + tidy import order (ref #92) - Important: lifespan finally now awaits gather(*tasks, return_exceptions=True) after cancel(), so blocking subprocess/socket I/O in aggregator refreshes doesn't race uvicorn's shutdown timeout. - Minor: move 'from contextlib import asynccontextmanager' into the stdlib import group at the top of the file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(metrics): Ship nftables ingress tap for visitor-origin (ref #92) Private inet secubox_metrics table with a timeout'd src-IP set, hooked from prerouting at priority -300 so additions happen before secubox-firewall's filter chain decides whether to drop the packet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(metrics): Weekly GeoLite2 ASN refresh timer (ref #92) Conditional on /etc/secubox/secrets/maxmind.conf existing, so the unit is a silent no-op on installs that haven't supplied a license key. RandomizedDelay spreads load when many boxes deploy together. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * build(metrics): Package live-panel deps, nft ruleset, and geoipupdate timer (ref #92) - control: add python3-maxminddb, python3-cryptography, geoipupdate, nftables - rules: install nftables/ and systemd/ assets - postinst: secubox -> haproxy group, cache + secrets + GeoIP dirs, nftables reload, timer enable - service: ReadWritePaths gains /var/cache/secubox Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(metrics): Run geoipupdate as secubox + restart svc on upgrade (ref #92) - secubox-geoipupdate.service: User/Group=secubox so .mmdb files inherit the ownership the metrics service expects when reading them. Previously the unit ran as root and created root-owned files that secubox-metrics could not open. - postinst: switch 'systemctl start' to 'systemctl restart' so the secubox user's new haproxy-group membership is picked up by an already-running service after an upgrade. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(banner): v1.3.0 live panel — visitor origin, live hosts, cert status (ref #92) Three independent fetch loops on a shared 30s cadence, three DOM sections, per-section hide on enabled=false / empty / fetch error. Uses existing design tokens (gold/cyan/matrix-green) so no new CSS variables are added. A failing section never affects the others. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(banner): Correct banner element id lookup in live-panel (ref #92) The new live-panel sectionContainer() helper looked up getElementById('sbx-health-banner'), but the actual banner element is created with id='health-banner'. The mismatch made banner null, so the three live-panel sections were silently never appended to the DOM. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: Session 160 — Health Banner Live Panel (ref #92) README documents the three new endpoints + config blocks. HISTORY / WIP / MIGRATION-MAP entries describe the feature, the spec/plan paths, and the session's outcome. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(metrics): Address whole-branch review findings (ref #92) - Wrap _read_nft_set / _read_haproxy_stats in asyncio.to_thread so blocking I/O (subprocess up to 5s, AF_UNIX recv up to 2s) no longer stalls the event loop on every refresh tick. - Replace falsy current() guard with explicit _refreshed flag. Previously, a successful refresh that produced entries=[] would fall through to the on-disk cache, serving stale non-empty data during low-traffic periods. - Move geoipupdate from Depends to Recommends. It lives in bookworm/contrib, so a hard dependency breaks 'apt install secubox-metrics' on systems without contrib enabled. The aggregator already degrades gracefully when the mmdb is absent, making Recommends the correct strength. README documents the contrib note. - prerm stops + disables secubox-geoipupdate.timer/service so 'apt remove' doesn't leave an orphan timer firing weekly with a missing unit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: CyberMind-FR <gandalf@Gk2.net> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .claude | ||
| .github/workflows | ||
| .superpowers/brainstorm/1465198-1777214258 | ||
| .vscode | ||
| apt | ||
| board | ||
| cache/repo | ||
| cmd/secubox | ||
| common | ||
| config | ||
| daemon | ||
| docs | ||
| doctrine/opad | ||
| hardware | ||
| image | ||
| kernel-build | ||
| packages | ||
| profiles | ||
| prototypes | ||
| redroid | ||
| remote-ui | ||
| repo | ||
| schemas | ||
| scripts | ||
| templates | ||
| tests | ||
| tools | ||
| vm | ||
| wiki | ||
| .gitignore | ||
| build-eye-remote-full.sh | ||
| CLAUDE.md | ||
| LICENCE-CMSD-1.0.md | ||
| LICENSE-CMSD-1.0.en.md | ||
| LICENSING.md | ||
| PROMPT_SYSTEM.md | ||
| README.md | ||
| REPORT-2026-04-10.md | ||
| secubox.conf.example | ||
| setup-dev.sh | ||
| TOOLS.md | ||
SecuBox
Your Network Security Appliance — Plug, Protect, Peace of Mind
License — CyberMind Source-Disclosed (CMSD-1.0)
Source disclosed, rights reserved.
This software is released under the CyberMind Source-Disclosed License v1.0 — a source-available license designed for transparency and security auditability while preserving all commercial rights.
| What you CAN do | What you CANNOT do |
|---|---|
| Read and study the source code | Use in production (any environment) |
| Compile for isolated testing/audit | Redistribute or create derivatives |
| Publish security research results | Integrate into other products |
| Quote in academic/journalistic contexts | Provide as hosted service (SaaS) |
ANSSI CSPN Ready: The license explicitly authorizes audits by accredited security labs (CESTI, CC equivalents) without prior authorization.
See LICENCE-CMSD-1.0.md (French, authoritative) or LICENSE-CMSD-1.0.en.md (English, informative).
| Metric | Value |
|---|---|
131 .deb packages |
|
| 123/131 modules migrated | |
| FastAPI + JWT auth | |
|  |
SecuBox transforms any compatible device into a complete network security appliance with VPN, firewall, intrusion detection, and web dashboard — all preconfigured and ready to use.
What You Get
- VPN Server — WireGuard with QR codes for mobile devices
- Intrusion Detection — CrowdSec IDS/IPS with automatic threat blocking
- Network Monitoring — Real-time traffic analysis and bandwidth control
- Web Dashboard — Modern dark-themed interface accessible from any browser
- Automatic Updates — Security patches applied automatically
Quick Start
Option 1: VirtualBox (Try It Now)
Download and run in VirtualBox — no hardware required:
# Download the image
wget https://github.com/CyberMind-FR/secubox-deb/releases/latest/download/secubox-live-amd64-bookworm.img.gz
# Extract
gunzip secubox-live-amd64-bookworm.img.gz
# Create VM (requires VBoxManage)
./scripts/create-secubox-vm.sh secubox-live-amd64-bookworm.img
Access: Open https://localhost:9443 in your browser
Login: admin / secubox
Option 2: Live USB (Any PC)
Boot from USB on any x86_64 computer:
# Download
wget https://github.com/CyberMind-FR/secubox-deb/releases/latest/download/secubox-live-amd64-bookworm.img.gz
# Flash to USB (replace /dev/sdX with your USB device)
zcat secubox-live-amd64-bookworm.img.gz | sudo dd of=/dev/sdX bs=4M status=progress
Boot from USB, then access the dashboard at https://<device-ip>/
Option 3: Dedicated Hardware
For 24/7 operation, flash to dedicated hardware:
| Device | Best For | Image |
|---|---|---|
| Raspberry Pi 4/5 | Home use | secubox-rpi-arm64-*.img.gz |
| ESPRESSObin | Small office | secubox-espressobin-v7-*.img.gz |
| MOCHAbin | Enterprise | secubox-mochabin-*.img.gz |
| Any x86_64 PC | Repurposed hardware | secubox-live-amd64-*.img.gz |
Features
Security Dashboard
Central control panel showing system health, active threats, and quick actions.
VPN (WireGuard)
Create VPN connections with one click. Scan QR codes on mobile devices.
Intrusion Detection (CrowdSec)
Automatic threat detection and IP blocking with community threat intelligence.
Network Control
- Bandwidth management (QoS)
- Device access control
- Deep packet inspection
- Virtual hosts with SSL
System Management
- Service control
- Log viewer
- Automatic backups
- Easy updates
Eye Remote — External Dashboard
A standalone round display that connects to SecuBox via USB OTG, showing real-time metrics with a cyberpunk 3D visualization.
| Feature | Description |
|---|---|
| Hardware | Raspberry Pi Zero W + HyperPixel 2.1 Round (480×480) |
| Connection | USB OTG composite gadget (network + serial) |
| Display | 3D rotating cube + rainbow ring metrics |
| Metrics | CPU, Memory, Disk, Temperature, WiFi RSSI |
Quick Start
# Download Eye Remote image
wget https://github.com/CyberMind-FR/secubox-deb/releases/download/v2.2.1-eye-remote/secubox-eye-remote-2.2.1.img.xz
# Flash to SD card
xzcat secubox-eye-remote-2.2.1.img.xz | sudo dd of=/dev/sdX bs=4M status=progress
- Insert SD in Pi Zero W with HyperPixel display
- Connect USB DATA port (middle) to SecuBox
- Dashboard appears automatically (~60s boot)
SSH: pi@10.55.0.2 (password: raspberry)
📖 Full documentation: remote-ui/round/README.md
Default Credentials
| Service | Username | Password |
|---|---|---|
| Web Dashboard | admin |
secubox |
| SSH | root |
secubox |
Change these immediately after first login!
Support
- Wiki: github.com/CyberMind-FR/secubox-deb/wiki
- Issues: github.com/CyberMind-FR/secubox-deb/issues
- Email: support@secubox.in
License
CMSD-1.0 (CyberMind Source-Disclosed License) © 2026 CyberMind · Gérald Kerma See LICENCE-CMSD-1.0.md for terms.
Technical Reference (Click to Expand)
Architecture
OpenWrt / LuCI → Debian bookworm
─────────────────────────────────────────────────────────
RPCD shell backend → FastAPI + Uvicorn (Unix socket)
UCI config /etc/config/ → TOML /etc/secubox/secubox.conf
luci-app-*/htdocs/ (JS/CSS/HTML) → Conservé + XHR réécrits
OpenWrt packages (.ipk) → Paquets Debian (.deb)
opkg → apt + repo apt.secubox.in
Supported Hardware
| Board | SoC | RAM | Network | Profile |
|---|---|---|---|---|
| MOCHAbin | Armada 7040 Quad 1.8GHz | 4 GB | 2× SFP+ 10GbE + 4× GbE | Pro |
| ESPRESSObin v7 | Armada 3720 Dual 1.2GHz | 1–2 GB | WAN + 2× LAN DSA | Lite |
| ESPRESSObin Ultra | Armada 3720 Dual 1.2GHz | 2 GB | WAN PoE + 4× LAN + Wi-Fi | Lite+ |
| Raspberry Pi 4/400 | BCM2711 Quad 1.5-1.8GHz | 2-8 GB | GbE + USB | Lite |
| Raspberry Pi 5 | BCM2712 Quad 2.4GHz | 4-8 GB | GbE + USB | Full |
| VM x86_64 | Any | 2+ GB | Virtio/NAT | Full |
Packages (126 modules)
Core: secubox-core, secubox-hub, secubox-portal, secubox-system
Security: secubox-crowdsec, secubox-wireguard, secubox-auth, secubox-nac, secubox-waf, secubox-users
Network: secubox-netmodes, secubox-dpi, secubox-qos, secubox-vhost, secubox-haproxy
Monitoring: secubox-netdata, secubox-mediaflow, secubox-cdn
DNS/Email: secubox-dns, secubox-mail, secubox-webmail
Publishing: secubox-droplet, secubox-streamlit, secubox-metablogizer, secubox-publish
API Reference
All modules expose REST APIs at /api/v1/<module>/
# Login
curl -X POST https://localhost/api/v1/portal/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"secubox"}'
# Use token
curl https://localhost/api/v1/hub/status \
-H 'Authorization: Bearer <token>'
Key Endpoints:
GET /api/v1/hub/dashboard— Dashboard dataGET /api/v1/crowdsec/decisions— Active bansPOST /api/v1/crowdsec/ban— Ban IPGET /api/v1/wireguard/peers— VPN peersGET /api/v1/wireguard/qrcode/{peer}— Peer QR code
Configuration
Main config: /etc/secubox/secubox.conf (TOML)
[general]
hostname = "secubox"
timezone = "Europe/Paris"
[auth]
jwt_secret = "your-secret-key"
session_timeout = 86400
[network]
wan_interface = "eth0"
lan_interface = "eth1"
Development
# Setup
bash setup-dev.sh && source .venv/bin/activate
# Run module API
cd packages/secubox-crowdsec
uvicorn api.main:app --reload --port 8001
# Build package
dpkg-buildpackage -us -uc -b
# Build image
sudo bash image/build-image.sh --board vm-x64 --vdi
UI Design Guidelines
Color Palette (Cyberpunk/Hermetic):
| Variable | Color | Usage |
|---|---|---|
--cosmos-black |
#0a0a0f |
Background |
--gold-hermetic |
#c9a84c |
Accents, titles |
--cinnabar |
#e63946 |
Alerts, errors |
--matrix-green |
#00ff41 |
Success |
--void-purple |
#6e40c9 |
Links |
--cyber-cyan |
#00d4ff |
Info, hover |
--text-primary |
#e8e6d9 |
Main text |
Typography: Cinzel (titles), IM Fell English (body), JetBrains Mono (code)