# Architecture ## Components 1. **Debian host** - Git polling, Docker engine, package assembly and optional publication. 2. **Docker builder** - Rust 1.88, Clang/LLD and a verified FreeBSD 15.1 sysroot extracted from official `base.txz`. 3. **OPNsense package** - `os-rustproxy-*.pkg`, installed directly with `pkg add -f`. No FreeBSD VM is used. ## Why the sysroot is enough for the binary build Rust provides `x86_64-unknown-freebsd`. Clang receives `--target=x86_64-unknown-freebsd15.1` and `--sysroot=/opt/freebsd-sysroot`, so Rust and C/assembly dependencies such as `ring` link against FreeBSD headers and libraries instead of Debian ones. The container is still Linux. It cannot execute the generated FreeBSD binary, so the pipeline performs Linux tests before cross-compilation and ELF inspection after cross-compilation. Runtime validation must happen on an OPNsense/FreeBSD test firewall. ## Package construction FreeBSD pkg archives are compressed tar archives with metadata files beginning with `+` before package data. The Linux packager creates: ```text +COMPACT_MANIFEST +MANIFEST usr/local/... ``` and compresses it with zstd to `.pkg`. ## Source isolation ```text /opt/opn-rustproxy/packaging packaging repository /opt/opn-rustproxy/source/RustProxy dynamically fetched application /opt/opn-rustproxy/cache Docker/Cargo cache ``` The exact RustProxy SHA and package version are written to `dist/BUILD-INFO.txt`. ## Build-only FreeBSD patch layer RustProxy upstream is kept unchanged. Before Docker compilation, the Debian builder copies the checked-out source into a temporary directory under `dist/.build-source/` and applies version-specific patches from `builder/freebsd/patches//`. Docker receives the temporary copy read-only. The temporary tree is removed after the build. For RustProxy 0.20.0 the patch is `builder/freebsd/patches/0.20.0/0001-opnsense-build.patch`. This makes the FreeBSD/OPNsense compatibility changes part of the packaging repository rather than the RustProxy repository.