#!/bin/bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" SOURCE_DIR="${RUSTPROXY_SOURCE_DIR:?RUSTPROXY_SOURCE_DIR is required}" BINARY="${RUSTPROXY_BINARY:?RUSTPROXY_BINARY is required}" OPNSENSE_ABI="${OPNSENSE_ABI:-26.7}" FREEBSD_ABI="${FREEBSD_ABI:-FreeBSD:15:amd64}" FREEBSD_ARCH="${FREEBSD_ARCH:-freebsd:15:x86:64}" SOURCE_REVISION="${RUSTPROXY_SOURCE_REVISION:-0}" SOURCE_COMMIT="${RUSTPROXY_SOURCE_COMMIT:-unknown}" SOURCE_URL="${RUSTPROXY_SOURCE_URL:-https://git.linuxiarz.pl/gru/RustProxy}" SOURCE_REF="${RUSTPROXY_SOURCE_REF:-HEAD}" for tool in python3 sha256sum tar zstd file; do command -v "$tool" >/dev/null 2>&1 || { echo "Missing tool: $tool" >&2; exit 1; } done [[ -f "$SOURCE_DIR/Cargo.toml" ]] || { echo "Missing Cargo.toml in $SOURCE_DIR" >&2; exit 1; } [[ -f "$BINARY" ]] || { echo "Missing cross-built binary: $BINARY" >&2; exit 1; } binary_desc="$(file -b "$BINARY")" echo "$BINARY: $binary_desc" if [[ "${ALLOW_NON_FREEBSD_BINARY:-0}" != "1" ]] && [[ "$binary_desc" != *FreeBSD* ]]; then echo "Refusing to package a binary that is not identified as FreeBSD." >&2 exit 1 fi app_version="$(awk -F '"' '/^version = "/ {print $2; exit}' "$SOURCE_DIR/Cargo.toml")" [[ -n "$app_version" ]] || { echo "Cannot read app version" >&2; exit 1; } if [[ "$SOURCE_REVISION" == "0" ]]; then pkg_version="$app_version" else pkg_version="${app_version}_${SOURCE_REVISION}" fi work="$ROOT/dist/.package-work" stage="$work/stage" meta="$work/meta" repo_dir="$ROOT/dist/packages/$OPNSENSE_ABI/amd64" package_file="$repo_dir/os-rustproxy-${pkg_version}.pkg" rm -rf "$work" "$ROOT/dist/packages" mkdir -p "$stage/usr/local" "$meta" "$repo_dir" # OPNsense plugin files map directly below /usr/local. cp -a "$ROOT/opnsense-plugin/www/rustproxy/src/." "$stage/usr/local/" mkdir -p "$stage/usr/local/sbin" install -m 0555 "$BINARY" "$stage/usr/local/sbin/rust-proxy" # Ensure executable hooks/scripts keep executable mode in the package. chmod 0555 "$stage/usr/local/etc/rc.d/rustproxy" chmod 0555 "$stage/usr/local/etc/rc.syshook.d/10-rustproxy.start" chmod 0555 "$stage/usr/local/opnsense/scripts/rustproxy/service.sh" POST_INSTALL_FILE="$ROOT/opnsense-plugin/www/rustproxy/+POST_INSTALL.pre" PRE_DEINSTALL_FILE="$ROOT/opnsense-plugin/www/rustproxy/+PRE_DEINSTALL.pre" python3 - "$stage" "$meta" "$pkg_version" "$FREEBSD_ABI" "$FREEBSD_ARCH" \ "$POST_INSTALL_FILE" "$PRE_DEINSTALL_FILE" <<'PY' import hashlib import json import os from pathlib import Path import sys stage = Path(sys.argv[1]) meta_dir = Path(sys.argv[2]) version = sys.argv[3] abi = sys.argv[4] arch = sys.argv[5] post_install = Path(sys.argv[6]).read_text(encoding="utf-8") pre_deinstall = Path(sys.argv[7]).read_text(encoding="utf-8") files = {} flatsize = 0 for p in sorted(stage.rglob("*")): if p.is_symlink(): rel = "/" + p.relative_to(stage).as_posix() files[rel] = "-" elif p.is_file(): rel = "/" + p.relative_to(stage).as_posix() files[rel] = hashlib.sha256(p.read_bytes()).hexdigest() flatsize += p.stat().st_size common = { "name": "os-rustproxy", "version": version, "origin": "opnsense/os-rustproxy", "comment": "RustProxy reverse proxy service", "desc": "RustProxy packaged as an OPNsense plugin. The initial UI exposes Enabled/Disabled only.", "maintainer": "local@localhost", "www": "https://git.linuxiarz.pl/gru/RustProxy", "prefix": "/usr/local", "abi": abi, "arch": arch, "flatsize": flatsize, "licenselogic": "single", "licenses": ["UNKNOWN"], "categories": ["www"], "deps": {}, "options": {}, } manifest = dict(common) manifest["files"] = files manifest["scripts"] = { "post-install": post_install, "pre-deinstall": pre_deinstall, } (meta_dir / "+COMPACT_MANIFEST").write_text( json.dumps(common, separators=(",", ":"), ensure_ascii=False) + "\n", encoding="utf-8", ) (meta_dir / "+MANIFEST").write_text( json.dumps(manifest, separators=(",", ":"), ensure_ascii=False) + "\n", encoding="utf-8", ) PY archive="$work/os-rustproxy.tar" rm -f "$archive" "$package_file" tar --format=ustar --owner=0 --group=0 --numeric-owner \ -cf "$archive" -C "$meta" +COMPACT_MANIFEST +MANIFEST tar --format=ustar --owner=0 --group=0 --numeric-owner \ -rf "$archive" -C "$stage" usr zstd -q -f -19 -T0 "$archive" -o "$package_file" # Convenience stable path for direct deployment. cp -f "$package_file" "$ROOT/dist/os-rustproxy-latest.pkg" (cd "$repo_dir" && sha256sum "$(basename "$package_file")") > "$ROOT/dist/SHA256" cat > "$ROOT/dist/BUILD-INFO.txt" </dev/null rm -rf "$work" echo "Package: $package_file" echo "Latest: $ROOT/dist/os-rustproxy-latest.pkg"