Summary
The workspace configurator should allow users to select common development tools that get pre-installed in the workspace template. This improves the developer experience and ensures reproducible environments.
Motivation
Currently, tools like docker, docker-compose, node, python, etc. are either missing or require manual installation after workspace creation. In containerized Coder workspaces, Docker-in-Docker also requires specific Linux capabilities (CAP_SYS_ADMIN) that must be configured at the template level — something end users cannot do themselves.
Root Cause Analysis (investigated & resolved)
Three separate issues were identified and fixed during investigation:
1. Missing CAP_SYS_ADMIN — Docker daemon cannot start
Even running dockerd as root inside the workspace fails with:
unshare: operation not permitted
failed to register layer: unshare: operation not permitted
because the container bounding set does not include CAP_SYS_ADMIN or CAP_NET_ADMIN.
What does NOT work (all tested):
--storage-driver=vfs → still fails with unshare: operation not permitted
--iptables=false --bridge=none → daemon starts but image layer extraction fails
--seccomp-profile=unconfined → no effect, blocked at kernel capability level
- Running
dockerd as root via sudo → same result; sudo cannot grant capabilities outside the bounding set
Fix: privileged: true on the workspace container in main.tf.
2. Missing start-dockerd script
The new Dockerfile installs a /usr/local/bin/start-dockerd helper script. Existing workspaces (built before the template update) don't have this script — the startup_script in main.tf calls it and fails with:
sudo: start-dockerd: command not found
Fix: After a workspace template update that changes the Dockerfile, existing workspaces need to be stopped and restarted to pull the new image. The script can also be created manually as a workaround.
3. MongoDB bind-mount permission denied
MongoDB in docker-compose.dev.yml is configured with user: "10001:1003" and a bind mount ./data/mongo:/data/db. If the host directory doesn't exist or is owned by root, MongoDB fails on startup:
Error creating journal directory: Permission denied [system:13]: "/data/db/journal"
Fix: The ./data/mongo directory must be created and owned by 10001:1003 before starting the stack:
mkdir -p ./data/mongo
sudo chown -R 10001:1003 ./data/mongo
This should be automated in a setup script or documented in the project README.
Fix Already Applied to remotevibe Template
The following changes have already been made to /workspace/template/ and pushed via coder templates push:
main.tf changes
privileged = true on the workspace container — grants CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_MKNOD
- New persistent Docker data volume:
docker_data_volume → /var/lib/docker — pulled images survive workspace restarts
startup_script automatically calls sudo start-dockerd on every workspace start
Dockerfile changes
- Full Docker engine installed:
docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin, docker-compose-plugin
- Standalone
docker-compose v2 binary at /usr/local/bin/docker-compose (supports legacy docker-compose invocation)
coder user added to docker group
/usr/local/bin/start-dockerd helper script:
- Tries full networking first (bridge + iptables)
- Falls back to
--bridge=none --iptables=false if network capabilities are missing
- Sets
/var/run/docker.sock permissions so coder user can use Docker without sudo
Proposed Configurator Feature
Add a "Development Tools" section to the workspace configurator UI. For each selected tool, the generated template should automatically apply the required configuration:
| Tool |
Installed |
Template Change |
| Docker + docker-compose |
docker-ce, docker-compose binary |
privileged: true, /var/lib/docker volume, start-dockerd in startup |
| Node.js / pnpm / npm |
via NodeSource |
— |
| Python + pip |
system packages |
— |
| Go |
binary from go.dev |
PATH export |
| Rust |
via rustup |
PATH export |
| kubectl / Helm |
binaries |
— |
| AWS/Azure/gcloud CLI |
package installs |
— |
Acceptance Criteria
Summary
The workspace configurator should allow users to select common development tools that get pre-installed in the workspace template. This improves the developer experience and ensures reproducible environments.
Motivation
Currently, tools like
docker,docker-compose,node,python, etc. are either missing or require manual installation after workspace creation. In containerized Coder workspaces, Docker-in-Docker also requires specific Linux capabilities (CAP_SYS_ADMIN) that must be configured at the template level — something end users cannot do themselves.Root Cause Analysis (investigated & resolved)
Three separate issues were identified and fixed during investigation:
1. Missing
CAP_SYS_ADMIN— Docker daemon cannot startEven running
dockerdas root inside the workspace fails with:because the container bounding set does not include
CAP_SYS_ADMINorCAP_NET_ADMIN.What does NOT work (all tested):
--storage-driver=vfs→ still fails withunshare: operation not permitted--iptables=false --bridge=none→ daemon starts but image layer extraction fails--seccomp-profile=unconfined→ no effect, blocked at kernel capability leveldockerdas root viasudo→ same result; sudo cannot grant capabilities outside the bounding setFix:
privileged: trueon the workspace container inmain.tf.2. Missing
start-dockerdscriptThe new Dockerfile installs a
/usr/local/bin/start-dockerdhelper script. Existing workspaces (built before the template update) don't have this script — thestartup_scriptinmain.tfcalls it and fails with:Fix: After a workspace template update that changes the Dockerfile, existing workspaces need to be stopped and restarted to pull the new image. The script can also be created manually as a workaround.
3. MongoDB bind-mount permission denied
MongoDB in
docker-compose.dev.ymlis configured withuser: "10001:1003"and a bind mount./data/mongo:/data/db. If the host directory doesn't exist or is owned by root, MongoDB fails on startup:Fix: The
./data/mongodirectory must be created and owned by10001:1003before starting the stack:This should be automated in a setup script or documented in the project README.
Fix Already Applied to
remotevibeTemplateThe following changes have already been made to
/workspace/template/and pushed viacoder templates push:main.tfchangesprivileged = trueon the workspace container — grantsCAP_SYS_ADMIN,CAP_NET_ADMIN,CAP_MKNODdocker_data_volume→/var/lib/docker— pulled images survive workspace restartsstartup_scriptautomatically callssudo start-dockerdon every workspace startDockerfilechangesdocker-ce,docker-ce-cli,containerd.io,docker-buildx-plugin,docker-compose-plugindocker-composev2 binary at/usr/local/bin/docker-compose(supports legacydocker-composeinvocation)coderuser added todockergroup/usr/local/bin/start-dockerdhelper script:--bridge=none --iptables=falseif network capabilities are missing/var/run/docker.sockpermissions socoderuser can use Docker withoutsudoProposed Configurator Feature
Add a "Development Tools" section to the workspace configurator UI. For each selected tool, the generated template should automatically apply the required configuration:
docker-ce,docker-composebinaryprivileged: true,/var/lib/dockervolume,start-dockerdin startupAcceptance Criteria
privileged: truein the generated template/var/lib/dockeras a persistent named volumedockerdstarts automatically at workspace startup when Docker is selecteddocker-compose(standalone binary) is pre-installed and callable directlystartup_scriptautomatically creates and chowns bind-mount directories (e.g../data/mongo) required by project-level docker-compose files