Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
0

Configure Feed

Select the types of activity you want to include in your feed.

chore: better configure release asset builds

Signed-off-by: Xe Iaso <me@xeiaso.net>

+161 -8
+1 -1
.dockerignore
··· 9 9 # The Dockerfile itself and editor cruft. 10 10 Dockerfile 11 11 .dockerignore 12 - **/*.swp 12 + **/*.swp
+7
docker-bake.hcl
··· 28 28 context = "." 29 29 dockerfile = "docker/Dockerfile.leveva" 30 30 tags = ["${REGISTRY}leveva:${TAG}"] 31 + platforms = [ 32 + "linux/amd64", 33 + "linux/arm64", 34 + "linux/ppc64le", 35 + "linux/ppc64", 36 + "linux/riscv64", 37 + ] 31 38 }
+66 -7
docker/Dockerfile.leveva
··· 3 3 # leveva is a workspace member, so the whole workspace is copied in: cargo needs 4 4 # every member manifest to resolve the lockfile, even though `-p leveva` only 5 5 # compiles leveva and its path dependency (leveva-iauth). The build is pure Rust 6 - # (rustls/ring for TLS, no system OpenSSL), so the runtime image needs nothing 7 - # beyond glibc. 6 + # (rustls/ring for TLS, no system OpenSSL), and we cross-compile to a fully 7 + # static musl target with cargo-zigbuild, so the runtime image needs nothing. 8 + # 9 + # The build stage pins itself to the native BUILDPLATFORM (no QEMU emulation); 10 + # cargo-zigbuild then cross-compiles to whichever musl triple matches the 11 + # requested TARGETARCH (amd64 -> x86_64, arm64 -> aarch64). Both ARGs are 12 + # populated automatically by `docker buildx`. 8 13 9 - FROM rust:1-bookworm AS build 14 + FROM --platform=$BUILDPLATFORM rust:1-bookworm AS build 10 15 WORKDIR /src 11 16 17 + # Install zig from ziglang.org rather than apt: Debian's package is far behind, 18 + # and leveva's cross-build path (cargo-zigbuild) wants a current toolchain. 19 + # The tarball is a self-contained static binary; just extract and symlink. 20 + ARG ZIG_VERSION=0.16.0 21 + RUN apt-get update \ 22 + && apt-get install -y --no-install-recommends curl xz-utils ca-certificates \ 23 + && rm -rf /var/lib/apt/lists/* \ 24 + && case "$(dpkg --print-architecture)" in \ 25 + amd64) ZIG_ARCH=x86_64 ;; \ 26 + arm64) ZIG_ARCH=aarch64 ;; \ 27 + riscv64) ZIG_ARCH=riscv64 ;; \ 28 + ppc64le) ZIG_ARCH=powerpc64le ;; \ 29 + *) echo "unsupported arch: $(dpkg --print-architecture)" >&2; exit 1 ;; \ 30 + esac \ 31 + && curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}.tar.xz" \ 32 + | tar -xJ -C /opt \ 33 + && ln -s "/opt/zig-${ZIG_ARCH}-linux-${ZIG_VERSION}/zig" /usr/local/bin/zig \ 34 + && cargo install cargo-zigbuild 35 + 36 + # Map the Docker TARGETARCH to a Rust musl triple, add the std component for it, 37 + # then cross-build. The artifact is copied to a stable path (/leveva) so the 38 + # runtime stage's COPY doesn't need to know the triple. 39 + ARG TARGETARCH 40 + 12 41 # Copy the full workspace (path deps + lockfile) and build only leveva. 13 42 COPY . . 14 - RUN cargo build --release --locked -p leveva --bin leveva 43 + RUN set -eux; \ 44 + case "$TARGETARCH" in \ 45 + amd64) RUST_TARGET=x86_64-unknown-linux-musl ;; \ 46 + arm64) RUST_TARGET=aarch64-unknown-linux-musl ;; \ 47 + riscv64) RUST_TARGET=riscv64gc-unknown-linux-musl ;; \ 48 + ppc64le) RUST_TARGET=powerpc64le-unknown-linux-musl ;; \ 49 + ppc64) RUST_TARGET=powerpc64-unknown-linux-musl ;; \ 50 + *) echo "unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; \ 51 + esac; \ 52 + rustup target add "$RUST_TARGET"; \ 53 + cargo zigbuild --release --locked --target "$RUST_TARGET" -p leveva --bin leveva; \ 54 + cp "target/$RUST_TARGET/release/leveva" /leveva 15 55 16 56 # --- 17 57 18 - FROM debian:bookworm-slim AS runtime 19 - RUN useradd --system --user-group --home-dir /var/lib/leveva --create-home leveva 58 + # A throwaway stage that supplies the two pieces of userland the scratch runtime 59 + # needs: the CA bundle and the unprivileged service account. Both are pure data 60 + # (PEM files / passwd entries), so we pin this to the native BUILDPLATFORM — it 61 + # never has to match the target arch, and the alpine image only needs to exist 62 + # for the builder. This is what lets the runtime work on ppc64 (big endian), 63 + # which has no official alpine/debian image of its own. 64 + FROM --platform=$BUILDPLATFORM alpine:3.24 AS rootfs 65 + RUN apk add --no-cache ca-certificates \ 66 + && addgroup -g 10001 leveva \ 67 + && adduser -S -u 10001 -G leveva -h /var/lib/leveva leveva 20 68 21 - COPY --from=build /src/target/release/leveva /usr/local/bin/leveva 69 + # --- 70 + 71 + # The binary is a fully static musl build, so the runtime image needs nothing but 72 + # the binary itself plus the CA bundle and account skeleton from the rootfs stage. 73 + # scratch has no per-arch base image, so every target platform is satisfied. 74 + FROM scratch AS runtime 75 + 76 + COPY --from=rootfs /etc/ssl/certs /etc/ssl/certs 77 + COPY --from=rootfs /etc/passwd /etc/passwd 78 + COPY --from=rootfs /etc/group /etc/group 79 + COPY --from=rootfs --chown=10001:10001 /var/lib/leveva /var/lib/leveva 80 + COPY --from=build /leveva /usr/local/bin/leveva 22 81 23 82 # Config lives in /etc/leveva; runtime state (none today) under /var/lib/leveva. 24 83 WORKDIR /var/lib/leveva
+85
scripts/generate-release-assets.sh
··· 1 + #!/usr/bin/env bash 2 + # 3 + # generate-release-assets.sh — build leveva for x86_64 + aarch64 and emit 4 + # .deb and .rpm packages for each architecture. 5 + # 6 + # Cross-compilation is handled by cargo-zigbuild (zig as the linker/sysroot), 7 + # so no per-arch C toolchain is required. Both targets are static musl builds. 8 + # Packaging is pure-Rust: cargo-deb and cargo-generate-rpm read the 9 + # [package.metadata.deb] / [package.metadata.generate-rpm] tables in 10 + # leveva/Cargo.toml. Passing --target to each rewrites the `target/release/` 11 + # asset prefix to `target/<triple>/release/`, so they pick up the cross binary. 12 + # 13 + # Outputs (relative to the workspace root): 14 + # target/<triple>/debian/leveva_<ver>_<arch>.deb 15 + # target/<triple>/generate-rpm/leveva-<ver>-1.<arch>.rpm 16 + # and a copy of every artifact collected under dist/release/. 17 + set -euo pipefail 18 + 19 + # Resolve the workspace root (parent of this script's directory) so the script 20 + # works regardless of the caller's cwd; cargo-deb/-rpm resolve asset paths 21 + # relative to it. 22 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 23 + ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" 24 + cd "${ROOT_DIR}" 25 + 26 + TARGETS=( 27 + x86_64-unknown-linux-musl 28 + aarch64-unknown-linux-musl 29 + riscv64gc-unknown-linux-musl 30 + powerpc64le-unknown-linux-musl 31 + powerpc64-unknown-linux-musl 32 + ) 33 + 34 + OUT_DIR="${ROOT_DIR}/var/dist/release" 35 + 36 + require() { 37 + command -v "$1" >/dev/null 2>&1 || { 38 + echo "error: required tool '$1' not found in PATH" >&2 39 + echo " install with: $2" >&2 40 + exit 1 41 + } 42 + } 43 + 44 + require cargo "https://rustup.rs" 45 + require zig "https://ziglang.org/download/ (or: brew install zig)" 46 + require cargo-zigbuild "cargo install cargo-zigbuild" 47 + require cargo-deb "cargo install cargo-deb" 48 + require cargo-generate-rpm "cargo install cargo-generate-rpm" 49 + 50 + # Ensure the rustup std component is present for each target; zigbuild links the 51 + # objects but rustc still needs the precompiled std for the triple. 52 + for triple in "${TARGETS[@]}"; do 53 + if ! rustup target list --installed 2>/dev/null | grep -qx "${triple}"; then 54 + echo ">> adding rust target ${triple}" 55 + rustup target add "${triple}" 56 + fi 57 + done 58 + 59 + mkdir -p "${OUT_DIR}" 60 + 61 + for triple in "${TARGETS[@]}"; do 62 + echo 63 + echo "==> ${triple}" 64 + 65 + echo ">> cargo zigbuild --release" 66 + cargo zigbuild --quiet --release --target "${triple}" -p leveva 67 + 68 + # --no-build: reuse the zigbuild artifact above (cargo-deb would otherwise 69 + # invoke a plain `cargo build` that lacks the zig cross linker). 70 + # --no-strip: the host `strip` can't process a foreign-arch binary; the 71 + # musl release binary is already lean enough to ship unstripped. 72 + echo ">> cargo deb" 73 + cargo deb -p leveva --target "${triple}" --no-build --no-strip 74 + 75 + echo ">> cargo generate-rpm" 76 + cargo generate-rpm -p leveva --target "${triple}" 77 + 78 + # Collect the artifacts into one place for convenience. 79 + cp -v "target/${triple}/debian/"*.deb "${OUT_DIR}/" 80 + cp -v "target/${triple}/generate-rpm/"*.rpm "${OUT_DIR}/" 81 + done 82 + 83 + echo 84 + echo "==> release assets collected in ${OUT_DIR}:" 85 + ls -1 "${OUT_DIR}"
+2
var/.gitignore
··· 1 + * 2 + !.gitignore