Integrates ttyd WebSocket terminal into RTTY Remote module:
- New "Web Terminal" menu item in System Hub
- Iframe-based terminal embedding ttyd on port 7681
- Node selector for local/remote terminal access
- Remote node detection (direct ttyd or SSH fallback)
- Fullscreen and refresh controls
- RPCD method: start_terminal for remote node terminal info
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements token-based authentication that grants RPC and terminal access
without requiring LuCI credentials. Support technicians can connect using
a short 6-character code.
CLI commands:
- rttyctl token generate [ttl] [permissions]
- rttyctl token list
- rttyctl token validate <code>
- rttyctl token revoke <code>
- rttyctl token-rpc <code> <object> <method> [params]
RPCD methods:
- token_generate: Create support token with TTL
- token_list: List active tokens
- token_validate: Check token validity
- token_revoke: Revoke a token
- token_rpc: Execute RPC with token auth (no LuCI session needed)
LuCI Support Panel:
- Generate code with selectable validity (30m/1h/2h/4h)
- Enter code to connect to remote node
- Token-authenticated RPC execution
- Live token list with copy/revoke actions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Local addresses (127.0.0.1, localhost, 192.168.255.1, lan IP) now use
direct ubus call instead of HTTP JSON-RPC, providing full access to
all ubus methods without authentication restrictions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- jshn cannot embed raw JSON in objects, use printf instead
- Return proper {"success":true,"result":{...}} format
- Handle error cases with escaped error messages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix TypeError in support.js: add null checks for DOM elements
- Move menu entries from Services to System Hub (KISS UI)
- Menu paths: admin/secubox/system/system-hub/rtty-remote
- Menu paths: admin/secubox/system/system-hub/support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Dashboard now includes:
- Authoritative Zones table with View/Dump/Reload actions
- Import Zone modal with domain input
- Zone content viewer with download option
- Secondary DNS providers section
- Add Secondary modal (OVH/Gandi/Cloudflare support)
New RPC calls for zone_list, zone_dump, zone_import, zone_export,
zone_reload, secondary_list, secondary_add, secondary_remove.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove 2>/dev/null from for-loop glob pattern which causes syntax
error in BusyBox ash shell. The [ -f "$zf" ] check handles the
case when no zone files exist.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive zone management for DNS master functionality:
- vortexctl zone list/dump/import/export/reload commands
- Secondary DNS provider configuration (OVH support)
- RPCD methods for LuCI integration
- ACL permissions for new methods
This enables importing zones from external providers (Gandi) and
configuring OVH as secondary DNS with SecuBox as authoritative master.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Skip UCI userlists already defined in AUTH_USERLIST_FILE to avoid
duplicate 'secubox_users' userlist warning
- Fix indentation of nocache http-request rules in _emit_sorted_path_acls
- Use correct ACL names for path-based nocache rules
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Port 8889 conflicts with avatar-tap Streamlit service.
Updated mitmproxy-in instance to use port 8890 for HAProxy WAF routing.
Changes:
- UCI config: proxy_port and listen_port now default to 8890
- mitmproxyctl: Updated fallback defaults and documentation
- README: Updated architecture diagrams with correct port
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Root cause: jshn overhead + subshell issues with piped while loops
- Solution: Direct JSON output with printf, temp file for vhosts
- Deployed ACL file for LuCI authentication
- Handler now returns 226 vhosts in <10 seconds
Also:
- Added ROADMAP.md with version milestones and dependency graph
- Updated WIP.md with today's completed tasks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Lyrion: Default media_path changed from /srv/media to /mnt/MUSIC
- PhotoPrism: Default originals_path changed from /srv/photoprism/originals to /mnt/PHOTO
These paths reflect the actual mount points used for external media storage.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PHOTOPRISM_READONLY=true to prevent writes to originals
- Add PHOTOPRISM_SIDECAR_PATH and PHOTOPRISM_CACHE_PATH to writable storage
- Create run_photoprism_cmd helper to pass environment to lxc-attach
- Fixes indexing on read-only Apple Photos library mounts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add originals_path option to UCI config (default: /srv/photoprism/originals)
- Add set_config RPC method to update originals_path from LuCI
- Add Storage Settings section to LuCI dashboard
- Update LXC config to use configurable ORIGINALS_PATH
- Update get_stats to scan originals_path instead of data_path/originals
- Lyrion media_path already configurable via Settings page
Both services now support external mount points:
- PhotoPrism: /mnt/PHOTO for photos
- Lyrion: /mnt/MUSIC for music
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace MariaDB with SQLite (no external database needed)
- Update LXC config with proper device permissions and capabilities
- Install libvips42 instead of mariadb-server
- Fix binary path to ./bin/photoprism
- Use environment variables instead of options.yml
- Simplify backup to just archive storage directory
- Update WIP.md with SQLite note
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New packages:
- secubox-app-photoprism: LXC-based PhotoPrism deployment
- Debian Bookworm container with MariaDB, FFmpeg
- AI face recognition, object detection, places/maps
- photoprismctl CLI: install/start/stop/index/import/emancipate
- HAProxy integration via mitmproxy (WAF-safe)
- luci-app-photoprism: KISS-themed dashboard
- Stats cards (photos, videos, storage)
- Service controls and AI feature display
- Emancipate form for public exposure
- RPCD backend with 12 methods
docs: Update WIP.md with PhotoPrism feature
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix jshn boolean handling (use 1/0 instead of "true"/"false")
- Rework UI with dark theme compatible styling
- Add emoji-based status indicators (🔗🔒🛡️✅)
- Simplify interface with async Load More pagination
- Update README.md to v0.18.0 with 86 modules
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Renamed from routes-status to vhosts-checker to avoid conflict with
OpenWrt's default network routes page.
- KISS UI theme with header chips and status cards
- Shows HAProxy vhosts with mitmproxy route status (OUT/IN)
- SSL certificate status indicators
- WAF bypass detection
- Sync routes and add missing route actions
- Accessible at Status → VHosts Checker and KISS UI Network → VHosts Checker
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rewrite overview.js with KissTheme.wrap() for consistent SecuBox styling
- Add header chips for stats (vhosts, active, missing routes, WAF bypass, SSL)
- Add service status cards (HAProxy, mitmproxy, host IP)
- Add to KISS navigation under Network → Routes Status
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New package luci-app-routes-status providing:
- HAProxy vhosts status overview (218+ vhosts supported)
- mitmproxy route configuration status (OUT/IN routes)
- SSL certificate status indicators
- WAF bypass detection (vhosts not using mitmproxy_inspector)
- Sync routes and add missing route actions
- RPCD backend with batch processing for large vhost counts
Accessible at Status → Routes Status in LuCI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
secubox-users:
- Add gitea and jellyfin to supported services list
- Add create/update/delete handlers for gitea (via API) and jellyfin
- Update CLI help and status display to include new services
luci-app-secubox-users:
- Add jellyfin service checkbox and badge in frontend
- Update RPCD handler to check jellyfin service status
mitmproxy routing fix:
- nextcloudctl: Use host LAN IP instead of 127.0.0.1 for WAF routes
(mitmproxy runs in container, can't reach host's localhost)
- metablogizerctl: Same fix for mitmproxy route registration
- mitmproxyctl: Fix sync_metablogizer_routes to use host IP
This fixes 502/403 errors when accessing services through HAProxy->mitmproxy
because the mitmproxy container couldn't route to 127.0.0.1 on the host.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- network-modes: Remove orphan code block after final esac statement
- netdata-dashboard: Replace bash process substitution with POSIX awk
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, emancipation relied on secubox-route or mitmproxyctl sync-routes
which didn't reliably add routes to haproxy-routes.json. This caused newly
emancipated services to return 404 from mitmproxy.
Changes:
- streamlitctl: Direct JSON write as primary method for route registration
- metablogizerctl: Direct JSON write as primary method
- peertubectl: Direct JSON write as primary method
- pinaforectl: Direct JSON write + route through mitmproxy_inspector for WAF
All emancipation flows now directly write to /srv/mitmproxy-in/haproxy-routes.json
using Python, with secubox-route and mitmproxyctl as fallbacks.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPCD returns 'bytes_saved' but the JS was looking for
'bandwidth_saved_bytes', causing the "BW Saved" stat to always show 0.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Validated secubox-image.sh and secubox-sysupgrade.sh scripts:
- Fixed curl redirect issue: ASU API returns 301 redirects
- Added -L flag to 9 curl calls across both scripts
- Verified all device profiles valid (mochabin, espressobin, x86-64)
- Confirmed POSIX sh compatibility for sysupgrade script
- Validated first-boot script syntax
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
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>
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>