From 276685f1099fb43a83f88b3ba58d08bb58bddc84 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Wed, 18 Mar 2026 09:10:01 +0100 Subject: [PATCH] feat(repo): Add package repository at repo.secubox.in - Fix preseed URLs from non-existent repo.secubox.org to repo.secubox.in - Make feed URLs architecture-aware (x86_64, aarch64_cortex-a72, etc.) - Add publish-package-repo.yml workflow for GitHub Pages deployment - Workflow downloads release artifacts, generates opkg Packages index - Supports all SecuBox architectures with proper opkg feed structure Package repository structure: - https://repo.secubox.in/packages/{arch}/ - Core SecuBox packages - https://repo.secubox.in/luci/{arch}/ - LuCI apps - https://repo.secubox.in/catalog/ - Repository metadata Co-Authored-By: Claude Opus 4.5 --- .github/workflows/build-vm-appliance.yml | 21 +- .github/workflows/publish-package-repo.yml | 358 +++++++++++++++++++++ secubox-tools/c3box-vm-full-build.sh | 17 +- 3 files changed, 385 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/publish-package-repo.yml diff --git a/.github/workflows/build-vm-appliance.yml b/.github/workflows/build-vm-appliance.yml index e553de23..6a5df77e 100644 --- a/.github/workflows/build-vm-appliance.yml +++ b/.github/workflows/build-vm-appliance.yml @@ -187,11 +187,20 @@ jobs: mkdir -p imagebuilder/files/etc/opkg mkdir -p imagebuilder/files/etc/secubox - # SecuBox feed configuration for opkg - cat > imagebuilder/files/etc/opkg/customfeeds.conf << 'FEED_EOF' + # SecuBox feed configuration for opkg - architecture-aware + PKG_ARCH="${{ matrix.pkg_arch }}" + # Normalize architecture string for opkg + case "$PKG_ARCH" in + x86-64) OPKG_ARCH="x86_64" ;; + aarch64-cortex-a72) OPKG_ARCH="aarch64_cortex-a72" ;; + rockchip-armv8) OPKG_ARCH="aarch64_generic" ;; + *) OPKG_ARCH="$PKG_ARCH" ;; + esac + + cat > imagebuilder/files/etc/opkg/customfeeds.conf << FEED_EOF # SecuBox Official Package Feed - src/gz secubox_packages https://repo.secubox.org/packages/aarch64_generic - src/gz secubox_luci https://repo.secubox.org/luci/aarch64_generic + src/gz secubox_packages https://repo.secubox.in/packages/${OPKG_ARCH} + src/gz secubox_luci https://repo.secubox.in/luci/${OPKG_ARCH} FEED_EOF # Preseed script for first boot - Network & System @@ -248,7 +257,7 @@ jobs: uci set secubox.main=core uci set secubox.main.enabled='1' uci set secubox.main.log_level='info' - uci set secubox.main.appstore_url='https://repo.secubox.org/catalog' + uci set secubox.main.appstore_url='https://repo.secubox.in/catalog' uci set secubox.main.appstore_fallback_local='1' uci set secubox.main.health_check_interval='300' uci set secubox.main.watchdog_interval='60' @@ -318,7 +327,7 @@ jobs: # Wait for network echo "Waiting for network..." for i in $(seq 1 30); do - if ping -c1 repo.secubox.org >/dev/null 2>&1; then + if ping -c1 repo.secubox.in >/dev/null 2>&1; then echo "Network ready" break fi diff --git a/.github/workflows/publish-package-repo.yml b/.github/workflows/publish-package-repo.yml new file mode 100644 index 00000000..3a53507b --- /dev/null +++ b/.github/workflows/publish-package-repo.yml @@ -0,0 +1,358 @@ +name: Publish Package Repository + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., v1.0.0-beta)' + required: true + default: 'v1.0.0-beta' + release: + types: [published] + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build-repo: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Set version + id: version + run: | + if [ "${{ github.event_name }}" = "release" ]; then + VERSION="${{ github.event.release.tag_name }}" + else + VERSION="${{ inputs.version }}" + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + # Strip 'v' prefix for package naming + VERSION_NUM="${VERSION#v}" + echo "version_num=$VERSION_NUM" >> $GITHUB_OUTPUT + + - name: Download package tarballs from release + env: + GH_TOKEN: ${{ github.token }} + run: | + mkdir -p downloads + cd downloads + + VERSION="${{ steps.version.outputs.version }}" + VERSION_NUM="${{ steps.version.outputs.version_num }}" + + echo "Downloading packages from release $VERSION..." + + # Architecture-specific packages + ARCHITECTURES=( + "x86-64:x86_64" + "aarch64-generic:aarch64_generic" + "aarch64-cortex-a72:aarch64_cortex-a72" + "aarch64-cortex-a53:aarch64_cortex-a53" + "rockchip-armv8:aarch64_generic" + "bcm27xx-bcm2711:aarch64_cortex-a72" + "mediatek-filogic:aarch64_cortex-a53" + "mips-24kc:mips_24kc" + "mipsel-24kc:mipsel_24kc" + ) + + for arch_map in "${ARCHITECTURES[@]}"; do + ARCH="${arch_map%%:*}" + OPKG_ARCH="${arch_map##*:}" + TARBALL="secubox-${VERSION_NUM}-${ARCH}.tar.gz" + + echo "Downloading $TARBALL for opkg arch $OPKG_ARCH..." + gh release download "$VERSION" -p "$TARBALL" || echo "Skipping $TARBALL (not found)" + done + + # All-architectures package (LuCI apps, configs) + gh release download "$VERSION" -p "secubox-${VERSION_NUM}-all-architectures.tar.gz" || true + + ls -lh + + - name: Create repository structure + run: | + mkdir -p repo/packages + mkdir -p repo/luci + mkdir -p repo/catalog + + VERSION_NUM="${{ steps.version.outputs.version_num }}" + + # Architecture mappings + declare -A ARCH_MAP=( + ["x86-64"]="x86_64" + ["aarch64-generic"]="aarch64_generic" + ["aarch64-cortex-a72"]="aarch64_cortex-a72" + ["aarch64-cortex-a53"]="aarch64_cortex-a53" + ["rockchip-armv8"]="aarch64_generic" + ["bcm27xx-bcm2711"]="aarch64_cortex-a72" + ["mediatek-filogic"]="aarch64_cortex-a53" + ["mips-24kc"]="mips_24kc" + ["mipsel-24kc"]="mipsel_24kc" + ) + + # Extract and organize packages + for ARCH in "${!ARCH_MAP[@]}"; do + OPKG_ARCH="${ARCH_MAP[$ARCH]}" + TARBALL="downloads/secubox-${VERSION_NUM}-${ARCH}.tar.gz" + + if [ -f "$TARBALL" ]; then + echo "Processing $TARBALL -> $OPKG_ARCH" + + # Create arch directories + mkdir -p "repo/packages/${OPKG_ARCH}" + mkdir -p "repo/luci/${OPKG_ARCH}" + + # Extract to temp + TMPDIR=$(mktemp -d) + tar -xzf "$TARBALL" -C "$TMPDIR" + + # Move LuCI packages to luci/ and others to packages/ + find "$TMPDIR" -name '*.ipk' | while read pkg; do + PKG_NAME=$(basename "$pkg") + if [[ "$PKG_NAME" == luci-* ]]; then + cp "$pkg" "repo/luci/${OPKG_ARCH}/" + else + cp "$pkg" "repo/packages/${OPKG_ARCH}/" + fi + done + + rm -rf "$TMPDIR" + fi + done + + # Handle all-architectures tarball (architecture-independent packages) + ALL_TARBALL="downloads/secubox-${VERSION_NUM}-all-architectures.tar.gz" + if [ -f "$ALL_TARBALL" ]; then + echo "Processing all-architectures packages..." + TMPDIR=$(mktemp -d) + tar -xzf "$ALL_TARBALL" -C "$TMPDIR" + + # Copy all-arch packages to each architecture directory + for OPKG_ARCH in "x86_64" "aarch64_generic" "aarch64_cortex-a72" "aarch64_cortex-a53" "mips_24kc" "mipsel_24kc"; do + if [ -d "repo/packages/${OPKG_ARCH}" ]; then + find "$TMPDIR" -name '*.ipk' | while read pkg; do + PKG_NAME=$(basename "$pkg") + # Skip if architecture-specific version exists + if [ ! -f "repo/packages/${OPKG_ARCH}/${PKG_NAME}" ] && \ + [ ! -f "repo/luci/${OPKG_ARCH}/${PKG_NAME}" ]; then + if [[ "$PKG_NAME" == luci-* ]]; then + cp "$pkg" "repo/luci/${OPKG_ARCH}/" 2>/dev/null || true + else + cp "$pkg" "repo/packages/${OPKG_ARCH}/" 2>/dev/null || true + fi + fi + done + fi + done + rm -rf "$TMPDIR" + fi + + echo "Repository structure:" + find repo -type d + echo "" + echo "Package counts:" + for dir in repo/packages/* repo/luci/*; do + if [ -d "$dir" ]; then + count=$(find "$dir" -name '*.ipk' 2>/dev/null | wc -l) + echo " $dir: $count packages" + fi + done + + - name: Generate opkg Packages index + run: | + # Install uscan/dpkg-scanpackages alternative for IPK + # We'll use a simple shell script to generate Packages index + + generate_packages_index() { + DIR="$1" + cd "$DIR" + + echo "Generating Packages index for $DIR" + + # Clear existing + rm -f Packages Packages.gz Packages.sig + + for ipk in *.ipk; do + [ -f "$ipk" ] || continue + + # Extract control file + TMPDIR=$(mktemp -d) + ar x "$ipk" --output="$TMPDIR" 2>/dev/null || { + # Try tar for newer ipk format + tar -xf "$ipk" -C "$TMPDIR" 2>/dev/null || continue + } + + # Find control.tar.gz or control.tar.zst + CONTROL_TAR="" + for ctrl in "$TMPDIR"/control.tar.gz "$TMPDIR"/control.tar.zst "$TMPDIR"/control.tar; do + [ -f "$ctrl" ] && CONTROL_TAR="$ctrl" && break + done + + if [ -n "$CONTROL_TAR" ]; then + # Extract control file + case "$CONTROL_TAR" in + *.gz) tar -xzf "$CONTROL_TAR" -C "$TMPDIR" 2>/dev/null ;; + *.zst) zstd -d "$CONTROL_TAR" -c | tar -x -C "$TMPDIR" 2>/dev/null ;; + *) tar -xf "$CONTROL_TAR" -C "$TMPDIR" 2>/dev/null ;; + esac + + if [ -f "$TMPDIR/control" ]; then + # Output control fields + cat "$TMPDIR/control" + + # Add filename and size + SIZE=$(stat -c%s "$ipk" 2>/dev/null || stat -f%z "$ipk" 2>/dev/null) + MD5=$(md5sum "$ipk" | cut -d' ' -f1) + SHA256=$(sha256sum "$ipk" | cut -d' ' -f1) + + echo "Filename: $ipk" + echo "Size: $SIZE" + echo "MD5Sum: $MD5" + echo "SHA256sum: $SHA256" + echo "" + fi + fi + + rm -rf "$TMPDIR" + done > Packages + + # Compress + gzip -9c Packages > Packages.gz + + echo " Created: Packages ($(wc -l < Packages) lines)" + + cd - > /dev/null + } + + # Generate index for each directory + for dir in repo/packages/* repo/luci/*; do + if [ -d "$dir" ] && [ -n "$(ls -A "$dir"/*.ipk 2>/dev/null)" ]; then + generate_packages_index "$dir" + fi + done + + - name: Create catalog index + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Create catalog.json with available packages + cat > repo/catalog/index.json << 'CATALOG_EOF' + { + "version": "$VERSION", + "updated": "$(date -Iseconds)", + "architectures": [ + "x86_64", + "aarch64_generic", + "aarch64_cortex-a72", + "aarch64_cortex-a53", + "mips_24kc", + "mipsel_24kc" + ], + "feeds": { + "packages": "https://repo.secubox.in/packages/{arch}", + "luci": "https://repo.secubox.in/luci/{arch}" + } + } + CATALOG_EOF + + # Replace variables + sed -i "s/\$VERSION/$VERSION/g" repo/catalog/index.json + sed -i "s|\$(date -Iseconds)|$(date -Iseconds)|g" repo/catalog/index.json + + - name: Create index page + run: | + VERSION="${{ steps.version.outputs.version }}" + + cat > repo/index.html << 'HTML_EOF' + + + + SecuBox Package Repository + + + + +

