# CMS Quickstarts

DDEV is [ready to go](<https://ddev.github.io/ddev/en/stable/users/project/index.md>) with generic project types for PHP frameworks, and more specific project types for working with popular platforms and CMSes. To learn more about how to manage projects in DDEV visit [Managing Projects](<https://ddev.github.io/ddev/en/stable/users/usage/managing-projects/index.md>).

Before proceeding, make sure your installation of DDEV is up to date. In a new and empty project folder, using your favorite shell, run the following commands:

## Asterios

Use a new or existing Composer project, or clone a Git repository.

The Asterios project type can be used for [Scaffolding](<https://github.com/asteriosframework/asterios-app>) and others, as it is used with basic Asterios. DDEV automatically updates or creates the `.env` file with the database information.

Create the project directory and configure DDEV:

```
mkdir -p my-asterios-site && cd my-asterios-site
ddev config --project-type=asterios --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Asterios via Composer:

```
ddev composer create-project asterios/app
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-asterios.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-asterios-site && cd my-asterios-site
> ddev config --project-type=asterios --docroot=public
> ddev start -y
> ddev composer create-project asterios/app
> ddev launch
> EOF
> chmod +x setup-asterios.sh
> ./setup-asterios.sh
> ```

## Backdrop

You can start a new [Backdrop](<https://backdropcms.org>) project or configure an existing one.

Create the project directory and configure DDEV:

```
mkdir -p my-backdrop-site && cd my-backdrop-site
ddev config --project-type=backdrop
# Add the official Bee CLI add-on
ddev add-on get backdrop-ops/ddev-backdrop-bee
```

Start DDEV (this may take a minute):

```
ddev start
```

Download Backdrop core and create admin user:

```
# Download Backdrop core
ddev bee download-core
# Create admin user
ddev bee si --username=admin --password=Password123 --db-name=db --db-user=db --db-pass=db --db-host=db --auto
```

Launch the site:

```
# Login using `admin` user and `Password123` password
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-backdrop.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-backdrop-site && cd my-backdrop-site
> ddev config --project-type=backdrop
> ddev add-on get backdrop-ops/ddev-backdrop-bee
> ddev start -y
> ddev bee download-core
> ddev bee si --username=admin --password=Password123 --db-name=db --db-user=db --db-pass=db --db-host=db --auto
> ddev launch
> EOF
> chmod +x setup-backdrop.sh
> ./setup-backdrop.sh
> ```

You can start using DDEV with an existing project, too—but make sure you have a database backup handy!

Create project directory and clone your repository:

```
mkdir -p my-backdrop-site && cd my-backdrop-site
git clone https://github.com/ddev/test-backdrop.git .
```

Configure DDEV:

```
ddev config --project-type=backdrop
```

Add the official Bee CLI add-on:

```
ddev add-on get backdrop-ops/ddev-backdrop-bee
```

Start DDEV (this may take a minute):

```
ddev start
```

Import database and files backups:

```
ddev import-db --file=/path/to/db.sql.gz
ddev import-files --source=/path/to/files.tar.gz
ddev bee cc all
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-backdrop-existing.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-backdrop-site && cd my-backdrop-site
> git clone https://github.com/ddev/test-backdrop.git .
> ddev config --project-type=backdrop
> ddev add-on get backdrop-ops/ddev-backdrop-bee
> ddev start -y
> ddev import-db --file=/path/to/db.sql.gz
> ddev import-files --source=/path/to/files.tar.gz
> ddev bee cc all
> ddev launch
> EOF
> chmod +x setup-backdrop-existing.sh
> ./setup-backdrop-existing.sh
> ```

## CakePHP

You can start a new [CakePHP](<https://cakephp.org>) project or configure an existing one.

The CakePHP project type can be used with any CakePHP project \>= 3.x, but it has been fully tested with CakePHP 5.x. DDEV automatically creates the `.env` file with the database information, email transport configuration and a random salt. If `.env` file already exists, `.env.ddev` will be created, so you can take any variable and put it into your `.env` file.

Please note that you will need to change the PHP version to 7.4 to be able to work with CakePHP 3.x.

Create the project directory and configure DDEV:

```
mkdir -p my-cakephp-composer-site && cd my-cakephp-composer-site
ddev config --project-type=cakephp --docroot=webroot
```

Start DDEV (this may take a minute):

```
ddev start
```

Install CakePHP via Composer:

```
ddev composer create-project --prefer-dist --no-interaction cakephp/app:~5.0
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-cakephp.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-cakephp-composer-site && cd my-cakephp-composer-site
> ddev config --project-type=cakephp --docroot=webroot
> ddev start -y
> ddev composer create-project --prefer-dist --no-interaction cakephp/app:~5.0
> ddev launch
> EOF
> chmod +x setup-cakephp.sh
> ./setup-cakephp.sh
> ```

Clone the repository and configure DDEV:

```
git clone <my-cakephp-repo> my-cakephp-git-site
cd my-cakephp-git-site
ddev config --project-type=cakephp --docroot=webroot
```

Start DDEV (this may take a minute):

```
ddev start
```

Install dependencies and launch:

```
ddev composer install
ddev cake
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-cakephp-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> git clone <my-cakephp-repo> my-cakephp-git-site
> cd my-cakephp-git-site
> ddev config --project-type=cakephp --docroot=webroot
> ddev start -y
> ddev composer install
> ddev cake
> ddev launch
> EOF
> chmod +x setup-cakephp-git.sh
> ./setup-cakephp-git.sh
> ```

## CiviCRM (Standalone)

[CiviCRM Standalone](<https://civicrm.org/blog/ufundo/next-steps-civicrm-standalone>) allows running [CiviCRM](<https://civicrm.org/>) without a CMS. Visit [Install CiviCRM (Standalone)](<https://docs.civicrm.org/installation/en/latest/standalone>) for more installation details.

Create the project directory and configure DDEV:

```
mkdir -p my-civicrm-site && cd my-civicrm-site
ddev config --project-type=php --composer-root=core --upload-dirs=public/media
```

Start DDEV (this may take a minute):

```
ddev start
```

Download and extract CiviCRM:

```
ddev exec "curl -fsSL https://download.civicrm.org/latest/civicrm-STABLE-standalone.tar.gz -o /tmp/civicrm-standalone.tar.gz"
ddev exec "tar --strip-components=1 -xzf /tmp/civicrm-standalone.tar.gz"
ddev composer require civicrm/cli-tools --no-scripts
```

Install CiviCRM (or use `ddev launch` to install manually):

```
# You can install CiviCRM manually in your browser using `ddev launch`
# and selecting `db` for the server and `db` for database/username/password
# or do the same automatically using the command below:
# The parameter `-m loadGenerated=1` includes sample data
ddev exec cv core:install \
    --cms-base-url='$DDEV_PRIMARY_URL' \
    --db=mysql://db:db@db/db \
    -m loadGenerated=1 \
    -m extras.adminUser=admin \
    -m extras.adminPass=admin \
    -m extras.adminEmail=admin@example.com
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-civicrm.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-civicrm-site && cd my-civicrm-site
> ddev config --project-type=php --composer-root=core --upload-dirs=public/media
> ddev start -y
> ddev exec "curl -fsSL https://download.civicrm.org/latest/civicrm-STABLE-standalone.tar.gz -o /tmp/civicrm-standalone.tar.gz"
> ddev exec "tar --strip-components=1 -xzf /tmp/civicrm-standalone.tar.gz"
> ddev composer require civicrm/cli-tools --no-scripts
> ddev exec cv core:install \
>     --cms-base-url='$DDEV_PRIMARY_URL' \
>     --db=mysql://db:db@db/db \
>     -m loadGenerated=1 \
>     -m extras.adminUser=admin \
>     -m extras.adminPass=admin \
>     -m extras.adminEmail=admin@example.com
> ddev launch
> EOF
> chmod +x setup-civicrm.sh
> ./setup-civicrm.sh
> ```

## CodeIgniter

Use a new or existing Composer project, or clone a Git repository.

DDEV automatically updates or creates the `.env` file with the database information.

Create the project directory and configure DDEV:

```
mkdir -p my-ci4-site && cd my-ci4-site
ddev config --project-type=codeigniter --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install CodeIgniter via Composer:

```
ddev composer create-project codeigniter4/appstarter
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-codeigniter.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-ci4-site && cd my-ci4-site
> ddev config --project-type=codeigniter --docroot=public
> ddev start -y
> ddev composer create-project codeigniter4/appstarter
> ddev launch
> EOF
> chmod +x setup-codeigniter.sh
> ./setup-codeigniter.sh
> ```

## Contao

Further information on the DDEV procedure can also be found in the [Contao documentation](<https://docs.contao.org/manual/en/guides/local-installation/ddev/>).

Create the project directory and configure DDEV:

```
mkdir -p my-contao-composer-site && cd my-contao-composer-site
ddev config --project-type=php --docroot=public --webserver-type=apache-fpm --php-version=8.4
```

Install Contao via Composer (this may take a minute):

```
ddev composer create-project contao/managed-edition:5.7
```

Configure database and mailer settings:

```
ddev dotenv set .env.local --database-url=mysql://db:db@db:3306/db --mailer-dsn=smtp://localhost:1025
```

Create the database:

```
ddev exec contao-console contao:migrate --no-interaction
```

Create backend user:

```
ddev exec contao-console contao:user:create --username=admin --name=Administrator --email=admin@example.com --language=en --password=Password123 --admin
```

Launch the administration area:

```
ddev launch contao
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-contao.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-contao-composer-site && cd my-contao-composer-site
> ddev config --project-type=php --docroot=public --webserver-type=apache-fpm --php-version=8.4
> ddev composer create-project contao/managed-edition:5.7
> ddev dotenv set .env.local --database-url=mysql://db:db@db:3306/db --mailer-dsn=smtp://localhost:1025
> ddev exec contao-console contao:migrate --no-interaction
> ddev exec contao-console contao:user:create --username=admin --name=Administrator --email=admin@example.com --language=en --password=Password123 --admin
> ddev launch contao
> EOF
> chmod +x setup-contao.sh
> ./setup-contao.sh
> ```

Like most PHP projects, Contao could be installed and updated with Composer. The [Contao Manager](<https://docs.contao.org/manual/en/installation/contao-manager/>) is a tool that provides a graphical user interface to manage a Contao installation.

Create the project directory and configure DDEV:

```
mkdir -p my-contao-manager-site && cd my-contao-manager-site
ddev config --project-type=php --docroot=public --webserver-type=apache-fpm --php-version=8.4
```

Configure database and mailer settings:

```
ddev dotenv set .env.local --database-url=mysql://db:db@db:3306/db --mailer-dsn=smtp://localhost:1025
```

Start DDEV (this may take a minute):

```
ddev start
```

Download the Contao Manager:

```
ddev exec "wget -O public/contao-manager.phar.php https://download.contao.org/contao-manager/stable/contao-manager.phar"
```

Launch the Contao Manager and follow the setup wizard:

```
ddev launch contao-manager.phar.php
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-contao-manager.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-contao-manager-site && cd my-contao-manager-site
> ddev config --project-type=php --docroot=public --webserver-type=apache-fpm --php-version=8.4
> ddev dotenv set .env.local --database-url=mysql://db:db@db:3306/db --mailer-dsn=smtp://localhost:1025
> ddev start -y
> ddev exec "wget -O public/contao-manager.phar.php https://download.contao.org/contao-manager/stable/contao-manager.phar"
> ddev launch contao-manager.phar.php
> EOF
> chmod +x setup-contao-manager.sh
> ./setup-contao-manager.sh
> ```

The [Contao demo website](<https://demo.contao.org/>) is maintained for the currently supported Contao versions and can be [optionally installed](<https://github.com/contao/contao-demo>). Via the Contao Manager you can select this option during the first installation.

## Craft CMS

Start a new [Craft CMS](<https://craftcms.com>) project or retrofit an existing one.

DDEV injects a number of special environment variables into the container (via `.ddev/.env.web`) that [automatically configure](<https://craftcms.com/docs/5.x/configure.html#environment-overrides>) Craft’s database connection and the project’s primary site URL. You may opt out of this behavior with the [`disable_settings_management`](<https://ddev.github.io/ddev/en/stable/users/configuration/config/#disable_settings_management>) setting.

> [!TIP]
>
> **Compatibility with Craft CMS 3**
>
> The `craftcms` project works best with configuration features that became available in Craft CMS 4.x. If you are using Craft CMS 3.x or earlier, you may want to use the `php` project type and explicitly define [database connection details](<https://ddev.github.io/ddev/en/stable/users/usage/database-management/#database-backends-and-defaults>) via [Craft’s `db.php`](<https://craftcms.com/docs/3.x/config/db-settings.html>).

Create the project directory and configure DDEV:

```
mkdir -p my-craft-site && cd my-craft-site
ddev config --project-type=craftcms --docroot=web
```

Start DDEV (this may take a minute):

```
ddev start
```

Scaffold a new project with Composer:

```
ddev composer create-project craftcms/craft
```

Craft’s setup wizard will start automatically!

[Third-party starter projects](<https://craftcms.com/knowledge-base/using-the-starter-project#community-starter-projects>) can be substituted for `craftcms/craft` when running `ddev composer create-project`.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-craft.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-craft-site && cd my-craft-site
> ddev config --project-type=craftcms --docroot=web
> ddev start -y
> ddev composer create-project craftcms/craft
> EOF
> chmod +x setup-craft.sh
> ./setup-craft.sh
> ```

You can start using DDEV with an existing Craft project, too. All you need is the codebase and a database backup!

Clone the repository (or navigate to a local project directory):

```
git clone https://github.com/example/example-site my-craft-site
cd my-craft-site
```

Configure DDEV:

```
ddev config --project-type=craftcms --docroot=web
```

Start DDEV and install Composer packages:

```
ddev start
ddev composer install
```

Import database backup and launch:

```
ddev craft db/restore /path/to/db.sql.gz
ddev launch
```

Craft CMS projects use MySQL 8.0, by default. You can override this setting (and the PHP version) during setup with [`config` command flags](<https://ddev.github.io/ddev/en/stable/users/usage/commands/#config>) or after setup via the [configuration files](<https://ddev.github.io/ddev/en/stable/users/configuration/config/index.md>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-craft-existing.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> git clone https://github.com/example/example-site my-craft-site
> cd my-craft-site
> ddev config --project-type=craftcms --docroot=web
> ddev start -y
> ddev composer install
> ddev craft db/restore /path/to/db.sql.gz
> ddev launch
> EOF
> chmod +x setup-craft-existing.sh
> ./setup-craft-existing.sh
> ```

### Running Craft in a Subdirectory

Set [`composer_root`](<https://ddev.github.io/ddev/en/stable/users/configuration/config/#composer_root>) to the subdirectory where Craft is installed. For example, `ddev config --composer-root=app`.

> [!TIP]
>
> **Installing Craft**
>
> Read more about installing Craft in the [official documentation](<https://craftcms.com/docs>).

## Drupal

Create the project directory and configure DDEV:

```
mkdir -p my-drupal11-site && cd my-drupal11-site
ddev config --project-type=drupal11 --docroot=web
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Drupal via Composer:

```
ddev composer create-project drupal/recommended-project
ddev composer require drush/drush
```

Run Drupal installation and launch:

```
ddev drush site:install --account-name=admin --account-pass=admin -y
ddev launch
# or automatically log in with:
ddev launch $(ddev drush uli)
```

Read more about [Drupal Core](<https://new.drupal.org/about/overview/technical>) &amp; [Documentation](<https://www.drupal.org/docs>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal11.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-drupal11-site && cd my-drupal11-site
> ddev config --project-type=drupal11 --docroot=web
> ddev start -y
> ddev composer create-project drupal/recommended-project
> ddev composer require drush/drush
> ddev drush site:install --account-name=admin --account-pass=admin -y
> ddev launch
> EOF
> chmod +x setup-drupal11.sh
> ./setup-drupal11.sh
> ```

Create the project directory and configure DDEV:

```
mkdir -p my-drupalcms-site && cd my-drupalcms-site
ddev config --project-type=drupal11 --docroot=web
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Drupal CMS via Composer:

```
ddev composer create-project drupal/cms
# Note: recipe-unpack runs automatically in DDEV v1.25.0+
ddev composer drupal:recipe-unpack
```

Launch the site:

```
ddev launch
```

Read more about [Drupal CMS](<https://new.drupal.org/drupal-cms>) &amp; [Documentation](<https://new.drupal.org/docs/drupal-cms>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal-cms.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-drupalcms-site && cd my-drupalcms-site
> ddev config --project-type=drupal11 --docroot=web
> ddev start -y
> ddev composer create-project drupal/cms
> # Note: recipe-unpack runs automatically in DDEV v1.25.0+
> ddev composer drupal:recipe-unpack
> ddev launch
> EOF
> chmod +x setup-drupal-cms.sh
> ./setup-drupal-cms.sh
> ```

Create the project directory and configure DDEV:

```
mkdir -p my-drupal10-site && cd my-drupal10-site
ddev config --project-type=drupal10 --docroot=web
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Drupal via Composer:

```
ddev composer create-project "drupal/recommended-project:^10"
ddev composer require drush/drush
```

Run Drupal installation and launch:

```
ddev drush site:install --account-name=admin --account-pass=admin -y
ddev launch
# or automatically log in with:
ddev launch $(ddev drush uli)
```

Read more about [Drupal Core](<https://new.drupal.org/about/overview/technical>) &amp; [Documentation](<https://www.drupal.org/docs>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal10.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-drupal10-site && cd my-drupal10-site
> ddev config --project-type=drupal10 --docroot=web
> ddev start -y
> ddev composer create-project "drupal/recommended-project:^10"
> ddev composer require drush/drush
> ddev drush site:install --account-name=admin --account-pass=admin -y
> ddev launch
> EOF
> chmod +x setup-drupal10.sh
> ./setup-drupal10.sh
> ```

Clone your Drupal repository:

```
git clone https://github.com/example/my-drupal-site
cd my-drupal-site
```

Configure DDEV (follow prompts):

```
ddev config
```

Start DDEV and launch:

```
ddev start
ddev launch /install.php
```

Drupal 7 doesn’t know how to redirect from the front page to `/install.php` if the database is not set up but the settings files *are* set up, so launching with `/install.php` gets you started with an installation. You can also run `drush site-install`, then `ddev exec drush site-install --yes`.

See [Importing a Database](<https://ddev.github.io/ddev/en/stable/users/usage/managing-projects/#importing-a-database>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal67.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> git clone https://github.com/example/my-drupal-site
> cd my-drupal-site
> ddev config
> ddev start -y
> ddev launch /install.php
> EOF
> chmod +x setup-drupal67.sh
> ./setup-drupal67.sh
> ```

This example shows how to work on an existing Drupal project, using a clone of a test repository. Replace with your Git repository.

Clone your web project repository:

```
PROJECT_GIT_URL=https://github.com/ddev/test-drupal11.git
git clone ${PROJECT_GIT_URL} my-drupal11-site
cd my-drupal11-site
```

Configure and start DDEV:

```
ddev config --project-type=drupal11 --docroot=web
ddev start
```

Install dependencies and set up Drupal:

```
ddev composer install
ddev drush site:install --account-name=admin --account-pass=admin -y
```

Launch the site:

```
ddev launch
```

Read more about [Drupal Core](<https://new.drupal.org/about/overview/technical>) &amp; [Documentation](<https://www.drupal.org/docs>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> PROJECT_GIT_URL=https://github.com/ddev/test-drupal11.git
> git clone ${PROJECT_GIT_URL} my-drupal11-site
> cd my-drupal11-site
> ddev config --project-type=drupal11 --docroot=web
> ddev start -y
> ddev composer install
> ddev drush site:install --account-name=admin --account-pass=admin -y
> ddev launch
> EOF
> chmod +x setup-drupal-git.sh
> ./setup-drupal-git.sh
> ```

Those who want to try out the unreleased upcoming Drupal 12 can install it this way:

```
mkdir -p my-drupal12-site && cd my-drupal12-site
ddev config --project-type=drupal12 --docroot=web
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Drupal via Composer:

```
ddev composer create-project drupal/recommended-project:main-dev@dev
ddev composer require drush/drush
```

Run Drupal installation and launch:

```
ddev drush site:install --account-name=admin --account-pass=admin -y
ddev launch
# or automatically log in with:
ddev launch $(ddev drush uli)
```

Read more about [Drupal Core](<https://new.drupal.org/about/overview/technical>) &amp; [Documentation](<https://www.drupal.org/docs>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-drupal12.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-drupal12-site && cd my-drupal12-site
> ddev config --project-type=drupal12 --docroot=web
> ddev start -y
> ddev composer create-project drupal/recommended-project:main-dev@dev
> ddev composer require drush/drush
> ddev drush site:install --account-name=admin --account-pass=admin -y
> ddev launch
> EOF
> chmod +x setup-drupal12.sh
> ./setup-drupal12.sh
> ```

## ExpressionEngine

Create the project directory:

```
mkdir -p my-ee-zip-site && cd my-ee-zip-site
```

Download and extract the latest ExpressionEngine release:

```
DOWNLOAD_URL=$(curl -fsSL https://api.github.com/repos/ExpressionEngine/ExpressionEngine/releases/latest | docker run -i --rm ddev/ddev-utilities jq -r '.assets | map(select(.name | test("^ExpressionEngine.*\\.zip$")))[0].browser_download_url')
curl -fsSL -o ee.zip "${DOWNLOAD_URL}"
unzip ee.zip && rm -f ee.zip
```

Configure and start DDEV:

```
ddev config --database=mysql:8.0
ddev start
```

Launch the installation wizard:

```
ddev launch /admin.php
```

When the installation wizard prompts for database settings, enter `db` for the *DB Server Address*, *DB Name*, *DB Username*, and *DB Password*.

Visit your site.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-ee.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-ee-zip-site && cd my-ee-zip-site
> DOWNLOAD_URL=$(curl -fsSL https://api.github.com/repos/ExpressionEngine/ExpressionEngine/releases/latest | docker run -i --rm ddev/ddev-utilities jq -r '.assets | map(select(.name | test("^ExpressionEngine.*\\.zip$")))[0].browser_download_url')
> curl -fsSL -o ee.zip "${DOWNLOAD_URL}"
> unzip ee.zip && rm -f ee.zip
> ddev config --database=mysql:8.0
> ddev start -y
> ddev launch /admin.php
> EOF
> chmod +x setup-ee.sh
> ./setup-ee.sh
> ```

Follow these steps based on the [ExpressionEngine Git Repository README.md](<https://github.com/ExpressionEngine/ExpressionEngine#how-to-install>):

Create the project directory and clone the repository:

```
mkdir -p my-ee-git-site && cd my-ee-git-site
git clone https://github.com/ExpressionEngine/ExpressionEngine .
```

Configure and start DDEV:

```
ddev config --database=mysql:8.0
ddev start
```

Install Composer dependencies and prepare installation:

```
ddev composer install
touch system/user/config/config.php
echo "EE_INSTALL_MODE=TRUE" >.env.php
```

Launch the installation wizard:

```
ddev launch /admin.php
```

When the installation wizard prompts for database settings, enter `db` for the *DB Server Address*, *DB Name*, *DB Username*, and *DB Password*.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-ee-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-ee-git-site && cd my-ee-git-site
> git clone https://github.com/ExpressionEngine/ExpressionEngine .
> ddev config --database=mysql:8.0
> ddev start -y
> ddev composer install
> touch system/user/config/config.php
> echo "EE_INSTALL_MODE=TRUE" >.env.php
> ddev launch /admin.php
> EOF
> chmod +x setup-ee-git.sh
> ./setup-ee-git.sh
> ```

## Generic

The [`webserver_type: generic`](<https://ddev.github.io/ddev/en/stable/users/configuration/config/#webserver_type>) allows you to define your own web server process(es) and exposed ports for projects that don’t use the standard `nginx-fpm` or `apache-fpm` configurations.

> [!TIP]
>
> **Looking for more advanced generic web server examples?**
>
> Check out the [Node.js](<#nodejs>) and [Wagtail](<#wagtail-python-generic>) examples below.
>
> See also the [ddev-frankenphp](<https://github.com/ddev/ddev-frankenphp>) add-on, which uses the `generic` webserver under the hood.

This trivial example demonstrates running PHP’s built-in web server inside DDEV’s web container. The `ddev-webserver` container will not start the default `nginx` or `php-fpm` daemons—the PHP built-in server will handle all requests. You probably wouldn’t find this useful compared to the normal `nginx-fpm` or `apache-fpm` configurations, but it’s offered here as an example of how the `generic` webserver type works.

Create the project directory and configure DDEV:

```
export GENERIC_SITENAME=my-generic-site
mkdir -p ${GENERIC_SITENAME} && cd ${GENERIC_SITENAME}
ddev config --project-type=php
```

Create a sample PHP info page:

```
echo "<?php phpinfo(); ?>" > index.php
```

Configure the web server to run PHP’s built-in server:

```
cat <<'EOF' > .ddev/config.php-server.yaml
webserver_type: generic
web_extra_daemons:
    - name: "php-server"
      command: "php -S 0.0.0.0:8000 -t \"${DDEV_DOCROOT:-.}\""
      directory: /var/www/html
web_extra_exposed_ports:
    - name: "php-server"
      container_port: 8000
      http_port: 80
      https_port: 443
EOF
```

Start DDEV (this may take a minute):

```
ddev start
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-generic.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> export GENERIC_SITENAME=my-generic-site
> mkdir -p ${GENERIC_SITENAME} && cd ${GENERIC_SITENAME}
> ddev config --project-type=php
> echo "<?php phpinfo(); ?>" > index.php
> cat <<'INNEREOF' > .ddev/config.php-server.yaml
> webserver_type: generic
> web_extra_daemons:
>     - name: "php-server"
>       command: "php -S 0.0.0.0:8000 -t \"${DDEV_DOCROOT:-.}\""
>       directory: /var/www/html
> web_extra_exposed_ports:
>     - name: "php-server"
>       container_port: 8000
>       http_port: 80
>       https_port: 443
> INNEREOF
> ddev start -y
> ddev launch
> EOF
> chmod +x setup-generic.sh
> ./setup-generic.sh
> ```

## Grav

Create the project directory and configure DDEV:

```
mkdir -p my-grav-composer-site && cd my-grav-composer-site
ddev config --php-version=8.3 --omit-containers=db
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Grav via Composer:

```
ddev composer create-project getgrav/grav
```

Install the [Admin2](<https://github.com/getgrav/grav-plugin-admin2>) plugin and launch:

```
ddev exec gpm install admin2 -y
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-grav.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-grav-composer-site && cd my-grav-composer-site
> ddev config --php-version=8.3 --omit-containers=db
> ddev start -y
> ddev composer create-project getgrav/grav
> ddev exec gpm install admin2 -y
> ddev launch
> EOF
> chmod +x setup-grav.sh
> ./setup-grav.sh
> ```

Create the project directory and clone Grav:

```
mkdir -p my-grav-git-site && cd my-grav-git-site
git clone -b master https://github.com/getgrav/grav.git .
```

Configure DDEV:

```
ddev config --php-version=8.3 --omit-containers=db
```

Start DDEV (this may take a minute):

```
ddev start
```

Install dependencies and initialize Grav:

```
ddev composer install
ddev exec grav install
```

Install the [Admin2](<https://github.com/getgrav/grav-plugin-admin2>) plugin and launch:

```
ddev exec gpm install admin2 -y
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-grav-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-grav-git-site && cd my-grav-git-site
> git clone -b master https://github.com/getgrav/grav.git .
> ddev config --php-version=8.3 --omit-containers=db
> ddev start -y
> ddev composer install
> ddev exec grav install
> ddev exec gpm install admin2 -y
> ddev launch
> EOF
> chmod +x setup-grav-git.sh
> ./setup-grav-git.sh
> ```

> [!TIP]
>
> **How to update?**
>
> Upgrade Grav core:
>
> ```
> ddev exec gpm selfupgrade -f
> ```
>
> Update plugins and themes:
>
> ```
> ddev exec gpm update -f
> ```

Visit the [Grav Documentation](<https://learn.getgrav.org/17>) for more information about Grav in general and visit [Local Development with DDEV](<https://learn.getgrav.org/17/webservers-hosting/local-development-with-ddev>) for more details about the usage of Grav with DDEV.

## Ibexa DXP

Install [Ibexa DXP](<https://www.ibexa.co>) OSS Edition.

Create the project directory and configure DDEV:

```
mkdir -p my-ibexa-site && cd my-ibexa-site
ddev config --project-type=symfony --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Ibexa via Composer:

```
ddev composer create-project ibexa/oss-skeleton
```

Run Ibexa installation:

```
ddev console ibexa:install --no-interaction
ddev console ibexa:graphql:generate-schema
```

Launch the admin interface:

```
ddev launch /admin/login
```

In the web browser, log into your account using `admin` and `publish`.

Visit [Ibexa documentation](<https://doc.ibexa.co/en/latest/getting_started/install_with_ddev/>) for more cases.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-ibexa.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-ibexa-site && cd my-ibexa-site
> ddev config --project-type=symfony --docroot=public
> ddev start -y
> ddev composer create-project ibexa/oss-skeleton
> ddev console ibexa:install --no-interaction
> ddev console ibexa:graphql:generate-schema
> ddev launch /admin/login
> EOF
> chmod +x setup-ibexa.sh
> ./setup-ibexa.sh
> ```

## Joomla

Create the project directory and download Joomla:

```
mkdir -p my-joomla-site && cd my-joomla-site
curl -fsSL -o joomla.zip "https://www.joomla.org/latest"
unzip joomla.zip && rm -f joomla.zip
```

Configure DDEV:

```
ddev config --project-type=joomla
```

Adjust `php.ini` settings for Joomla:

```
echo "display_errors = off" > .ddev/php/joomla.ini
echo "output_buffering = off" >> .ddev/php/joomla.ini
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Joomla:

```
ddev php installation/joomla.php install --site-name="My Joomla Site" --admin-user="Administrator" --admin-username=admin --admin-password=AdminAdmin1! --admin-email=admin@example.com --db-type=mysql --db-encryption=0 --db-host=db --db-user=db --db-pass="db" --db-name=db --db-prefix=ddev_ --public-folder=""
```

Launch the admin interface (login with `admin` and `AdminAdmin1!`):

```
ddev launch /administrator
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-joomla.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-joomla-site && cd my-joomla-site
> curl -fsSL -o joomla.zip "https://www.joomla.org/latest"
> unzip joomla.zip && rm -f joomla.zip
> ddev config --project-type=joomla
> echo "display_errors = off" > .ddev/php/joomla.ini
> echo "output_buffering = off" >> .ddev/php/joomla.ini
> ddev start -y
> ddev php installation/joomla.php install --site-name="My Joomla Site" --admin-user="Administrator" --admin-username=admin --admin-password=AdminAdmin1! --admin-email=admin@example.com --db-type=mysql --db-encryption=0 --db-host=db --db-user=db --db-pass="db" --db-name=db --db-prefix=ddev_ --public-folder=""
> ddev launch /administrator
> EOF
> chmod +x setup-joomla.sh
> ./setup-joomla.sh
> ```

## Kirby CMS

Start a new [Kirby CMS](<https://getkirby.com>) project or use an existing one.

Create a new Kirby CMS project from the official [Starterkit](<https://github.com/getkirby/starterkit>) using DDEV’s [`composer create-project` command](<https://ddev.github.io/ddev/en/stable/users/usage/commands/#composer>):

Create the project directory and configure DDEV:

```
mkdir -p my-kirby-site && cd my-kirby-site
ddev config --omit-containers=db --webserver-type=apache-fpm
```

Start DDEV (this may take a minute):

```
ddev start
```

Install the Kirby Starterkit:

```
ddev composer create-project getkirby/starterkit
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-kirby.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-kirby-site && cd my-kirby-site
> ddev config --omit-containers=db --webserver-type=apache-fpm
> ddev start -y
> ddev composer create-project getkirby/starterkit
> ddev launch
> EOF
> chmod +x setup-kirby.sh
> ./setup-kirby.sh
> ```

You can start using DDEV with an existing project as well:

Navigate to your existing project directory:

```
cd my-kirby-site
```

Configure DDEV:

```
ddev config --omit-containers=db --webserver-type=apache-fpm
```

Start DDEV (this may take a minute):

```
ddev start
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-kirby-existing.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> cd my-kirby-site
> ddev config --omit-containers=db --webserver-type=apache-fpm
> ddev start -y
> ddev launch
> EOF
> chmod +x setup-kirby-existing.sh
> ./setup-kirby-existing.sh
> ```

> [!TIP]
>
> **Installing Kirby**
>
> Read more about developing your Kirby project with DDEV in our [extensive DDEV guide](<https://getkirby.com/docs/cookbook/setup/ddev>).

## Laravel

Use a new or existing Composer project, or clone a Git repository.

The Laravel project type can be used for [StarterKits](<https://laravel.com/docs/starter-kits>), [Laravel Livewire](<https://livewire.laravel.com/>) and others, as it is used with basic Laravel. DDEV automatically updates or creates the `.env` file with the database information.

Laravel defaults to SQLite, but we use MariaDB to better mimic a production environment:

Create the project directory and configure DDEV:

```
mkdir -p my-laravel-composer-site && cd my-laravel-composer-site
ddev config --project-type=laravel --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Laravel via Composer:

```
ddev composer create-project laravel/laravel
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-laravel.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-laravel-composer-site && cd my-laravel-composer-site
> ddev config --project-type=laravel --docroot=public
> ddev start -y
> ddev composer create-project laravel/laravel
> ddev launch
> EOF
> chmod +x setup-laravel.sh
> ./setup-laravel.sh
> ```

To use the SQLite configuration provided by Laravel:

Create the project directory and configure DDEV:

```
mkdir -p my-laravel-sqlite-site && cd my-laravel-sqlite-site
ddev config --project-type=laravel --docroot=public --omit-containers=db
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Laravel via Composer:

```
ddev composer create-project laravel/laravel
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-laravel-sqlite.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-laravel-sqlite-site && cd my-laravel-sqlite-site
> ddev config --project-type=laravel --docroot=public --omit-containers=db
> ddev start -y
> ddev composer create-project laravel/laravel
> ddev launch
> EOF
> chmod +x setup-laravel-sqlite.sh
> ./setup-laravel-sqlite.sh
> ```

To switch an existing Laravel project to SQLite:

Configure for SQLite and restart:

```
ddev config --project-type=laravel --docroot=public --omit-containers=db
ddev restart
```

Run post-install scripts:

```
ddev composer run-script post-root-package-install
ddev dotenv set .env --db-connection=sqlite
ddev composer run-script post-create-project-cmd
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > switch-laravel-sqlite.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> ddev config --project-type=laravel --docroot=public --omit-containers=db
> ddev restart
> ddev composer run-script post-root-package-install
> ddev dotenv set .env --db-connection=sqlite
> ddev composer run-script post-create-project-cmd
> ddev launch
> EOF
> chmod +x switch-laravel-sqlite.sh
> ./switch-laravel-sqlite.sh
> ```

Create the project directory and configure DDEV:

```
mkdir -p my-laravel-installer-site && cd my-laravel-installer-site
ddev config --project-type=laravel --docroot=public
# For SQLite instead, use:
# ddev config --project-type=laravel --docroot=public --omit-containers=db
```

Create Dockerfile to add Laravel installer:

```
cat <<'DOCKERFILEEND' >.ddev/web-build/Dockerfile.laravel
ARG COMPOSER_HOME=/usr/local/composer
RUN composer global require laravel/installer
RUN ln -s $COMPOSER_HOME/vendor/bin/laravel /usr/local/bin/laravel
DOCKERFILEEND
```

Start DDEV (this may take a minute):

```
ddev start
```

Run Laravel installer (follow prompts and select starter kit):

```
ddev exec laravel new temp --database=sqlite
# SQLite is used here as other database types would fail due to
# the .env file not being ready, which DDEV will fix on 'ddev restart'
```

Move files and clean up:

```
ddev exec 'rsync -rltgopD temp/ ./ && rm -rf temp'
rm -f .ddev/web-build/Dockerfile.laravel .env
```

Restart and finalize:

```
ddev restart
ddev composer run-script post-root-package-install
ddev composer run-script post-create-project-cmd
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-laravel-installer.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-laravel-installer-site && cd my-laravel-installer-site
> ddev config --project-type=laravel --docroot=public
>
> cat <<'INNEREOF' >.ddev/web-build/Dockerfile.laravel
> ARG COMPOSER_HOME=/usr/local/composer
> RUN composer global require laravel/installer
> RUN ln -s $COMPOSER_HOME/vendor/bin/laravel /usr/local/bin/laravel
> INNEREOF
>
> ddev start -y
> ddev exec laravel new temp --database=sqlite
> ddev exec 'rsync -rltgopD temp/ ./ && rm -rf temp'
> rm -f .ddev/web-build/Dockerfile.laravel .env
> ddev restart
> ddev composer run-script post-root-package-install
> ddev composer run-script post-create-project-cmd
> ddev launch
> EOF
> chmod +x setup-laravel-installer.sh
> ./setup-laravel-installer.sh
> ```

Clone your Laravel repository:

```
git clone <my-laravel-repo> my-laravel-git-site
cd my-laravel-git-site
```

Configure and start DDEV:

```
ddev config --project-type=laravel --docroot=public
ddev start
```

Install dependencies and run post-install scripts:

```
ddev composer install
ddev composer run-script post-root-package-install
ddev composer run-script post-create-project-cmd
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-laravel-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> git clone <my-laravel-repo> my-laravel-git-site
> cd my-laravel-git-site
> ddev config --project-type=laravel --docroot=public
> ddev start -y
> ddev composer install
> ddev composer run-script post-root-package-install
> ddev composer run-script post-create-project-cmd
> ddev launch
> EOF
> chmod +x setup-laravel-git.sh
> ./setup-laravel-git.sh
> ```

> [!TIP]
>
> **Add Vite support?**
>
> Since Laravel v9.19, Vite is included as the default [asset bundler](<https://laravel.com/docs/vite>). See the [Vite Integration](<https://ddev.github.io/ddev/en/stable/users/usage/vite/#laravel>) documentation for complete setup instructions.

## Magento 2

Normal details of a Composer build for Magento 2 are on the [Magento 2 site](<https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/composer.html>). You must have a public and private key to install from Magento’s repository. When prompted for “username” and “password” in `composer create-project`, it’s asking for your public key as “username” and private key as “password”.

> [!TIP]
>
> **Store Adobe/Magento Composer credentials in the global DDEV config**
>
> If you have Composer installed on your workstation and have an `auth.json` you can reuse the `auth.json` by making a symlink. See the example in [Composer Authentication](<https://ddev.github.io/ddev/en/stable/users/extend/in-container-configuration/#composer-authentication>).
>
> Alternately, you can install the Adobe/Magento Composer credentials in your global `$HOME/.ddev/homeadditions/.composer/auth.json` and never have to enter them again (see below):
>
> **Script to store Adobe/Magento Composer credentials (click me)**
>
> ```
> # Enter your username/password and agree to store your credentials
> ddev_dir="$(ddev version -j | docker run -i --rm ddev/ddev-utilities jq -r ".raw.\"global-ddev-dir\" | select (.!=null) // \"$HOME/.ddev\"" 2>/dev/null)"
> mkdir -p $ddev_dir/homeadditions/.composer
> docker_command=("docker" "run" "-it" "--rm" "-v" "$ddev_dir/homeadditions/.composer:/composer" "--workdir=/tmp" "-e" "COMPOSER_HOME=/composer" "--user" "$(id -u):$(id -g)")
> auth_json_path="$ddev_dir/homeadditions/.composer/auth.json"
> if [ -L "$auth_json_path" ]; then
>     # If auth.json is a symlink, add the optional mount
>     auth_json_dir=$(dirname "$(readlink -f "$auth_json_path")")
>     docker_command+=("-v" "$auth_json_dir:$auth_json_dir")
> fi
> image="$(ddev version -j | docker run -i --rm ddev/ddev-utilities jq -r ".raw.web | select (.!=null)" 2>/dev/null)"
> docker_command+=("$image" "bash" "-c" "composer create-project --repository https://repo.magento.com/ magento/project-community-edition --no-install")
> # Execute the command to store credentials
> "${docker_command[@]}"
> ```

Create the project directory and configure DDEV:

```
export MAGENTO_HOSTNAME=my-magento2-site
mkdir -p ${MAGENTO_HOSTNAME} && cd ${MAGENTO_HOSTNAME}
ddev config --project-type=magento2 --docroot=pub --upload-dirs=media --disable-settings-management
ddev add-on get ddev/ddev-opensearch
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Magento via Composer:

```
ddev composer create-project --repository https://repo.magento.com/ magento/project-community-edition
rm -f app/etc/env.php
```

Run Magento setup:

```
ddev magento setup:install --base-url="https://${MAGENTO_HOSTNAME}.ddev.site/" \
    --cleanup-database --db-host=db --db-name=db --db-user=db --db-password=db \
    --opensearch-host=opensearch --search-engine=opensearch --opensearch-port=9200 \
    --admin-firstname=Magento --admin-lastname=User --admin-email=user@example.com \
    --admin-user=admin --admin-password=Password123 --language=en_US
```

Configure Magento and launch:

```
ddev magento deploy:mode:set developer
ddev magento module:disable Magento_TwoFactorAuth Magento_AdminAdobeImsTwoFactorAuth
ddev config --disable-settings-management=false
# Change the backend frontname URL to /admin_ddev
ddev magento setup:config:set --backend-frontname="admin_ddev" --no-interaction
# Login using `admin` user and `Password123` password
ddev launch /admin_ddev
```

Change the admin name and related information as needed.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-magento.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> export MAGENTO_HOSTNAME=my-magento2-site
> mkdir -p ${MAGENTO_HOSTNAME} && cd ${MAGENTO_HOSTNAME}
> ddev config --project-type=magento2 --docroot=pub --upload-dirs=media --disable-settings-management
> ddev add-on get ddev/ddev-opensearch
> ddev start -y
> ddev composer create-project --repository https://repo.magento.com/ magento/project-community-edition
> rm -f app/etc/env.php
> ddev magento setup:install --base-url="https://${MAGENTO_HOSTNAME}.ddev.site/" \
>     --cleanup-database --db-host=db --db-name=db --db-user=db --db-password=db \
>     --opensearch-host=opensearch --search-engine=opensearch --opensearch-port=9200 \
>     --admin-firstname=Magento --admin-lastname=User --admin-email=user@example.com \
>     --admin-user=admin --admin-password=Password123 --language=en_US
> ddev magento deploy:mode:set developer
> ddev magento module:disable Magento_TwoFactorAuth Magento_AdminAdobeImsTwoFactorAuth
> ddev config --disable-settings-management=false
> ddev magento setup:config:set --backend-frontname="admin_ddev" --no-interaction
> ddev launch /admin_ddev
> EOF
> chmod +x setup-magento.sh
> ./setup-magento.sh
> ```

The admin login URL is specified by `frontName` in `app/etc/env.php`.

You may want to add the [Magento 2 Sample Data](<https://experienceleague.adobe.com/docs/commerce-operations/installation-guide/next-steps/sample-data/composer-packages.html>) with:

```
ddev magento sampledata:deploy
ddev magento setup:upgrade
```

## Maho

You can start a new [Maho](<https://mahocommerce.com>) project or configure an existing one. Maho is an e-commerce platform derived from Magento 1, with modern PHP support and no external service requirements: it needs only a web server, PHP and a database.

DDEV automatically creates `app/etc/local.xml` with the database connection details, so importing an existing site is just `ddev import-db` and `ddev import-files` away. For a fresh installation the Maho installer needs `--force` to take over that pre-created file.

Create the project directory and configure DDEV:

```
mkdir -p my-maho-site && cd my-maho-site
ddev config --project-type=maho --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Maho via Composer:

```
ddev composer create-project mahocommerce/maho-starter
```

Run the Maho installer with sample data:

```
ddev maho install --force \
  --license_agreement_accepted yes \
  --locale en_US --timezone UTC --default_currency USD \
  --db_host db --db_name db --db_user db --db_pass db \
  --url "$(ddev exec echo '$DDEV_PRIMARY_URL')" \
  --use_secure 1 --secure_base_url "$(ddev exec echo '$DDEV_PRIMARY_URL')" --use_secure_admin 1 \
  --admin_firstname Store --admin_lastname Admin --admin_email admin@example.com \
  --admin_username admin --admin_password veryl0ngpassw0rd \
  --sample_data 1
```

Re-index and flush the cache:

```
ddev maho index:reindex:all && ddev maho cache:flush
```

Launch the admin interface (login with `admin` and `veryl0ngpassw0rd`):

```
ddev launch /admin
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-maho.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-maho-site && cd my-maho-site
> ddev config --project-type=maho --docroot=public
> ddev start -y
> ddev composer create-project mahocommerce/maho-starter
> ddev maho install --force \
>   --license_agreement_accepted yes \
>   --locale en_US --timezone UTC --default_currency USD \
>   --db_host db --db_name db --db_user db --db_pass db \
>   --url "$(ddev exec echo '$DDEV_PRIMARY_URL')" \
>   --use_secure 1 --secure_base_url "$(ddev exec echo '$DDEV_PRIMARY_URL')" --use_secure_admin 1 \
>   --admin_firstname Store --admin_lastname Admin --admin_email admin@example.com \
>   --admin_username admin --admin_password veryl0ngpassw0rd \
>   --sample_data 1
> ddev maho index:reindex:all && ddev maho cache:flush
> ddev launch /admin
> EOF
> chmod +x setup-maho.sh
> ./setup-maho.sh
> ```

> [!WARNING]
>
> **For contributing to Maho core only**
>
> This setup is only for contributing to Maho itself. Never build a store on a clone of the core repository — use the Composer setup instead.

Create the project directory and clone the repository:

```
mkdir -p maho && cd maho
git clone https://github.com/MahoCommerce/maho .
```

Configure and start DDEV:

```
ddev config --project-type=maho --docroot=public
ddev start
```

Install Composer dependencies:

```
ddev composer install
```

Run the Maho installer with sample data:

```
ddev maho install --force \
  --license_agreement_accepted yes \
  --locale en_US --timezone UTC --default_currency USD \
  --db_host db --db_name db --db_user db --db_pass db \
  --url "$(ddev exec echo '$DDEV_PRIMARY_URL')" \
  --use_secure 1 --secure_base_url "$(ddev exec echo '$DDEV_PRIMARY_URL')" --use_secure_admin 1 \
  --admin_firstname Store --admin_lastname Admin --admin_email admin@example.com \
  --admin_username admin --admin_password veryl0ngpassw0rd \
  --sample_data 1
```

Re-index and flush the cache:

```
ddev maho index:reindex:all && ddev maho cache:flush
```

Launch the admin interface (login with `admin` and `veryl0ngpassw0rd`):

```
ddev launch /admin
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-maho-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p maho && cd maho
> git clone https://github.com/MahoCommerce/maho .
> ddev config --project-type=maho --docroot=public
> ddev start -y
> ddev composer install
> ddev maho install --force \
>   --license_agreement_accepted yes \
>   --locale en_US --timezone UTC --default_currency USD \
>   --db_host db --db_name db --db_user db --db_pass db \
>   --url "$(ddev exec echo '$DDEV_PRIMARY_URL')" \
>   --use_secure 1 --secure_base_url "$(ddev exec echo '$DDEV_PRIMARY_URL')" --use_secure_admin 1 \
>   --admin_firstname Store --admin_lastname Admin --admin_email admin@example.com \
>   --admin_username admin --admin_password veryl0ngpassw0rd \
>   --sample_data 1
> ddev maho index:reindex:all && ddev maho cache:flush
> ddev launch /admin
> EOF
> chmod +x setup-maho-git.sh
> ./setup-maho-git.sh
> ```

## MODX Revolution

DDEV supports both [MODX](<https://modx.com/>) Revolution 2.x and 3.x.

Create the project directory and configure DDEV:

```
mkdir -p my-modx-site && cd my-modx-site
ddev config --project-type=modx
```

Start DDEV (this may take a minute):

```
ddev start
```

Install MODX Revolution via Composer:

```
ddev composer create-project modx/revolution
```

Create the project directory:

```
mkdir -p my-modx-site && cd my-modx-site
```

Download the latest MODX Revolution release and extract it. The archive extracts into a versioned subdirectory, so move its contents up to the project root:

```
MODX_VERSION=$(curl -fsSL https://api.github.com/repos/modxcms/revolution/tags | grep -o '"v[0-9][0-9.]*-pl"' | head -1 | tr -dc '0-9.')
curl -fLo modx.zip "https://modx.s3.amazonaws.com/releases/${MODX_VERSION}/modx-${MODX_VERSION}-pl.zip"
unzip -q modx.zip && rm -f modx.zip
(shopt -s dotglob && mv "modx-${MODX_VERSION}-pl"/* .) && rmdir "modx-${MODX_VERSION}-pl"
```

Set `MODX_VERSION` yourself to install a specific release, for example `MODX_VERSION=2.8.9` for MODX Revolution 2.x. Releases are also listed on [modx.com](<https://modx.com/download>).

Configure and start DDEV:

```
ddev config --project-type=modx
ddev start
```

DDEV generates a `#ddev-generated` `core/config/config.inc.php` with the DDEV database credentials (database name, user, and password are all `db`; host is `db`). Install MODX with the CLI installer, which performs a fresh install using those credentials:

```
ddev php setup/cli-install.php \
  --database_server=db --database=db --database_user=db --database_password=db \
  --table_prefix=modx_ --http_host=my-modx-site.ddev.site \
  --cmsadmin=admin --cmspassword=Admin123! --cmsadminemail=admin@example.com --language=en \
  --context_mgr_path=/var/www/html/manager/ --context_mgr_url=/manager/ \
  --context_connectors_path=/var/www/html/connectors/ --context_connectors_url=/connectors/
```

The four `--context_*` arguments are the installer’s own defaults. Passing them explicitly keeps the install non-interactive; leave them out and the installer stops to ask for each one.

Launch the manager (log in with `admin` / `Admin123!`):

```
ddev launch /manager/
```

> [!NOTE]
>
> **Web installer and the DDEV-managed config**
>
> You can also install through the web wizard with `ddev launch /setup/`. Because DDEV has already written a valid `core/config/config.inc.php`, MODX opens the web wizard in *upgrade* mode; for a brand-new site use the CLI installer above (or remove `core/config/config.inc.php` before opening `/setup/`). When you import an existing MODX site and its database (for example with [`ddev import-db`](<https://ddev.github.io/ddev/en/stable/users/usage/commands/#import-db>)), the DDEV-generated `config.inc.php` connects it straight away with no installer step.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-modx.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-modx-site && cd my-modx-site
> ddev config --project-type=modx
> ddev start -y
> ddev composer create-project modx/revolution
> ddev php setup/cli-install.php \
>   --database_server=db --database=db --database_user=db --database_password=db \
>   --table_prefix=modx_ --http_host=my-modx-site.ddev.site \
>   --cmsadmin=admin --cmspassword=Admin123! --cmsadminemail=admin@example.com --language=en \
>   --context_mgr_path=/var/www/html/manager/ --context_mgr_url=/manager/ \
>   --context_connectors_path=/var/www/html/connectors/ --context_connectors_url=/connectors/
> ddev launch /manager/
> EOF
> chmod +x setup-modx.sh
> ./setup-modx.sh
> ```

## Moodle

Create the project directory and configure DDEV:

```
mkdir -p my-moodle-site && cd my-moodle-site
ddev config --docroot=public --webserver-type=apache-fpm
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Moodle via Composer:

```
ddev composer create-project moodle/moodle
```

Run Moodle installation:

```
ddev exec 'php admin/cli/install.php --non-interactive --agree-license --wwwroot=$DDEV_PRIMARY_URL --dbtype=mariadb --dbhost=db --dbname=db --dbuser=db --dbpass=db --fullname="DDEV Moodle Demo" --shortname=Demo --adminemail=admin@example.com --adminpass=password'
```

Launch Moodle (login with `admin` and `password`)::

```
ddev launch /login
```

Visit the [Moodle Admin Quick Guide](<https://docs.moodle.org/400/en/Admin_quick_guide>) for more information.

> [!TIP]
>
> Moodle relies on a periodic cron job—don’t forget to set that up! See [ddev/ddev-cron](<https://github.com/ddev/ddev-cron>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-moodle.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-moodle-site && cd my-moodle-site
> ddev config --docroot=public --webserver-type=apache-fpm
> ddev start -y
> ddev composer create-project moodle/moodle
> ddev exec 'php admin/cli/install.php --non-interactive --agree-license --wwwroot=$DDEV_PRIMARY_URL --dbtype=mariadb --dbhost=db --dbname=db --dbuser=db --dbpass=db --fullname="DDEV Moodle Demo" --shortname=Demo --adminemail=admin@example.com --adminpass=password'
> ddev launch /login
> EOF
> chmod +x setup-moodle.sh
> ./setup-moodle.sh
> ```

## Node.js

This example installation sets up the SvelteKit demo in DDEV with the `generic` webserver.

Node.js support as in this example is experimental, and your suggestions and improvements are welcome.

```
export SVELTEKIT_SITENAME=my-sveltekit-site
mkdir -p ${SVELTEKIT_SITENAME} && cd ${SVELTEKIT_SITENAME}
ddev config --project-type=generic --webserver-type=generic
ddev start

cat <<EOF > .ddev/config.sveltekit.yaml
web_extra_exposed_ports:
    - name: svelte
      container_port: 3000
      http_port: 80
      https_port: 443
web_extra_daemons:
    - name: "sveltekit-demo"
      command: "node build"
      directory: /var/www/html
EOF

# When it prompts "Directory not empty. Continue?", choose Yes
ddev exec "npx sv create --template=demo --types=ts --no-add-ons --no-install ."

# Use adapter-node, and set the port and allowed hosts in vite.config.ts
ddev exec "sed -i -e 's#adapter-auto#adapter-node#' -e 's#^export default defineConfig({#&\n\tserver: { port: 3000, allowedHosts: true },#' vite.config.ts"
ddev npm install @sveltejs/adapter-node
ddev npm install
ddev npm run build
ddev restart
ddev launch
```

SvelteKit requires just a bit of configuration to make it run. There are many ways to make any Node.js site work, these are just examples. SvelteKit 3 no longer uses `svelte.config.js`; its configuration is passed to the `sveltekit()` plugin in `vite.config.ts`, which can be adapted in many ways. For more Vite configuration options, see the [Vite Integration](<https://ddev.github.io/ddev/en/stable/users/usage/vite/index.md>) documentation.

- The `sed` command switches the adapter from `adapter-auto` to `adapter-node`.
- It also sets `server.port` to 3000 and `server.allowedHosts` to `true` in `vite.config.ts`.

```
export NODEJS_SITENAME=my-nodejs-site
mkdir -p ${NODEJS_SITENAME} && cd ${NODEJS_SITENAME}
ddev config --project-type=generic --webserver-type=generic
ddev start
ddev npm install express

cat <<EOF > .ddev/config.nodejs.yaml
web_extra_exposed_ports:
    - name: node-example
      container_port: 3000
      http_port: 80
      https_port: 443

web_extra_daemons:
    - name: "node-example"
      command: "node server.js"
      directory: /var/www/html
EOF

ddev exec curl -fsSLO https://raw.githubusercontent.com/ddev/test-nodejs/main/server.js
ddev restart
ddev launch
```

The [`server.js`](<https://github.com/ddev/test-nodejs/blob/main/server.js>) used here is a trivial Express-based Node.js webserver. Yours will be more extensive.

## OpenMage

Visit [OpenMage Docs](<https://docs.openmage.org>) for more installation details.

Create the project directory and configure DDEV:

```
mkdir -p my-openmage-composer-site && cd my-openmage-composer-site
ddev config --project-type=magento --docroot=public_test --php-version=8.3 --web-environment-add=MAGE_IS_DEVELOPER_MODE=1
```

Start DDEV (this may take a minute):

```
ddev start
```

Initialize and configure Composer:

```
ddev composer init --name "openmage/composer-test" --description "OpenMage starter project" --type "project" -l "OSL-3.0" -s "dev" -q
ddev composer config prefer-stable true
ddev composer config policy.advisories.block false
ddev composer config extra.magento-root-dir "public_test"
ddev composer config extra.magento-core-package-type "magento-source"
ddev composer config allow-plugins.vaimo/composer-patches true
ddev composer config allow-plugins.magento-hackathon/magento-composer-installer true
ddev composer config allow-plugins.aydin-hassan/magento-core-composer-installer true
ddev composer config allow-plugins.openmage/composer-plugin true
ddev composer require --no-update "aydin-hassan/magento-core-composer-installer":"^2.1.0" "openmage/magento-lts":"^20.19"
```

Download the OpenMage install command and install dependencies:

```
ddev exec wget -O .ddev/commands/web/openmage-install https://raw.githubusercontent.com/OpenMage/magento-lts/refs/heads/main/.ddev/commands/web/openmage-install
ddev composer install
```

Run OpenMage silent installation with sample data:

```
ddev openmage-install -q
```

Launch the admin interface (login with `admin` and `veryl0ngpassw0rd`):

```
ddev launch /admin
```

> [!NOTE]
>
> **Make sure that `docroot` is set correctly**
>
> DDEV config `--docroot` has to match Composer config `extra.magento-root-dir`.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-openmage.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-openmage-composer-site && cd my-openmage-composer-site
> ddev config --project-type=magento --docroot=public_test --php-version=8.3 --web-environment-add=MAGE_IS_DEVELOPER_MODE=1
> ddev start -y
> ddev composer init --name "openmage/composer-test" --description "OpenMage starter project" --type "project" -l "OSL-3.0" -s "dev" -q
> ddev composer config prefer-stable true
> ddev composer config policy.advisories.block false
> ddev composer config extra.magento-root-dir "public_test"
> ddev composer config extra.magento-core-package-type "magento-source"
> ddev composer config allow-plugins.vaimo/composer-patches true
> ddev composer config allow-plugins.magento-hackathon/magento-composer-installer true
> ddev composer config allow-plugins.aydin-hassan/magento-core-composer-installer true
> ddev composer config allow-plugins.openmage/composer-plugin true
> ddev composer require --no-update "aydin-hassan/magento-core-composer-installer":"^2.1.0" "openmage/magento-lts":"^20.19"
> ddev exec wget -O .ddev/commands/web/openmage-install https://raw.githubusercontent.com/OpenMage/magento-lts/refs/heads/main/.ddev/commands/web/openmage-install
> ddev composer install
> ddev openmage-install -q
> ddev launch /admin
> EOF
> chmod +x setup-openmage.sh
> ./setup-openmage.sh
> ```

Create the project directory and clone the repository:

```
mkdir -p my-openmage-git-site && cd my-openmage-git-site
git clone https://github.com/OpenMage/magento-lts .
```

Configure and start DDEV:

```
ddev config --project-type=magento --php-version=8.3 --web-environment-add=MAGE_IS_DEVELOPER_MODE=1
ddev start
```

Install Composer dependencies:

```
ddev composer install
```

Run OpenMage silent installation with sample data:

```
ddev openmage-install -q
```

Launch the admin interface (login with `admin` and `veryl0ngpassw0rd`):

```
ddev launch /admin
```

Note that OpenMage itself provides several custom DDEV commands, including `openmage-install`, `openmage-admin`, `phpmd`, `rector`, `phpcbf`, `phpstan`, `vendor-patches`, and `php-cs-fixer`.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-openmage-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-openmage-git-site && cd my-openmage-git-site
> git clone https://github.com/OpenMage/magento-lts .
> ddev config --project-type=magento --php-version=8.3 --web-environment-add=MAGE_IS_DEVELOPER_MODE=1
> ddev start -y
> ddev composer install
> ddev openmage-install -q
> ddev launch /admin
> EOF
> chmod +x setup-openmage-git.sh
> ./setup-openmage-git.sh
> ```

## October CMS

Start a new [October CMS](<https://octobercms.com>) project or configure an existing one.

October CMS is built on Laravel, so it uses the `laravel` project type. DDEV automatically updates or creates the `.env` file with the database information.

Create the project directory and configure DDEV:

```
mkdir -p my-october-site && cd my-october-site
ddev config --project-type=laravel --webserver-type=apache-fpm
```

Start DDEV (this may take a minute):

```
ddev start
```

Install October CMS via Composer:

```
ddev composer create-project october/october
```

Run the installer:

```
ddev artisan october:install --no-interaction
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-october.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-october-site && cd my-october-site
> ddev config --project-type=laravel --webserver-type=apache-fpm
> ddev start -y
> ddev composer create-project october/october
> ddev artisan october:install --no-interaction
> ddev launch
> EOF
> chmod +x setup-october.sh
> ./setup-october.sh
> ```

You can start using DDEV with an existing October CMS project too — but make sure you have a database backup handy!

Clone the repository (or navigate to a local project directory):

```
git clone <my-october-repo> my-october-site
cd my-october-site
```

Configure DDEV:

```
ddev config --project-type=laravel --webserver-type=apache-fpm
```

Start DDEV and install dependencies:

```
ddev start
ddev composer install
```

Import your database and run migrations:

```
ddev import-db --file=/path/to/db.sql.gz
ddev artisan october:migrate
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-october-existing.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> git clone <my-october-repo> my-october-site
> cd my-october-site
> ddev config --project-type=laravel --webserver-type=apache-fpm
> ddev start -y
> ddev composer install
> ddev import-db --file=/path/to/db.sql.gz
> ddev artisan october:migrate
> ddev launch
> EOF
> chmod +x setup-october-existing.sh
> ./setup-october-existing.sh
> ```

> [!TIP]
>
> **Installing October CMS**
>
> Read more about installing October CMS in the [official documentation](<https://docs.octobercms.com/3.x/setup/installation.html>).

## Pimcore

Using the [Pimcore skeleton](<https://github.com/pimcore/skeleton>) repository:

Create the project directory and configure DDEV:

```
mkdir -p my-pimcore-site && cd my-pimcore-site
ddev config --project-type=php --docroot=public --webimage-extra-packages='php${DDEV_PHP_VERSION}-amqp'
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Pimcore via Composer:

```
ddev composer create-project pimcore/skeleton
```

Run Pimcore installation:

```
ddev exec pimcore-install \
    --mysql-username=db \
    --mysql-password=db \
    --mysql-host-socket=db \
    --mysql-database=db \
    --admin-password=admin \
    --admin-username=admin
```

Create consumer daemon configuration:

```
echo "web_extra_daemons:
  - name: consumer
    command: 'while true; do /var/www/html/bin/console messenger:consume pimcore_core pimcore_maintenance pimcore_scheduled_tasks pimcore_image_optimize pimcore_asset_update --memory-limit=250M --time-limit=3600; done'
    directory: /var/www/html" >.ddev/config.pimcore.yaml
```

Restart and launch:

```
ddev restart
ddev launch /admin
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-pimcore.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-pimcore-site && cd my-pimcore-site
> ddev config --project-type=php --docroot=public --webimage-extra-packages='php${DDEV_PHP_VERSION}-amqp'
> ddev start -y
> ddev composer create-project pimcore/skeleton
> ddev exec pimcore-install \
>     --mysql-username=db \
>     --mysql-password=db \
>     --mysql-host-socket=db \
>     --mysql-database=db \
>     --admin-password=admin \
>     --admin-username=admin
> echo "web_extra_daemons:
>   - name: consumer
>     command: 'while true; do /var/www/html/bin/console messenger:consume pimcore_core pimcore_maintenance pimcore_scheduled_tasks pimcore_image_optimize pimcore_asset_update --memory-limit=250M --time-limit=3600; done'
>     directory: /var/www/html" >.ddev/config.pimcore.yaml
> ddev restart
> ddev launch /admin
> EOF
> chmod +x setup-pimcore.sh
> ./setup-pimcore.sh
> ```

## ProcessWire

To get started with [ProcessWire](<https://processwire.com/>), create a new directory and use the ZIP file download, composer, or Git checkout to build. These instructions are adapted from [ProcessWire Install Documentation](<https://processwire.com/docs/start/install/new/#installing-processwire>).

Create the project directory:

```
mkdir -p my-processwire-zip-site && cd my-processwire-zip-site
```

Download and extract ProcessWire:

```
curl -LJOf https://github.com/processwire/processwire/archive/master.zip
unzip processwire-master.zip && rm -f processwire-master.zip
cp -R processwire-master/. . && rm -rf processwire-master
```

Configure and start DDEV:

```
ddev config --project-type=php --webserver-type=apache-fpm
ddev start
```

Launch ProcessWire:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-processwire-zip.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-processwire-zip-site && cd my-processwire-zip-site
> curl -LJOf https://github.com/processwire/processwire/archive/master.zip
> unzip processwire-master.zip && rm -f processwire-master.zip
> cp -R processwire-master/. . && rm -rf processwire-master
> ddev config --project-type=php --webserver-type=apache-fpm
> ddev start -y
> ddev launch
> EOF
> chmod +x setup-processwire-zip.sh
> ./setup-processwire-zip.sh
> ```

Create the project directory and configure DDEV:

```
mkdir -p my-processwire-composer-site && cd my-processwire-composer-site
ddev config --project-type=php --webserver-type=apache-fpm
```

Start DDEV (this may take a minute):

```
ddev start
```

Install ProcessWire via Composer:

```
ddev composer create-project "processwire/processwire:^3"
```

Launch ProcessWire:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-processwire.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-processwire-composer-site && cd my-processwire-composer-site
> ddev config --project-type=php --webserver-type=apache-fpm
> ddev start -y
> ddev composer create-project "processwire/processwire:^3"
> ddev launch
> EOF
> chmod +x setup-processwire.sh
> ./setup-processwire.sh
> ```

Create the project directory:

```
mkdir -p my-processwire-git-site && cd my-processwire-git-site
```

Clone ProcessWire (main branch for stable release):

```
git clone https://github.com/processwire/processwire.git .
# For latest features, use dev branch instead:
# git clone -b dev https://github.com/processwire/processwire.git .
```

Configure and start DDEV:

```
ddev config --webserver-type=apache-fpm
ddev start
```

Launch ProcessWire:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-processwire-git.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-processwire-git-site && cd my-processwire-git-site
> git clone https://github.com/processwire/processwire.git .
> ddev config --webserver-type=apache-fpm
> ddev start -y
> ddev launch
> EOF
> chmod +x setup-processwire-git.sh
> ./setup-processwire-git.sh
> ```

When the installation wizard prompts for database settings, enter:

- `DB Name` = `db`
- `DB User` = `db`
- `DB Pass` = `db`
- `DB Host` = `db` (**not** `localhost`!)
- `DB Charset` = `utf8mb4`
- `DB Engine` = `InnoDB`

If you get a warning about “Apache mod\_rewrite” during the compatibility check, Click “refresh”.

**After installation,** configure `upload_dirs` to specify where user-generated files are managed by Processwire:

```
ddev config --upload-dirs=sites/assets/files && ddev restart
```

## Shopware

Though you can set up a Shopware 6 environment many ways, we recommend the following technique. DDEV creates a `.env.local` file for you by default; if you already have one DDEV adds necessary information to it. When `ddev composer create-project` asks if you want to include Docker configuration, answer `x`, as this approach does not use their Docker configuration.

Create the project directory and configure DDEV:

```
mkdir -p my-shopware-site && cd my-shopware-site
ddev config --project-type=shopware6 --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Shopware via Composer:

```
ddev composer create-project shopware/production
# If it asks `Do you want to include Docker configuration from recipes?`
# answer `x`, as we're using DDEV for this rather than its recipes.
```

Run Shopware installation and launch:

```
ddev console system:install --basic-setup
ddev launch /admin
# Default username and password are `admin` and `shopware`
```

Log into the admin site (`/admin`) using the web browser. The default credentials are username `admin` and password `shopware`. You can use the web UI to install sample data or accomplish many other tasks.

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-shopware.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-shopware-site && cd my-shopware-site
> ddev config --project-type=shopware6 --docroot=public
> ddev start -y
> # Answer `x` to "Do you want to include Docker configuration from recipes?"
> # so Shopware's Docker recipe is not added (DDEV provides the environment).
> printf "x\n" | ddev composer create-project shopware/production
> ddev console system:install --basic-setup
> ddev launch /admin
> EOF
> chmod +x setup-shopware.sh
> ./setup-shopware.sh
> ```

For more advanced tasks, such as

- setting up workers and the scheduler as automated tasks,
- installing additional services like RabbitMQ, or
- mirroring production media through an nginx proxy,

see [notebook.vanwittlaer.de](<https://notebook.vanwittlaer.de/ddev-for-shopware/>).

### shopware-cli and hot-reload watchers

For `shopware6` projects, DDEV bundles the [`shopware-cli`](<https://github.com/shopware/shopware-cli>) tool and hot-reload watcher commands automatically, with no add-on required. The `shopware-cli` binary is baked into the web image, and these commands become available:

- `ddev shopware-cli` — run `shopware-cli` inside the web container
- `ddev storefront-watch` — hot-reload the storefront (proxy on port 9998)
- `ddev admin-watch <plugin-dir>` — hot-reload a plugin’s administration (Vite, port 5173)

Reach the watchers through your project’s primary URL with the relevant port, for example `https://my-shopware-site.ddev.site:9998` for the storefront, not `localhost`.

> [!NOTE]
>
> **Requires Shopware 6.7.4.2 or newer**
>
> The bundled watchers target the Vite-based administration (port 5173) introduced in Shopware 6.7.4.2. Older Shopware versions use a different watcher setup.

## Silverstripe CMS

Use a new or existing Composer project, or clone a Git repository.

Create the project directory and configure DDEV:

```
mkdir -p my-silverstripe-composer-site && cd my-silverstripe-composer-site
ddev config --project-type=silverstripe --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Silverstripe via Composer:

```
ddev composer create-project --prefer-dist silverstripe/installer
ddev sake dev/build flush=all
```

Launch the admin area:

```
ddev launch /admin
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-silverstripe.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-silverstripe-composer-site && cd my-silverstripe-composer-site
> ddev config --project-type=silverstripe --docroot=public
> ddev start -y
> ddev composer create-project --prefer-dist silverstripe/installer
> ddev sake dev/build flush=all
> ddev launch /admin
> EOF
> chmod +x setup-silverstripe.sh
> ./setup-silverstripe.sh
> ```

```
git clone <my-silverstripe-repo> my-silverstripe-git-site
cd my-silverstripe-git-site
ddev config --project-type=silverstripe --docroot=public
ddev start
ddev composer install
ddev sake dev/build flush=all
```

Your Silverstripe CMS project is now ready. The CMS can be found at `/admin`, log into the default admin account using `admin` and `password`.

Visit the Silverstripe CMS [user documentation](<https://userhelp.silverstripe.org/>) and [developer documentation](<https://docs.silverstripe.org/>) for more information.

`ddev sake` can be used as a shorthand for the Silverstripe CLI command `ddev exec vendor/bin/sake`.

To open the CMS directly from CLI, run `ddev launch /admin`.

## Statamic

Use a new or existing Composer project, or clone a Git repository.

The Laravel project type can be used for [Statamic](<https://statamic.com/>) like it can for Laravel. DDEV automatically updates or creates the `.env` file with the database information.

Create the project directory and configure DDEV:

```
mkdir -p my-statamic-composer-site && cd my-statamic-composer-site
ddev config --project-type=laravel --docroot=public
```

Install Statamic via Composer:

```
ddev composer create-project --prefer-dist statamic/statamic
```

Create admin user and launch:

```
ddev php please make:user admin@example.com --password=admin1234 --super --no-interaction
ddev launch /cp
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-statamic.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-statamic-composer-site && cd my-statamic-composer-site
> ddev config --project-type=laravel --docroot=public
> ddev composer create-project --prefer-dist statamic/statamic
> ddev php please make:user admin@example.com --password=admin1234 --super --no-interaction
> ddev launch /cp
> EOF
> chmod +x setup-statamic.sh
> ./setup-statamic.sh
> ```

```
git clone <my-statamic-repo> my-statamic-git-site
cd my-statamic-git-site
ddev config --project-type=laravel --docroot=public
ddev start
ddev composer install
ddev exec "php artisan key:generate"
ddev launch /cp
```

## Sulu

Create the project directory and configure DDEV:

```
mkdir -p my-sulu-site && cd my-sulu-site
ddev config --project-type=php --docroot=public --upload-dirs=uploads --database=mysql:8.0
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Sulu via Composer:

```
ddev composer create-project sulu/skeleton
```

Create your default webspace configuration `mv config/webspaces/website.xml config/webspaces/my-sulu-site.xml` and adjust the values for `<name>` and `<key>` so that they are matching your project:

```
<?xml version="1.0" encoding="utf-8"?>
<webspace xmlns="http://schemas.sulu.io/webspace/webspace"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://schemas.sulu.io/webspace/webspace http://schemas.sulu.io/webspace/webspace-1.1.xsd">
    <!-- See: http://docs.sulu.io/en/latest/book/webspaces.html how to configure your webspace-->

    <name>My Sulu Site</name>
    <key>my-sulu-site</key>
```

Alternatively, use the following commands to adjust the values for `<name>` and `<key>` to match your project setup:

Configure webspace settings:

```
export SULU_PROJECT_NAME="My Sulu Site"
export SULU_PROJECT_KEY="my-sulu-site"
export SULU_PROJECT_CONFIG_FILE="config/webspaces/my-sulu-site.xml"
ddev exec "mv config/webspaces/website.xml ${SULU_PROJECT_CONFIG_FILE}"
ddev exec "sed -i -e 's|<name>.*</name>|<name>${SULU_PROJECT_NAME}</name>|g' -e 's|<key>.*</key>|<key>${SULU_PROJECT_KEY}</key>|g' ${SULU_PROJECT_CONFIG_FILE}"
```

> [!WARNING]
>
> **Caution**
>
> Changing the `<key>` for a webspace later on causes problems. It is recommended to decide on the value for the key before the database is build in the next step.

Build the database with the `dev` argument (adds user `admin` with password `admin`):

```
ddev dotenv set .env.local --app-env=dev --database-url="mysql://db:db@db:3306/db?serverVersion=8.0&charset=utf8mb4"
ddev exec bin/adminconsole sulu:build dev --no-interaction
```

Launch Sulu (login with `admin` and `admin`):

```
ddev launch /admin
```

> [!TIP]
>
> If you don’t want to add an admin user use the `prod` argument instead
>
> ```
> ddev execute bin/adminconsole sulu:build prod
> ```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-sulu.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-sulu-site && cd my-sulu-site
> ddev config --project-type=php --docroot=public --upload-dirs=uploads --database=mysql:8.0
> ddev start -y
> ddev composer create-project sulu/skeleton
> export SULU_PROJECT_NAME="My Sulu Site"
> export SULU_PROJECT_KEY="my-sulu-site"
> export SULU_PROJECT_CONFIG_FILE="config/webspaces/my-sulu-site.xml"
> ddev exec "mv config/webspaces/website.xml ${SULU_PROJECT_CONFIG_FILE}"
> ddev exec "sed -i -e 's|<name>.*</name>|<name>${SULU_PROJECT_NAME}</name>|g' -e 's|<key>.*</key>|<key>${SULU_PROJECT_KEY}</key>|g' ${SULU_PROJECT_CONFIG_FILE}"
> ddev dotenv set .env.local --app-env=dev --database-url="mysql://db:db@db:3306/db?serverVersion=8.0&charset=utf8mb4"
> ddev exec bin/adminconsole sulu:build dev --no-interaction
> ddev launch /admin
> EOF
> chmod +x setup-sulu.sh
> ./setup-sulu.sh
> ```

## Symfony

There are many ways to install Symfony, here are a few of them based on the [Symfony docs](<https://symfony.com/doc/current/setup.html>).

DDEV automatically updates or creates the `.env.local` file with the database information.

Create the project directory and configure DDEV:

```
mkdir -p my-symfony-composer-site && cd my-symfony-composer-site
ddev config --project-type=symfony --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Symfony via Composer, pinned to the current [long-term support (LTS) release](<https://symfony.com/doc/current/setup.html#symfony-lts-versions>):

```
ddev composer create-project symfony/skeleton:"7.4.*"
ddev composer require webapp
# When it asks if you want to include docker configuration, say "no" with "x"
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-symfony.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-symfony-composer-site && cd my-symfony-composer-site
> ddev config --project-type=symfony --docroot=public
> ddev start -y
> ddev composer create-project symfony/skeleton:"7.4.*"
> ddev composer require webapp
> ddev launch
> EOF
> chmod +x setup-symfony.sh
> ./setup-symfony.sh
> ```

```
mkdir -p my-symfony-cli-site && cd my-symfony-cli-site
ddev config --project-type=symfony --docroot=public
ddev start
ddev exec symfony check:requirements
# --version=lts always resolves to the current long-term support release
ddev exec symfony new temp --webapp --version=lts
# 'symfony new' can't install in the current directory right away,
# so we use 'rsync' to move the installed files one level up
ddev exec 'rsync -rltgopD temp/ ./ && rm -rf temp'
ddev launch
```

```
git clone <my-symfony-repo> my-symfony-git-site
cd my-symfony-git-site
ddev config --project-type=symfony --docroot=public
ddev start
ddev composer install
ddev launch
```

> [!TIP]
>
> **Want to run Symfony Console (`bin/console`)?**
>
> ```
> ddev console list
> # ddev console doctrine:schema:update --force
> ```

> [!TIP]
>
> **Consuming Messages (Running the Worker)**
>
> Edit `.ddev/config.yaml` in your project directory and uncomment `post-start` hook to see `messenger:consume` command logs, and run:
>
> ```
> ddev exec symfony server:log
> ```

## Tempest

Create the project directory and configure DDEV:

```
PROJECT_NAME=my-tempest-site
mkdir -p ${PROJECT_NAME} && cd ${PROJECT_NAME}
ddev config --project-type=php --docroot=public --php-version=8.5 --omit-containers=db
```

Start DDEV (this may take a minute):

```
ddev start
```

Install Tempest via Composer:

```
ddev composer create-project tempest/app
```

Launch the site:

```
ddev launch
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-tempest.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> PROJECT_NAME=my-tempest-site
> mkdir -p ${PROJECT_NAME} && cd ${PROJECT_NAME}
> ddev config --project-type=php --docroot=public --php-version=8.5 --omit-containers=db
> ddev start -y
> ddev composer create-project tempest/app
> ddev launch
> EOF
> chmod +x setup-tempest.sh
> ./setup-tempest.sh
> ```

## TYPO3

Create the project directory and configure DDEV:

```
PROJECT_NAME=my-typo3-site
mkdir -p ${PROJECT_NAME} && cd ${PROJECT_NAME}
ddev config --project-type=typo3 --docroot=public
```

Start DDEV (this may take a minute):

```
ddev start
```

Install TYPO3 via Composer:

```
ddev composer create-project "typo3/cms-base-distribution:^14"
```

Install the Camino default theme [recommended for TYPO3 Core](<https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/Installation/Install.html>):

```
ddev composer require typo3/theme-camino
```

Run the TYPO3 setup:

```
ddev typo3 setup \
    --admin-user-password="Demo123*" \
    --driver=mysqli \
    --server-type=other \
    --dbname=db \
    --username=db \
    --password=db \
    --port=3306 \
    --host=db \
    --admin-username=admin \
    --admin-email=admin@example.com \
    --project-name="My TYPO3 site" \
    --force
```

Launch the site content:

```
ddev launch /camino
```

Launch the backend:

```
ddev launch /typo3/
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-typo3.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> PROJECT_NAME=my-typo3-site
> mkdir -p ${PROJECT_NAME} && cd ${PROJECT_NAME}
> ddev config --project-type=typo3 --docroot=public
> ddev start -y
> ddev composer create-project "typo3/cms-base-distribution:^14"
> ddev composer require typo3/theme-camino
> ddev typo3 setup \
>     --admin-user-password="Demo123*" \
>     --driver=mysqli \
>     --server-type=other \
>     --dbname=db \
>     --username=db \
>     --password=db \
>     --port=3306 \
>     --host=db \
>     --admin-username=admin \
>     --admin-email=admin@example.com \
>     --project-name="My TYPO3 site" \
>     --force
> ddev launch /camino
> ddev launch /typo3/
> EOF
> chmod +x setup-typo3.sh
> ./setup-typo3.sh
> ```

This example uses a clone of a test repository, `github.com/ddev/test-typo3.git`. Replace that with your git repository.

```
PROJECT_GIT_URL=https://github.com/ddev/test-typo3.git
PROJECT_NAME=my-typo3-site
mkdir -p ${PROJECT_NAME} && cd ${PROJECT_NAME}
git clone ${PROJECT_GIT_REPOSITORY} .
ddev config --project-type=typo3 --docroot=public
ddev start
ddev composer install
ddev exec touch public/FIRST_INSTALL
ddev launch /typo3/install.php
```

## Wagtail (Python, Generic)

[Wagtail](<https://wagtail.org/>) is a popular, open-source content management system built on the Django web framework. This quickstart installs Wagtail into the web image, as described in [Python Packages from `requirements.txt`](<https://ddev.github.io/ddev/en/stable/users/extend/customizing-images/#python-packages-from-requirementstxt>), and runs the Django development server.

Create the project directory and configure DDEV:

```
export WAGTAIL_SITENAME=my-wagtail-site
mkdir -p ${WAGTAIL_SITENAME} && cd ${WAGTAIL_SITENAME}
ddev config --project-type=generic --webserver-type=generic \
    --webimage-extra-packages=python3-venv \
    --web-environment-add=DJANGO_SETTINGS_MODULE=mysite.settings.dev \
    --omit-containers=db
```

Add a placeholder `requirements.txt` that installs Wagtail so it can create the project, a Django setting to detect HTTPS behind the [Traefik](<https://ddev.github.io/ddev/en/stable/users/extend/traefik-router/index.md>) router, and the DDEV configuration:

```
echo wagtail > requirements.txt
mkdir -p mysite/settings
echo 'SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")' > mysite/settings/local.py
cat <<'EOF' > .ddev/docker-compose.wagtail.yaml
services:
  web:
    build:
      additional_contexts:
        project: ${DDEV_APPROOT}
EOF
cat <<'EOF' > .ddev/web-build/Dockerfile.wagtail
COPY --from=project --chmod=644 requirements.txt /tmp/requirements.txt
RUN install -d -o "$username" /opt/wagtail \
    && runuser -u "$username" -- python3 -m venv /opt/wagtail \
    && runuser -u "$username" -- /opt/wagtail/bin/pip install --no-cache-dir -r /tmp/requirements.txt \
    && echo 'export PATH="/opt/wagtail/bin:$PATH"' > /etc/bashrc/wagtail.bashrc
EOF
cat <<'EOF' > .ddev/config.wagtail.yaml
web_extra_daemons:
    - name: "wagtail"
      command: "python manage.py runserver 0.0.0.0:8000"
      directory: /var/www/html
web_extra_exposed_ports:
    - name: "wagtail"
      container_port: 8000
      http_port: 80
      https_port: 443
EOF
```

Start DDEV (this may take a minute):

```
ddev start
```

Create the Wagtail project, which replaces the placeholder with its own `requirements.txt`:

```
ddev exec "rm -f requirements.txt && wagtail start mysite ."
```

Run database migrations and create a superuser:

```
ddev exec python manage.py migrate --noinput
ddev exec "DJANGO_SUPERUSER_PASSWORD=admin python manage.py createsuperuser --username=admin --email=admin@example.com --noinput"
```

Restart DDEV to rebuild the virtual environment from Wagtail’s `requirements.txt` and start the server:

```
ddev restart
```

Launch the Wagtail admin interface (login with `admin` and `admin`):

```
ddev launch /admin
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-wagtail.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> export WAGTAIL_SITENAME=my-wagtail-site
> mkdir -p ${WAGTAIL_SITENAME} && cd ${WAGTAIL_SITENAME}
> ddev config --project-type=generic --webserver-type=generic \
>     --webimage-extra-packages=python3-venv \
>     --web-environment-add=DJANGO_SETTINGS_MODULE=mysite.settings.dev \
>     --omit-containers=db
> echo wagtail > requirements.txt
> mkdir -p mysite/settings
> echo 'SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")' > mysite/settings/local.py
> cat <<'INNEREOF' > .ddev/docker-compose.wagtail.yaml
> services:
>   web:
>     build:
>       additional_contexts:
>         project: ${DDEV_APPROOT}
> INNEREOF
> cat <<'INNEREOF' > .ddev/web-build/Dockerfile.wagtail
> COPY --from=project --chmod=644 requirements.txt /tmp/requirements.txt
> RUN install -d -o "$username" /opt/wagtail \
>     && runuser -u "$username" -- python3 -m venv /opt/wagtail \
>     && runuser -u "$username" -- /opt/wagtail/bin/pip install --no-cache-dir -r /tmp/requirements.txt \
>     && echo 'export PATH="/opt/wagtail/bin:$PATH"' > /etc/bashrc/wagtail.bashrc
> INNEREOF
> cat <<'INNEREOF' > .ddev/config.wagtail.yaml
> web_extra_daemons:
>     - name: "wagtail"
>       command: "python manage.py runserver 0.0.0.0:8000"
>       directory: /var/www/html
> web_extra_exposed_ports:
>     - name: "wagtail"
>       container_port: 8000
>       http_port: 80
>       https_port: 443
> INNEREOF
> ddev start -y
> ddev exec "rm -f requirements.txt && wagtail start mysite ."
> ddev exec python manage.py migrate --noinput
> ddev exec "DJANGO_SUPERUSER_PASSWORD=admin python manage.py createsuperuser --username=admin --email=admin@example.com --noinput"
> ddev restart
> ddev launch /admin
> EOF
> chmod +x setup-wagtail.sh
> ./setup-wagtail.sh
> ```

## WordPress

There are several easy ways to use DDEV with WordPress:

DDEV has built-in support for [WP-CLI](<https://wp-cli.org/>), the command-line interface for WordPress.

Create the project directory and configure DDEV:

```
mkdir -p my-wp-cli-site && cd my-wp-cli-site
# Create a new DDEV project inside the newly-created folder
# (Primary URL automatically set to `https://<folder>.ddev.site`)
ddev config --project-type=wordpress
```

Start DDEV (this may take a minute):

```
ddev start
```

Download WordPress:

```
ddev wp core download
```

Install WordPress (or use `ddev launch` to install via browser):

```
# You can launch in browser to finish installation:
# ddev launch
# OR use the following installation command
ddev wp core install --url="$(ddev exec echo '$DDEV_PRIMARY_URL')" --title='My WordPress site' --admin_user=admin --admin_password=admin --admin_email=admin@example.com
```

Launch WordPress admin dashboard:

```
ddev launch wp-admin/
```

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-wordpress.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-wp-cli-site && cd my-wp-cli-site
> ddev config --project-type=wordpress
> ddev start -y
> ddev wp core download
> ddev wp core install --url="$(ddev exec echo '$DDEV_PRIMARY_URL')" --title='My WordPress site' --admin_user=admin --admin_password=admin --admin_email=admin@example.com
> ddev launch wp-admin/
> EOF
> chmod +x setup-wordpress.sh
> ./setup-wordpress.sh
> ```

[Bedrock](<https://roots.io/bedrock/>) is a modern, Composer-based installation in WordPress:

```
mkdir -p my-wp-bedrock-site && cd my-wp-bedrock-site
ddev config --project-type=wp-bedrock
ddev start
ddev composer create-project roots/bedrock
```

DDEV automatically manages the `.env` file with the correct database credentials and `WP_HOME` URL. No manual `.env` configuration is needed.

You can then run:

```
ddev wp core install --url="$(ddev exec echo '$DDEV_PRIMARY_URL')" --title='My Bedrock Site' --admin_user=admin --admin_password=admin --admin_email=admin@example.com
ddev launch /wp/wp-admin/
```

For more details, see [Bedrock installation](<https://docs.roots.io/bedrock/master/installation/>).

> [!TIP]
>
> **Prefer to run as a script?**
>
> To run the whole setup as a script, examine and run this script:
>
> ```
> cat > setup-wp-bedrock.sh << 'EOF'
> #!/usr/bin/env bash
> set -euo pipefail
> mkdir -p my-wp-bedrock-site && cd my-wp-bedrock-site
> ddev config --project-type=wp-bedrock
> ddev start -y
> ddev composer create-project roots/bedrock
> ddev wp core install --url="$(ddev exec echo '$DDEV_PRIMARY_URL')" --title='My Bedrock Site' --admin_user=admin --admin_password=admin --admin_email=admin@example.com
> ddev launch /wp/wp-admin/
> EOF
> chmod +x setup-wp-bedrock.sh
> ./setup-wp-bedrock.sh
> ```

To get started using DDEV with an existing WordPress project, clone the project’s repository.

```
PROJECT_GIT_URL=https://github.com/ddev/test-wordpress.git
git clone ${PROJECT_GIT_URL} my-wp-git-site
cd my-wp-git-site
ddev config --project-type=wordpress
ddev start
ddev wp core install --url="$(ddev exec echo '$DDEV_PRIMARY_URL')" --title='My WordPress site' --admin_user=admin --admin_password=admin --admin_email=admin@example.com
ddev launch wp-admin/
```

You’ll see a message like:

> An existing user-managed wp-config.php file has been detected! Project DDEV settings have been written to:
>
> /Users/rfay/workspace/bedrock/web/wp-config-ddev.php

Comment out any database connection settings in your `wp-config.php` file and add the following snippet to your `wp-config.php`, near the bottom of the file and before the include of `wp-settings.php`:

```
// Include for DDEV-managed settings in wp-config-ddev.php.
$ddev_settings = __DIR__ . '/wp-config-ddev.php';
if (is_readable($ddev_settings) && !defined('DB_USER')) {
require_once($ddev_settings);
}
```

If you don’t care about those settings, or config is managed elsewhere (like in a `.env` file), you can eliminate this message by adding a comment to `wp-config.php`:

```
// wp-config-ddev.php not needed
```

Now run [`ddev start`](<https://ddev.github.io/ddev/en/stable/users/usage/commands/#start>) and continue [Importing a Database](<https://ddev.github.io/ddev/en/stable/users/usage/managing-projects/#importing-a-database>) if you need to.
