]> git.ipfire.org Git - thirdparty/freeradius-server.git/log
thirdparty/freeradius-server.git
2 weeks agoredhat: install config under /etc/freeradius to match the debian layout
Arran Cudbard-Bell [Thu, 21 May 2026 18:46:24 +0000 (14:46 -0400)] 
redhat: install config under /etc/freeradius to match the debian layout

The RPM build used the historical /etc/raddb path while the debian
package installs to /etc/freeradius. Everything downstream that
mounts FR config (the multi-server compose files, the profiling
image's m4 macro) was already on /etc/freeradius - the RPM was the
odd one out, leaving operators of rocky9/10-derived images to deal
with a different config path than ubuntu/debian operators.

The configure call gains --with-raddbdir=%{_sysconfdir}/freeradius
so FR's compile-time raddbdir matches what the spec actually
packages. All the hardcoded %{_sysconfdir}/raddb paths in the %files
manifest and the post-install bootstrap, the systemd unit's
ReadOnlyDirectories, and the sysv init script's config_dir default
all flip to %{_sysconfdir}/freeradius / /etc/freeradius.

Operators upgrading an existing RPM install will need to move (or
symlink) /etc/raddb to /etc/freeradius before reinstall - the
%config(noreplace) entries won't migrate files across paths, and
the post-install certificate bootstrap reads from the new location.

2 weeks agomulti-server: standardise compose mounts on /etc/freeradius
Arran Cudbard-Bell [Thu, 21 May 2026 18:40:46 +0000 (14:40 -0400)] 
multi-server: standardise compose mounts on /etc/freeradius

The kafka, proxy, and proxy-multihop env files mounted configs at
/etc/raddb/, while the four new accept / ldap / mysql / pap-auth env
files mounted at /etc/freeradius/. Both paths resolve to the same
underlying directory (the freeradius4-profiling image has an
/etc/raddb -> /etc/freeradius symlink configured by
common.freeradius-profile-build.m4, and the standard debian package
that backs freeradius4-service installs config under /etc/freeradius
with raddbdir pointing there), but FR's semaphore association uses
the literal path it was started with - so kafka-producer1 and the
proxy homeserver containers were associating semaphores against a
file path that didn't quite match what FR ultimately opened, tripping
ENOENT on -n-prefixed runs.

Rewrite every /etc/raddb/... bind target to /etc/freeradius/...
across all the multi-server env files (and the start_valgrind_profiling.sh
script's mount target) so the kafka and proxy suites work against
both the service image and the profiling image without per-image
divergence. ${raddbdir} references inside the rendered radiusd.conf
fragments stay as-is - that's FR's compile-time variable, not a
literal path, and it already resolves to /etc/freeradius on both
images.

2 weeks agoci: retarget docker prune at the internal registry, not the host daemon
Arran Cudbard-Bell [Thu, 21 May 2026 18:30:03 +0000 (14:30 -0400)] 
ci: retarget docker prune at the internal registry, not the host daemon

The previous prune walked the runner host's docker daemon looking for
images carrying a ci-ttl label, but the entire CI pipeline builds
inside per-job DIND sidecars - those images live in dind, never on
the host daemon, and go away when each job ends. The prune ran every
30 minutes and reliably reported `removed=0 kept=0` because the place
it was looking was always empty. Meanwhile the actual disk pressure
is on the internal registry, where docker-server.yml and
docker-crossbuild.yml accumulate one freeradius4-<type>/<image>:<sha>
per commit until something cleans them up.

The new job runs inside the self-hosted-docker-cli container,
authenticates to docker.internal.networkradius.com with the
DOCKER_REPO_UPDATE_* secrets, walks the catalog for repos under the
freeradius4-* namespaces, pulls each tag's manifest + image config
to recover the ci-ttl label and creation timestamp, and issues
`DELETE /v2/<name>/manifests/<digest>` for anything past its
deadline. The label TTL semantics, log shape, and 30-minute cron
are unchanged. Disk reclamation still needs `registry
garbage-collect` to run on the registry host afterwards; that's not
in scope here.

2 weeks agoversion.sh: silence git describe stderr on branches without release/branch tags
Arran Cudbard-Bell [Thu, 21 May 2026 17:49:44 +0000 (13:49 -0400)] 
version.sh: silence git describe stderr on branches without release/branch tags

`version.sh commit_depth` runs
`git describe --tags --match 'branch_*' --match 'release_*'`
to count commits since the last branch/release tag. On feature
branches and freshly-checked-out CI workspaces neither tag class is
reachable from HEAD, so git describe exits non-zero and emits
"fatal: No names found, cannot describe anything." to stderr. The
existing `|| echo "${commit_depth}"` fallback already covers the
exit code; redirect stderr to /dev/null on the git describe call so
the message stops leaking into CI build logs (it was showing up
twice per docker-server.yml step plus once inside the in-container
`make deb`).

2 weeks agoci: docker prune script logs the actual image being pruned
Arran Cudbard-Bell [Thu, 21 May 2026 17:18:18 +0000 (13:18 -0400)] 
ci: docker prune script logs the actual image being pruned

The remove / skip lines used to identify the image by sha256 hash
only, which is useless when you're trying to figure out which build
of which type just disappeared at 02:14am. Pull the docker inspect
output forward to include {{join .RepoTags ","}} and render each
decision as `<repo:tag,repo:tag,...> (sha256:first-19-chars)`.
Falls back to "<dangling>" when RepoTags is empty (orphaned cache
layers). Added a corresponding keep line so the log shows the full
picture of what the prune considered each pass, not just the
deletions, and surfaced the parsed ci-ttl value in each message so
the cron / TTL pairing is visible without cross-referencing the
labels yourself.

2 weeks agoci: re-add nightly schedule trigger to multi-server
Arran Cudbard-Bell [Thu, 21 May 2026 17:14:51 +0000 (13:14 -0400)] 
ci: re-add nightly schedule trigger to multi-server

Restore the nightly cron entry that was lost when the workflow was
narrowed to workflow_run-only. The schedule path runs the full
multi-server test set instead of the per-commit CI subset (the
original split before the gating change). It fires independently of
the upstream Docker crossbuild images workflow, so the matching
crossbuild image may not be in the internal registry at trigger time
(e.g. after a registry prune) - docker.mk's stamp dependency chain
handles that: a pull-through miss on the crossbuild image cascades
into a local crossbuild docker build via the existing fallback
branch, then the profiling layer is built on top. Slow path but
self-sufficient.

The job-level if: gate now lets schedule events through (the prior
workflow_run.conclusion check would have skipped them). The checkout
ref: falls back to github.sha when event.workflow_run.head_sha is
unset (schedule has no upstream workflow_run context). The test
command split keys on matrix.mode + event_name so service / profiling
each get the full target on schedule and the .ci suffix otherwise.

2 weeks agoci: rename docker / crossbuild workflows to reflect what they publish
Arran Cudbard-Bell [Thu, 21 May 2026 17:11:19 +0000 (13:11 -0400)] 
ci: rename docker / crossbuild workflows to reflect what they publish

docker.yml -> docker-server.yml ("Docker service images") and
crossbuild.yml -> docker-crossbuild.yml ("Docker crossbuild images")
so the workflow names match the freeradius4-<type>/<image>:<sha>
namespaces they push to the internal registry. The workflow_run
trigger in ci-multi-server-tests.yml, the failure-diagnosis filter
in claude-ci-failure-diagnosis.yml, and the comment refs in
docker-refresh.yml all updated to the new names.

The dead `if [ "\$GITHUB_EVENT_NAME" = "schedule" ]` branches in the
multi-server test step are gone too; multi-server is now
workflow_run-only, so the schedule case never fires.

2 weeks agoci: multi-server tests trigger via Check Crossbuild only
Arran Cudbard-Bell [Thu, 21 May 2026 17:02:57 +0000 (13:02 -0400)] 
ci: multi-server tests trigger via Check Crossbuild only

Drop the push / pull_request / schedule / workflow_dispatch triggers
left over from the previous shape. Each of them would race ahead of
Check Crossbuild and find no freeradius4-crossbuild/<image>:<sha> in
the internal registry to consume, falling all the way back to a
local rebuild and defeating the whole pull-through chain.

workflow_run is now the only entry point. The job-level if: gate
simplifies to a straight conclusion == 'success' check and the
checkout step pins straight to event.workflow_run.head_sha without
the prior fallback for the now-deleted triggers.

2 weeks agoci: chain multi-server tests after crossbuild and use push-capable creds
Arran Cudbard-Bell [Thu, 21 May 2026 17:00:13 +0000 (13:00 -0400)] 
ci: chain multi-server tests after crossbuild and use push-capable creds

The push steps in crossbuild.yml + docker.yml reused the existing
DOCKER_REPO_USERNAME / DOCKER_REPO_PASSWORD secrets, which only carry
read access to docker.internal.networkradius.com (enough for pulling
the self-hosted base images). Each push 401'd against nginx with
"Authorization Required". Both workflows now do a second docker login
right before the push using DOCKER_REPO_UPDATE_USERNAME /
DOCKER_REPO_UPDATE_PASSWORD, which override dind's auth config for the
upload only - the earlier read-only login remains for the pull paths.

ci-multi-server-tests.yml now fires off Check Crossbuild completion
via workflow_run instead of on every push. The job skips when the
upstream crossbuild run didn't succeed (workflow_run.conclusion gate),
and the checkout pins to the SHA the crossbuild run was triggered
against (event.workflow_run.head_sha) so the multi-server pass tests
the same commit the crossbuild image was built from. PR / schedule /
manual dispatch triggers are untouched.

2 weeks agomulti-server: switch ldap suite to dinkel/openldap
Arran Cudbard-Bell [Thu, 21 May 2026 14:51:55 +0000 (10:51 -0400)] 
multi-server: switch ldap suite to dinkel/openldap

osixia/openldap fights docker bind-mounts at every granularity: its
slapd-bootstrap chowns the LDIF mount on startup (fails read-only),
post-init rms the parent dir (fails when the dir is bind-mounted),
and runs `sed -i` on the LDIF via a temp-file rename (fails on a
file-level bind-mount because rename can't replace the target). No
mount shape survives all three rewrites without baking the LDIF into
a derived image.

dinkel/openldap reads `/etc/ldap/prepopulate/*.ldif` and slapadds them
once on first start, never touching the mount. The image takes
SLAPD_DOMAIN / SLAPD_PASSWORD via env, listens on the default port
389, and our existing configs/openldap/bootstrap/01-testuser.ldif
works as-is. Healthcheck uses bash's /dev/tcp because dinkel doesn't
ship ldap-utils.

2 weeks agomulti-server: use \$PROFILING not \${PROFILING} in test templates
Arran Cudbard-Bell [Thu, 21 May 2026 04:58:01 +0000 (00:58 -0400)] 
multi-server: use \$PROFILING not \${PROFILING} in test templates

radenv's events/CommandEvents.run_command runs every shell snippet
through a `\${name}` -> `<project>-<name>-1` regex before docker exec,
treating any \${...} as a container reference. That silently rewrote
our profiling-mode branch's `if [ "\${PROFILING}" = "yes" ]` to a
container-name comparison, always taking the non-profiling branch and
running freeradius without valgrind. Bash accepts the unbraced
\$PROFILING form and the radenv regex doesn't match it.

With this in place test.multi-server.profiling.ci produces real
callgrind output (~21 per-thread files per suite) for all four new
suites.

2 weeks agoutil: make libbacktrace recipe a grouped target and use a relative HEADERS path
Arran Cudbard-Bell [Thu, 21 May 2026 14:48:59 +0000 (10:48 -0400)] 
util: make libbacktrace recipe a grouped target and use a relative HEADERS path

libfreeradius-util.mk drove libbacktrace via a regular two-target rule
that called the libbacktrace sub-make. GNU make >=4.3 expands a
multi-target rule as one independent rule per target sharing the same
recipe text, so parallel make can schedule the recipe twice when both
outputs are needed in the same invocation. Two concurrent sub-makes
land in the same .a / .libs/ directory; ar mid-writing libbacktrace.a
(with mmapio.o as a member) while a peer ranlib reads it surfaces as
"ranlib: .libs/libbacktrace.a: error reading mmapio.o: file truncated"
under -j>1. The grouped-target form (`&:`, added in GNU make 4.3) tells
make a single recipe invocation produces both outputs and only
schedules it once.

The HEADERS entry for backtrace.h was `$(top_srcdir)/.../backtrace.h`.
The install rule does `$(addprefix ${SRC_INCLUDE_DIR}/,$(HEADERS))`,
so an absolute path produces a double-slash install target like
`${SRC_INCLUDE_DIR}//abs/path/backtrace.h`. The pattern rule
`${SRC_INCLUDE_DIR}/%.h: src/include/%.h` still matches that target,
but its derived prereq `src/include//abs/path/backtrace.h` doesn't
exist, so `make install` fails with "No rule to make target". This
breaks every build where $(top_srcdir) resolves to an absolute path,
i.e. inside docker builds where @abs_top_srcdir@ is /usr/local/...
The relative `backtrace/backtrace.h` form reaches the same file via
the src/include/backtrace -> ../lib/backtrace symlink set up just
below.

2 weeks agobuild,profiling-image: gate dsymutil on apple-darwin so libbacktrace links survive ELF
Arran Cudbard-Bell [Thu, 21 May 2026 14:48:12 +0000 (10:48 -0400)] 
build,profiling-image: gate dsymutil on apple-darwin so libbacktrace links survive ELF

scripts/boiler.mk:702 used to set DSYMUTIL = $(shell which dsymutil)
whenever AC_HAVE_BACKTRACE was set, with no target-platform check.
On Linux that picked the LLVM dsymutil up off PATH (now reliably
present in the profiling image because kcachegrind/inferno pull in
the LLVM toolchain), and jlibtool then invoked it against every
linked .so. dsymutil only understands Mach-O, so the first link of
libfreeradius-make-dlopen.so under -g3 aborted with "cannot parse
the debug map for build/lib/.libs/libfreeradius-make-dlopen.so:
The file was not recognized as a valid object file" and the make
plugin's recursive build never produced the .so the parent make
tried to load. Restricting the binary lookup to apple-darwin
TARGET_SYSTEM falls back to the existing `DSYMUTIL := echo` no-op
on every other platform, so the recipe step stays harmless.

scripts/docker/m4/common.freeradius-profile-build.m4 now wipes any
host build artefacts that survived the COPY before invoking
autoconf/make so the container builds from a clean state. The
libbacktrace submodule in particular tends to carry host-absolute
paths in its generated Makefile / libtool, which broke the
in-container configure when the host tree had been built natively
on a different architecture.

2 weeks agomulti-server: dedup load-generator-packets across all suites and ignore host build/
Arran Cudbard-Bell [Thu, 21 May 2026 03:52:38 +0000 (23:52 -0400)] 
multi-server: dedup load-generator-packets across all suites and ignore host build/

The proxy / proxy-multihop / kafka suites all carried their own copy of
the same load-generator packet.conf, byte-identical to what the new
accept/ldap/mysql/pap-auth suites now read from configs/freeradius/
common/proto-load/. Drop the per-suite copies and repoint the compose
envs at the shared one. The unused common/proto-load/template.d
placeholder is removed (no radiusd.conf.j2 or env mount referenced it).

.dockerignore now also excludes the local build/ and prof-results/
directories so docker builds that do `COPY . .` don't drag a polluted
host tree into the image and confuse in-container Makefile installs
with absolute host paths.

2 weeks agomulti-server: dedup proto_load scaffolding into common/proto-load
Arran Cudbard-Bell [Thu, 21 May 2026 03:45:23 +0000 (23:45 -0400)] 
multi-server: dedup proto_load scaffolding into common/proto-load

The proto_load packet config, stats placeholder, packet template
fragment, and load-generator-packets/packet.conf were byte-identical
across accept/ldap/mysql/pap-auth. Lift them to configs/freeradius/
common/proto-load/ and point each suite's compose env at the common
mount path. A one-line change to the load profile now touches one file
instead of four.

2 weeks agomulti-server: fold profiling into standard suites with a MODE matrix
Arran Cudbard-Bell [Thu, 21 May 2026 03:30:01 +0000 (23:30 -0400)] 
multi-server: fold profiling into standard suites with a MODE matrix

Renames prof-accept/prof-ldap/prof-mysql/prof-pap-auth to accept/ldap/
mysql/pap-auth so they sit alongside proxy-accept and kafka-produce as
ordinary multi-server suites. Each suite is now driven once with MODE=
service (default, freeradius-build:latest, exec the server directly)
and once with MODE=profiling (freeradius-prof:latest, source the
valgrind/callgrind wrapper). The compose envs reference
${FREERADIUS_IMAGE} and ${PROFILING}, and the per-test recipe in
all.mk exports those alongside PROF_RESULTS_PATH based on MODE. The
bespoke Dockerfile.multi-server-prof and the build_image.sh /
run_container.sh wrappers are gone; the standard
freeradius4-profiling/<image>:<sha> image (with FreeRADIUS now compiled
in by common.freeradius-profile-build.m4) is just re-tagged as
freeradius-prof:latest by the new freeradius-prof.image target.

ci-profiling.yml is deleted; ci-multi-server-tests.yml grows a
matrix.mode = [service, profiling] so both passes share one job
template, one set of dind/cli images, and one workflow_dispatch entry.
The mariadb fixture now loads the canonical schema from
raddb/mods-config/sql/main/mysql/schema.sql via an additional ordered
mount and only seeds the testuser row locally; the openldap fixture
switched to osixia/openldap:1.5.0 plus an LDIF bootstrap; mariadb data
moved to tmpfs so init.sql re-applies on every compose-up.

2 weeks agomulti-server: early review fixes on PR 5848
Arran Cudbard-Bell [Thu, 21 May 2026 03:19:44 +0000 (23:19 -0400)] 
multi-server: early review fixes on PR 5848

Pulled in via merge from marc-casavant/profiling-multi-server-tests, then
addressed the structural and bug review feedback before the larger suite
restructure: the bogus crossbuild.ubuntu24.profile.* and docker.openldap.prof
target references in all.mk are gone, the multi-server prof Dockerfile now
FROMs the standard freeradius4-profiling/ubuntu24 image via build-arg, and
the configure/make/install pass with callgrind-friendly CFLAGS is lifted
into a shared common.freeradius-profile-build.m4 so every distro's
Dockerfile.profiling produces an image with FreeRADIUS already installed.

Bug fixes in start_valgrind_profiling.sh: VALGRIND_PID now captures the
valgrind process (was tee, leaving the fallback kill paths hitting the
wrong PID), the dead PROFILE_DURATION string-arithmetic line is removed,
and the eval-wrapped callgrind_annotate call is replaced with a direct
invocation. 5min.test.yml files now use test_verify_timeout to match the
template (was test_state1_verify_timeout, undefined). prof-ldap/prof-mysql
no longer mount mods-config/files/authorize, neither config loads files.
README path under scripts/profiling/ corrected. Openldap fixture switched
to osixia/openldap:1.5.0 with an LDIF bootstrap under
configs/openldap/bootstrap/ instead of the missing docker.openldap.prof
target.

2 weeks agoWIP: Removed unnecessary build steps
Marc-Andre Casavant [Thu, 14 May 2026 16:41:03 +0000 (12:41 -0400)] 
WIP: Removed unnecessary build steps

2 weeks agoWIP: Fixed typo
Marc-Andre Casavant [Thu, 14 May 2026 15:46:33 +0000 (11:46 -0400)] 
WIP: Fixed typo

2 weeks agoWIP: Removed previous location of packet.conf
Marc-Andre Casavant [Thu, 14 May 2026 15:45:03 +0000 (11:45 -0400)] 
WIP: Removed previous location of packet.conf

2 weeks agoWIP: CI profiling workflow is now split into two jobs; build-profiling-image to build...
Marc-Andre Casavant [Thu, 14 May 2026 14:56:44 +0000 (10:56 -0400)] 
WIP: CI profiling workflow is now split into two jobs; build-profiling-image to build profiling images and push to docker registry, profiling-tests that pulls images from registry and runs tests.

2 weeks agoWIP: New CI profiling workflow
Marc-Andre Casavant [Thu, 14 May 2026 14:30:35 +0000 (10:30 -0400)] 
WIP: New CI profiling workflow

2 weeks agoWIP: Add test.multi-server.profiling and test.multi-server.profiling.ci make targets
Marc-Andre Casavant [Thu, 14 May 2026 14:27:52 +0000 (10:27 -0400)] 
WIP: Add test.multi-server.profiling and test.multi-server.profiling.ci make targets

2 weeks agoWIP: new PROF_MODE makefile argument to generate prof-results with different director...
Marc-Andre Casavant [Thu, 14 May 2026 14:10:58 +0000 (10:10 -0400)] 
WIP: new PROF_MODE makefile argument to generate prof-results with different directory structures for ci and dev

2 weeks agoWIP: use server's default pap config
Marc-Andre Casavant [Thu, 14 May 2026 14:09:29 +0000 (10:09 -0400)] 
WIP: use server's default pap config

2 weeks agoWIP: additional updates to simplify proto-load test env
Marc-Andre Casavant [Thu, 14 May 2026 13:06:56 +0000 (09:06 -0400)] 
WIP: additional updates to simplify proto-load test env

2 weeks agoWIP: consolidating common proto_load configs for profiling tests starting with the...
Marc-Andre Casavant [Wed, 13 May 2026 19:45:00 +0000 (15:45 -0400)] 
WIP: consolidating common proto_load configs for profiling tests starting with the prof-ldap test

2 weeks agoFour new valgrind profiling multi-server tests
Marc-Andre Casavant [Thu, 23 Apr 2026 13:47:28 +0000 (09:47 -0400)] 
Four new valgrind profiling multi-server tests

2 weeks agoci: retrigger ci-deb against refreshed self-hosted-deb-* images
Arran Cudbard-Bell [Wed, 20 May 2026 18:20:27 +0000 (14:20 -0400)] 
ci: retrigger ci-deb against refreshed self-hosted-deb-* images

2 weeks agoci: retrigger ci-deb against refreshed self-hosted-deb-* images
Arran Cudbard-Bell [Wed, 20 May 2026 18:20:27 +0000 (14:20 -0400)] 
ci: retrigger ci-deb against refreshed self-hosted-deb-* images

2 weeks agoadd warning for WITH_VERIFY_PTR
Alan T. DeKok [Thu, 21 May 2026 14:25:39 +0000 (09:25 -0500)] 
add warning for WITH_VERIFY_PTR

so that people know that it kills performance if used in production
networks

Manual port of commit df330a6867b

2 weeks agoadd notes on coding style
Alan T. DeKok [Thu, 21 May 2026 13:04:14 +0000 (08:04 -0500)] 
add notes on coding style

2 weeks agomake variable unsigned
Alan T. DeKok [Wed, 20 May 2026 20:27:35 +0000 (15:27 -0500)] 
make variable unsigned

because it's also used in an array lookup (with cast), and is
also cast to (size_t).  Where negative numbers would result in
gigantic size_t values

2 weeks agouse more fr_sbuff_uint8() when passing results to tolower()
Alan T. DeKok [Wed, 20 May 2026 20:23:54 +0000 (15:23 -0500)] 
use more fr_sbuff_uint8() when passing results to tolower()

2 weeks agodocker: drive per-type wiring from a single TYPES list
Arran Cudbard-Bell [Wed, 20 May 2026 19:46:20 +0000 (15:46 -0400)] 
docker: drive per-type wiring from a single TYPES list

docker.mk and dockerfile.mk both had a hand-written stanza per type:
four DOCKER_BUILD calls, four DOCKERFILE_RULE calls, four umbrellas.
Adding a fifth type meant editing every block. Collapse them into a
single DOCKER_TYPES / DOCKERFILE_TYPES list plus a double foreach over
images and types.

Per-type quirks (profiling's --build-arg=from=crossbuild and crossbuild
stamp dependency, the optional CB_FROM_$(IMG) override on crossbuild)
move into DOCKER_BUILD_ARGS_<type> / DOCKER_BUILD_DEPS_<type> recursive
variables, so the $(IMG) inside them resolves at the right point in the
foreach. Adding a new type is now: append to the list, drop in the m4
files, optionally set the two lookup vars.

2 weeks agodocker: put the build-log path back on the BUILD echo line
Arran Cudbard-Bell [Wed, 20 May 2026 19:41:06 +0000 (15:41 -0400)] 
docker: put the build-log path back on the BUILD echo line

2 weeks agoupdate CHAP howto
Alan T. DeKok [Wed, 20 May 2026 19:08:26 +0000 (14:08 -0500)] 
update CHAP howto

2 weeks agodocs-v4: update howto/modules/CHAP for v4, added diagram, and separated doc
nolade [Tue, 21 Apr 2026 17:28:41 +0000 (13:28 -0400)] 
docs-v4: update howto/modules/CHAP for v4, added diagram, and separated doc
into pages for increased readability.
Formatting, typo, and nav fixes (2nd commit).

2 weeks agominor tweaks to tacacs
Alan T. DeKok [Wed, 20 May 2026 16:56:25 +0000 (11:56 -0500)] 
minor tweaks to tacacs

2 weeks agoci: surface the docker build log when docker.yml fails
Arran Cudbard-Bell [Wed, 20 May 2026 18:50:53 +0000 (14:50 -0400)] 
ci: surface the docker build log when docker.yml fails

DOCKER_BUILD redirects buildkit output to build/docker/build.<image>.<type>
to keep parallel builds from interleaving on stdout. When CI fails,
the workflow log shows the BUILD echo then several silent minutes
followed by Post job cleanup, with no clue what broke. Add an
if-failure cat step in both job variants so the underlying error
surfaces in the run page.

2 weeks agoci: add workflow_dispatch trigger to the CI workflows
Arran Cudbard-Bell [Wed, 20 May 2026 18:23:31 +0000 (14:23 -0400)] 
ci: add workflow_dispatch trigger to the CI workflows

Lets a maintainer re-fire any of these from the Actions UI against an
arbitrary branch without having to push an empty commit. Useful when
the failure is in something the workflow consumes externally (an
internal-registry image, a third-party service) and the commit hasn't
changed.

2 weeks agoci: retrigger ci-deb against refreshed self-hosted-deb-* images
Arran Cudbard-Bell [Wed, 20 May 2026 18:20:27 +0000 (14:20 -0400)] 
ci: retrigger ci-deb against refreshed self-hosted-deb-* images

2 weeks agoci: claude diagnosis dedupes against the most recent prior comment
Arran Cudbard-Bell [Wed, 20 May 2026 16:49:24 +0000 (12:49 -0400)] 
ci: claude diagnosis dedupes against the most recent prior comment

When a CI failure persists across several pushes (e.g. a workflow
re-fires while we're iterating on a fix), the diagnosis bot was
posting an identical comment on every commit. Walk the first-parent
history back up to 20 commits looking for the bot's last diagnosis
for the same workflow, and if classification + failing step +
key evidence all match, skip posting. Print the duplicate-of-<sha>
line so the run log records the decision.

2 weeks agodocker: skip libkqueue source build on amd64
Arran Cudbard-Bell [Wed, 20 May 2026 15:56:57 +0000 (11:56 -0400)] 
docker: skip libkqueue source build on amd64

NetworkRADIUS's extras repo ships libkqueue0 only for amd64; on that
arch we install from there so libfreeradius4's `Depends: libkqueue0
(= <NR version>)` resolves cleanly. On every other arch (arm64,
armhf, ppc64el, ...) the toolchain layer source-builds libkqueue and
deposits the .debs in /opt/libkqueue-debs/ for the service runtime
stage to install.

The directory is created unconditionally so the runtime stage's
COPY --from=build /opt/libkqueue-debs/ /tmp/ succeeds whether or not
the build stage produced any .debs.

2 weeks agodocker: move per-image state from scripts/docker/build/.state to build/docker
Arran Cudbard-Bell [Wed, 20 May 2026 15:49:02 +0000 (11:49 -0400)] 
docker: move per-image state from scripts/docker/build/.state to build/docker

Stamps and build / configure / test logs land in the top-level build/
tree now, next to every other generated artifact. The whole build/ is
already gitignored at the repo root, so the per-dir .gitignore that
hid the old .state/ subtree is gone.

crossbuild.yml's "show build log" steps cat the same files under the
new path.

2 weeks agoadd and fix LICENSE link
Alan T. DeKok [Wed, 20 May 2026 16:26:46 +0000 (11:26 -0500)] 
add and fix LICENSE link

2 weeks agodoc-v4: Fix & update broken links/fragments in online v4 docs at freeradius.org
nolade [Thu, 7 May 2026 16:47:17 +0000 (12:47 -0400)] 
doc-v4: Fix & update broken links/fragments in online v4 docs at freeradius.org

2 weeks agocleanups and rearrangements
Alan T. DeKok [Wed, 20 May 2026 16:18:55 +0000 (11:18 -0500)] 
cleanups and rearrangements

2 weeks agodocs-v4: update howto/passwd section with more details, formatting, and headings
nolade [Thu, 7 May 2026 20:07:49 +0000 (16:07 -0400)] 
docs-v4: update howto/passwd section with more details, formatting, and headings

2 weeks agoclean up for v4
Alan T. DeKok [Wed, 20 May 2026 16:14:47 +0000 (11:14 -0500)] 
clean up for v4

2 weeks agodocs-v4: updated pam howto into sections, added details to steps
nolade [Wed, 13 May 2026 18:17:52 +0000 (14:17 -0400)] 
docs-v4: updated pam howto into sections, added details to steps

2 weeks agotalloc_strndup() stops at the first NUL character
Alan T. DeKok [Wed, 20 May 2026 16:02:00 +0000 (11:02 -0500)] 
talloc_strndup() stops at the first NUL character

so use talloc_strlen(str) instead of the input fuzzer len

2 weeks agoci: dockerfile.* in Makefile filter, new state path in crossbuild.yml
Arran Cudbard-Bell [Wed, 20 May 2026 15:39:26 +0000 (11:39 -0400)] 
ci: dockerfile.* in Makefile filter, new state path in crossbuild.yml

Two stale references the docker-pipeline refactor missed:

* Makefile:48 / Makefile:120 filter only excludes targets matching
  crossbuild.% / docker.% from the "need Make.inc" gate. The new
  dockerfile.* targets weren't in the list, so `make dockerfile.crossbuild.check`
  in CI fell through to "Missing 'Make.inc' Run './configure'".

* crossbuild.yml's post-test "show build log" steps cat'd
  scripts/docker/crossbuild/{build,configure,log}.<OS>. The stamp +
  log dir moved to scripts/docker/build/.state/ with .<type> suffixes
  in commit 4f0ce71a6f, and the test cycle log is now test.<image>.crossbuild
  rather than log.<image>.

2 weeks agoci: tag built service image under the new freeradius4-service namespace
Arran Cudbard-Bell [Wed, 20 May 2026 15:35:38 +0000 (11:35 -0400)] 
ci: tag built service image under the new freeradius4-service namespace

The docker pipeline refactor renamed locally-built images from
freeradius4/<distro>:latest to freeradius4-service/<distro>:<short-sha>.
The multi-server-tests workflow's `docker tag ... freeradius-build:latest`
step still pointed at the old name and failed with "No such image"
after `make docker.service.ubuntu24` succeeded. Query the same short
sha that DOCKER_BUILD uses so the source tag resolves.

2 weeks agoredhat: add -fPIC to the rpm build CFLAGS
Arran Cudbard-Bell [Wed, 20 May 2026 14:50:28 +0000 (10:50 -0400)] 
redhat: add -fPIC to the rpm build CFLAGS

freeradius's libraries are shared objects. Rocky 10's default CFLAGS
ship with -flto=auto -ffat-lto-objects -fPIE but without -fPIC; on
aarch64 the linker then rejects R_AARCH64_ADR_PREL_PG_HI21 relocations
against symbols that might bind externally (e.g. _fr_dbuff_extend_talloc
when libfreeradius-util.la links). Adding -fPIC to the explicit CFLAGS
export keeps the shared-object link viable.

The why-now is unclear. binutils ld's diagnostic in bfd/elfnn-aarch64.c
is identical between binutils 2.35 (EL9) and 2.41 (EL10), and the
redhat-rpm-config macros for %optflags / _gcc_lto_cflags / hardened-cc1
also match. The most likely candidate is a gcc codegen change between
gcc-11 and gcc-14 -- gcc-14 on aarch64 appears more willing to emit
adrp direct references to extern functions under -fPIE, and that
survives into the -shared link where the linker (correctly) refuses.
Not confirmed by bisect or .s diff in this commit.

2 weeks agoUpdate autoconf output
Arran Cudbard-Bell [Wed, 20 May 2026 14:39:01 +0000 (10:39 -0400)] 
Update autoconf output

2 weeks agobuild: regenerate libbacktrace's configure on autoconf-2.70+ hosts
Arran Cudbard-Bell [Wed, 20 May 2026 14:29:38 +0000 (10:29 -0400)] 
build: regenerate libbacktrace's configure on autoconf-2.70+ hosts

src/lib/backtrace's shipped configure was generated by an autoconf
older than 2.70 and rejects --runstatedir. Rocky 10's redhat-rpm-config
(and any other recent %configure / dh_auto_configure macro that runs
on autoconf >= 2.70) passes --runstatedir down to subdir configures
via AC_CONFIG_SUBDIRS, taking the whole build with it.

Run autoreconf -fi against src/lib/backtrace inside the parent
configure when the build host has autoreconf available, and add a
note next to the autoconf BuildRequires / Build-Depends so a future
reader sees why a project that ships a pre-generated configure
needs autoconf at build time.

2 weeks agodocker: build libkqueue from source in the shared toolchain layers
Arran Cudbard-Bell [Wed, 20 May 2026 07:00:13 +0000 (03:00 -0400)] 
docker: build libkqueue from source in the shared toolchain layers

Rocky's arm64 archives don't ship libkqueue at all, and the
NetworkRADIUS extras repo only carries amd64 .debs, so every
type that runs `dnf builddep` or `mk-build-deps` against
freeradius's spec / control was failing on the missing dep.
The runtime service images then re-tripped the same gap on
`dnf install` / `apt install` of the freeradius package.

Two new m4 fragments build libkqueue from upstream HEAD as
proper .rpm / .deb files with `-debuginfo` / `-dbg` sidecar
packages (CMAKE_BUILD_TYPE=RelWithDebInfo so symbols survive,
CPACK_RPM_DEBUGINFO_PACKAGE=ON with an out-of-tree build dir
long enough for cpack's source-path constraint, and
CPACK_DEBIAN_PACKAGE_NAME=libkqueue0 so the cpack-emitted name
matches what freeradius's debian/control expects). Both are
included from the shared toolchain m4 so service / ci /
crossbuild / profiling all pick the same libkqueue up.

The two service templates (deb + rpm) additionally COPY the
runtime package across to the second stage so the final
freeradius install resolves at install time. The inline
non-amd64 libkqueue workaround that used to live in
service.deb.m4 went away -- it's covered by the toolchain
layer now and was previously skipping the debug-symbols build.

Other fixes folded in to land the full image set:
- ci.deb.m4 drops `--no-install-recommends` from mk-build-deps's
  apt-get arg so debian/control closures with Recommends-only
  pulls actually install (apt's resolver was previously bailing
  to "remove the dummy" rather than installing the deps).
- profiling.{deb,rpm}.m4 switch from distro cargo to a one-shot
  rustup install, so inferno's transitive crate MSRVs no longer
  collide with debian12's rustc 1.63 / Rocky's cargo. Toolchain
  is removed after the install to keep the layer small.
- profiling.deb.m4 drops the `google-perftools` binary package
  (gone from debiansid / ubuntu26 archives; libgoogle-perftools-dev
  ships the pprof binaries directly now).
- profiling.rpm.m4 uses `dnf --skip-broken` so Rocky 10's
  missing heaptrack doesn't take down the whole layer.
- common.deb.dbgsym.m4 / common.rpm.debuginfo.m4 install
  per-package with `|| true` so the structural Ubuntu LTS
  ddebs-vs-main version skew doesn't take down the layer
  either; a WARNING line surfaces any miss.

31 / 32 image stamps now build on arm64-Mac. rocky10.service
remains blocked on a freeradius-source bug -- src/lib/backtrace's
configure (autogenerated by an older autoconf) doesn't recognize
the --runstatedir option that Rocky 10's redhat-rpm-config
injects via %configure. That's a freeradius source fix
(autoreconf the submodule), not a docker pipeline change.

2 weeks agodocker: type-agnostic lifecycle, profiling for all distros, legacy crossbuild aliases
Arran Cudbard-Bell [Tue, 19 May 2026 20:41:30 +0000 (16:41 -0400)] 
docker: type-agnostic lifecycle, profiling for all distros, legacy crossbuild aliases

Splits the surface area further: docker.mk owns the generic image /
container / test machinery for every TYPE; crossbuild.mk is now a
thin alias layer (crossbuild.* -> docker.crossbuild.*) plus the
legacy crossbuild.help. DOCKER_TEST is the renamed type-parameterised
form of the old crossbuild test cycle, so docker.<type>.<image>.test
exists for every (image, type).

Profiling is no longer ubuntu24-only. A new profiling.rpm.m4 mirrors
the deb variant (valgrind, gperftools, heaptrack, kcachegrind, libkqueue
rebuild with debug symbols, FlameGraph, Inferno) using Rocky package
names, and common.rpm.debuginfo.m4 / common.deb.dbgsym.m4 are now
included unconditionally from both ci.* and crossbuild.* templates.
The deb repo URL was wrong (debian-debug.debian.net is unresolvable);
swapped to debug.mirrors.debian.org. The rpm side now goes through
`dnf debuginfo-install` (via dnf-plugins-core) so Rocky's per-version
debug-repo naming shifts don't break the build.

2 weeks agodocker: split into dockerfile.mk + docker.mk, lifecycle for every type
Arran Cudbard-Bell [Tue, 19 May 2026 20:16:35 +0000 (16:16 -0400)] 
docker: split into dockerfile.mk + docker.mk, lifecycle for every type

Restructures the build-system surface area into two files:
dockerfile.mk owns m4 -> Dockerfile.<type> generation and exposes
dockerfile / dockerfile.TYPE / dockerfile.TYPE.check; docker.mk
includes it and adds the image-build + container-lifecycle layer.
The shared _common.mk / m4-macros.mk indirection went away -- each
macro now lives in the file that calls it.

Lifecycle was previously crossbuild-only (CROSSBUILD_IMAGE_RULE
define). Pulled out into DOCKER_LIFECYCLE and applied to all four
types, so docker.TYPE.IMAGE.up / .down / .sh / .log / .reset works
for service / ci / crossbuild / profiling. Containers are named
$(DOCKER_IMAGE_PREFIX)-TYPE-IMAGE and sleep forever with the host
git tree bind-mounted read-only at /srv/src; an operator can drop
into any image with `make docker.TYPE.IMAGE.sh`. The crossbuild test
cycle (refresh + configure + make test) stays crossbuild-specific
behind CROSSBUILD_TEST, with `crossbuild.IMAGE` retained as a legacy
alias for `docker.crossbuild.IMAGE.test`.

Workflow paths updated for the new target shape (docker.<image>.build
-> docker.service.<image>). The legacy `docker` / `crossbuild` /
`crossbuild.IMAGE` / `crossbuild.common` entry points are kept as
aliases so external muscle memory and existing CI invocations keep
working unchanged.

2 weeks agodocker: target naming, clean rules, debuginfo factoring
Arran Cudbard-Bell [Tue, 19 May 2026 20:04:41 +0000 (16:04 -0400)] 
docker: target naming, clean rules, debuginfo factoring

Restructures the m4-template / make-target surface area exposed by
scripts/docker/. Macros and phonies are now consistently named:
dockerfile.<type>[.check] regenerates files, docker.<type>[.IMAGE][.status][.clean]
acts on the corresponding image. Umbrellas dockerfile / dockerfile.check /
docker.clean cover every type; per-image clean only nukes the stamp
when docker rmi succeeds, so a clean against a still-running container
leaves the state coherent for retry. Image tag namespace lifted to a
single DOCKER_IMAGE_PREFIX variable, stamp + per-build-log paths
relocated under scripts/docker/build/.state/, and CB_DIR stripped of
the project-root prefix so the docker-build invocations log relative
paths.

Debug-symbol install factored into common.deb.dbgsym.m4 (deb/ubuntu
dispatcher) and common.rpm.debuginfo.m4. The deb dispatcher routes
to private _common.ubuntu.dbgsym.m4 / _common.debian.dbgsym.m4 (the
underscore marks them as dispatcher-only), each handling the t64
package-name transition internally. ci and crossbuild templates now
pull in the relevant snippet so test failures inside those images
yield resolvable backtraces. Soft-fail tolerance dropped: a renamed
or retired -dbgsym / -debuginfo package now fails the build at
image-create time instead of silently producing an image without
symbols.

2 weeks agoci: prune locally-built docker images via ci-ttl label
Arran Cudbard-Bell [Tue, 19 May 2026 17:34:48 +0000 (13:34 -0400)] 
ci: prune locally-built docker images via ci-ttl label

Every image built by the scripts/docker pipeline now carries a
ci-ttl=<duration> label (default 60m, see DOCKER_BUILD in
scripts/docker/m4-macros.mk). This workflow walks each self-hosted
runner host on a 30-minute cron, parses the per-image TTL, and
removes anything whose age exceeds the declared lifetime. Hub-published
images aren't subject to this since they live on Docker Hub rather
than the runners; this is purely a local-disk hygiene job.

Duration parsing accepts go-style suffixes (s / m / h / d); anything
else is logged and skipped so an operator who later sets ci-ttl=keep
or similar doesn't wedge the prune loop.

2 weeks agodocker: add profiling image type, layered on the crossbuild base
Arran Cudbard-Bell [Tue, 19 May 2026 17:34:08 +0000 (13:34 -0400)] 
docker: add profiling image type, layered on the crossbuild base

Carry-over of PR 5834's profiling Dockerfile, refolded onto the
unified DOCKER_BUILD / M4_REGEN_* macros from the previous commit.
The image installs valgrind, gperftools, heaptrack, kcachegrind,
ubuntu-dbgsym repos and libkqueue with debug symbols on top of the
crossbuild image, plus FlameGraph and Inferno for callgraph
rendering.

The profiling step only makes sense on ubuntu (ddebs.ubuntu.com,
dbgsym suffixes), so the regen and build rules are gated to the
ubuntu24 distro via $(filter ...). Build prereqs include the
crossbuild stamp so make wires the dependency correctly, and the
docker build invocation passes --build-arg=from=
freeradius4-crossbuild/ubuntu24:<sha> so the profiling image is
genuinely a child layer rather than rebuilding the entire toolchain.

2 weeks agodocker: dedupe service / ci / crossbuild build rules into shared macros
Arran Cudbard-Bell [Tue, 19 May 2026 17:31:02 +0000 (13:31 -0400)] 
docker: dedupe service / ci / crossbuild build rules into shared macros

The four-and-soon-to-be-five m4-generated Dockerfile families were
each carrying their own hand-rolled per-image regen rule, drift
detector, and build rule. Fold the common shape into four reusable
macros in scripts/docker/m4-macros.mk: M4_REGEN_RULE for the per-image
m4 -> Dockerfile.<type> rule, M4_REGEN_BUNDLE for the umbrella regen
target, M4_REGEN_CHECK for the regen.check drift detector, and
DOCKER_BUILD for the per-image stamp-tracked docker build.

DOCKER_BUILD derives everything from (image, type): output is
freeradius4-<type>/<image>:<short-sha>, log lands at
$(DD)/build.<image>.<type>, stamp at $(DD)/stamp-image.<image>.<type>,
and every locally-built image is labelled ci-ttl=60m so the
periodic prune workflow can identify ephemeral builds. Local
build stamp paths gained the .<type> suffix; anyone with scripts
that rm the old stamp-image.<image> needs to know.

2 weeks agodocker: rename generated Dockerfile output suffixes
Arran Cudbard-Bell [Tue, 19 May 2026 17:24:43 +0000 (13:24 -0400)] 
docker: rename generated Dockerfile output suffixes

Adopt the Dockerfile.<type> convention across the m4-generated tree.
The production image is now scripts/docker/build/<distro>/Dockerfile.service
(was Dockerfile), the crossbuild image is Dockerfile.crossbuild (was
Dockerfile.cb). Dockerfile.ci was already correctly suffixed and is
unchanged.

scripts/docker/docker.mk and scripts/docker/crossbuild.mk point at
the new paths in their build / regen / regen.check rules. The
crossbuild.yml workflow comment that mentioned Dockerfile.cb was
updated too; matrix entries and other workflow paths were already
type-suffixed and didn't move.

2 weeks agodocker: rename type identifiers to service / ci / crossbuild
Arran Cudbard-Bell [Tue, 19 May 2026 17:22:45 +0000 (13:22 -0400)] 
docker: rename type identifiers to service / ci / crossbuild

The m4-generated Dockerfile family used inconsistent labels: the
production image was called "docker" (overloaded with the make
namespace), the CI base image was called "ci-base", and crossbuild
was already correctly named. Rename the m4 source files
(docker.{deb,rpm}.m4 -> service.{deb,rpm}.m4, ci-base.{deb,rpm}.m4
-> ci.{deb,rpm}.m4), the D_TYPE values passed to m4, and the make
bundle targets to docker.<type>.regen[.check] so all docker-adjacent
targets share a single namespace prefix.

The dispatcher template's "Rebuild this file with" header now points
at the bundle target (make docker.<type>.regen) since per-image regen
phonies were retired in an earlier commit. Workflow steps and the
top-level Makefile conditional include were updated to match; the
docker-refresh.yml inline comment that referenced ci-base.m4 was
corrected too.

2 weeks agomore char -> uint8_t fixes for callers of fr_sbuff_char()
Alan T. DeKok [Wed, 20 May 2026 14:56:35 +0000 (09:56 -0500)] 
more char -> uint8_t fixes for callers of fr_sbuff_char()

2 weeks agoadd and use fr_sbuff_uint8()
Alan T. DeKok [Wed, 20 May 2026 14:38:24 +0000 (09:38 -0500)] 
add and use fr_sbuff_uint8()

which is just a cast to uint8_t around fr_sbuff_char()

so that when use the char as an index into arrays, we don't have
negative indices

2 weeks agocase to unsigned before using char as index into array
Alan T. DeKok [Wed, 20 May 2026 14:34:34 +0000 (09:34 -0500)] 
case to unsigned before using char as index into array

2 weeks agocheck for remaining before dereferencing
Alan T. DeKok [Wed, 20 May 2026 14:05:21 +0000 (09:05 -0500)] 
check for remaining before dereferencing

and add test case

2 weeks agoturn off fuzzer_cf so that we can merge other things
Alan T. DeKok [Wed, 20 May 2026 12:33:47 +0000 (07:33 -0500)] 
turn off fuzzer_cf so that we can merge other things

2 weeks agocatch case where function call fails
Alan T. DeKok [Tue, 19 May 2026 22:49:24 +0000 (17:49 -0500)] 
catch case where function call fails

2 weeks agocatch corner case in sbuff, and add test for it
Alan T. DeKok [Tue, 19 May 2026 22:06:39 +0000 (17:06 -0500)] 
catch corner case in sbuff, and add test for it

2 weeks agoskip: cap fr_skip_brackets / fr_skip_xlat recursion at 64
Arran Cudbard-Bell [Tue, 19 May 2026 15:12:00 +0000 (11:12 -0400)] 
skip: cap fr_skip_brackets / fr_skip_xlat recursion at 64

fr_skip_brackets recurses into itself for `(`, calls fr_skip_xlat for `${`/`%{`, and fr_skip_xlat recurses back into fr_skip_brackets. Nothing tracked depth, so an input like `${(((((...` consumed C-stack until SIGABRT. The new fuzzer_cf harness in CI found it; cf_expand_variables now reports the parse error instead of crashing.

Wrap the bodies in static skip_brackets / skip_xlat helpers that carry a depth counter; the public fr_skip_brackets / fr_skip_xlat call them at depth 0 so the API stays unchanged. Cap is 64, matching what fuzzer_cf already filters its inputs at.

2 weeks agodocker / crossbuild: declare regen and regen.check targets .PHONY
Arran Cudbard-Bell [Tue, 19 May 2026 14:43:33 +0000 (10:43 -0400)] 
docker / crossbuild: declare regen and regen.check targets .PHONY

These targets produce no file output, so make would skip them if a file with the matching name ever appeared in the cwd - cheap footgun, .PHONY is the right hygiene. Stay consistent with the per-image .build target which is .PHONY for the same reason.

2 weeks agocrossbuild: regen deb Dockerfile.cb files for fakeroot
Arran Cudbard-Bell [Tue, 19 May 2026 14:30:26 +0000 (10:30 -0400)] 
crossbuild: regen deb Dockerfile.cb files for fakeroot

`fakeroot` was added to common.deb.toolchain.m4 earlier (to unstick `make deb` on newer dpkg) but the deb-family Dockerfile.cb files weren't regenerated then - only the production Dockerfile and Dockerfile.ci got refreshed. The newly-landed crossbuild.regen.check caught it.

2 weeks agodocker / crossbuild: verify generated Dockerfiles match m4 source
Arran Cudbard-Bell [Tue, 19 May 2026 14:17:42 +0000 (10:17 -0400)] 
docker / crossbuild: verify generated Dockerfiles match m4 source

New `docker.regen.check`, `ci-base.regen.check` and `crossbuild.regen.check` make targets render each m4 source to a temp file and diff against the committed Dockerfile / Dockerfile.ci / Dockerfile.cb. Fails noisily if a contributor edited an m4 template but forgot to regen + commit.

Wire the checks into docker.yml and crossbuild.yml as a pre-build step. Both workflows fire on push to any branch so the drift is caught at PR time, before stale Dockerfiles get used in a release-side build.

2 weeks agodocker.yml: drop the explicit Regenerate Dockerfile step
Arran Cudbard-Bell [Tue, 19 May 2026 14:14:44 +0000 (10:14 -0400)] 
docker.yml: drop the explicit Regenerate Dockerfile step

The Dockerfiles under scripts/docker/build/<distro>/ are m4-generated by contributors locally and committed alongside the m4 source. The workflow doesn't need to rm + regen them before building - the committed file is the canonical version and matches the m4 by virtue of the regen happening at commit time. Drop the step from both job paths (selfhosted and public-fork variants).

2 weeks agodocker / crossbuild: drop per-image .regen phony aliases
Arran Cudbard-Bell [Tue, 19 May 2026 13:49:17 +0000 (09:49 -0400)] 
docker / crossbuild: drop per-image .regen phony aliases

`docker.<distro>.regen`, `crossbuild.<distro>.regen` and (previously) `ci-base.<distro>.regen` were thin phony aliases over the underlying Dockerfile / Dockerfile.cb / Dockerfile.ci file targets. The file targets already track their m4 deps correctly, so `make scripts/docker/build/<distro>/Dockerfile` does the same job. The bundle targets `docker.regen`, `crossbuild.regen`, `ci-base.regen` now depend on the file targets directly.

While in here, fix the umbrella `docker` / `docker.common` targets - they depended on `docker.<distro>` (no suffix), which was never defined, so `make docker` was a latent error. Point them at `docker.<distro>.build` to match what the help text says they do.

2 weeks agocrossbuild: use the workflow name as the job-title prefix
Arran Cudbard-Bell [Tue, 19 May 2026 13:25:48 +0000 (09:25 -0400)] 
crossbuild: use the workflow name as the job-title prefix

The hardcoded `v4.0.x-` prefix has been stale for years - the inner loop in crossbuild.{deb,rpm}.m4 iterates every `v[4-9]*.[0-9x]*.x` and master branch, so the displayed name was misleading. Use `${{ github.workflow }}` so the prefix follows whatever the workflow is called.

2 weeks agofuzzer: move util to standalone targets, unify test rules
Arran Cudbard-Bell [Tue, 19 May 2026 04:48:15 +0000 (00:48 -0400)] 
fuzzer: move util to standalone targets, unify test rules

util follows the per-protocol test_point shape (src/lib/util/fuzzer.c exposes util_tp_decode_proto / util_tp_encode_proto) but isn't a wire protocol, so it's a slightly odd entry in FUZZER_PROTOCOLS. Move it to FUZZER_NON_PROTOCOL_TARGETS alongside json/cf/value/xlat. fuzzer_util.c is the FUZZ_PROTOCOL template expansion baked out into a tracked source file; fuzzer_util.mk mirrors the other standalone .mk files.

While doing it, generalise the per-non-protocol test rule to read $(FUZZER_<name>_ARGS) so per-target extras flow through one mechanism. util's entry is "-D share/dictionary" (it needs the dict the same way the wire protocols do); the rest stay empty. The umbrella test.fuzzer and test.fuzzer.merge targets now span both lists.

2 weeks agofuzzer: wire json / cf / value / xlat into test.fuzzer and the schedule
Arran Cudbard-Bell [Tue, 19 May 2026 04:41:59 +0000 (00:41 -0400)] 
fuzzer: wire json / cf / value / xlat into test.fuzzer and the schedule

Four fuzzer binaries (fuzzer_json, fuzzer_cf, fuzzer_value, fuzzer_xlat) were built but never run by `test.fuzzer` or the nightly fuzzing workflow - they had no test.fuzzer.<name> targets and weren't in FUZZER_PROTOCOLS. They cover meaningful surface (JSON parsing, config-section parsing, value boxes, xlat expansion) and have been silently unfuzzed for a while.

Add a FUZZER_NON_PROTOCOL_TARGETS list and a FUZZ_NON_PROTOCOL_TEST define that emits the per-target test / merge rules, mirroring fuzzer.mk's per-protocol shape minus the `-D share/dictionary` flag (json/cf/value parse raw bytes; xlat resolves the dictionary itself from argv[0]). Corpus directories are created on demand; no .tar files shipped yet, so the first runs start from scratch. ci-scheduled-fuzzing.yml's set-matrix concatenates both lists so the schedule fans out to all sixteen binaries instead of twelve.

2 weeks agoci-macos / ci-freebsd: parallelise the trailing `make test`
Arran Cudbard-Bell [Tue, 19 May 2026 04:35:24 +0000 (00:35 -0400)] 
ci-macos / ci-freebsd: parallelise the trailing `make test`

The two workflows already parallelise the per-target test runs above (test.keywords / test.unit / test.modules / test.auth / test.digest), then immediately run `make test` (umbrella target) without -j, serialising whatever sub-targets it pulls in. Match the line above so the final pass also fans out across nproc cores.

2 weeks agoci-scheduled-fuzzing: parallelise test.unit
Arran Cudbard-Bell [Tue, 19 May 2026 04:29:30 +0000 (00:29 -0400)] 
ci-scheduled-fuzzing: parallelise test.unit

The main ci-tests action runs `make -j \`nproc\` test.unit ...` but the fuzzing workflow's test.unit invocation was missing the -j, so it ran sequentially across all unit tests on every fuzzer matrix entry (12 of them) - a significant chunk of the wall-clock per job. Match the main CI pattern.

2 weeks agofuzzer: explicitly link $(LIBS) into the non-protocol fuzzer binaries
Arran Cudbard-Bell [Tue, 19 May 2026 04:16:05 +0000 (00:16 -0400)] 
fuzzer: explicitly link $(LIBS) into the non-protocol fuzzer binaries

fuzzer_value, fuzzer_xlat and fuzzer_cf were missing the TGT_LDLIBS := $(LIBS) line that fuzzer.mk (for the per-protocol fuzzers) and fuzzer_json.mk already carry. They've been getting libtalloc and friends transitively from libfreeradius-*; a binutils linker default flip (`--no-copy-dt-needed-entries` on ubuntu 24.04 vs the older `--copy-dt-needed-entries`) stopped tolerating that, and the link failed with `undefined reference to symbol _talloc_array@@TALLOC_2.0.2`.

2 weeks agoself-hosted testbed: add openssh-client, jq, rsync
Arran Cudbard-Bell [Tue, 19 May 2026 04:09:47 +0000 (00:09 -0400)] 
self-hosted testbed: add openssh-client, jq, rsync

These come up routinely in CI workflows: openssh-client for any git-over-ssh deploy step (broke deploy-antora-docs), jq for any JSON-shaping bash, rsync for tree copies. wget was already present. Bake them in once instead of letting each migrating workflow apt-get them per job.

2 weeks agodocumentation: install openssh-client in deploy-antora-docs
Arran Cudbard-Bell [Tue, 19 May 2026 04:02:43 +0000 (00:02 -0400)] 
documentation: install openssh-client in deploy-antora-docs

The testbed image carries the build toolchain but not openssh-client, and the deploy step git-clones via ssh from git.networkradius.com. Without ssh git fails with `cannot run ssh: No such file or directory`.

2 weeks agoci-scheduled-fuzzing: pass workflow-env CC to freeradius-deps
Arran Cudbard-Bell [Tue, 19 May 2026 03:57:59 +0000 (23:57 -0400)] 
ci-scheduled-fuzzing: pass workflow-env CC to freeradius-deps

The set-matrix step emits PROTOCOL/TOTAL_RUNTIME/UPLOAD_SLOT/NUM_SLOTS but not CC, so `cc: ${{ matrix.env.CC }}` evaluated to empty and the freeradius-deps action's `Install LLVM` step (gated on `inputs.cc == 'clang'`) was skipped. clang-18 was already in the testbed image but the unsuffixed `clang` symlink that step's update-alternatives normally creates wasn't there, so the subsequent `$CC --version` failed with "clang: command not found". Pull CC from the workflow-level env where it actually lives.

2 weeks agoself-hosted CI containers: default shell to bash
Arran Cudbard-Bell [Tue, 19 May 2026 03:43:54 +0000 (23:43 -0400)] 
self-hosted CI containers: default shell to bash

GitHub Actions runs `run:` steps under sh (dash on the testbed image) when a `container:` block is set, not bash as on a bare runner. Several existing steps rely on bash arithmetic / quoting / arrays. Set the per-job default to bash on coverity, documentation, and scheduled-fuzzing so behaviour matches the pre-container workflows.

2 weeks agoci-scheduled-fuzzing: read FUZZER_PROTOCOLS from src/fuzzer/all.mk
Arran Cudbard-Bell [Tue, 19 May 2026 03:29:31 +0000 (23:29 -0400)] 
ci-scheduled-fuzzing: read FUZZER_PROTOCOLS from src/fuzzer/all.mk

The fuzzer code moved out of src/bin/ into its own directory in commit 1294535465, but the matrix-set step here kept reading src/bin/all.mk - the sed never matched, PROTOS was empty, and the build failed at `${P:0:-1}` with bash's misleading 'substring expression < 0' (because the empty-string substring index is degenerate). The workflow only runs on schedule so the silent breakage went unnoticed.

2 weeks agocoverity / scheduled-fuzzing: enable workflow_dispatch
Arran Cudbard-Bell [Tue, 19 May 2026 03:25:57 +0000 (23:25 -0400)] 
coverity / scheduled-fuzzing: enable workflow_dispatch

Lets us trigger these manually via `gh workflow run` (and the Actions UI) without having to push to coverity_scan / run-fuzzer-* branches just to kick a job. Useful for testing the just-landed self-hosted container migration ahead of the next scheduled run.

2 weeks agomove coverity / documentation / fuzzing to self-hosted CI container
Arran Cudbard-Bell [Tue, 19 May 2026 03:23:27 +0000 (23:23 -0400)] 
move coverity / documentation / fuzzing to self-hosted CI container

These three workflows ran on ubuntu-latest with ~30s of per-job apt setup (NetworkRADIUS repo, mk-build-deps, etc.) that's already baked into the self-hosted-ubuntu24 testbed image. They were also gated by `if:` conditions that mostly only fired for the FreeRADIUS org anyway - coverity needs the COVERITY_SCAN_TOKEN secret, the doc deploys push to FreeRADIUS-controlled infra, fuzzing pushes corpus updates back to the FreeRADIUS LFS. Drop the fork-compat branches, run on the self-hosted Proxmox fleet inside the standard CI container.

coverity loses ~30 lines of apt + mk-build-deps wiring. documentation keeps the asciidoctor/doxygen/graphviz/antora install since the testbed image doesn't carry doc-build tooling, but drops the sudo prefixes (we're root inside the container). scheduled-fuzzing's freeradius-deps action call flips from use_docker=false to use_docker=true so the action skips the host-setup steps it'd otherwise run on a bare ubuntu runner.

2 weeks agoRevert "ci-freebsd: prefer self-hosted runners on the FreeRADIUS org"
Arran Cudbard-Bell [Tue, 19 May 2026 02:40:33 +0000 (22:40 -0400)] 
Revert "ci-freebsd: prefer self-hosted runners on the FreeRADIUS org"

This reverts commit 2aff2baa6c4f3cb1969a7e26f84e08f45c082ba6.

2 weeks agoci-freebsd: prefer self-hosted runners on the FreeRADIUS org
Arran Cudbard-Bell [Tue, 19 May 2026 02:31:27 +0000 (22:31 -0400)] 
ci-freebsd: prefer self-hosted runners on the FreeRADIUS org

Mirror the existing ternary pattern from earlier crossbuild / ci-deb / ci-rpm work: when github.repository_owner is 'FreeRADIUS', use the self-hosted Proxmox fleet (which has the VM hypervisor cross-platform-actions needs for the FreeBSD VirtualBox VM and isn't subject to GH-hosted runner queue contention); otherwise fall through to ubuntu-latest so fork pushes and PRs still run.

2 weeks agoname the setup-dind step in workflows that use it
Arran Cudbard-Bell [Tue, 19 May 2026 02:28:45 +0000 (22:28 -0400)] 
name the setup-dind step in workflows that use it

All five `uses: ./.github/actions/setup-dind` invocations were anonymous, so the Actions UI displayed them as "Run ./.github/actions/setup-dind" - long, noisy, and not searchable in the step list. Add an explicit `name: setup-dind` to each so they render as "Run setup-dind" and line up with the other named steps.

2 weeks agocrossbuild: fix double-slash in m4 paths and auth dind to internal registry
Arran Cudbard-Bell [Tue, 19 May 2026 02:17:01 +0000 (22:17 -0400)] 
crossbuild: fix double-slash in m4 paths and auth dind to internal registry

CB_DIR was constructed via `$(dir $(realpath ...))`, which always ends in `/`. Subsequent concatenations of the form `$(CB_DIR)/build` produced rendered paths like `/workspace/scripts/docker//build`, which made the BUILD/REGEN log lines and stamp-file paths ugly (though make itself happily collapses the doubled slash). Strip the trailing slash once at the CB_DIR definition with patsubst so every existing `/foo` concat stays readable.

The dind sidecar's daemon isn't pre-authenticated to docker.internal.networkradius.com - only the self-hosted runner host's daemon is, via the runner's job-started hook, and that auth doesn't propagate into dind. crossbuild now FROMs self-hosted-* via the CB_FROM_<distro> overrides, so the inner build was failing with `401 Unauthorized` on the manifest HEAD. Add an explicit `docker login` step via the existing DOCKER_REPO_USERNAME/_PASSWORD secrets, mirroring what ci-multi-server-tests.yml already does for the same reason.

2 weeks agoci-base.deb: keep the debian/ prefix when staging source for mk-build-deps
Arran Cudbard-Bell [Tue, 19 May 2026 02:00:00 +0000 (22:00 -0400)] 
ci-base.deb: keep the debian/ prefix when staging source for mk-build-deps

Newer dpkg (in ubuntu26, debiansid) routes through /usr/share/dpkg/buildapi.mk, which reads `debian/control` relative to CWD when debian/rules is invoked. The previous COPY flattened the contents of debian/ into /tmp/freeradius-debian/, leaving rules with no `debian/control` underneath it to find - the build failed with `dpkg-buildapi: error: cannot read debian/control: No such file or directory` and an opaque `intcmp: empty value` from buildapi.mk. Older dpkg (debian12, ubuntu22-24, debian13) tolerated the flat layout.

Stage the source as /tmp/freeradius-build/debian/ and run mk-build-deps from /tmp/freeradius-build so debian/rules sees the canonical layout.

2 weeks agoci-base.deb: drop the extras-control mk-build-deps pass
Arran Cudbard-Bell [Tue, 19 May 2026 01:52:17 +0000 (21:52 -0400)] 
ci-base.deb: drop the extras-control mk-build-deps pass

The deb-build job only needs debian/control's closure plus libnl for the eapol_test build; the full scripts/ci/extra-packages.debian.control file is for the self-hosted-ubuntu24 integration testbed (dovecot, freetds, firebird, collectd, ...), and several of its entries either don't exist on older ubuntu/debian releases or have differently-named substitutes. Trying to mk-build-deps it on ubuntu22 failed with the misleading 'Unable to install freeradius-build-deps' - the -f resolver invoked internally by mk-build-deps -i discards the unconfigured meta-package rather than fetch a missing dep.

Cut over to a single mk-build-deps against debian/control, plus an explicit apt-get install of libnl-3-dev / libnl-genl-3-dev. The extras file is left for its actual consumer (scripts/ci/docker/Dockerfile, the ubuntu24 testbed), which uses the equivs-meta-package install path that doesn't double up.

2 weeks agoci-base.deb: purge meta-package between mk-build-deps passes
Arran Cudbard-Bell [Tue, 19 May 2026 01:42:51 +0000 (21:42 -0400)] 
ci-base.deb: purge meta-package between mk-build-deps passes

debian/control and scripts/ci/extra-packages.debian.control both declare
`Source: freeradius`, so both mk-build-deps invocations emit a meta-package
named freeradius-build-deps. Older apt (debian12, ubuntu22) silently
downgraded the first install when the second arrived; newer apt (debian13,
debiansid, ubuntu26 - and likely ubuntu24 next) refuses to reconfigure
and removes the meta-package instead, causing the second pass to fail with:

  mk-build-deps: Unable to install freeradius-build-deps

Mirror what scripts/ci/docker/Dockerfile (the self-hosted-ubuntu24 testbed
image) already does: apt-get -y --purge remove freeradius-build-deps after
each install. The transitively-pulled build deps stay installed (marked
auto-installed, but nothing in the image build ever runs autoremove), and
the second mk-build-deps installs cleanly without colliding.

2 weeks agofactor common build setup into shared m4 snippets, add ci-base template
Arran Cudbard-Bell [Tue, 19 May 2026 00:47:33 +0000 (20:47 -0400)] 
factor common build setup into shared m4 snippets, add ci-base template

The production / crossbuild / CI base Dockerfiles all installed the same
apt retry config, same toolchain, same NetworkRADIUS extras repo - three
times each, slightly differently. The CI bases were also hand-written
under scripts/ci/docker, sitting outside the m4 system the production
and crossbuild Dockerfiles already used.

Extract the shared chunks into scripts/docker/m4/common.*.m4:

  common.apt.retries.m4         apt + dpkg + debconf speedups
  common.deb.toolchain.m4       apt-get update + dist-upgrade + base toolchain
  common.deb.nr-extras.m4       NetworkRADIUS extras repo (per-distro substitutes)
  common.dnf.retries.m4         dnf retry / timeout overrides
  common.rpm.toolchain.m4       Rocky GPG import + dnf update + base toolchain + CRB
  common.rpm.nr-extras.m4       NetworkRADIUS extras repo (releasever-substituted)

The four existing content templates (docker.{deb,rpm}.m4, crossbuild.{deb,rpm}.m4)
rewritten to include() the shared chunks instead of inlining their own copies.
Add a third content template family ci-base.{deb,rpm}.m4 which generates
Dockerfile.ci per-distro - replaces the hand-written Dockerfile.{debian,rocky}
under scripts/ci/docker.

docker.mk gains an M4_SHARED dep list so any snippet change invalidates all
generated Dockerfiles, plus a top-level ci-base.regen that bundles all eight
images (no per-image variant; m4 rendering is milliseconds, not worth the
extra rule duplication). Makefile conditional include extended so
`make ci-base.regen` actually loads docker.mk.

docker-refresh.yml matrix entries for the rocky / deb bases switch from
referencing scripts/ci/docker/Dockerfile.{rocky,debian} + per-row
build_args.from to referencing the generated scripts/docker/build/<distro>/
Dockerfile.ci files directly. No build-args needed because m4 bakes the
FROM at regen time. Paths filter extended so Dockerfile.ci changes trigger
the refresh.

Production / crossbuild renderings shift slightly as a side effect of
sharing the snippets:

- apt timeouts switch from full HTTP Timeout (15s) to TCP ConnectTimeout
  (5s). Better behaviour: failover is bounded by reachability, not download
  duration, so a slow but progressing mirror isn't aborted.
- All apt-get installs now use --no-install-recommends. Slightly smaller
  images; no production-relevant Recommends were in play (lintian / dh-make
  / less were the main ones, none of which the build path needs).
- Production deb image picks up build-essential / ca-certificates /
  gnupg2 / lsb-release / make explicitly (was relying on mk-build-deps
  pull-through). Same end-state, more cache-stable layer.
- Rocky crossbuild now does the same rpmkeys --import the production
  image does. Harmless on a stock rockylinux base, defensive after dnf
  update if a key rotation lands.

The hand-written Dockerfile (self-hosted-ubuntu24 testbed),
Dockerfile.docker-cli, and Dockerfile.docker-dind under scripts/ci/docker
stay hand-written - they're specialised CI scaffolding (integration
testbed, dind sidecar, docker CLI wrapper), not build environments, and
don't fit the m4 build-image pattern.