- Add local-build.sh: comprehensive local build system
- Validates packages (Makefiles, JSON, JavaScript, shell scripts)
- Downloads and caches OpenWrt SDK
- Builds .ipk packages locally
- Supports multiple architectures (x86-64, ARM, MIPS)
- Collects artifacts with SHA256 checksums
- Update CLAUDE.md with local build documentation
- Add Local Build section with usage examples
- Update Development Workflow to include local testing
- List supported architectures and environment variables
- Update secubox-tools/README.md
- Add comprehensive local-build.sh documentation
- Update workflow examples to include local building
- Add dependencies and installation instructions
Benefits:
- Test builds locally before CI/CD
- Faster development iteration
- Reduced GitHub Actions usage
- Offline development support
Usage:
./secubox-tools/local-build.sh validate
./secubox-tools/local-build.sh build
./secubox-tools/local-build.sh build luci-app-<name>
./secubox-tools/local-build.sh build --arch <arch>
./secubox-tools/local-build.sh full
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
14 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
SecuBox is a comprehensive security and network management suite for OpenWrt. The repository contains 13 LuCI application packages that provide dashboards for security monitoring, network intelligence, access control, bandwidth management, and system administration.
Build Commands
OpenWrt SDK Build
# Build a single package
make package/luci-app-<module-name>/compile V=s
# Clean build for a package
make package/luci-app-<module-name>/clean
make package/luci-app-<module-name>/compile V=s
# Install package to staging directory
make package/luci-app-<module-name>/install
Testing Packages
# Transfer to router
scp bin/packages/*/base/luci-app-*.ipk root@192.168.1.1:/tmp/
# Install on router
ssh root@192.168.1.1
opkg install /tmp/luci-app-*.ipk
/etc/init.d/rpcd restart
/etc/init.d/uhttpd restart
Validation
# Run comprehensive module validation (RECOMMENDED)
./secubox-tools/validate-modules.sh
# Validate shell scripts (RPCD backends)
shellcheck luci-app-*/root/usr/libexec/rpcd/*
# Validate JSON files
find . -name "*.json" -exec jsonlint {} \;
# Run automated repair tool
./secubox-tools/secubox-repair.sh
# Run diagnostics
./secubox-tools/secubox-debug.sh luci-app-<module-name>
Local Build (Replicates GitHub Actions)
The local-build.sh script allows you to build and test packages locally, replicating the GitHub Actions workflows:
# Validate all packages (syntax, JSON, shell scripts)
./secubox-tools/local-build.sh validate
# Build all packages for x86_64
./secubox-tools/local-build.sh build
# Build single package
./secubox-tools/local-build.sh build luci-app-system-hub
# Build for specific architecture
./secubox-tools/local-build.sh build --arch aarch64-cortex-a72
# Full validation + build
./secubox-tools/local-build.sh full
# Clean build artifacts
./secubox-tools/local-build.sh clean
Supported architectures:
x86-64- PC, VMs (default)aarch64-cortex-a53- ARM Cortex-A53 (ESPRESSObin)aarch64-cortex-a72- ARM Cortex-A72 (MOCHAbin, RPi4)aarch64-generic- Generic ARM64mips-24kc- MIPS 24Kc (TP-Link)mipsel-24kc- MIPS LE (Xiaomi, GL.iNet)
The script automatically:
- Downloads and caches the OpenWrt SDK
- Configures feeds (packages, luci)
- Copies your packages to the SDK
- Builds .ipk packages
- Collects artifacts in
build/<arch>/
Environment variables:
OPENWRT_VERSION- OpenWrt version (default: 23.05.5)SDK_DIR- SDK directory (default: ./sdk)BUILD_DIR- Build output directory (default: ./build)CACHE_DIR- Download cache directory (default: ./cache)
Architecture
LuCI Package Structure
All SecuBox modules follow a standard LuCI application structure:
luci-app-<module-name>/
├── Makefile # OpenWrt package definition
├── README.md # Module documentation
├── htdocs/luci-static/resources/
│ ├── view/<module-name>/ # JavaScript UI views
│ │ ├── overview.js # Main dashboard view
│ │ └── *.js # Additional views
│ └── <module-name>/
│ ├── api.js # RPC API client module
│ └── dashboard.css # Module-specific styles
└── root/
├── etc/config/<module-name> # UCI configuration (optional)
└── usr/
├── libexec/rpcd/
│ └── luci.<module-name> # RPCD backend script (MUST use luci. prefix!)
└── share/
├── luci/menu.d/ # Menu JSON definition
│ └── luci-app-<module-name>.json
└── rpcd/acl.d/ # ACL permissions JSON
└── luci-app-<module-name>.json
Frontend-Backend Communication
-
Frontend (JavaScript): Located in
htdocs/luci-static/resources/- Views use LuCI's
formandviewclasses - API calls via
api.jsmodule usingL.resolveDefault() - UI components from
ui.js(Dropdown, Checkbox, Combobox, etc.)
- Views use LuCI's
-
Backend (RPCD): Located in
root/usr/libexec/rpcd/- Shell scripts that implement RPC methods
- Must output JSON to stdout
- Methods are called via ubus:
ubus call <module> <method>
-
Menu Definition:
root/usr/share/luci/menu.d/luci-app-<module>.json- Defines menu structure and navigation
- Specifies view paths and dependencies
-
ACL Definition:
root/usr/share/rpcd/acl.d/luci-app-<module>.json- Defines access control for ubus methods
- Maps read/write permissions to user groups
Critical Naming Conventions
IMPORTANT: The following naming rules are MANDATORY for modules to work correctly:
1. RPCD Script Must Match ubus Object Name
The RPCD script filename MUST exactly match the ubus object name used in JavaScript:
// In JavaScript (htdocs/luci-static/resources/view/*/):
var callStatus = rpc.declare({
object: 'luci.cdn-cache', // ← This object name
method: 'status'
});
# RPCD script filename MUST match:
root/usr/libexec/rpcd/luci.cdn-cache # ← Must be exactly 'luci.cdn-cache'
Common Error: If the names don't match, you'll get:
RPC call to luci.cdn-cache/status failed with error -32000: Object not foundCommand failed: Method not found
Solution: All RPCD scripts MUST use the luci. prefix:
- ✅ Correct:
luci.cdn-cache,luci.system-hub,luci.wireguard-dashboard - ❌ Wrong:
cdn-cache,system-hub,wireguard-dashboard
2. Menu Paths Must Match View File Locations
Menu JSON path entries MUST correspond to actual view files:
// In menu.d/luci-app-netifyd-dashboard.json:
{
"action": {
"type": "view",
"path": "netifyd-dashboard/overview" // ← Must match file location
}
}
# View file MUST exist at:
htdocs/luci-static/resources/view/netifyd-dashboard/overview.js
# ↑ Same path as menu ↑
Common Error: If paths don't match:
HTTP error 404 while loading class file '/luci-static/resources/view/netifyd/overview.js'
Solution: Ensure menu paths match directory structure:
- ✅ Correct: Menu path
netifyd-dashboard/overview→ fileview/netifyd-dashboard/overview.js - ❌ Wrong: Menu path
netifyd/overview→ fileview/netifyd-dashboard/overview.js
3. ubus Object Naming Convention
All ubus objects MUST start with luci. prefix:
// ✅ Correct:
object: 'luci.cdn-cache'
object: 'luci.system-hub'
object: 'luci.wireguard-dashboard'
// ❌ Wrong:
object: 'cdn-cache'
object: 'systemhub'
4. Validation Before Deployment
ALWAYS run validation before deploying:
./secubox-tools/validate-modules.sh
This script checks:
- RPCD script names match ubus objects
- Menu paths match view file locations
- View files have corresponding menu entries
- RPCD scripts are executable
- JSON files are valid syntax
- ubus objects follow naming convention
Makefile Structure
Each package Makefile must define:
PKG_NAME: Package name (must match directory)PKG_VERSION: Version numberPKG_RELEASE: Package release numberLUCI_TITLE: Display title in LuCILUCI_DEPENDS: Package dependencies (e.g.,+luci-base +rpcd)LUCI_DESCRIPTION: Brief descriptionPKG_MAINTAINER: Maintainer name and emailPKG_LICENSE: License (typically Apache-2.0)
The Makefile includes luci.mk from the LuCI build system which handles installation.
Common Development Patterns
Creating a New Module
- Copy template:
cp -r templates/luci-app-template luci-app-newmodule - Update Makefile with new PKG_NAME, LUCI_TITLE, etc.
- Create directory structure under
htdocs/androot/ - Implement RPCD backend in shell
- Create JavaScript views
- Define menu and ACL JSON files
RPCD Backend Pattern
RPCD backends are shell scripts that:
- Parse
$1for the method name - Output valid JSON using
printforecho - Use
casestatements for method routing - Source UCI config if needed:
. /lib/functions.sh
Example:
#!/bin/sh
case "$1" in
list)
echo '{ "status": {}, "stats": {} }'
;;
call)
case "$2" in
status)
# Output JSON
printf '{"running": true, "version": "1.0.0"}\n'
;;
esac
;;
esac
JavaScript View Pattern
Views extend L.view and implement load() and render():
'use strict';
'require view';
'require form';
'require <module>/api as API';
return L.view.extend({
load: function() {
return Promise.all([
API.getStatus(),
API.getStats()
]);
},
render: function(data) {
var m, s, o;
m = new form.Map('config', _('Title'));
s = m.section(form.TypedSection, 'section');
// Add form fields...
return m.render();
}
});
Module Categories
-
Core Control (2 modules)
- luci-app-secubox: Central hub
- luci-app-system-hub: System control center
-
Security & Monitoring (2 modules)
- luci-app-crowdsec-dashboard: CrowdSec security
- luci-app-netdata-dashboard: System monitoring
-
Network Intelligence (2 modules)
- luci-app-netifyd-dashboard: Deep packet inspection
- luci-app-network-modes: Network mode configuration
-
VPN & Access Control (3 modules)
- luci-app-wireguard-dashboard: WireGuard VPN
- luci-app-client-guardian: NAC & captive portal
- luci-app-auth-guardian: Authentication system
-
Bandwidth & Traffic (2 modules)
- luci-app-bandwidth-manager: QoS & quotas
- luci-app-media-flow: Media traffic detection
-
Performance & Services (2 modules)
- luci-app-cdn-cache: CDN proxy cache
- luci-app-vhost-manager: Virtual host manager
CI/CD Integration
GitHub Actions Workflows
-
build-openwrt-packages.yml: Compiles packages for all architectures
- Triggers on push, PR, and tags
- Matrix build for 13 architectures
- Uploads artifacts per architecture
-
build-secubox-images.yml: Builds custom OpenWrt images
- Creates complete firmware images with SecuBox pre-installed
-
test-validate.yml: Validation and testing
- Validates Makefile structure
- Checks JSON syntax
- Runs shellcheck on scripts
- Verifies file permissions
Supported Architectures
ARM64: aarch64-cortex-a53, aarch64-cortex-a72, aarch64-generic, mediatek-filogic, rockchip-armv8, bcm27xx-bcm2711
ARM32: arm-cortex-a7-neon, arm-cortex-a9-neon, qualcomm-ipq40xx, qualcomm-ipq806x
MIPS: mips-24kc, mipsel-24kc, mipsel-74kc
x86: x86-64, x86-generic
Key Files and Directories
makefiles/: Reference Makefiles for modules (backup/templates)secubox-tools/: Repair and debugging utilitiessecubox-repair.sh: Auto-fixes Makefile and RPCD issuessecubox-debug.sh: Validates package structure
templates/: Package templates for creating new modules.github/workflows/: CI/CD automation scripts
Common Issues and Solutions
RPC Errors: "Object not found" or "Method not found"
Error: RPC call to luci.cdn-cache/status failed with error -32000: Object not found
Cause: RPCD script name doesn't match ubus object name in JavaScript
Solution:
- Check JavaScript files for ubus object name:
grep -r "object:" luci-app-*/htdocs --include="*.js" - Rename RPCD script to match exactly (including
luci.prefix):mv root/usr/libexec/rpcd/cdn-cache root/usr/libexec/rpcd/luci.cdn-cache - Restart RPCD on router:
/etc/init.d/rpcd restart
HTTP 404 Errors: View Files Not Found
Error: HTTP error 404 while loading class file '/luci-static/resources/view/netifyd/overview.js'
Cause: Menu path doesn't match actual view file location
Solution:
- Check menu JSON for path:
grep '"path":' root/usr/share/luci/menu.d/*.json - Verify view file exists at matching location:
ls htdocs/luci-static/resources/view/ - Update menu path to match file location OR move file to match menu path
RPCD Not Responding
After installing/updating a package:
/etc/init.d/rpcd restart
/etc/init.d/uhttpd restart
Menu Not Appearing
Check that:
- Menu JSON is valid:
jsonlint root/usr/share/luci/menu.d/*.json - ACL grants access: Check
root/usr/share/rpcd/acl.d/*.json - Dependencies are installed: Check Makefile
LUCI_DEPENDS - Menu path matches view file location (see above)
Build Failures
Common causes:
- Missing fields in Makefile (PKG_NAME, LUCI_TITLE, etc.)
- Invalid JSON syntax in menu.d or acl.d
- RPCD script not executable (chmod +x needed)
- Wrong include path (should be
include ../../luci.mk) - RPCD script name doesn't match ubus object (must use
luci.prefix)
Use repair tool: ./secubox-tools/secubox-repair.sh
Quick Diagnosis
Run the validation script to check all naming conventions:
./secubox-tools/validate-modules.sh
Development Workflow
- Make changes to module files
- Run validation checks (CRITICAL):
./secubox-tools/validate-modules.sh # Or use the local build tool: ./secubox-tools/local-build.sh validate - Test JSON syntax:
jsonlint <file>.json - Test shell scripts:
shellcheck <script> - Build and test package locally (recommended):
# Build single package ./secubox-tools/local-build.sh build luci-app-<name> # Or build with manual SDK: make package/luci-app-<name>/compile V=s - Install on test router and verify functionality
- Run repair tool if needed:
./secubox-tools/secubox-repair.sh - Commit changes and push (triggers CI validation)
- Create tag for release:
git tag -a v1.0.0 -m "Release 1.0.0"
Important Notes
- CRITICAL: RPCD script names MUST match ubus object names (use
luci.prefix) - CRITICAL: Menu paths MUST match view file directory structure
- CRITICAL: Always run
./secubox-tools/validate-modules.shbefore committing - All modules use Apache-2.0 license
- RPCD backends must be executable (chmod +x)
- JavaScript files use strict mode:
'use strict'; - Menu entries require proper dependency chain
- ACL must grant both ubus call and luci-cgi access
- UCI config files are optional (many modules don't need them)
- All packages build as architecture
all(no compiled code)