SecuBox Package Repository

+

Official OpenWrt package repository for SecuBox security appliance.

+ +

Quick Setup

+

Add to /etc/opkg/customfeeds.conf:

+
src/gz secubox_packages https://repo.secubox.in/packages/{YOUR_ARCH}
+          src/gz secubox_luci https://repo.secubox.in/luci/{YOUR_ARCH}
+ +

Available Architectures

+
+ x86_64 - x86-64 VMs, Intel/AMD PCs +
packages/ | luci/ +
+
+ aarch64_cortex-a72 - Raspberry Pi 4, CM4 +
packages/ | luci/ +
+
+ aarch64_generic - NanoPi R4S/R5S, ROCKPro64, generic ARM64 +
packages/ | luci/ +
+
+ aarch64_cortex-a53 - MediaTek Filogic, budget ARM64 +
packages/ | luci/ +
+
+ mips_24kc - Atheros/QCA routers (big endian) +
packages/ | luci/ +
+
+ mipsel_24kc - MediaTek MT7621 routers +
packages/ | luci/ +
+ +

API

+

catalog/index.json - Repository metadata

+ + + + + HTML_EOF + + sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" repo/index.html + + - name: Create CNAME for custom domain + run: | + echo "repo.secubox.in" > repo/CNAME + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./repo + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build-repo + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/secubox-tools/c3box-vm-full-build.sh b/secubox-tools/c3box-vm-full-build.sh index 4e60cc66..0a114fad 100755 --- a/secubox-tools/c3box-vm-full-build.sh +++ b/secubox-tools/c3box-vm-full-build.sh @@ -181,11 +181,18 @@ mkdir -p imagebuilder/files/etc/c3box mkdir -p imagebuilder/files/etc/opkg mkdir -p imagebuilder/files/etc/secubox -# SecuBox feed configuration -cat > imagebuilder/files/etc/opkg/customfeeds.conf << 'EOF' +# SecuBox feed configuration - architecture-aware +case "$ARCH" in + x86-64) OPKG_ARCH="x86_64" ;; + rpi4) OPKG_ARCH="aarch64_cortex-a72" ;; + rockchip-armv8) OPKG_ARCH="aarch64_generic" ;; + *) OPKG_ARCH="aarch64_generic" ;; +esac + +cat > imagebuilder/files/etc/opkg/customfeeds.conf << EOF # SecuBox Official Package Feed -src/gz secubox_packages https://repo.secubox.org/packages/aarch64_generic -src/gz secubox_luci https://repo.secubox.org/luci/aarch64_generic +src/gz secubox_packages https://repo.secubox.in/packages/${OPKG_ARCH} +src/gz secubox_luci https://repo.secubox.in/luci/${OPKG_ARCH} EOF # Network preseed @@ -234,7 +241,7 @@ touch /etc/config/secubox uci set secubox.main=core uci set secubox.main.enabled='1' uci set secubox.main.log_level='info' -uci set secubox.main.appstore_url='https://repo.secubox.org/catalog' +uci set secubox.main.appstore_url='https://repo.secubox.in/catalog' uci set secubox.main.appstore_fallback_local='1' uci set secubox.main.health_check_interval='300' uci set secubox.main.watchdog_interval='60'