Lets a smoke-test harness pick its own image tag without racing the default
fabro:latest, and points future agent sessions at bin/dev/docker-build.sh
so they don't hand-roll a throwaway Dockerfile.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The shipped aarch64-unknown-linux-musl binary segfaulted at startup on
every arm64 runtime (Apple Silicon, Graviton, Ampere, Docker arm64).
Root cause: a glibc-vs-musl .init_array calling-convention mismatch --
a C static library in the dep graph has an __attribute__((constructor))
that expects (argc, argv, envp) per glibc, but musl on aarch64 calls
it with no args, so register garbage propagates into pointer arithmetic
and faults before main runs.
Switch the musl compile steps to cargo-zigbuild (zig 0.13.0). Zig's
bundled cc + lld produce working static-PIE binaries for both musl
targets, sidestepping Ubuntu musl-tools' -no-pie quirk and the
init_array ordering that triggered the crash. Drop the CARGO_TARGET_*
linker overrides and the musl-tools apt install -- zig handles both.
bin/dev/docker-build.sh mirrors the same toolchain so the local Docker
image build matches CI.
Verified by running fabro version from the resulting arm64 image on
ghcr.io/fabro-sh/dhi-alpine-base:3.23-dev, alpine:3.22, and
debian:stable-slim -- all print the version banner with exit 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runtime image now builds FROM ghcr.io/fabro-sh/dhi-alpine-base (Docker
Hardened Images mirror, Alpine 3.23) instead of alpine:3.22. Same
runtime shape, CVE-minimized base. Changelog updated to reflect the
DHI migration.
bin/dev/docker-build.sh grows --arch {amd64,arm64} and --compile-only
flags so local multi-arch verification works regardless of host arch.
Cargo target cache is now per-arch to prevent arm64/amd64 artifacts
from stomping each other in one shared volume.
Now that the release workflow publishes musl binaries, the runtime
image can drop the debian:trixie-slim base for alpine:3.22. The
image shrinks from ~287 MB to ~96 MB (66% smaller) with a smaller
attack surface.
- Dockerfile: alpine:3.22 base, apk packages (ca-certificates git
tini su-exec), BusyBox adduser/addgroup, tini at /sbin/tini.
- entrypoint.sh: replace runuser with su-exec, Alpine's idiomatic
drop-privileges helper.
- release.yml docker job: pull the two linux-musl artifacts instead
of linux-gnu. The docker image and the Alpine install.sh path now
ship the same binary.
- bin/dev/docker-build.sh: compile fabro-cli for the host's musl
target in rust:1-bookworm with musl-tools, the matching CC/LINKER
env vars, and LIBZ_SYS_STATIC=1. Same pattern as CI.
Verified locally on aarch64: Alpine image builds, server binds on
$PORT (default 32276), endpoints return 200, fabro server process
runs as unprivileged UID 1000 under tini.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The host cargo build on macOS produced a Mach-O binary that the
Linux runtime image refused with "Exec format error". Run the
compile in rust:1-bookworm so the output matches the target
platform, and cache the registry plus target dir in named volumes
for incremental rebuilds. Also gitignore docker-context/ since it
is regenerated on every build.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the docker/Dockerfile-based api+web compose setup with a
single root Dockerfile that runs the fabro server with the embedded
web UI on port 80, persists state under /storage, and drops to a
non-root fabro user with CAP_NET_BIND_SERVICE.
The release workflow stages the prebuilt Linux binaries from the
compile job into a buildx context and publishes multi-arch images
to ghcr.io/fabro-sh/fabro as :<version> (always), :latest (stable
tags only), and :nightly (nightly tags only).
Also address zizmor findings in nightly.yml (pinned
create-github-app-token, persist-credentials: false with explicit
remote URL setup) and release.yml (no-cache on tag-triggered
setup-bun to close the cache-poisoning path).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>