This adds Homebrew and mise to the Ubuntu dogfood images and makes mise shims win PATH resolution for the `coder` user. It installs Homebrew in `/home/linuxbrew/.linuxbrew`, installs the latest mise release (`v2026.4.19`) via its verified GitHub release artifact, exposes mise at `/usr/local/bin/mise`, wires `HOMEBREW_*` and `MISE_DATA_DIR`, and adds build-time checks for both tools. The mise executable target lives in writable `/opt/mise/bin` so `mise self-update` can replace it as the `coder` user. This also adds `libc6-dev` to the Go utility stages so the existing CGO-backed tool installs keep building on newer Ubuntu bases. The dogfood template now mounts a dedicated `/home/linuxbrew/` Docker volume in addition to `/home/coder/`. Fresh volumes are seeded from the image-baked Homebrew 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/coder` and `/home/linuxbrew` volumes. In those runs, `brew install hello` succeeded, `mise doctor` reported no PATH or activation problems, `mise self-update --force --yes --no-plugins 2026.4.19` succeeded as `coder`, and `mise use --global github:BurntSushi/ripgrep@14.1.1` moved `rg` resolution to the mise shim after container recreation. --- <details> <summary>📋 Implementation Plan</summary> # Plan: add `mise` and Homebrew to the dogfood Ubuntu images with mise-first PATH ## Goal - Make both dogfood Ubuntu images ship `brew` and `mise`. - Ensure `mise doctor` does **not** complain about activation/PATH ordering in the shell entrypoints we support. - Keep the implementation robust against the persistent `/home/coder` volume used by the dogfood template. ## Verified context - The relevant image definitions are: - `dogfood/coder/ubuntu-22.04/Dockerfile` - `dogfood/coder/ubuntu-26.04/Dockerfile` - The dogfood template mounts a persistent home volume at `/home/coder/` in `dogfood/coder/main.tf:840-843`, so required image-baked state should not live only under `/home/coder`. - Both Dockerfiles already manipulate PATH in multiple places: - Go appended early (`:26`) - Cargo prepended (`ubuntu-26.04/Dockerfile:202-206`; mirrored in 22.04) - Node via nvm prepended (`ubuntu-26.04/Dockerfile:245-255`; mirrored in 22.04) - Final `coder` PATH 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 global shell-init files is possible without Terraform changes. - `scripts/lib.sh:94-124` uses `command -v` for dependency detection, so PATH order is the practical repo-level behavior we need to control. - `.github/workflows/dogfood.yaml:99-126` builds both Ubuntu variants, and the 22.04 image is still tagged `latest`, so both Dockerfiles must be updated in the same change. ## Recommended implementation ### Phase 1 — Bootstrap Homebrew and `mise` in both Ubuntu Dockerfiles 1. Update both Dockerfiles in parallel: - `dogfood/coder/ubuntu-22.04/Dockerfile` - `dogfood/coder/ubuntu-26.04/Dockerfile` 2. Add the minimum explicit Homebrew prerequisites that are missing from the current apt package set. - The images already install `build-essential`, `curl`, `file`, and `git`. - Audit whether `procps` must be added explicitly for Homebrew’s Linux requirements. 3. Install Homebrew in the supported Linux prefix: - Prefix: `/home/linuxbrew/.linuxbrew` - Keep the install/build logic in the Dockerfile, before `USER coder`. - Make the resulting prefix writable by `coder` before switching users. Prefer the smallest-diff approach that leaves `brew install ...` usable as `coder`. 4. Install `mise` to a stable image-owned path instead of relying on `~/.local/bin`: - Preferred binary path: `/usr/local/bin/mise` - Use a pinned installation method that fits the current Dockerfile style (versioned release asset or otherwise explicitly pinned installer path). 5. Add defensive build-time sanity checks near the install steps so the image fails early if assumptions are wrong: - `test -x /usr/local/bin/mise` - `test -x /home/linuxbrew/.linuxbrew/bin/brew` - `brew --version` - `mise --version` **Quality gate:** both Dockerfiles build locally, and the resulting container can run `brew --version` and `mise --version` as `coder`. ### Phase 2 — Make `mise` win PATH resolution by default 1. After `USER coder` in both Dockerfiles, define stable environment variables for the final shell/runtime behavior: - `HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew` - `MISE_DATA_DIR=/home/coder/.local/share/mise` - `MISE_ACTIVATE_AGGRESSIVE=1` only if later shell activation proves necessary 2. Replace the final PATH composition so it resolves in this order: 1. `mise` shims 2. Homebrew `bin`/`sbin` 3. Existing `/home/coder/go/bin` 4. Existing image/system PATH 3. Keep the current Go/Rust/Node setup intact aside from the final PATH ordering. Add a short Dockerfile comment explaining that `mise` shims must be first so `mise doctor` and `command -v` resolve `mise`-managed tools ahead of Homebrew/system binaries. 4. Do **not** rely on image-baked `mise` state under `/home/coder` for the initial implementation. The goal here is binary availability and path precedence, not preinstalling shared `mise` toolchains. **Quality gate:** in a fresh container as `coder`, `echo "$PATH"` shows `mise` shims before Homebrew, and `mise doctor`/`mise doctor path` show no PATH or activation problem in the tested shell entrypoints. ### Phase 3 — Add shell-init hardening only if smoke tests prove it is needed 1. Start with the Dockerfile `ENV PATH` solution as the default behavior. 2. If dogfooding shows that supported login shells still need shell integration 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/` 3. If these files are needed, keep them narrowly scoped: - a Homebrew file that exports/evals `brew shellenv` - a `mise` file that only reinforces the intended shims-first behavior 4. Avoid touching per-user dotfiles in `/home/coder`; they are the wrong place for 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 - Both Ubuntu dogfood Dockerfiles are updated in one change and still build. - `brew` is installed in `/home/linuxbrew/.linuxbrew` and is usable as `coder`. - `mise` is installed at `/usr/local/bin/mise` and is usable as `coder`. - `mise doctor` does not report an activation/PATH-ordering problem in the shell entrypoints we verify. - Final PATH precedence is: 1. `mise` shims 2. Homebrew `bin`/`sbin` 3. existing user/tool paths 4. system paths - Existing dogfood workflows still work for Go/Rust/Node tooling after the PATH change. - The change passes the dogfood image CI path in `.github/workflows/dogfood.yaml`. ## Dogfooding and verification 1. Build both images locally: - `dogfood/coder/ubuntu-22.04` - `dogfood/coder/ubuntu-26.04` 2. Run each image with an empty mounted home volume at `/home/coder` to mimic the actual dogfood runtime constraint instead of only testing the image’s baked filesystem. 3. Capture a short terminal recording and screenshots for each variant showing: - `brew --prefix` - `brew --version` - `mise --version` - `echo "$PATH"` - `mise doctor` - `mise doctor path` 4. Verify at least one login-shell path and one non-login-shell path, so we can tell whether Dockerfile `ENV PATH` is sufficient or whether `/etc/profile.d` hardening is required. 5. Add one tool-resolution smoke test that proves `mise` wins when configured: - install/use a small `mise`-managed runtime as `coder` - run `which -a <tool>` - run `<tool> --version` 6. Verify existing image behavior did not regress: - `go version` - `node --version` - any other must-have image tools that were already on PATH 7. Preserve the artifacts from dogfooding for review: - screenshots attached to the change summary - a short screen recording (or terminal recording) covering the smoke test ## Risks and decision points - **Homebrew ownership model:** installing Homebrew during `docker build` is not enough by itself; the prefix must end up writable for `coder`. - **Scope control:** the initial change should solve `mise doctor` by fixing PATH precedence, not by introducing a larger `mise`-managed tool bootstrap. - **Shell-init uncertainty:** if the dogfood terminal entrypoints do not source `/etc/profile`, a Dockerfile `ENV PATH` fix may be sufficient and profile.d may be unnecessary. This should be decided by smoke tests, not by assumption. - **Persistent home behavior:** avoid any required implementation detail that only works if fresh volumes copy image-baked `/home/coder` contents. <details> <summary>Why this is the lowest-risk path</summary> This plan keeps the initial implementation focused on the user’s stated goal: install Homebrew and `mise`, then guarantee that `mise`-controlled paths win so `mise doctor` stays quiet. The main repo-specific constraint is the persistent `/home/coder` volume. That pushes required binaries and ownership-sensitive state out of `/home/coder` where 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. </details> </details> --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `openai:gpt-5.5` • Thinking: `xhigh`_
Coder is a self-hosted platform for cloud development environments and AI coding agents. Workspaces are defined with Terraform, connected through a secure Wireguard® tunnel, and automatically shut down when not used. Coder Agents runs a native AI coding agent whose loop executes in the control plane on your infrastructure, with no API keys in workspaces.
- Define cloud development environments in Terraform
- EC2 VMs, Kubernetes Pods, Docker Containers, etc.
- Automatically shutdown idle resources to save on costs
- Onboard developers in seconds instead of days
- Delegate coding work to AI agents on your infrastructure
- Bring any model (Anthropic, OpenAI, Google, Bedrock, self-hosted)
- No LLM credentials in workspaces, user identity on every action
- Centralized model governance, cost tracking, and audit logging
Quickstart
The most convenient way to try Coder is to install it on your local machine and experiment with provisioning cloud development environments using Docker (works on Linux, macOS, and Windows).
# First, install Coder
curl -L https://coder.com/install.sh | sh
# Start the Coder server (caches data in ~/.cache/coder)
coder server
# Navigate to http://localhost:3000 to create your initial user,
# create a Docker template and provision a workspace
Install
The easiest way to install Coder is to use the
install script for Linux
and macOS. For Windows, use the latest ..._installer.exe file from GitHub
Releases.
curl -L https://coder.com/install.sh | sh
You can run the install script with --dry-run to see the commands that will be used to install without executing them. Run the install script with --help for additional flags.
See install for additional methods.
Once installed, you can start a production deployment with a single command:
# Automatically sets up an external access URL on *.try.coder.app
coder server
# Requires a PostgreSQL instance (version 13 or higher) and external access URL
coder server --postgres-url <url> --access-url <url>
Use coder --help to get a list of flags and environment variables. See the install guides for a complete tutorial.
Documentation
Browse the documentation or visit a specific section below:
- Workspaces: Workspaces contain the IDEs, dependencies, and configuration information needed for software development
- Templates: Templates are written in Terraform and describe the infrastructure for workspaces
- Coder Agents: Delegate coding work to AI agents running on your self-hosted infrastructure
- Administration: Learn how to operate Coder
- Premium: Learn about paid features built for large teams
- IDEs: Connect your existing editor to a workspace
Support
Feel free to open an issue if you have questions, run into bugs, or have a feature request.
Join our Discord to provide feedback on in-progress features and chat with the community using Coder!
Integrations
New integrations are always in progress. Open an issue to request one. Contributions are welcome in any official or community repository.
Official
- Coder Registry: Templates, modules, and integrations for common development environments
- VS Code Extension: Open any Coder workspace in VS Code with a single click
- JetBrains Toolbox Plugin: Open any Coder workspace from JetBrains Toolbox with a single click
- JetBrains Gateway Plugin: Open any Coder workspace in JetBrains Gateway with a single click
- Dev Containers: Build development environments using
devcontainer.jsonon Docker, Kubernetes, and OpenShift - Kubernetes Log Stream: Stream Kubernetes Pod events to the Coder startup logs
- Self-Hosted VS Code Extension Marketplace: A private extension marketplace that works in restricted or airgapped networks integrating with code-server.
- GitHub Actions: An action to set up the Coder CLI in GitHub workflows
Community
- Community Templates: Community-contributed workspace templates in the Coder Registry
- Community Modules: Community-contributed modules to extend Coder templates
- Provision Coder with Terraform: Provision Coder on Google GKE, Azure AKS, AWS EKS, DigitalOcean DOKS, IBMCloud K8s, OVHCloud K8s, and Scaleway K8s Kapsule with Terraform
- Coder Template GitHub Action: A GitHub Action that updates Coder templates
- Discord: Chat with the community and provide feedback on in-progress features
Contributing
New contributors are always welcome. If you are new to the Coder codebase, see the contribution guide to get started.
Hiring
Apply on the careers page if you are interested in joining the team.
