Skip to content

Latest commit

 

History

History
1032 lines (780 loc) · 22.2 KB

File metadata and controls

1032 lines (780 loc) · 22.2 KB

Using DDEV Coder Workspaces

This guide covers daily workflows, tips, and best practices for working with DDEV in Coder workspaces.

Table of Contents

Workspace Lifecycle

Understanding Persistence

Your workspace has two types of storage:

Persistent (survives stop/restart):

  • /home/coder directory (all your files)
  • Docker volumes (DDEV databases, images, containers)

Non-persistent (reset on restart):

  • Running processes
  • Temporary files in /tmp
  • System packages installed with apt-get (unless in Docker image)

What this means:

  • Your code, databases, and DDEV projects are safe when stopping workspace
  • You need to restart DDEV projects after workspace restart
  • System-level changes (installed packages) are lost unless in Docker image

Starting Your Day

# 1. Start workspace (if stopped)
coder start my-workspace

# 2. SSH into workspace (or open VS Code)
coder ssh my-workspace

# 3. Navigate to project
cd ~/projects/my-site

# 4. Start DDEV
ddev start

# 5. Start developing!

Ending Your Day

# 1. Commit your changes
git add .
git commit -m "End of day commit"
git push

# 2. Stop DDEV projects (optional, saves a few seconds on next start)
ddev stop

# 3. Exit workspace
exit

# 4. Stop workspace (saves costs)
coder stop my-workspace

Note: Stopping workspace is optional. Some teams leave workspaces running 24/7.

Workspace States

State Description Billing Data Preserved
Running Active, can SSH and access Yes Yes
Stopped Powered off, cannot access No Yes
Starting Booting up, wait a moment No Yes
Deleting Being deleted No No

Managing Multiple Workspaces

# List all your workspaces
coder list

# Create second workspace
coder create --template user-defined-web my-second-workspace --yes

# Switch between workspaces
coder ssh my-first-workspace
coder ssh my-second-workspace

# Stop all workspaces
coder stop my-first-workspace my-second-workspace

Use cases for multiple workspaces:

  • Different projects with different requirements
  • Testing configurations without affecting main workspace
  • Separate staging and development environments
  • Different resource configurations (small vs large projects)

VS Code for Web

Accessing VS Code

From Coder dashboard:

  1. Find your workspace
  2. Click VS Code under "Apps"
  3. VS Code opens in new tab

Direct URL (bookmark this):

https://coder.example.com/@me/my-workspace/apps/code

Pre-installed Extensions

All workspaces come with these extensions automatically installed at workspace start:

Extension Purpose
PHP Debug (xdebug.php-debug) Xdebug step debugging
PHP Intelephense (bmewburn.vscode-intelephense-client) PHP IntelliSense, go-to-definition, autocomplete
ESLint (dbaeumer.vscode-eslint) JavaScript/TypeScript linting
Prettier (esbenp.prettier-vscode) Code formatting
PHPStan (sanderronde.phpstan-vscode) PHP static analysis
Code Spell Checker (streetsidesoftware.code-spell-checker) Spell checking in code and comments
Stylelint (stylelint.vscode-stylelint) CSS/SCSS linting
PHP Sniffer & Beautifier (valeryanm.vscode-phpsab) PHPCS/PHPCBF integration
DDEV Manager (biati.ddev-manager) DDEV control panel: start/stop/Xdebug toggle/etc.

Installing Additional Extensions

Extensions are installed from the Open VSX Registry — the open-source alternative to the Microsoft Marketplace used by VS Code Server and other non-Microsoft VS Code deployments.

To install an extension manually:

  1. Open Extensions panel (Ctrl+Shift+X)
  2. Search for the extension by name
  3. Click Install

Important: Not all extensions on the Microsoft Marketplace are available on Open VSX. Authors must publish to both registries independently. Some notable extensions that are only on the Microsoft Marketplace (and therefore unavailable here) include Pylance and GitHub Copilot.

If an extension you need is missing, check if it exists on open-vsx.org first. If the author hasn't published there, you can request it via the extension's issue tracker.

Adding Extensions to All Workspaces

Admins can pre-install additional extensions for all users by adding extension IDs to the extensions list in the template's vscode-web module. See the server setup guide for details.

