mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Add OpenWrt .apk packaging for OpenWrt 25+, where apk-tools is the mandatory package manager. The existing .ipk continues to cover OpenWrt 24.x and earlier. Built SDK-free like the .ipk: it reuses the cargo-zigbuild cross-compile and the shared installed-filesystem payload under openwrt-ipk/files, and assembles the ADB container with the official `apk mkpkg` applet from apk-tools 3.0.5 built from source, so no OpenWrt SDK image is needed. The package-openwrt workflow is refactored so a single compile-binaries job cross-compiles and strips each arch once; both the .ipk and .apk packagers consume the binaries via a new --bin-dir flag instead of each recompiling. A build-apk job (aarch64, x86_64) builds apk-tools, packages, and structurally verifies the .apk with `apk adbdump`. Releases now publish .apk artifacts and checksums alongside .ipk; the release download is scoped to fips_* so the shared raw-binary artifacts are not swept into the published release. apk-version.sh maps a release tag or commit height to an apk-tools-valid version, covered by a case-table test. Packages are unsigned, installed with `apk add --allow-untrusted`, matching the .ipk posture. Also fix the OpenWrt control socket: the init script now pre-creates /run/fips before starting the daemon, the procd equivalent of the systemd unit's RuntimeDirectory=fips. Without it, on a fresh boot the daemon resolves its control socket to /tmp (since /run/fips does not yet exist), while fips-gateway later creates /run/fips for its own gateway.sock, leaving fipsctl/fipstop resolving a /run/fips/control.sock the daemon never bound.
292 lines
9.7 KiB
Bash
Executable File
292 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# Build a FIPS .ipk package for OpenWrt without the OpenWrt SDK.
|
|
#
|
|
# Uses cargo-zigbuild for cross-compilation and assembles the .ipk directly.
|
|
# An .ipk is just an ar archive containing two tarballs — no SDK required.
|
|
#
|
|
# Usage:
|
|
# ./packaging/openwrt/build-ipk.sh [--arch <name>]
|
|
#
|
|
# Architectures (--arch):
|
|
# aarch64 GL.iNet MT3000/MT6000, RPi 3/4/5, most modern routers [default]
|
|
# mipsel Older MIPS routers (TP-Link, Netgear, GL.iNet AR750)
|
|
# mips MIPS big-endian routers (ath79)
|
|
# arm 32-bit ARM routers (Cortex-A7)
|
|
# x86_64 x86 routers / VMs
|
|
#
|
|
# Output: dist/fips_<version>_<openwrt-arch>.ipk
|
|
#
|
|
# Prerequisites:
|
|
# cargo install cargo-zigbuild
|
|
# rustup target add <rust-triple> (added automatically if missing)
|
|
|
|
set -euo pipefail
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Arguments
|
|
# ---------------------------------------------------------------------------
|
|
|
|
ARCH="aarch64"
|
|
BIN_DIR="" # if set, use prebuilt binaries from here instead of compiling
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--arch) ARCH="$2"; shift 2 ;;
|
|
--arch=*) ARCH="${1#*=}"; shift ;;
|
|
--bin-dir) BIN_DIR="$2"; shift 2 ;;
|
|
--bin-dir=*) BIN_DIR="${1#*=}"; shift ;;
|
|
*) echo "Unknown argument: $1" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Architecture mapping
|
|
#
|
|
# RUST_TARGET — passed to cargo --target
|
|
# OPENWRT_ARCH — goes in the .ipk control file and filename
|
|
# ---------------------------------------------------------------------------
|
|
|
|
case "$ARCH" in
|
|
aarch64)
|
|
RUST_TARGET="aarch64-unknown-linux-musl"
|
|
OPENWRT_ARCH="aarch64_cortex-a53"
|
|
;;
|
|
mipsel)
|
|
RUST_TARGET="mipsel-unknown-linux-musl"
|
|
OPENWRT_ARCH="mipsel_24kc"
|
|
;;
|
|
mips)
|
|
RUST_TARGET="mips-unknown-linux-musl"
|
|
OPENWRT_ARCH="mips_24kc"
|
|
;;
|
|
arm)
|
|
RUST_TARGET="arm-unknown-linux-musleabihf"
|
|
OPENWRT_ARCH="arm_cortex-a7"
|
|
;;
|
|
x86_64)
|
|
RUST_TARGET="x86_64-unknown-linux-musl"
|
|
OPENWRT_ARCH="x86_64"
|
|
;;
|
|
*)
|
|
echo "Unknown arch: $ARCH" >&2
|
|
echo "Valid: aarch64, mipsel, mips, arm, x86_64" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Paths
|
|
# ---------------------------------------------------------------------------
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
FILES_DIR="$SCRIPT_DIR/files"
|
|
DIST_DIR="$PROJECT_ROOT/dist"
|
|
|
|
PKG_NAME="fips"
|
|
PKG_VERSION="${PKG_VERSION:-$(cd "$PROJECT_ROOT" && git describe --tags --always --dirty 2>/dev/null || echo "0.1.0")}"
|
|
|
|
echo "==> Building $PKG_NAME $PKG_VERSION for $OPENWRT_ARCH ($RUST_TARGET)"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Obtain binaries
|
|
#
|
|
# Either use a directory of prebuilt binaries (--bin-dir; CI cross-compiles
|
|
# once in a shared job and hands them to both the .ipk and .apk packagers), or
|
|
# compile from source here for a self-contained local build.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if [ -n "$BIN_DIR" ]; then
|
|
RELEASE_DIR="$BIN_DIR"
|
|
echo "==> Using prebuilt binaries from $RELEASE_DIR"
|
|
for bin in fips fipsctl fipstop fips-gateway; do
|
|
[ -f "$RELEASE_DIR/$bin" ] || {
|
|
echo "Error: prebuilt binary not found: $RELEASE_DIR/$bin" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
else
|
|
if ! command -v cargo-zigbuild &>/dev/null; then
|
|
echo "Error: cargo-zigbuild not found." >&2
|
|
echo " Install: cargo install cargo-zigbuild" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! rustup target list --installed | grep -q "^$RUST_TARGET$"; then
|
|
echo "==> Adding Rust target $RUST_TARGET..."
|
|
rustup target add "$RUST_TARGET"
|
|
fi
|
|
|
|
echo "==> Compiling..."
|
|
cd "$PROJECT_ROOT"
|
|
cargo zigbuild \
|
|
--release \
|
|
--target "$RUST_TARGET" \
|
|
--bin fips \
|
|
--bin fipsctl \
|
|
--bin fipstop \
|
|
--bin fips-gateway
|
|
|
|
RELEASE_DIR="$PROJECT_ROOT/target/$RUST_TARGET/release"
|
|
|
|
echo "==> Stripping binaries..."
|
|
STRIP="${LLVM_STRIP:-strip}"
|
|
for bin in fips fipsctl fipstop fips-gateway; do
|
|
"$STRIP" "$RELEASE_DIR/$bin" 2>/dev/null || true
|
|
done
|
|
fi
|
|
|
|
SIZE=$(du -sh "$RELEASE_DIR/fips" | cut -f1)
|
|
echo " fips: $SIZE"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. Assemble .ipk
|
|
# ---------------------------------------------------------------------------
|
|
# An .ipk is an ar archive with three members:
|
|
# debian-binary — format version ("2.0\n")
|
|
# control.tar.gz — package metadata, conffiles, pre/post scripts
|
|
# data.tar.gz — the actual filesystem tree
|
|
|
|
WORK_DIR="$(mktemp -d)"
|
|
trap 'rm -rf "$WORK_DIR"' EXIT
|
|
|
|
CONTROL_DIR="$WORK_DIR/control"
|
|
DATA_DIR="$WORK_DIR/data"
|
|
mkdir -p "$CONTROL_DIR" "$DATA_DIR"
|
|
|
|
# ---- data tree ----
|
|
|
|
install -d "$DATA_DIR/usr/bin"
|
|
install -m 0755 "$RELEASE_DIR/fips" "$DATA_DIR/usr/bin/fips"
|
|
install -m 0755 "$RELEASE_DIR/fipsctl" "$DATA_DIR/usr/bin/fipsctl"
|
|
install -m 0755 "$RELEASE_DIR/fipstop" "$DATA_DIR/usr/bin/fipstop"
|
|
install -m 0755 "$RELEASE_DIR/fips-gateway" "$DATA_DIR/usr/bin/fips-gateway"
|
|
|
|
install -d "$DATA_DIR/etc/init.d"
|
|
install -m 0755 "$FILES_DIR/etc/init.d/fips" "$DATA_DIR/etc/init.d/fips"
|
|
install -m 0755 "$FILES_DIR/etc/init.d/fips-gateway" "$DATA_DIR/etc/init.d/fips-gateway"
|
|
|
|
install -d "$DATA_DIR/etc/fips"
|
|
install -m 0600 "$FILES_DIR/etc/fips/fips.yaml" "$DATA_DIR/etc/fips/fips.yaml"
|
|
install -m 0755 "$FILES_DIR/etc/fips/firewall.sh" "$DATA_DIR/etc/fips/firewall.sh"
|
|
|
|
install -d "$DATA_DIR/etc/dnsmasq.d"
|
|
install -m 0644 "$FILES_DIR/etc/dnsmasq.d/fips.conf" "$DATA_DIR/etc/dnsmasq.d/fips.conf"
|
|
|
|
install -d "$DATA_DIR/etc/sysctl.d"
|
|
install -m 0644 "$FILES_DIR/etc/sysctl.d/fips-bridge.conf" "$DATA_DIR/etc/sysctl.d/fips-bridge.conf"
|
|
install -m 0644 "$FILES_DIR/etc/sysctl.d/fips-gateway.conf" "$DATA_DIR/etc/sysctl.d/fips-gateway.conf"
|
|
|
|
install -d "$DATA_DIR/etc/hotplug.d/net"
|
|
install -m 0755 "$FILES_DIR/etc/hotplug.d/net/99-fips" "$DATA_DIR/etc/hotplug.d/net/99-fips"
|
|
|
|
install -d "$DATA_DIR/etc/uci-defaults"
|
|
install -m 0755 "$FILES_DIR/etc/uci-defaults/90-fips-setup" "$DATA_DIR/etc/uci-defaults/90-fips-setup"
|
|
|
|
install -d "$DATA_DIR/lib/upgrade/keep.d"
|
|
install -m 0644 "$FILES_DIR/lib/upgrade/keep.d/fips" "$DATA_DIR/lib/upgrade/keep.d/fips"
|
|
|
|
# ---- control files ----
|
|
|
|
PKG_SIZE=$(du -sk "$DATA_DIR" | cut -f1)
|
|
|
|
cat > "$CONTROL_DIR/control" <<EOF
|
|
Package: $PKG_NAME
|
|
Version: $PKG_VERSION
|
|
Architecture: $OPENWRT_ARCH
|
|
Maintainer: FIPS Network
|
|
Section: net
|
|
Priority: optional
|
|
Depends: kmod-tun, kmod-br-netfilter, kmod-nft-nat, kmod-nf-conntrack, ip-full
|
|
Description: FIPS Mesh Network Daemon
|
|
Distributed, decentralized mesh networking over UDP, TCP, and raw Ethernet.
|
|
Provides a TUN interface (fips0) with ULA IPv6 addressing and a DNS
|
|
responder for .fips name resolution.
|
|
Installed-Size: $PKG_SIZE
|
|
EOF
|
|
|
|
# Mark fips.yaml as a conffile so opkg won't overwrite user edits on upgrade.
|
|
cat > "$CONTROL_DIR/conffiles" <<EOF
|
|
/etc/fips/fips.yaml
|
|
EOF
|
|
|
|
cat > "$CONTROL_DIR/postinst" <<'EOF'
|
|
#!/bin/sh
|
|
# Run first-boot UCI setup (the script deletes itself when done).
|
|
if [ -x /etc/uci-defaults/90-fips-setup ]; then
|
|
/etc/uci-defaults/90-fips-setup && rm -f /etc/uci-defaults/90-fips-setup
|
|
fi
|
|
|
|
/etc/init.d/fips enable
|
|
/etc/init.d/fips start
|
|
/etc/init.d/fips-gateway enable
|
|
/etc/init.d/fips-gateway start
|
|
exit 0
|
|
EOF
|
|
chmod 0755 "$CONTROL_DIR/postinst"
|
|
|
|
cat > "$CONTROL_DIR/prerm" <<'EOF'
|
|
#!/bin/sh
|
|
/etc/init.d/fips-gateway stop 2>/dev/null || true
|
|
/etc/init.d/fips-gateway disable 2>/dev/null || true
|
|
/etc/init.d/fips stop 2>/dev/null || true
|
|
/etc/init.d/fips disable 2>/dev/null || true
|
|
exit 0
|
|
EOF
|
|
chmod 0755 "$CONTROL_DIR/prerm"
|
|
|
|
# ---- pack ----
|
|
|
|
PKG_FILENAME="${PKG_NAME}_${PKG_VERSION}_${OPENWRT_ARCH}.ipk"
|
|
IPK_WORK="$WORK_DIR/ipk"
|
|
mkdir -p "$IPK_WORK"
|
|
|
|
echo "2.0" > "$IPK_WORK/debian-binary"
|
|
|
|
# Detect a tar that supports --format=gnu.
|
|
# On macOS, Homebrew's GNU tar is installed as 'gtar'; the system tar is BSD.
|
|
# Our filenames are short so BSD tar (ustar) works too, but gnu is preferred
|
|
# to match ipkg-build exactly and to embed numeric UID/GID.
|
|
# COPYFILE_DISABLE=1 suppresses macOS resource-fork (._*) files; no-op on Linux.
|
|
if command -v gtar &>/dev/null; then
|
|
# Homebrew GNU tar on macOS
|
|
TAR_CMD="gtar"
|
|
TAR_EXTRA_FLAGS="--format=gnu --numeric-owner"
|
|
elif tar --version 2>/dev/null | grep -q 'GNU tar'; then
|
|
# System tar is GNU tar (Linux)
|
|
TAR_CMD="tar"
|
|
TAR_EXTRA_FLAGS="--format=gnu --numeric-owner"
|
|
else
|
|
# macOS BSD tar (libarchive). Its default format is PAX (typeflag 0x78),
|
|
# which OpenWrt's busybox tar cannot handle. Force ustar explicitly.
|
|
TAR_CMD="tar"
|
|
TAR_EXTRA_FLAGS="--format=ustar"
|
|
fi
|
|
|
|
ipk_tar() {
|
|
# ipk_tar <output.tar.gz> <source-dir> [paths...]
|
|
local out="$1" src="$2"; shift 2
|
|
local mtime_flags=""
|
|
if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then
|
|
mtime_flags="--mtime=@$SOURCE_DATE_EPOCH"
|
|
fi
|
|
COPYFILE_DISABLE=1 "$TAR_CMD" $TAR_EXTRA_FLAGS $mtime_flags -czf "$out" -C "$src" "$@"
|
|
}
|
|
|
|
ipk_tar "$IPK_WORK/control.tar.gz" "$CONTROL_DIR" .
|
|
ipk_tar "$IPK_WORK/data.tar.gz" "$DATA_DIR" .
|
|
|
|
# The outer .ipk container is a gzip-compressed tar — NOT an ar archive.
|
|
# (Debian .deb uses ar; OpenWrt .ipk uses tar.gz.)
|
|
# Entries must be named with ./ prefix, as ipkg-build produces.
|
|
mkdir -p "$DIST_DIR"
|
|
ipk_tar "$DIST_DIR/$PKG_FILENAME" "$IPK_WORK" ./debian-binary ./control.tar.gz ./data.tar.gz
|
|
|
|
echo ""
|
|
echo "==> Done: dist/$PKG_FILENAME"
|
|
echo " $(du -sh "$DIST_DIR/$PKG_FILENAME" | cut -f1)"
|
|
echo ""
|
|
echo "Install on router:"
|
|
echo " scp -O dist/$PKG_FILENAME root@192.168.1.1:/tmp/"
|
|
echo " ssh root@192.168.1.1 opkg install /tmp/$PKG_FILENAME"
|