- WAF-safe SSL: Route through mitmproxy_inspector, auto-add routes
- Scheduled backups: setup-backup-cron with hourly/daily/weekly support
- Email/SMTP: setup-mail command for outbound notifications
- CalDAV/CardDAV: connections command shows sync URLs for all clients
- New RPCD methods: get_connections, setup_mail, setup_backup_cron
- ACL updated with new method permissions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- JavaScript validation via Node.js --check (with pattern fallback)
- JSON validation for menu.d and acl.d files
- Shell script validation with shellcheck integration
- CSS validation for unclosed braces and typos
- LuCI-specific checks: require format, console.log, debugger
- Integrated into quick-deploy.sh as default for LuCI apps
- --lint/--no-lint flags for deployment control
- Documentation added to secubox-tools/README.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Design spec for WireGuard mesh peers as backup uplinks:
- Architecture for multi-WAN failover over WireGuard tunnels
- mwan3 integration plan for automatic failover
- Uplink capability advertisement via gossip
- CLI commands (wgctl uplink) and RPCD methods
- 4-phase implementation plan
Implementation planned for v2 release.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Enable WAF auto-ban by default (sensitivity: moderate, min_severity: high)
- Add whitelist for common safe IPs (localhost, router)
- Add browser cache busting via version parameter in CSS loads
- Document deployment scripts in secubox-tools/README.md
- Create CVE Layer 7 architecture documentation
WAF auto-ban now active with:
- 3 threats within 5 minutes triggers ban
- 4-hour ban duration
- Critical CVEs (Log4Shell, SQLi, CMDi) ban immediately
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Route AI requests through the AI Gateway for data sovereignty compliance.
Changes:
- secubox-mcp-server: ai.sh now prefers AI Gateway (port 4050), falls back to LocalAI
- secubox-threat-analyst: UCI config adds ai_gateway_url option
- threat-analyst CLI shows both Gateway and LocalAI status
- analyzer.sh and appliers.sh use ai_url (Gateway preferred)
- README updated with AI Gateway integration section
The AI Gateway ensures threat data (IPs, MACs, logs) is classified as
LOCAL_ONLY and never leaves the device, supporting ANSSI CSPN compliance.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement secubox-ai-gateway package with intelligent AI request routing
based on data sensitivity classification for GDPR/ANSSI compliance.
Features:
- 3-tier data classification: LOCAL_ONLY, SANITIZED, CLOUD_DIRECT
- Provider hierarchy: LocalAI > Mistral (EU) > Claude > GPT > Gemini > xAI
- PII sanitizer: IPv4/IPv6, MAC, credentials, private keys scrubbing
- OpenAI-compatible API proxy on port 4050
- aigatewayctl CLI: status, classify, sanitize, provider, audit commands
- RPCD backend with 11 ubus methods for LuCI integration
- ANSSI CSPN audit logging in JSONL format
Classification patterns detect:
- IP addresses, MAC addresses, private keys
- Credentials (password, secret, token, api_key)
- System paths, security tool references
- WireGuard configuration data
All cloud providers are opt-in. Default LOCAL_ONLY ensures data
sovereignty - sensitive data never leaves the device.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Conduit Matrix homeserver in LXC container
- Element Web client via uhttpd on port 8088
- HAProxy integration with SSL certificates
- Routes added to central secubox-route registry
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document the new secubox-route centralized WAF route management system
added in the previous commit.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add centralized route registry (`secubox-route`) in secubox-core to eliminate
route management duplication across metablogizerctl, streamlitctl, and
mitmproxyctl.
New features:
- `/etc/config/secubox-routes` - UCI config for central route registry
- `/usr/sbin/secubox-route` - CLI for route management (add, remove, sync)
- Import routes from HAProxy, MetaBlogizer, Streamlit with source tracking
- Auto-sync to all mitmproxy instances on route changes
- Skip wildcard domains and LuCI (port 8081) routes
Updated services to use centralized registry:
- metablogizerctl: Use secubox-route add instead of mitmproxyctl sync
- streamlitctl: Use secubox-route add with domain/port params
- peertubectl: Use secubox-route add for emancipation
- vhost-manager/mitmproxy.sh: Prefer secubox-route when available
- mitmproxyctl: Delegate to secubox-route import-all for sync-routes
This prevents route mixups between services and provides a single
source of truth for all WAF routing configuration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Skip wildcard domains (starting with '.') in sync-routes to allow
unknown subdomains to show "WAF SAYS NO" 404 page instead of blog
- Fix log_info() to output to stderr to prevent JSON corruption in
sync-routes when log messages mixed with JSON fragments
- Escape CSS curly braces in NOT_FOUND_HTML for Python .format()
compatibility (fixes KeyError: 'box-sizing')
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restores missing functionality in the Streamlit dashboard:
- Re-upload button: Upload new .py/.zip to replace existing app code
- Gitea Sync button: Pull latest changes from Gitea repository
The buttons appear in the Apps Library table for each app.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Meshname DNS for Yggdrasil mesh networks with gossip-based
service discovery and dnsmasq integration.
New packages:
- secubox-app-meshname-dns: Core service with meshnamectl CLI
- luci-app-meshname-dns: LuCI dashboard for service management
Features:
- Services announce .ygg domains via gossip protocol (meshname_announce)
- dnsmasq integration via /tmp/hosts/meshname dynamic hosts file
- Cross-node resolution through gossip message propagation
- RPCD handler with 8 methods for LuCI integration
CLI commands: announce, revoke, resolve, list, sync, status, daemon
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox_analytics.py: Add 'strict' as alias for 'aggressive' in autoban
- Fix waf_bypass false positives on LuCI static resources
- Root cause: different analytics versions across mitmproxy instances
- Update HISTORY.md with OpenClaw Gemini fix and WAF tuning
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Gemini 1.5 models no longer available in API. Updated model list to:
- gemini-2.0-flash
- gemini-2.5-flash
- gemini-2.5-pro
- gemini-flash-latest
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added gemini provider with models: gemini-1.5-flash, gemini-1.5-pro, gemini-pro
- Updated RPCD handler with Gemini API endpoint
- Updated settings.js with Google AI Studio link
- Updated chat.js to parse Gemini response format
- Changed Ollama default URL to LocalAI (port 8091)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete LuCI app with:
- Chat view with real-time AI conversation
- Settings view for provider/model/API key configuration
- Integrations view for Telegram/Discord/Slack/Email/Calendar
- RPCD backend handling all ubus calls
- Support for Anthropic, OpenAI, and Ollama providers
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy haproxy_router.py:
- Return 404 instead of routing to LuCI (8081) for missing routes
- Block any routes that point to port 8081
- Add "WAF Says NO" themed 404 page with multi-layer WAF visual
HAProxy (deployed on router):
- Configure end_of_internet backend with custom errorfiles
- Add "End of Internet" themed error pages for 5xx errors
- Patched haproxyctl to include errorfile directives
New package: secubox-app-openclaw
- Personal AI assistant integration for SecuBox
- Supports Anthropic Claude, OpenAI, and Ollama providers
- Chat integrations (Telegram, Discord, Slack)
- Email/calendar automation support
- CLI tool: openclawctl
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Was timing out with 199 HAProxy vhosts due to ~600 UCI calls.
Optimizations:
- get_haproxy_vhosts(): Single uci show + awk parsing instead of
per-vhost uci -q get calls (600 calls → 1 call)
- get_init_services(): Check only key services, use symlink detection
instead of executing init scripts
- get_metrics_summary(): Read CrowdSec data from cache file instead
of slow cscli commands
Result: Handler now responds in <1s with 204 published services.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
form.Map.render() returns a Promise, not a DOM element. Passing it
directly to KissTheme.wrap() caused "does not implement interface Node"
errors. Fixed by awaiting the Promise with .then() before wrapping.
Affected views:
- metablogizer/settings.js
- localai/settings.js
- domoticz/overview.js
- simplex/overview.js
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MIME type fix for static assets
- 403 fix for /apps/ routes
- Signaling endpoint URL correction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- luci.mailserver: Detect LXC containers for webmail status (not just Docker)
- docs: Add nginx static file fix and webmail detection to HISTORY/WIP
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace per-site UCI calls with single-pass awk parsing
- Pre-fetch listening ports, HAProxy backends, and Tor services
- Fix getline variable corruption that produced invalid JSON
- Reduce execution time from 30+ seconds to 0.23 seconds
- Update signaling.gk2.secubox.in route to port 8083 (LXC)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added routes for:
- pf.gk2.secubox.in (Streamlit prompt_forge, port 8502)
- secubox.maegia.tv (LuCI, port 8081)
- meet.maegia.tv (Jitsi, port 8088)
- xchat.gk2.secubox.in (XMPP, port 5280)
- fan.gk2.secubox.in (Streamlit, port 8529)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rewrote method_get_vhosts() to use single-pass awk parsing
- Reduced execution time from 30+ seconds timeout to 0.24 seconds
- Added arm, armada, files42 routes to mitmproxy config
The previous implementation made 4 UCI calls per vhost (764 total)
causing the luci-tree page to timeout. New implementation parses
uci show output once with awk.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add route management commands:
- `mitmproxyctl route list` - List all routes
- `mitmproxyctl route add <domain> <ip> <port>` - Add manual route
- `mitmproxyctl route remove <domain>` - Remove route
- `mitmproxyctl route check` - Check for missing routes
- Improve sync-routes to scan MetaBlogizer and Streamlit services:
- Auto-detect enabled MetaBlogizer sites and add routes
- Auto-detect enabled Streamlit instances with matching vhosts
- Warn about mitmproxy_inspector vhosts with missing routes
- Update routes config with 188 routes
This fixes the issue where services using mitmproxy_inspector backend
would fall back to default because their routes were not configured.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Deployed Yggdrasil on master (aarch64) and clone (x86_64)
- Connected to 2 public peers + LAN multicast auto-discovery
- Bidirectional ping6 and SSH over Yggdrasil working
- Fixed firewall zones: device="ygg0" required for nftables
- IPv6: master 201:e4d4:..., clone 201:a9d8:...
- Marks v1.1+ Yggdrasil overlay as complete
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed _print_uci_userlist to use config_list_foreach
- Each user now gets separate "user ... password ..." line
- Fixes HAProxy basic auth with multiple users
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix auth for Streamlit container (no ubus access)
- Use HTTP JSON-RPC to /ubus endpoint for authentication
- Add ALERTE.DEPOT app source to repo
- Update HISTORY.md with VoIP and auth fixes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Shell 'local' keyword only works inside functions, not case statements
- Remove all 'local' declarations to fix RPCD handler execution
- Fixes "not in a function" error when calling trunk_test and other methods
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix active_calls and extensions count to output clean integers
- Remove tr -cd which was causing duplicate values in JSON
- Use simpler variable assignment with fallback to 0
- Prevents malformed JSON output from cmd_status()
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Gitea as a service option in SecuBox Users UI
- Add Gitea checkbox in Add User modal
- Add Gitea service badge in status display
- Implement password sync to Gitea via API on password change
- Fix Gitea API call to include login_name parameter
- Add gitea to check_service() and get_status()
- Sync passwords to all enabled services (email, jabber, nextcloud, gitea)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bare `except:` clause catches SystemExit which is raised by
sys.exit(0), causing the script to fall through to sys.exit(1).
Changed to `except Exception:` which doesn't catch SystemExit,
allowing proper exit code propagation.
Also:
- Simplified Python extraction script
- Use double quotes for string literals (shell compatibility)
- Write Python script to temp file instead of heredoc (RPCD stdin conflict)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Streamlit upload now matches MetaBlogizer KISS pattern:
- Auto-detects ZIP files by magic bytes (PK header)
- Extracts app.py from ZIP archives automatically
- Adds UTF-8 encoding declaration to Python files
- Installs requirements.txt dependencies in background
- Restarts instance on re-upload for immediate update
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Upload modal now defaults to replacing index.html
- "Set as index" checkbox checked by default
- Uncheck to use original filename (shows destination field)
- Fixes issue where uploads weren't updating main page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed button logic from exp.vhost_exists to exp.emancipated
- Non-emancipated sites now correctly show "Expose" button
- Emancipated sites show "Unpublish" button
- vhost_exists was incorrectly true for some non-emancipated sites
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add auto-republish to method_upload_file (was only in upload_finalize)
- Add Gitea push to cmd_publish when gitea.enabled=1
- Use haproxyctl reload instead of init.d (container-aware)
- Uploaded content now triggers full republish flow for emancipated sites
This fixes the issue where uploading new HTML content didn't update
the live site because republish wasn't triggered.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New RPC method `change_password` in luci.secubox-users
- Verifies current password before allowing change
- Syncs new password to all enabled services (email, jabber, nextcloud)
- Matrix/PeerTube require manual password update (noted in response)
- Portal UI updates:
- New "Account" section with "Change Password" card
- Password change modal with current/new/confirm fields
- "My Services" card showing enabled services
- ACL updated to include new authentication methods
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>