feat: add aarch64 static builds, clean up docs

This commit is contained in:
Marco Cadetg
2025-12-26 22:09:32 +01:00
parent 5c13f1d696
commit ebc04fd09c
4 changed files with 43 additions and 221 deletions

View File

@@ -186,8 +186,17 @@ jobs:
if-no-files-found: error
build-static:
name: build-static-musl
runs-on: ubuntu-latest
name: build-static-${{ matrix.arch }}
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- arch: x86_64
runner: ubuntu-latest
target: x86_64-unknown-linux-musl
- arch: aarch64
runner: ubuntu-24.04-arm
target: aarch64-unknown-linux-musl
container:
image: rust:alpine
steps:
@@ -213,12 +222,12 @@ jobs:
run: |
file target/release/rustnet
# Use file command to verify (ldd behaves differently inside Alpine)
file target/release/rustnet | grep -q "static-pie linked" || \
file target/release/rustnet | grep -q "static.* linked" || \
(echo "ERROR: Binary is not statically linked" && exit 1)
- name: Create release archive
run: |
staging="rustnet-${{ github.ref_name }}-x86_64-unknown-linux-musl"
staging="rustnet-${{ github.ref_name }}-${{ matrix.target }}"
mkdir -p "$staging/assets"
cp target/release/rustnet "$staging/"
@@ -231,8 +240,8 @@ jobs:
- name: Upload static build artifact
uses: actions/upload-artifact@v6
with:
name: build-x86_64-unknown-linux-musl
path: rustnet-${{ github.ref_name }}-x86_64-unknown-linux-musl.tar.gz
name: build-${{ matrix.target }}
path: rustnet-${{ github.ref_name }}-${{ matrix.target }}.tar.gz
if-no-files-found: error
create-release:

View File

@@ -1,82 +0,0 @@
name: Test Static Build
on:
pull_request:
paths:
- 'Dockerfile.static'
- '.github/workflows/test-static-build.yml'
- '.github/workflows/release.yml'
- 'MUSL_BUILD.md'
workflow_dispatch:
permissions:
contents: read
jobs:
build-static:
name: build-static-musl
runs-on: ubuntu-latest
container:
image: rust:alpine
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install dependencies
run: |
apk add --no-cache \
musl-dev libpcap-dev pkgconfig build-base perl \
elfutils-dev zlib-dev zlib-static zstd-dev zstd-static \
clang llvm linux-headers git
rustup component add rustfmt
- name: Build static binary
env:
# -C strip=symbols: Strip debug symbols for smaller binary
# -C link-arg=-l:libzstd.a: Fix elfutils 0.189+ zstd dependency (libbpf/bpftool#152)
RUSTFLAGS: "-C strip=symbols -C link-arg=-l:libzstd.a"
run: cargo build --release
- name: Verify static linking
run: |
echo "=== File info ==="
file target/release/rustnet
echo ""
echo "=== ldd output ==="
ldd target/release/rustnet 2>&1 || true
echo ""
echo "=== Size ==="
ls -lh target/release/rustnet
echo ""
# Verify it's actually static using file command
# (ldd behaves differently inside Alpine vs glibc systems)
if file target/release/rustnet | grep -q "static-pie linked"; then
echo "✅ Binary is statically linked!"
else
echo "❌ ERROR: Binary is NOT statically linked"
exit 1
fi
- name: Test binary runs
run: |
./target/release/rustnet --version
./target/release/rustnet --help | head -20
- name: Create release archive
run: |
staging="rustnet-static-x86_64-unknown-linux-musl"
mkdir -p "$staging/assets"
cp target/release/rustnet "$staging/"
cp assets/services "$staging/assets/" 2>/dev/null || true
cp README.md "$staging/"
cp LICENSE "$staging/" 2>/dev/null || true
tar czf "$staging.tar.gz" "$staging"
- name: Upload static binary
uses: actions/upload-artifact@v4
with:
name: rustnet-static-musl
path: rustnet-static-x86_64-unknown-linux-musl.tar.gz
retention-days: 7

View File