Future IDE Possibilities

The current setup uses VS Code for Web (browser-based VS Code Server). Other IDE options are possible:

  • VS Code Desktop — Connect your locally-installed VS Code to the workspace via the Coder CLI (coder ssh). Requires the Coder CLI on your machine.
  • JetBrains IDEs (PhpStorm, GoLand, WebStorm, etc.) — Connect via JetBrains Gateway with the Coder plugin. Full native IDE with remote execution. Currently supported by the Coder platform but not configured in these templates by default.
  • Neovim / terminal editors — Available in any SSH session via coder ssh.

Terminal in VS Code

Open terminal:

  • Menu: Terminal → New Terminal
  • Keyboard: Ctrl+` (backtick)

Multiple terminals:

  • Click + to add terminal
  • Split terminal with split button
  • Switch between terminals with dropdown

Terminal tips:

# Terminal opens in /home/coder by default
# Navigate to project
cd ~/projects/my-site

# Run DDEV commands
ddev start
ddev describe

# Run composer/npm through DDEV
ddev composer install
ddev npm run dev

File Management

Opening projects:

  1. File → Open Folder
  2. Navigate to ~/projects/my-site
  3. Click OK

Drag and drop:

  • Drag files from your computer into VS Code to upload
  • Works for single files and folders (up to reasonable size)

File search:

  • Ctrl+P (Cmd+P): Quick file open
  • Ctrl+Shift+F (Cmd+Shift+F): Search in files
  • Ctrl+Shift+E (Cmd+Shift+E): File explorer

Git Integration

Built-in Git features:

  • Source Control panel (Ctrl+Shift+G)
  • Stage changes (click + next to file)
  • Commit (type message, click ✓)
  • Push/pull (click ... menu)
  • View diff (click modified file)

GitLens extension features:

  • Blame annotations (who changed each line)
  • Commit history
  • Repository explorer
  • Compare branches

Debugging

VS Code supports debugging for most languages:

PHP (with Xdebug via DDEV):

The DDEV Manager extension provides a UI panel for toggling Xdebug. Alternatively, use the terminal:

ddev xdebug on   # Enable Xdebug
ddev xdebug off  # Disable when done (improves performance)

Then in VS Code:

  1. Add a breakpoint (click left of line number — should appear solid red)
  2. Press F5 → select "Listen for Xdebug"
  3. Refresh your browser to trigger the breakpoint
  4. The bottom bar turns orange when the debug session is active

Node.js:

// .vscode/launch.json
{
  "type": "node",
  "request": "launch",
  "name": "Launch Program",
  "program": "${workspaceFolder}/server.js"
}

Press F5 to start debugging.

Extensions for DDEV Projects

Beyond the pre-installed set, these are useful additions for specific project types (search Open VSX by name):

Drupal:

  • Drupal Smart Snippets

WordPress:

  • WordPress Snippets

Laravel:

  • Laravel Blade Snippets

Node.js:

  • npm Intellisense
  • ES7+ React/Redux/React-Native snippets

Keyboard Shortcuts

Action macOS Windows/Linux
Command palette Cmd+Shift+P Ctrl+Shift+P
Quick open file Cmd+P Ctrl+P
Terminal Cmd+` Ctrl+`
Find in files Cmd+Shift+F Ctrl+Shift+F
Save Cmd+S Ctrl+S
Format document Shift+Alt+F Shift+Alt+F
Go to definition F12 F12
Find references Shift+F12 Shift+F12

DDEV Workflows

Project Types

DDEV supports 20+ project types. Common examples:

WordPress:

mkdir ~/projects/my-wordpress
cd ~/projects/my-wordpress
ddev config --project-type=wordpress --docroot=web
ddev start
ddev composer create roots/bedrock

Drupal:

mkdir ~/projects/my-drupal
cd ~/projects/my-drupal
ddev config --project-type=drupal --docroot=web
ddev composer create drupal/recommended-project
ddev drush site:install --account-name=admin --account-pass=admin -y

Laravel:

mkdir ~/projects/my-laravel
cd ~/projects/my-laravel
ddev config --project-type=laravel --docroot=public
ddev composer create laravel/laravel
ddev exec php artisan key:generate

Generic PHP:

mkdir ~/projects/my-php-site
cd ~/projects/my-php-site
ddev config --project-type=php --docroot=web
mkdir web
echo "<?php phpinfo();" > web/index.php
ddev start

Node.js:

mkdir ~/projects/my-node-app
cd ~/projects/my-node-app
ddev config --project-type=php --docroot=.
npm init -y
npm install express
# Create server.js
ddev start
ddev exec node server.js

Database Management

Import database:

# From SQL file
ddev import-db --file=dump.sql

# From compressed file
ddev import-db --file=dump.sql.gz

# From URL
ddev import-db --url=https://example.com/dump.sql.gz

Export database:

# Export to file
ddev export-db --file=dump.sql.gz

# Export to stdout (for piping)
ddev export-db > dump.sql

Direct MySQL access:

# MySQL CLI
ddev mysql

# Run SQL file
ddev mysql < query.sql

# One-line query
ddev mysql -e "SELECT * FROM users LIMIT 10;"

Database GUI (via browser):

# phpMyAdmin (if configured in .ddev/config.yaml)
ddev launch -p

# Or use MySQL Workbench/TablePlus via SSH tunnel:
coder port-forward my-workspace --tcp 3306:3306
# Connect to localhost:3306 from your machine

Running Commands

Execute commands in web container:

# Generic command
ddev exec <command>

# Examples
ddev exec pwd
ddev exec ls -la
ddev exec which php

# Run as root
ddev exec sudo <command>

SSH into web container:

ddev ssh

# You're now inside the web container
# Run any command
composer install
npm run build
exit

Composer commands:

ddev composer install
ddev composer require vendor/package
ddev composer update
ddev composer dump-autoload

npm/yarn commands:

ddev npm install
ddev npm run dev
ddev npm run build
ddev yarn install
ddev yarn build

Custom Commands

Create custom DDEV commands:

# Create .ddev/commands/web/ directory
mkdir -p .ddev/commands/web

# Create custom command
cat > .ddev/commands/web/mycommand <<'EOF'
#!/bin/bash
## Description: My custom command
## Usage: mycommand [args]
echo "Running my custom command"
# Your commands here
EOF

chmod +x .ddev/commands/web/mycommand

# Use it
ddev mycommand

Multiple Projects

Running multiple DDEV projects:

# Start all projects
cd ~/projects/project1 && ddev start
cd ~/projects/project2 && ddev start
cd ~/projects/project3 && ddev start

# List running projects
ddev list

# Stop specific project
cd ~/projects/project1
ddev stop

# Stop all projects
ddev stop --all

# Power off all (removes containers)
ddev poweroff

Port conflicts: If you run multiple projects simultaneously, they'll use different ports automatically. Check with:

ddev describe
# Shows URLs and ports for each project

Git Workflows

Initial Configuration

# Set your identity (one-time setup)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

# Set default branch name
git config --global init.defaultBranch main

# Useful aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit

SSH Keys

Your SSH key is managed by Coder and automatically available in workspaces.

Get your Coder public key:

# Inside workspace
coder publickey

# Copy the output (starts with ssh-ed25519 or ssh-rsa)

Add key to your Git host:

  1. GitHub: https://github.com/settings/keys → New SSH key
  2. GitLab: https://gitlab.com/-/profile/keys → Add key
  3. Bitbucket: https://bitbucket.org/account/settings/ssh-keys/ → Add key

Test SSH:

# Test GitHub
ssh -T git@github.com
# Should say: "Hi username! You've successfully authenticated..."

# Test GitLab
ssh -T git@gitlab.com
# Should say: "Welcome to GitLab, @username!"

How it works: Coder's GitSSH wrapper uses your Coder-managed SSH key automatically. No need to manage keys inside the workspace.

Common Workflows

Clone and start working:

cd ~/projects
git clone git@github.com:username/repo.git
cd repo
ddev config --auto  # If .ddev/config.yaml exists
ddev start

Daily workflow:

# Pull latest changes
git pull

# Create feature branch
git checkout -b feature/my-feature

# Make changes
# ... edit files ...

# Check status
git status

# Stage changes
git add .

# Commit
git commit -m "Add my feature"

# Push
git push origin feature/my-feature

Stash changes:

# Stash uncommitted changes
git stash

# Pull latest
git pull

# Restore stashed changes
git stash pop

Merge conflicts:

# If pull creates conflicts
git pull
# Auto-merging file.php
# CONFLICT (content): Merge conflict in file.php

# Resolve in VS Code (shows conflict markers)
# Edit file, remove <<<<<<, ======, >>>>>>

# Stage resolved files
git add file.php

# Complete merge
git commit

Pre-commit Hooks

# Install pre-commit hooks (if project uses them)
cd ~/projects/my-site

# If using PHP CodeSniffer
ddev composer require --dev phpcodesniffer

# If using ESLint
ddev npm install --save-dev eslint

# Hooks run automatically on git commit
git commit -m "Test commit"
# Runs linters, formatters, etc.

Port Forwarding

How Port Forwarding Works

In Coder, you don't access services via direct URLs. Instead:

  1. Service listens on port inside workspace (e.g., DDEV on port 80)
  2. Coder proxies port through its server
  3. You access via Coder's secure URL

Traditional DDEV:

https://my-site.ddev.site  ← Doesn't work in Coder

Coder DDEV:

https://ddev-web--workspace-name--owner.coder.example.com/  ← Use DDEV Web app URL

Accessing DDEV Projects

Via Coder UI (Recommended):

  1. Go to workspace in Coder dashboard
  2. Under Apps, click DDEV Web
  3. Your DDEV project loads in a new tab

The URL follows the pattern: https://ddev-web--workspace-name--owner.domain/

Common DDEV ports:

  • 80: HTTP web server
  • 443: HTTPS web server
  • 8025: Mailpit web UI (email testing)
  • 3306: MySQL (for external DB tools)

Port Forwarding via CLI

# Forward port to local machine
coder port-forward my-workspace --tcp 80:80

# Now access via:
# http://localhost:80

# Forward MySQL for database tools
coder port-forward my-workspace --tcp 3306:3306

# Connect MySQL Workbench or TablePlus to:
# Host: localhost, Port: 3306

Custom Services

If you run custom services, add port forwarding in template.tf (ask admin) or use CLI:

# Forward custom port (e.g., Node.js on 3000)
coder port-forward my-workspace --tcp 3000:3000

# Access via:
# http://localhost:3000

Common Tasks

Importing Existing Projects

From Git repository:

cd ~/projects
git clone git@github.com:username/existing-project.git
cd existing-project
ddev config --auto  # Auto-detect project type
ddev start
ddev composer install  # Or npm install
ddev import-db --file=backup.sql.gz

From local machine:

# Option 1: Via VS Code drag-and-drop
# Open VS Code, drag project folder into file explorer

# Option 2: Via SCP
coder scp ./local-project my-workspace:~/projects/

# Then in workspace:
cd ~/projects/local-project
ddev config --auto
ddev start

Database Snapshots

# Create snapshot (backup current state)
ddev snapshot

# Restore snapshot (revert to last snapshot)
ddev snapshot restore

# List snapshots
ddev snapshot --list

# Delete snapshots
ddev snapshot --cleanup

Use case: Before risky database changes:

ddev snapshot
# Try risky migration
ddev exec drush updatedb
# If fails, restore:
ddev snapshot restore

File Sync and Backup

Download files from workspace:

# Via SCP
coder scp my-workspace:~/projects/my-site ./local-backup/

# Via VS Code
# Right-click file/folder → Download

Upload files to workspace:

# Via SCP
coder scp ./local-files my-workspace:~/projects/my-site/

# Via VS Code drag-and-drop

Backup entire project:

# Inside workspace
cd ~/projects
tar -czf my-site-backup.tar.gz my-site/

# Download
exit
coder scp my-workspace:~/projects/my-site-backup.tar.gz ./

Package Management

Composer (PHP):

ddev composer install          # Install dependencies
ddev composer require pkg/name # Add package
ddev composer update           # Update packages
ddev composer dump-autoload    # Rebuild autoloader

npm (Node.js):

ddev npm install           # Install dependencies
ddev npm install package   # Add package
ddev npm update            # Update packages
ddev npm run <script>      # Run package.json script

System packages (not persistent):

# Install system tool (temporary)
sudo apt-get update
sudo apt-get install <package>

# For permanent install, ask admin to add to Docker image

Logs and Debugging

DDEV logs:

# All containers
ddev logs

# Specific container
ddev logs web
ddev logs db

# Follow logs (like tail -f)
ddev logs -f

Docker logs:

# List containers
docker ps

# View logs
docker logs <container-id>

# Follow logs
docker logs -f <container-id>

System logs:

# Coder agent logs
journalctl -u coder-agent -f

# Docker daemon logs
journalctl -u docker -f

# Docker daemon logs (written by startup script)
cat /tmp/dockerd.log

Debug DDEV:

# Verbose output
ddev start --debug

# Show DDEV config
ddev describe

# Show Docker info
docker info

# Show DDEV version
ddev version

Tips and Tricks

Aliases and Shortcuts

Add to ~/.bashrc:

# DDEV aliases
alias dl='ddev list'
alias ds='ddev start'
alias dx='ddev stop'
alias dr='ddev restart'
alias de='ddev exec'

# Git aliases
alias gs='git status'
alias gp='git pull'
alias gc='git commit'
alias gco='git checkout'

# Navigation
alias projects='cd ~/projects'
alias ll='ls -la'

# Reload bashrc
source ~/.bashrc

VS Code Workspace Settings

Per-project settings (.vscode/settings.json):

{
  "php.validate.executablePath": "/usr/bin/php",
  "phpcs.executablePath": "/usr/bin/phpcs",
  "eslint.workingDirectories": ["web/themes/custom"],
  "files.exclude": {
    "**/vendor": true,
    "**/node_modules": true
  }
}

Commit this file to Git for team consistency.

Performance Shortcuts

Skip DDEV router (for simple projects):

# .ddev/config.yaml
router_disabled: true

# Access via port forwarding instead of ddev URLs

Disable unnecessary services:

# .ddev/config.yaml
omit_containers: ["ddev-ssh-agent"]

Use shallow Git clones:

git clone --depth 1 git@github.com:user/repo.git

Multi-tab Workflows

Typical setup:

  1. Tab 1: VS Code (editing)
  2. Tab 2: Coder dashboard (port forwarding)
  3. Tab 3: DDEV project (browser)
  4. Tab 4: Mailpit (email testing)

Use browser bookmarks for quick access.

Keyboard-driven Development

Fast workflow:

# Terminal-only workflow (no clicking)
coder ssh my-workspace
cd ~/projects/my-site
ddev start
ddev logs -f &  # Background logs
vim web/index.php
git add . && git commit -m "Update" && git push
ddev describe  # Get ports, open in browser

Performance Optimization

Workspace Resources

Check current resources:

# CPU cores
nproc

# RAM
free -h

# Disk
df -h

If workspace is slow, increase resources:

# Stop workspace
coder stop my-workspace

# Delete and recreate with more resources
coder delete my-workspace --yes
coder create --template user-defined-web my-workspace \
  --parameter cpu=8 \
  --parameter memory=16 \
  --yes

# Restore from Git
cd ~/projects
git clone git@github.com:user/repo.git

DDEV Performance

Disable Xdebug (when not debugging):

ddev xdebug off

Use NFS (if file operations are slow):

# .ddev/config.yaml
nfs_mount_enabled: true

Reduce container memory:

# .ddev/config.yaml
resources:
  limits:
    memory: 2g

Docker Cleanup

# Remove unused images/containers
docker system prune -a -f

# Remove all volumes (careful!)
docker volume prune -f

# Check disk usage
docker system df

Git Performance

Shallow clones (for large repos):

git clone --depth 1 --single-branch git@github.com:user/repo.git

Sparse checkout (for monorepos):

git clone --filter=blob:none --sparse git@github.com:user/repo.git
cd repo
git sparse-checkout set path/to/needed/directory

Getting Help

Documentation

Community

Quick Troubleshooting

Problem Quick Fix
Docker not working sudo systemctl restart docker
DDEV won't start ddev poweroff && ddev start
Out of disk space docker system prune -a -f
Workspace slow Stop unused DDEV projects: ddev stop --all
Git SSH failing Re-add SSH key to Coder and Git host
Port not accessible Use Coder UI port links, not direct URLs

Happy coding! For more help, see Getting Started or Troubleshooting Guide.