Initial commit: SecuBox v1.0.0

This commit is contained in:
CyberMind-FR 2025-12-21 09:46:33 +01:00
commit 0981987c10
15 changed files with 2919 additions and 0 deletions

View File

@ -0,0 +1,551 @@
name: Build OpenWrt Packages
on:
push:
branches: [main, master, develop]
tags:
- 'v*'
pull_request:
branches: [main, master]
workflow_dispatch:
inputs:
openwrt_version:
description: 'OpenWrt version'
required: true
default: '23.05.5'
type: choice
options:
- '23.05.5'
- '23.05.4'
- '22.03.7'
- 'SNAPSHOT'
architectures:
description: 'Architectures to build (comma-separated or "all")'
required: false
default: 'all'
env:
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
jobs:
# ============================================
# Determine build matrix
# ============================================
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: version
run: |
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION="${{ github.ref_name }}"
else
VERSION="0.0.0-$(git rev-parse --short HEAD)"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "📦 Package version: ${VERSION#v}"
- name: Set build matrix
id: set-matrix
run: |
# Full architecture matrix for OpenWrt
# Format: target/subtarget -> SDK name mapping
ALL_TARGETS=$(cat << 'EOF'
{
"include": [
{
"target": "x86-64",
"arch": "x86_64",
"sdk_name": "x86-64",
"description": "x86 64-bit (PC, VM, containers)"
},
{
"target": "x86-generic",
"arch": "i386_pentium4",
"sdk_name": "x86-generic",
"description": "x86 32-bit (legacy PC)"
},
{
"target": "aarch64-generic",
"arch": "aarch64_generic",
"sdk_name": "armsr-armv8",
"description": "ARM 64-bit generic (RPi4, Rock64)"
},
{
"target": "aarch64-cortex-a53",
"arch": "aarch64_cortex-a53",
"sdk_name": "mvebu-cortexa53",
"description": "ARM Cortex-A53 (ESPRESSObin, Sheeva64)"
},
{
"target": "aarch64-cortex-a72",
"arch": "aarch64_cortex-a72",
"sdk_name": "mvebu-cortexa72",
"description": "ARM Cortex-A72 (MOCHAbin, MACCHIATObin)"
},
{
"target": "arm-cortex-a7-neon",
"arch": "arm_cortex-a7_neon-vfpv4",
"sdk_name": "sunxi-cortexa7",
"description": "ARM Cortex-A7 (Orange Pi, Banana Pi)"
},
{
"target": "arm-cortex-a9-neon",
"arch": "arm_cortex-a9_neon",
"sdk_name": "mvebu-cortexa9",
"description": "ARM Cortex-A9 (Linksys WRT, Turris)"
},
{
"target": "arm-cortex-a15-neon",
"arch": "arm_cortex-a15_neon-vfpv4",
"sdk_name": "armvirt-32",
"description": "ARM Cortex-A15 (QEMU ARM)"
},
{
"target": "mips-24kc",
"arch": "mips_24kc",
"sdk_name": "ath79-generic",
"description": "MIPS 24Kc (TP-Link, Ubiquiti)"
},
{
"target": "mipsel-24kc",
"arch": "mipsel_24kc",
"sdk_name": "ramips-mt7621",
"description": "MIPS Little-Endian (Xiaomi, GL.iNet)"
},
{
"target": "mipsel-74kc",
"arch": "mipsel_74kc",
"sdk_name": "bcm47xx-mips74k",
"description": "MIPS 74Kc (Broadcom routers)"
},
{
"target": "mediatek-filogic",
"arch": "aarch64_cortex-a53",
"sdk_name": "mediatek-filogic",
"description": "MediaTek Filogic (MT7981, MT7986)"
},
{
"target": "qualcomm-ipq40xx",
"arch": "arm_cortex-a7_neon-vfpv4",
"sdk_name": "ipq40xx-generic",
"description": "Qualcomm IPQ40xx (Google WiFi, Zyxel)"
},
{
"target": "qualcomm-ipq806x",
"arch": "arm_cortex-a15_neon-vfpv4",
"sdk_name": "ipq806x-generic",
"description": "Qualcomm IPQ806x (Netgear R7800)"
},
{
"target": "rockchip-armv8",
"arch": "aarch64_generic",
"sdk_name": "rockchip-armv8",
"description": "Rockchip (NanoPi R4S, R5S)"
},
{
"target": "bcm27xx-bcm2711",
"arch": "aarch64_cortex-a72",
"sdk_name": "bcm27xx-bcm2711",
"description": "Raspberry Pi 4"
}
]
}
EOF
)
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
MATRIX="$ALL_TARGETS"
else
# Filter matrix based on input
MATRIX=$(echo "$ALL_TARGETS" | jq -c --arg archs "$INPUT_ARCHS" '
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t or . == "all")))
')
fi
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
echo "📋 Build matrix:"
echo "$MATRIX" | jq '.'
# ============================================
# Build packages for each architecture
# ============================================
build:
needs: setup
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
name: Build ${{ matrix.target }}
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
df -h
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils python3-setuptools rsync \
swig unzip zlib1g-dev file wget curl jq
- name: Cache OpenWrt SDK
uses: actions/cache@v4
id: cache-sdk
with:
path: ~/sdk
key: openwrt-sdk-${{ env.OPENWRT_VERSION }}-${{ matrix.sdk_name }}
- name: Download OpenWrt SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
run: |
echo "📥 Downloading SDK for ${{ matrix.description }}..."
VERSION="${{ env.OPENWRT_VERSION }}"
SDK_NAME="${{ matrix.sdk_name }}"
if [[ "$VERSION" == "SNAPSHOT" ]]; then
BASE_URL="https://downloads.openwrt.org/snapshots/targets"
else
BASE_URL="https://downloads.openwrt.org/releases/${VERSION}/targets"
fi
# Parse target/subtarget from sdk_name
TARGET=$(echo "$SDK_NAME" | cut -d'-' -f1)
SUBTARGET=$(echo "$SDK_NAME" | cut -d'-' -f2-)
SDK_URL="${BASE_URL}/${TARGET}/${SUBTARGET}"
echo "🔍 Looking for SDK at: $SDK_URL"
# Find SDK filename
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.(xz|zst)' | head -1)
if [[ -z "$SDK_FILE" ]]; then
echo "⚠️ SDK not found, trying alternative URL pattern..."
SDK_FILE=$(curl -sL "$SDK_URL/sha256sums" | grep -oP 'openwrt-sdk[^\s]+' | head -1)
fi
if [[ -z "$SDK_FILE" ]]; then
echo "❌ Could not find SDK for ${{ matrix.target }}"
echo "🔗 Checked: $SDK_URL"
exit 1
fi
echo "📦 Downloading: $SDK_FILE"
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz || \
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.zst
mkdir -p ~/sdk
if [[ "$SDK_FILE" == *.zst ]]; then
zstd -d /tmp/sdk.tar.zst -o /tmp/sdk.tar
tar -xf /tmp/sdk.tar -C ~/sdk --strip-components=1
else
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
fi
echo "✅ SDK extracted to ~/sdk"
- name: Prepare SDK
run: |
cd ~/sdk
# Update feeds
echo "📋 Updating feeds..."
./scripts/feeds update -a
./scripts/feeds install -a
# Configure SDK
echo "⚙️ Configuring SDK..."
make defconfig
- name: Copy packages to SDK
run: |
echo "📁 Copying SecuBox packages to SDK..."
# List of our packages
PACKAGES=(
"luci-app-crowdsec-dashboard"
"luci-app-netdata-dashboard"
"luci-app-netifyd-dashboard"
"luci-app-wireguard-dashboard"
"luci-app-network-modes"
"luci-app-client-guardian"
"luci-app-system-hub"
)
# Create package directory
mkdir -p ~/sdk/package/secubox
# Copy each package if it exists
for pkg in "${PACKAGES[@]}"; do
if [[ -d "$GITHUB_WORKSPACE/$pkg" ]]; then
echo " 📦 $pkg"
cp -r "$GITHUB_WORKSPACE/$pkg" ~/sdk/package/secubox/
else
echo " ⚠️ $pkg not found in repository"
fi
done
# If packages are in a subdirectory
if [[ -d "$GITHUB_WORKSPACE/packages" ]]; then
cp -r "$GITHUB_WORKSPACE/packages/"* ~/sdk/package/secubox/ 2>/dev/null || true
fi
# List what we have
echo "📋 Packages in SDK:"
ls -la ~/sdk/package/secubox/ || echo " (empty)"
- name: Update package version
run: |
VERSION="${{ needs.setup.outputs.version }}"
echo "📝 Setting package version to: $VERSION"
# Update Makefile version in each package
for makefile in ~/sdk/package/secubox/*/Makefile; do
if [[ -f "$makefile" ]]; then
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "$makefile"
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "$makefile"
echo " ✅ Updated: $(dirname $makefile | xargs basename)"
fi
done
- name: Build packages
run: |
cd ~/sdk
echo "🔨 Building SecuBox packages for ${{ matrix.description }}..."
# Enable our packages
for pkg in ~/sdk/package/secubox/*/; do
PKG_NAME=$(basename "$pkg")
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
done
make defconfig
# Build with verbose output on error
make package/secubox/compile V=s -j$(nproc) || {
echo "❌ Build failed, retrying with single thread..."
make package/secubox/compile V=s -j1
}
# Generate package index
make package/index V=s
- name: Collect artifacts
id: collect
run: |
echo "📦 Collecting built packages..."
mkdir -p $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
# Find and copy .ipk files
find ~/sdk/bin -name "*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \;
# Copy package index
find ~/sdk/bin -name "Packages*" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
# List artifacts
echo "📋 Built packages for ${{ matrix.target }}:"
ls -la $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/
# Count packages
PKG_COUNT=$(find $GITHUB_WORKSPACE/artifacts/${{ matrix.target }} -name "*.ipk" | wc -l)
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
if [[ $PKG_COUNT -eq 0 ]]; then
echo "⚠️ No packages built!"
exit 1
fi
- name: Create checksums
run: |
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
sha256sum *.ipk > SHA256SUMS
echo "✅ Checksums created"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: packages-${{ matrix.target }}
path: artifacts/${{ matrix.target }}/
retention-days: 30
# ============================================
# Create combined release
# ============================================
release:
needs: [setup, build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
- name: Organize packages
run: |
echo "📁 Organizing release packages..."
VERSION="${{ needs.setup.outputs.version }}"
mkdir -p release
# Create architecture-specific archives
for arch_dir in packages/packages-*/; do
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
echo "📦 Processing $ARCH..."
# Create tarball
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "$arch_dir" .
# Copy individual .ipk files to flat structure
mkdir -p "release/ipk/${ARCH}"
cp "$arch_dir"/*.ipk "release/ipk/${ARCH}/" 2>/dev/null || true
done
# Create "all architectures" mega-archive
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C packages .
# Create release notes
cat > release/RELEASE_NOTES.md << EOF
# SecuBox $VERSION
## 📦 Packages Included
- luci-app-crowdsec-dashboard - CrowdSec Security Dashboard
- luci-app-netdata-dashboard - Netdata Monitoring Dashboard
- luci-app-netifyd-dashboard - Netifyd DPI Dashboard
- luci-app-wireguard-dashboard - WireGuard VPN Dashboard
- luci-app-network-modes - Network Mode Switcher
- luci-app-client-guardian - NAC & Captive Portal
- luci-app-system-hub - System Hub Control Center
## 🏗️ Supported Architectures
| Target | Architecture | Description |
|--------|--------------|-------------|
| x86-64 | x86_64 | PC, VMs, Containers |
| aarch64-cortex-a53 | aarch64 | ESPRESSObin, Sheeva64 |
| aarch64-cortex-a72 | aarch64 | MOCHAbin, RPi4 |
| arm-cortex-a7 | arm | Orange Pi, Banana Pi |
| arm-cortex-a9 | arm | Linksys WRT, Turris |
| mips-24kc | mips | TP-Link, Ubiquiti |
| mipsel-24kc | mipsel | Xiaomi, GL.iNet |
| mediatek-filogic | aarch64 | MT7981, MT7986 |
| qualcomm-ipq40xx | arm | Google WiFi |
| rockchip-armv8 | aarch64 | NanoPi R4S, R5S |
## 📥 Installation
\`\`\`bash
# Download package for your architecture
opkg update
opkg install luci-app-crowdsec-dashboard_${VERSION}_*.ipk
# ... install other packages as needed
\`\`\`
## 🔗 Links
- [Documentation](https://cybermind.fr/docs/secubox)
- [GitHub](https://github.com/gkerma)
- [CyberMind.fr](https://cybermind.fr)
---
Built with OpenWrt SDK ${{ env.OPENWRT_VERSION }}
EOF
echo "✅ Release organized"
ls -la release/
- name: Create global checksums
run: |
cd release
sha256sum *.tar.gz > SHA256SUMS
echo "✅ Global checksums created"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: SecuBox ${{ needs.setup.outputs.version }}
body_path: release/RELEASE_NOTES.md
files: |
release/*.tar.gz
release/SHA256SUMS
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================
# Build status summary
# ============================================
summary:
needs: [setup, build]
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
continue-on-error: true
- name: Generate build summary
run: |
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ needs.setup.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**OpenWrt:** ${{ env.OPENWRT_VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Architecture | Status | Packages |" >> $GITHUB_STEP_SUMMARY
echo "|--------------|--------|----------|" >> $GITHUB_STEP_SUMMARY
for arch_dir in packages/packages-*/; do
if [[ -d "$arch_dir" ]]; then
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
PKG_COUNT=$(find "$arch_dir" -name "*.ipk" 2>/dev/null | wc -l)
if [[ $PKG_COUNT -gt 0 ]]; then
echo "| $ARCH | ✅ Success | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
else
echo "| $ARCH | ⚠️ No packages | 0 |" >> $GITHUB_STEP_SUMMARY
fi
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Download artifacts from the Actions tab above." >> $GITHUB_STEP_SUMMARY

View File

@ -0,0 +1,398 @@
name: Build SecuBox Images (GlobalScale)
on:
workflow_dispatch:
inputs:
device:
description: 'Target device'
required: true
type: choice
options:
- espressobin-v7
- espressobin-ultra
- sheeva64
- sheeva64-wifi
- mochabin
- all
openwrt_version:
description: 'OpenWrt version'
required: true
default: '23.05.5'
type: choice
options:
- '23.05.5'
- '23.05.4'
- 'SNAPSHOT'
include_secubox:
description: 'Include SecuBox packages'
required: true
type: boolean
default: true
env:
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version }}
jobs:
# ============================================
# Build firmware images for GlobalScale devices
# ============================================
build-image:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- device: espressobin-v7
target: mvebu
subtarget: cortexa53
profile: globalscale_espressobin
description: "ESPRESSObin V7 (1-2GB DDR4)"
enabled: ${{ github.event.inputs.device == 'espressobin-v7' || github.event.inputs.device == 'all' }}
- device: espressobin-ultra
target: mvebu
subtarget: cortexa53
profile: globalscale_espressobin-ultra
description: "ESPRESSObin Ultra (PoE, WiFi)"
enabled: ${{ github.event.inputs.device == 'espressobin-ultra' || github.event.inputs.device == 'all' }}
- device: sheeva64
target: mvebu
subtarget: cortexa53
profile: globalscale_sheeva64
description: "Sheeva64 (Plug computer)"
enabled: ${{ github.event.inputs.device == 'sheeva64' || github.event.inputs.device == 'all' }}
- device: sheeva64-wifi
target: mvebu
subtarget: cortexa53
profile: globalscale_sheeva64
description: "Sheeva64 WiFi (802.11ac + BT)"
enabled: ${{ github.event.inputs.device == 'sheeva64-wifi' || github.event.inputs.device == 'all' }}
- device: mochabin
target: mvebu
subtarget: cortexa72
profile: globalscale_mochabin
description: "MOCHAbin (Quad-core A72, 10G)"
enabled: ${{ github.event.inputs.device == 'mochabin' || github.event.inputs.device == 'all' }}
name: ${{ matrix.description }}
if: ${{ matrix.enabled != 'false' }}
steps:
- name: Checkout SecuBox packages
uses: actions/checkout@v4
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo docker image prune --all --force
df -h
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils python3-setuptools rsync \
swig unzip zlib1g-dev file wget curl qemu-utils
- name: Clone OpenWrt
run: |
if [[ "${{ env.OPENWRT_VERSION }}" == "SNAPSHOT" ]]; then
git clone --depth 1 https://github.com/openwrt/openwrt.git openwrt
else
git clone --depth 1 --branch v${{ env.OPENWRT_VERSION }} \
https://github.com/openwrt/openwrt.git openwrt
fi
- name: Update feeds
run: |
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
- name: Copy SecuBox packages
if: ${{ github.event.inputs.include_secubox == 'true' }}
run: |
mkdir -p openwrt/package/secubox
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
echo "📦 Adding $pkg"
cp -r "$pkg" openwrt/package/secubox/
fi
done
- name: Generate SecuBox config
run: |
cd openwrt
# Base configuration
cat > .config << EOF
# Target
CONFIG_TARGET_${{ matrix.target }}=y
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}=y
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}_DEVICE_${{ matrix.profile }}=y
# Image settings
CONFIG_TARGET_ROOTFS_SQUASHFS=y
CONFIG_TARGET_ROOTFS_EXT4FS=y
CONFIG_TARGET_KERNEL_PARTSIZE=32
CONFIG_TARGET_ROOTFS_PARTSIZE=512
# Base packages
CONFIG_PACKAGE_luci=y
CONFIG_PACKAGE_luci-ssl=y
CONFIG_PACKAGE_luci-app-opkg=y
CONFIG_PACKAGE_luci-theme-openwrt-2020=y
# Networking essentials
CONFIG_PACKAGE_curl=y
CONFIG_PACKAGE_wget-ssl=y
CONFIG_PACKAGE_iptables=y
CONFIG_PACKAGE_ip6tables=y
CONFIG_PACKAGE_kmod-nft-core=y
# USB support
CONFIG_PACKAGE_kmod-usb-core=y
CONFIG_PACKAGE_kmod-usb3=y
CONFIG_PACKAGE_kmod-usb-storage=y
# Filesystem
CONFIG_PACKAGE_kmod-fs-ext4=y
CONFIG_PACKAGE_kmod-fs-vfat=y
CONFIG_PACKAGE_block-mount=y
# Wireless (if applicable)
CONFIG_PACKAGE_hostapd-common=y
CONFIG_PACKAGE_wpad-basic-mbedtls=y
# Monitoring tools
CONFIG_PACKAGE_htop=y
CONFIG_PACKAGE_iftop=y
CONFIG_PACKAGE_tcpdump=y
# SSH
CONFIG_PACKAGE_openssh-sftp-server=y
EOF
- name: Add SecuBox packages to config
if: ${{ github.event.inputs.include_secubox == 'true' }}
run: |
cd openwrt
# CrowdSec
cat >> .config << EOF
CONFIG_PACKAGE_crowdsec=y
CONFIG_PACKAGE_crowdsec-firewall-bouncer=y
CONFIG_PACKAGE_luci-app-crowdsec-dashboard=y
EOF
# Netdata
cat >> .config << EOF
CONFIG_PACKAGE_netdata=y
CONFIG_PACKAGE_luci-app-netdata-dashboard=y
EOF
# Netifyd
cat >> .config << EOF
CONFIG_PACKAGE_netifyd=y
CONFIG_PACKAGE_luci-app-netifyd-dashboard=y
EOF
# WireGuard
cat >> .config << EOF
CONFIG_PACKAGE_wireguard-tools=y
CONFIG_PACKAGE_kmod-wireguard=y
CONFIG_PACKAGE_luci-app-wireguard-dashboard=y
CONFIG_PACKAGE_qrencode=y
EOF
# SecuBox core
cat >> .config << EOF
CONFIG_PACKAGE_luci-app-network-modes=y
CONFIG_PACKAGE_luci-app-client-guardian=y
CONFIG_PACKAGE_luci-app-system-hub=y
EOF
- name: Add device-specific packages
run: |
cd openwrt
case "${{ matrix.device }}" in
mochabin)
# 10G networking, more RAM
cat >> .config << EOF
CONFIG_PACKAGE_kmod-sfp=y
CONFIG_PACKAGE_kmod-phy-marvell-10g=y
CONFIG_PACKAGE_prometheus-node-exporter-lua=y
EOF
;;
espressobin-ultra|sheeva64-wifi)
# WiFi support
cat >> .config << EOF
CONFIG_PACKAGE_kmod-mt76=y
CONFIG_PACKAGE_kmod-mac80211=y
EOF
;;
sheeva64*)
# Minimal for plug computer
cat >> .config << EOF
# Optimized for plug form factor
CONFIG_PACKAGE_kmod-ledtrig-heartbeat=y
EOF
;;
esac
- name: Make defconfig
run: |
cd openwrt
make defconfig
- name: Download packages
run: |
cd openwrt
make download -j$(nproc) V=s || make download -j1 V=s
- name: Build firmware
run: |
cd openwrt
echo "🔨 Building firmware for ${{ matrix.description }}..."
echo "⏱️ This may take 1-2 hours..."
make -j$(nproc) V=s 2>&1 | tee build.log || {
echo "❌ Build failed, retrying with single thread..."
make -j1 V=s 2>&1 | tee build-retry.log
}
- name: Prepare artifacts
run: |
mkdir -p artifacts
# Copy firmware images
find openwrt/bin/targets -name "*.img.gz" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*.bin" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*sysupgrade*" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*factory*" -exec cp {} artifacts/ \;
# Copy packages
mkdir -p artifacts/packages
find openwrt/bin/packages -name "luci-app-*secubox*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
find openwrt/bin/packages -name "luci-app-*dashboard*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
# Generate checksums
cd artifacts
sha256sum * > SHA256SUMS 2>/dev/null || true
# Create info file
cat > BUILD_INFO.txt << EOF
SecuBox Firmware Build
=======================
Device: ${{ matrix.description }}
Profile: ${{ matrix.profile }}
Target: ${{ matrix.target }}/${{ matrix.subtarget }}
OpenWrt: ${{ env.OPENWRT_VERSION }}
SecuBox: ${{ github.event.inputs.include_secubox }}
Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)
Commit: ${{ github.sha }}
EOF
echo "📦 Artifacts:"
ls -la
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}
path: artifacts/
retention-days: 30
# ============================================
# Create combined release for all devices
# ============================================
release:
needs: build-image
runs-on: ubuntu-latest
if: github.event.inputs.device == 'all'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: firmware
pattern: secubox-*
- name: Organize release
run: |
mkdir -p release
for device_dir in firmware/secubox-*/; do
DEVICE=$(basename "$device_dir" | sed 's/secubox-//' | sed "s/-${{ env.OPENWRT_VERSION }}//")
echo "📦 Processing $DEVICE..."
# Create device archive
tar -czf "release/secubox-firmware-${DEVICE}.tar.gz" -C "$device_dir" .
done
# Global checksums
cd release
sha256sum *.tar.gz > SHA256SUMS
# Release notes
cat > RELEASE_NOTES.md << 'EOF'
# SecuBox Firmware Images
Pre-built firmware images for GlobalScale devices with SecuBox modules pre-installed.
## Included Devices
| Device | SoC | RAM | Description |
|--------|-----|-----|-------------|
| ESPRESSObin V7 | Armada 3720 | 1-2GB | Entry-level |
| ESPRESSObin Ultra | Armada 3720 | 1-2GB | WiFi + PoE |
| Sheeva64 | Armada 3720 | 1GB | Plug computer |
| MOCHAbin | Armada 7040 | 4-8GB | Quad-core + 10G |
## Pre-installed SecuBox Modules
- luci-app-crowdsec-dashboard
- luci-app-netdata-dashboard
- luci-app-netifyd-dashboard
- luci-app-wireguard-dashboard
- luci-app-network-modes
- luci-app-client-guardian
- luci-app-system-hub
## Installation
1. Download the appropriate firmware for your device
2. Flash using OpenWrt sysupgrade or manufacturer tools
3. Access LuCI at http://192.168.1.1
4. Navigate to Services → SecuBox
## Support
- [Documentation](https://cybermind.fr/docs/secubox)
- [CyberMind.fr](https://cybermind.fr)
EOF
- name: Create release
if: github.ref == 'refs/heads/main'
uses: softprops/action-gh-release@v2
with:
name: "SecuBox Firmware ${{ env.OPENWRT_VERSION }}"
tag_name: "firmware-${{ env.OPENWRT_VERSION }}-${{ github.run_number }}"
body_path: release/RELEASE_NOTES.md
files: |
release/*.tar.gz
release/SHA256SUMS
draft: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

327
.github/workflows/test-validate.yml vendored Normal file
View File

@ -0,0 +1,327 @@
name: Test & Validate Packages
on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master]
jobs:
# ============================================
# Lint and validate package structure
# ============================================
lint:
runs-on: ubuntu-latest
name: Lint & Validate
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install validators
run: |
sudo apt-get update
sudo apt-get install -y shellcheck jq
- name: Validate Makefile structure
run: |
echo "📋 Validating Makefile structure..."
ERRORS=0
for makefile in */Makefile; do
if [[ -f "$makefile" ]]; then
PKG=$(dirname "$makefile")
echo " 🔍 Checking $PKG..."
# Required fields
REQUIRED_FIELDS=(
"PKG_NAME"
"PKG_VERSION"
"PKG_RELEASE"
"PKG_LICENSE"
"LUCI_TITLE"
)
for field in "${REQUIRED_FIELDS[@]}"; do
if ! grep -q "^${field}:=" "$makefile"; then
echo " ❌ Missing: $field"
ERRORS=$((ERRORS + 1))
fi
done
# Check for include statements
if ! grep -q "include.*luci.mk\|include.*package.mk" "$makefile"; then
echo " ❌ Missing include statement (luci.mk or package.mk)"
ERRORS=$((ERRORS + 1))
fi
fi
done
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS errors"
exit 1
fi
echo "✅ All Makefiles valid"
- name: Validate JSON files
run: |
echo "📋 Validating JSON files..."
ERRORS=0
# Find all JSON files
while IFS= read -r jsonfile; do
echo " 🔍 Checking $jsonfile..."
if ! jq empty "$jsonfile" 2>/dev/null; then
echo " ❌ Invalid JSON"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.json" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS JSON errors"
exit 1
fi
echo "✅ All JSON files valid"
- name: Validate JavaScript syntax
run: |
echo "📋 Validating JavaScript files..."
# Install node for syntax check
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
ERRORS=0
while IFS= read -r jsfile; do
echo " 🔍 Checking $jsfile..."
if ! node --check "$jsfile" 2>/dev/null; then
echo " ❌ Syntax error"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.js" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS JavaScript errors"
exit 1
fi
echo "✅ All JavaScript files valid"
- name: Validate shell scripts
run: |
echo "📋 Validating shell scripts..."
ERRORS=0
# Check RPCD scripts
while IFS= read -r script; do
echo " 🔍 Checking $script..."
if ! shellcheck -s sh "$script"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/rpcd/*" -type f -executable)
# Check init scripts
while IFS= read -r script; do
echo " 🔍 Checking $script..."
if ! shellcheck -s sh "$script"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/init.d/*" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "⚠️ Found $ERRORS shellcheck warnings (non-blocking)"
fi
echo "✅ Shell script validation complete"
- name: Check file permissions
run: |
echo "📋 Checking file permissions..."
ERRORS=0
# RPCD scripts should be executable
while IFS= read -r script; do
if [[ ! -x "$script" ]]; then
echo " ❌ Not executable: $script"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/usr/libexec/rpcd/*" -type f 2>/dev/null)
# Init scripts should be executable
while IFS= read -r script; do
if [[ ! -x "$script" ]]; then
echo " ❌ Not executable: $script"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS permission errors"
exit 1
fi
echo "✅ File permissions correct"
- name: Validate package structure
run: |
echo "📋 Validating package structure..."
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
echo " 📦 Checking $pkg..."
# Required directories/files
REQUIRED=(
"Makefile"
)
# Optional but recommended
RECOMMENDED=(
"htdocs/luci-static/resources"
"root/usr/share/luci/menu.d"
"root/usr/share/rpcd/acl.d"
)
for req in "${REQUIRED[@]}"; do
if [[ ! -e "${pkg}${req}" ]]; then
echo " ❌ Missing required: $req"
exit 1
fi
done
for rec in "${RECOMMENDED[@]}"; do
if [[ ! -e "${pkg}${rec}" ]]; then
echo " ⚠️ Missing recommended: $rec"
fi
done
fi
done
echo "✅ Package structure valid"
# ============================================
# Quick build test on x86_64
# ============================================
test-build:
runs-on: ubuntu-latest
name: Test Build (x86_64)
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils rsync unzip zlib1g-dev wget
- name: Cache OpenWrt SDK
uses: actions/cache@v4
id: cache-sdk
with:
path: ~/sdk
key: openwrt-sdk-23.05.5-x86-64-test
- name: Download OpenWrt SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
run: |
SDK_URL="https://downloads.openwrt.org/releases/23.05.5/targets/x86/64"
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.xz' | head -1)
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
mkdir -p ~/sdk
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
- name: Prepare SDK
run: |
cd ~/sdk
./scripts/feeds update -a
./scripts/feeds install -a
make defconfig
- name: Copy packages
run: |
mkdir -p ~/sdk/package/secubox
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
cp -r "$pkg" ~/sdk/package/secubox/
fi
done
- name: Build test
run: |
cd ~/sdk
# Enable packages
for pkg in ~/sdk/package/secubox/*/; do
PKG_NAME=$(basename "$pkg")
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
done
make defconfig
# Build with timeout
timeout 30m make package/secubox/compile V=s -j$(nproc) || {
echo "⚠️ Build timeout or error"
exit 1
}
- name: Verify output
run: |
echo "📋 Built packages:"
find ~/sdk/bin -name "*.ipk" -exec ls -la {} \;
PKG_COUNT=$(find ~/sdk/bin -name "*.ipk" | wc -l)
echo "📦 Total packages built: $PKG_COUNT"
if [[ $PKG_COUNT -eq 0 ]]; then
echo "❌ No packages were built!"
exit 1
fi
# ============================================
# Generate documentation
# ============================================
docs:
runs-on: ubuntu-latest
name: Generate Docs
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Generate package list
run: |
echo "# SecuBox Packages" > PACKAGES.md
echo "" >> PACKAGES.md
echo "| Package | Version | Description |" >> PACKAGES.md
echo "|---------|---------|-------------|" >> PACKAGES.md
for makefile in luci-app-*/Makefile; do
if [[ -f "$makefile" ]]; then
PKG_NAME=$(grep "^PKG_NAME:=" "$makefile" | cut -d'=' -f2)
PKG_VERSION=$(grep "^PKG_VERSION:=" "$makefile" | cut -d'=' -f2)
PKG_TITLE=$(grep "^LUCI_TITLE:=" "$makefile" | cut -d'=' -f2-)
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
fi
done
echo "" >> PACKAGES.md
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
cat PACKAGES.md
- name: Upload docs
uses: actions/upload-artifact@v4
with:
name: documentation
path: PACKAGES.md

232
README.md Normal file
View File

@ -0,0 +1,232 @@
# SecuBox OpenWrt CI/CD
[![Build OpenWrt Packages](https://github.com/gkerma/secubox/actions/workflows/build-openwrt-packages.yml/badge.svg)](https://github.com/gkerma/secubox/actions/workflows/build-openwrt-packages.yml)
[![Test & Validate](https://github.com/gkerma/secubox/actions/workflows/test-validate.yml/badge.svg)](https://github.com/gkerma/secubox/actions/workflows/test-validate.yml)
## 🎯 Overview
Ce dépôt contient les workflows GitHub Actions pour compiler automatiquement les packages SecuBox LuCI pour **toutes les architectures OpenWrt supportées**.
## 📦 Packages Compilés
| Package | Description |
|---------|-------------|
| `luci-app-crowdsec-dashboard` | Dashboard CrowdSec |
| `luci-app-netdata-dashboard` | Dashboard Netdata |
| `luci-app-netifyd-dashboard` | Dashboard Netifyd DPI |
| `luci-app-wireguard-dashboard` | Dashboard WireGuard VPN |
| `luci-app-network-modes` | Modes réseau (Router/Bridge/AP) |
| `luci-app-client-guardian` | NAC & Portail Captif |
| `luci-app-system-hub` | Centre de contrôle unifié |
## 🏗️ Architectures Supportées
### ARM 64-bit (AArch64)
| Target | Architecture | Devices |
|--------|--------------|---------|
| `aarch64-cortex-a53` | Cortex-A53 | **ESPRESSObin**, **Sheeva64**, BananaPi R64 |
| `aarch64-cortex-a72` | Cortex-A72 | **MOCHAbin**, Raspberry Pi 4, NanoPi R4S |
| `aarch64-generic` | Generic ARMv8 | Rock64, Pine64, QEMU ARM64 |
| `mediatek-filogic` | MT7981/MT7986 | GL.iNet MT3000, BananaPi R3 |
| `rockchip-armv8` | RK3328/RK3399 | NanoPi R4S, R5S, FriendlyARM |
| `bcm27xx-bcm2711` | BCM2711 | Raspberry Pi 4, Compute Module 4 |
### ARM 32-bit
| Target | Architecture | Devices |
|--------|--------------|---------|
| `arm-cortex-a7-neon` | Cortex-A7 | Orange Pi, BananaPi, Allwinner |
| `arm-cortex-a9-neon` | Cortex-A9 | Linksys WRT, Turris Omnia |
| `arm-cortex-a15-neon` | Cortex-A15 | QEMU ARM |
| `qualcomm-ipq40xx` | IPQ40xx | Google WiFi, Zyxel NBG6617 |
| `qualcomm-ipq806x` | IPQ806x | Netgear R7800, R7500 |
### MIPS
| Target | Architecture | Devices |
|--------|--------------|---------|
| `mips-24kc` | MIPS 24Kc | TP-Link Archer, Ubiquiti |
| `mipsel-24kc` | MIPS LE 24Kc | Xiaomi, GL.iNet, Netgear |
| `mipsel-74kc` | MIPS LE 74Kc | Broadcom BCM47xx |
### x86
| Target | Architecture | Devices |
|--------|--------------|---------|
| `x86-64` | x86_64 | PC, VMs, Docker, Proxmox |
| `x86-generic` | i386 | Legacy PC, old Atom |
## 🚀 Utilisation
### Compilation Automatique
Les packages sont compilés automatiquement lors de :
1. **Push sur `main`/`master`** : Compilation de test
2. **Pull Request** : Validation et test
3. **Tag `v*`** : Création de release avec tous les packages
### Compilation Manuelle
1. Aller dans **Actions** → **Build OpenWrt Packages**
2. Cliquer sur **Run workflow**
3. Sélectionner :
- **OpenWrt version** : 23.05.5, 22.03.7, ou SNAPSHOT
- **Architectures** : `all` ou liste séparée par virgules
```
# Exemples d'architectures
all # Toutes les architectures
x86-64 # Uniquement x86_64
aarch64-cortex-a53,aarch64-cortex-a72 # GlobalScale devices
mips-24kc,mipsel-24kc # MIPS routeurs
```
### Téléchargement des Artifacts
1. Aller dans **Actions** → Sélectionner un workflow
2. Cliquer sur le run souhaité
3. Télécharger les **Artifacts** en bas de page
Les artifacts sont organisés par architecture :
```
packages-x86-64/
├── luci-app-crowdsec-dashboard_1.0.0-1_all.ipk
├── luci-app-netdata-dashboard_1.0.0-1_all.ipk
├── ...
└── SHA256SUMS
```
## 📁 Structure du Dépôt
```
secubox/
├── .github/
│ └── workflows/
│ ├── build-openwrt-packages.yml # Build principal
│ └── test-validate.yml # Tests & validation
├── luci-app-crowdsec-dashboard/
│ ├── Makefile
│ ├── htdocs/luci-static/resources/
│ │ ├── view/crowdsec/ # JavaScript views
│ │ └── crowdsec/ # API & CSS
│ └── root/
│ ├── etc/config/ # UCI config
│ └── usr/
│ ├── libexec/rpcd/ # RPCD backend
│ └── share/
│ ├── luci/menu.d/ # Menu JSON
│ └── rpcd/acl.d/ # ACL JSON
├── luci-app-netdata-dashboard/
├── luci-app-netifyd-dashboard/
├── luci-app-wireguard-dashboard/
├── luci-app-network-modes/
├── luci-app-client-guardian/
├── luci-app-system-hub/
└── README.md
```
## 🔧 Créer un Nouveau Package
1. Copier le template :
```bash
cp -r templates/luci-app-template luci-app-nouveau
```
2. Éditer `Makefile` :
```makefile
PKG_NAME:=luci-app-nouveau
PKG_VERSION:=1.0.0
LUCI_TITLE:=Mon Nouveau Dashboard
LUCI_DEPENDS:=+luci-base +nouveau-backend
```
3. Créer les fichiers requis :
```bash
luci-app-nouveau/
├── Makefile
├── htdocs/luci-static/resources/
│ ├── view/nouveau/
│ │ └── overview.js
│ └── nouveau/
│ ├── api.js
│ └── dashboard.css
└── root/
└── usr/share/
├── luci/menu.d/luci-app-nouveau.json
└── rpcd/acl.d/luci-app-nouveau.json
```
4. Commit et push :
```bash
git add luci-app-nouveau/
git commit -m "feat: add luci-app-nouveau"
git push
```
## 🏷️ Créer une Release
```bash
# Créer un tag versionné
git tag -a v1.2.0 -m "Release 1.2.0"
git push origin v1.2.0
```
La release sera créée automatiquement avec :
- Archives `.tar.gz` par architecture
- Archive globale toutes architectures
- Checksums SHA256
- Notes de release générées
## ⚙️ Configuration CI
### Variables d'Environnement
| Variable | Default | Description |
|----------|---------|-------------|
| `OPENWRT_VERSION` | `23.05.5` | Version OpenWrt SDK |
### Secrets Requis
Aucun secret requis pour la compilation. Le `GITHUB_TOKEN` par défaut suffit pour créer les releases.
### Cache
Le SDK OpenWrt est mis en cache par architecture pour accélérer les builds suivants.
## 🧪 Tests & Validation
Le workflow `test-validate.yml` vérifie :
- ✅ Structure des Makefiles (champs requis)
- ✅ Syntaxe JSON (menu, ACL)
- ✅ Syntaxe JavaScript (views)
- ✅ Scripts shell (shellcheck)
- ✅ Permissions des fichiers
- ✅ Build test sur x86_64
## 📊 Matrice de Compatibilité
| OpenWrt | Status | Notes |
|---------|--------|-------|
| 24.10.x | 🔜 Prévu | En attente release |
| 23.05.x | ✅ Supporté | Recommandé |
| 22.03.x | ✅ Supporté | LTS |
| 21.02.x | ⚠️ Partiel | Fin de support |
| SNAPSHOT | ✅ Supporté | Instable |
## 🔗 Liens
- [OpenWrt SDK Documentation](https://openwrt.org/docs/guide-developer/using_the_sdk)
- [LuCI Development Guide](https://github.com/openwrt/luci/wiki)
- [CyberMind.fr](https://cybermind.fr)
- [SecuBox Project](https://cybermind.fr/secubox)
## 📄 License
Apache-2.0 © 2025 CyberMind.fr
---
**Made with ❤️ in France 🇫🇷**

551
build-openwrt-packages.yml Normal file
View File

@ -0,0 +1,551 @@
name: Build OpenWrt Packages
on:
push:
branches: [main, master, develop]
tags:
- 'v*'
pull_request:
branches: [main, master]
workflow_dispatch:
inputs:
openwrt_version:
description: 'OpenWrt version'
required: true
default: '23.05.5'
type: choice
options:
- '23.05.5'
- '23.05.4'
- '22.03.7'
- 'SNAPSHOT'
architectures:
description: 'Architectures to build (comma-separated or "all")'
required: false
default: 'all'
env:
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version || '23.05.5' }}
jobs:
# ============================================
# Determine build matrix
# ============================================
setup:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version
id: version
run: |
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION="${{ github.ref_name }}"
else
VERSION="0.0.0-$(git rev-parse --short HEAD)"
fi
echo "version=${VERSION#v}" >> $GITHUB_OUTPUT
echo "📦 Package version: ${VERSION#v}"
- name: Set build matrix
id: set-matrix
run: |
# Full architecture matrix for OpenWrt
# Format: target/subtarget -> SDK name mapping
ALL_TARGETS=$(cat << 'EOF'
{
"include": [
{
"target": "x86-64",
"arch": "x86_64",
"sdk_name": "x86-64",
"description": "x86 64-bit (PC, VM, containers)"
},
{
"target": "x86-generic",
"arch": "i386_pentium4",
"sdk_name": "x86-generic",
"description": "x86 32-bit (legacy PC)"
},
{
"target": "aarch64-generic",
"arch": "aarch64_generic",
"sdk_name": "armsr-armv8",
"description": "ARM 64-bit generic (RPi4, Rock64)"
},
{
"target": "aarch64-cortex-a53",
"arch": "aarch64_cortex-a53",
"sdk_name": "mvebu-cortexa53",
"description": "ARM Cortex-A53 (ESPRESSObin, Sheeva64)"
},
{
"target": "aarch64-cortex-a72",
"arch": "aarch64_cortex-a72",
"sdk_name": "mvebu-cortexa72",
"description": "ARM Cortex-A72 (MOCHAbin, MACCHIATObin)"
},
{
"target": "arm-cortex-a7-neon",
"arch": "arm_cortex-a7_neon-vfpv4",
"sdk_name": "sunxi-cortexa7",
"description": "ARM Cortex-A7 (Orange Pi, Banana Pi)"
},
{
"target": "arm-cortex-a9-neon",
"arch": "arm_cortex-a9_neon",
"sdk_name": "mvebu-cortexa9",
"description": "ARM Cortex-A9 (Linksys WRT, Turris)"
},
{
"target": "arm-cortex-a15-neon",
"arch": "arm_cortex-a15_neon-vfpv4",
"sdk_name": "armvirt-32",
"description": "ARM Cortex-A15 (QEMU ARM)"
},
{
"target": "mips-24kc",
"arch": "mips_24kc",
"sdk_name": "ath79-generic",
"description": "MIPS 24Kc (TP-Link, Ubiquiti)"
},
{
"target": "mipsel-24kc",
"arch": "mipsel_24kc",
"sdk_name": "ramips-mt7621",
"description": "MIPS Little-Endian (Xiaomi, GL.iNet)"
},
{
"target": "mipsel-74kc",
"arch": "mipsel_74kc",
"sdk_name": "bcm47xx-mips74k",
"description": "MIPS 74Kc (Broadcom routers)"
},
{
"target": "mediatek-filogic",
"arch": "aarch64_cortex-a53",
"sdk_name": "mediatek-filogic",
"description": "MediaTek Filogic (MT7981, MT7986)"
},
{
"target": "qualcomm-ipq40xx",
"arch": "arm_cortex-a7_neon-vfpv4",
"sdk_name": "ipq40xx-generic",
"description": "Qualcomm IPQ40xx (Google WiFi, Zyxel)"
},
{
"target": "qualcomm-ipq806x",
"arch": "arm_cortex-a15_neon-vfpv4",
"sdk_name": "ipq806x-generic",
"description": "Qualcomm IPQ806x (Netgear R7800)"
},
{
"target": "rockchip-armv8",
"arch": "aarch64_generic",
"sdk_name": "rockchip-armv8",
"description": "Rockchip (NanoPi R4S, R5S)"
},
{
"target": "bcm27xx-bcm2711",
"arch": "aarch64_cortex-a72",
"sdk_name": "bcm27xx-bcm2711",
"description": "Raspberry Pi 4"
}
]
}
EOF
)
INPUT_ARCHS="${{ github.event.inputs.architectures }}"
if [[ -z "$INPUT_ARCHS" || "$INPUT_ARCHS" == "all" ]]; then
MATRIX="$ALL_TARGETS"
else
# Filter matrix based on input
MATRIX=$(echo "$ALL_TARGETS" | jq -c --arg archs "$INPUT_ARCHS" '
.include |= map(select(.target as $t | $archs | split(",") | map(gsub("^\\s+|\\s+$";"")) | any(. == $t or . == "all")))
')
fi
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
echo "📋 Build matrix:"
echo "$MATRIX" | jq '.'
# ============================================
# Build packages for each architecture
# ============================================
build:
needs: setup
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
name: Build ${{ matrix.target }}
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
df -h
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils python3-setuptools rsync \
swig unzip zlib1g-dev file wget curl jq
- name: Cache OpenWrt SDK
uses: actions/cache@v4
id: cache-sdk
with:
path: ~/sdk
key: openwrt-sdk-${{ env.OPENWRT_VERSION }}-${{ matrix.sdk_name }}
- name: Download OpenWrt SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
run: |
echo "📥 Downloading SDK for ${{ matrix.description }}..."
VERSION="${{ env.OPENWRT_VERSION }}"
SDK_NAME="${{ matrix.sdk_name }}"
if [[ "$VERSION" == "SNAPSHOT" ]]; then
BASE_URL="https://downloads.openwrt.org/snapshots/targets"
else
BASE_URL="https://downloads.openwrt.org/releases/${VERSION}/targets"
fi
# Parse target/subtarget from sdk_name
TARGET=$(echo "$SDK_NAME" | cut -d'-' -f1)
SUBTARGET=$(echo "$SDK_NAME" | cut -d'-' -f2-)
SDK_URL="${BASE_URL}/${TARGET}/${SUBTARGET}"
echo "🔍 Looking for SDK at: $SDK_URL"
# Find SDK filename
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.(xz|zst)' | head -1)
if [[ -z "$SDK_FILE" ]]; then
echo "⚠️ SDK not found, trying alternative URL pattern..."
SDK_FILE=$(curl -sL "$SDK_URL/sha256sums" | grep -oP 'openwrt-sdk[^\s]+' | head -1)
fi
if [[ -z "$SDK_FILE" ]]; then
echo "❌ Could not find SDK for ${{ matrix.target }}"
echo "🔗 Checked: $SDK_URL"
exit 1
fi
echo "📦 Downloading: $SDK_FILE"
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz || \
wget -q --show-progress "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.zst
mkdir -p ~/sdk
if [[ "$SDK_FILE" == *.zst ]]; then
zstd -d /tmp/sdk.tar.zst -o /tmp/sdk.tar
tar -xf /tmp/sdk.tar -C ~/sdk --strip-components=1
else
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
fi
echo "✅ SDK extracted to ~/sdk"
- name: Prepare SDK
run: |
cd ~/sdk
# Update feeds
echo "📋 Updating feeds..."
./scripts/feeds update -a
./scripts/feeds install -a
# Configure SDK
echo "⚙️ Configuring SDK..."
make defconfig
- name: Copy packages to SDK
run: |
echo "📁 Copying SecuBox packages to SDK..."
# List of our packages
PACKAGES=(
"luci-app-crowdsec-dashboard"
"luci-app-netdata-dashboard"
"luci-app-netifyd-dashboard"
"luci-app-wireguard-dashboard"
"luci-app-network-modes"
"luci-app-client-guardian"
"luci-app-system-hub"
)
# Create package directory
mkdir -p ~/sdk/package/secubox
# Copy each package if it exists
for pkg in "${PACKAGES[@]}"; do
if [[ -d "$GITHUB_WORKSPACE/$pkg" ]]; then
echo " 📦 $pkg"
cp -r "$GITHUB_WORKSPACE/$pkg" ~/sdk/package/secubox/
else
echo " ⚠️ $pkg not found in repository"
fi
done
# If packages are in a subdirectory
if [[ -d "$GITHUB_WORKSPACE/packages" ]]; then
cp -r "$GITHUB_WORKSPACE/packages/"* ~/sdk/package/secubox/ 2>/dev/null || true
fi
# List what we have
echo "📋 Packages in SDK:"
ls -la ~/sdk/package/secubox/ || echo " (empty)"
- name: Update package version
run: |
VERSION="${{ needs.setup.outputs.version }}"
echo "📝 Setting package version to: $VERSION"
# Update Makefile version in each package
for makefile in ~/sdk/package/secubox/*/Makefile; do
if [[ -f "$makefile" ]]; then
sed -i "s/PKG_VERSION:=.*/PKG_VERSION:=$VERSION/" "$makefile"
sed -i "s/PKG_RELEASE:=.*/PKG_RELEASE:=1/" "$makefile"
echo " ✅ Updated: $(dirname $makefile | xargs basename)"
fi
done
- name: Build packages
run: |
cd ~/sdk
echo "🔨 Building SecuBox packages for ${{ matrix.description }}..."
# Enable our packages
for pkg in ~/sdk/package/secubox/*/; do
PKG_NAME=$(basename "$pkg")
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
done
make defconfig
# Build with verbose output on error
make package/secubox/compile V=s -j$(nproc) || {
echo "❌ Build failed, retrying with single thread..."
make package/secubox/compile V=s -j1
}
# Generate package index
make package/index V=s
- name: Collect artifacts
id: collect
run: |
echo "📦 Collecting built packages..."
mkdir -p $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
# Find and copy .ipk files
find ~/sdk/bin -name "*.ipk" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \;
# Copy package index
find ~/sdk/bin -name "Packages*" -exec cp {} $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/ \; 2>/dev/null || true
# List artifacts
echo "📋 Built packages for ${{ matrix.target }}:"
ls -la $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}/
# Count packages
PKG_COUNT=$(find $GITHUB_WORKSPACE/artifacts/${{ matrix.target }} -name "*.ipk" | wc -l)
echo "pkg_count=$PKG_COUNT" >> $GITHUB_OUTPUT
if [[ $PKG_COUNT -eq 0 ]]; then
echo "⚠️ No packages built!"
exit 1
fi
- name: Create checksums
run: |
cd $GITHUB_WORKSPACE/artifacts/${{ matrix.target }}
sha256sum *.ipk > SHA256SUMS
echo "✅ Checksums created"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: packages-${{ matrix.target }}
path: artifacts/${{ matrix.target }}/
retention-days: 30
# ============================================
# Create combined release
# ============================================
release:
needs: [setup, build]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
- name: Organize packages
run: |
echo "📁 Organizing release packages..."
VERSION="${{ needs.setup.outputs.version }}"
mkdir -p release
# Create architecture-specific archives
for arch_dir in packages/packages-*/; do
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
echo "📦 Processing $ARCH..."
# Create tarball
tar -czf "release/secubox-${VERSION}-${ARCH}.tar.gz" -C "$arch_dir" .
# Copy individual .ipk files to flat structure
mkdir -p "release/ipk/${ARCH}"
cp "$arch_dir"/*.ipk "release/ipk/${ARCH}/" 2>/dev/null || true
done
# Create "all architectures" mega-archive
tar -czf "release/secubox-${VERSION}-all-architectures.tar.gz" -C packages .
# Create release notes
cat > release/RELEASE_NOTES.md << EOF
# SecuBox $VERSION
## 📦 Packages Included
- luci-app-crowdsec-dashboard - CrowdSec Security Dashboard
- luci-app-netdata-dashboard - Netdata Monitoring Dashboard
- luci-app-netifyd-dashboard - Netifyd DPI Dashboard
- luci-app-wireguard-dashboard - WireGuard VPN Dashboard
- luci-app-network-modes - Network Mode Switcher
- luci-app-client-guardian - NAC & Captive Portal
- luci-app-system-hub - System Hub Control Center
## 🏗️ Supported Architectures
| Target | Architecture | Description |
|--------|--------------|-------------|
| x86-64 | x86_64 | PC, VMs, Containers |
| aarch64-cortex-a53 | aarch64 | ESPRESSObin, Sheeva64 |
| aarch64-cortex-a72 | aarch64 | MOCHAbin, RPi4 |
| arm-cortex-a7 | arm | Orange Pi, Banana Pi |
| arm-cortex-a9 | arm | Linksys WRT, Turris |
| mips-24kc | mips | TP-Link, Ubiquiti |
| mipsel-24kc | mipsel | Xiaomi, GL.iNet |
| mediatek-filogic | aarch64 | MT7981, MT7986 |
| qualcomm-ipq40xx | arm | Google WiFi |
| rockchip-armv8 | aarch64 | NanoPi R4S, R5S |
## 📥 Installation
\`\`\`bash
# Download package for your architecture
opkg update
opkg install luci-app-crowdsec-dashboard_${VERSION}_*.ipk
# ... install other packages as needed
\`\`\`
## 🔗 Links
- [Documentation](https://cybermind.fr/docs/secubox)
- [GitHub](https://github.com/gkerma)
- [CyberMind.fr](https://cybermind.fr)
---
Built with OpenWrt SDK ${{ env.OPENWRT_VERSION }}
EOF
echo "✅ Release organized"
ls -la release/
- name: Create global checksums
run: |
cd release
sha256sum *.tar.gz > SHA256SUMS
echo "✅ Global checksums created"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: SecuBox ${{ needs.setup.outputs.version }}
body_path: release/RELEASE_NOTES.md
files: |
release/*.tar.gz
release/SHA256SUMS
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ============================================
# Build status summary
# ============================================
summary:
needs: [setup, build]
runs-on: ubuntu-latest
if: always()
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: packages
pattern: packages-*
continue-on-error: true
- name: Generate build summary
run: |
echo "# 📊 SecuBox Build Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ needs.setup.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "**OpenWrt:** ${{ env.OPENWRT_VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Architecture | Status | Packages |" >> $GITHUB_STEP_SUMMARY
echo "|--------------|--------|----------|" >> $GITHUB_STEP_SUMMARY
for arch_dir in packages/packages-*/; do
if [[ -d "$arch_dir" ]]; then
ARCH=$(basename "$arch_dir" | sed 's/packages-//')
PKG_COUNT=$(find "$arch_dir" -name "*.ipk" 2>/dev/null | wc -l)
if [[ $PKG_COUNT -gt 0 ]]; then
echo "| $ARCH | ✅ Success | $PKG_COUNT |" >> $GITHUB_STEP_SUMMARY
else
echo "| $ARCH | ⚠️ No packages | 0 |" >> $GITHUB_STEP_SUMMARY
fi
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 📦 Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Download artifacts from the Actions tab above." >> $GITHUB_STEP_SUMMARY

398
build-secubox-images.yml Normal file
View File

@ -0,0 +1,398 @@
name: Build SecuBox Images (GlobalScale)
on:
workflow_dispatch:
inputs:
device:
description: 'Target device'
required: true
type: choice
options:
- espressobin-v7
- espressobin-ultra
- sheeva64
- sheeva64-wifi
- mochabin
- all
openwrt_version:
description: 'OpenWrt version'
required: true
default: '23.05.5'
type: choice
options:
- '23.05.5'
- '23.05.4'
- 'SNAPSHOT'
include_secubox:
description: 'Include SecuBox packages'
required: true
type: boolean
default: true
env:
OPENWRT_VERSION: ${{ github.event.inputs.openwrt_version }}
jobs:
# ============================================
# Build firmware images for GlobalScale devices
# ============================================
build-image:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- device: espressobin-v7
target: mvebu
subtarget: cortexa53
profile: globalscale_espressobin
description: "ESPRESSObin V7 (1-2GB DDR4)"
enabled: ${{ github.event.inputs.device == 'espressobin-v7' || github.event.inputs.device == 'all' }}
- device: espressobin-ultra
target: mvebu
subtarget: cortexa53
profile: globalscale_espressobin-ultra
description: "ESPRESSObin Ultra (PoE, WiFi)"
enabled: ${{ github.event.inputs.device == 'espressobin-ultra' || github.event.inputs.device == 'all' }}
- device: sheeva64
target: mvebu
subtarget: cortexa53
profile: globalscale_sheeva64
description: "Sheeva64 (Plug computer)"
enabled: ${{ github.event.inputs.device == 'sheeva64' || github.event.inputs.device == 'all' }}
- device: sheeva64-wifi
target: mvebu
subtarget: cortexa53
profile: globalscale_sheeva64
description: "Sheeva64 WiFi (802.11ac + BT)"
enabled: ${{ github.event.inputs.device == 'sheeva64-wifi' || github.event.inputs.device == 'all' }}
- device: mochabin
target: mvebu
subtarget: cortexa72
profile: globalscale_mochabin
description: "MOCHAbin (Quad-core A72, 10G)"
enabled: ${{ github.event.inputs.device == 'mochabin' || github.event.inputs.device == 'all' }}
name: ${{ matrix.description }}
if: ${{ matrix.enabled != 'false' }}
steps:
- name: Checkout SecuBox packages
uses: actions/checkout@v4
- name: Free disk space
run: |
echo "🧹 Cleaning up disk space..."
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo docker image prune --all --force
df -h
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils python3-setuptools rsync \
swig unzip zlib1g-dev file wget curl qemu-utils
- name: Clone OpenWrt
run: |
if [[ "${{ env.OPENWRT_VERSION }}" == "SNAPSHOT" ]]; then
git clone --depth 1 https://github.com/openwrt/openwrt.git openwrt
else
git clone --depth 1 --branch v${{ env.OPENWRT_VERSION }} \
https://github.com/openwrt/openwrt.git openwrt
fi
- name: Update feeds
run: |
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
- name: Copy SecuBox packages
if: ${{ github.event.inputs.include_secubox == 'true' }}
run: |
mkdir -p openwrt/package/secubox
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
echo "📦 Adding $pkg"
cp -r "$pkg" openwrt/package/secubox/
fi
done
- name: Generate SecuBox config
run: |
cd openwrt
# Base configuration
cat > .config << EOF
# Target
CONFIG_TARGET_${{ matrix.target }}=y
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}=y
CONFIG_TARGET_${{ matrix.target }}_${{ matrix.subtarget }}_DEVICE_${{ matrix.profile }}=y
# Image settings
CONFIG_TARGET_ROOTFS_SQUASHFS=y
CONFIG_TARGET_ROOTFS_EXT4FS=y
CONFIG_TARGET_KERNEL_PARTSIZE=32
CONFIG_TARGET_ROOTFS_PARTSIZE=512
# Base packages
CONFIG_PACKAGE_luci=y
CONFIG_PACKAGE_luci-ssl=y
CONFIG_PACKAGE_luci-app-opkg=y
CONFIG_PACKAGE_luci-theme-openwrt-2020=y
# Networking essentials
CONFIG_PACKAGE_curl=y
CONFIG_PACKAGE_wget-ssl=y
CONFIG_PACKAGE_iptables=y
CONFIG_PACKAGE_ip6tables=y
CONFIG_PACKAGE_kmod-nft-core=y
# USB support
CONFIG_PACKAGE_kmod-usb-core=y
CONFIG_PACKAGE_kmod-usb3=y
CONFIG_PACKAGE_kmod-usb-storage=y
# Filesystem
CONFIG_PACKAGE_kmod-fs-ext4=y
CONFIG_PACKAGE_kmod-fs-vfat=y
CONFIG_PACKAGE_block-mount=y
# Wireless (if applicable)
CONFIG_PACKAGE_hostapd-common=y
CONFIG_PACKAGE_wpad-basic-mbedtls=y
# Monitoring tools
CONFIG_PACKAGE_htop=y
CONFIG_PACKAGE_iftop=y
CONFIG_PACKAGE_tcpdump=y
# SSH
CONFIG_PACKAGE_openssh-sftp-server=y
EOF
- name: Add SecuBox packages to config
if: ${{ github.event.inputs.include_secubox == 'true' }}
run: |
cd openwrt
# CrowdSec
cat >> .config << EOF
CONFIG_PACKAGE_crowdsec=y
CONFIG_PACKAGE_crowdsec-firewall-bouncer=y
CONFIG_PACKAGE_luci-app-crowdsec-dashboard=y
EOF
# Netdata
cat >> .config << EOF
CONFIG_PACKAGE_netdata=y
CONFIG_PACKAGE_luci-app-netdata-dashboard=y
EOF
# Netifyd
cat >> .config << EOF
CONFIG_PACKAGE_netifyd=y
CONFIG_PACKAGE_luci-app-netifyd-dashboard=y
EOF
# WireGuard
cat >> .config << EOF
CONFIG_PACKAGE_wireguard-tools=y
CONFIG_PACKAGE_kmod-wireguard=y
CONFIG_PACKAGE_luci-app-wireguard-dashboard=y
CONFIG_PACKAGE_qrencode=y
EOF
# SecuBox core
cat >> .config << EOF
CONFIG_PACKAGE_luci-app-network-modes=y
CONFIG_PACKAGE_luci-app-client-guardian=y
CONFIG_PACKAGE_luci-app-system-hub=y
EOF
- name: Add device-specific packages
run: |
cd openwrt
case "${{ matrix.device }}" in
mochabin)
# 10G networking, more RAM
cat >> .config << EOF
CONFIG_PACKAGE_kmod-sfp=y
CONFIG_PACKAGE_kmod-phy-marvell-10g=y
CONFIG_PACKAGE_prometheus-node-exporter-lua=y
EOF
;;
espressobin-ultra|sheeva64-wifi)
# WiFi support
cat >> .config << EOF
CONFIG_PACKAGE_kmod-mt76=y
CONFIG_PACKAGE_kmod-mac80211=y
EOF
;;
sheeva64*)
# Minimal for plug computer
cat >> .config << EOF
# Optimized for plug form factor
CONFIG_PACKAGE_kmod-ledtrig-heartbeat=y
EOF
;;
esac
- name: Make defconfig
run: |
cd openwrt
make defconfig
- name: Download packages
run: |
cd openwrt
make download -j$(nproc) V=s || make download -j1 V=s
- name: Build firmware
run: |
cd openwrt
echo "🔨 Building firmware for ${{ matrix.description }}..."
echo "⏱️ This may take 1-2 hours..."
make -j$(nproc) V=s 2>&1 | tee build.log || {
echo "❌ Build failed, retrying with single thread..."
make -j1 V=s 2>&1 | tee build-retry.log
}
- name: Prepare artifacts
run: |
mkdir -p artifacts
# Copy firmware images
find openwrt/bin/targets -name "*.img.gz" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*.bin" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*sysupgrade*" -exec cp {} artifacts/ \;
find openwrt/bin/targets -name "*factory*" -exec cp {} artifacts/ \;
# Copy packages
mkdir -p artifacts/packages
find openwrt/bin/packages -name "luci-app-*secubox*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
find openwrt/bin/packages -name "luci-app-*dashboard*.ipk" -exec cp {} artifacts/packages/ \; 2>/dev/null || true
# Generate checksums
cd artifacts
sha256sum * > SHA256SUMS 2>/dev/null || true
# Create info file
cat > BUILD_INFO.txt << EOF
SecuBox Firmware Build
=======================
Device: ${{ matrix.description }}
Profile: ${{ matrix.profile }}
Target: ${{ matrix.target }}/${{ matrix.subtarget }}
OpenWrt: ${{ env.OPENWRT_VERSION }}
SecuBox: ${{ github.event.inputs.include_secubox }}
Built: $(date -u +%Y-%m-%dT%H:%M:%SZ)
Commit: ${{ github.sha }}
EOF
echo "📦 Artifacts:"
ls -la
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: secubox-${{ matrix.device }}-${{ env.OPENWRT_VERSION }}
path: artifacts/
retention-days: 30
# ============================================
# Create combined release for all devices
# ============================================
release:
needs: build-image
runs-on: ubuntu-latest
if: github.event.inputs.device == 'all'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: firmware
pattern: secubox-*
- name: Organize release
run: |
mkdir -p release
for device_dir in firmware/secubox-*/; do
DEVICE=$(basename "$device_dir" | sed 's/secubox-//' | sed "s/-${{ env.OPENWRT_VERSION }}//")
echo "📦 Processing $DEVICE..."
# Create device archive
tar -czf "release/secubox-firmware-${DEVICE}.tar.gz" -C "$device_dir" .
done
# Global checksums
cd release
sha256sum *.tar.gz > SHA256SUMS
# Release notes
cat > RELEASE_NOTES.md << 'EOF'
# SecuBox Firmware Images
Pre-built firmware images for GlobalScale devices with SecuBox modules pre-installed.
## Included Devices
| Device | SoC | RAM | Description |
|--------|-----|-----|-------------|
| ESPRESSObin V7 | Armada 3720 | 1-2GB | Entry-level |
| ESPRESSObin Ultra | Armada 3720 | 1-2GB | WiFi + PoE |
| Sheeva64 | Armada 3720 | 1GB | Plug computer |
| MOCHAbin | Armada 7040 | 4-8GB | Quad-core + 10G |
## Pre-installed SecuBox Modules
- luci-app-crowdsec-dashboard
- luci-app-netdata-dashboard
- luci-app-netifyd-dashboard
- luci-app-wireguard-dashboard
- luci-app-network-modes
- luci-app-client-guardian
- luci-app-system-hub
## Installation
1. Download the appropriate firmware for your device
2. Flash using OpenWrt sysupgrade or manufacturer tools
3. Access LuCI at http://192.168.1.1
4. Navigate to Services → SecuBox
## Support
- [Documentation](https://cybermind.fr/docs/secubox)
- [CyberMind.fr](https://cybermind.fr)
EOF
- name: Create release
if: github.ref == 'refs/heads/main'
uses: softprops/action-gh-release@v2
with:
name: "SecuBox Firmware ${{ env.OPENWRT_VERSION }}"
tag_name: "firmware-${{ env.OPENWRT_VERSION }}-${{ github.run_number }}"
body_path: release/RELEASE_NOTES.md
files: |
release/*.tar.gz
release/SHA256SUMS
draft: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

@ -0,0 +1 @@
Subproject commit ad209f3982d9722f5d9e9da90e4489176633a65c

@ -0,0 +1 @@
Subproject commit f5920202d2b1c0652147c61e6b5c0a58c687c4ca

@ -0,0 +1 @@
Subproject commit 6dca2579d3ded391ee5158ccd6d31140239c4f6d

@ -0,0 +1 @@
Subproject commit 944342f7cf10a36ffd57f51f898f7a197e9167f2

@ -0,0 +1 @@
Subproject commit f909422b1888a7b52fa7ed3a0d3a5a73010beef0

1
luci-app-system-hub Submodule

@ -0,0 +1 @@
Subproject commit 7ddc649872109f61e3e2bffc6900d11e3721bd2d

@ -0,0 +1 @@
Subproject commit 4f9120c0566bd0c649d3f7b607c6f91e97e5a0ba

128
templates/Makefile.template Normal file
View File

@ -0,0 +1,128 @@
# SecuBox LuCI Application Makefile Template
# Copyright (C) 2025 CyberMind.fr
# SPDX-License-Identifier: Apache-2.0
include $(TOPDIR)/rules.mk
# ============================================
# Package Information
# ============================================
PKG_NAME:=luci-app-TEMPLATE-dashboard
PKG_VERSION:=1.0.0
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Gandalf <contact@cybermind.fr>
# ============================================
# LuCI Configuration
# ============================================
LUCI_TITLE:=LuCI TEMPLATE Dashboard
LUCI_DESCRIPTION:=Dashboard for TEMPLATE on OpenWrt
LUCI_DEPENDS:=+luci-base +TEMPLATE
LUCI_PKGARCH:=all
# Optional: Extra dependencies
# +luci-lib-jsonc +rpcd +uhttpd
include $(TOPDIR)/feeds/luci/luci.mk
# ============================================
# Package Definition
# ============================================
define Package/$(PKG_NAME)
SECTION:=luci
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=$(LUCI_TITLE)
DEPENDS:=$(LUCI_DEPENDS)
PKGARCH:=$(LUCI_PKGARCH)
endef
define Package/$(PKG_NAME)/description
$(LUCI_DESCRIPTION)
Features:
- Real-time status monitoring
- Configuration management
- Interactive dashboard
- System integration
endef
# ============================================
# Installation
# ============================================
define Package/$(PKG_NAME)/install
# JavaScript views
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/TEMPLATE
$(INSTALL_DATA) ./htdocs/luci-static/resources/view/TEMPLATE/*.js \
$(1)/www/luci-static/resources/view/TEMPLATE/
# API and CSS
$(INSTALL_DIR) $(1)/www/luci-static/resources/TEMPLATE
$(INSTALL_DATA) ./htdocs/luci-static/resources/TEMPLATE/*.js \
$(1)/www/luci-static/resources/TEMPLATE/
$(INSTALL_DATA) ./htdocs/luci-static/resources/TEMPLATE/*.css \
$(1)/www/luci-static/resources/TEMPLATE/
# Menu configuration
$(INSTALL_DIR) $(1)/usr/share/luci/menu.d
$(INSTALL_DATA) ./root/usr/share/luci/menu.d/$(PKG_NAME).json \
$(1)/usr/share/luci/menu.d/
# ACL configuration
$(INSTALL_DIR) $(1)/usr/share/rpcd/acl.d
$(INSTALL_DATA) ./root/usr/share/rpcd/acl.d/$(PKG_NAME).json \
$(1)/usr/share/rpcd/acl.d/
# RPCD backend
$(INSTALL_DIR) $(1)/usr/libexec/rpcd
$(INSTALL_BIN) ./root/usr/libexec/rpcd/TEMPLATE \
$(1)/usr/libexec/rpcd/
# UCI default config (optional)
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) ./root/etc/config/TEMPLATE \
$(1)/etc/config/
# UCI defaults (optional - runs on first install)
# $(INSTALL_DIR) $(1)/etc/uci-defaults
# $(INSTALL_BIN) ./root/etc/uci-defaults/$(PKG_NAME) \
# $(1)/etc/uci-defaults/
endef
# ============================================
# Post-installation
# ============================================
define Package/$(PKG_NAME)/postinst
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
# Reload rpcd to register new methods
/etc/init.d/rpcd reload 2>/dev/null || true
# Clear LuCI cache
rm -rf /tmp/luci-modulecache 2>/dev/null || true
rm -rf /tmp/luci-indexcache* 2>/dev/null || true
echo "$(PKG_NAME) installed successfully"
}
exit 0
endef
define Package/$(PKG_NAME)/postrm
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] || {
# Reload rpcd
/etc/init.d/rpcd reload 2>/dev/null || true
# Clear LuCI cache
rm -rf /tmp/luci-modulecache 2>/dev/null || true
rm -rf /tmp/luci-indexcache* 2>/dev/null || true
}
exit 0
endef
# ============================================
# Build
# ============================================
$(eval $(call BuildPackage,$(PKG_NAME)))

327
test-validate.yml Normal file
View File

@ -0,0 +1,327 @@
name: Test & Validate Packages
on:
push:
branches: [main, master, develop]
pull_request:
branches: [main, master]
jobs:
# ============================================
# Lint and validate package structure
# ============================================
lint:
runs-on: ubuntu-latest
name: Lint & Validate
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install validators
run: |
sudo apt-get update
sudo apt-get install -y shellcheck jq
- name: Validate Makefile structure
run: |
echo "📋 Validating Makefile structure..."
ERRORS=0
for makefile in */Makefile; do
if [[ -f "$makefile" ]]; then
PKG=$(dirname "$makefile")
echo " 🔍 Checking $PKG..."
# Required fields
REQUIRED_FIELDS=(
"PKG_NAME"
"PKG_VERSION"
"PKG_RELEASE"
"PKG_LICENSE"
"LUCI_TITLE"
)
for field in "${REQUIRED_FIELDS[@]}"; do
if ! grep -q "^${field}:=" "$makefile"; then
echo " ❌ Missing: $field"
ERRORS=$((ERRORS + 1))
fi
done
# Check for include statements
if ! grep -q "include.*luci.mk\|include.*package.mk" "$makefile"; then
echo " ❌ Missing include statement (luci.mk or package.mk)"
ERRORS=$((ERRORS + 1))
fi
fi
done
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS errors"
exit 1
fi
echo "✅ All Makefiles valid"
- name: Validate JSON files
run: |
echo "📋 Validating JSON files..."
ERRORS=0
# Find all JSON files
while IFS= read -r jsonfile; do
echo " 🔍 Checking $jsonfile..."
if ! jq empty "$jsonfile" 2>/dev/null; then
echo " ❌ Invalid JSON"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.json" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS JSON errors"
exit 1
fi
echo "✅ All JSON files valid"
- name: Validate JavaScript syntax
run: |
echo "📋 Validating JavaScript files..."
# Install node for syntax check
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
ERRORS=0
while IFS= read -r jsfile; do
echo " 🔍 Checking $jsfile..."
if ! node --check "$jsfile" 2>/dev/null; then
echo " ❌ Syntax error"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.js" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS JavaScript errors"
exit 1
fi
echo "✅ All JavaScript files valid"
- name: Validate shell scripts
run: |
echo "📋 Validating shell scripts..."
ERRORS=0
# Check RPCD scripts
while IFS= read -r script; do
echo " 🔍 Checking $script..."
if ! shellcheck -s sh "$script"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/rpcd/*" -type f -executable)
# Check init scripts
while IFS= read -r script; do
echo " 🔍 Checking $script..."
if ! shellcheck -s sh "$script"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/init.d/*" -type f)
if [[ $ERRORS -gt 0 ]]; then
echo "⚠️ Found $ERRORS shellcheck warnings (non-blocking)"
fi
echo "✅ Shell script validation complete"
- name: Check file permissions
run: |
echo "📋 Checking file permissions..."
ERRORS=0
# RPCD scripts should be executable
while IFS= read -r script; do
if [[ ! -x "$script" ]]; then
echo " ❌ Not executable: $script"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/usr/libexec/rpcd/*" -type f 2>/dev/null)
# Init scripts should be executable
while IFS= read -r script; do
if [[ ! -x "$script" ]]; then
echo " ❌ Not executable: $script"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -path "*/etc/init.d/*" -type f 2>/dev/null)
if [[ $ERRORS -gt 0 ]]; then
echo "❌ Found $ERRORS permission errors"
exit 1
fi
echo "✅ File permissions correct"
- name: Validate package structure
run: |
echo "📋 Validating package structure..."
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
echo " 📦 Checking $pkg..."
# Required directories/files
REQUIRED=(
"Makefile"
)
# Optional but recommended
RECOMMENDED=(
"htdocs/luci-static/resources"
"root/usr/share/luci/menu.d"
"root/usr/share/rpcd/acl.d"
)
for req in "${REQUIRED[@]}"; do
if [[ ! -e "${pkg}${req}" ]]; then
echo " ❌ Missing required: $req"
exit 1
fi
done
for rec in "${RECOMMENDED[@]}"; do
if [[ ! -e "${pkg}${rec}" ]]; then
echo " ⚠️ Missing recommended: $rec"
fi
done
fi
done
echo "✅ Package structure valid"
# ============================================
# Quick build test on x86_64
# ============================================
test-build:
runs-on: ubuntu-latest
name: Test Build (x86_64)
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk \
gcc-multilib g++-multilib gettext git libncurses5-dev \
libssl-dev python3-distutils rsync unzip zlib1g-dev wget
- name: Cache OpenWrt SDK
uses: actions/cache@v4
id: cache-sdk
with:
path: ~/sdk
key: openwrt-sdk-23.05.5-x86-64-test
- name: Download OpenWrt SDK
if: steps.cache-sdk.outputs.cache-hit != 'true'
run: |
SDK_URL="https://downloads.openwrt.org/releases/23.05.5/targets/x86/64"
SDK_FILE=$(curl -sL "$SDK_URL/" | grep -oP 'openwrt-sdk[^"]+\.tar\.xz' | head -1)
wget -q "${SDK_URL}/${SDK_FILE}" -O /tmp/sdk.tar.xz
mkdir -p ~/sdk
tar -xf /tmp/sdk.tar.xz -C ~/sdk --strip-components=1
- name: Prepare SDK
run: |
cd ~/sdk
./scripts/feeds update -a
./scripts/feeds install -a
make defconfig
- name: Copy packages
run: |
mkdir -p ~/sdk/package/secubox
for pkg in luci-app-*/; do
if [[ -d "$pkg" ]]; then
cp -r "$pkg" ~/sdk/package/secubox/
fi
done
- name: Build test
run: |
cd ~/sdk
# Enable packages
for pkg in ~/sdk/package/secubox/*/; do
PKG_NAME=$(basename "$pkg")
echo "CONFIG_PACKAGE_${PKG_NAME}=m" >> .config
done
make defconfig
# Build with timeout
timeout 30m make package/secubox/compile V=s -j$(nproc) || {
echo "⚠️ Build timeout or error"
exit 1
}
- name: Verify output
run: |
echo "📋 Built packages:"
find ~/sdk/bin -name "*.ipk" -exec ls -la {} \;
PKG_COUNT=$(find ~/sdk/bin -name "*.ipk" | wc -l)
echo "📦 Total packages built: $PKG_COUNT"
if [[ $PKG_COUNT -eq 0 ]]; then
echo "❌ No packages were built!"
exit 1
fi
# ============================================
# Generate documentation
# ============================================
docs:
runs-on: ubuntu-latest
name: Generate Docs
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Generate package list
run: |
echo "# SecuBox Packages" > PACKAGES.md
echo "" >> PACKAGES.md
echo "| Package | Version | Description |" >> PACKAGES.md
echo "|---------|---------|-------------|" >> PACKAGES.md
for makefile in luci-app-*/Makefile; do
if [[ -f "$makefile" ]]; then
PKG_NAME=$(grep "^PKG_NAME:=" "$makefile" | cut -d'=' -f2)
PKG_VERSION=$(grep "^PKG_VERSION:=" "$makefile" | cut -d'=' -f2)
PKG_TITLE=$(grep "^LUCI_TITLE:=" "$makefile" | cut -d'=' -f2-)
echo "| $PKG_NAME | $PKG_VERSION | $PKG_TITLE |" >> PACKAGES.md
fi
done
echo "" >> PACKAGES.md
echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> PACKAGES.md
cat PACKAGES.md
- name: Upload docs
uses: actions/upload-artifact@v4
with:
name: documentation
path: PACKAGES.md