@@ -216,6 +216,34 @@ sudo setcap 'cap_net_raw,cap_bpf,cap_perfmon=eip' $(brew --prefix)/bin/rustnet
rustnet
```
#### Static Binary (Portable - Any Linux Distribution)
For maximum portability, static binaries are available that work on **any Linux distribution** regardless of GLIBC version. These are fully self-contained and require no system dependencies.
```bash
# Download the static binary for your architecture:
# - rustnet-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz (x86_64)
# - rustnet-vX.Y.Z-aarch64-unknown-linux-musl.tar.gz (ARM64)
# Extract the archive
tar xzf rustnet-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz
# Move binary to PATH
sudo mv rustnet-vX.Y.Z-x86_64-unknown-linux-musl/rustnet /usr/local/bin/
# Grant capabilities (modern kernel 5.8+)
sudo setcap 'cap_net_raw,cap_bpf,cap_perfmon=eip' /usr/local/bin/rustnet
# Run without sudo
rustnet
```
**When to use static binaries:**
- Older distributions with outdated GLIBC (e.g., CentOS 7, older Ubuntu)
- Minimal/containerized environments
- Air-gapped systems where installing dependencies is difficult
- When you want a single portable binary
### FreeBSD Installation
FreeBSD support is available starting from version 0.15.0.

View File

@@ -1,133 +0,0 @@
# musl Static Build Guide
This document explains how to build fully static RustNet binaries using musl.
## Quick Start
```bash
# Build static binary with eBPF support (default, ~6.5MB)
docker build -f Dockerfile.static -t rustnet-static .
# Or build without eBPF (smaller, ~5.2MB)
docker build -f Dockerfile.static --build-arg FEATURES="--no-default-features" -t rustnet-static .
# Extract the binary
mkdir -p dist
docker run --rm -v $(pwd)/dist:/out rustnet-static cp /build/target/release/rustnet /out/
# Verify it's static
file dist/rustnet
# Output: ELF 64-bit LSB pie executable, x86-64, ..., static-pie linked
ldd dist/rustnet
# Output: statically linked
```
## Binary Characteristics
| Build | Size | eBPF | Process Detection | Compatibility |
|-------|------|------|-------------------|---------------|
| With eBPF | ~6.5MB | Yes | eBPF + procfs fallback | Any Linux |
| Without eBPF | ~5.2MB | No | procfs only | Any Linux |
## How It Works
The `Dockerfile.static` uses `rust:alpine` which provides:
- Native musl toolchain (no glibc/musl mixing issues)
- `libpcap-dev` package with static library (`/usr/lib/libpcap.a`)
- `elfutils-dev` with static libelf for eBPF
- All dependencies compiled against musl
### The zstd Fix
Alpine's elfutils 0.189+ has an undeclared dependency on zstd for ELF section compression. The Dockerfile includes a workaround:
```toml
# .cargo/config.toml
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "link-arg=-l:libzstd.a"]
```
This explicitly links the static zstd library, fixing the link order issue. See [libbpf/bpftool#152](https://github.com/libbpf/bpftool/issues/152) for details.
## Running the Static Binary
```bash
# Set capabilities for packet capture
sudo setcap 'cap_net_raw=eip' dist/rustnet
# For eBPF support (Linux 5.8+)
sudo setcap 'cap_net_raw,cap_bpf,cap_perfmon=eip' dist/rustnet
# Run
./dist/rustnet
```
## CI Integration
For GitHub Actions, use the native container approach (faster than Docker build):
```yaml
build-static:
name: build-static-musl
runs-on: ubuntu-latest
container:
image: rust:alpine
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: |
apk add --no-cache \
musl-dev libpcap-dev pkgconfig build-base perl \
elfutils-dev zlib-dev zlib-static zstd-dev zstd-static \
clang llvm linux-headers git
rustup component add rustfmt
- name: Configure static zstd linking
run: |
mkdir -p .cargo
printf '[target.x86_64-unknown-linux-musl]\nrustflags = ["-C", "link-arg=-l:libzstd.a"]\n' > .cargo/config.toml
- name: Build
run: cargo build --release
- name: Verify static linking
run: |
file target/release/rustnet
ldd target/release/rustnet 2>&1 | grep -q "statically linked"
```
## Historical Context
### Previous Challenges (Resolved)
Earlier attempts using cross-rs with Ubuntu-based containers failed:
- Installing `libpcap-dev` in Ubuntu provides glibc-linked libraries
- Mixing glibc libraries with musl linking caused undefined references
- Errors included pthread, math (exp), and dladdr symbols
### Why Alpine Works
Alpine Linux uses musl as its system C library:
- All packages are compiled against musl
- Static libraries (`*.a`) are musl-compatible
- No glibc/musl mixing occurs
### The eBPF Challenge (Resolved)
Static eBPF builds initially failed due to elfutils → zstd dependency chain:
- elfutils 0.189+ added ZSTD compression for ELF sections
- libbpf-sys didn't propagate the zstd link dependency
- Fixed by explicitly linking `-l:libzstd.a` via cargo config
## References
- [libbpf/bpftool#152](https://github.com/libbpf/bpftool/issues/152) - zstd link fix
- [arachsys/libelf](https://github.com/arachsys/libelf) - Standalone libelf (alternative)
- [Alpine Static Linking](https://build-your-own.org/blog/20221229_alpine/) - General guidance
---
*Last updated: 2025-12-26*
*Status: Fully working with eBPF support*