feat(dogfood/coder): add brew and mise to ubuntu images#24618
Conversation
e66bc02 to
8d65209
Compare
aslilac
left a comment
There was a problem hiding this comment.
I'm technically off until monday, but I saw this and got excited.
homebrew needs a bit more than this, as we need to update the terraform to mount a volume at /home/linuxbrew/. the current volume only mounts at /home/coder/.
I also am not super sure what the behavior is when you create files in a directory in the container image and then mount a volume there. all of the mise stuff that you're adding is in /home/coder/, which is good because it will be persisted, but does it all get copied into the volume? does it do that but only if the volume is empty or something? basically, we need to do some testing to see how exactly docker is gonna handle all of this. I'll be happy to help next week when I'm back if you don't have it figured out by then.
d2c63c4 to
70903d7
Compare
70903d7 to
02b4327
Compare
aslilac
left a comment
There was a problem hiding this comment.
one (pair of?) nit(s), but I'm excited to test this out!
02b4327 to
163e1ef
Compare
This adds Homebrew and mise to the Ubuntu dogfood images and makes mise shims win
PATH resolution for the
coderuser. It installs Homebrew in/home/linuxbrew/.linuxbrew, installs the latest mise release (v2026.4.19) viaits verified GitHub release artifact, exposes mise at
/usr/local/bin/mise, wiresHOMEBREW_*andMISE_DATA_DIR, and adds build-time checks for both tools. Themise executable target lives in writable
/opt/mise/binsomise self-updatecan replace it as the
coderuser. This also addslibc6-devto the Go utilitystages so the existing CGO-backed tool installs keep building on newer Ubuntu
bases.
The dogfood template now mounts a dedicated
/home/linuxbrew/Docker volume inaddition to
/home/coder/. Fresh volumes are seeded from the image-bakedHomebrew tree on first mount, while user-installed formulae persist across
workspace container recreation.
I revalidated the bootstrap on jammy and resolute base images with fresh mounted
/home/coderand/home/linuxbrewvolumes. In those runs,brew install hellosucceeded,
mise doctorreported no PATH or activation problems,mise self-update --force --yes --no-plugins 2026.4.19succeeded ascoder, andmise use --global github:BurntSushi/ripgrep@14.1.1movedrgresolution tothe mise shim after container recreation.
📋 Implementation Plan
Plan: add
miseand Homebrew to the dogfood Ubuntu images with mise-first PATHGoal
brewandmise.mise doctordoes not complain about activation/PATH ordering in the shell entrypoints we support./home/codervolume used by the dogfood template.Verified context
dogfood/coder/ubuntu-22.04/Dockerfiledogfood/coder/ubuntu-26.04/Dockerfile/home/coder/indogfood/coder/main.tf:840-843, so required image-baked state should notlive only under
/home/coder.:26)ubuntu-26.04/Dockerfile:202-206; mirrored in 22.04)ubuntu-26.04/Dockerfile:245-255; mirrored in22.04)
coderPATH prepends/home/coder/go/bin(
ubuntu-26.04/Dockerfile:348-358; mirrored in 22.04)COPY files /is already present in both Dockerfiles, so adding new globalshell-init files is possible without Terraform changes.
scripts/lib.sh:94-124usescommand -vfor dependency detection, so PATHorder is the practical repo-level behavior we need to control.
.github/workflows/dogfood.yaml:99-126builds both Ubuntu variants, and the22.04 image is still tagged
latest, so both Dockerfiles must be updated inthe same change.
Recommended implementation
Phase 1 — Bootstrap Homebrew and
misein both Ubuntu Dockerfilesdogfood/coder/ubuntu-22.04/Dockerfiledogfood/coder/ubuntu-26.04/Dockerfilecurrent apt package set.
build-essential,curl,file, andgit.procpsmust be added explicitly for Homebrew’s Linuxrequirements.
/home/linuxbrew/.linuxbrewUSER coder.coderbefore switching users.Prefer the smallest-diff approach that leaves
brew install ...usable ascoder.miseto a stable image-owned path instead of relying on~/.local/bin:/usr/local/bin/mise(versioned release asset or otherwise explicitly pinned installer path).
fails early if assumptions are wrong:
test -x /usr/local/bin/misetest -x /home/linuxbrew/.linuxbrew/bin/brewbrew --versionmise --versionQuality gate: both Dockerfiles build locally, and the resulting container can
run
brew --versionandmise --versionascoder.Phase 2 — Make
misewin PATH resolution by defaultUSER coderin both Dockerfiles, define stable environment variablesfor the final shell/runtime behavior:
HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrewMISE_DATA_DIR=/home/coder/.local/share/miseMISE_ACTIVATE_AGGRESSIVE=1only if later shell activation provesnecessary
miseshimsbin/sbin/home/coder/go/binordering. Add a short Dockerfile comment explaining that
miseshims must befirst so
mise doctorandcommand -vresolvemise-managed tools ahead ofHomebrew/system binaries.
misestate under/home/coderfor theinitial implementation. The goal here is binary availability and path
precedence, not preinstalling shared
misetoolchains.Quality gate: in a fresh container as
coder,echo "$PATH"showsmiseshims before Homebrew, andmise doctor/mise doctor pathshow no PATHor activation problem in the tested shell entrypoints.
Phase 3 — Add shell-init hardening only if smoke tests prove it is needed
ENV PATHsolution as the default behavior.beyond the final
ENV PATH, add minimal global shell-init files under:dogfood/coder/ubuntu-22.04/files/etc/profile.d/dogfood/coder/ubuntu-26.04/files/etc/profile.d/brew shellenvmisefile that only reinforces the intended shims-first behavior/home/coder; they are the wrong placefor required image behavior because of the persistent home volume.
Quality gate: if profile.d files are added, login-shell smoke tests pass and
we do not introduce new PATH-order regressions versus the Dockerfile-only path.
Acceptance criteria
brewis installed in/home/linuxbrew/.linuxbrewand is usable ascoder.miseis installed at/usr/local/bin/miseand is usable ascoder.mise doctordoes not report an activation/PATH-ordering problem in theshell entrypoints we verify.
miseshimsbin/sbinchange.
.github/workflows/dogfood.yaml.Dogfooding and verification
dogfood/coder/ubuntu-22.04dogfood/coder/ubuntu-26.04/home/coderto mimicthe actual dogfood runtime constraint instead of only testing the image’s
baked filesystem.
brew --prefixbrew --versionmise --versionecho "$PATH"mise doctormise doctor pathtell whether Dockerfile
ENV PATHis sufficient or whether/etc/profile.dhardening is required.
misewins when configured:mise-managed runtime ascoderwhich -a <tool><tool> --versiongo versionnode --versionRisks and decision points
docker buildis notenough by itself; the prefix must end up writable for
coder.mise doctorby fixing PATHprecedence, not by introducing a larger
mise-managed tool bootstrap./etc/profile, a DockerfileENV PATHfix may be sufficient and profile.dmay be unnecessary. This should be decided by smoke tests, not by assumption.
only works if fresh volumes copy image-baked
/home/codercontents.Why this is the lowest-risk path
This plan keeps the initial implementation focused on the user’s stated goal:
install Homebrew and
mise, then guarantee thatmise-controlled paths win somise doctorstays quiet.The main repo-specific constraint is the persistent
/home/codervolume. Thatpushes required binaries and ownership-sensitive state out of
/home/coderwhere possible, and it argues against relying on user dotfiles for required
image behavior.
Starting with Dockerfile-level install steps plus a final PATH reorder keeps the
diff small, makes behavior consistent across shells, and gives us a clean place
to add shell-init hardening only if the smoke tests prove it is necessary.
Generated with
mux• Model:openai:gpt-5.5• Thinking:xhigh