Implement secubox-master-link (backend) and luci-app-master-link (LuCI
frontend) for secure node onboarding into the SecuBox mesh via
HMAC-SHA256 join tokens, blockchain-backed peer trust, and gigogne
(nested) hierarchy with depth limiting.
Backend provides: token management, join/approve/reject protocol, IPK
bundle serving, CGI API endpoints, and a dark-themed landing page for
new nodes. Frontend provides a 3-tab LuCI view (overview, join requests,
mesh tree) with RPCD integration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
grep -c returns exit code 1 when no matches found (even though it
outputs 0), causing `|| echo 0` to append an extra 0 and corrupt
the JSON response. This broke ubus calls and LuCI status display.
Use `: ${var:=0}` pattern instead to provide defaults.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Read LXC path from /etc/lxc/lxc.conf instead of hardcoding /var/lib/lxc
(OpenWrt uses /srv/lxc by default)
- Skip Alpine rootfs download if file already exists in /tmp
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The factory_audit_log function's ubus call was only redirecting stderr,
allowing stdout JSON output to leak into CGI responses when Gitea backup
is enabled. This caused JSON parse errors in the Factory dashboard when
creating snapshots.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox-app-mitmproxy: Sensitivity-based auto-ban system
- luci-app-mitmproxy: Updated frontend
- luci-app-crowdsec-dashboard: Ban button on alerts page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WAF Auto-ban Features:
- Three sensitivity levels: aggressive, moderate, permissive
- Aggressive: Immediate ban on first critical threat
- Moderate: Ban after 3 attempts in 5 minutes (default)
- Permissive: Ban after 5 attempts in 1 hour
- Attempt tracking with configurable thresholds
Critical threats (immediate in aggressive/moderate):
- CVE exploits, SQL injection, Command injection
- XXE, Log4Shell, SSTI attacks
CrowdSec Integration:
- Auto-ban requests written to /srv/mitmproxy/autoban-requests.log
- Cron job processes bans every minute via mitmproxyctl
- Bans sent to CrowdSec for network-wide enforcement
New Commands:
- mitmproxyctl process-autoban: Process pending bans
- mitmproxyctl reload-autoban: Reload config after UCI changes
CrowdSec Dashboard:
- Added ban button to alerts page
- Modal confirmation with 24h ban duration
- Real-time banned IP tracking
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Integrate SimpleX Chat SMP and XFTP servers for privacy-focused messaging:
- secubox-app-simplex: Backend with LXC container management
- SMP server for message relay (port 5223)
- XFTP server for encrypted file sharing (port 443)
- Auto-download of SimpleX binaries for aarch64/x86_64
- TLS certificate generation (self-signed or Let's Encrypt)
- Firewall and HAProxy integration
- luci-app-simplex: LuCI dashboard with:
- Service status monitoring
- Server address display with copy-to-clipboard
- Full configuration forms for SMP, XFTP, and TLS
- Install/certificate management actions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restored the original settings.js functionality as setup.js with
updated nav references. The simplified version was broken.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The settings page was showing "CAPI: Error" because the status
method didn't return the capi_enrolled field. Added CAPI status
check to get_status() so the health display shows correct status.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Content-Type based CVE detection must happen before SSRF patterns
to avoid false positives when routing through localhost.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
LAN transparent mode now requires explicit opt-in via transparent.enabled
to prevent HTTPS certificate errors for LAN clients.
Changes:
- mitmproxyctl: Check transparent_enabled before setting up LAN firewall rules
- LuCI settings: Add warning about certificate requirements for LAN mode
- Default config already has transparent.enabled='0'
WAN protection mode remains active for incoming threat detection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add WAF-like functionality to mitmproxy for protecting services exposed
to the internet. Incoming WAN traffic is redirected through mitmproxy
for threat detection before reaching backend services.
Features:
- WAN protection mode with nftables rules for incoming traffic
- Enhanced bot scanner detection with 50+ scanner signatures
- Behavioral detection for config/admin/backup/shell hunting
- CrowdSec integration with new scenarios for bot scanners
- LuCI interface for WAN protection configuration
- DPI mirror mode support (secondary feature)
New CrowdSec scenarios:
- secubox/mitmproxy-botscan: Detect automated reconnaissance
- secubox/mitmproxy-shell-hunter: Detect shell/backdoor hunting
- secubox/mitmproxy-config-hunter: Detect credential file hunting
- secubox/mitmproxy-suspicious-ua: Detect suspicious user agents
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of showing clickable model suggestions when Ollama is stopped,
display a helpful message prompting the user to start Ollama first.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace pipe-to-while loops with grep/cut to avoid subshell variable
scope issues in method_status, method_get_providers, and method_set_provider.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
DNS Guard (luci-secubox-dnsguard):
- Privacy-focused DNS manager with KISS UI
- DNS provider feed: FDN, Quad9, Cloudflare, Mullvad, AdGuard, etc.
- Smart Config auto-detects fastest DNS for location
- Category filtering (privacy, security, fast, family, adblock)
- One-click provider switching with dnsmasq integration
Ollama:
- Add suggested models grid when no models installed
- Clickable model cards to download directly
- Models: tinyllama, llama3.2, phi3, gemma2, qwen2.5, mistral, codellama
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change Gitea default port to 3001 (avoid AdGuard Home conflict)
- Add process_name and description to Gitea known service
- Use reserved port from config, verify if actually listening
- Add separate listening/running flags for better status reporting
- Reserved ports are tracked for dedup, dynamic detection fills gaps
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change AdGuard Home default port to 3003 (avoid Gitea conflict)
- Update config file path to /var/lib/adguardhome/AdGuardHome.yaml
- Add netstat-based port detection for running processes
- Actual listening port overrides default when service is running
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AdGuard Home to known services (port 3000, security category)
- Enhance _add_exposed_service to handle YAML config files
- Add process name detection and running status for known services
- Fix subshell issue in dynamic service detection (while loop)
- Add port deduplication between known and dynamic services
- Include description and process fields in service response
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated packages:
- luci-app-ollama: KISS UI rewrite
- luci-app-secubox-netdiag: Temperature monitoring and port mode controls
- secubox-core, secubox-p2p: Latest versions
- All other packages rebuilt with current SDK
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ollama:
- Complete KISS UI rewrite with simplified dashboard
- RPC declarations without expect clauses for reliability
- Service controls, model management, and chat interface
Network Diagnostics:
- Add temperature display with color-coded thresholds
- Add error collection and export functionality
- Add port mode switching (speed/duplex/EEE)
- Add collect_errors, get_port_modes, get_temperature RPC methods
- Add set_port_mode RPC method for port configuration
- Fix ACL permissions for new methods
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change nav paths from services/crowdsec to security/crowdsec in alerts,
bouncers, decisions, and settings views to match the new menu location.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
getDecisions() was looking for result.alerts but RPC returns
result.decisions - fixed to use correct property name.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change RPCD to return alerts_raw and decisions_raw as JSON strings
- Add parseAlerts() to parse alerts_raw in JavaScript
- Fix countries and alerts now display correctly in overview
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix nav links to use correct path (security instead of services)
- Add parseCountries() to convert top_countries_raw JSON to object
- Fix geo data display in overview
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move mitmproxy from Services to SecuBox → Security & Access menu
alongside CrowdSec for better organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use SVG output instead of PNG (PNG disabled in OpenWrt qrencode)
- Fix endpoint port duplication when port already in endpoint string
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix qrcode require path (slash to dot notation)
- Load hosting status asynchronously to prevent XHR timeout
- Dashboard now loads instantly with sites, HAProxy/IP populate after
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPCD returns data directly without wrapping in a 'result' object,
but api.js was using expect: { result: {} } which caused empty data
in the UI (0 sites shown instead of 6).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace overview.js with dashboard.js using standard cbi-* classes
- Add api.js module for RPC declarations
- Show port, runtime, backend_running status in sites table
- Add sync_config, discover_vhosts, import_vhost RPC methods
- Update ACL with new method permissions
- Menu: Sites -> Dashboard
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Running Instances section with enable/disable/delete actions
- Add Instance form to create new instances on different ports
- Add Gitea clone functionality to pull apps from repositories
- Add Gitea configuration section in Settings page
- RPCD handler now supports:
- get_gitea_config, save_gitea_config
- gitea_clone, gitea_pull, gitea_list_repos
- API module exports all new Gitea methods
- Upload supports both .py files and .zip archives
- Instance status shown with colored indicators
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When an app has no description, return empty string instead of null
to prevent "null" text from being rendered in the instances table.
Also: secubox-p2p bumped to v0.6.0-r3 with catalog fix.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When HAProxy inspection mode routes all vhosts through mitmproxy_inspector,
the catalog now uses the original_backend UCI property to correctly map
domains to their actual services.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use POST method for creating new files and PUT for updates.
Gitea requires this distinction - PUT with no SHA fails for new files.
Changes:
- Use POST for creating new files in catalog_push_gitea()
- Use PUT only when existing SHA is available (updates)
- Add explicit branch parameter for consistency
- Bump version to 0.6.0-r2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add file exec permissions for:
- /usr/bin/secubox-services-status
- /bin/sh
Required for fs.exec() to work in LuCI frontend.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create /usr/bin/secubox-services-status helper script
- Update portal scanInitServices to use helper script
- Fallback to inline script if helper not available
- Fixes 0/0 services display caused by fs.exec output buffering
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use pgrep without -f flag (OpenWrt compatibility)
- Use printf instead of echo for reliable output
- Add explicit /bin/sh path
- Add error logging for debugging
Fixes 0/0 services display on dashboard.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Distributed Catalog:
- Implement catalog_push_gitea() to push node catalogs via Gitea REST API
- Add catalog_push_merged_gitea() for merged catalog sync
- Create /api/factory/catalog-sync POST endpoint for triggering sync
- Catalogs pushed to catalog/nodes/{hostname}.json in Gitea repo
Health Probing:
- Add get_service_health() with cached latency measurement
- HTTP probe with curl to measure response time
- Fallback to /proc/net/tcp port check
- 60-second cache TTL to keep catalog endpoint fast
Files:
- factory.sh: Gitea REST API integration for catalog push
- catalog: Health probing with latency measurement
- catalog-sync: New CGI endpoint for sync operations
- Makefile: Install catalog-sync endpoint
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bouncer creates multiple sets: crowdsec-blacklists (empty base),
crowdsec-blacklists-CAPI (community blocklists ~19k IPs), and
crowdsec-blacklists-crowdsec (local decisions). Now counts IPs from
all sets in the table instead of just the base set.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move CrowdSec from Services to Security & Access menu
- Fix get_decisions() to return {"decisions":[]} not {"alerts":[]}
- Fix active_bans to use local_decisions count instead of parsing
unreliable metrics output
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The mitmproxy container mounts /srv/mitmproxy as /data, so the GeoIP
database path must use /data/GeoLite2-Country.mmdb for the addon to
find it. This enables proper country detection for external IPs in
threat logs, allowing CrowdSec SSRF scenarios to correctly identify
and ban foreign attackers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The threat monitor now checks netifyd_running and dpi_available fields
in addition to ndpid running status. This fixes the "nDPId not running"
warning when only netifyd is installed.
- Check ndpid.running OR netifyd_running OR dpi_available
- Show flow count in DPI service badge
- Rename badge from "nDPId" to "DPI" for clarity
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change analytics addon to write threats to /data/threats.log (bind-mounted to host)
- Add CrowdSec acquisition config to read from /srv/mitmproxy/threats.log
- Add parser for mitmproxy JSON threat logs with source_ip in Meta
- Add scenarios for web attacks, scanners, SSRF, and CVE exploits
- Update RPCD to read alerts from host-visible path without lxc-attach
This enables automatic IP banning when mitmproxy detects:
- SQL injection, XSS, command injection (capacity: 3, ban: 15m)
- Path traversal, XXE, LDAP injection, Log4Shell
- Aggressive web scanning (capacity: 10, ban: 10m)
- SSRF attempts from external IPs (capacity: 5, ban: 10m)
- Known CVE exploits (immediate trigger, ban: 30m)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The alerts, threat_stats, clear_alerts, haproxy_enable, haproxy_disable,
and sync_routes methods were not in the ACL file, causing permission
denied errors when calling them from LuCI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPCD was looking for alerts in /tmp/secubox-mitm-alerts.json but
the analytics addon writes to /var/log/crowdsec/secubox-mitm.log in
JSONL format (one JSON object per line).
Changes:
- RPCD: Read from container's /var/log/crowdsec/secubox-mitm.log
- RPCD: Convert JSONL to JSON array using awk
- JS: Handle new field names (source_ip, timestamp, request)
Alerts now display correctly in LuCI dashboard.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sync-routes command was failing to generate routes for most vhosts due to:
- Subshell bug: pipe in while loop caused variable changes to be lost
- Only supported old-style backends (inline .server field)
- Did not support new-style backends with separate =server sections
Changes:
- Rewrite sync-routes to avoid subshell by using temp file
- Add support for both backend styles (inline and separate server sections)
- Use original_backend field when vhosts are in inspection mode
- Skip luci/fallback/mitmproxy_inspector backends in route generation
Now properly generates 13+ routes for HAProxy backend inspection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add HAProxy → mitmproxy → Backend inspection chain for filtering
all vhost traffic through mitmproxy with threat detection
- Add haproxy_router.py addon for Host-based request routing
- Add mitmproxyctl commands: sync-routes, haproxy-enable, haproxy-disable
- Add auth token to status response for Web UI auto-authentication
- Add HAProxy Backend Inspection section to LuCI status page with
enable/disable/sync controls
- Add HAProxy Router settings section to LuCI settings page
- LXC container now supports dual-port mode (8888 + 8889 for HAProxy)
- Token displayed with copy button in dashboard
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Swiss Army knife for SecuBox with interactive menu and direct commands:
- status: System overview with services, docker, mesh
- mesh: P2P mesh operations (peers, discover, sync)
- security: CrowdSec status, threats, block/unblock
- docker: Container management
- haproxy: Vhosts and reload
- network: Diagnostics, ports, connections
- recover: Snapshot/restore operations
- feed: Package management
Also updates feed with Jitsi packages and core v0.10.0-r11.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox-app-jitsi: Docker-based Jitsi stack with jitsctl control CLI
- luci-app-jitsi: LuCI web configuration interface
- Catalog entry for SecuBox AppStore
Features:
- End-to-end encrypted video conferencing
- HAProxy integration with WebSocket/SSL support
- Mesh federation for SecuBox P2P network
- User authentication management
- Backup/restore functionality
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Distributed service registry with HAProxy vhost discovery
- Multi-endpoint URLs (haproxy/mesh/local) per service
- DNS federation for mesh peers (*.sb.local via dnsmasq)
- Catalog tab with service filtering and QR codes
- Linked peers navigation panel
- Tools panel with DNS management
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Separate static files from CGI scripts in uhttpd configuration:
- Static files (index.html) served from /www
- CGI scripts executed from /www/api/*
- API base changed from /factory/ to /api/factory/
This fixes HAProxy routing where /factory/ serves the UI and
/api/factory/* routes to the P2P API backend.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement distributed service catalog that discovers HAProxy vhosts
and provides multi-endpoint access URLs (haproxy/mesh/local). Add
dynamic DNS federation that auto-populates dnsmasq with mesh peer
hostnames (hostname.mesh.local).
New features:
- /factory/catalog API endpoint with service registry
- Catalog tab (📚) in Factory UI with endpoint filtering
- QR codes with URL type switching (haproxy/mesh/local)
- Linked mesh peers navigation panel
- DNS federation via /tmp/hosts/secubox-mesh
- CLI commands: dns-enable/disable/update, catalog sync/list/generate
Bumps secubox-p2p to v0.6.0.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add mesh-services CGI endpoint for aggregated service discovery
across all mesh peers
- Update Factory UI with tabbed interface: Dashboard and Mesh Services
- Mesh Services panel features:
- Real-time service discovery from all nodes
- Filter by search, status, or node
- Direct access links for services with ports
- Status indicators (running/stopped/disabled)
- Summary stats (nodes online, running/total services)
- Bump version to 0.5.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change API base URL to use relative /factory/ path instead of
absolute URL with port 7331. HAProxy routes /factory/* API paths
to the factory backend while serving UI from luci backend.
This fixes mixed content blocking when accessing via HTTPS.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace signify-openbsd calls with HMAC-based signatures
(OpenWrt's signify lacks -n flag for no-passphrase)
- Fix API paths in UI: use /factory/ not /api/factory/
- Support cross-port API calls (UI on 8081, API on 7331)
- Update LuCI view to use relative /factory/ path
- Update feed with secubox-p2p 0.4.0 packages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement mesh-distributed, cryptographically-validated control center:
- Add factory.sh library with Ed25519 signing via signify-openbsd
- Add Merkle tree calculation for /etc/config validation
- Add CGI endpoints: dashboard, tools, run, snapshot, pubkey
- Add KISS Web UI (~280 lines vanilla JS, inline CSS, zero deps)
- Add gossip-based 3-peer fanout for snapshot synchronization
- Add offline operations queue with replay on reconnect
- Add LuCI iframe integration under MirrorBox > Factory tab
- Configure uhttpd alias for /factory/ on port 7331
- Bump secubox-p2p version to 0.4.0
Factory UI accessible at http://<device>:7331/factory/
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox-p2p upgraded to v0.3.0 with multi-address mesh support
- WAN IP detection via ipify/ifconfig.me for NAT traversal
- WireGuard tunnel IP enumeration for secure redundancy
- Failover priority: WireGuard → WAN → LAN
- luci-app-secubox-portal KISS redesign (~1000 → ~500 lines)
- Service categorization: Web/Proxy, Security, AI/ML, Containers, Media, Apps
- Dynamic init.d service scanning with 60s caching
- Rebuilt all packages in feed
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_wan_ip() to detect real WAN/public IP address
- Add get_wg_ips() to enumerate WireGuard tunnel addresses
- Add get_node_addresses() returning JSON array of all addresses
- Update register_self() to include WAN and WireGuard addresses
- Update get_node_status() API to expose all addresses
- Update add_peer() to support multi-address peers
- Update daemon connectivity check to try:
1. WireGuard tunnel (secure redundancy)
2. WAN address (external reach)
3. LAN address (local fallback)
- Add UCI options: advertise_wan, advertise_wireguard, prefer_wireguard
- Version bump to 0.3.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify portal to ~500 lines (from ~1000)
- Add service categories: Web/Proxy, Security, AI/ML, Containers, Media, Apps
- Dynamic init.d service scanning with status detection
- Clean dark theme with inline CSS (no external dependencies)
- Quick stats: Services, Memory, Uptime, Network
- Active ports section for external services
- Responsive grid layouts for all screen sizes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Services tab to TUI displaying services from all mesh peers
- Implement get_peer_services() fetching via P2P API (port 7331/services)
- Add 60-second caching to avoid slow repeated API calls
- Group services into categories: Web/Proxy, Security, AI/ML, Containers, Apps
- Fix service endpoint URL: /services not /api/services
- Increase API timeout to 15s for comprehensive service scans
- Version bump to 1.2.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rewrite all views with KISS CSS (1200+ lines removed)
- Use unified cs-* CSS prefix with SecuBox theme variables
- Move CrowdSec from Security to Services menu
- Update navigation paths in all views and nav.js
- Add CSS loading in each view's load() function
- Fix Services menu as proper firstchild submenu
- Simplify dashboard.css from 950+ to 112 lines
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Console v1.1.0 with mesh participation as first-class peer
- Add announce command to register console on mesh devices
- Add mesh command to query P2P network status and peers
- Improve discovery with 3-phase approach (mesh peers, network scan, probe)
- Implement working update mechanism with SSH-based downloads
- Add proper Add Device modal dialog in Textual TUI
- Add Discover dialog with async progress display
- Show console identity in Mesh tab (node ID, name, IP, port)
- Auto-announce during discover and sync operations
- Add announce button and keybinding (m) in TUI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC `expect: { peers: [] }` extracts the array directly, so result
IS the peers array, not result.peers. Added Array.isArray() defensive
check for consistent handling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix register_self() to handle JSON whitespace with awk
- Update get_peers() to auto-register local node if peers list is empty
- Ensure node identity is initialized before querying peers
This ensures C3BOX always shows itself in the P2P Hub peers view.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add get_settings to read permissions and save_settings to write permissions
to fix RPC access denied error (-32002) on the settings page.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /chain/tip endpoint for blockchain tip query
- Add /catalog/console endpoint for version info
- Add symlinks for /api/ prefix compatibility
- Fix chain.json malformed JSON structure
Enables console to discover C3BOX device via mesh API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Console Enrollment section to settings with persistent key storage
- Integrate CrowdSec CSS with SecuBox global theme variables (--cyber-*)
- Fix modules.js install button and add installModule function
- Map cs-*, soc-*, sh-* CSS variables to SecuBox theme for consistency
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CAPI status now shows "Connected" when either enrolled or LAPI is available,
fixing misleading "Disconnected" display when CAPI is actually working.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove theme.js and themes/ directory (classic, cards, cyberpunk)
- Remove theme selector from settings page
- Use fixed 'cs-theme-classic' class in overview and settings views
- Simplify load() functions by removing theme.init() calls
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace hardcoded port 8180 with dynamic detection from credentials file
- Extract LAPI port from local_api_credentials.yaml URL
- Convert port to hex for /proc/net/tcp lookup
- Fix GeoIP database path detection (check /srv/crowdsec/data and /var/lib)
- Update default API URL fallback to 8090 (actual CrowdSec default)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a site's DNS doesn't point to our public IP, skip the external
HTTP check to avoid 5-second timeouts. This significantly speeds up
the get_hosting_status API call which was causing XHR timeouts in
the LuCI frontend.
Sites with DNS mismatch now show frontend_status: "dns_mismatch"
instead of timing out.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BusyBox ash does not support 'local' keyword outside of functions.
Removed 'local' from update_vhost case handler to fix "not in a function"
error that caused ubus calls to fail with no response.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add mDNS service announcement via avahi-publish for _secubox._tcp
- Add REST API endpoints on port 7331 (/api/peers, /api/status, /api/services)
- Add node self-registration to ensure local node visible in mesh view
- Add UCI defaults for uhttpd P2P API instance and firewall rules
- Bump secubox-p2p version to 0.2.0
fix(vhost-manager): Fix uninitialized variable syntax errors
- Add 'local' keyword to variable declarations on lines 606, 621, 693
fix(metablogizer,service-registry): Add HAProxy availability fallback
- Add haproxy_available() helper to check if HAProxy is running
- Gracefully skip HAProxy operations when service unavailable
- Store pending HAProxy config for later when service becomes available
- Prevent crashes when HAProxy container is stopped
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Set umask 022 before file operations
- chmod 644 immediately after base64 decode
- chmod 755 on site_path after each upload
- Prevents 403 Forbidden from restrictive permissions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Dynamic .onion address generation for hosted sites:
- enable_tor: Create Tor hidden service for a site
- disable_tor: Remove Tor hidden service
- get_tor_status: Get Tor status for all sites
- Sites now include onion_address and onion_url in listings
When enabled, sites are accessible via both:
- Public domain (https://domain.com)
- Tor hidden service (http://xxx.onion)
Also includes DNS resolution fix using Google DNS API.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
KISS approach to DNS resolution:
1. Primary: Use Google DNS API (https://dns.google/resolve)
- Most reliable, bypasses local resolver issues
2. Fallback: nslookup with tail -1 to skip DNS server line
3. Fallback: host command
The bug was parsing nslookup output which includes DNS server
address (127.0.0.1) before the actual resolved IP.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- apps.js: ZIP file upload with tree view file selection
- Client-side ZIP parsing for file list preview
- Interactive tree with checkboxes for file selection
- Select All / Deselect All / Python Only buttons
- Supports both .py and .zip file uploads
- api.js: Added previewZip() and uploadZip() RPC methods
- luci.streamlit RPCD:
- preview_zip: List ZIP contents with file sizes
- upload_zip: Extract selected files to app directory
- Automatic main .py file detection and registration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CDN Cache:
- Add file read permissions for cache, logs, and SSL dirs
- Add new RPCD methods to ACL (get_ca_cert, set_ssl_bump)
Tor Shield:
- Create tor-ip-update.sh for caching exit/real IPs
- Use --socks5-hostname for DNS through Tor
- Add cron job for periodic IP updates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CDN Cache:
- Migrate from nginx to Squid proxy for better caching
- Add aggressive caching rules for Windows Update, Linux repos, Steam, Apple
- Proper firewall integration via UCI (transparent proxy)
- Real-time stats from Squid access logs
Network Modes:
- Complete UI rework with MirrorBox dark theme
- 9 network modes with emojis and descriptions
- Dynamic CSS animations and modern styling
Fixes:
- Fix jshn boolean handling in secubox-recovery (1/0 vs true/false)
- Fix nDPId RPCD to use netifyd as fallback DPI provider
- Update media-flow and security-threats dashboards
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Overview Page (SOC Admin Landing):
- Architecture diagram with layer visualization
- Modular component cards with status indicators
- Network topology with animated orbital nodes
- System status grid with health indicators
- Development roadmap timeline
Profiles Page (Dynamic Cloning):
- Component readiness tracking with progress bars
- Quick presets for common configurations
- Package feeds management with toggles
- Saved profiles list with load/delete
- Clone & deploy actions (export, import, sync, push)
Menu Structure:
- Renamed P2P Hub to MirrorBox
- Added Overview as landing page
- Added Profiles for cloning management
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add new RPCD methods to luci.gitea for P2P mesh auto-setup:
- create_user: Create regular Gitea user via CLI
- generate_token: Generate access token with configurable scopes
- create_repo: Create repository for a user via admin API
These methods enable automated P2P mesh repository setup without
requiring manual token generation in Gitea web UI.
Requires lxc-attach package for container access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add autoCreateMeshRepo() function that automatically:
- Generates repo name from hostname: secubox-mesh-{hostname}
- Detects local Gitea server (gitea.local, git.local, etc.)
- Only prompts for access token on first use (one-time setup)
- Creates private repository with README
- Pushes initial mesh state immediately
Replace manual "➕ Create" button with "🚀 Auto Setup" for seamless
mesh repository initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add complete backend implementation for Gitea integration and local backups
with admin permissions:
RPCD Methods (luci.secubox-p2p):
- get_gitea_config / set_gitea_config - Gitea server configuration
- create_gitea_repo - Create new Gitea repository via API
- list_gitea_repos - List user's Gitea repositories
- get_gitea_commits - Fetch commit history
- push_gitea_backup - Push config/packages/scripts to Gitea
- pull_gitea_backup - Restore from Gitea commit
- create_local_backup - Create local backup snapshot
- list_local_backups - List available local backups
- restore_local_backup - Restore from local backup
UCI Config (secubox-p2p):
- gitea section: server_url, repo_name, access_token, auto_backup options
- backup section: backup_dir, max_backups, auto_cleanup
Frontend (hub.js):
- Updated createGiteaRepo() to use backend API
- Updated backup functions to use backend storage
- Added refreshGiteaCommits() for real API calls
- Load function now fetches Gitea config and backup list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add createGiteaRepo() function with modal interface for creating new Gitea
repositories directly from the P2P Hub. Users can configure server URL,
repo name, description, access token, and options (private, init README,
push current state).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Backup & Versioning panel with three cards:
- Mesh Auto-Backup: scheduled snapshots with configurable targets
- Test Cloning: clone config from any peer with auto-sync option
- Gitea History: connect to Gitea for version control and commit feed
- Add backup history modal with restore/delete actions
- Add Gitea configuration modal with server/repo/token settings
- Add formatTime helper for relative timestamps
- Add comprehensive CSS for backup panel, gitea commits, history modal
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add self-peer for local mesh testing without remote nodes
- Add gigogne (nested matryoshka) distribution mode with configurable depth
- Add distribution mode selector: gigogne, mono, ring, full-mesh
- Add visual indicators for self/gigogne peers on globe and peers panel
- Add test mode badge and clear test button
- Add rebuildGigogneStructure for dynamic mode switching
- Update CSS with gigogne/self peer styles and animations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Animated 3D globe with CSS transformations
- Peer nodes positioned around globe with depth sorting
- Master node at center with pulse animation
- Connection lines between master and peers
- Stars background with twinkle animation
- Health indicators with emoji status (💚💛❤️)
- Quick stats (Peers, Online, Services, Registry)
- Quick actions (Discover, Sync All, Add Peer)
- Responsive layout for mobile
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix "not a constructor" error by using baseclass.singleton()
pattern instead of baseclass.extend() with manual instantiation.
Theme module now exports a singleton directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Make Setup Wizard the first menu item in SecuBox (order 5)
- Add P2P Hub collaborative catalog API methods:
- Peer discovery and management
- Catalog sharing between SecuBox instances
- Settings for P2P sharing preferences
- Fix crowdsec-dashboard theme.js to return class instead of instance
- Update views to properly instantiate theme class
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add theme manager with selectable themes and profiles:
- classic: Professional SOC-style dark theme (default)
- cards: Modern card-based UI with gradients
- cyberpunk: Neon glow effects with terminal aesthetics
Profiles extend themes with custom options:
- default, soc, modern, hacker
Theme selection available in Settings > Appearance with live preview.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move CrowdSec dashboard from admin/services/crowdsec to
admin/secubox/security/crowdsec to integrate with SecuBox menu structure.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Installs all packages from the local feed in dependency order:
1. secubox-core and secubox-app (base)
2. secubox-app-* backend packages
3. luci-app-* frontend packages
4. luci-theme-* themes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix recursive inclusion bug where secubox-app-bonus was including itself
causing 1GB package size (now 7.5MB with 73 packages)
- Fix Packages index generation to strip Source/SourceName/SourceDateEpoch/URL
fields that caused opkg parsing issues
- Add rebuild_bonus_package() to local-build.sh for proper feed embedding
- Update secubox-feed install command to handle local dependencies from files
(workaround for opkg signature bug with file:// URLs)
- Clean up libc dependency stripping in Packages generation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Even rpcd, bash, jsonfilter, jq depend on libc themselves. Since these
packages are always present on a working OpenWrt/SecuBox system, we should
not declare any dependencies at all.
- secubox-core 0.10.0-r9: DEPENDS:= (empty)
- luci-app-secubox-admin 1.0.0-r19: LUCI_DEPENDS:= (empty)
This prevents opkg from trying to resolve any feed packages and their
cascading libc dependencies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The OpenWrt SDK automatically adds libc as a dependency to all packages,
even pure shell/JavaScript packages that don't need it. This causes
opkg installation failures when the local feed version of libc doesn't
match the router's installed version.
Solution: Add PKG_FLAGS:=nonshared to Makefiles of arch-independent
packages (secubox-core, luci-app-secubox-admin, secubox-app-bonus).
This tells the build system these packages don't link against libc.
Changes:
- secubox-core: 0.10.0-r6 → r7 with PKG_FLAGS:=nonshared
- luci-app-secubox-admin: 1.0.0-r17 → r18 with PKG_FLAGS:=nonshared
- secubox-app-bonus: 0.3.0-r1 → r2 with PKG_FLAGS:=nonshared
- Regenerated Packages index without libc dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add four major features to enhance SecuBox AppStore:
1. Feed Source Management:
- Feed types: published, unpublished, development
- Share tokens for private feed access
- CLI: secubox feed list/add/share/import
- LuCI: Feed type badges and share URLs in catalog-sources
2. Profile Export/Import:
- Export configurations with feed sources embedded
- Import from URL or file with merge/replace modes
- CLI: secubox profile export/import/share
- LuCI: New profiles.js view with export/import dialogs
3. Skill System:
- Capability discovery from module catalogs
- Quality indicators based on provider count
- CLI: secubox skill list/providers/install/check
- LuCI: New skills.js view with provider browser
4. Feedback Loop:
- Issue reporting and resolution tracking
- Search existing resolutions
- CLI: secubox feedback report/resolve/search/list
- LuCI: New feedback.js view for knowledge base
Technical changes:
- RPCD backend with 17 new API methods
- POSIX shell compatibility fixes (ESC via printf, tr A-Z a-z)
- LuCI menu entries for new views
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove all LuCI dependencies (luci-base, rpcd, luci-lib-jsonc)
- Remove LuCI-specific files (RPCD backend, ACL, menu, JS views)
- Package now only provides local opkg feed and documentation
- Remove Packages.sig to avoid signature verification errors
- Update local-build.sh to skip signature generation for local feeds
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update local-build.sh to remove libc from Packages index
- Prevents opkg architecture mismatch errors on install
- Regenerate secubox-feed with 74 packages
- Update RPCD scripts for lyrion, mailinabox, metablogizer, nextcloud
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add RPCD methods to mitmproxy: settings, save_settings, set_mode,
setup_firewall, clear_firewall
- Add apply_now parameter to tor-shield save_settings to restart
service and apply iptables rules immediately
- Update ACL files with new permissions
- Add Save & Apply button to tor-shield settings page
- Update api.js files to use correct RPCD method signatures
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The direct services provider was calling jsonfilter in a loop for each
listening port (~40 ports), causing XHR timeouts in the UI.
Changes:
- Disable direct provider by default (set enabled=0)
- Add limit of 20 services if enabled
- Skip common system ports (22, 53, 67, 68, 123, 547, 953)
- Add note about enabling via UCI if needed
The real services come from HAProxy vhosts and UCI published services.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Run Lyrion as nobody (uid 65534) via LXC init.uid/gid settings
- Use cgroup2 memory limit format (lxc.cgroup2.memory.max)
- Convert memory limit string (1G, 256M) to bytes for cgroup2
- Skip opkg install if LXC binaries already exist
- Set proper file ownership during rootfs creation
- Remove su command from start.sh (handled by LXC config)
Fixes the container crash loop caused by Lyrion refusing to run as root.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tor Shield:
- Store current_preset in UCI when enabling with preset
- Return current_preset in status response
- Initialize currentPreset from stored UCI value on page load
Security Threats:
- Fix get_security_stats() firewall packet counting
- Use correct nftables chain names (input_wan, handle_reject)
- Fix grep -c exit code issue (returns 1 when no matches)
- Improve numeric validation (use tr -cd to strip non-digits)
- Add fallbacks for HAProxy socket paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- refresh_ips now fetches reverse DNS for exit IP
- Status includes exit_hostname from cache
- Dashboard displays hostname below exit IP
- get_exit_ip also returns hostname
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The expect: { success: false } was causing LuCI RPC to return false
instead of the actual response. Changed all expect declarations to
empty objects to get raw API responses.
Also improved error messages to show actual response for debugging.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Clicking a preset card now enables/restarts Tor with that preset
- Previously it only selected the preset for next toggle
- Added better error handling for toggle and preset changes
- Page reloads after successful preset change
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The toggle handler was receiving status captured at render time which
could be stale due to polling. Now fetches fresh status before deciding
to enable or disable, and does a full page reload after action.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The cumulative impact summary was showing zeros because it only checked
the plugins catalog. Now also counts:
- HAProxy vhosts directly from UCI
- Running LXC containers
- Running Docker containers
- Firewall WAN ACCEPT rules with ports
- DNSmasq entries
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix disabled buttons in Network Tweaks using conditional rendering
- Change AdGuard Home ports to avoid conflicts (web: 3003, dns: 5353)
- Add DNS & Proxy link from Tor Shield to Network Tweaks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add always-visible toggle switch at top of dashboard
- Clear visual indication: green when protected, red when exposed
- Shows protection status text and toggle switch
- Easier one-click enable/disable of Tor protection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AdGuard Home status card with enable/disable and Open UI button
- Add setAdGuardEnabled RPCD method for Docker container control
- Rename section to "DNS & Proxy Services"
- Responsive grid layout for 3 service cards
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CDN cache status card with enable/disable and restart buttons
- Add WPAD auto-proxy card with enable/disable toggle
- Add getProxyStatus, getWpadStatus, setWpadEnabled RPCD methods
- Move menu to Services section
- Update ACL for CDN cache and WPAD control
Also fixes:
- security-threats: Fix HAProxy socket path for connection stats
- tor-shield: Add missing ACL methods for excluded destinations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_excluded_destinations() method to list bypassed destinations
- Add add_excluded_destination() to exclude IPs/CIDRs/domains from Tor
- Add remove_excluded_destination() to remove exclusions
- Add apply_exclusions() to restart tor-shield with new rules
- Domain resolution attempts to get IP for iptables compatibility
- Existing private network CIDRs (192.168/10/172.16/127) are default excluded
Also includes metablogizer fixes:
- reload_haproxy() helper function
- Server address uses 127.0.0.1 for uhttpd backends
- fix_permissions() on file uploads
PKG_RELEASE: tor-shield=3, metablogizer=3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add reload_haproxy() helper function for consistent reloads
- Use 127.0.0.1 for uhttpd backend address instead of 192.168.255.1
- Call fix_permissions() on upload_file to ensure correct file access
- Update delete_site to use reload_haproxy helper
- Bump PKG_RELEASE to 3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BREAKING: Default policy changed from quarantine to open
- Disabled by default (was enabled)
- Default policy: open (was quarantine - blocked new devices!)
- Auto-zoning: disabled by default
- Auto-parking zone: lan_private (was guest)
- Night block schedule: disabled by default
- Threat auto-ban: disabled by default
Safety mechanisms added:
- MAX_BLOCKED_DEVICES limit (10) prevents mass blocking
- check_safety_limit() function validates before blocking
- clear_all_cg_rules() emergency function via RPCD
- safety_status RPCD method to check current state
UI improvements:
- Added warnings for restrictive policies
- Reordered options (safe options first)
- Clearer descriptions of consequences
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move 9 service apps from admin/secubox/services/ to admin/services/:
- localai, lyrion, magicmirror2, mailinabox, mmpm
- nextcloud, ollama, vhost-manager, mitmproxy
Services now appear under standard LuCI Services menu for consistency.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix LAPI status check to dynamically read port from config
- Previously hardcoded wrong port (8080 vs 8180)
- Add comprehensive SecuBox feed documentation to README
- Document opkg configuration, HAProxy publishing, troubleshooting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_network_info RPCD method:
- Public IPv4/IPv6 detection via external services
- Reverse DNS hostname lookup
- External port accessibility test (upstream router/ISP check)
- Enhance check_service_health:
- Compare DNS resolution against actual public IP
- Detect private IP misconfiguration (192.168.x.x pointing)
- Test external port reachability
- Add Network Connectivity panel to dashboard:
- Shows public IPs with hostnames
- External port 80/443 accessibility status
- Local firewall and HAProxy status
- Improve URL Readiness Checker:
- Display public IP info
- Show specific recommendations with IP addresses
- Detect and explain DNS pointing to private IP
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document all features including:
- Health monitoring and URL readiness checker
- Service publishing workflow
- Health check API usage
- Troubleshooting guide for common issues
- UCI configuration reference
- RPCD methods reference
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add health check RPCD methods:
- check_service_health: Check DNS, cert, firewall for single domain
- check_all_health: Batch check all published services
- Add URL Readiness Checker wizard card to dashboard:
- Check if domain DNS resolves correctly
- Verify firewall ports 80/443 are open
- Check SSL certificate status
- Show actionable recommendations
- Display inline health status badges on service rows:
- DNS resolution status (ok/failed)
- Certificate expiry (ok/warning/critical/expired)
- Add health summary bar showing overall system status
- Add per-service health check button
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatically creates firewall rules for HAProxy when:
- Requesting a certificate (haproxyctl cert add)
- Publishing a service with a domain (service-registry)
Added firewall rules:
- HAProxy-HTTP: Allow port 80 from WAN (ACME challenges)
- HAProxy-HTTPS: Allow port 443 from WAN (HTTPS traffic)
Rules are only created if they don't exist, preventing duplicates.
Firewall reloads automatically after rule creation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Certificate issuance now uses webroot mode instead of standalone:
- HAProxy routes /.well-known/acme-challenge/ to local ACME webserver
- Added acme_challenge backend on port 8402
- Uses busybox httpd to serve challenge files
- No HAProxy restart required during certificate requests
- Config auto-regenerates before cert request to ensure ACME backend
This eliminates downtime during certificate issuance and allows
multiple concurrent certificate requests.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HAProxy Certificates:
- Add async certificate request API (start_cert_request, get_cert_task)
- Non-blocking ACME requests with background processing
- Real-time progress tracking with phases (starting → validating → requesting → verifying → complete)
- Add staging vs production mode toggle for ACME
- New modern UI with visual progress indicators
- Task persistence and polling support
Service Registry:
- Fix QR codes using api.qrserver.com (Google Charts deprecated)
- Fix form prefill with proper _new section selectors
- Add change event dispatch for LuCI form bindings
- Update landing page generator with working QR API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove expect clause from RPC declarations to get raw response
- Add proper error handling with catch blocks for all RPC calls
- Fix landing page generator to chmod 644 after generation
- Fixes "No Services Found" issue in dashboard
- Fixes "Forbidden" error when accessing landing page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement Service Registry LuCI app for unified service management:
- RPCD backend aggregating services from HAProxy, Tor, netstat, LXC
- One-click publish to clearnet (HAProxy+ACME) and/or Tor hidden service
- Static landing page generator with QR codes for all URLs
- LuCI dashboard with service grid, quick publish form
- CLI tool (secubox-registry) for command-line management
- Share buttons for X, Telegram, WhatsApp
RPCD methods: list_services, publish_service, unpublish_service,
generate_landing_page, get_qr_data, list_categories
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix tor-shield/api.js: Use baseclass.extend() pattern correctly
- Fix tor-shield ACL: Add missing 'restart' write permission
- Fix secubox-app-tor: Disable conflicting default tor init in postinst
- Move metablogizer menu from secubox/services to admin/services
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC declaration with `expect: { sites: [] }` extracts the array
directly, so data[1] IS the sites array, not an object with .sites property.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /etc/config/metablogizer with default settings
- Update Makefile to install config as conffile
- Fixes 404 error when accessing MetaBlogizer in LuCI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- CrowdSec Dashboard: Add bouncer_count, geoip_enabled, acquisition_count,
scenario_count fields to get_overview and get_health_check RPCD functions
- MetaBlogizer: Fix menu path to admin/secubox/services/metablogizer
- Portal: Add MetaBlogizer and Gitea to apps registry for services section
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The dashboard was showing 0 decisions because `cscli decisions list`
only returns local decisions, not CAPI blocklist entries.
Fixed by:
- Parsing CAPI decision counts from `cscli metrics` output
- Added separate local_decisions and capi_decisions fields
- Updated overview to show "CAPI Blocklist" and "Local Bans" separately
- Fixed get_capi_metrics to use metrics parsing instead of decisions list
This correctly shows ~15,000 CAPI blocklist IPs instead of 0.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change evt.Line contains -> evt.Line.Raw contains in parsers
(pipeline.Line type requires .Raw accessor for string operations)
- Remove invalid filter: field from acquisition configs
(filter belongs in parsers, not acquisition files)
Fixes CrowdSec v1.7.6 startup failures.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New luci-app-metablogizer package replacing metabolizer with simplified
static site publishing:
- RPCD backend with create/delete/sync site methods
- Auto HAProxy vhost creation with SSL/ACME
- Nginx LXC container integration for serving static files
- Git sync from Gitea repositories
- QR code generation for published URLs
- Social share buttons (Twitter, LinkedIn, Facebook, Telegram, WhatsApp, Email)
- Drag-and-drop file upload UI
- SecuBox light theme styling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Bump CrowdSec version from 1.7.4 to 1.7.6
- Add modernc.org/sqlite v1.34.2 vendor module (Go 1.21 compatible)
- Patch strings.SplitSeq in hubtest for Go 1.23 compatibility
- Add replace directive for sqlite to use vendored version
Built and tested: crowdsec_1.7.6-r1_aarch64_cortex-a72.ipk (80MB)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- README.md: Update to v0.16.0 with all 38 modules categorized
- CHANGELOG.md: Create comprehensive changelog (v0.12.0-v0.16.0)
- CLAUDE.md: Add toolchain build rules for Go/CGO packages
- secubox-tools/README.md: Add SDK vs toolchain build guidance
- TODO-ANALYSE.md: Mark completed tasks, update health score
- HISTORY.md: Document ARM64 toolchain discovery, multi-instance
- dev-status-widget.js: Update stats (38 modules, 1500 commits)
SDK builds produce LSE atomics that crash on some ARM64 CPUs.
Go/CGO packages (crowdsec, netifyd) must use full toolchain.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CrowdSec:
- Change LAPI default port from 8080 to 8180 (avoid Docker conflict)
- Update bouncer config, init script, and RPCD dashboard
- Fix port detection hex value (1FF4 for 8180)
Streamlit:
- Complete rewrite with folder-based app structure
- Multi-instance support (multiple apps on different ports)
- Gitea integration (clone, pull, setup commands)
- Auto-install requirements.txt with hash-based caching
HexoJS:
- Multi-instance support with folder structure
- Multiple blog instances on different ports
HAProxy:
- Auto-generate fallback backends (luci, apps, default_luci)
- Add --server letsencrypt to ACME commands
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add publish_to_www RPCD method to publish static files to /www/blog
- Add Build & Publish card in sync.js with configurable publish path
- Add generate RPC call for building site
- Fix file permissions for all RPCD scripts and init.d scripts
- Bump luci-app-hexojs to 1.0.0-r3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Streamlit Instances:
- Add Publish button with HAProxy integration (uses instance port)
- Add Edit dialog for modifying instance settings
- Replace enable/disable buttons with checkbox
- Get LAN IP dynamically from status data
- Bump luci-app-streamlit to r8
HAProxy:
- Add haproxy-acme-cron script for background cert processing
- Cron runs every 5 minutes to issue pending ACME certificates
- Prevents UI blocking during certificate issuance
- Bump secubox-app-haproxy to r19
RPCD:
- Fix json_error to return consistent format with json_success
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix enabled/disabled select showing wrong value
- Normalize memory limit values (1G/2G/4G -> 1024M/2048M/4096M)
- Fix boolean value handling for headless and usage stats
- Use Object.assign for conditional selected attribute
- Bump to r6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Instances tab to LuCI Streamlit dashboard
- RPCD backend: list/add/remove/enable/disable instances
- API module: instance management methods
- UI: Instance table with status, port, enable/disable/remove actions
- Add Instance form with app selector and auto port assignment
- Apply & Restart button to apply instance changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move nested functions outside parent functions (ash doesn't support local functions)
- Fix _build_instance_entry and _print_instance_json syntax
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add multi-instance mode: run multiple apps on different ports
- New UCI config structure with 'instance' sections
- Container starts multiple streamlit processes via STREAMLIT_INSTANCES env
- CLI commands: instance list/add/remove/enable/disable
- Each instance has its own port, requirements auto-install
- Backward compatible: single-app mode still works
- Bumped to 1.0.0-r4
Example config:
config instance 'dashboard'
option app 'dashboard.py'
option port '8502'
option enabled '1'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-detect and install app-specific requirements on container start
- Supports: <app>.requirements.txt, <app>_requirements.txt, requirements.txt
- Uses hash-based caching to avoid reinstalling on each restart
- Bumped to 1.0.0-r3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes:
- HAProxy: Prevent duplicate server names when both inline and separate
server UCI sections exist for same backend
- Streamlit: Force --server.headless=true in start script (required for server)
- Dashboard: Optimize get_dashboard_data RPC call (6.56s → 0.09s) by using
fast catalog counting instead of slow appstore list command
- Exposure: Add themed dashboard with SecuBox styling
- ACL: Add missing RPCD permissions for various LuCI apps
Version bumps:
- luci-app-exposure: 1.0.0-r3
- secubox-core: 0.10.0-r5
- secubox-app-haproxy: 1.0.0-r18
- secubox-app-streamlit: 1.0.0-r2
- Portal: v0.15.51
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cert_is_production() to detect Let's Encrypt staging certificates
- Add cert_validate_public() to verify certificate publicly via curl/openssl
- Add cert_info() to display certificate details (domain, issuer, dates)
- Add cmd_cert_verify command for on-demand certificate verification
- Update cmd_cert_list to show staging/production status with icons
- Update cmd_cert_add to warn about staging mode and verify after issuance
- Bump package release to r16
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace buttons with toggle switches for enabling/disabling exposures
- Show current exposure status with colored indicators
- Load and display Tor hidden services and SSL backends status
- Add stats cards for exposable services, Tor services, and SSL backends
- Modal dialogs for configuring exposure parameters on toggle
- Bump luci-app-exposure to 1.0.0-r2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix HAProxy certificate key naming (.key -> .crt.key) for directory loading
- Add auto-fix in container startup script for existing certificates
- Add list_exposed_services RPC method to fetch services from secubox-exposure
- Add dynamic port scanning for running services discovery
- Add "Quick Select" dropdown in Add Server modal for service auto-fill
- Bump luci-app-haproxy to 1.0.0-r8
- Bump secubox-app-haproxy to 1.0.0-r15
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- HAProxy overview: Add prominent emergency banner showing service status
with quick health indicators (Container/HAProxy/Config) and one-click
Restart/Start/Stop buttons
- SecuBox dashboard: Add Critical Services Quick Restart section with
buttons for HAProxy, CrowdSec, Tor Shield, and Gitea
- Metabolizer config: Fix portal_path to /www/blog
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Exposure Manager:
- Fix RPCD subshell issues in status and ssl_list methods
- Fix JS views to handle both array and object API responses
MagicMirror2:
- Change default port from 8082 to 8085 (avoid CyberFeed conflict)
- Update mm2ctl, RPCD, settings.js, dashboard.js, config
Tor Shield:
- Add restart method to RPCD and API
- Add health status minicard (Service, Bootstrap, DNS, Kill Switch)
Portal:
- Add 'active-ports' section for detected services
- Separate portal apps (Services) from detected ports (Active Ports)
Service Detection:
- Prioritize port-based identification over process name
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- RPCD: Use temp file for scan to avoid pipe subshell issues
- api.js: Use baseclass.extend() for proper LuCI module pattern
- Menu: Remove UCI dependency that caused 404
- Makefile: Make haproxy/tor optional dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New features in this release:
- Service Exposure integration in network section
- Security stats on dashboard (WAN drops, firewall rejects, CrowdSec)
- Threat Monitor in security cards
- Fixed http:// URLs for local services
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New app entry for service-exposure in portal network apps:
- Port conflict management
- Tor hidden services
- HAProxy SSL backends
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New unified tool for service exposure management:
- Port conflict detection and resolution (scan, conflicts, fix-port)
- Dynamic Tor hidden service management (tor add/list/remove)
- HAProxy SSL reverse proxy configuration (ssl add/list/remove)
Commands:
secubox-exposure scan # List listening services
secubox-exposure conflicts # Detect port collisions
secubox-exposure tor add gitea # Create .onion for service
secubox-exposure ssl add svc domain # Add HAProxy SSL backend
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Service detection now prioritizes process name matching over port-based
detection for more accurate identification of netifyd, streamlit,
cyberfeed, metabolizer, magicmirror, and picobrew services.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Services in LXC/Docker containers don't have SSL certificates,
so always use http:// instead of inheriting the browser's protocol.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add threat-monitor app to security section in portal.js
- Add security stats RPC call (get_security_stats)
- Display packets blocked and alerts on dashboard
- Add Threat Monitor to featured quick access apps
- Show WAN dropped + firewall rejects in events section
- Link to Threat Monitor dashboard from events
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Security Stats:
- Add get_security_stats RPCD method for quick overview
- Track WAN drops, firewall rejects, CrowdSec bans
- Add secubox-stats CLI tool for quick stats check
Gitea Mirror Commands:
- Add mirror-sync to trigger mirror repository sync
- Add mirror-list to show all mirrored repos
- Add mirror-create to create new mirrors from GitHub URLs
- Add repo-list to list all repositories
- Requires API token: uci set gitea.main.api_token=<token>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- haproxy: Add explicit restart_service function
- tor-shield: Add explicit restart_service function
- wireguard-dashboard/qrcode.js: Use baseclass.extend() pattern
to fix "factory yields invalid constructor" error
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HAProxy requires certificate files to contain both the fullchain
(cert + intermediate CA) and the private key concatenated together.
Changes:
- haproxyctl: Fix cert_add to create combined .pem files
- haproxy-sync-certs: New script to sync ACME certs to HAProxy format
- haproxy.sh: ACME deploy hook for HAProxy
- init.d: Sync certs before starting HAProxy
- Makefile: Install new scripts, add cron job for cert sync
This fixes the "No Private Key found" error when HAProxy tries to
load certificates that only contain the fullchain without the key.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC expect clause unwraps responses - when `expect: { peers: [] }`
is used, the response `{peers: [...]}` gets unwrapped to just `[...]`.
Fixed:
- api.js: getAllData and getMonitoringData now handle both array
and object formats for peers, interfaces, and rates
- overview.js: render and polling functions now safely unwrap
data that may be array or nested object
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
RPCD backend:
- Fix critical json_init bug: variables must be extracted BEFORE
json_init() which wipes the loaded JSON. Affected functions:
save_settings, do_enable, set_bridges, add/remove_hidden_service
- Fix process detection: use pgrep instead of pid file
- Fix uptime calculation: get PID from pgrep, not pid file
- Fix RPC expect unwrapping in getDashboardData for presets
Init script:
- Remove PidFile directive (procd manages the process)
- Clean up stale files before starting to avoid permission issues
- Set proper ownership on torrc after generation
- Fix iptables chain creation to handle "already exists" gracefully
- Remove from OUTPUT chain before attempting chain deletion
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC expect clause unwraps the response, so circuits data may be
an array directly rather than an object with circuits property.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix subshell bug in get_circuits (pipe loses JSON state)
- Add has_control flag to status for frontend awareness
- Fix UseBridges without bridge lines causing Tor to fail
- Fix hidden service directory ownership (tor:tor)
- Change log output from file to syslog
- Fix run directory ownership and permissions (700)
- Add CookieAuthentication for control socket auth
- Use socat instead of nc (BusyBox lacks Unix socket support)
- Add socat as package dependency
- Optimize duplicate curl calls in status check
- Use fallback IP services for real_ip detection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_services RPCD method to detect listening TCP services
- Map known ports to service names, icons, and categories
- Display clickable service cards in portal Services tab
- Services link directly to their URLs (e.g., :3000 for Gitea)
- Filter to show only externally accessible services with URLs
- Add ACL permissions for portal and admin apps
Detected services include: Gitea, HexoJS, CyberFeed, Streamlit,
HAProxy Stats, Netifyd, LuCI, Lyrion, and more.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
HexoJS now serves dynamically on :4000 via HAProxy vhost routing.
- Disabled auto_publish in metabolizer
- Disabled portal in hexojs
- /www stays free for SecuBox portal and other apps
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'generate' as alias for 'build' command
- Rename cmd_publish for drafts to cmd_publish_draft
- Fix duplicate cmd_publish functions
- Add portal config section with /www/blog path
- publish draft <slug> for drafts, publish for portal
- Metabolizer integration now working
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- RPCD _add_backend now parses inline 'server' option format
- Servers embedded in backend response with inline flag
- update_server converts inline servers to separate UCI sections
- delete_server handles both inline and separate server sections
- API and UI pass inline flag for proper handling
Fixes server port editing in LuCI backends interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add showEditVhostModal() for editing virtual host properties
- Add showEditBackendModal() for editing backend configuration
- Add showEditServerModal() for editing server properties
- Modern card-based UI with inline edit/delete actions
- Toggle enable/disable for backends
- Fix haproxyctl to read server option from backend UCI sections
- Add debug logging to container startup script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change all hardcoded /blog/ paths to use / as root:
Theme configuration:
- _config.yml: Menu paths now /cybersecurity/ instead of /blog/cybersecurity/
- Blog submenu path changed to /categories/
Layout templates:
- post.ejs: Category link uses url_for with root path
- index.ejs: "Voir le blog" links to /categories/
- category.ejs: Breadcrumb and back links use /categories/
Scripts:
- dynamic-blog.js: Category paths now /{slug}/ instead of /blog/{slug}/
- Menu blog path changed to /categories/
Presets:
- tech.yml: Menu paths updated
- portfolio.yml: Blog link updated
hexoctl:
- Default portal_path changed from /www/blog to /www
- Help text updated
This allows the blog to be served from the root URL with categories
at /{category}/ paths.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change pidfile from haproxy-lxc.pid to haproxy.pid for consistency
with the actual container name.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change container references from 'haproxy-lxc' to 'haproxy' to match
the actual container name used by secubox-app-haproxy. This fixes
the LuCI status view showing container_running: false.
Fixes affected methods:
- method_status: container existence and state checks
- method_get_stats: container running check
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Templates now properly use Hexo's url_for() helper:
- apps.ejs: navigation links
- category.ejs: breadcrumb, apps, services, blog links
- showcase.ejs: contact, portfolio, apps, services links
This ensures all links work correctly when root is set to a
subdirectory (e.g., /blog/ instead of /)
Bumped release to r5
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Calculate web root from portal path (e.g., /www/blog → /blog/)
- Update _config.yml root setting before regenerating
- Run hexo clean && generate to apply new root
- Bumped release to r4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Piped while loop runs in subshell, JSON additions don't persist
- Use temp file + redirect to avoid subshell issue
- Also fix list_backups with same pattern
- Bumped release to r2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Server now binds to 0.0.0.0 instead of localhost for external access
- Added publish command to copy static files to /www/blog/
- Startup script always regenerates to ensure correct binding
- Bumped release to r3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add gitea_status, gitea_sync, gitea_clone, gitea_save_config RPCD methods
- Add Gitea section to sync.js with config form and sync buttons
- Update ACL for new Gitea methods
- Fix luci-app-metabolizer install section for RPCD executable
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove yaml import, use simple string parsing for front matter
- Remove dependency on host metabolizerctl
- Use environment variables for paths (METABOLIZER_CONTENT)
- Remove switch_page calls that fail in container
- CMS now works standalone inside Streamlit container
- Bump to r2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Export PATH at top of startup script for git binary
- Export HOME=/data for proper environment
- Set SCRIPT_TYPE=sh in app.ini (no bash in Alpine)
- Bump to r5
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Alpine's adduser wasn't creating the group properly, causing
chown git:git to fail with "unknown group".
- Add explicit addgroup -g 1000 git before adduser
- Use -G git flag to assign user to the group
- Bump to r4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use /bin/sh instead of /bin/bash for git user shell
- Check for su-exec binary instead of marker file for deps
- Always recreate git user on startup (doesn't persist in container)
- Set explicit UID 1000 for git user
- Bump release to r3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create /data, /opt, /run directories in rootfs during install
- Simplify mount entries (single /data mount)
- Ensure host data directories exist before creating LXC config
- Install dependencies (git, su-exec, etc.) on first container run
- Create required subdirectories in startup script
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add is_installed() and is_running() checks to init.d
- Show reason when service not running (disabled/not installed)
- Enable gitea by default in UCI config
- Require installation before starting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Metabolizer Blog Pipeline - integrated CMS for SecuBox:
- Gitea: Mirror GitHub repos, store blog content
- Streamlit: CMS app with markdown editor and live preview
- HexoJS: Static site generator (clean → generate → publish)
- Webhooks: Auto-rebuild on git push
- Portal: Static blog served at /blog/
Pipeline: Edit in Streamlit CMS → Push to Gitea → Build with Hexo → Publish
Packages:
- secubox-app-streamlit: Streamlit server with LXC container
- luci-app-streamlit: LuCI dashboard for Streamlit apps
- secubox-app-metabolizer: CMS pipeline orchestrator
CMS Features:
- Two-column markdown editor with live preview
- YAML front matter editor
- Post management (drafts, publish, unpublish)
- Media library with image upload
- Git sync and Hexo build controls
- Cyberpunk theme styling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Amber (#ffb000) for titles, borders, hover effects
- Green (#33ff33) for dates, sources, navigation
- Gradient timeline line (amber → green → amber)
- Glow effects on text and borders
- Audio items highlighted in green
- Status bar with item count and sync time
- Emojified content from AWK parser preserved
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Left panel (1/3): CRT monitor style with:
- Phosphor green text with glow effect
- Scanlines overlay
- Screen curvature effect
- Power LED with pulse animation
- VT323 monospace font
- Scrollable latest 15 items
- Right panel (2/3): Standard cyberpunk timeline with:
- Vertical timeline with neon gradient line
- Date grouping
- Audio player support
- Source badges
- Responsive: stacks vertically on mobile (CRT on top)
- Auto-refresh every 3 minutes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Star Wars opening crawl style timeline with:
- Starfield background with twinkling stars
- "A long time ago in a network far, far away...." intro
- CYBERFEED logo zoom animation
- 3D perspective text crawl (rotateX transform)
- Yellow text (#ffd700) with cyan accents (#0ff)
- Auto-refresh every 3 minutes
- Controls: PAUSE, RESET, HOME, REFRESH
- Fix LuCI API array handling in getFeeds/getItems:
- RPC `expect` declarations auto-extract nested properties
- Response IS the array, not res.feeds/res.items
- Add Array.isArray check to handle both cases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move emoji injection inside AWK parser to avoid corrupting JSON keys
- Use grep -o | wc -l for accurate item count on single-line JSON
- Emojis now only applied to title and desc fields, not URLs or keys
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rewrite RSS parser to use BusyBox-compatible AWK (no capture groups)
- Use extract_tag() helper with substr() instead of match() capture
- Use extract_attr() helper for XML attribute extraction
- Fix settings.js select elements to properly set initial value
- Use sel.value = ... instead of selected attribute
- Add new UCI config options for enhanced features:
- download_media, media_dir, history_file, generate_timeline
- Bump versions: secubox-app-cyberfeed 0.2.1, luci-app-cyberfeed 0.1.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Radio France presets (France Inter, France Culture, France Info, FIP, Mouv)
- Add international radio (BBC World, NPR)
- Add tech podcasts (Darknet Diaries, Changelog, Syntax.fm)
- Add 'radio' category to feed selector
- One-click quick-add buttons for all radio presets
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- get_feeds now returns {"feeds": [...]} instead of raw array
- get_items now returns {"items": [...]} instead of raw array
- Updated api.js to extract arrays from wrapped responses
- Fixes feed list not displaying in LuCI dashboard
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New packages:
- secubox-app-cyberfeed: Core RSS aggregator service
- Pure shell script, OpenWrt compatible
- Cyberpunk emoji injection based on content keywords
- Caching with configurable TTL
- JSON and HTML output with neon/glitch effects
- RSS-Bridge support for social media (Facebook, Twitter, YouTube)
- luci-app-cyberfeed: LuCI dashboard with cyberpunk theme
- Dashboard with stats, quick actions, recent items
- Feed management with add/delete
- RSS-Bridge templates for easy social media setup
- Preview with category filtering
- Settings page for service configuration
Features:
- Auto-emojification (security, tech, mystical themes)
- Dark neon UI with scanlines and glitch effects
- RSS-Bridge integration for Facebook/Twitter/YouTube
- Category-based filtering
- Auto-refresh via cron (5 min default)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add pollRegistered flag to prevent duplicate poll registration
- Fix refreshDashboard to use replaceChild instead of dom.content
- Build content arrays explicitly to avoid null values in arrays
- Fix disabled attribute handling for action buttons
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix TypeError "haproxy.api factory yields invalid constructor" by
refactoring api.js to use correct LuCI module pattern:
- Define RPC calls at module level with rpc.declare()
- Reference them in baseclass.extend() object
- Add getDashboardData helper function at module level
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add secubox-app-haproxy: LXC-containerized HAProxy service
- Alpine Linux container with HAProxy
- Multi-certificate SSL/TLS termination with SNI routing
- ACME/Let's Encrypt auto-renewal
- Virtual hosts management
- Backend health checks and load balancing
- Add luci-app-haproxy: Full LuCI web interface
- Overview dashboard with service status
- Virtual hosts management with SSL options
- Backends and servers configuration
- SSL certificate management (ACME + import)
- ACLs and URL-based routing rules
- Statistics dashboard and logs
- Settings for ports, timeouts, ACME
- Update luci-app-secubox-portal:
- Add Services category with HAProxy, HexoJS, PicoBrew,
Tor Shield, Jellyfin, Home Assistant, AdGuard Home, Nextcloud
- Make portal dynamic - only shows installed apps
- Add empty state UI for sections with no apps
- Remove 404 errors for uninstalled apps
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add start-hexo.sh script as container init command
- Set PATH properly for hexo CLI in lxc_exec()
- Container now starts Hexo server automatically on boot
- Falls back to tail -f /dev/null if no site exists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox-app-hexojs: LXC-containerized Hexo service with Node.js
- hexoctl control script for container/site management
- Bundled CyberMind theme with dark/light mode
- Theme presets (minimal, tech, portfolio)
- Post/page scaffolds
- luci-app-hexojs: Full CMS dashboard
- Overview with stats and quick actions
- Post editor with Markdown toolbar and preview
- Media library browser
- Categories and tags management
- Apps portfolio for CyberMind theme
- Build and deploy to GitHub Pages
- GitHub Sync wizard (clone, pull, push)
- Theme configuration and presets
- Site settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add secubox-app-tor (backend) and luci-app-tor-shield (frontend) packages
for Tor anonymization on OpenWrt.
Backend features:
- UCI configuration with presets (anonymous, selective, censored)
- procd init script with iptables transparent proxy
- torctl CLI tool for status, enable/disable, circuits, leak-test
- DNS over Tor and kill switch support
- Hidden services and bridge management
Frontend features:
- Modern purple/onion themed dashboard
- One-click master toggle with visual status
- Real-time circuit visualization (Guard -> Middle -> Exit)
- Hidden services (.onion) management with copy/QR
- Bridge configuration (obfs4, snowflake, meek-azure)
- Leak detection tests
- Advanced settings for ports and exit node restrictions
Note: LuCI package renamed to luci-app-tor-shield to avoid conflict
with existing luci-app-tor package in OpenWrt LuCI feeds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Flask 1.1.2 requires specific old versions of dependencies:
- Jinja2==2.11.3 (escape moved in 3.1)
- markupsafe==1.1.1
- itsdangerous==1.1.0 (json removed in 2.x)
- Werkzeug==1.0.1
- click==7.1.2
- pybeerxml<2.0.0 (Parser import changed in 2.x)
- marshmallow<4.0.0
Also:
- Use pip-installed package instead of git repo mount
- Simplify LXC mounts to just data directories
Tested and working on OpenWrt 24.10.5.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add two new packages for self-hosted brewing controller support:
secubox-app-picobrew:
- LXC container-based PicoBrew Server installation
- Alpine Linux rootfs with Python/Flask environment
- UCI configuration for port, memory, brewing defaults
- procd service management with respawn
- Commands: install, uninstall, update, status, logs, shell
luci-app-picobrew:
- Modern dashboard UI with SecuBox styling
- Service controls (start/stop/restart/install/update)
- Real-time status monitoring and logs
- Settings page for server and brewing configuration
- RPCD backend with full API coverage
Supports PicoBrew Zymatic, Z, Pico C, and Pico Pro devices.
Repository: https://github.com/CyberMind-FR/picobrew-server
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The wizard.js was looking for a global QRCode object that doesn't exist.
Updated to import and use our qrcode module like other views do.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed from baseclass.extend() to simple object return pattern
to match other libraries (chart.js). The baseclass dependency
was causing the module to fail loading.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The JavaScript QR code fallback was limited to Version 5 (106 bytes max),
but WireGuard configs are typically 200-250 bytes. This caused QR code
generation to fail when the backend qrencode binary is not installed.
Changes:
- Auto-select optimal QR version (1-20) based on data length
- Support up to 858 bytes (Version 20)
- Proper Reed-Solomon error correction with dynamic generator polynomials
- Data interleaving for multiple EC blocks
- Alignment patterns for all versions
- Version info encoding for version 7+
- Quiet zone in SVG output
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Refactor CROWDSEC object to use luci.crowdsec-dashboard RPC instead of file.exec
- Add getNftablesStats() for accurate blocked IPs count from firewall bouncer
- Update updateDiskUsage() to use luci.system-hub.get_system_status RPC
- Update loadSystemLogs() to use luci.system-hub.get_logs RPC
- Add proper ACL permissions for luci.crowdsec-dashboard and luci.system-hub
- Bump version to 1.5.0-r3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Downgrade golang.org/x/net from v0.44.0 to v0.33.0 (Go 1.23 compatible)
- Patch out http.Protocols usage (Go 1.24+ feature) from:
- pkg/acquisition/modules/http/run.go
- pkg/acquisition/modules/appsec/config.go
- pkg/acquisition/modules/kubernetesaudit/config.go
- pkg/apiserver/apiserver.go
- Patch strings.SplitSeq to strings.Split (Go 1.24+ iterator feature) in:
- cmd/crowdsec-cli/clisetup/acquisition.go
- cmd/crowdsec/flags.go
This fixes the build failure caused by CrowdSec 1.7.4 using Go 1.24+
features while OpenWrt SDK ships Go 1.23.x.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The -x flag requires exact process name match which doesn't work
reliably on OpenWrt/BusyBox. Removed -x from all pgrep calls in:
- luci-app-bandwidth-manager
- luci-app-secubox-security-threats
- luci-app-auth-guardian
- luci-app-media-flow
- luci-app-vhost-manager
- luci-app-network-modes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add RPC call to fetch CrowdSec nftables statistics
- Replace Security Modules widget with IPs Blocked widget
- Show active/inactive status based on firewall bouncer health
- Add detailed breakdown in System Overview (IPv4/IPv6, CAPI/local)
- Gracefully handle missing CrowdSec dashboard package
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove -q (quiet) flag from wget to show download errors
- Use architecture-specific tarball (60MB) instead of multi-arch (126MB)
- Add fallback to multi-arch tarball if ARM download fails
- Add explicit error messages for download and extraction failures
- Verify download file exists and is non-empty before extraction
The previous -q flag was hiding the actual wget error, making it
difficult to diagnose download failures in the chroot environment.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- lxc_create_rootfs now checks for Lyrion installation (slimserver.pl)
instead of just Alpine (alpine-release) to detect complete installs
- Auto-cleanup incomplete installations where Alpine downloaded but
Lyrion failed to install (e.g., network issues during chroot)
- Add verification after installation to confirm Lyrion was installed
- Add 'destroy' command to manually clean up failed installations
- Bump version to 2.0.1
This fixes the issue where 'lyrionctl install' would report success
when Alpine was downloaded but the chroot setup script failed silently.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use L.url() for proper ubus endpoint URL
- Pass messages as array instead of JSON string
- Add credentials and better error handling
- Fix AbortController error handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change default API port from 8080 to 8081
- Increase chat API timeout to 120 seconds (LLMs can be slow on ARM)
- Use custom fetch-based chat call with AbortController for timeout control
- Fix wget/curl timeout for RPCD backend
Resolves "XHR request timed out" errors when using chat with TinyLlama.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace Docker/LXC-based approach with direct binary download
- Download LocalAI v2.25.0 binary from GitHub releases
- Add localaictl CLI for install, model management, and service control
- Change default port to 8081 (avoid CrowdSec conflict on 8080)
- Remove secubox-app-localai-wb (merged into secubox-app-localai)
- Add model presets: tinyllama, phi2, mistral
Usage:
localaictl install
localaictl model-install tinyllama
/etc/init.d/localai enable && /etc/init.d/localai start
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New package for building LocalAI from source with llama-cpp backend:
- localai-wb-ctl: On-device build management
- check: Verify build prerequisites
- install-deps: Install build dependencies
- build: Compile LocalAI with llama-cpp
- Model management, service control
- build-sdk.sh: Cross-compile script for SDK
- Uses OpenWrt toolchain for ARM64
- Produces optimized binary with llama-cpp
Alternative to Docker-based secubox-app-localai for native builds.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New LuCI application for Ollama management:
- Dashboard with service status and controls
- Model management (pull, remove, list)
- Chat interface with model selection
- Settings page for configuration
Files:
- RPCD backend (luci.ollama)
- Dashboard, Models, Chat, Settings views
- ACL and menu definitions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Download Docker image layers directly via Registry API
- No dockerd or podman daemon required anymore
- Same approach as mitmproxy and magicmirror2 packages
- All backends included (llama-cpp, whisper, etc.)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated default version from v2.25.0 to v3.10.0
- Fixed binary URL format: local-ai-v3.10.0-linux-arm64
- Updated Docker image tag to v3.10.0-ffmpeg
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add runtime_is_working() to verify daemon connectivity
- Falls back to standalone binary with helpful message if daemon not running
- Provides hint: /etc/init.d/dockerd start
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When using `localaictl install --lxc`:
1. If podman/docker available: extracts rootfs from Docker image
- Includes ALL backends (llama-cpp, whisper, etc.)
- Creates LXC container with full LocalAI capabilities
2. If no docker/podman: falls back to standalone binary
- Limited backend support
This gives the best of both worlds:
- LXC lightweight container management
- Full Docker image backends
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- is_running() now checks LXC with lxc-info before Docker/Podman
- get_status() calculates uptime from LXC container PID
- Order: LXC -> Podman -> Docker -> native process
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update is_running() to detect Docker/Podman containers
- Fix get_status() uptime calculation for containers
- Improve do_chat() with better error messages and logging
- Use curl if available for API calls (more reliable than wget POST)
- Add debug logging to syslog (logger -t localai-chat)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
LocalAI changes:
- Rewrite localaictl to use Docker/Podman instead of standalone binary
- Use localai/localai:v2.25.0-ffmpeg image with all backends included
- Fix llama-cpp backend not found issue
- Auto-detect podman or docker runtime
- Update UCI config with Docker settings
New Ollama package:
- Add secubox-app-ollama as lighter alternative to LocalAI
- Native ARM64 support with backends included
- Simple CLI: ollamactl pull/run/list
- Docker image ~1GB vs 2-4GB for LocalAI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The LuCI rpc.declare with expect: { models: [] } returns the array
directly, not wrapped in {models: [...]}. Fixed all views to handle
this correctly.
- models.js: Check Array.isArray(data) first
- dashboard.js: Extract array from results[1] directly
- chat.js: Same array handling fix
Version: 0.1.0-r12
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add secubox-app-localai package with LXC container support for LocalAI service
- Add luci-app-localai with dashboard, chat, models and settings views
- Implement RPCD backend for LocalAI API integration via /v1/models and /v1/chat/completions
- Use direct RPC declarations in LuCI views for reliable frontend communication
- Add LocalAI and Glances to secubox-portal services page
- Move Glances from services to monitoring section
Packages:
- secubox-app-localai: 0.1.0-r1
- luci-app-localai: 0.1.0-r8
- luci-app-secubox-portal: 0.6.0-r5
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Improve Services tab with pgrep-based status detection
- Add service enable/disable toggle buttons
- Add port forwards table to Firewall tab
- Add process list to System tab
- Add CrowdSec alerts table
- Reorganize quick actions into grouped layout
- Add Flush DNS, Sync NTP, and LuCI Admin shortcuts
- Change URL path from /secubox-dashboard/ to /secubox/
- Bump version to 1.4.1 (v2.4)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use separate -B and -p args for bind address and port
- Add hostname resolution by populating /etc/hosts dynamically
- Add --disable-autodiscover and --disable-check-update flags
- Fixes DNS resolution errors causing immediate container exit
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add secubox-app-glances and luci-app-glances packages:
secubox-app-glances:
- LXC container with nicolargo/glances:latest-full Docker image
- Web UI on port 61208, API on port 61209
- UCI configuration for monitoring options and alert thresholds
- glancesctl management script
luci-app-glances:
- Dashboard view with service status and quick actions
- Embedded Web UI view with iframe
- Settings view for configuration
- RPCD backend with proper ACL permissions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_web_token to RPCD ACL permissions (was missing, causing 403)
- Add fallback token retrieval from container via lxc-attach
- Improve token capture regex to support alphanumeric tokens
- Fix startup script with background process + tee for reliable capture
- Add IP forwarding enablement for transparent proxy mode
- Fix bypass rule for traffic destined to router itself
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Consider sync OK when CAPI blocklists are active (capi_elements > 0)
even if local decisions = 0
- Add capi_elements_count to health response
- Fixes false "Out of sync" warning when using community blocklists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- install_module now uses mmpmctl if available (has module registry)
- Fallback to manual git clone only with explicit URLs
- Add proper Node.js PATH for npm commands
- update_module also uses mmpmctl when available
- Fix npm PATH in both install and update functions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use `mmpm ui --start/--stop/--status` instead of `mmpm ui --port --host`
- MMPM v4 manages GUI via pm2, not direct execution
- Update status command to check pm2 status and get URL from mmpm
- Auto-install UI if not present when starting service
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add NODE_PATH variable for container npm/pm2 access
- Add run_mmpm helper function with proper PATH export
- Fix module install/remove/upgrade/search/list commands
- Fix MMPM GUI service start with proper PATH
- Fix list command to use --installed flag
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update module list to match portal.js apps
- Add MagicMirror2 and MMPM to modules
- Add changelog entries for v0.15.0-alpha1 to alpha3
- Update roadmap with Certification CE/FCC and Phase 2 funding (2027)
- Update version badge to v0.15.0-alpha3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix pip install with --break-system-packages for Debian Trixie PEP 668
- Fix MMPM binary path detection (/usr/local/bin/mmpm)
- Fix RPCD backend to detect MMPM UI status with correct PATH
- Add Services section to portal navigation
- Update MMPM commands to use full path in container
- Configure MMPM environment for /opt/magic_mirror
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add symlink from modules/default to __modules/default (Docker entrypoint logic)
- Copy CSS files from __css to css directory on startup
- Fix shebang escaping issue by using printf instead of heredoc for #!/bin/sh
- Bump release to 0.4.0-r7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New packages:
- secubox-app-magicmirror2 (0.4.0): MagicMirror² smart display platform
- LXC container with Docker image extraction
- mm2ctl CLI for management
- Support for gzip/zstd compressed layers
- Default port 8082
- luci-app-magicmirror2 (0.4.0): LuCI web interface
- Dashboard, modules, webui, settings views
- RPCD backend for service control
- Module management integration
- secubox-app-mmpm (0.2.0): MMPM package manager
- Installs MMPM in MagicMirror2 container
- mmpmctl CLI for module management
- Web GUI on port 7891
- luci-app-mmpm (0.2.0): LuCI interface for MMPM
- Dashboard with install/update controls
- Module search and management
- Embedded web GUI view
Portal integration:
- Added MagicMirror² and MMPM to Services section
- Portal version bumped to 0.6.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add PYTHONUNBUFFERED=1 to ensure mitmweb output is not buffered
- Use inline while loop to capture authentication token from startup output
- Fix RPCD backend to read token from correct path ($DATA_DIR/.mitmproxy_token)
- Add proper shell detection and symlink creation in Docker rootfs extraction
- Remove unnecessary exec in pipeline that prevented output capture
The mitmweb authentication token is now properly captured and available
to the LuCI Web UI view for iframe embedding.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous pipe approach didn't work because the while loop
runs in a subshell. Now using a background job to poll the log
file for the token while tee outputs to both console and log.
Bump release to r13.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_web_token RPCD method to retrieve auth token
- Create webui.js view that embeds mitmweb in an iframe
- Capture auth token at startup and save to file
- Add Web UI navigation to all mitmproxy views
- Fix PATH for /usr/local/bin in Docker image
- Change default port from 8080 to 8888 (avoid CrowdSec conflict)
secubox-app-mitmproxy: bump to r12
luci-app-mitmproxy: bump to r2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Recent mitmproxy versions require web authentication by default.
Disable it with --set web_password= for easier LAN access.
Bump release to r11.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Port 8080 conflicts with CrowdSec API. Using 8888 as default.
Also removes --flow-detail option not available in latest mitmproxy.
Bump release to r10.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract rootfs directly from mitmproxy/mitmproxy Docker image.
This provides the latest mitmproxy with all Rust components pre-compiled.
No more version compatibility issues - uses whatever version is in
the official Docker image.
Bump release to r8.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 7.0.4 doesn't support the --flow-detail option which was
causing the startup script to fail.
Bump release to r7.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 8.x has dataclass compatibility issues with Python 3.11
in the grpc contentviews module.
Bump release to r6.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
werkzeug 3.0+ removed url_quote from werkzeug.urls which breaks
Flask imports in mitmproxy 8.1.1.
Bump release to r5.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
zstandard requires gcc to compile. Added build-base and dev packages
for compilation, then remove them after pip install to save space.
Bump release to r4.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- mitmproxy 9.x requires mitmproxy-wireguard (Rust)
- mitmproxy 10.x requires mitmproxy_rs (Rust)
- mitmproxy 8.1.1 is the last version without any Rust dependencies
Bump release to r3.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 10.x requires mitmproxy_rs which needs Rust compilation.
mitmproxy 9.0.1 is the last pure-Python version that works in Alpine
chroot without /proc mounted.
Bump release to r2.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 10.2+ requires mitmproxy_rs which needs Rust 1.80+, but
Alpine 3.19 only has Rust 1.76. Using mitmproxy 10.1.6 which is the
last pure-Python version without Rust requirements.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 10.2+ requires mitmproxy_rs which needs Rust.
Install rust and cargo from Alpine packages, compile mitmproxy,
then remove build deps to save space.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy_rs now requires Rust compilation which fails in chroot
environment without /proc mounted. Switch to Alpine's pre-built
mitmproxy package from the community repository.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add nftables transparent mode support with automatic REDIRECT rules
- Create SecuBox Python filter addon for CDN/Media/Ad tracking
- Add whitelist/bypass configuration for IPs and domains
- Expand UCI config with transparent, whitelist, filtering sections
- Update RPCD backend with new config methods and firewall control
- Update LuCI settings view with all new configuration options
- Add new API methods: firewall_setup, firewall_clear, list management
Features:
- Transparent proxy with nftables integration
- CDN tracking (Cloudflare, Akamai, Fastly, etc.)
- Media streaming tracking (YouTube, Netflix, Spotify)
- Ad/tracker blocking
- IP and domain whitelist bypass
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move UCI defaults script for auto-registration to cs-firewall-bouncer
- Remove redundant secubox-app-crowdsec-bouncer wrapper package
- Update luci-app-crowdsec-dashboard reference to new package name
- Increment PKG_RELEASE to 3
The defaults script handles:
- Automatic bouncer registration with CrowdSec LAPI
- Interface detection for LAN/WAN
- API key generation and UCI config update
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
luci-app-crowdsec-dashboard is more complete with:
- Overview, Setup Wizard, WAF/AppSec, Metrics views
- Proper location in SecuBox > Security menu
- Bouncers management
luci-app-secubox-crowdsec was a simpler duplicate in Services menu.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create mitmproxyctl script with LXC container management
- Alpine Linux rootfs with Python and mitmproxy via pip
- Support for regular, transparent, upstream, and reverse proxy modes
- UCI configuration for proxy_port, web_port, memory_limit, etc.
- procd init script for service management
- Update luci-app-mitmproxy RPCD backend for LXC container status
Ports:
- 8080: Proxy port
- 8081: Web interface (mitmweb)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add perl-template-toolkit and perl-file-slurp dependencies
- Remove bundled Template.pm (conflicts with system version 3.101)
- Add Devel::Peek stub module for runtime inspection
- Fix lxc_logs() to read logs from container via lxc-attach
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update Lyrion download URLs to downloads.lms-community.org
- Switch from noCPAN to full tarball (noCPAN missing modules)
- Replace perl-image-scale with perl-gd + imagemagick (Alpine)
- Remove conflicting bundled CPAN modules (DBD::SQLite, XML::Parser, YAML, DBI)
- Add Image::Scale stub module for artwork resizing
- Fix permissions for nobody user on /config and /var/log/lyrion
- Add missing perl-digest-sha1 and perl-sub-name dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Removed unrealistic items (AI Threat Detection, Mobile App, Cloud) and
replaced with practical goals based on current module progress:
- Network Modes 1.0 (currently at 35%)
- SecuBox Hub 1.0 (currently at 31%)
- Multi-WAN Failover
- Documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fixed incorrect year (2025 -> 2026) in changelog dates
- Added v0.15.0-rc2 changelog entry for CrowdSec firewall bouncer fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The init script created nftables sets and chains but never added the
actual DROP rules to block traffic from blacklisted IPs. This caused
the bouncer to populate sets correctly but traffic was never blocked.
Added DROP rules for:
- IPv4 input chain (crowdsec-blacklists)
- IPv4 forward chain (crowdsec-blacklists)
- IPv6 input chain (crowdsec6-blacklists)
- IPv6 forward chain (crowdsec6-blacklists)
Each rule respects the deny_log and deny_action configuration options.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename crowdsec-firewall-bouncer to secubox-app-cs-firewall-bouncer
- Rename secubox-auth-logger to secubox-app-auth-logger
- Delete secubox-crowdsec-setup (merged into other packages)
- Fix circular dependencies in luci-app-secubox-crowdsec
- Fix dependency chain in secubox-app-crowdsec-bouncer
- Add consolidated get_overview API to crowdsec-dashboard
- Improve crowdsec-dashboard overview performance
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The new get_overview RPC method was missing from the ACL file,
causing "Access denied" errors in the frontend.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Consolidate multiple dashboard API calls into a single get_overview RPC
method to reduce network overhead and improve page load performance.
The frontend now transforms the consolidated response to maintain
compatibility with existing view logic. Also increases poll interval
from 30s to 60s.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix typo seccubox_logs -> secubox_logs
- Get country data from alerts (source.cn) instead of decisions
- Display CrowdSec logs instead of non-existent secubox.log
- Rename "SecuBox Log Tail" to "CrowdSec Logs"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CrowdSec decisions don't contain country data. GeoIP enricher adds
country info to alerts (source.cn or source.country field).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds "Connexion" link at the end of the public menu to redirect
to the admin authentication page.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace github.com/gkerma/secubox-openwrt with
github.com/CyberMind-FR/secubox-openwrt across all files.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add devstatus.js with modules list, roadmap, and changelog
- Reorder public pages: Crowdfunding (10), Bug Bounty (20), Dev Status (30)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The 403 error was caused by missing ACL file. Added
luci-app-secubox-portal.json with read permissions for
luci.secubox and luci.system-hub ubus methods.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move Debug Console from Client Guardian to System Hub
- Add Auto-Zoning Rules dedicated view in Client Guardian
- Add public pages for Bug Bounty and Crowdfunding (no ACL)
- Fix auth-logger to only detect real login attempts
- Add private IP whitelist for CrowdSec (RFC1918 ranges)
- Update navigation menus across all apps
- Bump secubox-auth-logger to v1.2.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- v2.0.0: Multi-runtime support with auto-detection
- LXC preferred when available (150MB RAM vs 300MB for Docker)
- New lyrionctl commands: runtime, shell
- Alpine Linux rootfs creation for LXC
- UCI config: runtime option (auto/docker/lxc)
- Memory limit configuration via cgroups
- Updated plugin manifest with runtime info
Runtime selection:
option runtime 'auto' - Auto-detect (LXC preferred)
option runtime 'docker' - Force Docker
option runtime 'lxc' - Force LXC
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add explicit 644 permissions for overview.js and dashboard.css
- Fixes HTTP 403 error when accessing the view
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add sync command to synchronize packages from package/secubox to local-feed
- Add local-feed deletion to clean-all command
- Add missing packages to package/secubox:
- luci-app-secubox-crowdsec
- secubox-crowdsec-setup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- v1.2.1: Remove timestamp generation (ucode time functions unavailable)
- Use simple format: secubox-auth[1]: authentication failure for...
- Update parser to use raw line parsing with custom label type
- Change acquisition from type:syslog to type:secubox-auth
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- secubox-auth-logger v1.2.0: Patch LuCI ucode dispatcher.uc to log
authentication failures server-side instead of relying on JS hooks
- crowdsec-firewall-bouncer: Add helper function for UCI list reading
and default to eth1, br-lan, br-wan interfaces to ensure WAN traffic
is checked against the blocklist
- Update postrm to properly restore dispatcher backup on uninstall
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CGI hook to capture client IP during failed auth attempts
- Add JavaScript hook to intercept ubus session.login failures
- Add rpcd plugin for ubus-based auth logging
- Update CrowdSec parser for case-insensitive matching
- Inject JS hook into LuCI theme headers on install
This enables CrowdSec to detect and block brute-force attacks
on the LuCI web interface, which previously only logged
successful authentications.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Local Protection Mode banner when CAPI unavailable (LAPI still works)
- Save enrollment key to UCI config for future repairs
- Improve text contrast in wizard (better readability)
- Simplify LAPI repair function based on official OpenWrt approach
- Never delete CAPI credentials to avoid rate-limiting
- Add get_settings/save_settings RPC methods
- Bump version to 0.7.0-r27
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add automatic restart after successful console enrollment
- Update wizard UI to inform user about validation on app.crowdsec.net
- Service must restart after enrollment is validated on CrowdSec Console
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Service restarts during bouncer registration and service start can
cause XHR connections to abort. Treat these as success since the
operation likely completed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New wizard approach:
- Automatic health check on load (LAPI, CAPI, Bouncer, nftables, collections)
- Single configuration page with all options visible
- Only repairs what's broken
- No hub update without CAPI connection
- Single "Apply Configuration" button at the end
- Progress bar during apply
- Summary of what was done at completion
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The RPC method was returning "Access denied" because it was missing
from the rpcd ACL configuration.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Large package feed files exceed GitHub's 100MB limit.
These are build artifacts that should be generated locally.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add get_public_ips method to secubox-core rpcd backend
- Fetch public IPs from multiple services with fallback
- Display in new "Public IP Addresses" panel on dashboard
- Auto-update IPs on poll refresh
- Bump luci-app-secubox to 0.7.1-r2
- Bump secubox-core to 0.10.0-r4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Treat XHR abort as success when CrowdSec restarts after acquisition config
- Auto-advance to Step 5 after brief delay
- Bump to 0.7.0-r21
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- repair_lapi() now removes stale online_api_credentials.yaml and retries
- New repair_capi() function for dedicated CAPI repair
- console_enroll() handles CAPI credential cleanup before retry
- Added repairCapi API method in frontend
- Bump luci-app-crowdsec-dashboard to 0.7.0-r20
- Add openwrt-luci-bf.yaml scenario for LuCI brute force detection
- Add secubox-auth-acquis.yaml acquisition config
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The serviceWarning variable was null when CrowdSec is running, and
LuCI's E() function rendered it as literal "null" text. Fixed by
using empty fragment when no warning needed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The refreshView() call was aborting the pending configureAcquisition
XHR request by triggering new API calls. Now only updates the button
state without a full view refresh.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
CrowdSec on OpenWrt doesn't support "source: command" acquisition.
Changed to file-based acquisition reading /var/log/messages.
Also configures busybox syslog to write to file automatically.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When SSH logging is enabled in the wizard, automatically:
- Set dropbear.@dropbear[0].verbose=1 to log auth failures
- Restart dropbear to apply changes
This ensures CrowdSec can detect SSH brute force attempts.
Without verbose mode, Dropbear doesn't log failed auth to syslog.
Also enable uhttpd syslog when HTTP logging is enabled.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Parse ndpid-apps.json array format [{name: "TLS.YouTube", ...}]
- Use jq contains() instead of test() regex (ONIGURUMA not available on OpenWrt)
- Filter streaming services: YouTube, Netflix, Spotify, AppleiTunes, etc.
- Aggregate streams by app name (combine TLS.YouTube + QUIC.YouTube)
- Estimate quality based on data volume (SD/HD/FHD)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SecuBox dark theme initialization to all views (dashboard, alerts,
clients, services, history)
- Fix flow count detection by using jsonfilter instead of jq (OpenWrt native)
- Prioritize /var/run/netifyd/status.json for ndpid-compat flow data
- Remove filtering expect{} from API.getActiveStreams() RPC declaration
- Update CLAUDE.md with jsonfilter usage guidelines for OpenWrt
The dashboard now correctly displays:
- Total Flows count from nDPId via ndpid-compat
- nDPId/Netifyd status indicators
- SecuBox dark theme with portal header
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change 'config main' to 'config ndpid main' for proper section naming
- Change 'config compat' to 'config ndpid compat'
- Enable ndpid by default (enabled='1')
- Init scripts expect named sections, not typed sections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Scan ALL nftables sets (CAPI, cscli, etc.) instead of just base set
- Display blocked IPs count by origin (Community vs Local)
- Show sample of blocked IPs with Unban button
- Add ipv4_capi_count, ipv4_cscli_count, ipv4_total_count to API response
- Support for 14,000+ community blocklist IPs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add health_check API with LAPI/CAPI/Console status verification
- Add capi_metrics API for community blocklist statistics
- Add hub_available, install_hub_item, remove_hub_item APIs
- Add System Health panel to overview with visual status indicators
- Add CAPI Blocklist section showing community vs local decisions
- Add Installed Collections card with version display
- Fix settings.js syntax error (missing comma)
- Fix metrics.js null display in acquisition statistics
- Update ACL file with new RPC method permissions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rebuilt all luci-app-* and secubox-app-* packages for aarch64-cortex-a72
- Updated local-build.sh with FORCE=1 to bypass rsync prereq check
- Removed packages that failed SDK build (require full buildroot)
- Updated Packages index and apps-local.json manifest
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Include all built .ipk packages in luci-app-secubox-bonus
- Generate Packages index and apps-local.json manifest
- Remove .gitignore to allow package tracking
- Enables offline package installation via SecuBox > Local Packages
Packages included:
- 27 luci-app-* packages
- 11 secubox-app-* packages
- luci-theme-secubox
- secubox-core
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create /etc/opkg/customfeeds.conf with secubox feed pre-configured
- Install file via Makefile instead of postinst script
- Mark as conffile to preserve user modifications on upgrade
- Add .gitignore to exclude built .ipk files from git tracking
(packages are embedded at build time by embed_local_feed)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add embed_local_feed() to local-build.sh that copies built packages
into bonus app as /www/secubox-feed/ for offline installation
- Generate Packages index and apps-local.json manifest for opkg
- Add RPCD backend (luci.secubox-store) for package install/remove
- Add LuCI view for browsing and managing local packages
- Fix OPENWRT_ONLY_PACKAGES to allow secubox-app-* wrappers in SDK build
- Remove experimental python3-* packages (unfinished mitmproxy native plan)
- Set rootfs partition size to 16GB for larger overlay
- Bump luci-app-secubox-bonus to v0.2.0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New package: crowdsec-firewall-bouncer (v0.0.34)
- Based on official OpenWrt package from openwrt/packages
- Full nftables integration with IPv4/IPv6 support
- Timeout-based sets for automatic ban expiration
- Input and forward chain filtering
- Interface-based filtering
- procd service management with ujail support
- UCI configuration
Init script features:
- Creates nftables tables: crowdsec (IPv4), crowdsec6 (IPv6)
- Creates timeout-enabled sets for blocklists
- Generates YAML config from UCI settings
- Automatic cleanup on service stop
Updated secubox-app-crowdsec-bouncer to v0.0.32
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New features:
- New RPCD method: acquisition_metrics for detailed stats
- Realtime metrics display with 10-second polling
- Visual stat cards: lines read, parsed, unparsed, buckets
- Parse rate progress bar with color coding
- Active acquisition sources badges
- Rate calculation (events/sec) between polls
- Live update indicator with timestamp
API changes:
- Added getAcquisitionMetrics() to API layer
- Added acquisition_metrics to ACL permissions
Bumped version to 0.7.0-17
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
OpenWrt uses logd by default which doesn't write to files.
CrowdSec file-based acquisition needs /var/log/messages to exist.
Changes:
- Init script: setup_syslog() configures log_file before each start
- Defaults script: setup_syslog_file() configures at install time
- openwrt-syslog.yaml: Remove non-existent /var/log/syslog reference
The init script sets:
uci set system.@system[0].log_file='/var/log/messages'
uci set system.@system[0].log_size='512'
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Native OpenWrt package for zstandard compression library.
Can be used as alternative to pip installation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The zstandard package required by mitmproxy 8.1.1 doesn't have musllinux
wheels in older versions, causing pip to try compiling from source which
fails without gcc on the router.
Fix: Pre-install zstandard 0.23.0 which has musllinux aarch64 wheels
before installing mitmproxy.
Changes:
- Bump version to 2.1.0
- Revert to pip-based installation (native build requires full toolchain)
- Add zstandard 0.23.0 pre-install step in postinst
- Restore wrapper scripts for mitmproxy/mitmdump/mitmweb
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add OpenWrt .config for mvebu/cortexa72 target
- Update .gitignore
- Update Claude settings
- Minor portal.js update
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 9.x requires mitmproxy-wireguard (Rust).
Version 8.1.1 is pure Python and works on OpenWrt.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 10.x requires mitmproxy-rs which needs Rust compiler.
Version 9.0.1 is pure Python and works on OpenWrt.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
LuCI requires modules to use baseclass.extend() pattern.
Fixed "factory yields invalid constructor" error.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Portal Integration:
- Add mitmproxy to Security section with service status tracking
- Add vhost-manager to new Services section
- Add Services section to portal navigation header
- Update path detection for security/mitmproxy and services/vhosts
mitmproxy Changes:
- Move menu from admin/secubox/mitmproxy to admin/secubox/security/mitmproxy
- Update view navigation links to use new path structure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
mitmproxy 11.x requires Python 3.12 which is not available on OpenWrt.
Version 10.4.2 is the last stable release supporting Python 3.10+.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch to runtime pip installation instead of build-time
- Remove complex build dependencies (python3-package.mk)
- Add wrapper scripts for mitmproxy, mitmdump, mitmweb
- Postinst installs mitmproxy==11.1.3 via pip on device
- Supports all architectures with PKGARCH:=all
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update mitmproxy to v11.1.3
- Build from Python source (no prebuilt arm64 binaries)
- Add Python dependencies
- Add mitmproxy to local-build.sh and sync-openwrt-packages.sh
- Set PKGARCH:=all for Python package
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New packages for full URL/cookie/header capture via MITM proxy:
secubox-app-mitmproxy:
- Downloads mitmproxy v11.1.2 binary for aarch64
- Transparent proxy mode with iptables integration
- mitmweb UI on port 8081
- Auto CA certificate generation
- mitmproxyctl CLI management tool
luci-app-mitmproxy:
- SecuBox themed dashboard with red color scheme
- Real-time request capture view
- Top hosts statistics
- CA certificate management
- Full UCI settings interface
- RPCD backend for ubus API
This enables full HTTP/HTTPS inspection including:
- Complete URLs (not just hostnames like nDPId)
- Cookies and headers
- Request/response bodies
- Flow recording for replay
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
OpenWrt jq is compiled without ONIGURUMA regex library, so test()
function doesn't work. Replace all regex patterns with contains()
for streaming service detection.
- Use ascii_downcase + contains() for pattern matching
- Define is_streaming, get_category, get_quality as jq functions
- Detects: YouTube, Netflix, Spotify, WhatsApp, Discord, Zoom, etc.
- Bump version to 0.6.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove PKG_FILE_MODES that caused chown build errors
- Add missing $(eval $(call BuildPackage)) macro
- Add explicit install rules for all resources
- Bump version to 0.6.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>