Installation
See the installation instructions for details, but it's easy:
- macOS:
brew install ddev/ddev/ddevor justbrew upgrade ddev. - Linux: Use
sudo apt-get update && sudo apt-get install ddev, see apt/yum installation - Windows and WSL2: Download the Windows Installer; you can run it for install or upgrade.
winget install --interactive ddevworks too.
⚠️ Traditional Windows users (not WSL2): If needed, the installer will prompt you to uninstall the previous system-wide installation to avoid conflicts with the new per-user installation. - Consider
ddev delete imagesorddev delete images --allafter upgrading to free up disk space used by previous Docker image versions. This does no harm. - Consider
ddev config --autoto update your projects to current configuration.
Highlights
New defaults
- Debian Trixie is now the base image for
ddev-webserverandddev-ssh-agent(replacing Debian Bookworm). See Issues to be aware of for Trixie.
(Some projects with complex Dockerfiles or obsoletewebimage_extra_packagesmay need to be updated.) - XHGui is now the default profiler (prepend mode remains available via
ddev config global --xhprof-mode=prepend). - Node.js v24 is default in new projects (replacing Node.js v22)
- PHP 8.4 is default in new projects (replacing PHP 8.3)
- MariaDB 11.8 is default in new projects (replacing MariaDB 10.11)
Additional highlights
- Completely revised Windows installer now uses per-user installation for WSL2 or traditional Windows (no admin account required)
- Reworked configurable
ddev sharecommand with a new cloudflared share provider, see (draft) Newddev shareProvider System Brings Free Sharing Options - Add
ddev utility xdebug-diagnosecommand, see (draft) Xdebug in DDEV: Understanding, Debugging, and Troubleshooting Step Debugging - Add
ddev utility mutagen-diagnosecommand, see (draft) Mutagen in DDEV: Functionality, Issues, and Debugging ddev pantheon pullgot newDDEV_PANTHEON_SITE,DDEV_PANTHEON_ENVIRONMENT,DDEV_USE_PANTHEON_BACKUPvariables, see updated Pantheon Integrationddev snapshotnow uses zstd instead of gzip for significantly faster exports and restores, thanks to @deviantintegral- Add CodeIgniter project type, thanks to @Franky5831
- Experimental support for Podman and Docker Rootless, see Podman and Docker Rootless in DDEV
ddev-frankenphpis an official add-on with many improvements, see updated (draft) Using FrankenPHP with DDEV
Features
- New Wagtail (Python, Generic) quickstart
- Added Drupal 12 project type (development branch). Drupal 12 has not yet been released, but it's showing up in developer builds already.
- New
--no-cacheflag forddev startandddev restart(as an alternative toddev utility rebuild) - Improved support for non-Codespaces devcontainers
- Refactored
ddev add-onsubcommands with a fallback mechanism to avoid GitHub API rate limits - Much faster
ddev add-on listandddev add-on search - Shell autocompletion for
ddev add-on get <TAB> - SELinux enviroment detection (auto SELinux label for bind mounts)
- Support for additional SSH config files (
*.conf) in.ddev/homeadditions/.ssh/config.d(global or project-level), see SSH confugation, thanks to @codebymikey - More portable database collations. Databases imported and exported from newer MySQL and MariaDB are less likely to have problems with proprietary collations like
utf8mb4_0900_ai_ciandutf8mb4_uca1400_ai_cias they use more traditional collations in DDEV. - DBeaver support for traditional Windows, thanks to @ddubau
Traefik Router Features, Fixes, and Breaking Changes
- Project Traefik configuration is now standardized to a single file:
.ddev/traefik/config/<projectname>.yaml(all other files are ignored). See issue #8047. - Add any global Traefik configuration inside the
$HOME/.ddev/traefik/custom-global-config/directory - Removed
defaultRuleSyntax: v2andruleSyntax: v3from Traefik configs. Traefik v3 syntax is now used by default. - Traefik configuration errors now show warnings instead of failing hard
- Improved Traefik health checks for more reliable router verification
- Prevent unnecessary router recreation when bound ports are unchanged
ddev-routeris no longer stopped automatically when the last project is stopped, useddev poweroffto fully stop the router- Traefik monitoring port is now bound to localhost only, thanks to @JUVOJustin
- Paused or stopped projects are excluded from Traefik configuration
- Bypass router port checks when all ports appear busy (for example, when endpoint security software intercepts localhost traffic)
Breaking Changes / Removals
- Default
xhprof_modechanged from "prepend" to "xhgui" but you can easily change it back - Removed
ddev utility capabilities, useddev_version_constraintinstead in add-ons. - Removed NFS support, use Mutagen
- Removed
ddev service, custom services can be installed/uninstalled viaddev add-on - Removed
ddev nvm, install theddev-nvmadd-on if needed - Removed obsolete or non-functional commands and command aliases:
ddev restore-snapshotddev auth pantheonddev config pantheon
- Removed obsolete
ddev configflags:--mutagen-enabled(use--performance-mode=mutagen)--upload-dir(use--upload-dirs)--db-image,--db-image-default(never documented or used)
- Removed deprecated
ddev configflag aliases:--http-port→--router-http-port--https-port→--router-https-port--mailhog-port→--mailpit-http-port--mailhog-https-port→--mailpit-https-port--projectname→--project-name--projecttype,--apptype→--project-type--sitename→--project-name--image-defaults→--web-image-default
- Removed
nginx.orgrepository fromddev-webserver, now using nginx from the Debian Trixie repository - Migrated all APT repositories in
ddev-webserverfrom legacy*.listfiles to*.sources(deb822) format
Bug Fixes
- Fixed
ddev heidisqlsupport for multiple databases - Fixed PostgreSQL builds when overriding the database username
- Fixed Windows installer behavior on non-English Windows locales
- Improved Bash detection for non-admin Windows installations
- Fixed
host.docker.internalIP detection for WSL2 mirrored mode with virtual adapters present - Fixed conflicts between
HostWorkingDirandWebWorkingDiraffectingddev npm, thanks to @crowjake - Fixed support for
PKCS#8keys inddev auth ssh - Fixed
ddev snapshotcommand forpostgres:9 - Create Docker volumes only for the configured database type
- Fixed
ddev xdebug,ddev xhprof, andddev blackfirehandlers for the ddev-frankenphp add-on - Fixed
ddev snapshotfailure when run immediately afterddev snapshot restore - Always show the correct project name in
ddev mutagen st, thanks to @agviu - Warn about non-persistent changes when using
ddev composer self-updateandddev composer global - Added support for
COMPOSER_NO_SECURITY_BLOCKING=1inddev composer - Run
post-create-project-cmdfor plugin events inddev composer create-project - Improved
log-stderr.shreporting duringddev start - Skip poweroff prompts when containers are already stopped during version upgrades
- Fixed database port type in TYPO3 settings, thanks to @BreathCodeFlow
- Detect and warn about multiple global config directories during
ddev start
Minor Updates
- PHP 8.3.30, 8.4.17, and 8.5.2
- Docker Compose v5.0.2
- Updated Generic webserver quickstart
- Add
APP_FULL_BASE_URLfor CakePHP, thanks to @ajibarra - Updated Lagoon provider instructions with sync configuration, thanks to @froboy
- Added Cloudflare WARP networking instructions, thanks to @lguigo22
- Updated Ibexa DXP installation steps, thanks to @adriendupuis
- Added troubleshooting guidance for endpoint security interfering with Xdebug, thanks to @joelpittet
- Replaced
github.com/docker/dockerwithgithub.com/moby/moby/clientandgithub.com/moby/moby/api
What's Changed
- test: Allow overriding ignore expiring keys [skip buildkite] by @rfay in #7803
- test: Improve TestHasConfigNameOverride so it doesn't leave projects after completion, fixes #7797 by @rfay in #7798
- test: don't check for expiring keys in forks, for #7803 by @stasadev in #7831
- build(deps): bump golangci/golangci-lint-action from 8 to 9 by @dependabot[bot] in #7832
- fix(heidisql): use
--databasesflag only when needed, fixes #7829 by @stasadev in #7830 - docs: add missing dot in
.ddev/.env.*by @yanniboi in #7828 - fix(postgres): use placeholder for username, fixes #7820 by @stasadev in #7827
- docs: remove community examples link in documentation by @weitzman in #7834
- refactor: improve
ddev auth sshreadability and reuse cmd in tests by @stasadev in #7816 - test(quickstart): check for new FrankenPHP headers by @stasadev in #7836
- docs: Update Docker connection failure explanations with more on docker context ls by @rfay in #7833
- chore(images): Remove image build for ddev-nginx-proxy-router by @rfay in #7818
- chore: Remove
ddev utility capabilitiescommand completely, fixes #7174 by @Copilot in #7814 - build: fix getopt detection on macOS by @deviantintegral in #7846
- docs: Add Claude Code for Web environment configuration guide [skip ci] by @rfay in #7838
- chore(traefik): Remove redundant Traefik rule syntax configuration, fixes #7822 by @rfay in #7823
- chore: Remove NFS support for v1.25.0, remove unused CircleCI config, fixes #7810 by @Copilot in #7811
- build: use debian:trixie as base for ddev-webserver by @rfay in #7649
- fix(heidisql): add default
--databases=dbto postgres, for #7830 by @raphaelportmann in #7847 - test(timezone): Windows may show 'Universal' instead of UTC by @rfay in #7848
- build(deps): bump docker to v29 by @stasadev in #7835
- test(share): Fix TestShareCmd to handle non-string types in JSON logs by @Copilot in #7851
- fix: remove trailing comma from schema.json by @stasadev in #7850
- fix: Disable 64-bit file system redirection in Windows installer Section to access wsl.exe by @rfay in #7839
- test(typo3): Fix Apache version of TYPO3 TestDdevFullSiteSetup and untarring symlinks, fixes #7754, fixes #6972 by @rfay in #7817
- test(pantheon): fix TestPantheonPush, which was broken by composer 2.9 [skip buildkite] by @rfay in #7854
- test: Add CI tests for ddev-hostname with passwordless sudo, fixes #7795 [skip buildkite] by @Copilot in #7855
- test: prevent panic in TestDownloadAndExtractTarball when cleanup is nil, fixes #7652 by @Copilot in #7857
- chore: Change xhprof_mode default from prepend to xhgui, fixes #7808 by @Copilot in #7809
- docs: clarify instructions for disabling mutagen on a single project by @q0rban in #7861
- test: Can't do ddev-hostname on WSL2 by @rfay in #7860
- test: default key expiration 90 days, for #7831 [skip ci] by @stasadev in #7873
- chore(nodejs): Change default nodejs_version for new projects to 24, fixes #7819 by @rfay in #7821
- ci(golangci-lint): add import-shadowing check by @stasadev in #7865
- test: stop project after addon tests that create docker-compose services, for #7607 by @Copilot in #7858
- docs(fritzbox): Update FritzBox references and point to new blog by @rfay in #7867
- chore: Remove
ddev servicecommand, fixes #7812 by @Copilot in #7813 - chore(deprecation): remove ddev nvm functionality in v1.25.0 by @rfay in #7826
- fix(quickstart): temporarily install Composer from snapshot for 2.9 compatibility by @stasadev in #7864
- docs(xdebug): Add details on how to repair WSL2 networking by @rfay in #7879
- docs: fix MD060 table column style errors for markdownlint v0.37+ [skip buildkite] by @rfay in #7882
- test(quickstart): pin Composer to 2.8.12 for Magento 2 by @stasadev in #7883
- test(wsl-mirrored): Skip TestGetLocalHTTPResponse on WSL2 mirrored by @rfay in #7884
- feat: Change default PHP version to 8.4, fixes #7874 by @Copilot in #7875
- chore(composer): remove
--snapshotworkaround, for #7864 by @stasadev in #7887 - test(quickstart): fix Backdrop, FrankenPHP, Grav by @stasadev in #7886
- fix: Add gpgv, configure APT, convert sources to deb822 (except mariadb), update script references, and add audit tests to prevent SHA1 key trust failures in February 2026, fixes #7849 by @Copilot in #7877
- test(windows): make sure we have a clean install distro by @rfay in #7891
- docs: stop recommending Stack Overflow by @rfay in #7895
- test(quickstart): fix frankenphp build by @stasadev in #7889
- docs: update TYPO3 link by @stasadev in #7898
- build(curl): use trixie-backports to install newer curl by @stasadev in #7897
- fix(xdebug): Use a more sophisticated search for windows host ip address on WSL mirrored mode by @rfay in #7880
- test(typo3): Fix TYPO3 quickstart, failing since TYPO3 v14.0.0 released by @rfay in #7901
- fix: db port should be integer in generated TYPO3 AdditionalConfiguration.php, fixes #7892 by @BreathCodeFlow in #7893
- test(quickstart): php8.3 for silverstripe and symfony, disable typo3 v13 by @stasadev in #7909
- fix(commands): make
HostWorkingDirrespectWebWorkingDirby @crowjake in #7907 - build(docker): add more php8.5 packages by @stasadev in #7908
- test(add-on): replace redis-commander with redis-insight by @stasadev in #7911
- chore(deprecation): update default MariaDB version to 11.8 for new projects, for #6861 by @rfay in #7824
- build(mkdocs): bump actions/setup-python from 6.0.0 to 6.1.0, pin click to 8.2.1 by @dependabot[bot] in #7913
- fix: check for multiple global config dirs on
ddev startand improve usage for~/.ddevin the docs, fixes #7582 by @rfay in #7859 - test(quickstart): remove version pins from Magento 2, Silverstripe, Symfony, TYPO3, fixes #7905 by @stasadev in #7914
- fix: remove unnecessary debug output when probing for TYPO3 project type, fixes #7890 by @Copilot in #7918
- test(windows): stop uninstalling as it leads to intermittent problems by @rfay in #7916
- fix: Windows installer refuses to install on wrong architecture, fixes #7524, fixes #7900 by @Copilot in #7910
- feat(pantheon): address Pantheon hosting provider issues, fixes #7730, fixes #7655 by @rfay in #7837
- fix(collation): Use more portable default collations for mysql8.x and mariadb11.x by @rfay in #7906
- feat: Warn WSL2 users with project on Windows filesystem, fixes #7888 by @Copilot in #7917
- fix(diagnose): Remove the hard-coded IP "127.0.0.1" from the DNS check, since it may be incorrect, fixes #7871 by @grummbeer in #7872
- docs: update instructions for maintainers by @stasadev in #7924
- chore(debug): Migrate
ddev debugstatements toddev utilitystatements by @rfay in #7925 - fix: Remove obsolete config syntax and commands for v1.25.0, fixes #7825 by @Copilot in #7919
- build(php): install php8.5-xdebug (amd64/arm64), php7.0-7.3-redis (arm64), php8.5-memcached (amd64) by @stasadev in #7928
- feat: add Podman rootless/rootful and Docker rootless support, fixes #2276, fixes #2899 by @stasadev in #7702
- docs: Fix link to globalsign safenet drivers by @rfay in #7932
- fix: use correct condition for host ports, fixes #7920 by @stasadev in #7922
- fix(ddev-ssh-agent): Update ddev-ssh-agent to base on Trixie and accept PKCS8 RSA keys, fixes #4802 by @rfay in #7933
- fix(docker): support SELinux shared label, fixes #7196 by @stasadev in #7939
- build(deps): bump actions/cache from 4 to 5 by @dependabot[bot] in #7944
- build(deps): bump actions/upload-artifact from 5 to 6 by @dependabot[bot] in #7943
- fix: convert Windows installer to per-user installation, fixes #7776 by @rfay in #7931
- feat: support using zstd for snapshots, fix
postgres:9snapshot, fixes #7844, fixes #3583 by @deviantintegral in #7845 - fix: only create volume for configured db type, add project label by @stasadev in #7937
- feat: restart supervisor for generic webserver and blackfire, xdebug, xhprof, fixes #7941, for ddev/ddev-frankenphp#44 by @stasadev in #7945
- fix(router): ensure Traefik dashboard port is always bound to localhost by @JUVOJustin in #7942
- fix: fail on
ddev startfor docker-rootless w/o no-bind-mounts, don't test with latest rootless by @stasadev in #7952 - fix: remove stale target files in getBackupCommand to prevent "Is a directory" errors, fixes #7936 by @Copilot in #7938
- fix(windows): Change FindBashPath to detect user-local Git Bash installations on Windows, fixes #7948 by @Copilot in #7949
- test(lima): force limactl stop [skip ci] by @rfay in #7957
- docs(ssh): Explain what to do when remote host identification has changed, fixes #7946 by @rfay in #7956
- feat(share): Rework
ddev share, add cloudflared share provider, enhance tests, fixes #7784, fixes #6441 by @rfay in #7802 - docs(codespaces): persist global config on codespaces, fixes #6228 [skip ci] by @rfay in #7958
- test(buildkite): Make sure to clean up global traefik dir [skip ci] by @rfay in #7965
- test(windows): Fix timing bug in TestWindowsInstallerWSL2 polling loop by @rfay in #7964
- test(share): fix TestShareCmdProviderSystem/ProviderArgsFlag assertion, fixes #7959 by @rfay in #7960
- test: Stop using old version of memcached to prevent output about docker-compose version tag [skip ci] by @rfay in #7973
- fix(platform): Resume environment if not running by @rfay in #7972
- build(deps): install tzdata-legacy for Debian 13 Trixie by @stasadev in #7971
- fix: show correct project name in
ddev mutagen st, fixes #7969 by @stasadev in #7970 - test(buildkite): Use colima stop -f to force stop [skip ci] by @rfay in #7977
- docs: add cloudflare warp networking instructions by @lguigo22 in #7975
- docs: lima template creation for users [skip buildkite] by @rfay in #7985
- docs(developer): Update template syntax for lima in developer docs by @rfay in #7984
- test: show ddev version at start of tests by @rfay in #7983
- fix(traefik): Convert Traefik configuration errors to warnings instead of failures by @Copilot in #7967
- fix(test): Force TestDownloadFileRetryLogic to work even if DDEV_DEBUG wasn't set [skip ci] by @rfay in #7986
- refactor: systematize #ddev-generated signature checking by @rfay in #7982
- feat: Add
ddev utility mutagen-diagnosecommand for Mutagen troubleshooting, fixes #7740 by @rfay in #7988 - fix(router): Improve Traefik healthcheck for better router verification by @Copilot in #7981
- test(buildkite): Clean up lima and colima containers at start by @rfay in #8006
- test(github): Allow skipping github tests with [skip github] by @rfay in #8007
- fix(router): Prevent unnecessary router re-creation when bound ports unchanged, fixes #6703 by @Copilot in #7992
- fix(composer): warn that global and self-update changes don't persist, use
stablefor emptycomposer_version, fixes #7993 by @stasadev in #7995 - feat: add
--no-cacheflag forddev startandddev restartby @stasadev in #7999 - fix(router): healthcheck after new config must happen as normal user by @rfay in #8010
- test(traefik): improve reliability of traefik.bats router API tests by @rfay in #8013
- docs: separate CLAUDE.md from AGENTS.md with focused content by @shaal in #8011
- feat: include additional ssh config files by @codebymikey in #8008
- fix(tests): make GitHub release downloads more resilient [skip buildkite] by @rfay in #8015
- chore(codespaces): Use newer test project for codespaces, fixes #8017 by @rfay in #8022
- docs: Update Ibexa DXP install by @adriendupuis in #8021
- test: Disable long-running tests when GOTEST_SHORT is set, fixes #8026 by @rfay in #8028
- build(docker-compose): Bump docker-compose to v5.0.1 before release by @rfay in #8031
- test(docker): Add Docker CE container cleanup for WSL instances, fixes #8029 by @Copilot in #8030
- fix: prevent panic during
ddev poweroffor use of container.Names[0], fixes #8024 by @Copilot in #8027 - docs(xdebug): Add step-debugging.md endpoint security notes by @joelpittet in #8002
- feat(codeigniter): add CodeIgniter 4 app type, fixes #7303 by @Franky5831 in #7853
- fix(composer): run post-create-project-cmd for plugin events by @stasadev in #8039
- fix: sort web_extra_exposed_ports for router port matching in generic webserver, fixes #7640 by @stasadev in #8040
- feat(xdebug-diagnose): Add
ddev utility xdebug-diagnosecommand with interactive mode and WSL2 support by @Copilot in #8004 - fix: exclude paused/stopped projects from router's Traefik configuration by @rfay in #7961
- test(quickstart): fix TYPO3 v14 test [skip ci] by @stasadev in #8044
- fix(pause): resolve race condition in app.Pause() causing intermittent test failures by @rfay in #8043
- feat(devcontainer): Add more explicit support for non-codespaces devcontainer, for #7294, for #7876, fixes #8018 by @rfay in #8032
- fix: pull all app images at once, initialize XHGui ports and mode if empty, fixes #8023 by @stasadev in #8046
- fix(webserver): better log-stderr.sh reporting, remove trixie-backports by @stasadev in #8042
- build(deps): bump go.mod and docker-compose to v5.0.2 by @stasadev in #8045
- test(quickstart): add Wagtail (Django) Python, remove FrankenPHP by @stasadev in #8049
- fix(cakephp): add new variable APP_FULL_BASE_URL to .env file by @ajibarra in #8048
- fix(poweroff): Skip poweroff prompt when containers already stopped during version upgrade by @Copilot in #8052
- fix(router): Fix ephemeral port allocation when router is unhealthy, fixes #8041 by @Copilot in #8051
- feat(add-ons): Use addons.json to avoid GitHub API rate limits, fixes #7707 by @stasadev in #7978
- build(deps): bump actions/setup-python from 6.1.0 to 6.2.0 by @dependabot[bot] in #8059
- docs: Update Lagoon provider instructions with sync config, fixes #7990 by @froboy in #7991
- test(quickstart): disable symfony tests, update Laravel SQLite, for #8058 by @stasadev in #8060
- feat(drupal12): Drupal 12 is now showing up in dev, support it, fixes #8055 by @rfay in #8056
- fix(ddevapp): check file existence in isCustomConfigFile by @stasadev in #8061
- fix(router): bypass CheckRouterPorts when all ports appear busy, fixes #7921 by @stasadev in #7927
- docs(drupal-cms): In the Drupal CMS quick-start, call drupal recipe:unpack by @phenaproxima in #8037
- chore(quickstart): enable tests for symfony, fixes #8058 by @stasadev in #8070
- feat(commands): add Windows support for DBeaver outside WSL, add cygwin to OSTYPE by @ddubau in #8065
- build(docker): bump images to v1.25.0 for release, update MariaDB gpg key by @stasadev in #8062
- fix(lagoon): bug in lagoon-sync means it fails if ~/.ssh/known_hosts doesn't exist [skip buildkite] by @rfay in #8072
- fix(healthcheck): resolve optional profiles to services, for #7745 by @stasadev in #8071
- test(quickstart): fix Statamic check for login page by @stasadev in #8073
- test: fix drupal.bats for drupal cms 2 by @rpkoller in #8074
- test: add DDEV_EMBARGO_TESTS to skip tests via environment variable, fixes #8076 [skip buildkite] by @rfay in #8077
- build(webserver): fix check for MariaDB keyring [skip buildkite] by @stasadev in #8078
- chore: update version history for v1.25.0, for #7934 by @stasadev in #8079
- test: skip TestExtractCurlBody when httpbin.org is unavailable [skip buildkite] by @rfay in #8080
- test(openmage): add --no-security-blocking to openmage.bats for Composer 2.9 compatibility [skip buildkite] by @rfay in #8092
- chore(github): update PR template by @stasadev in #8089
- fix(heidisql): get basename for postgres library, fixes #8086 by @stasadev in #8087
- fix(add-on): Re-add the output suggesting ddev restart after add-on, fixes #8088 by @rfay in #8090
- docs: add note on restarting for environment variable changes by @MurzNN in #8093
- fix(add-on): normalize
ddev add-on getoutput when there's no version by @stasadev in #8094
New Contributors
- @q0rban made their first contribution in #7861
- @BreathCodeFlow made their first contribution in #7893
- @crowjake made their first contribution in #7907
- @grummbeer made their first contribution in #7872
- @JUVOJustin made their first contribution in #7942
- @lguigo22 made their first contribution in #7975
- @codebymikey made their first contribution in #8008
- @Franky5831 made their first contribution in #7853
- @ddubau made their first contribution in #8065
Full Changelog: v1.24.10...v1.25.0