Conversation
exynos_defconfig has none of the namespace/cgroup/netfilter/overlayfs wiring docker needs, and NETFILTER itself defaults off, so nothing under it resolves without a fragment. defaults/kernel-config/docker follows app-containers/docker's own CONFIG_CHECK, including the IP_NF_IPTABLES_LEGACY chain the ebuild only requires from kernel 6.17 onward. The dongle (0bda:f179, sold as "RTL8188FTV") is an RTL8188FU, which mainline's rtl8xxxu already knows how to drive; CFG80211, MAC80211 and LEDS_CLASS are already on courtesy of the board's own defconfig, so the board-specific fragment is one line. Firmware comes from the same linux-firmware clone already used for the onboard RTL8153 NIC. wpa_supplicant/iw/wireless-regdb go in target-packages.txt rather than being left for an on-device emerge, since the dongle may be the only network path available to bootstrap one. SSID/PSK are deliberately left out -- a per-deployment secret, not something to commit. app-containers/docker itself is left out: it would be the first Go cross-compile in this tree, and installing it natively once the board is booted and networked avoids that risk entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
board.conf documents this field as bash-array syntax
(KERNEL_CONFIG_FRAGMENTS=("docker" "wifi-rtl8188fu"), per
defaults/kernel-config/docker's own header comment), and the config-file
line parser correctly routes any value starting with '(' into the
`arrays` map. But the field was read back with `kv.get(...)`, the plain
scalar map, which never has this key when array syntax is used -- so it
silently fell through to unwrap_or_default() and produced an empty
fragment list on every single build.
Caught on real odroid-xu4 hardware: docker's netfilter/bridge/USER_NS
config and the RTL8188FU wifi driver were both documented as "baked
into every image" but neither actually made it into the kernel .config
for the 2026-09-06 build. dockerd failed to start
(`failed to register "bridge" driver: ... Module ip_tables not found`)
and `find /lib/modules -iname "*bridge*" -o -iname "*veth*"` came back
empty, which is what led here -- confirmed against the build's own
linux/.config, which has `# CONFIG_RTL8XXXU is not set` and none of the
docker fragment's symbols despite board.conf listing both fragments.
Fixed by checking `arrays` first, falling back to the old
whitespace-split `kv` read so a future board.conf that writes this
field unquoted without parens keeps working. Added regression tests for
both syntaxes plus the empty-default case.
This requires rebuilding the odroid-xu4 image from scratch -- the
2026-09-06 image was built before this fix and needs to be replaced,
not patched on-device (the kernel comes from the boot partition, not
something on-device package installs can fix).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
…onfig
kernel_config_fragments() generated `make ... ARCH=$ARCH
CROSS_COMPILE=$CROSS_COMPILE olddefconfig`, referencing shell variables
that default_kernel()'s script never exports -- the other two `make`
invocations in the same script correctly substitute the real karch/cc
values via Rust format interpolation (`ARCH={karch}`), but this one was
left as literal, unexpanded `$ARCH`/`$CROSS_COMPILE` text. With ARCH
empty, `make` resolves `arch/$(ARCH)/Makefile` to `arch//Makefile`,
which doesn't exist:
make: *** No rule to make target 'arch//Makefile'. Stop.
This was never exercised until now: the previous commit's
KERNEL_CONFIG_FRAGMENTS parsing bug meant board.kernel_config_fragments
was always empty, so kernel_config_fragments() always short-circuited
to an empty string before ever reaching this line. Fixing the parsing
bug immediately surfaced this second one on the very next odroid-xu4
build.
Fixed by threading karch/cc through as parameters and interpolating
them the same way the surrounding calls do. Updated the existing unit
tests' call sites and added an assertion that the generated script
never contains the bare `$ARCH` form.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
… exist
CONFIG_NET_CLS_CGROUP lives in net/sched/Kconfig's QoS/fair-queueing
submenu, itself gated by the `menuconfig NET_SCHED` bool (default n).
Without NET_SCHED=y the whole submenu is unreachable, so olddefconfig
doesn't just turn NET_CLS_CGROUP off -- it drops the line from .config
entirely, not even leaving behind a "# CONFIG_NET_CLS_CGROUP is not
set" comment. That's exactly what image.rs's post-fragment check exists
to catch:
kernel config lost: CONFIG_NET_CLS_CGROUP=m
Caught on the first-ever real application of this fragment (see the
previous two commits: a board.conf parsing bug meant no board's kernel
fragments were ever actually merged into a build before now, which in
turn meant this fragment had never been run through an actual kernel
tree despite its header comment claiming it was "verified line-by-line
against v7.2's actual Kconfig defaults/types").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
… the image Installing app-containers/docker natively on real hardware hit four Portage-environment issues (documented in README's "Known gotchas"): a missing RTC breaking emerge-webrsync, two packages' hardcoded CGO_ENABLED=0 on 32-bit ARM's PIE-by-default Go, and containerd needing live network past FEATURES=network-sandbox. Doing all of that by hand after every fresh flash is exactly the kind of thing this project bakes into the image instead: - make.conf (auto-appended into the target's /etc/portage/make.conf by the existing per-board mechanism): CGO_ENABLED=1, so ebuilds that read the variable rather than hardcoding it off build correctly. - post-assemble.sh: a global /etc/portage/bashrc post_src_prepare() hook that sed-patches the two Makefiles (dev-go/go-md2man, app-containers/containerd) that hardcode CGO_ENABLED=0 literally, where a mere env var can't override it; and a package.env entry disabling network-sandbox for containerd (its go mod download needs live network, unlike go-md2man's vendored deps tarball) plus SHIM_CGO_ENABLED=1 for its shim target, which unlike the hardcoded ones reads a `?=`-defaulted variable and takes the env var straight. Verified against a real rebuild: all four files land correctly in the packed rootfs.ext4 (checked via debugfs, no mount needed), alongside the kernel-side fix from the previous three commits -- rtl8xxxu.ko, bridge.ko, br_netfilter.ko, veth.ko and the nf_nat/xt_* netfilter modules are all present in /lib/modules now, where before none of them were. RTC/webrsync and emerge-webrsync itself are unchanged: net-misc/ntp and ntpd:default were already in target-packages.txt/BOOT_SERVICES, and there's no ebuild-Makefile-shaped fix for "the clock is wrong on first boot" to bake in the same way. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
Structural half of what was originally one commit (see boards-odroid-xu4-full for the other half, defaulting the gcc pin to gcc_slot -- a fix for a specific package-version-drift scenario, left out of this branch on purpose since it doesn't reproduce regardless of what's currently in the Portage tree). These three are logic bugs / dead code, independent of tree state: Reordering install_overlay() after install_host_deps() fixes a fresh-stage3 failure: overlay checkout uses git, which a bare stage3 doesn't have until install_host_deps() emerges dev-vcs/git. Dropping the unconditional --ex-pkg sys-devel/clang-crossdev-wrappers: nothing in this codebase reads it, and getting it installed means compiling an entire pinned-slot clang+lld from source for a symlink package nothing depends on. Gating --ex-pkg sys-devel/rust-std on board.rustflags: cross rust-std needs dev-lang/rust from source as its bootstrap (needs ~9.6GB tmpfs), not worth forcing on every board when most never touch Rust. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dev-vcs/git's "rust" USE flag is on by default and builds a Rust component
("gitcore") that needs the armv7a rust-std target. This board doesn't set
BOARD_RUSTFLAGS, so sandbox.rs deliberately skips cross rust-std (see the
rust_std_ex_pkg gating in setup_crossdev) -- without this override, git
fails cross-compiling with "can't find crate for `std`".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
…icapsule odroid-xu3_defconfig enables CONFIG_TOOLS_MKEFICAPSULE. That host tool is built directly by U-Boot's own Makefile (HOSTCC/HOSTLD), not by any ebuild, and links against the sandbox's own net-libs/gnutls -- which lacks PKCS#11 support by default, so the link fails with "undefined reference to `gnutls_pkcs11_init`" and four similar symbols. net-libs/gnutls is named explicitly in sandbox-packages.txt (not just given a package.use entry) so that Portage::emerge's --changed-use actually rebuilds the already-installed, flag-less copy instead of leaving it in place. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
README.md: this session's actual build host was Ubuntu/WSL2, not Gentoo, so "Building without a Gentoo host" documents the container setup that worked (cap-add=SYS_ADMIN + unconfined seccomp/apparmor for hakoniwa's overlayfs, a real bind-mounted cache dir to dodge the overlay-on-overlay kernel limit, building the crossdev-stages binary on the actual host, and -e USER=builder on every docker exec). boards/odroid-xu4/README.md: documents the Docker (kernel support baked in, package emerged natively on-device) and WiFi (RTL8188FU driver/firmware baked in, SSID/PSK deliberately left out and configured post-boot) decisions that shaped the last several commits, and records that the 2026-09-06 build carrying both compiled and packed cleanly without yet being flashed/booted. (This is boards-odroid-xu4-portable's copy of the original combined docs commit, with the perl-pin paragraph left out: that pin lives in portage.rs, which this branch doesn't carry -- see boards-odroid-xu4-full for that half.) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Real-hardware install of app-containers/docker hit four environment issues, none of them crossdev-stages bugs: no battery-backed RTC breaking emerge-webrsync's snapshot walk, go-md2man's hardcoded CGO_ENABLED=0 (known upstream Gentoo/Go bug 924632), containerd's build needing live network past network-sandbox, and a second PIE/cgo failure in containerd-shim-runc-v2 caused by a `?=`-defaulted var rather than a hardcoded one. Record the diagnosis and fix for each so the next from-scratch setup doesn't re-derive them. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
…d in The previous commit moved three of the four documented workarounds (go-md2man's and containerd-shim's CGO_ENABLED, containerd's network-sandbox) from manual post-boot Portage config into make.conf and post-assemble.sh, so the README's "run these commands" framing was now wrong -- it described manual steps an image built from this directory already does automatically. Reframe as background on what each gotcha is and why, mark the three that are now baked in, and note that the RTC/ntpd one mostly self-corrects on boot already (ntpd:default + NTPD_OPTS="-g" step the clock within seconds), keeping the manual `ntpd -q -g -x` only as a fallback. Also: emerge app-containers/docker alone gets a running daemon and no `docker` CLI to talk to it -- docker-cli is a separate package. Added it to the install line, and the usermod -aG docker step for using it without sudo (came up when actually running through this on hardware). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CyTatHFT5zUgSV7cVE8Ngi
lu-zero
reviewed
Sep 13, 2026
| runner.run(&format!( | ||
| "crossdev {chost} \ | ||
| --gcc {gcc_ver} \ | ||
| --ex-pkg sys-devel/clang-crossdev-wrappers{rust_std_ex_pkg}" |
Owner
There was a problem hiding this comment.
why you dropped the crossdev wrappers?
Contributor
Author
There was a problem hiding this comment.
I built failed with clang while building rust on the Gentoo container, so this change needs to use GCC instead of clang.
But... I think this might just be a mess-up in my dev environment... I'll rebuild and check on an Ubuntu host with hakoniwa
lu-zero
reviewed
Sep 13, 2026
| // overlay repo is the source of truth and the checkout is cheap | ||
| // and idempotent. Safe here specifically because a sandbox that | ||
| // reached `.prepared` already has git from a previous prepare. | ||
| install_overlay(self.runner(), &self.dir, defaults_root)?; |
Owner
There was a problem hiding this comment.
this looks wrong, why you had to move it here?
Contributor
Author
There was a problem hiding this comment.
Before that change, container couldn't find 'git' command. This seems also an issue with my build environment, I'll check again on Ubuntu host (not Gentoo container!)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Docker and USB WiFi dongle (RTL8188FU) support for the odroid-xu4 board.
My build environment is a Gentoo Docker container, so I left out the commits that only work around issues specific to that particular build environment. That said, I haven't actually tested building this outside that container, so it'd be worth someone verifying it builds on a different machine too.
I feel somehow this is a fairly niche patch, it means it's only useful if someone actually want Docker on this board, so I'm not sure it's something that should be merged as-is.