This guide covers the deployment and management of the DDEV Coder template for administrators.
Before deploying this template, ensure the following are in place:
- Coder v2+ server installed and running
- Administrative access to Coder
- Coder CLI installed and authenticated (
coder login <url>)
Setting up a new server? See the Server Setup Guide for step-by-step installation of Docker, Sysbox, and Coder.
-
Sysbox runtime installed on all Coder agent nodes:
# Install prerequisites sudo apt-get install -y jq # Download Sysbox CE package (check https://github.com/nestybox/sysbox/releases for latest version) SYSBOX_VERSION=0.6.7 wget https://downloads.nestybox.com/sysbox/releases/v${SYSBOX_VERSION}/sysbox-ce_${SYSBOX_VERSION}-0.linux_amd64.deb # Install the package (note: sysbox-ce is not in standard apt repos) sudo apt-get install -y ./sysbox-ce_${SYSBOX_VERSION}-0.linux_amd64.deb # Verify installation sudo systemctl status sysbox -n20 sysbox-runc --version
Note: Docker must be installed (not via snap) before installing Sysbox. The installer will restart Docker. See Sysbox install docs for details.
-
Docker configured to use Sysbox runtime for appropriate containers
-
Sufficient storage for Docker volumes (each workspace uses dedicated
/var/lib/dockervolume)
- Access to push images (Docker Hub or private registry)
- Registry credentials configured if using private registry
- For Docker Hub:
docker login
- Docker installed locally for building images
- Coder CLI installed and configured
- Git for version management
- Make (
sudo apt-get install -y makeon Ubuntu, pre-installed on macOS)
The base image contains Ubuntu, Docker daemon, DDEV, Node.js, and essential development tools.
The Makefile automates all build and deployment tasks:
# Show available commands
make help
# Build image with cache
make build
# Build without cache (clean build)
make build-no-cache
# Push to registry
make push
# Build and push in one step
make build-and-push
# Test the built image
make test
# Show version info
make infoSee image/README.md for details on customizing the Docker image.
# Push template only
make push-template-user-defined-web
# Full deployment (build image + push image + push template)
make deploy-user-defined-web
# Full deployment without cache
make deploy-user-defined-web-no-cacheThe template is defined in user-defined-web/template.tf. Key configuration parameters:
variable "workspace_image_registry" {
default = "index.docker.io/ddev/coder-ddev"
}
variable "image_version" {
default = "v0.1" # Update this when releasing new image versions
}
variable "cpu" {
default = 4 # CPU cores per workspace
}
variable "memory" {
default = 8 # RAM in GB per workspace
}
variable "docker_gid" {
default = 988 # Docker group ID (must match host)
}To use a private registry:
- Update
workspace_image_registryintemplate.tf - Configure
registry_usernameandregistry_passwordvariables - Push template:
coder templates push --directory user-defined-web user-defined-web --yes
The VERSION file in the root directory controls the image tag. The Makefile automatically copies it into the template directory before pushing, and template.tf reads it from there — no manual edits to template.tf are needed.
# 1. Update VERSION file
echo "v0.7" > VERSION
# 2. Build, push image, and push template (VERSION is synced automatically)
make deploy-user-defined-web
# Or without cache for clean build
make deploy-user-defined-web-no-cacheVia Web UI:
- Log into Coder dashboard
- Click "Create Workspace"
- Select "user-defined-web" template
- Enter workspace name
- Configure parameters (optional: CPU, memory)
- Click "Create Workspace"
Via CLI:
# Create with defaults
coder create --template user-defined-web my-workspace --yes
# Create with custom parameters
coder create --template user-defined-web my-workspace \
--parameter cpu=8 \
--parameter memory=16 \
--yes# List all workspaces
coder list
# List workspaces for specific template
coder list --template user-defined-web
# Show detailed workspace info
coder show my-workspace# Stop workspace (saves state, stops billing)
coder stop my-workspace
# Start workspace
coder start my-workspace
# Restart workspace
coder restart my-workspaceWhen you push a new template version, existing workspaces don't automatically update.
To update a workspace to new template version:
# Update in place (preserves /home/coder)
coder update my-workspace
# Or from web UI: Click workspace → Update buttonNotes:
- Updates template configuration but NOT the Docker image
- To update Docker image, workspace must be rebuilt (delete and recreate)
- Updating preserves
/home/codervolume - DDEV containers may need to be restarted after update
# Delete workspace (warns if running)
coder delete my-workspace
# Force delete
coder delete my-workspace --yes
# Delete multiple workspaces
coder delete workspace1 workspace2 workspace3 --yesNote: Deleting a workspace removes:
- Workspace container
/home/codervolume (host directory)/var/lib/dockervolume (Docker daemon data)- All DDEV containers and volumes inside the workspace
# 1. Edit template.tf
vim user-defined-web/template.tf
# 2. Push updated template
make push-template-user-defined-web# 1. Edit image/Dockerfile (if needed)
# 2. Increment version (template reads this automatically)
echo "v0.7" > VERSION
# 3. Build and deploy
make deploy-user-defined-web
# Users must rebuild workspaces to get new Docker image# Revert to previous template version
git checkout <previous-commit> user-defined-web/template.tf
coder templates push --directory user-defined-web user-defined-web --yes
# Users on old version are unaffected
# Users can update to rollback version via: coder update <workspace>Each workspace stores persistent data in:
- Home directory:
/coder-workspaces/<owner>-<workspace>on host - Docker volume: Named volume
coder-<owner>-<workspace>-dind-cache
Backup strategy:
# Backup home directory
tar -czf workspace-backup.tar.gz /coder-workspaces/<owner>-<workspace>
# Backup Docker volume
docker run --rm \
-v coder-<owner>-<workspace>-dind-cache:/source \
-v $(pwd):/backup \
ubuntu:24.04 \
tar -czf /backup/docker-volume-backup.tar.gz -C /source .
# Restore Docker volume
docker volume create coder-<owner>-<workspace>-dind-cache
docker run --rm \
-v coder-<owner>-<workspace>-dind-cache:/target \
-v $(pwd):/backup \
ubuntu:24.04 \
tar -xzf /backup/docker-volume-backup.tar.gz -C /targetStore template versions in git:
# Tag releases
git tag -a v0.1 -m "Release v0.1"
git push origin v0.1
# Track changes
git log --oneline user-defined-web/template.tfCheck workspace health:
# View workspace logs
coder ssh my-workspace -- journalctl -u coder-agent -f
# Check Docker daemon inside workspace
coder ssh my-workspace -- docker ps
coder ssh my-workspace -- docker info
# Check DDEV status
coder ssh my-workspace -- ddev listResource usage:
# Check workspace container resources
docker stats coder-<workspace-id>
# Check disk usage
df -h /coder-workspaces/
docker system dfSee troubleshooting.md for detailed debugging procedures.
Quick checks:
# Template deployment failed
coder templates list # Check if template exists
terraform validate # Validate template syntax
# Workspace won't start
coder logs my-workspace # View startup logs
docker logs coder-<workspace-id> # View container logs
# Docker daemon issues
coder ssh my-workspace -- cat /tmp/dockerd.log
coder ssh my-workspace -- systemctl status dockerSysbox provides secure nested containers without privileged mode:
- No
--privilegedflag required - Isolated Docker daemon per workspace
- AppArmor and seccomp profiles configured
Security profiles in template.tf:
security_opt = ["apparmor:unconfined", "seccomp:unconfined"]These are required for Sysbox functionality and are safer than --privileged.
- Each workspace has isolated Docker daemon
- Workspaces cannot access other workspaces' Docker containers
- Users have sudo access inside their workspace only
- Store registry credentials in Coder secrets or environment variables
- Avoid hardcoding credentials in template.tf
- Use private registries for proprietary images
- DDEV uses Coder's port forwarding (not direct host binding)
- Ports are proxied through Coder server
- Configure firewall rules on Coder server, not individual workspaces
- Default: 4 CPU cores, 8GB RAM (suitable for most PHP/Node projects)
- Large projects: 8 cores, 16GB RAM
- Small projects: 2 cores, 4GB RAM
Monitor resource usage and adjust template defaults accordingly.
- Use clear, descriptive names:
user-defined-web,ddev-developer - Version templates for major changes:
user-defined-web-v2 - Avoid generic names:
template1,test
- Always tag images with specific versions and
latest - Test images before pushing to production registry
- Document changes in git commit messages
- Keep Dockerfile layer count reasonable (current: ~10 layers)
- Short-lived workspaces: Ideal for temporary work, prototyping
- Long-lived workspaces: Personal development environments
- Stop workspaces when not in use to save resources
- Keep
CLAUDE.mdupdated for AI-assisted development - Update user docs in
/docs/user/when template changes - Document breaking changes in git tags and release notes
- Server Setup Guide - Fresh server installation (Docker, Sysbox, Coder)
- User Management Guide - Managing users and permissions
- Troubleshooting Guide - Debugging workspace issues
- Coder Documentation - Official Coder docs
- Sysbox Documentation - Sysbox runtime details
- DDEV Documentation - DDEV usage and configuration