├── .githooks ├── README.md ├── linkallchecks.sh ├── pre-push.allchecks └── unlinkprepush.sh ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .markdownlintrc ├── LICENSE ├── README.md ├── custom-commands ├── drupal-login │ ├── README.md │ └── login ├── dump-and-deploy-db │ ├── README.md │ ├── dump-db-example.png │ └── web │ │ ├── deploy-db │ │ ├── dump-db │ │ └── targets │ │ └── README.txt ├── dynamic-service │ ├── readme.md │ └── service ├── fetchproductiondb │ ├── README.md │ └── fetchproductiondb ├── general-log │ ├── README.md │ ├── general_log │ └── general_log-usage.png ├── git-exclude │ ├── README.md │ └── git-exclude ├── gulp │ ├── README.md │ └── gulp ├── inotify-proxy │ ├── README.md │ └── inotify ├── silverstripe │ ├── README.md │ └── sake ├── stop-other │ ├── README.md │ └── stop-other ├── symfony │ ├── README.md │ ├── console-about-example.png │ └── web │ │ ├── console │ │ └── phpunit └── tinker │ ├── README.md │ └── web │ └── tinker ├── docker-compose-services ├── drupal8-behat-selenium │ ├── README.md │ ├── account_registration.feature │ ├── behat.yml │ └── docker-compose.selenium.yaml ├── drupalci-chromedriver │ ├── README.md │ └── docker-compose.chromedriver.yaml ├── elastichq │ ├── README.md │ └── docker-compose.elastichq.yaml ├── headless-chrome │ ├── README.md │ ├── behat.yml │ ├── docker-compose.chrome.yaml │ └── first-test.feature ├── kibana │ ├── README.md │ └── docker-compose.kibana.yaml ├── meilisearch │ ├── README.md │ └── docker-compose.meilisearch.yaml ├── mongodb │ ├── README.md │ └── docker-compose.mongo.yaml ├── old_php │ ├── .ddev │ │ ├── apache │ │ │ └── apache-site.conf │ │ ├── docker-compose.php.yaml │ │ └── mysql │ │ │ └── noutf8.cnf │ ├── README.md │ └── example.user.ini ├── php8_2 │ ├── README.md │ ├── docker-compose.php8_2.yaml │ ├── nginx-site.conf │ └── php-build │ │ ├── Dockerfile │ │ └── usr │ │ └── local │ │ └── etc │ │ └── php │ │ └── php.ini ├── portainer │ ├── README.md │ ├── docker-compose.portainer.yaml │ └── images │ │ ├── davidjguru_ddev_portainer_get_report.png │ │ └── davidjguru_ddev_portainer_sign_up.png ├── rabbitmq │ ├── README.md │ ├── docker-compose.rabbitmq.yaml │ └── rabbitmq-build │ │ └── enabled_plugins ├── solr-4 │ ├── README.md │ ├── core.properties │ └── docker-compose.solr.yml ├── solr-5 │ ├── README.md │ └── docker-compose.solr.yaml ├── solr-7 │ ├── README.md │ ├── docker-compose.solr.yaml │ └── solr │ │ ├── conf │ │ └── README.md │ │ └── solr-configupdate.sh ├── sqlsrv │ ├── Dockerfile │ ├── README.md │ ├── docker-compose.sqlsrv.yaml │ └── install-drupal-regex-function.sh ├── typo3-solr │ ├── README.md │ └── docker-compose.solr.yaml └── varnish │ ├── README.md │ ├── default.vcl │ └── docker-compose.varnish.yml ├── docker-compose-snippets ├── environment-variable │ └── docker-compose.env.yaml ├── mounting-directory │ ├── README.md │ └── docker-compose.mount.yaml ├── phpmyadmin-user-settings │ ├── README.md │ └── docker-compose.phpmyadmin.yaml └── project-communication │ ├── README.md │ └── docker-compose.project2.yaml ├── hook-examples └── import-db-if-empty │ ├── README.md │ └── import-if-empty.sh ├── recipes ├── bludit-cms │ └── README.md ├── civicrm │ └── README.md ├── cronjob │ ├── README.md │ ├── commands │ │ └── web │ │ │ └── cron │ └── config.cron.yml ├── drupal7-subfolder │ ├── README.md │ ├── dot.ddev │ │ ├── config.yaml │ │ └── nginx_full │ │ │ └── nginx-site.conf │ └── sites │ │ └── default │ │ └── ddev-subfolder.settings.php ├── drupal8-multisite │ ├── README.md │ ├── dot.ddev │ │ └── config.multisite.yaml │ ├── drush │ │ └── sites │ │ │ ├── basic.site.yml │ │ │ ├── d8m.yml │ │ │ └── umami.site.yml │ └── web │ │ └── sites │ │ ├── basic │ │ └── settings.php │ │ ├── default │ │ └── settings.base.php │ │ ├── sites.php │ │ └── umami │ │ └── settings.php ├── flextype-cms │ └── README.md ├── git-hooks │ └── pre-commit-phpcs │ │ ├── README.md │ │ ├── pre-commit │ │ └── pre-commit-phpcs.php ├── laravel-horizon │ ├── README.md │ ├── config │ │ └── database.php │ ├── dot.ddev │ │ ├── config.laravel-horizon.yaml │ │ └── web-build │ │ │ ├── Dockerfile │ │ │ └── horizon.conf │ └── dot.env ├── proxy │ ├── Dockerfile │ ├── README.md │ ├── config.json │ ├── http-proxy.conf │ └── tinyproxy.conf ├── puppeteer-headless-chrome-support │ ├── README.md │ └── demo │ │ ├── .ddev │ │ ├── commands │ │ │ └── web │ │ │ │ └── yarn │ │ └── config.yaml │ │ ├── .gitignore │ │ ├── package.json │ │ ├── postcss.config.js │ │ ├── src │ │ ├── main.js │ │ └── styles.css │ │ ├── tailwind.config.js │ │ ├── web │ │ ├── criticalcss │ │ │ └── .gitignore │ │ ├── hero.png │ │ ├── index.php │ │ └── webpack-assets │ │ │ └── .gitignore │ │ ├── webpack.config.js │ │ └── yarn.lock ├── redaxo-cms │ └── README.md └── sshd │ ├── README.md │ ├── config.sshd.yaml │ └── docker-compose.sshd.yaml └── web-container-dockerfiles ├── grpc ├── Dockerfile └── README.md ├── laravel-queue-worker ├── Dockerfile ├── README.md ├── config.laravel.yaml └── laravel-worker.conf └── stripe-cli ├── Dockerfile └── README.md /.githooks/README.md: -------------------------------------------------------------------------------- 1 | # Git hooks 2 | 3 | Hook scripts in this directory can be placed in .git/hooks to get git to help with our workflow. These are for developer use only, and have no impact by just being here in .githooks. 4 | 5 | You should also be able to link them, for example (if you don't mind if they change upstream, and don't introduce any changes of your own) 6 | 7 | The easiest way to do it is to use the script: `.githooks/linkallchecks.sh` and `.githooks/unlinkprepush.sh`. If you have a situation where you want to push without the checks, just `unlinkprepush.sh` and then put it back with `linkallchecks.sh`. 8 | 9 | But what you're actually doing is this: 10 | 11 | ``` 12 | cd .git/hooks 13 | # For all the static checks: 14 | ln -s ../../.githooks/pre-push.allchecks pre-push 15 | # or for just gofmt quick check 16 | ln -s ../../.githooks/pre-push.gofmt pre-push 17 | ``` 18 | -------------------------------------------------------------------------------- /.githooks/linkallchecks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | # Find the directory of this script 8 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 9 | 10 | ln -sf $DIR/pre-push.allchecks $DIR/../.git/hooks/pre-push 11 | 12 | echo "Linked pre-push.allchecks as pre-push git hook" -------------------------------------------------------------------------------- /.githooks/pre-push.allchecks: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # markdownlint 4 | markdownlint -o /tmp/mdlint.out $(find . -name "*.md") 5 | if [ "$?" != "0" ]; then 6 | echo "Markdownlint failed on these files:" 7 | awk -F: '{ print $1 }' < "/tmp/mdlint.out" | sort -u 8 | exit 1 9 | fi 10 | set -o errexit 11 | 12 | # Look for uncommitted files, http://stackoverflow.com/a/2659808/215713 13 | git diff-index --quiet HEAD || (echo "There are uncommitted files" && exit 1) 14 | 15 | # Look for unstaged files 16 | test -z "$(git ls-files --exclude-standard --others)" || (echo "There are unstaged files" && exit 2) 17 | -------------------------------------------------------------------------------- /.githooks/unlinkprepush.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | # Find the directory of this script 8 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 9 | 10 | rm -f $DIR/../.git/hooks/pre-push 11 | 12 | echo "Unlinked pre-push git hook" -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ## The New Solution/Problem/Issue/Bug: 9 | 10 | ## How this PR Solves The Problem: 11 | 12 | ## Manual Testing Instructions: 13 | 18 | 19 | ## Related Issue Link(s): 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | 3 | .idea -------------------------------------------------------------------------------- /.markdownlintrc: -------------------------------------------------------------------------------- 1 | { 2 | 3 | // These rules mostly come from mkdocs rules 4 | // https://github.com/mkdocs/mkdocs/blob/master/.markdownlintrc 5 | 6 | // Enable all markdownlint rules 7 | "default": true, 8 | 9 | // Fine with long lines, editor can wrap 10 | "line-length": false, 11 | 12 | "MD004": { "style": "consistent" }, 13 | 14 | // Set Ordered list item prefix to "ordered" (use 1. 2. 3. not 1. 1. 1.) 15 | "MD029": { "style": "ordered" }, 16 | 17 | // Set list indent level to 4 which Python-Markdown requires 18 | "MD007": { "indent": 4 }, 19 | 20 | // Fenced code blocks do not need language spec 21 | "MD040": false, 22 | 23 | // Exclude code block style 24 | "MD046": false 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ddev-contrib: ARCHIVED Contrib for DDEV 2 | 3 | Contrib space for DDEV add-ons, services, tools, snippets, and approaches. **MOSTLY OBSOLETE!** 4 | 5 | ## THIS REPO IS ARCHIVED AND OBSOLETE, Check the Add-On Registry! 6 | 7 | **MOST OF THESE recipes have been made obsolete by maintained DDEV add-ons. Please look for add-ons before using anything here. `ddev get --list --all`** 8 | 9 | See [docs](https://ddev.readthedocs.io/en/stable/users/extend/additional-services/) and `ddev get --list` for official add-ons, `ddev get --list --all` for all add-ons. 10 | 11 | ## config.yaml hook examples 12 | 13 | * [Import a SQL dump if database is empty](hook-examples/import-db-if-empty/) 14 | 15 | ## docker-compose.*.yaml snippets to solve simple problems 16 | 17 | Don't forget the [Official documentation](https://ddev.readthedocs.io/en/stable/users/extend/custom-compose-files/). 18 | 19 | * [Mounting a directory into web container](docker-compose-snippets/mounting-directory/) 20 | * [Setting an environment variable](docker-compose-snippets/environment-variable/docker-compose.env.yaml) 21 | * [Communication between two DDEV projects](docker-compose-snippets/project-communication/) 22 | * [Set default language (or other settings) in phpmyadmin](docker-compose-snippets/phpmyadmin-user-settings/) 23 | 24 | ## Custom command examples 25 | 26 | DDEV's [custom commands](https://ddev.readthedocs.io/en/latest/users/extend/custom-commands/) are a great way to add team-level or project-level commands. They're simple scripts that can be run in any of the containers or on the host. Note that several examples are already shipped with DDEV, you'll find them in .ddev/commands/*/*.example, and then can be enabled by symlinking or copying.) 27 | 28 | * [Dump and deploy SQL from/to remote servers](custom-commands/dump-and-deploy-db/) 29 | * [Fetch Production DB from remote server](custom-commands/fetchproductiondb/) 30 | * [Exclude DDEV directory from git: git-exclude](custom-commands/git-exclude) 31 | * [Enable and view MySQL/MariaDB GENERAL_LOG](custom-commands/general-log/) 32 | * [inotify-proxy to enable file watchers on NFS shares](custom-commands/inotify-proxy) 33 | * [Executing Symfony console and phpunit commands without ssh](custom-commands/symfony/) 34 | * [Build Drupal theme assets with Gulp](custom-commands/gulp) -- with minor modifications, this approach will work for other frameworks (WordPress, etc.) and other front-end build tools. 35 | * [Run Laravel `tinker` or Drupal's `drush php` with a single command](custom-commands/tinker) 36 | * [Stop all running projects except the current](custom-commands/stop-other) 37 | * [Dynamically enable / disable a service](custom-commands/dynamic-service) 38 | * [Automatically open browser and login to Drupal](custom-commands/drupal-login) 39 | * [Run Silverstripe frameworks command directly](custom-commands/silverstripe) 40 | 41 | ## Additional services added via docker-compose.\.yaml 42 | 43 | General information on how to do additional services and some additional examples are [in the docs](https://ddev.readthedocs.io/en/latest/users/extend/additional-services/). 44 | 45 | * [Behat, Selenium, Drupal 8/9](docker-compose-services/drupal8-behat-selenium) 46 | * [DrupalCI with Headless Chrome and Behat](docker-compose-services/drupalci-chromedriver). This example uses Drupal's DrupalCI approach, supports Behat, DrupalCI, etc. 47 | * [Elastichq](docker-compose-services/elastichq) 48 | * [Headless Chrome for Behat Testing](docker-compose-services/headless-chrome) 49 | * [Kibana](docker-compose-services/kibana) 50 | * [Meilisearch](docker-compose-services/meilisearch/) 51 | * [MongoDB](docker-compose-services/mongodb/) 52 | * [Old PHP Versions to run old sites](docker-compose-services/old_php) 53 | * [Portainer Service for DDEV](docker-compose-services/portainer) 54 | * [RabbitMQ](docker-compose-services/rabbitmq) 55 | * [Solr 4 Integration (Drupal-focused)](docker-compose-services/solr-4) 56 | * [Solr 5 Integration (Drupal-focused)](docker-compose-services/solr-5) 57 | * [Solr 7 Integration (Drupal-focused)](docker-compose-services/solr-7) 58 | * [Solr Integration (TYPO3-focused)](docker-compose-services/typo3-solr) 59 | * [SQL Server (Microsoft)](docker-compose-services/sqlsrv) 60 | * [Varnish](docker-compose-services/varnish) 61 | 62 | ## .ddev/web-build/Dockerfile examples to customize web container 63 | 64 | * [Laravel Queue-Worker](web-container-dockerfiles/laravel-queue-worker) (This is also a good example of adding an additional process to supervisord,) 65 | * [Stripe CLI](web-container-dockerfiles/stripe-cli) (This is also a good example of adding any non-standard Debian repository.) 66 | * [gRPC](web-container-dockerfiles/grpc) (This is also a good example of adding a pecl module that is not supported via apt-get.) 67 | 68 | ## Full recipes 69 | 70 | * [Using DDEV with a corporate (or other) web proxy (obsolete - use `ddev get ddev/ddev-proxy-support`)](recipes/proxy) 71 | * [enable TYPO3 cronjob on start or on demand (typo3 scheduler:run)](recipes/cronjob/) 72 | * [Setting up Drupal 8 multisite, including Drush support](recipes/drupal8-multisite/) 73 | * [Bludit CMS](recipes/bludit-cms) 74 | * [Drupal 7 in a Subfolder of Main Site](recipes/drupal7-subfolder) 75 | * [Flexitype CMS](recipes/flexitype-cms) 76 | * [Laravel Horizon](recipes/laravel-horizon) 77 | * [REDAXO CMS](recipes/redaxo-cms) 78 | * [SSH Server](recipes/sshd): Adding a "real" sshd server in web container 79 | * Also see a more recent [third-party add-on](#third-party-add-ons) above 80 | * [Puppeteer Headless Chrome support](recipes/puppeteer-headless-chrome-support/README.md) 81 | * [PHPCS Git hook without PHP on the host machine](recipes/git-hooks/pre-commit-phpcs) 82 | * [Install CiviCRM with DDEV](recipes/civicrm/) 83 | 84 | ## Third-party add-ons 85 | 86 | * [SSH Server](https://github.com/hanoii/ddev-sshd) 87 | -------------------------------------------------------------------------------- /custom-commands/drupal-login/README.md: -------------------------------------------------------------------------------- 1 | # Automatic login to Drupal site 2 | 3 | Run `ddev login` or add it under a hook (eg: `post-start`) to automatically open the default browser and login. 4 | Can take a username or uid as an argument. 5 | 6 | ## Installation 7 | Copy the [login](login) file under your project's `.ddev/commands/host` folder. 8 | 9 | **Contributed by [@bserem (Bill Seremetis)](https://github.com/bserem)** 10 | -------------------------------------------------------------------------------- /custom-commands/drupal-login/login: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Launch a browser and login to the current Drupal project. 4 | ## Usage: login [--name=USER] 5 | ## Example: "ddev login" or "ddev login --name=username" or "ddev login --uid=1" 6 | 7 | FULLURL=${DDEV_PRIMARY_URL} 8 | HTTPS="" 9 | if [ ${DDEV_PRIMARY_URL%://*} = "https" ]; then HTTPS=true; fi 10 | FULLURL=`ddev drush uli ${1}` 11 | 12 | case $OSTYPE in 13 | linux-gnu) 14 | xdg-open ${FULLURL} 15 | ;; 16 | "darwin"*) 17 | open ${FULLURL} 18 | ;; 19 | "win*"* | "msys"*) 20 | start ${FULLURL} 21 | ;; 22 | esac 23 | -------------------------------------------------------------------------------- /custom-commands/dump-and-deploy-db/README.md: -------------------------------------------------------------------------------- 1 | # Dump and deploy SQL from/to remote servers 2 | 3 | This adds custom commands which dump or deploy SQL data to/from databases. As database servers are usually not reachable through the internet, it can tunnel its connection through SSH. 4 | 5 | ## Original intent 6 | 7 | This was originally meant as a simple tool to refresh the DDEV database from time to time during feature development with current live data. A fancy interface was built to facilitate adoption with colleagues ;) - the normal workflow would be `ddev dump-db my-remote-live-server; ddev deploy-db ddev`. 8 | 9 | It came in handy during TYPO3 upgrades, too when being able to diff SQL data table by table helps facilitate single update steps. This is a controversial topic, but during upgrades I found it helpful to even git the data/SQL together with the code and thus be able to completely undo steps (even if they have side effects on the data) when necessary. 10 | 11 | ## Installation 12 | 13 | Copy [the web/ directory](web/) into your project's .ddev/commands/web. 14 | 15 | ## Configuration 16 | 17 | Without configuration this lets you dump and and deploy the local (called ‹ddev›) database. 18 | 19 | In order to add other hosts, see [web/targets/README.txt](web/targets/README.txt) for the config file structure. You basically need SSH and DB connection info. You can use private keys (e.g. via `ddev auth ssh`) or a password prompt to connect. 20 | 21 | ## Usage 22 | 23 | Running `ddev deploy-db` or `ddev dump-db` will show the available host configurations and parameters. 24 | 25 | `ddev dump-db` will save the SQL data at ./data/sql/records and ./data/sql/struct. 26 | 27 | `ddev deploy-db` also expects .sql files to be in any of these directories. For the ‹ddev› target this is functionally identical to `cat ./data/sql/struct/*.sql ./data/sql/records/*.sql | ddev mysql`. 28 | 29 | ## Example 30 | 31 | > This is what `ddev dump-db my-host` looks like: 32 | 33 | ![dump-db](dump-db-example.png) 34 | 35 | **Contributed by [@jonaseberle](https://github.com/jonaseberle)** 36 | -------------------------------------------------------------------------------- /custom-commands/dump-and-deploy-db/dump-db-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/custom-commands/dump-and-deploy-db/dump-db-example.png -------------------------------------------------------------------------------- /custom-commands/dump-and-deploy-db/web/deploy-db: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: deploy MySQL/MariaDB to remote system from ./data/sql/(records|struct)/ directories 4 | ## Usage: deploy-db [options, call without params for help] ‹target/source› 5 | 6 | endC="\033[0m" 7 | #black="\033[0;30m" 8 | #blackb="\033[1;30m" 9 | white="\033[0;37m" 10 | #whiteb="\033[1;37m" 11 | red="\033[0;31m" 12 | #redb="\033[1;31m" 13 | green="\033[0;32m" 14 | greenb="\033[1;32m" 15 | #yellow="\033[0;33m" 16 | #yellowb="\033[1;33m" 17 | #blue="\033[0;34m" 18 | #blueb="\033[1;34m" 19 | #purple="\033[0;35m" 20 | purpleb="\033[1;35m" 21 | #lightblue="\033[0;36m" 22 | #lightblueb="\033[1;36m" 23 | 24 | targetC=$green 25 | successC=$greenb 26 | errorC=$red 27 | 28 | function usage() { 29 | printf "Usage: ddev deploy-db [options] ‹target/source›\n" 30 | printf " %s %s\n" "‹target/source›" "Available targets/sources (from ./.ddev/commands/web/targets):" 31 | printf "\t%-15s · $targetC%s$endC\n" "" "ddev (the local ddev database)" 32 | find "$targetDir" -type f -not -name README.txt -print0 | 33 | while IFS= read -r -d '' _i; do 34 | printf "\t%-15s · $targetC%s$endC\n" "" "$(basename "$_i")" 35 | done 36 | printf " options:\n" 37 | printf "\t%-15s %s\n" "-y|--yes" "no question before data deletion" 38 | printf "\t%-15s %s\n" "-c|--creative" "use funny progress spinners" 39 | printf "\t%-15s %s\n" "-v|--verbose" "echo all executed commands" 40 | } 41 | 42 | function cursorBack() { 43 | echo -en "\033[$1D" 44 | } 45 | 46 | # global to keep its state 47 | iSpinner=0 48 | function spinner() { 49 | # make sure we use non-unicode character type locale 50 | # (that way it works for any locale as long as the font supports the characters) 51 | local LC_CTYPE=C 52 | 53 | local pid=$1 # Process Id of the previous running command 54 | 55 | if [ "$isCreative" == 0 ]; then 56 | spin="-\|/" 57 | local charwidth=1 58 | else 59 | declare -a spins 60 | local charwidth=3 61 | spins+=(" ▁▂▃▄▅▆▇█▉▊▋▌▍▎▏ ▏▎▍▌▋▊▉█▇▆▅▄▃▂▁") 62 | spins+=(" ▔▔▀▀██▐▐▕▕  ▕▕▐▐██▀▀▔▔") 63 | spins+=(" ▁▂▃▄▅▆▇███▀▔") 64 | spins+=('◐◓◑◒') 65 | spins+=('⠁⠂⠄⡀⢀⠠⠐⠈') 66 | spins+=('⣾⣽⣻⢿⡿⣟⣯⣷') 67 | spins+=('┤┘┴└├┌┬┐') 68 | spins+=('▖▘▝▗') 69 | spins+=('◢◣◤◥') 70 | spins+=('←↖↑↗→↘↓↙') 71 | spins+=('◰◳◲◱') 72 | spins+=('◴◷◶◵') 73 | spins+=(" ▏▎▍▌▋▊▉█▉▊▋▌▍▎▏") 74 | spins+=(" ▁▂▃▄▅▆▇█▇▆▅▄▃▂▁") 75 | spin=${spins[$((RANDOM % ${#spins[@]}))]} 76 | fi 77 | 78 | tput civis # cursor invisible 79 | while kill -0 "$pid" 2>/dev/null; do 80 | iSpinner=$(((iSpinner + charwidth) % ${#spin})) 81 | printf "$purpleb%s$endC" "${spin:$iSpinner:$charwidth}" 82 | 83 | cursorBack 1 84 | sleep .1 85 | done 86 | tput cnorm 87 | wait "$pid" # capture exit code 88 | return $? 89 | } 90 | 91 | function shutdown() { 92 | if [ "$isDumpDdev" == 0 ]; then 93 | # this would allow short running mysqldumps to finish before we shut off the line 94 | sleep 1 95 | printf "\nClosing tunnel …" 96 | # we ignore the actual result because it might already be closed 97 | pkill -TERM -f "^ssh -f" 98 | cursorBack 1 99 | printf "${successC}✓${endC}\n" 100 | fi 101 | printf "\n" 102 | tput cnorm # reset cursor 103 | } 104 | 105 | function parseArgs() { 106 | # -allow a command to fail with !’s side effect on errexit 107 | # -use return value from ${PIPESTATUS[0]}, because ! hosed $? 108 | ! getopt --test >/dev/null 109 | if [[ ${PIPESTATUS[0]} -ne 4 ]]; then 110 | echo -e "$errorC‹getopt --test› failed in this environment.$endC" 111 | exit 1 112 | fi 113 | 114 | OPTIONS="ycv" 115 | LONGOPTS="yes,creative,verbose" 116 | 117 | # -regarding ! and PIPESTATUS see above 118 | # -temporarily store output to be able to check for errors 119 | # -activate quoting/enhanced mode (e.g. by writing out “--options”) 120 | # -pass arguments only via -- "$@" to separate them correctly 121 | ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") 122 | if [[ ${PIPESTATUS[0]} -ne 0 ]]; then 123 | # e.g. return value is 1 124 | # then getopt has complained about wrong arguments to stdout 125 | usage 126 | exit 2 127 | fi 128 | # read getopt’s output this way to handle the quoting right: 129 | eval set -- "$PARSED" 130 | 131 | while true; do 132 | case "$1" in 133 | -y | --yes) 134 | isForce=1 135 | shift 136 | ;; 137 | -c | --creative) 138 | isCreative=1 139 | shift 140 | ;; 141 | -v | --verbose) 142 | isVerbose=1 143 | shift 144 | ;; 145 | --) 146 | shift 147 | break 148 | ;; 149 | *) 150 | targetName="$1" 151 | usage 152 | exit 3 153 | ;; 154 | esac 155 | done 156 | 157 | # handle non-option arguments 158 | if [[ $# -ne 1 ]]; then 159 | usage 160 | exit 4 161 | fi 162 | targetName="$1" 163 | 164 | if [ "$targetName" == "ddev" ]; then 165 | isDumpDdev=1 166 | else 167 | # read target config 168 | if ! . "$targetDir"/"$targetName" 2>/dev/null; then 169 | printf "${errorC}Target/source ‹$targetC%s$errorC› not found.$endC\n" "$targetName" 170 | usage 171 | exit 3 172 | fi 173 | fi 174 | } 175 | 176 | function openTunnel() { 177 | if [ $isDumpDdev == 1 ]; then 178 | target=( 179 | [mysqlHost]=db 180 | [mysqlPort]=3306 181 | [mysqlUser]=db 182 | [mysqlPass]=db 183 | [mysqlDatabase]=db 184 | # TODO: make configurable 185 | [ignoredDbTablesPattern]="^(sys_log|.*_sessions|cf_.*|.*cache.*|sys_file_processedfile|sys_refindex|sys_lockedrecords|tx_realurl_urldata|index_debug|index_fulltext|index_grlist|index_phash|index_rel|index_section|index_stat_search|index_stat_word|index_words|tx_crawler_queue|tx_extensionmanager_domain_model_extension)$" 186 | ) 187 | 188 | mysqlConnectString="--host=${target[mysqlHost]} --port=${target[mysqlPort]} --user=${target[mysqlUser]@Q} --password=${target[mysqlPass]@Q}" 189 | else 190 | printf "Opening tunnel …" 191 | 192 | if [ -z "${target[sshPrivKey]}" ]; then 193 | sshIdentitiyArg= 194 | else 195 | sshIdentitiyArg="-i \"/var/www/html/${target[sshPrivKey]}\"" 196 | fi 197 | localMysqlPort=33060 198 | 199 | # remotely use socket or port? 200 | if [ -n "${target[mysqlSocket]:-}" ]; then 201 | sshCommand="ssh -f -N -o LogLevel=ERROR -p ${target[sshPort]} $sshIdentitiyArg ${target[sshUser]}@${target[sshHost]} -L 127.0.0.1:$localMysqlPort:${target[mysqlSocket]}" 202 | else 203 | sshCommand="ssh -f -N -o LogLevel=ERROR -p ${target[sshPort]} $sshIdentitiyArg ${target[sshUser]}@${target[sshHost]} -L 127.0.0.1:$localMysqlPort:${target[mysqlHost]}:${target[mysqlPort]}" 204 | fi 205 | 206 | if eval "$sshCommand"; then 207 | cursorBack 1 208 | printf "%b✓%b\n" "${successC}" "${endC}" 209 | else 210 | cursorBack 1 211 | printf "%b✓%b\n" "${errorC}" "${endC}" 212 | exit 1 213 | fi 214 | 215 | mysqlConnectString="--host=127.0.0.1 --port=$localMysqlPort --user=${target[mysqlUser]@Q} --password=${target[mysqlPass]@Q}" 216 | fi 217 | trap shutdown EXIT 218 | 219 | mysqlCommand="mysql $mysqlConnectString --default-character-set=utf8mb4 ${target[mysqlDatabase]@Q}" 220 | } 221 | 222 | function gatherTables() { 223 | tablesCommand="$mysqlCommand --skip-column-names --batch -e \"SHOW TABLES;\"" 224 | 225 | if ! tables="$(eval "$tablesCommand")"; then 226 | cursorBack 1 227 | printf "%b🞩%b Could not gather tables\n" "${errorC}" "${endC}" 228 | exit 1 229 | fi 230 | } 231 | 232 | function dropTable() { 233 | eval "$mysqlCommand <<< 'DROP TABLE \`${T}\`' &> /dev/null &" 234 | if ! spinner $!; then 235 | printf " \n%b🞩%b Found foreign key in ‹%s›. Restarting " "${errorC}" "${endC}" "$T" 236 | return 1 237 | fi 238 | } 239 | 240 | # saner programming env: these switches turn some bugs into errors 241 | set -o errexit -o pipefail -o noclobber -o nounset 242 | 243 | # init 244 | targetDir=$(dirname "$0")/targets 245 | structDir="/var/www/html/data/sql/struct" 246 | dataDir="/var/www/html/data/sql/records" 247 | sqlDir="/var/www/html/data/sql" 248 | 249 | # arguments 250 | isForce=0 251 | isVerbose=0 252 | isDumpDdev=0 253 | isCreative=0 254 | targetName= 255 | typeset -A target 256 | 257 | parseArgs "$@" 258 | 259 | if [ $isVerbose == 1 ]; then 260 | set -x 261 | fi 262 | 263 | openTunnel 264 | 265 | # delete existing data 266 | if [ $isForce == 0 ]; then 267 | while true; do 268 | printf "This will delete all existing data in the database ‹%s› on host ‹%s›!\n" \ 269 | "${target[mysqlDatabase]}" \ 270 | "${target[mysqlHost]}" 271 | read -rp "Are you sure? [y/n] " yn 272 | case $yn in 273 | [Yy]*) break ;; 274 | [Nn]*) exit 130 ;; 275 | *) echo -e "${errorC}Please answer y or n.$endC" ;; 276 | esac 277 | done 278 | fi 279 | 280 | gatherTables 281 | nTables=$(echo "$tables" | wc -w) 282 | printf "${white}Dropping %d tables${endC} " "$nTables" 283 | while true; do 284 | declare -i _dropHasErrors=0 285 | for T in $tables; do 286 | printf "." 287 | 288 | if ! dropTable; then 289 | _dropHasErrors=1 290 | fi 291 | done 292 | [ $_dropHasErrors -eq 0 ] && break 293 | gatherTables 294 | done 295 | printf " %b✓%b\n" "${successC}" "${endC}" 296 | 297 | printf "Creating database if not there yet " 298 | eval "$mysqlCommand <<< 'CREATE DATABASE IF NOT EXISTS ${target[mysqlDatabase]}'&" 299 | if ! spinner $!; then 300 | echo $? 301 | printf "%b✓%b\n" "${errorC}" "${endC}" 302 | printf "Error\n" 303 | exit 1 304 | fi 305 | printf "%b✓%b\n" "${successC}" "${endC}" 306 | 307 | findCommand="find ${structDir@Q} ${dataDir@Q} ${sqlDir@Q} -maxdepth 1 -type f -name '*.sql'" 308 | 309 | nFiles=$(eval "$findCommand" | wc -l) 310 | 311 | printf "${white}Deploying %d sql files …${endC}\n" "$nFiles" 312 | 313 | declare -i _i=0 314 | eval "$findCommand -print0" | 315 | while IFS= read -r -d '' _file; do 316 | _i+=1 317 | printf "$white%${#nFiles}d/%d$endC" $_i "$nFiles" 318 | 319 | printf " %-80s " "$(eval "sed -e 's/\/var\/www\/html\///g' <<< $_file")" 320 | eval "$mysqlCommand < ${_file@Q}&" 321 | if ! spinner $!; then 322 | echo $? 323 | printf "%b✓%b\n" "${errorC}" "${endC}" 324 | printf "Error\n" 325 | exit 1 326 | fi 327 | printf "${successC}✓${endC} (%s)\n" "$(du --apparent-size --human-readable "$_file" | cut -f1)" 328 | done 329 | 330 | printf "\nFinished. Deployed SQL (%s)\n" "$(du --apparent-size --human-readable $dataDir | cut -f1)" 331 | -------------------------------------------------------------------------------- /custom-commands/dump-and-deploy-db/web/targets/README.txt: -------------------------------------------------------------------------------- 1 | # This directory holds "targets/sources" aka host configurations. 2 | # Create files of any names (except README.txt) in this directory to provide access to remote systems via this form configuration: 3 | 4 | target=( 5 | # The SSH user used to connect to the remote webapp server. 6 | [sshUser]= 7 | # The SSH host of the remote webapp. Enclose IPv6 addresses in []. 8 | [sshHost]= 9 | # The SSH port 10 | [sshPort]=22 11 | # You can provide a path to an SSH private key here (local path from inside the web container). 12 | # If you leave it empty, other means of authentification will be used: 13 | # * after running `ddev auth ssh`, your SSH private keys from /.ssh/* will be available 14 | # * putting the key into .ddev/homeadditions/.ssh/id_rsa will make it available 15 | # * or you will be asked for the SSH password 16 | [sshPrivKey]= 17 | # The hostname that the webapp uses to reach the MySQL/MariaDB database (the connection will be tunneled through SSH to sshUser@sshHost) 18 | [mysqlHost]=mysql.myserver.com 19 | [mysqlPort]=3306 20 | [mysqlUser]= 21 | [mysqlPass]= 22 | [mysqlDatabase]= 23 | # Provide a RegEx against which each database table is checked. If it matches, its data won't be downloaded (structure is unaffected by this). 24 | # This is an example to ignore some common TYPO3 tables with cached or easily rebuildable data. 25 | [ignoredDbTablesPattern]="^(sys_log|.*_sessions|cf_.*|.*cache.*|sys_file_processedfile|sys_refindex|sys_lockedrecords|tx_realurl_urldata|index_debug|index_fulltext|index_grlist|index_phash|index_rel|index_section|index_stat_search|index_stat_word|index_words|tx_crawler_queue|tx_extensionmanager_domain_model_extension)$" 26 | ) 27 | 28 | # PS: 29 | # The files are interpreted by Bash so you can use bash logic to fill in values 30 | -------------------------------------------------------------------------------- /custom-commands/dynamic-service/readme.md: -------------------------------------------------------------------------------- 1 | # Dynamically enable / disable a service 2 | 3 | Have you ever wanted to enable a serivce locally, but not on you CI? 4 | Need to quickly disable a service for debugging? 5 | 6 | This handle little command lets you enable/disable a DDEV `docker-compose` based service. 7 | 8 | ## Installation 9 | 10 | - Copy the `service` file into the DDEV commands directory. 11 | 12 | To activate the command for all DDEV projects, copy it to your global DDEV config directory: `~/.ddev/commands/host`. 13 | 14 | If you prefer to enable it on a per-project basis, copy it into the project commands directory: `./.ddev/commands/host`. 15 | 16 | Note: If you have a copy in both locations, you will recieve a warning: 17 | 18 | ```shell 19 | Project-level command 'service' is overriding the global 'service' command 20 | ``` 21 | 22 | ## Usage 23 | 24 | EG. Lets assume you have `./.ddev/docker-compose.cypress.yaml` file that provides the `cypress` service. 25 | 26 | Type the following command to disable the service: 27 | 28 | ```shell 29 | ddev service cypress disable 30 | ``` 31 | 32 | The file is renamed to `./.ddev/docker-compose.cypress.yaml.disabled`. It will no longer be read by DDEV on startup. 33 | 34 | Type the following command to enable the service: 35 | 36 | ```shell 37 | ddev service cypress enable 38 | ``` 39 | 40 | ## Notes 41 | 42 | - If a service is updated, "enabled" or "disabled", DDEV will automatically restart to apply the changes. 43 | - The service name is parsed from the file name; `docker-composer.goo.yaml` assumes the service is called `goo`. 44 | - You can update the command variable `DISABLED_EXT` to change the disabled extension. Default is ".`disabled`" 45 | 46 | **Contributed by [@tyler36](https://github.com/tyler36)** 47 | -------------------------------------------------------------------------------- /custom-commands/dynamic-service/service: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: This allows DDEV services activated via docker-compose to be enabled/disabled 4 | ## Usage: service [service-name] [status] 5 | ## Example: To enable a service: "ddev service postgres enable", "ddev service postgres on" 6 | ## Example: To disable a service: "ddev service postgres disable", "ddev service postgres off" 7 | 8 | 9 | DISABLED_EXT="disabled" 10 | STATUS=null 11 | FILE="./.ddev/docker-compose.$1.yaml" 12 | 13 | list_services() { 14 | ddev describe 15 | exit 0; 16 | } 17 | 18 | if [[ "$1" == "status" ]] || [ -z "$1" ]; then 19 | list_services 20 | fi 21 | 22 | if [ -f "${FILE}" ]; then 23 | STATUS="enabled" 24 | fi 25 | 26 | if [ -f "${FILE}.${DISABLED_EXT}" ]; then 27 | STATUS="disabled" 28 | fi 29 | 30 | if [ -z "${STATUS}" ]; then 31 | echo "DDEV '$1' was not detected" 32 | echo "Are you sure you have ${FILE} file?" 33 | exit 0 34 | fi 35 | 36 | if 37 | echo "DDEV '$1' service is currently ${STATUS}." 38 | 39 | case $2 in 40 | on|true|enable|start) 41 | TARGET="enabled" 42 | if [ "${STATUS}" = "${TARGET}" ]; then 43 | echo "Nothing to do" 44 | exit 0 45 | fi 46 | 47 | mv "${FILE}.${DISABLED_EXT}" "${FILE}" 48 | ;; 49 | off|false|disable|stop) 50 | TARGET="disabled" 51 | if [ "${STATUS}" = "${TARGET}" ]; then 52 | echo "Nothing to do." 53 | exit 0 54 | fi 55 | 56 | mv "${FILE}" "${FILE}.${DISABLED_EXT}" 57 | ;; 58 | *) 59 | echo "Invalid argument: $2" 60 | exit 0; 61 | ;; 62 | esac 63 | 64 | echo "DDEV '$1' has been ${TARGET}." 65 | ddev restart 66 | -------------------------------------------------------------------------------- /custom-commands/fetchproductiondb/README.md: -------------------------------------------------------------------------------- 1 | # Pull Production DB Custom Command (ddev fetchproductiondb) 2 | 3 | 1. Copy the [fetchproductiondb](./fetchproductiondb) command to the .ddev/commands/host/ directory. 4 | 2. adjust $SSH_TARGET and $TARGET_DBNAME in the command 5 | 3. If $SSH_TARGET user on host does not already have permissions on the database, you can put credentials in ~/.my.cnf on the server as shown here: 6 | 7 | ```ini 8 | [client] 9 | user=username 10 | password=password 11 | ``` 12 | 13 | now you can run `ddev fetchproductiondb`. You can easily build the same for files using rsync. 14 | 15 | **Contributed by [@kaystrobach](https://github.com/kaystrobach)** 16 | -------------------------------------------------------------------------------- /custom-commands/fetchproductiondb/fetchproductiondb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Fetch a database from production and load it into current project 4 | ## Usage: fetchproductiondb 5 | ## Example: "ddev fetchprodctiondb" 6 | 7 | set -o errexit pipefail nounset 8 | #set -x 9 | 10 | SSH_TARGET=remoteuser@remotehost.com 11 | TARGET_DBNAME=somedb 12 | 13 | DUMPDIR=${DDEV_APPROOT}/.dumps 14 | mkdir -p ${DUMPDIR} 15 | echo "Fetching ${TARGET_DBNAME} from ${SSH_TARGET} into ${DUMPDIR}/${DDEV_SITENAME}.sql.gz" 16 | ssh ${SSH_TARGET} "mysqldump ${TARGET_DBNAME} | gzip" > ${DUMPDIR}/${DDEV_SITENAME}.sql.gz 17 | ddev import-db --src=${DUMPDIR}/${DDEV_SITENAME}.sql.gz 18 | -------------------------------------------------------------------------------- /custom-commands/general-log/README.md: -------------------------------------------------------------------------------- 1 | # Enable and show MySQL/MariaDB GENERAL_LOG (ddev general_log) 2 | 3 | This custom `ddev` command shows all database queries. 4 | 5 | It activates the [MySQL/MariaDB general_log](https://dev.mysql.com/doc/refman/8.0/en/query-log.html) temporarily and de-activates it when it exits. 6 | 7 | ## Usage 8 | 9 | * Run `ddev general_log` 10 | * In order to exit, press `CTRL+C`. 11 | 12 | ## Example 13 | 14 | > After running `ddev general_log` you would see all executed database queries: 15 | 16 | ![dump-db](general_log-usage.png) 17 | 18 | ## Installation 19 | 20 | Copy [the file general_log](general_log) into your project's .ddev/commands/**db**. 21 | 22 | 23 | **Contributed by [@jonaseberle](https://github.com/jonaseberle)** 24 | -------------------------------------------------------------------------------- /custom-commands/general-log/general_log: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Enable and show database general_log. Disables log after exiting (via CTRL+C) 4 | ## Usage: general_log 5 | 6 | # saner programming env: these switches turn some bugs into errors 7 | set -o errexit -o pipefail -o noclobber -o nounset 8 | endC="\033[0m" 9 | greenb="\033[1;32m" 10 | purpleb="\033[1;35m" 11 | #red="\033[0;31m" 12 | 13 | noticeC=$purpleb 14 | successC=$greenb 15 | #errorC=$red 16 | 17 | function spinner() { 18 | function cursorBack() { 19 | echo -en "\033[$1D" 20 | } 21 | # make sure we use non-unicode character type locale 22 | # (that way it works for any locale as long as the font supports the characters) 23 | local LC_CTYPE=C 24 | 25 | local pid=$1 # Process Id of the previous running command 26 | 27 | spin="-\|/" 28 | local iSpinner=0 29 | local charwidth=1 30 | 31 | tput civis # cursor invisible 32 | while kill -0 "$pid" 2>/dev/null; do 33 | iSpinner=$(((iSpinner + charwidth) % ${#spin})) 34 | printf "$noticeC%s$endC" "${spin:$iSpinner:$charwidth}" 35 | 36 | cursorBack 1 37 | sleep .1 38 | done 39 | tput cnorm 40 | wait "$pid" # capture exit code 41 | return $? 42 | } 43 | function enable() { 44 | printf "Enabling general_log " 45 | mysql -uroot -proot <<< "SET GLOBAL general_log_file='general_log.log'" 46 | mysql -uroot -proot <<< "SET GLOBAL general_log=1" & 47 | spinner $! 48 | printf "%b✓%b \n" "${successC}" "${endC}" 49 | printf "%bPress CTRL+C to exit.%b\n\n" "${noticeC}" "${endC}" 50 | } 51 | function shutdown() { 52 | printf " \n\nDisabling general_log " 53 | mysql -uroot -proot <<< "SET GLOBAL general_log=0" & 54 | spinner $! 55 | printf "%b✓%b \n" "${successC}" "${endC}" 56 | 57 | exit 0 58 | } 59 | trap shutdown INT 60 | 61 | enable 62 | tail -f /var/lib/mysql/general_log.log 63 | -------------------------------------------------------------------------------- /custom-commands/general-log/general_log-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/custom-commands/general-log/general_log-usage.png -------------------------------------------------------------------------------- /custom-commands/git-exclude/README.md: -------------------------------------------------------------------------------- 1 | # Excludes ddev from Git Custom Command (ddev git-exclude) 2 | 3 | Copy the [git-exclude](./git-exclude) command to the .ddev/commands/host/ directory or the global ~/.ddev/commands/host directory (to make it work for all projects). 4 | 5 | now you can run `ddev git-exclude` and avoid tracking the ddev files in git. 6 | 7 | **Contributed by [@pcambra](https://github.com/pcambra) and [@facine](https://github.com/facine)** 8 | -------------------------------------------------------------------------------- /custom-commands/git-exclude/git-exclude: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Exclude ddev generated files from the project repo 4 | ## Usage: git-exclude 5 | 6 | case $OSTYPE in 7 | linux-gnu | "darwin"* ) 8 | if [ $DDEV_PROJECT_TYPE == "drupal7" ]; then 9 | grep -qxF ".ddev" .git/info/exclude || echo ".ddev" >> .git/info/exclude 10 | grep -qxF "${DDEV_DOCROOT}/sites/default/.gitignore" .git/info/exclude || echo "${DDEV_DOCROOT}/sites/default/.gitignore" >> .git/info/exclude 11 | elif [ $DDEV_PROJECT_TYPE == "drupal8" ] || [ $DDEV_PROJECT_TYPE == "drupal9" ]; then 12 | grep -qxF ".ddev" .git/info/exclude || echo ".ddev" >> .git/info/exclude 13 | grep -qxF "drush/.gitignore" .git/info/exclude || echo "drush/.gitignore" >> .git/info/exclude 14 | grep -qxF "${DDEV_DOCROOT}/sites/default/.gitignore" .git/info/exclude || echo "${DDEV_DOCROOT}/sites/default/.gitignore" >> .git/info/exclude 15 | fi 16 | ;; 17 | esac 18 | -------------------------------------------------------------------------------- /custom-commands/gulp/README.md: -------------------------------------------------------------------------------- 1 | # Build Drupal theme assets with Gulp 2 | 3 | 1. Edit the [gulp](./gulp) command to set the THEME to the relative path (from the docroot) to your custom theme. 4 | 1. Copy the edited command to your project's .ddev/commands/web directory. 5 | 6 | now you can run `ddev gulp` and it will build your theme. 7 | 8 | **Contributed by [@hotwebmatter (Matthew Obert)](https://github.com/hotwebmatter)** 9 | -------------------------------------------------------------------------------- /custom-commands/gulp/gulp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run gulp in theme directory. 4 | ## Usage: gulp build|watch 5 | ## Example: "ddev gulp", "ddev gulp build", "ddev gulp watch" 6 | 7 | ## Edit the following line to set the relative path from DDEV_DOCROOT 8 | ## to your custom theme root (this example works for Drupal projects.) 9 | THEME=themes/custom/customtheme 10 | 11 | ## Concatenates path to theme directory for your project. 12 | DDEV_THEMEROOT=/var/www/html/${DDEV_DOCROOT}/${THEME} 13 | 14 | ## Presupposes that gulp is installed in ${DDEV_THEMEROOT}/node_modules 15 | ## You may need to "npm install" theme dependencies before running this. 16 | if [ -d ${DDEV_THEMEROOT} ] 17 | then 18 | if [ -f ${DDEV_THEMEROOT}/node_modules/gulp/bin/gulp.js ] 19 | then 20 | pushd ${DDEV_THEMEROOT} 21 | ./node_modules/gulp/bin/gulp.js $@ 22 | popd 23 | else 24 | echo "Error: No gulp.js found at ./node_modules/gulp/bin/gulp.js." 25 | echo '(You may need to "npm install" theme dependencies first.)' 26 | fi 27 | else 28 | echo "Error: Directory ${DDEV_THEMEROOT} does not exist." 29 | echo '(Edit THEME variable in ./ddev/commands/web/gulp to fix this.)' 30 | fi 31 | exit 32 | 33 | ## The same approach should work for other front-end build tools 34 | ## (e.g., grunt, brunch, less, sass, compass, etc.) 35 | ## which expect to be run with the theme directory as working directory. 36 | ## It should also work when building theme assets for WordPress, etc., 37 | ## just by changing the DDEV_THEMEROOT to an appropriate directory. 38 | -------------------------------------------------------------------------------- /custom-commands/inotify-proxy/README.md: -------------------------------------------------------------------------------- 1 | # inotify-proxy to enable file watchers on NFS shares 2 | 3 | On a regular Linux or macOS filesystem, a process can subscribe to notifications about file changes ("inotify" or "fsnotify"). Most IDEs like PhpStorm depend on this notification to update files or rendering when they change. However, the NFS protocol predates the inotify feature, and so does not support it. However, most developers on macOS and Windows use the [nfs_mount_enabled feature](https://ddev.readthedocs.io/en/stable/users/performance/#using-nfs-to-mount-the-project-into-the-web-container) to mount files from the host into the container instead of using the docker-native technique. Performance is much improved, but of course NFS does not support notifications. 4 | 5 | (Note that this is not necessary on Linux hosts; NFS is not needed there because the Docker filesystem mount is so fast.) 6 | This tool helps to detect changed files in Docker Containers if NFS mount is used. 7 | If a file is changed from host system a file watcher inside the container detects the change and triggers a notify event. The command runs inside the docker container. 8 | 9 | The tool is designed to run over a longer period of time. It comes with a garbage collector to cleanup old watched files in memory. 10 | 11 | The command will download the pre-compiled binary inotify-proxy from Github release page and executes it. 12 | 13 | The tool can be configured to watch only for files with defined extensions in configured directories. 14 | See https://github.com/cmuench/inotify-proxy#config for informations about the configuration format. 15 | 16 | ## Installation 17 | 18 | Copy the file `inotify` into your project **.ddev/commands/web** directory. 19 | 20 | ## Run the command 21 | 22 | ```sh 23 | ddev inotify 24 | ``` 25 | 26 | **Contributed by [@cmuench](https://github.com/cmuench)** 27 | -------------------------------------------------------------------------------- /custom-commands/inotify-proxy/inotify: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run inotify-proxy to recognize file system changes if NFS is used. 4 | ## Usage: inotify [-profile ] [-sleep ] [folder1] [folder2] [...folder n] 5 | ## Example: "ddev inotify -profile magento2-theme vendor/magento/theme-frontend-luma" 6 | 7 | CURRENT_DIR=$(dirname "$0") 8 | 9 | cd /var/www/html; 10 | 11 | INOTIFY=/usr/local/bin/inotify-proxy 12 | 13 | # Download inotify-proxy 14 | if [ ! -f "$INOTIFY" ]; then 15 | pushd /tmp/ >/dev/null || exit 16 | 17 | unamearch=$(uname -m) 18 | 19 | case ${unamearch} in 20 | x86_64) ARCH="linux_amd64"; 21 | ;; 22 | aarch64) ARCH="linux_arm64"; 23 | ;; 24 | *) printf "${RED}Sorry, your machine architecture ${unamearch} is not currently supported.\n${RESET}" && exit 106 25 | ;; 26 | esac 27 | 28 | curl -s https://api.github.com/repos/cmuench/inotify-proxy/releases/latest \ 29 | | grep "browser_download_url.*inotify-proxy.*_${ARCH}\.tar\.gz" \ 30 | | cut -d ":" -f 2,3 \ 31 | | tr -d \" \ 32 | | wget -qi - 33 | 34 | tarball="$(find . -name "inotify-proxy_*_${ARCH}\.tar\.gz")" 35 | echo $tarball 36 | tar -xzf $tarball 37 | 38 | chmod +x inotify-proxy 39 | 40 | sudo mv inotify-proxy "$INOTIFY" 41 | 42 | rm $tarball 43 | 44 | popd >/dev/null || exit 45 | fi 46 | 47 | cd /var/www/html; 48 | ${INOTIFY} "$@" 49 | -------------------------------------------------------------------------------- /custom-commands/silverstripe/README.md: -------------------------------------------------------------------------------- 1 | # Silverstripe "sake" command 2 | 3 | Copy the sake file to either your project's `.ddev/commands/web` folder. Or, for global usage, copy it to `{YOUR_HOME_FOLDER}/.ddev/commands/web` 4 | 5 | ## Usage 6 | 7 | Sake is the Silverstripe Make command, to run development tools. 8 | 9 | Use it as sake in your project: 10 | 11 | `ddev sake dev/tasks` for tasks 12 | 13 | `ddev sake dev/build` to build the database 14 | 15 | etc. 16 | 17 | For the full list of features of Silverstripe CLI, see the Silverstripe (developer) documentation. 18 | -------------------------------------------------------------------------------- /custom-commands/silverstripe/sake: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run Silverstripe make 4 | ## Usage: sake 5 | ## Example: "ddev sake dev/tasks" or "ddev sake dev/build flush=all" 6 | ## ExecRaw: true 7 | ## HostWorkingDir: true 8 | 9 | sake $@ 10 | -------------------------------------------------------------------------------- /custom-commands/stop-other/README.md: -------------------------------------------------------------------------------- 1 | # Stops all running projects except the current. 2 | 3 | Copy the [stop-other](./stop-other) command to the .ddev/commands/host/ directory or the global ~/.ddev/commands/host directory (to make it work for all projects). 4 | 5 | Now you can run `ddev stop-other` to stop all running projects except the one you are calling the command from. 6 | 7 | This requires that the `jq` command be installed. `brew install jq` or see https://stedolan.github.io/jq/download/ 8 | 9 | **Original idea by sceo (on Discord) and code by [@rfay](https://github.com/rfay)** 10 | 11 | -------------------------------------------------------------------------------- /custom-commands/stop-other/stop-other: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Stop all other running projects 4 | ## Usage: stop-other 5 | ## Example: "ddev stop-other" 6 | 7 | # Ensure jq is installed on the host. 8 | command -v jq >/dev/null 2>&1 || { echo >&2 "jq is required but it's not installed. See https://stedolan.github.io/jq/download/ for installation instructions."; exit 1; } 9 | 10 | # Stop all other running projects. 11 | ddev stop $(ddev list --active-only -j | jq -r ".raw[].name" | grep -v $(ddev describe -j | jq -r ".raw.name")) 12 | -------------------------------------------------------------------------------- /custom-commands/symfony/README.md: -------------------------------------------------------------------------------- 1 | # Run Symfony console commands (ddev console) and phpunit tests (ddev phpunit) 2 | 3 | This adds custom command which executes the `bin/console` or `bin/phpunit` in the container without the need to SSH. 4 | 5 | ## Installation 6 | 7 | - Copy the [web](web/) directory into your project `.ddev/commands/web`, so that the [console](web/console) and the [phpunit](web/phpunit) commands would be in `.ddev/commands/web` folder. 8 | 9 | - If the Symfony project is in a subfolder, add to `.ddev/ddev.config.yaml`: 10 | ```yaml 11 | working_dir: 12 | web: /var/www/html/ 13 | ``` 14 | 15 | ## Usage 16 | 17 | Running `ddev console` or `ddev phpunit` is now equivalent to running `bin/console` or `bin/phpunit` from inside the container. It is now possible to get debug information such as `ddev console debug:router`, running a maker with `ddev console make:entity` or running phpunit tests without the need to SSH into the container. 18 | 19 | ## Example 20 | 21 | > This is how `ddev console about` would look like: 22 | 23 | ![console](console-about-example.png) 24 | 25 | **Contributed by [@alechko](https://github.com/alechko)** 26 | -------------------------------------------------------------------------------- /custom-commands/symfony/console-about-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/custom-commands/symfony/console-about-example.png -------------------------------------------------------------------------------- /custom-commands/symfony/web/console: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run Symphony console 4 | ## Usage: console 5 | ## Example: "ddev console about" or "ddev console debug:config" 6 | bin/console $@ 7 | -------------------------------------------------------------------------------- /custom-commands/symfony/web/phpunit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run Symphony phpunit tests 4 | ## Usage: phpunit 5 | ## Example: "ddev phpunit" or "ddev phpunit tests/Util" 6 | bin/phpunit $@ 7 | -------------------------------------------------------------------------------- /custom-commands/tinker/README.md: -------------------------------------------------------------------------------- 1 | # Run Laravel `tinker` or Drupal's `drush php` with a single command 2 | 3 | - [Installation](#installation) 4 | - [Per-project](#per-project) 5 | - [Usage](#usage) 6 | - [Arguments](#arguments) 7 | 8 | Both Laravel and Drupal have an interactive debugger & REPL environment for tinkering in PHP. You can test various php statements, resolve services or even query the database! Both environment's are customized versions of the excellent [PsySh](https://psysh.org/). 9 | 10 | - Laravel: [`php artisan tinker`](https://laravel.com/docs/artisan#tinker) 11 | 12 | - Drupal via a Drush: [`drush php`](https://www.drush.org/latest/commands/php_cli/) 13 | 14 | This new command, `ddev tinker`, checks which project you are currently in, and runs the correct command for the project. If you bounce between projects types, this command is really useful. 15 | 16 | ## Installation 17 | 18 | This command works best if installed globally (set-and-forget). It can then be accessed in any Laravel or Drupal project. 19 | 20 | - Copy the [web/tinker](web/tinker) file into `~/.ddev/commands/web`. 21 | 22 | ### Per-project 23 | 24 | You could also use this command on a per-project basis. 25 | 26 | - Copy the [web/tinker](web/tinker) file into your project `./.ddev/commands/web`. 27 | 28 | ## Usage 29 | 30 | To start your framework's REPL environment, simply type the follow: 31 | 32 | ```shell 33 | ddev tinker 34 | ``` 35 | 36 | ### Arguments 37 | 38 | - Tinker can accept simple arguments. 39 | 40 | ```shell 41 | $ ddev tinker 6+8 42 | 14 43 | ``` 44 | 45 | - More complex arguments should be wrapped with '. 46 | 47 | ```shell 48 | $ ddev tinker 'User::first()' 49 | [!] Aliasing 'User' to 'App\Models\User' for this Tinker session. 50 | App\Models\User^ {#4400 51 | ... 52 | 53 | $ ddev tinker 'node_access_rebuild()' 54 | [notice] Message: Content permissions have been rebuilt. 55 | 56 | $ ddev tinker '$node = \Drupal\node\Entity\Node::load(1); print $node->getTitle();' 57 | Who Doesn’t Like a Good Waterfall? 58 | ``` 59 | 60 | While this might be helpful for a quick one-off command, it's recommend to run `ddev tinker` for tinkering to avoid any Docker connection delays between multiple commands. 61 | 62 | - Wrapping may also work with ", depending on the command used. For more consistent results between frameworks and host OS, it is recommended to use '. 63 | - See https://github.com/ddev/ddev/issues/2547 64 | 65 | **Contributed by [@tyler36](https://github.com/tyler36)** 66 | -------------------------------------------------------------------------------- /custom-commands/tinker/web/tinker: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run project PHP REPL. Arguments are accepted in Laravel projects (with caveats) 4 | ## Usage: tinker 5 | ## Example: "ddev tinker" 6 | ## Example: "ddev tinker 'User::first()->email'" 7 | ## Example: "dev tinker '$node = \Drupal\node\Entity\Node::load(1); print $node->getTitle();'" 8 | ## ProjectTypes: laravel,drupal7,drupal8,drupal9,drupal10 9 | ## ExecRaw: true 10 | 11 | if [ "${DDEV_PROJECT_TYPE}" == "laravel" ]; then 12 | if [ -z "$1" ] 13 | then 14 | php artisan tinker 15 | else 16 | php artisan tinker --execute="dd($1);" 17 | fi 18 | 19 | exit 0 20 | fi 21 | 22 | # If this it hit, it's must be a Drupal project type. 23 | 24 | if ! command -v drush >/dev/null; then 25 | echo "drush is not available. You may need to 'ddev composer require drush/drush'" 26 | exit 1 27 | fi 28 | 29 | if [ -z "$1" ] 30 | then 31 | drush php 32 | else 33 | drush php:eval "$1" 34 | fi 35 | -------------------------------------------------------------------------------- /docker-compose-services/drupal8-behat-selenium/README.md: -------------------------------------------------------------------------------- 1 | # Setup Behat for Drupal 8/9 with DDEV-Local and Selenium 2 | 3 | **Note: You may want to take a look at the [ddev-selenium-standalone-chrome add-on](https://github.com/weitzman/ddev-selenium-standalone-chrome) for this situation.** 4 | 5 | 1. Add the [Behat Drupal Extension](https://github.com/jhedstrom/drupalextension) to your project using Composer: `ddev composer require drupal/drupal-extension='~4.0'` 6 | ` (see [youtube video](https://www.youtube.com/watch?v=KRqqKZPBqpA)) This installs Behat and other required dependencies. 7 | 8 | 2. Add a Selenium container in your project. Copy [docker-compose.selenium.yml](docker-compose.selenium.yaml) to your project's .ddev folder (see [original source Stack Overflow answer](https://stackoverflow.com/questions/51527663/running-selenium-tests-using-drupalextension-inside-ddev-docker-containers)) 9 | 10 | 3. Copy [behat.yml](behat.yml) to your project root. 11 | 12 | 4. Update `base_url` in behat.yml with your project's URL. 13 | 14 | 5. Initialize Behat with `ddev exec -d /var/www/html behat --init` - This will create a `features` folder in your project root. 15 | 16 | 6. Example test: Copy [account_registration.feature](account_registration.feature) to the `features` directory of your project. (See [youtube demonstration](https://www.youtube.com/watch?v=KRqqKZPBqpA).) 17 | 18 | 7. Run a simple test with `ddev exec -d /var/www/html behat` or 19 | 20 | ```bash 21 | ddev ssh -d /var/www/html 22 | behat 23 | ``` 24 | 25 | You should see results similar to this: 26 | 27 | ```text 28 | 29 | Feature: Account Registration 30 | In order to create an account 31 | As a user 32 | I need to be able to complete the registration form 33 | 34 | Scenario: Complete the registration form # features/account_registration.feature:8 35 | Given I am on "/user/register" # Drupal\DrupalExtension\Context\MinkContext::visit() 36 | And I enter "t@gmail.com" for "edit-mail" # Drupal\DrupalExtension\Context\MinkContext::assertEnterField() 37 | And I enter "tom" for "edit-name" # Drupal\DrupalExtension\Context\MinkContext::assertEnterField() 38 | And I press the "edit-submit" button # Drupal\DrupalExtension\Context\MinkContext::pressButton() 39 | 40 | 1 scenario (1 passed) 41 | 4 steps (4 passed) 42 | 0m0.56s (5.59Mb) 43 | ``` 44 | 45 | **Contributed by [@erubino1977](https://github.com/erubino1977)** 46 | -------------------------------------------------------------------------------- /docker-compose-services/drupal8-behat-selenium/account_registration.feature: -------------------------------------------------------------------------------- 1 | # This example feature should be placed in the project's "features" directory. 2 | 3 | Feature: Account Registration 4 | In order to create an account 5 | As a user 6 | I need to be able to complete the registration form 7 | 8 | Scenario: Complete the registration form 9 | Given I am on "/user/register" 10 | And I enter "t@gmail.com" for "edit-mail" 11 | And I enter "tom" for "edit-name" 12 | And I check the box "edit-contact--2" 13 | And I press the "edit-submit" button 14 | -------------------------------------------------------------------------------- /docker-compose-services/drupal8-behat-selenium/behat.yml: -------------------------------------------------------------------------------- 1 | # Make sure to update base_url: for your site 2 | default: 3 | suites: 4 | default: 5 | contexts: 6 | - Drupal\DrupalExtension\Context\DrupalContext 7 | - Drupal\DrupalExtension\Context\MinkContext 8 | - Drupal\DrupalExtension\Context\MessageContext 9 | - Drupal\DrupalExtension\Context\DrushContext 10 | extensions: 11 | Behat\MinkExtension: 12 | goutte: ~ 13 | selenium2: ~ 14 | base_url: https://myproject.ddev.site 15 | Drupal\DrupalExtension: 16 | blackbox: ~ 17 | -------------------------------------------------------------------------------- /docker-compose-services/drupal8-behat-selenium/docker-compose.selenium.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | web: 5 | depends_on: 6 | - db 7 | - selenium 8 | selenium: 9 | container_name: ddev-${DDEV_SITENAME}-selenium 10 | image: selenium/standalone-chrome-debug:3.13.0-argon 11 | networks: 12 | default: 13 | aliases: 14 | - web 15 | -------------------------------------------------------------------------------- /docker-compose-services/drupalci-chromedriver/README.md: -------------------------------------------------------------------------------- 1 | # [Obsolete] DrupalCI ChromeDriver (Behat, DrupalCI, FunctionalJavascript) 2 | 3 | **The recommended approach for running tests that require ChromeDriver is to use [ddev-selenium-standalone-chrome add-on](https://github.com/ddev/ddev-selenium-standalone-chrome) instead.** 4 | 5 | This recipe adds the DrupalCI ChromeDriver container to a project. 6 | 7 | **Note that the drupalci Chromedriver does not work on Apple Silicon computers, see the Selenium Standalone Chrome note above.** 8 | 9 | Among other things, this supports Drupal's FunctionalJavascript tests. 10 | But it also supports Behat with WebDriver or any other use of headless Chrome. 11 | It is based on [Matt Glaman's excelent blog post](https://glamanate.com/blog/running-drupals-functionaljavascript-tests-ddev) 12 | 13 | ## Installation 14 | 15 | * Copy `docker-compose.chromedriver.yaml` to the `.ddev` folder of your project. 16 | * Set environment variables in the "environment" section of the "web" service in `docker-compose.chromedriver.yaml` as appropriate. The defaults are for Drupal Functional and FunctionalJavascript testing. 17 | * Verify that your phpunit.xml does not define `MINK_DRIVER_ARGS_WEBDRIVER`, `SIMPLETEST_DB`, `SIMPLETEST_BASE_URL`, `BROWSERTEST_OUTPUT_DIRECTORY`, or `BROWSERTEST_OUTPUT_BASE_URL`. These should come from our docker-compose.chromedriver.yaml. 18 | * Ensure that one of the two `SIMPLETEST_DB` options is uncommented. 19 | * Start (or restart) DDEV to have the service initialized: `ddev start` 20 | * Your Drupal project must be built with --require-dev to get necessary dependencies like phpunit (for example, `ddev composer create drupal/recommended-project --require-dev`) 21 | * To test the setup, `ddev ssh` and run a Drupal unit test that triggers ChromeDriver. Example (assumes Drupal core is in the `web` directory): 22 | 23 | ```bash 24 | user@demo-web:/var/www/html$ phpunit -c web/core/phpunit.xml.dist web/core/modules/system/tests/src/FunctionalJavascript/System/DateFormatTest.php 25 | ``` 26 | ## Example run 27 | 28 | From @damienmckenna, here's an example run to demonstrate functionality: 29 | 30 | ```bash 31 | $ ddev exec phpunit -c core/phpunit.xml.dist core/modules/system/tests/src/FunctionalJavascript/System/DateFormatTest.php 32 | PHPUnit 8.5.8 by Sebastian Bergmann and contributors. 33 | 34 | Runtime: PHP 7.3.27-9+0~20210227.82+debian10~1.gbpa4a3d6 35 | Configuration: /var/www/html/core/phpunit.xml.dist 36 | 37 | Testing Drupal\Tests\system\FunctionalJavascript\System\DateFormatTest 38 | . 1 / 1 (100%) 39 | 40 | Time: 53.15 seconds, Memory: 4.00 MB 41 | 42 | OK (1 test, 6 assertions) 43 | 44 | HTML output was generated 45 | https://d91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-13-97496575.html 46 | https://d91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-14-97496575.html 47 | https://d91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-15-97496575.html 48 | https://d91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-16-97496575.html 49 | https://d91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-17-97496575.html 50 | ``` 51 | 52 | ## Notes 53 | 54 | * There is no need to modify the phpunit.xml.dist file, core's included file can be referenced as-is, per the example above. 55 | * In order for this to work all other ddev instances must be turned off, only the Drupal core instance which will be used for the PHPUnit tests can be running. 56 | * Do not modify the `SIMPLETEST_BASE_URL`, otherwise ChromeDriver will not be able to access the test site. 57 | 58 | ## Possible problems and potential solutions 59 | 60 | * If the tests return the error message "unable to set cookie" it is likely that the `SIMPLETEST_BASE_URL` value was modified from its original value of `http://web`. Changing it back to `http://web` should resolve this problem. 61 | * If the sample core test fails, load the output HTML files mentioned at the end of the output, e.g. `https://drupalcore91.ddev.site/sites/simpletest/browser_output/Drupal_Tests_system_FunctionalJavascript_System_DateFormatTest-9-12332112.html`, and see what the output contains, that may help track down the source of the problem. 62 | * If the output of the sample test contains HTML from a different website, check to see if other ddev instances or Docker images are running, and shut them down if needed. 63 | 64 | **Contributed by [@mglaman](https://github.com/mglaman) 65 | and [@heddn](https://github.com/heddn)** 66 | -------------------------------------------------------------------------------- /docker-compose-services/drupalci-chromedriver/docker-compose.chromedriver.yaml: -------------------------------------------------------------------------------- 1 | # Docker-ChromeDriver configuration for DDEV-Local. 2 | # There is one item that must be configured in this file in order for it to 3 | # work, please see below. 4 | 5 | services: 6 | chromedriver: 7 | image: drupalci/webdriver-chromedriver:production 8 | container_name: ddev-${DDEV_SITENAME}-chromedriver 9 | labels: 10 | com.ddev.site-name: ${DDEV_SITENAME} 11 | com.ddev.approot: $DDEV_APPROOT 12 | external_links: 13 | - ddev-router:${DDEV_SITENAME}.${DDEV_TLD} 14 | 15 | web: 16 | links: 17 | - chromedriver 18 | environment: 19 | # *** One of these must be uncommented *** 20 | # In order for the system to work, one of these must be uncommented so 21 | # that the test system can connect to the database. 22 | # - SIMPLETEST_DB=sqlite://tmp/test.sqlite 23 | # - SIMPLETEST_DB=mysql://db:db@db/db 24 | # 25 | # Note: Do not modify the base URL value. 26 | - SIMPLETEST_BASE_URL=http://web 27 | - BROWSERTEST_OUTPUT_DIRECTORY=/tmp 28 | - BROWSERTEST_OUTPUT_BASE_URL=${DDEV_PRIMARY_URL} 29 | - MINK_DRIVER_ARGS_WEBDRIVER=["chrome", {"browserName":"chrome","goog:chromeOptions":{"args":["--disable-gpu","--headless", "--no-sandbox"]}}, "http://chromedriver:9515"] 30 | -------------------------------------------------------------------------------- /docker-compose-services/elastichq/README.md: -------------------------------------------------------------------------------- 1 | # ElasticHQ 2 | 3 | This recipe adds an ElasticHQ container to a project. 4 | 5 | This will allow you to have a graphical interface for browsing data in your Elasticsearch server. 6 | 7 | **Note to Apple M1 and other arm64 users: At last check the [elasticsearch-hq image](https://hub.docker.com/r/elastichq/elasticsearch-hq) was amd64-only, so your mileage may vary with this recipe.** 8 | 9 | ## Requirements 10 | 11 | Elastic HQ requires a working instance of Elasticsearch running for it to connect to. This is based on the [docker-compose recipe for elasticsearch in ddev-contrib](../elasticsearch). 12 | 13 | ## Configuration 14 | 15 | If your Elasticsearch server is not available inside the elastichq container at `http://ddev--elasticsearch:9200` (as it is when using the [ddev-contrib recipe](../elasticsearch), then you need to edit `docker-compose.elastichq.yaml` and edit the following environment variable: 16 | 17 | * Change `HQ_DEFAULT_URL` to the url where your Elasticsearch server is available from inside the elastichq container. 18 | 19 | ## Installation 20 | 21 | * Copy `docker-compose.elastichq.yaml` to the `.ddev` folder of your project. 22 | * Start (or restart) DDEV to have the service initialized: `ddev start` 23 | * Access your ElasticHQ UI at `http://.ddev.site:5000` or via https at `https://.ddev.site:5443`. 24 | 25 | **Contributed by [@Graloth](https://github.com/Graloth)** 26 | -------------------------------------------------------------------------------- /docker-compose-services/elastichq/docker-compose.elastichq.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | elastichq: 4 | container_name: ddev-${DDEV_SITENAME}-elastichq 5 | hostname: ${DDEV_SITENAME}-elastichq 6 | image: elastichq/elasticsearch-hq 7 | restart: always 8 | expose: 9 | - "5000" 10 | labels: 11 | com.ddev.site-name: ${DDEV_SITENAME} 12 | com.ddev.approot: $DDEV_APPROOT 13 | environment: 14 | - VIRTUAL_HOST=$DDEV_HOSTNAME 15 | - HTTP_EXPOSE=5000:5000 16 | - HTTPS_EXPOSE=5443:5000 17 | - HQ_DEFAULT_URL=http://ddev-${DDEV_PROJECT}-elasticsearch:9200 18 | volumes: 19 | - ".:/mnt/ddev_config" 20 | elasticsearch: 21 | links: 22 | - elastichq:elastichq 23 | -------------------------------------------------------------------------------- /docker-compose-services/headless-chrome/README.md: -------------------------------------------------------------------------------- 1 | # Headless Chrome Service 2 | 3 | **Note: You may want to take a look at the [ddev-selenium-standalone-chrome add-on](https://github.com/ddev/ddev-selenium-standalone-chrome) for this situation.** 4 | 5 | This recipe allows you to configure a Headless Chrome which will be available inside the web container, at `chrome:9222`. 6 | 7 | I moved from selenium + Chrome to Headless Chrome because it's faster than Selenium + chrome. 8 | 9 | 1. Copy [docker-compose.chrome.yaml](docker-compose.chrome.yaml) into your project's .ddev directory. 10 | 2. `ddev start` 11 | 3. Begin testing. An example scenario is below if you don't have anything set up yet. 12 | 13 | An example of how to use this is provided in [behat blog post](https://gorannikolovski.com/blog/drupal-8-and-behat-tests): 14 | 15 | * `ddev composer require --dev behat/behat dmore/behat-chrome-extension drupal/drupal-extension bex/behat-screenshot` to install the needed tools if not already in your project. 16 | * Copy the example [behat.yml](behat.yml) provided here into the root of your project (it will be /var/www/html/behat.yml inside the container). 17 | * Edit "base_url" under `Drupal\MinkExtension`in the behat.yml. Use the `http` URL for your project rather than `https` because the chrome container does not trust the mkcert certificate used in the web container. 18 | * `ddev ssh` to get into the container and work in `/var/www/html` (which is the root of your project). 19 | * `vendor/bin/behat --init` 20 | * Copy [first-test.feature](first-test.feature) into the features directory that has just been created in the root of your repository. 21 | * `behat` (inside the container) or `ddev exec behat` on the host will test first-feature (which works on a default Drupal 9 profile install) 22 | 23 | **Contributed by [isholgueras](https://github.com/isholgueras)** 24 | -------------------------------------------------------------------------------- /docker-compose-services/headless-chrome/behat.yml: -------------------------------------------------------------------------------- 1 | default: 2 | suites: 3 | default: 4 | contexts: 5 | - FeatureContext 6 | - Drupal\DrupalExtension\Context\DrupalContext 7 | - Drupal\DrupalExtension\Context\MinkContext 8 | - Drupal\DrupalExtension\Context\MessageContext 9 | extensions: 10 | DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ 11 | Drupal\MinkExtension: 12 | base_url: https://.ddev.site 13 | ajax_timeout: 30 14 | # goutte: ~ 15 | browser_name: chrome 16 | sessions: 17 | default: 18 | chrome: 19 | api_url: "http://chrome:9222" 20 | socket_timeout: 20 21 | download_behavior: allow 22 | validate_certificate: false 23 | # Using drupalextension "drupal/drupal-extension": "v4.0.0rc1" or above. Use Behat\DrupalExtension if 24 | Drupal\DrupalExtension: 25 | drupal: 26 | # Change this to the relative path to the docroot 27 | drupal_root: "web" 28 | api_driver: 'drush' 29 | drush: 30 | root: /var/www/html/web 31 | region_map: 32 | header: "#header" 33 | sidebar: "#sidebar-first" 34 | content: "#content" 35 | footer: ".site-footer" 36 | -------------------------------------------------------------------------------- /docker-compose-services/headless-chrome/docker-compose.chrome.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | chrome: 4 | image: isholgueras/chrome-headless:latest 5 | restart: unless-stopped 6 | container_name: ddev-${DDEV_SITENAME}-chrome 7 | labels: 8 | com.ddev.site-name: ${DDEV_SITENAME} 9 | com.ddev.approot: ${DDEV_APPROOT} 10 | volumes: 11 | - ddev-global-cache:/mnt/ddev-global-cache 12 | - ".:/mnt/ddev_config" 13 | external_links: 14 | - "ddev-router:${DDEV_HOSTNAME}" 15 | cap_add: 16 | - SYS_ADMIN 17 | expose: 18 | - "9222" 19 | environment: 20 | - VIRTUAL_HOST=$DDEV_HOSTNAME 21 | - HTTP_EXPOSE=9221:9222 22 | - HTTPS_EXPOSE=9222:9222 23 | -------------------------------------------------------------------------------- /docker-compose-services/headless-chrome/first-test.feature: -------------------------------------------------------------------------------- 1 | @api 2 | Feature: Test account menu links 3 | 4 | Scenario: Make sure that logged in users see the account menu 5 | Given I am logged in as a user with the "authenticated" role 6 | And I am on "/" 7 | Then I should see the link "My account" in the "header" region 8 | And I should see the link "Log out" in the "header" region 9 | 10 | Scenario: Make sure that anonymous users see the account menu 11 | Given I am not logged in 12 | And I am on "/" 13 | Then I should see the link "Log in" in the "header" region 14 | 15 | -------------------------------------------------------------------------------- /docker-compose-services/kibana/README.md: -------------------------------------------------------------------------------- 1 | # Kibana 2 | 3 | This recipe adds Kibana container to a project. 4 | 5 | This will allow you to visualize your Elasticsearch data and do anything from tracking query load to understanding the way requests flow through your apps. 6 | 7 | **Note to Apple M1 and other arm64 users: At last check the [kibana 7.10.1 image](https://www.docker.elastic.co/r/kibana/kibana:7.10.1) referenced here was amd64-only, so your mileage may vary with this recipe. You may want to use one of the multiplatform images like kibana/kibana:7.13.3 at [the elastic.co docker repository](https://www.docker.elastic.co/r/kibana)** 8 | 9 | ## Requirements 10 | 11 | Kibana requires a working instance of Elasticsearch running for it to connect to. This requires the [docker-compose recipe for elasticsearch in ddev-contrib](../elasticsearch). 12 | 13 | ## Configuration 14 | 15 | If your Elasticsearch server is not available inside the kibana container at `http://ddev--elasticsearch:9200` (as it is when using the [ddev-contrib recipe](../elasticsearch), then you need to edit `docker-compose.kibana.yaml` and edit the following and edit the`ELASTICSEARCH_HOSTS` environment variable to the url your Elasticsearch server is available at within the kibana container. 16 | 17 | Current Kibana version is 7.10.1, to change the version you need to edit the `image` parameter in `docker-compose.kibana.yaml` 18 | 19 | ## Installation 20 | 21 | - Copy `docker-compose.kibana.yaml` to the `.ddev` folder of your project. 22 | - Start (or restart) DDEV to have the service initialized: `ddev start` 23 | - Access Kibana at `https://.ddev.site:5602`. 24 | 25 | **Contributed by [@alechko](https://github.com/alechko)** 26 | -------------------------------------------------------------------------------- /docker-compose-services/kibana/docker-compose.kibana.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | kibana: 4 | container_name: ddev-${DDEV_PROJECT}-kibana 5 | hostname: ${DDEV_PROJECT}-kibana 6 | image: docker.elastic.co/kibana/kibana:7.10.1 7 | restart: "no" 8 | expose: 9 | - '5601' 10 | labels: 11 | com.ddev.site-name: ${DDEV_SITENAME} 12 | com.ddev.approot: $DDEV_APPROOT 13 | environment: 14 | - VIRTUAL_HOST=$DDEV_HOSTNAME 15 | - HTTP_EXPOSE=5601:5601 16 | - HTTPS_EXPOSE=5602:5601 17 | - ELASTICSEARCH_HOSTS=http://ddev-${DDEV_PROJECT}-elasticsearch:9200 18 | - SERVER_NAME=ddev-${DDEV_PROJECT}-elasticsearch 19 | volumes: 20 | - '.:/mnt/ddev_config' 21 | depends_on: 22 | - elasticsearch 23 | -------------------------------------------------------------------------------- /docker-compose-services/meilisearch/README.md: -------------------------------------------------------------------------------- 1 | # Meilisearch 2 | 3 | [Meilisearch](https://www.meilisearch.com/) is an open source search-engine. It can be used in ddev to handle search indexes for the Drupal search_api, or as a backend for Laravel Scout. 4 | 5 | Using official meilisearch v0.27.2 container [meilisearch](https://hub.docker.com/r/getmeili/meilisearch). 6 | 7 | ## Installation 8 | 9 | Copy [docker-compose.meilisearch.yaml](docker-compose.meilisearch.yaml) to your project's .ddev folder. 10 | 11 | ## Configuration 12 | 13 | From within the container, the meilisearch container is reached at hostname: `ddev--meilisearch`, port: 7700, so the in-container server URL might be `http://ddev--meilisearch:7700`. 14 | 15 | Setup a Master Key by setting the environment variable `MEILI_MASTER_KEY` to a 16 byte UTF-8 string. 16 | 17 | ## Connection 18 | 19 | You can access the Meilisearch server directly from the host for debugging purposes by visiting `http://.ddev.site:7700`. 20 | 21 | You can use `ddev logs -s meilisearch` to investigate what the meilisearch daemon has been up to. 22 | 23 | ## Additional Resources 24 | 25 | - [Drupal search_api_meilisearch module](https://www.drupal.org/project/search_api_meilisearch) 26 | - [Meilisearch docs](https://docs.meilisearch.com/learn/getting_started/quick_start.html) 27 | - [Laravel Scout](https://laravel.com/docs/9.x/scout) 28 | 29 | **Contributed by [@thilohille](https://github.com/thilohille)** 30 | -------------------------------------------------------------------------------- /docker-compose-services/meilisearch/docker-compose.meilisearch.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | meilisearch: 4 | container_name: ddev-${DDEV_SITENAME}-meilisearch 5 | image: getmeili/meilisearch:v1.2.0 6 | hostname: ${DDEV_SITENAME}-meilisearch 7 | expose: 8 | - "7700" 9 | environment: 10 | - VIRTUAL_HOST=$DDEV_HOSTNAME 11 | - HTTP_EXPOSE=7700:7700 12 | volumes: 13 | - type: "volume" 14 | source: meilisearch 15 | target: "/data.ms" 16 | volume: 17 | nocopy: true 18 | - type: "bind" 19 | source: "." 20 | target: "/mnt/ddev_config" 21 | - ddev-global-cache:/mnt/ddev-global-cache 22 | labels: 23 | com.ddev.site-name: ${DDEV_SITENAME} 24 | com.ddev.approot: $DDEV_APPROOT 25 | web: 26 | links: 27 | - meilisearch:meilisearch 28 | 29 | volumes: 30 | meilisearch: 31 | -------------------------------------------------------------------------------- /docker-compose-services/mongodb/README.md: -------------------------------------------------------------------------------- 1 | # MongoDB 2 | 3 | This simple recipe creates two new containers, one for MongoDB and one for Mongo Express. 4 | 5 | Based on [MongoDb from Docker Hub](https://hub.docker.com/_/mongo?tab=description#-via-docker-stack-deploy-or-docker-compose), [ddev custom compose files](https://ddev.readthedocs.io/en/stable/users/extend/custom-compose-files/) and [API Platform tutorial](https://api-platform.com/docs/core/mongodb/#enabling-mongodb-support). 6 | 7 | I'm using it on a Symfony 4 app with API Platform. 8 | 9 | Steps to follow: 10 | 11 | 1. Install php-mongo extension by adding `webimage_extra_packages: [php7.3-mongodb]` to your .ddev/config.yaml. Note that the PHP version in the package name must correspond to the PHP version you are running, e.g. use `php7.4-mongodb` if your server runs PHP 7.4. 12 | 13 | 2. Add the file [docker-compose.mongo.yaml](docker-compose.mongo.yaml) to the project's `.ddev` directory. 14 | 15 | 3. Require the [Doctrine MongoDB ODM bundle](https://github.com/doctrine/DoctrineMongoDBBundle) 16 | `ddev composer require doctrine/mongodb-odm-bundle:^4.0.0@beta doctrine/mongodb-odm:^2.0.0@beta` 17 | 18 | 4. In your application `.env`, set the connection string: 19 | 20 | ``` 21 | MONGODB_URL=mongodb://db:db@ddev--mongo:27017 22 | MONGODB_DB=api 23 | ``` 24 | 25 | Mongo Express will now be accessible from `http://.ddev.site:8081` 26 | 27 | Caveats: 28 | 29 | * You can't define custom MongoDB configuration with this current setup. 30 | * You can't use `ddev import-db` to import to mongo. 31 | 32 | **Contributed by [@wtfred](https://github.com/wtfred)** 33 | -------------------------------------------------------------------------------- /docker-compose-services/mongodb/docker-compose.mongo.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | mongo: 5 | container_name: ddev-${DDEV_SITENAME}-mongo 6 | image: mongo:4.0 7 | volumes: 8 | - type: "volume" 9 | source: mongo 10 | target: "/data/db" 11 | volume: 12 | nocopy: true 13 | restart: "no" 14 | expose: 15 | - "27017" 16 | labels: 17 | com.ddev.site-name: ${DDEV_SITENAME} 18 | com.ddev.approot: $DDEV_APPROOT 19 | environment: 20 | - MONGO_INITDB_ROOT_USERNAME=db 21 | - MONGO_INITDB_ROOT_PASSWORD=db 22 | - MONGO_INITDB_DATABASE=db 23 | 24 | mongo-express: 25 | container_name: ddev-${DDEV_SITENAME}-mongo-express 26 | image: mongo-express:0.49 27 | restart: "no" 28 | labels: 29 | com.ddev.site-name: ${DDEV_SITENAME} 30 | com.ddev.approot: ${DDEV_APPROOT} 31 | com.ddev.platform: ddev 32 | 33 | links: 34 | - mongo:mongo 35 | expose: 36 | - "8081" 37 | environment: 38 | VIRTUAL_HOST: $DDEV_HOSTNAME 39 | ME_CONFIG_MONGODB_ADMINUSERNAME: db 40 | ME_CONFIG_MONGODB_ADMINPASSWORD: db 41 | HTTP_EXPOSE: "8081:8081" 42 | 43 | web: 44 | links: 45 | - mongo:mongo 46 | 47 | volumes: 48 | mongo: 49 | -------------------------------------------------------------------------------- /docker-compose-services/old_php/.ddev/apache/apache-site.conf: -------------------------------------------------------------------------------- 1 | # This apache-site.conf goes in .ddev/apache 2 | # It works against a back-end php-fpm docker container from devilbox 3 | 4 | RewriteEngine On 5 | RewriteCond %{HTTP:X-Forwarded-Proto} =https 6 | RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d 7 | RewriteRule ^(.+[^/])$ https://%{HTTP_HOST}$1/ [redirect,last] 8 | 9 | SetEnvIf X-Forwarded-Proto "https" HTTPS=on 10 | 11 | DocumentRoot /var/www/html 12 | 13 | AllowOverride All 14 | Allow from All 15 | 16 | 17 | CustomLog /var/log/apache2/access.log combined 18 | 19 | # ProxyFCGIBackendType GENERIC seems to be necessary for php5.2 20 | ProxyFCGIBackendType GENERIC 21 | ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/html/$1 22 | DirectoryIndex /index.php index.php 23 | 24 | 25 | Alias "/phpstatus" "/var/www/phpstatus.php" 26 | 27 | 28 | 29 | # vim: syntax=apache ts=4 sw=4 sts=4 sr noet 30 | -------------------------------------------------------------------------------- /docker-compose-services/old_php/.ddev/docker-compose.php.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | php: 5 | container_name: ddev-${DDEV_SITENAME}-php 6 | image: devilbox/php-fpm:5.2-work 7 | # image: devilbox/php-fpm:5.3-work 8 | # image: devilbox/php-fpm:5.4-work 9 | # image: devilbox/php-fpm:5.5-work 10 | 11 | restart: "no" 12 | ports: 13 | - 9000 14 | labels: 15 | com.ddev.site-name: ${DDEV_SITENAME} 16 | com.ddev.approot: $DDEV_APPROOT 17 | volumes: 18 | - type: bind 19 | source: ../ 20 | target: /var/www/html 21 | consistency: cached 22 | - ".:/mnt/ddev_config:ro" 23 | - ddev-global-cache:/mnt/ddev-global-cache 24 | environment: 25 | - DDEV_PHP_VERSION 26 | - IS_DDEV_PROJECT=true 27 | 28 | web: 29 | links: 30 | - php:php 31 | healthcheck: 32 | # Use "true" as the healthcheck to ignore its result 33 | test: ["CMD", "true"] 34 | 35 | -------------------------------------------------------------------------------- /docker-compose-services/old_php/.ddev/mysql/noutf8.cnf: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | collation-server = utf8_general_ci 3 | character-set-server = utf8 4 | innodb_large_prefix=false 5 | -------------------------------------------------------------------------------- /docker-compose-services/old_php/README.md: -------------------------------------------------------------------------------- 1 | # Using old PHP versions (pre-php5.6) 2 | 3 | It's not uncommon to need to be able to run a site that has been neglected for years or decades, often for upgrading, migrating, copying, or archiving purposes. But normally there are just too many errors and problems with these very old sites to get them to run with more recent PHP versions. And the oldest PHP version that ddev directly supports is PHP 5.6. 4 | 5 | However, there are images of older PHP versions on hub.docker.com, and we can use them as third-party services to get the behavior we need, which is usually just being able to *look* at a site. 6 | 7 | This recipe was explicitly tested on Drupal 4.7 and 5.x, both from the 2008-2010 timeframe. 5.x installation succeeded with this configuration and PHP 5.3. Drupal 4.7 installation (very manual) succeeeded with PHP 5.2. Another approach which I used initially is to build the site or recover it on an Ubuntu 12.04 VM. 8 | 9 | ## Architecture 10 | 11 | The normal ddev approach is to run both Nginx/Apache and php-fpm in the same container. However, it doesn't have to be that way. Here we're using *Apache* in the regular ddev-webserver, but we've set the Apache config to proxy to a different container, a PHP container running one of the Devilbox PHP images. 12 | 13 | This means that the `php_version` you have set in your .ddev/config.yaml is irrelevant; the actual PHP version is the one in the Devilbox container. 14 | 15 | ## Check out or download the repository and files into a project directory 16 | 17 | For example, on a Drupal site you'll want the code and the user-uploaded files from sites/default/files. 18 | 19 | If you're just kicking the tires, you can use a Drupal 4.7 version with `git clone -b 4.7.x https://git.drupal.org/project/drupal.git`. 20 | 21 | ## ddev config 22 | 23 | * `ddev config --project-type=php --webserver-type=apache-fpm --mariadb-version=5.5` sets up your project. 24 | 25 | Apache is required for the Devilbox PHP container to be used. The project type and MariaDB parameters are only needed if your project requires them. 26 | 27 | If your docroot is not the default, make sure to set it correctly in the .ddev/config.yaml. 28 | 29 | ## Copy the files from [.ddev](.ddev) into your project's .ddev 30 | 31 | For example `cp -r .ddev/* /path/to/your/repo/.ddev` 32 | 33 | ### Required 34 | * [apache/apache-site.conf](.ddev/apache/apache-site.conf), a generic apache configuration that points to the external PHP container for PHP execution. 35 | * [docker-compose.php.yaml](.ddev/docker-compose.php.yaml) adds the service itself. 36 | 37 | ### Optional 38 | * [mysql/noutf8.cnf](.ddev/mysql/noutf8.cnf), turning off UTF8 in MariaDB. utf8mb4, required for most current sites, makes indexes too long on some older sites. 39 | 40 | ## Start the project with `ddev start` 41 | 42 | `ddev start` 43 | 44 | ## Get, load and optionally pre-condition your database dump 45 | 46 | Get your database dump and load it into the 'db' database. Use `ddev import-db` or any other technique you prefer. 47 | 48 | If older databases have `TYPE=MyISAM` in the table creation stanzas, that will need to be edited out. However, it may be possible to configure MariaDB in the .ddev/mysql directory to provide MyISAM. 49 | 50 | ## Configure the database settings for your project 51 | 52 | ddev takes no responsiblity for your settings files if you have `type: php`, so you'll need to configure your settings files. For example, on a Drupal 4.7 site, you'll need to add `$db_url = 'mysql://db:db@db/db';` to the sites/default/settings.php file. Don't forget that the *hostname* is 'db', not 'localhost' as often defaulted on many installers. (User/password/database are also 'db'.) 53 | 54 | Now, if you're paranoid, do a `ddev restart` (probably unnecessary) and begin to debug the problems you've uncovered. 55 | 56 | The site you've set up can probably be used as a migration source, can be archived, converted to HTML with a sitesucker, etc. 57 | 58 | ## Configure PHP settings 59 | You cannot set PHP settings in .htaccess unless PHP is running as an Apache module. When not run running as an Apache module, PHP loads settings from [.user.ini](https://www.php.net/manual/en/configuration.file.per-user.php). This is important for enabling Xdebug, because the .ddev/php/xdebug.ini file that normally controls Xdebug settings is not used by the Devilbox PHP container. See [example.user.ini](example.user.ini). 60 | 61 | ## Options 62 | 63 | You may need another version of PHP. As noted in [docker-compose.php.yaml](.ddev/docker-compose.php.yaml), you can easily use 5.3, 5.4, or 5.5. 64 | 65 | ## Caveats 66 | 67 | * OK, you know that these PHP versions are long out of support and this recipe is provided only to help you resurrect and port or hibernate an old site, not for presentation or production purposes. 68 | * You definitely may have to do more than listed here to get your particular site going. 69 | * I haven't experimented with getting PHP4 to work. Please provide a PR to this recipe if you get it to work. 70 | 71 | **Contributed by [@rfay](https://github.com/rfay) and [@darrenoh](https://github.com/darrenoh)** 72 | -------------------------------------------------------------------------------- /docker-compose-services/old_php/example.user.ini: -------------------------------------------------------------------------------- 1 | xdebug.remote_enable = on 2 | xdebug.remote_host = host.docker.internal 3 | -------------------------------------------------------------------------------- /docker-compose-services/php8_2/README.md: -------------------------------------------------------------------------------- 1 | # PHP8.2 (while in alpha/beta/etc) 2 | 3 | ## Update: ddev v1.21.2 now supports PHP8.2, so this is obsolete until next time. 4 | 5 | DDEV-Local will directly support PHP 8.2 as soon as possible, but not likely until the full release in late 2022. At that time this recipe will be obsolete. 6 | 7 | This version adds composer support as well as the gd, fileinfo, pdo_mysql, opcache, and curl extensions. More can easily be added in the php-build/Dockerfile. 8 | 9 | In the meantime, you can use the [official docker php image](https://hub.docker.com/_/php) (currently php:8.2.0alpha2-fpm-buster) to serve PHP. This can be updated as new versions come out. 10 | 11 | 1. Copy [docker-compose.php8_2.yaml](docker-compose.php8_2.yaml) to your project's .ddev folder. 12 | 2. Copy [nginx-site.conf](nginx-site.conf) to your .ddev/nginx_full directory (overwriting the generated file there) 13 | 3. Copy recursively the php-build directory to your project .ddev directory 14 | 4. `ddev start` 15 | 16 | On some linux versions you may have to set the UID in the `user` section of the docker-compose.php.yaml. 17 | 18 | Note that this introduces a container named `php`, which you can accesss via `ddev ssh -s php`. It has the exact same code mounted in the same place as in the `web` container, at `/var/www/html`. 19 | 20 | You can `ddev exec -s php composer install` as well, and of course you can `ddev ssh -s php` to have full access to the container and work there. 21 | 22 | You may find that your project has some problems with PHP8.1 or that PHP8 has some problems with your project :) 23 | 24 | **Contributed by [@rfay](https://github.com/rfay)** 25 | -------------------------------------------------------------------------------- /docker-compose-services/php8_2/docker-compose.php8_2.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | php: 5 | container_name: ddev-${DDEV_SITENAME}-php 6 | restart: "no" 7 | # On Linux may need to to `export UID` in your environment 8 | # or add UID in project's .ddev/.env 9 | # user: "${UID}:${UID}" 10 | build: 11 | context: './php-build' 12 | args: 13 | BASE_IMAGE: php:8.2.0alpha2-fpm-buster 14 | links: 15 | - db:db 16 | expose: 17 | - 9000 18 | labels: 19 | com.ddev.site-name: ${DDEV_SITENAME} 20 | com.ddev.approot: $DDEV_APPROOT 21 | environment: 22 | - IS_DDEV_PROJECT=true 23 | - DDEV_PHP_VERSION=8.2 24 | volumes: 25 | - type: bind 26 | source: ../ 27 | target: /var/www/html 28 | consistency: cached 29 | - ".:/mnt/ddev_config:ro" 30 | - ddev-global-cache:/mnt/ddev-global-cache 31 | 32 | web: 33 | healthcheck: 34 | # Use "true" as the healthcheck to ignore its result 35 | test: ["CMD", "true"] 36 | 37 | -------------------------------------------------------------------------------- /docker-compose-services/php8_2/nginx-site.conf: -------------------------------------------------------------------------------- 1 | # ddev drupal9 config sending to a php container 2 | 3 | server { 4 | listen 80 default_server; 5 | listen 443 ssl default_server; 6 | 7 | root /var/www/html/web; 8 | 9 | ssl_certificate /etc/ssl/certs/master.crt; 10 | ssl_certificate_key /etc/ssl/certs/master.key; 11 | 12 | include /etc/nginx/monitoring.conf; 13 | 14 | index index.php index.htm index.html; 15 | 16 | # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html 17 | sendfile off; 18 | error_log /dev/stdout info; 19 | access_log /var/log/nginx/access.log; 20 | 21 | location / { 22 | absolute_redirect off; 23 | try_files $uri $uri/ /index.php?$query_string; # For Drupal >= 7 24 | } 25 | 26 | location @rewrite { 27 | # For D7 and above: 28 | # Clean URLs are handled in drupal_environment_initialize(). 29 | rewrite ^ /index.php; 30 | } 31 | 32 | # Handle image styles for Drupal 7+ 33 | location ~ ^/sites/.*/files/styles/ { 34 | try_files $uri @rewrite; 35 | } 36 | 37 | # pass the PHP scripts to FastCGI server listening on socket 38 | location ~ '\.php$|^/update.php' { 39 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 40 | fastcgi_pass php:9000; 41 | fastcgi_buffers 16 16k; 42 | fastcgi_buffer_size 32k; 43 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 44 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 45 | fastcgi_index index.php; 46 | include fastcgi_params; 47 | fastcgi_intercept_errors off; 48 | # fastcgi_read_timeout should match max_execution_time in php.ini 49 | fastcgi_read_timeout 10m; 50 | fastcgi_param SERVER_NAME $host; 51 | fastcgi_param HTTPS $fcgi_https; 52 | } 53 | 54 | # Expire rules for static content 55 | 56 | # Prevent clients from accessing hidden files (starting with a dot) 57 | # This is particularly important if you store .htpasswd files in the site hierarchy 58 | # Access to `/.well-known/` is allowed. 59 | # https://www.mnot.net/blog/2010/04/07/well-known 60 | # https://tools.ietf.org/html/rfc5785 61 | location ~* /\.(?!well-known\/) { 62 | deny all; 63 | } 64 | 65 | # Prevent clients from accessing to backup/config/source files 66 | location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { 67 | deny all; 68 | } 69 | 70 | ## Regular private file serving (i.e. handled by Drupal). 71 | location ^~ /system/files/ { 72 | ## For not signaling a 404 in the error log whenever the 73 | ## system/files directory is accessed add the line below. 74 | ## Note that the 404 is the intended behavior. 75 | log_not_found off; 76 | access_log off; 77 | expires 30d; 78 | try_files $uri @rewrite; 79 | } 80 | 81 | # Media: images, icons, video, audio, HTC 82 | location ~* \.(png|jpg|jpeg|gif|ico|svg)$ { 83 | try_files $uri @rewrite; 84 | expires max; 85 | log_not_found off; 86 | } 87 | 88 | # js and css always loaded 89 | location ~* \.(js|css)$ { 90 | try_files $uri @rewrite; 91 | expires -1; 92 | log_not_found off; 93 | } 94 | 95 | include /etc/nginx/common.d/*.conf; 96 | include /mnt/ddev_config/nginx/*.conf; 97 | } 98 | -------------------------------------------------------------------------------- /docker-compose-services/php8_2/php-build/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PHP_EXTENSIONS="curl fileinfo gd pdo_mysql" 2 | SHELL ["bash", "-c"] 3 | 4 | RUN (apt-get update || true) && apt-get install -y -qq build-essential less libpng-dev netcat procps telnet vim zlib1g-dev 5 | RUN set -eu -o pipefail && for extension in ${PHP_EXTENSIONS}; do \ 6 | docker-php-ext-configure ${extension} && docker-php-ext-install ${extension}; \ 7 | done 8 | RUN curl -o /usr/local/bin/composer -sSL https://getcomposer.org/composer-stable.phar && chmod ugo+wx /usr/local/bin/composer 9 | COPY /usr /usr 10 | -------------------------------------------------------------------------------- /docker-compose-services/portainer/README.md: -------------------------------------------------------------------------------- 1 | # Portainer Service for DDEV 2 | 3 | This recipe allows you to mount a new container in your ddev network with Portainer as new service. 4 | 5 | Portainer is a visual mode for management of containers and networks. Is open-source tool that provides a [GUI](https://en.wikipedia.org/wiki/Graphical_user_interface) to facilitate the management of Dockerized environments and by extension, DDEV-based container networks. 6 | 7 | * More about Portainer: 8 | * [Repo: github.com/portainer](https://github.com/portainer). 9 | * [Docs: portainer.io/documentation](https://www.portainer.io/documentation/). 10 | 11 | ## Installation and Use 12 | 13 | 1. Copy [docker-compose.portainer.yaml](docker-compose.portainer.yaml) into your project's .ddev directory. 14 | 2. Run `ddev start`. 15 | 3. Access to your Portainer Interface using the same project's name, through the ports assigned in the file (9000, 8000 by default), something like: projectname.ddev.site:9000. 16 | 4. Create the new admin user of the service writing down a secure password: 17 | ![DDEV Portainer Sign up](images/davidjguru_ddev_portainer_sign_up.png) 18 | 19 | 5. Access to the reports of your containers and perform actions on them: 20 | ![DDEV Portainer Get Report](images/davidjguru_ddev_portainer_get_report.png) 21 | 22 | 6. **Be aware!** Portainer gets data from the Docker socket in your system, so you'll get information about all the existing containers in your environment, so be careful with instructions given to containers, don't make a mistake. 23 | 24 | ## Connection 25 | 26 | Ok, by default you can access to the Portainer interface at the next addresses from your browser: 27 | 28 | ``` 29 | # using http 30 | http://projectname.ddev.site:9001 31 | http://127.0.0.1:9001 32 | 33 | # or using https 34 | https://projectname.ddev.site:8001 35 | https://127.0.0.1:8001 36 | ``` 37 | **Why?** Well, we're setting the mapped ports from Host to Guest just likes this: 38 | 39 | ``` 40 | environment: 41 | HTTP_EXPOSE: "9001:9000" 42 | HTTPS_EXPOSE: "8001:9000" 43 | ``` 44 | 45 | If you want to avoid conflicts in the host side, just stop your DDEV-Local network, changing the value in the former section and relaunch the containers. 46 | 47 | Just do: 48 | 49 | ``` 50 | $ ddev stop 51 | $ vim docker-compose.portainer.yaml 52 | environment: 53 | HTTP_EXPOSE: "3401:9000" 54 | HTTPS_EXPOSE: "3501:9000" 55 | :wq! 56 | $ ddev start 57 | ``` 58 | 59 | And remember that Portainer always exposes internally to the ddev network from its port 9000 in the container, so use this address as destiny in your mapping. 60 | 61 | **Contributed by [davidjguru](https://gitlab.com/davidjguru)**, [Drupal Developer](https://www.drupal.org/u/davidjguru) and blogger in [The Russian Lullaby](https://www.therussianlullaby.com/). 62 | -------------------------------------------------------------------------------- /docker-compose-services/portainer/docker-compose.portainer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.6' 3 | services: 4 | portainer: 5 | image: portainer/portainer:latest 6 | expose: 7 | - "9000" 8 | environment: 9 | - VIRTUAL_HOST=$DDEV_HOSTNAME 10 | - HTTP_EXPOSE=9001:9000 11 | - HTTPS_EXPOSE=8001:9000 12 | restart: "no" 13 | container_name: ddev-${DDEV_SITENAME}-portainer 14 | labels: 15 | com.ddev.site-name: ${DDEV_SITENAME} 16 | com.ddev.approot: $DDEV_APPROOT 17 | volumes: 18 | - /var/run/docker.sock:/var/run/docker.sock 19 | - portainer_data:/data 20 | external_links: 21 | - "ddev-router:${DDEV_HOSTNAME}" 22 | cap_add: 23 | - SYS_ADMIN 24 | volumes: 25 | portainer_data: 26 | -------------------------------------------------------------------------------- /docker-compose-services/portainer/images/davidjguru_ddev_portainer_get_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/docker-compose-services/portainer/images/davidjguru_ddev_portainer_get_report.png -------------------------------------------------------------------------------- /docker-compose-services/portainer/images/davidjguru_ddev_portainer_sign_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/docker-compose-services/portainer/images/davidjguru_ddev_portainer_sign_up.png -------------------------------------------------------------------------------- /docker-compose-services/rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # RabbitMQ 2 | 3 | This enables a RabbitMQ service container that can be used by other containers on the same network and the host machine itself. 4 | 5 | ## Installation 6 | 7 | > [!WARNING] 8 | > This obsolete recipe has been replaced by the add-on "ochorocho/ddev-rabbitmq" (`ddev get ochorocho/ddev-rabbitmq`). 9 | > See the repository https://github.com/ochorocho/ddev-rabbitmq/ 10 | 11 | 1. Copy [docker-compose.rabbitmq.yaml](docker-compose.rabbitmq.yaml) to your project 12 | 2. Copy the directory [rabbitmq-build](rabbitmq-build) to your project. 13 | 14 | The [rabbitmq-build](rabbitmq-build) directory contains the enabled plugins, these are required for having a functioning RabbitMQ service, as the container would otherwise stop itself shortly after starting. The plugins themselves are what enables the management UI and the graphs within it. 15 | 16 | ## Configuration 17 | 18 | From within the container, the RabbitMQ container is reached at hostname: `ddev--rabbitmq`, port: 5672, so the server URL might be `amqp://ddev--rabbitmq:5672`. 19 | 20 | For more details check the connection section below. 21 | 22 | ## Connection 23 | 24 | RabbitMQ is accessible from the host machine itself as well as between the containers on the same network, and comes with a nice management UI for ease of use. 25 | 26 | __Important:__ If you need to run multiple ddev sites that use this RabbitMQ service, you will have to alter the ports per site in the [docker-compose.rabbitmq.yaml](docker-compose.rabbitmq.yaml). 27 | 28 | ### Management UI 29 | 30 | The management UI can be accessed through `http://.ddev.site:15672` on the host machine. Username "rabbitmq", password "rabbitmq". 31 | 32 | ### AMQP protocol access 33 | 34 | You can access the RabbitMQ service through it's AMQP protocol two ways: 35 | 36 | * From the host machine: `amqp://.ddev.site:5672` 37 | * From docker containers on the same docker network (ddev_default): `amqp://ddev--rabbitmq:5672` 38 | 39 | **Originally by [@Graloth](https://github.com/Graloth)** 40 | -------------------------------------------------------------------------------- /docker-compose-services/rabbitmq/docker-compose.rabbitmq.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | rabbitmq: 4 | container_name: ddev-${DDEV_SITENAME}-rabbitmq 5 | hostname: ${DDEV_SITENAME}-rabbitmq 6 | image: "rabbitmq:3-management" 7 | ports: 8 | - "15672:15672" 9 | - "5672:5672" 10 | environment: 11 | - RABBITMQ_ERLANG_COOKIE=SWQOKODSQALRPCLNMEQG 12 | - RABBITMQ_DEFAULT_USER=rabbitmq 13 | - RABBITMQ_DEFAULT_PASS=rabbitmq 14 | - RABBITMQ_DEFAULT_VHOST=/ 15 | labels: 16 | com.ddev.site-name: ${DDEV_SITENAME} 17 | com.ddev.approot: $DDEV_APPROOT 18 | volumes: 19 | - "./rabbitmq-build/enabled_plugins:/etc/rabbitmq/enabled_plugins" 20 | - ".:/mnt/ddev_config" 21 | web: 22 | links: 23 | - rabbitmq:rabbitmq 24 | volumes: 25 | rabbitmq: 26 | -------------------------------------------------------------------------------- /docker-compose-services/rabbitmq/rabbitmq-build/enabled_plugins: -------------------------------------------------------------------------------- 1 | [rabbitmq_management, rabbitmq_management_visualiser]. -------------------------------------------------------------------------------- /docker-compose-services/solr-4/README.md: -------------------------------------------------------------------------------- 1 | # Solr 4.x 2 | 3 | This recipe allows you to configure a [Solr](https://lucene.apache.org/solr/) server for your project using version 4. 4 | 5 | The Solr version used in this recipe is 4.10.4 which is not supported officially anymore. 6 | 7 | To enable Solr in your project follow these steps: 8 | 9 | 1. Create a directory named _solr_ in your project's `.ddev` directory. 10 | 1. Copy [docker-compose.solr.yml](docker-compose.solr.yml) into `.ddev`. 11 | 1. Copy the [core.properties](core.properties) into `.ddev/solr` and edit it according to your needs. 12 | 1. Create a new directory `.ddev/solr/data`. 13 | 1. Copy the configuration suitable for Solr 4.x (including `schema.xml` and `solrconfig.xml`) into a new directory named `.ddev/solr/conf`. 14 | 1. Run `ddev start`. 15 | 16 | You now have a running Solr instance for your project. To get the URL for the instance run `ddev describe`. 17 | 18 | By default the Solr core is named "dev" and the host is named "solr" so applications running inside the web container will be able to access the Solr service at `http://ddev--solr:8983`; this is also displayed by `ddev describe`. 19 | 20 | ## Creating search indexes 21 | 22 | The `ddev start` process should create the 'dev' index the first time it the 23 | project is started. However, in certain circumstances this does not happen. 24 | The solution is to manually create the index from the server: 25 | 26 | $ ddev ssh --service solr 27 | $ bin/solr create_core -c dev -d /solr-conf 28 | 29 | This uses the Solr configuration files which ddev makes available from the path `/solr-conf` and creates an index named `dev`; it should result in the following output: 30 | 31 | Copying configuration to new core instance directory: 32 | /opt/solr/server/solr/dev 33 | 34 | Creating new core 'dev' using command: 35 | http://localhost:8983/solr/admin/cores?action=CREATE&name=dev&instanceDir=dev 36 | 37 | { 38 | "responseHeader":{ 39 | "status":0, 40 | "QTime":1580}, 41 | "core":"dev"} 42 | 43 | To create a additional indexes just change the `dev` portion of the command 44 | above, e.g. 45 | 46 | $ ddev ssh --service solr 47 | $ bin/solr create_core -c myindex -d /solr-conf 48 | 49 | ## Notes 50 | 51 | If you change the name of the core in [core.properties](core.properties) you also need to update the name in [docker-compose.solr.yml](docker-compose.solr.yml), section "services > solr > volumes". 52 | 53 | ## Troubleshooting 54 | 55 | If the Solr service is not available to the client project (e.g. Drupal) using 56 | the expected URL format, the Solr index may not have been created correctly. It 57 | is possible to access Solr directly from the host OS by loading its full URL, 58 | e.g. `http://myproject.ddev.site:8983`. 59 | 60 | * The browser may redirect to https://myproject.ddev.site:8983. This is a 61 | default behavior in Safari. The solution is to either load the page in a 62 | different browser, e.g. Firefox. 63 | 64 | Once http://myproject.ddev.site:8983 or http://myproject.ddev.site:8984 loads 65 | correctly it will redirect the browser to 66 | http://myproject.ddev.site:8983/solr/#/ or 67 | https://myproject.ddev.site:8984/solr/#/, which is the main dashboard page for 68 | Solr. From here it is possible to see how much memory and swap space the system 69 | is using. 70 | 71 | To see if the index was created correctly click on the "Core Admin" link on the 72 | left menu (underneath "Dashboard" and "Logging"). This page should list the 73 | `dev` index, including when it was last updated ("lastModified") and the number 74 | of records in the index ("numDocs"). 75 | 76 | If the `dev` index is not listed, follow the instructions above to create it, 77 | then try reloading the admin page to confirm it was created as expected. 78 | 79 | --- 80 | 81 | Special thanks to [Jeff Geerling](https://www.jeffgeerling.com/) for building [Docker images](https://hub.docker.com/r/geerlingguy/solr) using versions of Apache Solr that have been deprecated long time ago. 82 | -------------------------------------------------------------------------------- /docker-compose-services/solr-4/core.properties: -------------------------------------------------------------------------------- 1 | name=dev 2 | config=solrconfig.xml 3 | schema=schema.xml 4 | dataDir=data 5 | -------------------------------------------------------------------------------- /docker-compose-services/solr-4/docker-compose.solr.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | # This is the service name used when running ddev commands accepting the 5 | # --service flag. 6 | solr: 7 | # Name of container using standard ddev convention. 8 | container_name: ddev-${DDEV_SITENAME}-solr 9 | image: geerlingguy/solr:4.10.4 10 | restart: "always" 11 | # Solr is served from this port inside the container. 12 | ports: 13 | - 8983 14 | # These labels ensure this service is discoverable by ddev. 15 | labels: 16 | com.ddev.site-name: ${DDEV_SITENAME} 17 | com.ddev.approot: $DDEV_APPROOT 18 | environment: 19 | # This defines the host name the service should be accessible from. This 20 | # will be sitename.ddev.site. 21 | - VIRTUAL_HOST=$DDEV_HOSTNAME 22 | # This defines the ports the service should be accessible from at 23 | # sitename.ddev.site. 24 | - HTTP_EXPOSE=8983 25 | volumes: 26 | # solr core *data* is stored on the 'solr' docker volume 27 | # This mount is optional; without it your search index disappears 28 | # each time the ddev project is stopped and started. 29 | - solr:/var/solr 30 | 31 | # This mounts the conf in .ddev/solr into the container. 32 | - ./solr:/opt/solr/example/solr/dev 33 | 34 | - ".:/mnt/ddev_config" 35 | 36 | # Start the server. 37 | command: ["/opt/solr/bin/solr", "start", "-p", "8983", "-f"] 38 | 39 | external_links: 40 | - "ddev-router:${DDEV_SITENAME}.${DDEV_TLD}" 41 | 42 | # This links the Solr service to the web service defined in the main 43 | # docker-compose.yml, allowing applications running inside the web container to 44 | # access the Solr service at http://solr:8983 45 | web: 46 | links: 47 | - solr:solr 48 | volumes: 49 | # solr is a persistent Docker volume for solr data 50 | # The persistent volume should have the same name as the service so it can be deleted 51 | # when the project is deleted. 52 | solr: 53 | -------------------------------------------------------------------------------- /docker-compose-services/solr-5/README.md: -------------------------------------------------------------------------------- 1 | # Solr 5 integration with DDEV 2 | 3 | The documented ApacheSolr integration with DDEV assumes a newer version of Solr. 4 | 5 | With the default integration, Solr data from old versions is not stored in a Docker volume, so it is lost during each restart. This is because Solr changed where it stored its data at some point from `/opt/solr` to `/var/solr`. 6 | 7 | The author of this document is not sure if we need both the new `/var/solr` directory and the legacy `/opt/solr` directory since both have files in them for Solr 5 and likely other versions as well. 8 | 9 | ## General documentation 10 | 11 | [DDEV Integration documentation](https://ddev.readthedocs.io/en/stable/users/extend/additional-services/#apache-solr) 12 | 13 | [Docker Solr documentation](https://hub.docker.com/_/solr/) 14 | 15 | ## Why support old versions? 16 | 17 | At the time of writing, versions lower than 7 and 8 (current version) are end-of-life (EOL), or practically unsupported. So, why support Solr 5? 18 | 19 | Some hosting providers provide only older versions or old sites are running on these unsupported versions and local development needs to match. This was created for a site that really needs a version older than 5, but 5 seems to match close-enough. 20 | 21 | The Docker Solr integration currently supports versions as old as 5. 22 | 23 | ## Differences between default `docker-compose.solr.yaml` 24 | 25 | These are the only changes. You can either make them manually or use the included file. 26 | 27 | ``` 28 | services.solr: 29 | image: solr:5 30 | volumes: 31 | - solr_var:/var/solr 32 | - solr_opt:/opt/solr 33 | volumes: 34 | solr_var: 35 | solr_opt: 36 | ``` 37 | 38 | ## Limitations 39 | 40 | DDEV has a note that it will clean up volumes that match the service name. Since we have two volumes, they can't both match the service name, so that probably won't happen and you'll have to do that manually if it's a concern for you. DDEV creates standard Docker volumes, so they can be deleted with Docker by following standard documentation. 41 | 42 | `docker volume ls` to list the volumes 43 | 44 | `docker volume rm [volume name]` to remove a volume 45 | 46 | You'll see two named something like `ddev-example_solr_opt` and `ddev-example_solr_var`. 47 | 48 | ## Creating search indexes 49 | 50 | The `ddev start` process should create the 'dev' index the first time it the 51 | project is started. However, in certain circumstances this does not happen. 52 | The solution is to manually create the index from the server: 53 | 54 | $ ddev ssh --service solr 55 | $ bin/solr create_core -c dev -d /solr-conf 56 | 57 | This uses the Solr configuration files which ddev makes available from the path `/solr-conf` and creates an index named `dev`; it should result in the following output: 58 | 59 | Copying configuration to new core instance directory: 60 | /opt/solr/server/solr/dev 61 | 62 | Creating new core 'dev' using command: 63 | http://localhost:8983/solr/admin/cores?action=CREATE&name=dev&instanceDir=dev 64 | 65 | { 66 | "responseHeader":{ 67 | "status":0, 68 | "QTime":1580}, 69 | "core":"dev"} 70 | 71 | To create a additional indexes just change the `dev` portion of the command 72 | above, e.g. 73 | 74 | $ ddev ssh --service solr 75 | $ bin/solr create_core -c myindex -d /solr-conf 76 | 77 | ## Troubleshooting 78 | 79 | If the Solr service is not available to the client project (e.g. Drupal) using 80 | the expected URL format, the Solr index may not have been created correctly. It 81 | is possible to access Solr directly from the host OS by loading its full URL, 82 | e.g. `http://myproject.ddev.site:8983`. 83 | 84 | * The browser may redirect to https://myproject.ddev.site:8983. This is a 85 | default behavior in Safari. The solution is to either load the page in a 86 | different browser, e.g. Firefox. 87 | 88 | Once http://myproject.ddev.site:8983 or http://myproject.ddev.site:8984 loads 89 | correctly it will redirect the browser to 90 | http://myproject.ddev.site:8983/solr/#/ or 91 | https://myproject.ddev.site:8984/solr/#/, which is the main dashboard page for 92 | Solr. From here it is possible to see how much memory and swap space the system 93 | is using. 94 | 95 | To see if the index was created correctly click on the "Core Admin" link on the 96 | left menu (underneath "Dashboard" and "Logging"). This page should list the 97 | `dev` index, including when it was last updated ("lastModified") and the number 98 | of records in the index ("numDocs"). 99 | 100 | If the `dev` index is not listed, follow the instructions above to create it, 101 | then try reloading the admin page to confirm it was created as expected. 102 | 103 | Contributed by [@damontgomery](https://github.com/damontgomery) 104 | -------------------------------------------------------------------------------- /docker-compose-services/solr-5/docker-compose.solr.yaml: -------------------------------------------------------------------------------- 1 | # DDev Apache Solr recipe file. 2 | # 3 | # To use this in your own project: 4 | # 1. Copy this file to your project's ".ddev" directory. 5 | # 2. Create the folder path ".ddev/solr/conf". 6 | # 3. Copy the Solr configuration files for the appropriate plugin/module to 7 | # ".ddev/solr/conf". For example, using Drupal 8's Search API Solr module, 8 | # you'll get the config files as a file config.zip from 9 | # /admin/config/search/search-api/server/solr and unzip it into .ddev/solr/conf 10 | # so that a file exists with the path ".ddev/solr/conf/solrconfig.xml". 11 | # 12 | # To access Solr after it is installed: 13 | # - The Solr admin interface will be accessible at: 14 | # http://.ddev.site:8983/solr/ 15 | # For example, if the project is named "myproject" the hostname will be: 16 | # http://myproject.ddev.site:8983/solr/ 17 | # - To access the Solr container from the web container use: 18 | # http://solr:8983/solr/ 19 | # - A Solr core is automatically created with the name "dev" unless you 20 | # change that usage throughout. It can be 21 | # accessed at the URL: http://solr:8983/solr/dev (inside web container) 22 | # or at http://myproject.ddev.site:8983/solr/dev (on the host) 23 | 24 | version: '3.6' 25 | 26 | services: 27 | solr: 28 | # Name of container using standard ddev convention 29 | container_name: ddev-${DDEV_SITENAME}-solr 30 | # The solr docker image is at https://hub.docker.com/_/solr/ 31 | # and code at https://github.com/docker-solr/docker-solr 32 | # README: https://github.com/docker-solr/docker-solr/blob/master/README.md 33 | # It's almost impossible to work with it if you don't read the docs there 34 | image: solr:5 35 | restart: "no" 36 | # Solr is served from this port inside the container. 37 | ports: 38 | - 8983 39 | # These labels ensure this service is discoverable by ddev. 40 | labels: 41 | com.ddev.site-name: ${DDEV_SITENAME} 42 | com.ddev.approot: $DDEV_APPROOT 43 | environment: 44 | # This defines the host name the service should be accessible from. This 45 | # will be sitename.ddev.site. 46 | - VIRTUAL_HOST=$DDEV_HOSTNAME 47 | # This defines the ports the service should be accessible from at 48 | # sitename.ddev.site. 49 | - HTTP_EXPOSE=8983 50 | volumes: 51 | # solr core *data* is stored on the 'solr_var' or `solr_opt` docker 52 | # volumes depending on the version of solr. 53 | - solr_var:/var/solr 54 | - solr_opt:/opt/solr 55 | 56 | # This mounts the conf in .ddev/solr into the container where 57 | # the solr-precreate command in the entrypoint uses it as a one-time 58 | # configuration to copy config into the newly-created core. It is not 59 | # used if the core has previously been created. 60 | - ./solr:/solr-conf 61 | 62 | - ".:/mnt/ddev_config" 63 | 64 | # solr-configupdate.sh copies fresh configuration files into the 65 | # solr container on each 66 | # startup, so if you change the config in .ddev/solr/conf 67 | # it will be refreshed on `ddev start`. The file must be 68 | # executable (`chmod +x .ddev/solr/solr-init.sh 69 | - "./solr/solr-configupdate.sh:/docker-entrypoint-initdb.d/solr-configupdate.sh" 70 | 71 | entrypoint: [ "sh", "-c", "docker-entrypoint.sh solr-precreate dev /solr-conf" ] 72 | 73 | external_links: 74 | - "ddev-router:${DDEV_SITENAME}.${DDEV_TLD}" 75 | 76 | # This links the Solr service to the web service defined in the main 77 | # docker-compose.yml, allowing applications running inside the web container to 78 | # access the Solr service at http://solr:8983 79 | web: 80 | links: 81 | - solr:solr 82 | volumes: 83 | # solr_var and solr_opt are a persistent Docker volumes for solr data. 84 | # They are not automatically deleted, so you may need to delete them on your 85 | # own. 86 | solr_var: 87 | solr_opt: 88 | -------------------------------------------------------------------------------- /docker-compose-services/solr-7/README.md: -------------------------------------------------------------------------------- 1 | # Solr 7 for DDEV 2 | 3 | The documented ApacheSolr integration with DDEV assumes version 8 of Solr, but the Solr docker images have different configuration locations between versions of Solr. This means that the docker-compose file and `solr-configupdate.sh` script need to be tweaked for use with Solr 7. 4 | 5 | ## General documentation 6 | 7 | * [DDEV Integration documentation](https://ddev.readthedocs.io/en/stable/users/extend/additional-services/#apache-solr) 8 | * [Docker Solr documentation](https://hub.docker.com/_/solr/) 9 | 10 | ## Installation 11 | 12 | 1. Copy the `docker-compose.solr.yaml` file and the `solr/` directory into your `.ddev/` directory 13 | 2. Copy your desired solr core configuration into the `.ddev/solr/conf/` directory 14 | * You may be able to download your hosting provider's default core configuration 15 | * You can also use the [jump start configuration](https://git.drupalcode.org/project/search_api_solr/-/tree/4.x/jump-start/solr7/config-set) from `search_api_solr` module 16 | 3. Start (or restart) ddev 17 | 18 | **Note:** If you had a different version of solr running before, you'll need to delete the previous Solr docker volume so that the Solr 7 one can be created: 19 | 20 | 1. Use `docker volume ls` to list the volumes 21 | 2. Identify your Solr volume -- it will be named with the pattern `ddev-example_solr` 22 | 3. Use `docker volume rm [volume name]` to remove the volume 23 | 24 | ## Differences between default `docker-compose.solr.yaml` 25 | 26 | If you don't want to follow the installation steps above, you can make these changes manually: 27 | 28 | ``` 29 | services.solr: 30 | image: solr:7 31 | volumes: 32 | - solr:/opt/solr 33 | ``` 34 | 35 | You'll also need to use the updated `solr-configupdate.sh` script, because the Solr 7 image uses the directory `/opt/solr/server/solr/mycores/${CORENAME}/conf`, which is different from some other versions. 36 | 37 | ## Creating search indexes 38 | 39 | The `ddev start` process should create the 'dev' index the first time it the 40 | project is started. However, in certain circumstances this does not happen. 41 | The solution is to manually create the index from the server: 42 | 43 | $ ddev ssh --service solr 44 | $ bin/solr create_core -c dev -d /solr-conf 45 | 46 | This uses the Solr configuration files which ddev makes available from the path `/solr-conf` and creates an index named `dev`; it should result in the following output: 47 | 48 | Copying configuration to new core instance directory: 49 | /opt/solr/server/solr/dev 50 | 51 | Creating new core 'dev' using command: 52 | http://localhost:8983/solr/admin/cores?action=CREATE&name=dev&instanceDir=dev 53 | 54 | { 55 | "responseHeader":{ 56 | "status":0, 57 | "QTime":1580}, 58 | "core":"dev"} 59 | 60 | To create a additional indexes just change the `dev` portion of the command 61 | above, e.g. 62 | 63 | $ ddev ssh --service solr 64 | $ bin/solr create_core -c myindex -d /solr-conf 65 | 66 | ## Troubleshooting 67 | 68 | If the Solr service is not available to the client project (e.g. Drupal) using 69 | the expected URL format, the Solr index may not have been created correctly. It 70 | is possible to access Solr directly from the host OS by loading its full URL, 71 | e.g. `http://myproject.ddev.site:8983`. 72 | 73 | Once http://myproject.ddev.site:8983 loads 74 | correctly it will redirect the browser to 75 | http://myproject.ddev.site:8983/solr/#/ which is the main dashboard page for 76 | Solr. From here it is possible to see how much memory and swap space the system 77 | is using. 78 | 79 | To see if the index was created correctly click on the "Core Admin" link on the 80 | left menu (underneath "Dashboard" and "Logging"). This page should list the 81 | `dev` index, including when it was last updated ("lastModified") and the number 82 | of records in the index ("numDocs"). 83 | 84 | If the `dev` index is not listed, follow the instructions above to create it, 85 | then try reloading the admin page to confirm it was created as expected. 86 | 87 | **Contributed by [@becw](https://github.com/becw)** 88 | -------------------------------------------------------------------------------- /docker-compose-services/solr-7/docker-compose.solr.yaml: -------------------------------------------------------------------------------- 1 | # DDev Apache Solr recipe file. 2 | # 3 | # To use this in your own project: 4 | # 1. Copy this file to your project's ".ddev" directory. 5 | # 2. Create the folder path ".ddev/solr/conf". 6 | # 3. Copy the Solr configuration files for the appropriate plugin/module to 7 | # ".ddev/solr/conf". For example, using Drupal 8's Search API Solr module, 8 | # you'll get the config files as a file config.zip from 9 | # /admin/config/search/search-api/server/solr and unzip it into .ddev/solr/conf 10 | # so that a file exists with the path ".ddev/solr/conf/solrconfig.xml". 11 | # 12 | # To access Solr after it is installed: 13 | # - The Solr admin interface will be accessible at: 14 | # http://.ddev.site:8983/solr/ 15 | # For example, if the project is named "myproject" the hostname will be: 16 | # http://myproject.ddev.site:8983/solr/ 17 | # - To access the Solr container from the web container use: 18 | # http://solr:8983/solr/ 19 | # - A Solr core is automatically created with the name "dev" unless you 20 | # change that usage throughout. It can be 21 | # accessed at the URL: http://solr:8983/solr/dev (inside web container) 22 | # or at http://myproject.ddev.site:8983/solr/dev (on the host) 23 | 24 | services: 25 | solr: 26 | # Name of container using standard ddev convention 27 | container_name: ddev-${DDEV_SITENAME}-solr 28 | # The solr docker image is at https://hub.docker.com/_/solr/ 29 | # and code at https://github.com/docker-solr/docker-solr 30 | # README: https://github.com/docker-solr/docker-solr/blob/master/README.md 31 | # It's almost impossible to work with it if you don't read the docs there 32 | image: solr:7 33 | restart: "no" 34 | # Solr is served from this port inside the container. 35 | expose: 36 | - 8983 37 | # These labels ensure this service is discoverable by ddev. 38 | labels: 39 | com.ddev.site-name: ${DDEV_SITENAME} 40 | com.ddev.approot: $DDEV_APPROOT 41 | environment: 42 | # This defines the host name the service should be accessible from. This 43 | # will be sitename.ddev.site. 44 | - VIRTUAL_HOST=$DDEV_HOSTNAME 45 | # HTTP_EXPOSE exposes http traffic from the container port 8983 46 | # to the host port 8983 vid ddev-router reverse proxy. 47 | - HTTP_EXPOSE=8983:8983 48 | volumes: 49 | # solr core *data* is stored on the 'solr' docker volume 50 | # This mount is optional; without it your search index disappears 51 | # each time the ddev project is stopped and started. 52 | - solr:/opt/solr 53 | 54 | # This mounts the conf in .ddev/solr into the container where 55 | # the solr-precreate command in the entrypoint uses it as a one-time 56 | # configuration to copy config into the newly-created core. It is not 57 | # used if the core has previously been created. 58 | - ./solr:/solr-conf 59 | 60 | - ".:/mnt/ddev_config" 61 | 62 | # solr-configupdate.sh copies fresh configuration files into the 63 | # solr container on each 64 | # startup, so if you change the config in .ddev/solr/conf 65 | # it will be refreshed on `ddev start`. The file must be 66 | # executable (`chmod +x .ddev/solr/solr-configupdate.sh`) 67 | - "./solr/solr-configupdate.sh:/docker-entrypoint-initdb.d/solr-configupdate.sh" 68 | 69 | entrypoint: [ "sh", "-c", "docker-entrypoint.sh solr-precreate dev /solr-conf" ] 70 | 71 | external_links: 72 | - "ddev-router:${DDEV_SITENAME}.${DDEV_TLD}" 73 | healthcheck: 74 | test: ["CMD-SHELL", "curl --fail -s localhost:8983/solr/"] 75 | 76 | # This links the Solr service to the web service defined in the main 77 | # docker-compose.yml, allowing applications running inside the web container to 78 | # access the Solr service at http://solr:8983 79 | web: 80 | links: 81 | - solr:solr 82 | volumes: 83 | # solr is a persistent Docker volume for solr data 84 | # The persistent volume should have the same name as the service so it can be deleted 85 | # when the project is deleted. 86 | solr: 87 | name: "ddev-${DDEV_SITENAME}_solr" 88 | -------------------------------------------------------------------------------- /docker-compose-services/solr-7/solr/conf/README.md: -------------------------------------------------------------------------------- 1 | Copy your desired solr core configuration into this directory. 2 | 3 | You may be able to download your hosting provider's default core configuration, or else you can use the [jump start configuration](https://git.drupalcode.org/project/search_api_solr/-/tree/4.x/jump-start/solr7/config-set) from `search_api_solr` module. 4 | -------------------------------------------------------------------------------- /docker-compose-services/solr-7/solr/solr-configupdate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Ensure "dev" core config is always up to date even after the 5 | # core has been created. This does not execute the first time, 6 | # when solr-precreate has not yet run. 7 | CORENAME=dev 8 | if [ -d /opt/solr/server/solr/mycores/${CORENAME}/conf ]; then 9 | # Replace existing conf dir entirely to ensure deleted config files are removed. 10 | rm -r /opt/solr/server/solr/mycores/${CORENAME}/conf 11 | cp -r /solr-conf/conf /opt/solr/server/solr/mycores/${CORENAME}/conf 12 | fi 13 | -------------------------------------------------------------------------------- /docker-compose-services/sqlsrv/Dockerfile: -------------------------------------------------------------------------------- 1 | ENV PATH="${PATH}:/opt/mssql-tools/bin" 2 | RUN (apt-get update || true) && DEBIAN_FRONTEND=noninteractive apt-get install -y -o Dpkg::Options::="--force-confold" --no-install-recommends --no-install-suggests apt-utils curl gnupg2 ca-certificates 3 | 4 | RUN curl -sSL -O https://packages.microsoft.com/keys/microsoft.asc 5 | RUN apt-key add > "/etc/php/8.0/mods-available/sqlsrv.ini" 18 | RUN echo 'extension=pdo_sqlsrv.so' >> "/etc/php/8.0/mods-available/pdo_sqlsrv.ini" 19 | 20 | RUN phpenmod sqlsrv pdo_sqlsrv 21 | -------------------------------------------------------------------------------- /docker-compose-services/sqlsrv/README.md: -------------------------------------------------------------------------------- 1 | # SQL Server (Microsoft) 2 | 3 | Using SQL server from Microsoft. 4 | 5 | ## Installation 6 | 7 | 1. Copy `docker-compose.sqlsrv.yaml` to your project's `.ddev` directory. 8 | 2. Copy `Dockerfile` to your project's `.devv/web-build` directory. 9 | 3. Copy the full post start hook commands to your project's `config.yaml` or add them to `config.sqlsrv.yaml`. 10 | 4. *(optional)* For Drupal 9+ projects: copy `install-drupal-regex-function.sh` to your project's `.ddev` directory. 11 | 12 | ## Connection 13 | 14 | Connect to `sqlsrv` host/db server from within the web container with: 15 | 16 | ``` 17 | Host: `ddev-projectname-sqlsrv` 18 | User: sa 19 | Password: password! 20 | Database: master 21 | ``` 22 | 23 | Connect to `sqlsrv` host/db server from project directory: 24 | 25 | ```bash 26 | ddev exec -s sqlsrv "/opt/mssql-tools/bin/sqlcmd -P password! -S localhost -U sa -d master" 27 | ``` 28 | 29 | For external access, use the port used in your `docker-compose.sqlsrv.yaml` and `127.0.0.1` as host. 30 | 31 | When using multiple databases in your project with SQL Server support, remember to update your `docker-compose.sqlsrv.yaml` to use different ports: 32 | 33 | ```yaml 34 | ports: 35 | - :1433 36 | ``` 37 | 38 | ## Installing the PHP extensions 39 | 40 | The PHP extensions for SQL Server CANNOT be installed by adding them to the `webimage_extra_packages` setting. The problem is that they are not available as a Debian or any other distribution package. The 2 extensions (`sqlsrv` and `pdo_sqlsrv`) need to be compiled and this needs to be done after PHP is installed on the webimage. The following commands need to be copied to the end of the main `config.yaml` file: 41 | 42 | ```yaml 43 | hooks: 44 | post-start: 45 | - exec: echo export PATH="$PATH:/opt/mssql-tools/bin" >> ~/.bashrc 46 | - exec: source ~/.bashrc 47 | ``` 48 | 49 | The minimum required PHP version the these extensions is PHP 7.3. For more information about these extension, see: [MS SQL driver for PHP](https://github.com/microsoft/msphpsql). 50 | 51 | 52 | ## Drupal Notice 53 | 54 | Drupal CMS needs the a database function installed that is mimicking the Regex function as Drupal requires. As a one-time setup for Drupal, install the database function by running the following command from your project's directory: 55 | 56 | ```bash 57 | ./install-drupal-regex-function.sh -u -p -d 58 | ``` 59 | 60 | This script also changes the setting for the following database variables: 61 | * `show advanced options` will be set to 1 62 | * `clr strict security` will be set to 0 63 | * `clr enable` will be set to 1 64 | 65 | Drupal also the module `sqlsrv` to be installed as it is providing the database driver for SQL Server. The module can be installed with composer with the following command: 66 | 67 | ```bash 68 | $ php composer require drupal/sqlsrv 69 | ``` 70 | 71 | ## Disabling MySQL & MariaSQL 72 | 73 | * If your project only uses a SQL Server database, you can disable the MySql & MariaDb services. 74 | * Run the following command from your project root. 75 | 76 | ```bash 77 | ddev config --omit-containers db 78 | ``` 79 | 80 | * Alternatively, you can update your project's `.ddev/config.yaml` directly by updating the following line: 81 | 82 | ```yaml 83 | omit_containers: [db] 84 | ``` 85 | 86 | * See [.ddev/config.yaml Options](https://ddev.readthedocs.io/en/stable/users/extend/config_yaml/) for additional notes. 87 | 88 | ## TODO 89 | 90 | Future enhancements (PR's welcome here) include: 91 | 92 | * Provide custom commands. 93 | 94 | ## Links with useful information 95 | 96 | * [SQL Server docker hub](https://hub.docker.com/_/microsoft-mssql-server) 97 | * [Installing the ODBC driver for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server) 98 | * [Installing the ODBC driver for SQL Server Tutorial](https://docs.microsoft.com/en-us/sql/connect/php/installation-tutorial-linux-mac) 99 | * [Installation tutorial for MS drivers for PHP](https://docs.microsoft.com/en-us/sql/connect/php/installation-tutorial-linux-mac) 100 | * [The SQLCMD utility](https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility) 101 | * [The SQL Server on Linux](https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-overview) 102 | * [The password policy](https://docs.microsoft.com/en-us/sql/relational-databases/security/password-policy) 103 | * [The SQL Server environment variables](https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-configure-environment-variables) 104 | * [Beakerboy's Drupal Regex database function](https://github.com/Beakerboy/drupal-sqlsrv-regex) 105 | * [Drupal's module for the SQL Server](https://www.drupal.org/project/sqlsrv) 106 | * [Github MS drivers for PHP](https://github.com/microsoft/msphpsql) 107 | -------------------------------------------------------------------------------- /docker-compose-services/sqlsrv/docker-compose.sqlsrv.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | sqlsrv: 5 | container_name: ddev-${DDEV_SITENAME}-sqlsrv 6 | hostname: ddev-${DDEV_SITENAME}-sqlsrv 7 | 8 | # For possible options: https://hub.docker.com/_/microsoft-mssql-server. 9 | # This does not yet work with Apple M1. See: https://github.com/microsoft/mssql-docker/issues/734 10 | image: mcr.microsoft.com/mssql/server:2019-CU12-ubuntu-20.04 11 | 12 | user: root 13 | volumes: 14 | - sqlsystem:/var/opt/mssql/ 15 | restart: "no" 16 | ports: 17 | - "1433:1433" 18 | labels: 19 | com.ddev.site-name: ${DDEV_SITENAME} 20 | com.ddev.approot: $DDEV_APPROOT 21 | environment: 22 | 23 | # With the following setting you agree with Microsoft's end user license 24 | # agreement. 25 | - 'ACCEPT_EULA=Y' 26 | 27 | # The SQL Server enforces password complexity. Trying to set a password 28 | # that is not sufficiently complex will result in the password not be set. 29 | # As a result you cannot login with the "SA" user account. 30 | # The password for the SA account needs to follow the following policy: 31 | # https://docs.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver15 32 | - 'SA_PASSWORD=Password12!' 33 | 34 | # The following setting is for selecting the SQL Server edition or product 35 | # key. For possible options: 36 | # https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-configure-environment-variables?view=sql-server-ver15 37 | - 'MSSQL_PID=Evaluation' 38 | 39 | # Sets the default collation for SQL Server. This setting is optional. The 40 | # current setting is best for Drupal projects. For more information, see: 41 | # https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver15 42 | - 'MSSQL_COLLATION=LATIN1_GENERAL_100_CI_AS_SC_UTF8' 43 | 44 | # For more possible environment variables that can be set, see: 45 | # https://docs.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver15 46 | 47 | web: 48 | links: 49 | - sqlsrv:sqlsrv 50 | 51 | volumes: 52 | sqlsystem: 53 | -------------------------------------------------------------------------------- /docker-compose-services/sqlsrv/install-drupal-regex-function.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Installs the Regex database function for compatibility with Drupal version 9 or higher. 3 | # This script only needs to be run once for a database. 4 | 5 | usage() { echo "./install-drupal-regex-function.sh -u -p -d " 1>&2; exit 1; } 6 | 7 | # The password for the database defaults to "" 8 | password="" 9 | 10 | # The username for the database defaults to "SA" 11 | username="SA" 12 | 13 | # The database name defaults to "master" 14 | database="master" 15 | 16 | while getopts ":u:p:d:h:" arg; do 17 | case $arg in 18 | u) 19 | username=${OPTARG} 20 | ;; 21 | p) 22 | password=${OPTARG} 23 | ;; 24 | d) 25 | database=${OPTARG} 26 | ;; 27 | h) 28 | usage 29 | ;; 30 | *) 31 | usage 32 | ;; 33 | esac 34 | done 35 | 36 | if [ -z $password ] 37 | then 38 | echo "The parameter -p for the password is not set." 39 | exit 1 40 | fi 41 | 42 | if ! ddev exec -s sqlsrv test -e "/RegEx.dll" &>/dev/null; 43 | then 44 | # Download the Regex.dll file and copy it to the right location. 45 | ddev exec -s sqlsrv wget https://github.com/Beakerboy/drupal-sqlsrv-regex/releases/download/1.0/RegEx.dll 46 | fi 47 | 48 | # The following are changed to allow the installation and execution of the user provided database function. 49 | ddev exec -s sqlsrv "/opt/mssql-tools/bin/sqlcmd -P $password -S localhost -U $username -d $database -Q 'EXEC sp_configure \"show advanced options\", 1; RECONFIGURE; EXEC sp_configure \"clr strict security\", 0; RECONFIGURE; EXEC sp_configure \"clr enable\", 1; RECONFIGURE;'" 50 | 51 | # Create the assambly and the function for the Regex helper. 52 | ddev exec -s sqlsrv "/opt/mssql-tools/bin/sqlcmd -P $password -S localhost -U $username -d $database -Q 'CREATE ASSEMBLY Regex from \"/RegEx.dll\" WITH PERMISSION_SET = SAFE'" 53 | ddev exec -s sqlsrv "/opt/mssql-tools/bin/sqlcmd -P $password -S localhost -U $username -d $database -Q 'CREATE FUNCTION dbo.REGEXP(@pattern NVARCHAR(100), @matchString NVARCHAR(100)) RETURNS bit EXTERNAL NAME Regex.RegExCompiled.RegExCompiledMatch'" 54 | 55 | # **Contributed by [@drupal-daffie](https://github.com/drupal-daffie)** 56 | -------------------------------------------------------------------------------- /docker-compose-services/typo3-solr/README.md: -------------------------------------------------------------------------------- 1 | # TYPO3-specific Apache Solr Integration for DDEV-Local 2 | 3 | Although ddev has [documented generic Solr support](https://ddev.readthedocs.io/en/stable/users/extend/additional-services/#apache-solr) it is as simple as possible, and supports only a single core named "dev". 4 | 5 | The TYPO3 extension assumes a different approach and a slightly different Solr image. 6 | 7 | These instructions were tested with TYPO3 LTS v9.5. 8 | 9 | Resources: 10 | 11 | * ApacheSolrForTypo3 EXT:Solr [docs (master)](https://docs.typo3.org/p/apache-solr-for-typo3/solr/master/en-us/) 12 | * [typo3solr/ext-solr](https://hub.docker.com/r/typo3solr/ext-solr/) Solr image on hub.docker.com. 13 | * [typo3solr Slack Channel](https://typo3.slack.com/messages/ext-solr/) (request your invite for TYPO3 Slack at ) 14 | * [Original Stack Overflow Tutorial](https://stackoverflow.com/questions/51479399/how-to-set-up-solr-server-for-typo3-using-ddev) that this is based on. 15 | 16 | 1. Add the solr extension to your project: `ddev composer require apache-solr-for-typo3/solr` 17 | 2. Deactivate and then re-activate the "Apache Solr for TYPO3" module to make sure that its database tables get installed: `ddev typo3 extension:deactivate solr && ddev typo3 extension:activate solr` 18 | 3. Copy [docker-compose.solr.yaml](docker-compose.solr.yaml) to your project's .ddev folder. 19 | 4. If you want your solr data to be persistent across `ddev restart`, then uncomment the `- solrdata:/var/solr` line in docker-compose.solr.yaml. The comments there explain what you have to do if you want to start over. It's recommended to wait to uncomment that until you have everything else working. 20 | 5. Copy the default Solr configuration from Ext:Solr to ddev: 21 | * `mkdir -p .ddev/solr` 22 | * TYPO3 v12 and above: `cp -r vendor/apache-solr-for-typo3/solr/Resources/Private/Solr/* .ddev/solr` 23 | * TYPO3 v11 and below: `cp -r public/typo3conf/ext/solr/Resources/Private/Solr/* .ddev/solr` 24 | * You will have `configsets`, `cores`, `solr.xml` and `zoo.cfg` in .ddev/solr. 25 | 6. `ddev restart` will bring up the new solr container. 26 | 7. On the TYPO3 backend "Sites" module, choose your site 27 | * Make sure that on the "General" tab a full URL is specified for "Entry Point". Just using "/" here results in a failure of the extension. 28 | * On the "Solr" tab (far right) set "Host" to "solr" (NOT the default "localhost") 29 | * On the "Languages" tab configure a Corename at the bottom of the page ("English" selected on the right-hand select widget will result in "core_en" being selected.) 30 | * Save configuration 31 | 8. On the "Template" module, edit your site/page and 32 | * Choose "Info/Modify" in the select widget at the top of the pane 33 | * Click "Edit the whole template record" at the bottom. 34 | * Click the "Includes" tab" 35 | * Add "Search - Base Configuration (solr)" and "Search - Default Stylesheets (solr)" to the "Selected Items" pane and save. 36 | 9. "Flush all caches" using the lightning bolt icon on top of the screen. 37 | 10. Click the "Apache Solr" "Info" module on the left and choose your site, you should see that it has connected the Apache Solr server. 38 | 11. Click "Index Queue" module under "Apache Solr" and 39 | 40 | * Click the checkbox to initialize all pages. 41 | * Queue all pages for indexing 42 | * "Index now" as needed to create the index. 43 | 44 | At this point you should have the core_en core populated with an index. 45 | 46 | Visit `http://.ddev.site:8983/solr` to use the Solr admin dashboard. If you visit the "Core Admin" and choose "core_en" to see statistics about indexed documents, etc. 47 | 48 | Now revisit the [EXT:Solr docs](https://docs.typo3.org/p/apache-solr-for-typo3/solr/master/en-us/Index.html) for help with specific configuration, including templating for quality indexing, etc. 49 | 50 | When everything is working, consider enabling the `- solrdata:/var/solr` line in .ddev/docker-compose.solr.yaml so you'll have persistent Solr data. If the docker volume accidentally already had data in it, then stop the project and delete the volume with `docker rm ddev-_solrdata` before you restart. 51 | -------------------------------------------------------------------------------- /docker-compose-services/typo3-solr/docker-compose.solr.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | solr: 5 | container_name: ddev-${DDEV_SITENAME}-solr 6 | image: typo3solr/ext-solr:10.0.1 7 | restart: "no" 8 | expose: 9 | - 8983 10 | labels: 11 | com.ddev.site-name: ${DDEV_SITENAME} 12 | com.ddev.approot: $DDEV_APPROOT 13 | environment: 14 | - VIRTUAL_HOST=$DDEV_HOSTNAME 15 | - HTTP_EXPOSE=8983 16 | volumes: 17 | - "./solr:/opt/solr/server/solr" 18 | # If you want your solr to persist over `ddev stop` and `ddev start` then uncomment the following line 19 | # If you uncomment it and want to flush your data you have to `ddev stop` and then 20 | # `docker volume rm ddev-_solrdata` to destroy it. 21 | # - solr:/var/solr 22 | web: 23 | links: 24 | - solr 25 | 26 | volumes: 27 | # solr is a persistent Docker volume for this project's solr data 28 | # the volume will be named ddev-_solr 29 | solr: 30 | -------------------------------------------------------------------------------- /docker-compose-services/varnish/README.md: -------------------------------------------------------------------------------- 1 | # Varnish 2 | 3 | This recipe allows you to configure a Varnish reverse proxy for your project. 4 | 5 | The Varnish service inserts itself between ddev-router and the web container, so that calls 6 | to the web container are routed through Varnish first. The [docker-compose.varnish.yaml](https://github.com/ddev/ddev-contrib/blob/master/docker-compose-services/varnish/docker-compose.varnish.yml) 7 | replaces the ```VIRTUAL_HOST``` variable of the web container with a subdomain of 8 | the website URL (see below) and uses the default domain as its own host name. 9 | 10 | To enable Varnish in your project follow these steps: 11 | 12 | 1. Copy [docker-compose.varnish.yaml](https://github.com/ddev/ddev-contrib/blob/master/docker-compose-services/varnish/docker-compose.varnish.yml) into your project's .ddev directory. 13 | 2. Create a directory named _varnish_ in your project's .ddev directory. 14 | 3. Copy the [default.vcl](default.vcl) in this directoy. 15 | 4. Run `ddev start`. 16 | 5. From now on calls to the web container (e.g. `https://example.ddev.site`) are 17 | routed through Varnish. If you would like to access the site without Varnish, 18 | simply prepend the URL with _novarnish._ (e.g. `https://novarnish.example.ddev.site`). 19 | 20 | --- 21 | 22 | Based on the work of [rikwillems](https://github.com/rikwillems). 23 | -------------------------------------------------------------------------------- /docker-compose-services/varnish/default.vcl: -------------------------------------------------------------------------------- 1 | # Simple default VCL. 2 | # 3 | # For a more advanced example see https://github.com/mattiasgeniar/varnish-6.0-configuration-templates 4 | 5 | vcl 4.1; 6 | 7 | backend default { 8 | .host = "web"; 9 | .port = "80"; 10 | } 11 | -------------------------------------------------------------------------------- /docker-compose-services/varnish/docker-compose.varnish.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | # This is the service name used when running ddev commands accepting the 5 | # --service flag. 6 | varnish: 7 | # This is the name of the container. It is recommended to follow the same 8 | # name convention used in the main docker-compose.yml file. 9 | container_name: ddev-${DDEV_SITENAME}-varnish 10 | # Use "varnish:latest" to get the latest stable image. 11 | image: varnish:6.4 12 | # These labels ensure this service is discoverable by ddev. 13 | labels: 14 | com.ddev.site-name: ${DDEV_SITENAME} 15 | com.ddev.approot: $DDEV_APPROOT 16 | environment: 17 | # This defines the host name the service should be accessible from. This 18 | # will be sitename.ddev.site. 19 | # This is the first half of the trick that puts varnish "in front of" the 20 | # web container, just by switching the names. 21 | - VIRTUAL_HOST=$DDEV_HOSTNAME 22 | # This defines the ports the service should be accessible from at 23 | # sitename.ddev.site. 24 | - HTTPS_EXPOSE=443:80,8026:8025 25 | - HTTP_EXPOSE=80:80,8025:8025 26 | volumes: 27 | # This exposes a mount to the host system `.ddev/varnish` directory where 28 | # your default.vcl should be. 29 | - "./varnish:/etc/varnish" 30 | - ".:/mnt/ddev_config" 31 | links: 32 | - web:web 33 | # This is the second half of the trick that puts varnish "in front of" the web 34 | # container, just by switching the names. 35 | web: 36 | environment: 37 | - VIRTUAL_HOST=novarnish.$DDEV_HOSTNAME 38 | -------------------------------------------------------------------------------- /docker-compose-snippets/environment-variable/docker-compose.env.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | web: 5 | environment: 6 | - TYPO3_CONTEXT=Development 7 | -------------------------------------------------------------------------------- /docker-compose-snippets/mounting-directory/README.md: -------------------------------------------------------------------------------- 1 | # Mounting a directory into web container 2 | 3 | This simple [docker-compose.mount.yaml](docker-compose.mount.yaml) just mounts a directory from the host into the web container. 4 | 5 | Caveats: 6 | 7 | * The source directory on the host must be shared via docker. 8 | * If the mount should be read-only in the container, add `:ro` to the mount 9 | -------------------------------------------------------------------------------- /docker-compose-snippets/mounting-directory/docker-compose.mount.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | web: 4 | volumes: 5 | # The source (here /Users/rfay/tmp) must be in an area shared by docker 6 | # You can target any directory you want as long as the parent exists (here /mnt) 7 | - "/Users/rfay/tmp:/mnt/in-container:ro" 8 | -------------------------------------------------------------------------------- /docker-compose-snippets/phpmyadmin-user-settings/README.md: -------------------------------------------------------------------------------- 1 | # Configuring phpmyadmin through a user settings file 2 | 3 | This simple [docker-compose.phpmyadmin.yaml](docker-compose.phpmyadmin.yaml) just mounts a file from the host into the dba container. 4 | 5 | You can create a directory in the `.ddev` folder named `phpmyadmin`. In there you can create a custom settings file `config.user.inc.php`. 6 | 7 | When you restart ddev, the settings file will be used when starting phpmyadmin. 8 | 9 | Example file contents of `config.user.inc.php`: 10 | 11 | ```php 12 | `. 14 | 15 | ``` 16 | hooks: 17 | post-start: 18 | - exec: /var/www/html/import-if-empty.sh 19 | - exec: echo 'other post-start hooks will now be executed' 20 | ``` 21 | -------------------------------------------------------------------------------- /hook-examples/import-db-if-empty/import-if-empty.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set TABLETOFIND to a table which should exist in a loaded database 4 | TABLETOFIND=users 5 | 6 | if ! mysql -e "SELECT * FROM ${TABLETOFIND};" db >/dev/null 2>&1; then 7 | echo "loading database since table named '${TABLETOFIND}' was not found." 8 | # This assumes the db.sql.gz is in the root of your repository, but 9 | # adjust as necessary. 10 | gzip -dc /var/www/html/.tarballs/d8composer.sql.gz | mysql db 11 | else 12 | echo "NOT loading database; it already exists; table '${TABLETOFIND}' was found." 13 | fi 14 | -------------------------------------------------------------------------------- /recipes/bludit-cms/README.md: -------------------------------------------------------------------------------- 1 | # Install [Bludit CMS](https://www.bludit.com/) with DDEV 2 | 3 | ## What is Bludit 4 | 5 | Bludit is an open source content managment system. Its a flat file cms which means that you dont need a database for it, bludit saves everything in the folders. You can read more about that, in the Bludit Documentation for the [Folder Structure](https://docs.bludit.com/en/developers/folder-structure). 6 | 7 | ## Installation 8 | 9 | Installation is the same as for any general-purpose PHP or HTML project, you get the code and then use `ddev config` and `ddev start`. 10 | 11 | Clone the git repository for bludit: `git clone https://github.com/bludit/bludit.git` 12 | 13 | ## Configure ddev 14 | 15 | * Use `ddev config --project-type=php` to configure the project. 16 | 17 | ## Start ddev and install Bludit 18 | 19 | * `ddev start` 20 | * Visit the selected URL (like `https://bludit.ddev.site`) to install Bludit. 21 | * To see complete ddev project information, use `ddev describe`. 22 | 23 | ## Original Author: [@crydotsnake](https://twitter.com/crydotsnake) 24 | -------------------------------------------------------------------------------- /recipes/civicrm/README.md: -------------------------------------------------------------------------------- 1 | # Install [CiviCRM](https://civicrm.org/) with DDEV 2 | 3 | ## What is CiviCRM 4 | 5 | [CiviCRM](https://civicrm.org/) is an open source Customer Relationship Management solution for nonprofit and civic sector organizations. It is a highly customizable CRM, used by a diverse range of organizations around the world and translated into dozens of languages. 6 | 7 | 8 | ## Configure DDEV 9 | 10 | CiviCRM should work with the latest version of your favorite CMS, so create an instance of DDEV, for example [Drupal 10](https://ddev.readthedocs.io/en/latest/users/quickstart/#drupal). 11 | 12 | 13 | ## Install CiviCRM 14 | 15 | See https://docs.civicrm.org/installation/en/latest/drupal/. Other CMS'es, such as Backdrop, Joomla, or WordPress are also supported. 16 | 17 | For Drupal 10, download CiviCRM with this command. Study the guide above for details: 18 | 19 | `ddev composer require civicrm/civicrm-{core,packages,drupal-8}` 20 | 21 | 22 | ## Import separate CiviCRM database, configure database and template settings 23 | 24 | It was previously recommended to use two separate databases: One for the CMS, and one for CiviCRM. Currently, the recommendation is: 25 | 26 | > It is also possible to install CiviCRM on a separate database. As a rule of thumb: 27 | > 28 | > - A shared database works well for small deployments (eg a few thousand records and a single administrator or developer). 29 | > - Separate databases work well for large deployments (eg a million records and multiple administrators/developers). 30 | 31 | https://docs.civicrm.org/installation/en/latest/general/requirements/#mysql-connection 32 | 33 | If you need to restore a separate CiviCRM database in DDEV, first restore the Drupal installation files and database. 34 | 35 | To set up DDEV, for example for a non-Composer Drupal 7 and CiviCRM with PHP 7.4, run this command: 36 | 37 | `ddev config --project-type drupal7 --php-version 7.4 --docroot . --project-name civicrm` 38 | 39 | Restore your Drupal 7 installation, and then import the CiviCRM database with this command: 40 | 41 | `ddev import-db --database=cividb --file=cividb.sql` 42 | 43 | **Note**: The extra database `cividb` will not be included if you run `ddev describe`. 44 | 45 | ### `civicrm.settings.php` 46 | 47 | Comment out the server settings, and use these values in your `civicrm.settings.php` file, inserted right after global `$civicrm_root;` if you want to keep them in one place: 48 | 49 | ``` 50 | global $civicrm_root; 51 | 52 | /* LOCAL DEVELOPMENT */ 53 | define( 'CIVICRM_UF_DSN' , 'mysql://db:db@db:3306/cividb?new_link=true' ); 54 | define( 'CIVICRM_DSN' , 'mysql://db:db@db:3306/cividb?new_link=true' ); 55 | define('CIVICRM_LOGGING_DSN', CIVICRM_DSN); 56 | $civicrm_root = '/var/www/html/sites/all/modules/civicrm'; 57 | define( 'CIVICRM_TEMPLATE_COMPILEDIR', '/var/www/html/sites/default/files/civicrm/templates_c/' ); 58 | define( 'CIVICRM_UF_BASEURL' , 'https://civicrm.ddev.site/' ); 59 | ``` 60 | 61 | --- 62 | 63 | **Contributed by [@gitressa](https://github.com/gitressa)** 64 | -------------------------------------------------------------------------------- /recipes/cronjob/README.md: -------------------------------------------------------------------------------- 1 | # Running TYPO3 Cron inside the web container 2 | 3 | **OBSOLETE: This recipe is obsolete in favor of `ddev get ddev/ddev-cron`, see [ddev-cron](https://github.com/ddev/ddev-cron) for more details*** 4 | 5 | This recipe provides two completely different techniques to do TYPO3 cron inside the web container. 6 | 7 | * Enable Linux cron on `ddev start` and have it run the TYPO3 cron every minute or 8 | * Just run a custom command (`ddev cron`) which will `ddev exec` the TYPO3 cron process every 60 seconds. (Run it in a separate window.) 9 | 10 | ## Enable cronjob on start or on demand 11 | 12 | 1. Install the `ddev cron` custom command [commands/web/cron](commands/web/cron) in your .ddev/commands/web directory. Make sure that it's executable (`chmod +x .ddev/commands/web/cron`). This allows you to simulate a real cron job by just running `ddev cron` in a separate window and it 13 | 2. Place [config.cron.yml](config.cron.yml) in the .ddev directory (or add it to your .ddev/config.yaml); it will run the custom `ddev cron` command on project start, which will run a cronjob for typo3 scheduler:run every minute. 14 | 3. Change config.cron.yml to use your username instead of "root" in the first hook. (You can verify your in-container username with `ddev exec id -un`). (So for user rfay, `- exec: echo '*/1 * * * * root TYPO3_CONTEXT=Development/Local /usr/bin/php /var/www/html/public/typo3/sysext/core/bin/typo3 scheduler:run' | sudo tee -a /etc/cron.d/typo3` would become `- exec: echo '*/1 * * * * rfay TYPO3_CONTEXT=Development/Local /usr/bin/php /var/www/html/public/typo3/sysext/core/bin/typo3 scheduler:run' | sudo tee -a /etc/cron.d/typo3`) 15 | 16 | ## Run TYPO3 cron via `ddev exec` from a separate window 17 | 18 | To run the TYPO3 cron process every 60 seconds, use the `ddev cron` custom command provided here. 19 | 20 | 1. Install [commands/web/cron](commands/web/cron) into your project's .ddev/commands/web directory. 21 | 2. Make it executable (`chmod +x .ddev/commands/web/cron`) 22 | 3. After starting the project, run `ddev cron` in a separate window and let it do its job. 23 | 24 | **Contributed by [@thomaskieslich](https://github.com/thomaskieslich)** 25 | -------------------------------------------------------------------------------- /recipes/cronjob/commands/web/cron: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ## Description: Run typo3 scheduler:run on every minute 4 | ## Usage: cron 5 | ## Example: "ddev cron" 6 | 7 | while true 8 | do 9 | sleep 60 10 | /var/www/html/vendor/bin/typo3 scheduler:run 11 | done 12 | -------------------------------------------------------------------------------- /recipes/cronjob/config.cron.yml: -------------------------------------------------------------------------------- 1 | webimage_extra_packages: [cron] 2 | 3 | hooks: 4 | post-start: 5 | - exec: echo '*/1 * * * * root TYPO3_CONTEXT=Development/Local /usr/bin/php /var/www/html/public/typo3/sysext/core/bin/typo3 scheduler:run' | sudo tee -a /etc/cron.d/typo3 6 | - exec: sudo chmod 0600 /etc/cron.d/typo3 && sudo service cron start 7 | -------------------------------------------------------------------------------- /recipes/drupal7-subfolder/README.md: -------------------------------------------------------------------------------- 1 | # Drupal 7 in a subfolder of a main site 2 | 3 | This is a public summary of what we had to do to make DDEV work with a Drupal 7 site subfolder setup. 4 | 5 | A Drupal site might be operated from a subfolder (subdirectory) of a domain. Example for such a URL: 6 | 7 | * No Subfolder frontpage: `https://example.com` 8 | * Subfolder frontpage: `https://example.com/jobs` 9 | 10 | That means the Drupal site only lives in the `/jobs` part. A reverse proxy sits in front of the production site and delivers requests either to the main page "/" or the Drupal site at "/jobs. 11 | 12 | The organization of your site might look like this, with a top-level index.html (or some full main site) and a subdirectory named "jobs" which contains a Drupal 7 site. DDEV is configured in the top-level directory: 13 | 14 | ```text 15 | ├── .ddev (Config for top-level site) 16 | └── config.yaml 17 | └── nginx_full 18 | └── nginx-site.conf 19 | ├── index.html (Top-level site) 20 | ├── jobs (Drupal 7 folder) 21 | ├── CHANGELOG.txt 22 | ├── README.txt 23 | ├── cron.php 24 | ├── index.php 25 | ├── install.php 26 | ├── modules 27 | ├── sites 28 | ├── themes 29 | └── xmlrpc.php 30 | └── sites 31 | └── default 32 | ``` 33 | 34 | ## Simulating a subfolder setup in DDEV 35 | 36 | In order to have a development environment that mimics the production site subfolder as much as possible we want to run DDEV also with a URL subfolder. We need to change a couple of things for that. 37 | 38 | An example top-level index.html might look like this: 39 | 40 | ```html 41 |

This is the main site

42 | You could go to the JOBS site if you wanted to. It's in a subdirectory. 43 | ``` 44 | 45 | ### Demo repository with the .ddev config folder 46 | 47 | See [https://github.com/jobiqo/drupal7-subfolder](https://github.com/jobiqo/drupal7-subfolder). 48 | 49 | ### Nginx 50 | 51 | Nginx needs two rewrite rules for the `/jobs` subfolder (replace /jobs with your subfolder name). Change the provided [dot.ddev/nginx_full/nginx-site.conf](dot.ddev/nginx_full/nginx-site.conf) to change "jobs" to the subdirectory you need, and put it in your project's `.ddev/nginx_full` directory. You could easily duplicate "jobs" with other subdirectories. See also [DDEV-Local nginx configuration docs](https://ddev.readthedocs.io/en/stable/users/extend/customization-extendibility/#providing-custom-nginx-configuration) 52 | 53 | Copy the full [nginx-site.conf](dot.ddev/nginx_full/nginx-site.conf) into your project's .ddev/nginx_full directory (overwriting the ddev-generated one that may be there) and then change "jobs" to whatever your subdirectory is. 54 | 55 | ### Base URL 56 | 57 | We want the site to be reachable at `https://example.ddev.site/jobs` . We need to set the base URL for Drupal so achieve that. Add a settings.php copy hook in `.ddev/config.yaml`: 58 | 59 | ``` 60 | hooks: 61 | pre-start: 62 | - exec-host: cp -f sites/default/ddev-subfolder.settings.php sites/default/settings.php 63 | ``` 64 | 65 | Create [sites/default/ddev-subfolder.settings.php](sites/default/ddev-subfolder.settings.php): 66 | 67 | ```php 68 | $base_url"; 90 | exit; 91 | } 92 | ``` 93 | 94 | That should be it! 95 | 96 | ## Contributed by [@klausi](https://github.com/klausi) 97 | -------------------------------------------------------------------------------- /recipes/drupal7-subfolder/dot.ddev/config.yaml: -------------------------------------------------------------------------------- 1 | name: drupal7-subfolder 2 | type: drupal7 3 | docroot: "" 4 | php_version: "7.2" 5 | router_http_port: "80" 6 | router_https_port: "443" 7 | xdebug_enabled: false 8 | provider: default 9 | use_dns_when_possible: true 10 | 11 | hooks: 12 | pre-start: 13 | - exec-host: cp -f sites/default/ddev-subfolder.settings.php sites/default/settings.php 14 | 15 | -------------------------------------------------------------------------------- /recipes/drupal7-subfolder/dot.ddev/nginx_full/nginx-site.conf: -------------------------------------------------------------------------------- 1 | # ddev drupal7 config 2 | 3 | # This file is overridden from DDEV because we need Nginx customizations for the 4 | # /jobs subfolder setup. 5 | 6 | 7 | server { 8 | listen 80; 9 | listen 443 ssl; 10 | 11 | root /var/www/html; 12 | 13 | ssl_certificate /etc/ssl/certs/master.crt; 14 | ssl_certificate_key /etc/ssl/certs/master.key; 15 | 16 | include /etc/nginx/monitoring.conf; 17 | 18 | index index.php index.htm index.html; 19 | 20 | # Make site accessible from http://localhost/ 21 | server_name _; 22 | 23 | # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html 24 | sendfile off; 25 | error_log /dev/stdout info; 26 | access_log /var/log/nginx/access.log; 27 | 28 | # Rewrite the /jobs subfolder. 29 | # Special rule for the front page: we need to pass "/" explicitly here to 30 | # $_GET['q'] and PHP. This is not done by Nginx automatically and then 31 | # Drupal falls back to the full request URI which would include the 32 | # subfolder /jobs. 33 | rewrite ^/jobs/?$ /index.php?q=/&$args last; 34 | rewrite ^/jobs/(.*)$ /$1 last; 35 | 36 | location / { 37 | absolute_redirect off; 38 | 39 | # First attempt to serve request as file, then 40 | # as directory, then fall back to index.html 41 | try_files $uri $uri/ /index.php?q=$uri&$args; 42 | } 43 | 44 | location @rewrite { 45 | # For D7 and above: 46 | # Clean URLs are handled in drupal_environment_initialize(). 47 | rewrite ^ /index.php?q=$uri&$args; 48 | } 49 | 50 | # Handle image styles for Drupal 7+ 51 | location ~ ^/sites/.*/files/styles/ { 52 | try_files $uri @rewrite; 53 | } 54 | 55 | # pass the PHP scripts to FastCGI server listening on socket 56 | location ~ \.php$ { 57 | try_files $uri =404; 58 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 59 | fastcgi_pass unix:/run/php-fpm.sock; 60 | fastcgi_buffers 16 16k; 61 | fastcgi_buffer_size 32k; 62 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 63 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 64 | fastcgi_index index.php; 65 | include fastcgi_params; 66 | fastcgi_intercept_errors off; 67 | # fastcgi_read_timeout should match max_execution_time in php.ini 68 | fastcgi_read_timeout 10m; 69 | fastcgi_param SERVER_NAME $host; 70 | fastcgi_param HTTPS $fcgi_https; 71 | } 72 | 73 | # Expire rules for static content 74 | # Feed 75 | location ~* \.(?:rss|atom)$ { 76 | expires 1h; 77 | } 78 | 79 | # Media: images, icons, video, audio, HTC 80 | location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { 81 | try_files $uri @rewrite; 82 | expires max; 83 | log_not_found off; 84 | } 85 | 86 | # Prevent clients from accessing hidden files (starting with a dot) 87 | # This is particularly important if you store .htpasswd files in the site hierarchy 88 | # Access to `/.well-known/` is allowed. 89 | # https://www.mnot.net/blog/2010/04/07/well-known 90 | # https://tools.ietf.org/html/rfc5785 91 | location ~* /\.(?!well-known\/) { 92 | deny all; 93 | } 94 | 95 | # Prevent clients from accessing to backup/config/source files 96 | location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { 97 | deny all; 98 | } 99 | 100 | ## Regular private file serving (i.e. handled by Drupal). 101 | location ^~ /system/files/ { 102 | ## For not signaling a 404 in the error log whenever the 103 | ## system/files directory is accessed add the line below. 104 | ## Note that the 404 is the intended behavior. 105 | log_not_found off; 106 | access_log off; 107 | expires 30d; 108 | try_files $uri @rewrite; 109 | } 110 | 111 | include /mnt/ddev_config/nginx/*.conf; 112 | } 113 | -------------------------------------------------------------------------------- /recipes/drupal7-subfolder/sites/default/ddev-subfolder.settings.php: -------------------------------------------------------------------------------- 1 | $base_url"; 23 | exit; 24 | } 25 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/README.md: -------------------------------------------------------------------------------- 1 | # DDEV-Local Drupal 8 Multisite Recipe 2 | 3 | DDEV supports Drupal 8 multisite, however it is not always obvious what changes need to be done to make it work. Additionally, sometimes setup helpful for single-site configuration blocks the desired behavior for a multi-site setup. 4 | 5 | This example will show how to setup a basic two-site multisite configuration, covering ddev, database, drush, and other issues. It has been tested on macOS, but should work anywhere. 6 | 7 | Neither of the sites will be default to ensure that if something is misconfigured, commands will fail against incomplete Drupal site instance instead of silently running against wrong one. 8 | 9 | ## Initial DDEV-Local and Drupal 8 setup 10 | 11 | Let's mostly follow the suggested configuration in [the official DDEV documentation for Drupal 8 setup](https://ddev.readthedocs.io/en/stable/users/cli-usage/#drupal-8-quickstart). 12 | 13 | ``` 14 | mkdir d8m 15 | cd d8m 16 | ddev config --project-type=drupal8 --docroot=web --create-docroot --disable-settings-management 17 | ddev composer create drupal/recommended-project 18 | ddev composer remove drupal/core-project-message 19 | ddev composer require drush/drush 20 | ddev restart 21 | ddev describe 22 | ``` 23 | 24 | Note that we used `--disable-settings-management` with `ddev config`. THis prevents ddev from trying to be helpful by creating settings files for Drupal or drush. But it means that we are completely in charge of our settings files. 25 | 26 | This gets us to the basic Drupal 8 site using composer setup At this point, if you go to the assigned URL ( you will see Drupal's site creation dialogue. Let's leave that as is and not configure the default site. 27 | 28 | Let's create two sites: 29 | 30 | * **basic** - using *standard* install profile 31 | * **umami** - using *umami* install profile 32 | 33 | ## Prepare the databases and URLs 34 | 35 | The file `.ddev/config.yaml` is where additional URLs are setup and where we can use hooks to create the databases. However, it may be better to use [a separate override config file](https://ddev.readthedocs.io/en/stable/users/extend/customization-extendibility/#extending-configyaml-with-custom-configyaml-files) to keep that information more clear and easier to track. The combination of sites may also be different on each individual machine, so this file may or may not be checked into the version control. 36 | 37 | To setup the databases, we can add the command into the *post-start* hook. And the hostnames are declared in *additional_hostnames* options. 38 | 39 | So, let's setup an `.ddev/config.multisite.yaml` with additional information for both of our sites. Notice that while it is possible to have multiple config files, they specific options override each other, not extend. So, it is not possible to have one extension config file per site. 40 | 41 | 1. Copy [example config.multisite.yaml](dot.ddev/config.multisite.yaml) to your setup's .ddev directory. 42 | 2. ddev restart 43 | 44 | You should get a message that additional domains are now available: 45 | 46 | > Your project can be reached at 47 | 48 | ## Enable multisite 49 | 50 | First we need to enable the multisite support by copying `example.sites.php` to `sites.php`. And then, because we are using DDEV for development and our production URLs will be different from test URLs, we want to define explicit aliases. That also allows us to have nice site directory names. 51 | 52 | ``` 53 | cd web/sites 54 | mkdir basic umami 55 | cp example.sites.php sites.php 56 | ``` 57 | 58 | 1. Configure sites in the sites.php to match the URL with the correct directory. 59 | 2. If you know the production URLs, you can add them at the same time. 60 | 61 | The final `sites.php` should look something like the [example included](web/sites/sites.php). 62 | 63 | ## Provide a base settings.base.php 64 | 65 | Since the settings.php for each subsite is nearly the same, we can use a basic settings file and include it in each subsite. The example provided here is [web/sites/default/settings.base.php](web/sites/default/settings.base.php). Copy that into the `web/sites/default` directory of your project. 66 | 67 | ## Prepare example umami site 68 | 69 | Inspect [web/sites/umami/settings.php](web/sites/umami/settings.php) and copy it to `web/sites/umami`. 70 | 71 | Now, if `drush status -l umami.ddev.site` is run from within the *web* container's `sites/umami` directory (that is after executing `ddev ssh`), the output should look similar to following: 72 | 73 | ``` 74 | web/sites/umami$ $ drush status -l umami.ddev.site 75 | Drupal version : 8.8.4 76 | Site URI : http://umami.ddev.site 77 | DB driver : mysql 78 | DB port : 79 | DB username : db 80 | DB name : umami 81 | PHP binary : /usr/bin/php7.3 82 | PHP config : /etc/php/7.3/cli/php.ini 83 | PHP OS : Linux 84 | Drush script : /usr/local/bin/drush 85 | Drush version : 10.2.2 86 | Drush temp : /tmp 87 | Drush configs : /var/www/html/vendor/drush/drush/drush.yml 88 | Drupal root : /var/www/html/web 89 | Site path : sites/umami 90 | ``` 91 | 92 | If *Site path* looks different or DB information is missing, that means something has gone wrong. 93 | 94 | ## Install the umami demo site 95 | 96 | Now, visiting will show the site creation form. Going through the form and setting the values and defaults (including *Demo: Umami* profile) will create the Umami Food Magazine site. 97 | 98 | Notice that visiting either or still shows the site creation form. 99 | 100 | And reruning `drush status` inside the `sites/umami` directory inside the *web* container should now show additional information from the initialized site. 101 | 102 | ## Install the "basic" demo site 103 | 104 | We can follow the same steps as we did for "umami" for the "basic" site. We already have the directory, URL, database, and `sites.php` setup. So all that needs to be done is: 105 | 106 | 1. Inspect [web/sites/basic/settings.php](web/sites/basic/settings.php) and copy it to `web/sites/basic`. 107 | 2. Visit `https://basic.ddev.site` and install the site with the *Standard* profile 108 | 109 | Now, we have a simple Drupal site at a food magazine at and still only a configuration form at the original 110 | 111 | ## Set up drush site aliases 112 | 113 | [Drush site aliases](http://docs.drush.org/en/9.x/usage/#site-aliases) can address individual sites without being in the specific directory inside the web container. 114 | 115 | We'll set the *root* and *uri* parameters to point to the Drupal root (within container) and the full url to the site instance. 116 | 117 | 1. `mkdir -p drush/sites && cd drush/sites` 118 | 2. Inspect and copy the sample aliases files in [drush/sites](drush/sites) into your project's drush/sites directory. 119 | 3. Run `ddev exec drush site:alias` from outside the container to check that the alias is recognized 120 | 4. Run `ddev exec drush @umami.ddev status` to check that all site-specific information is now present, including full *Site URI* 121 | 5. Run `ddev exec drush @basic.ddev status` to check that the alias is working for the second site too. 122 | 6. Run `ddev exec drush status` to see what the default configuration still shows. 123 | 124 | ## Add more sites 125 | 126 | Now that we have a basic setup in place, new site requires us to: 127 | 128 | 1. Update ddev's [config.multisite.yaml](dot.ddev/config.multisite.yaml) to add the database and set the additional_hostnames (remember to run `ddev restart` to pick up the changes). This can also be done directly in the .ddev/config.yaml. 129 | 2. Create a directory for the new site in `web/sites/`. 130 | 3. Copy `settings.php` to the new directory and update the database name. 131 | 4. Add new alias to the `sites.php`. 132 | 5. Copy a drush alias and updating the `uri` option. 133 | 6. Visit each new site to install Drupal. 134 | 135 | **Contributed by [@arafalov](https://github.com/arafalov)** 136 | **Major updates and reviews by [@amitaibu](https://github.com/amitaibu)** 137 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/dot.ddev/config.multisite.yaml: -------------------------------------------------------------------------------- 1 | additional_hostnames: 2 | - basic 3 | - umami 4 | hooks: 5 | post-start: 6 | - exec: mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS basic; GRANT ALL ON basic.* to 'db'@'%';" 7 | service: db 8 | - exec: mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS umami; GRANT ALL ON umami.* to 'db'@'%';" 9 | service: db 10 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/drush/sites/basic.site.yml: -------------------------------------------------------------------------------- 1 | ddev: 2 | root: /var/www/html/web/sites/basic 3 | uri: https://basic.ddev.site 4 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/drush/sites/d8m.yml: -------------------------------------------------------------------------------- 1 | ddev: 2 | root: /var/www/html/web 3 | uri: https://d8m.ddev.site 4 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/drush/sites/umami.site.yml: -------------------------------------------------------------------------------- 1 | ddev: 2 | root: /var/www/html/web/sites/umami 3 | uri: https://umami.ddev.site 4 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/web/sites/basic/settings.php: -------------------------------------------------------------------------------- 1 | "db", 22 | 'username' => "db", 23 | 'password' => "db", 24 | 'host' => $host, 25 | 'driver' => "mysql", 26 | 'port' => $port, 27 | 'prefix' => "", 28 | ); 29 | 30 | ini_set('session.gc_probability', 1); 31 | ini_set('session.gc_divisor', 100); 32 | ini_set('session.gc_maxlifetime', 200000); 33 | ini_set('session.cookie_lifetime', 2000000); 34 | 35 | $settings['hash_salt'] = 'mHewfhRYNyqRPBnAZIBvUgmMBbpcuKwzSowSDHcCFmUYLBKrHPjlBekBEIaYxVzv'; 36 | 37 | // This will prevent Drupal from setting read-only permissions on sites/default. 38 | $settings['skip_permissions_hardening'] = TRUE; 39 | 40 | // This will ensure the site can only be accessed through the intended host 41 | // names. Additional host patterns can be added for custom configurations. 42 | $settings['trusted_host_patterns'] = ['.*']; 43 | 44 | // Don't use Symfony's APCLoader. ddev includes APCu; Composer's APCu loader has 45 | // better performance. 46 | $settings['class_loader_auto_detect'] = FALSE; 47 | 48 | // This specifies the default configuration sync directory. 49 | // $config_directories (pre-Drupal 8.8) and 50 | // $settings['config_sync_directory'] are supported 51 | // so it should work on any Drupal 8 or 9 version. 52 | if (defined('CONFIG_SYNC_DIRECTORY') && empty($config_directories[CONFIG_SYNC_DIRECTORY])) { 53 | $config_directories[CONFIG_SYNC_DIRECTORY] = 'sites/default/files/sync'; 54 | } 55 | elseif (empty($settings['config_sync_directory'])) { 56 | $settings['config_sync_directory'] = 'sites/default/files/sync'; 57 | } 58 | -------------------------------------------------------------------------------- /recipes/drupal8-multisite/web/sites/sites.php: -------------------------------------------------------------------------------- 1 | 39 | 40 | PHP CodeSniffer configuration for Drupal website development. 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | RoboFile.php 49 | web/modules/custom 50 | web/themes/custom 51 | 52 | 53 | ./.ddev 54 | ./vendor 55 | ./web/core 56 | ./web/libraries 57 | ./web/modules/contrib 58 | ./web/themes/contrib 59 | ./web/sites 60 | 61 | 62 | ./config 63 | 64 | 65 | 66 | 67 | 68 | ``` 69 | 70 | #### Resources 71 | 72 | - https://www.drupal.org/node/1419988 73 | - https://www.drupal.org/docs/contributed-modules/code-review-module/php-codesniffer-command-line-usage 74 | 75 | 76 | ## Usage 77 | 78 | - Once installed the hook will run on `pre-commit`, checking files to be commited. 79 | - Add ignored files/files in your `phpcs.xml` file. 80 | 81 | --- 82 | 83 | **Contributed by [@bserem](https://github.com/bserem)** 84 | -------------------------------------------------------------------------------- /recipes/git-hooks/pre-commit-phpcs/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Run pre-commit check PHP script inside ddev when committing from host. 4 | if [ "$IS_DDEV_PROJECT" != true ]; then 5 | ddev exec /usr/bin/php scripts/git/pre-commit-phpcs.php 6 | else 7 | /usr/bin/php scripts/git/pre-commit-phpcs.php 8 | fi 9 | -------------------------------------------------------------------------------- /recipes/git-hooks/pre-commit-phpcs/pre-commit-phpcs.php: -------------------------------------------------------------------------------- 1 | /dev/null', $files, $return); 19 | $against = ($return == 0) ? 'HEAD' : '4b825dc642cb6eb9a060e54bf8d69288fbee4904'; 20 | 21 | // Identify changed files. 22 | exec("git diff-index --cached --name-only $against", $files); 23 | 24 | print "\nPrecommit PHPCS\n\n"; 25 | 26 | foreach ($files as $file) { 27 | 28 | if (file_exists($file) && !is_dir($file)) { 29 | 30 | // Perform PHP syntax check (lint). 31 | $return = 0; 32 | $lint_cmd = "php -l {$file}"; 33 | $lint_output = []; 34 | exec($lint_cmd, $lint_output, $return); 35 | if ($return !== 0) { 36 | // Format error messages and set exit code. 37 | $exit_code = 1; 38 | } 39 | 40 | // Perform phpcs test. 41 | $return = 0; 42 | $phpcs_cmd = 'phpcs ' . $file; 43 | $phpcs_output = []; 44 | exec($phpcs_cmd, $phpcs_output, $return); 45 | if ($return !== 0) { 46 | // Format error messages and set exit code. 47 | echo implode("\n", $phpcs_output), "\n"; 48 | $exit_code = 1; 49 | } 50 | } 51 | } 52 | 53 | exit($exit_code); 54 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/README.md: -------------------------------------------------------------------------------- 1 | # Laravel: Horizon 2 | 3 | This is an step-by-step guide to install [Laravel Horizon](https://laravel.com/docs/master/horizon) into your project. 4 | This expects the project to already have an working laravel project. 5 | 6 | ## Steps 7 | 8 | 1. Install redis using 9 | the [service example](https://github.com/ddev/ddev-contrib/blob/master/docker-compose-services/redis) 10 | 2. Configure the redis configuration in `.env` 11 | 3. Run `ddev composer require laravel/horizon` 12 | 4. Run `ddev artisan horizon:install` 13 | 5. Run horizon process in DDEV Installation 14 | 15 | * Option A: Run using nohup 16 | 17 | Copy the `dot.ddev/config.laravel-horizon.yaml` into your project's .ddev directory, or incorporate it into your .ddev/config.yaml. This snipped uses a post-start hook to use artisan to start the horizon process. 18 | 19 | * Option B: Run using supervisor 20 | 21 | Use both `dot.ddev/web-build/Dockerfile` and `dot.ddev/web-build/horizon.conf` 22 | 23 | 6. Run `ddev restart` 24 | 7. Configure your horizon configuration to your liking; see horizon documentation for reference 25 | 26 | You are set! As configured in the supervisor or nohup command the logs are written in `/storage/logs/horizon.log`. 27 | 28 | **Inspired 29 | by [laravel-queue-worker](https://github.com/ddev/ddev-contrib/blob/master/web-container-dockerfiles/laravel-queue-worker) 30 | by [@karlshea](https://github.com/karlshea)** 31 | 32 | **Contributed by [@bmoex](https://github.com/bmoex)** 33 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/config/database.php: -------------------------------------------------------------------------------- 1 | [ 17 | 18 | 'client' => 'phpredis', 19 | 20 | 'default' => [ 21 | 'host' => env('REDIS_HOST', '127.0.0.1'), 22 | 'password' => env('REDIS_PASSWORD', null), 23 | 'port' => env('REDIS_PORT', 6379), 24 | 'database' => 0, 25 | ], 26 | 27 | ], 28 | // .. 29 | ]; 30 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/dot.ddev/config.laravel-horizon.yaml: -------------------------------------------------------------------------------- 1 | hooks: 2 | post-start: 3 | - exec: "nohup bash -c '/var/www/html/artisan horizon &' > /var/www/html/storage/logs/horizon.log" 4 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/dot.ddev/web-build/Dockerfile: -------------------------------------------------------------------------------- 1 | # Add horizon supervisor 2 | ADD horizon.conf /etc/supervisor/conf.d 3 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/dot.ddev/web-build/horizon.conf: -------------------------------------------------------------------------------- 1 | [program:horizon] 2 | process_name=%(program_name)s 3 | command=php /var/www/html/artisan horizon 4 | autostart=true 5 | autorestart=true 6 | redirect_stderr=true 7 | stdout_logfile=/var/www/html/storage/logs/horizon.log 8 | stopwaitsecs=3600 9 | -------------------------------------------------------------------------------- /recipes/laravel-horizon/dot.env: -------------------------------------------------------------------------------- 1 | # Configure redis queue to be used 2 | QUEUE_DRIVER=redis 3 | 4 | # Configure redis host from docker container 5 | REDIS_HOST=redis 6 | REDIS_PASSWORD=redis 7 | -------------------------------------------------------------------------------- /recipes/proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | # This is a Dockerfile for use with the ddev-webserver image 2 | # It should be in .ddev/web-build/Dockerfile 3 | # and then you can expand on it. 4 | # If HTTP_PROXY is set in the docker environment, then add the same proxy configuration 5 | # into apt system in the Debian-based ddev-webserver image at 6 | # /etc/apt/apt.conf.d/proxy.conf 7 | # This is only needed if the apt subsystem must be used *after* the image is built, 8 | # for example in a post-start hook. 9 | RUN if [ ! -z "${HTTP_PROXY}" ]; then printf "Acquire {\nHTTP::proxy \"$HTTP_PROXY\";\nHTTPS::proxy \"$HTTPS_PROXY\";\n}\n" > /etc/apt/apt.conf.d/proxy.conf ; fi 10 | # You can add additional Dockerfile build activities here. 11 | -------------------------------------------------------------------------------- /recipes/proxy/README.md: -------------------------------------------------------------------------------- 1 | # Using ddev behind a corporate web proxy (obsolete) 2 | 3 | **This recipe is now obsolete. Please use [ddev get ddev/ddev-proxy-support](https://github.com/ddev/ddev-proxy-support)** 4 | 5 | Some of us have to live with web proxies for access to the internet. There are loads of implications of this. Web browsers are great with proxies, as they've had to deal with them from the beginning of web browsing. But in a complex container environment there are loads of other things to think about, including curl, apt-get, docker containers, etc. 6 | 7 | There are 4 basic things that need to work in a behind-proxy ddev environment: 8 | 9 | 1. The host needs to be configured to work. Of course if you're already working in a proxied environment you already know how to do this. Typically it's set up in the OS settings, and then the browsers are configured to use the system proxy settings. curl typically respects HTTP_PROXY and HTTPS_PROXY, and wget will respect http_proxy, etc. 10 | 11 | 2. The docker server needs to be configured via either: 12 | 13 | * The "proxies" section of the Docker Desktop application (on Windows or macOS) or 14 | * by creating an `/etc/systemd/system/docker.service.d/http-proxy.conf` file on Linux - 15 | [see Docker docs](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy) . This will allow actions like `docker pull` to work correctly using the proxy. See [example http-proxy.conf](http-proxy.conf). 16 | 17 | If you use the first approach, you need to set the "http proxy server" and "https proxy server" to point to your proxy, and add "127.0.0.1" to the proxy bypass settings in Docker Desktop (Settings -> Resources -> Proxies). 18 | 19 | Example: 20 | 21 | * Web Server (HTTP) : `http://proxy:8888` 22 | * Secure Web Server (HTTPS) : `http://proxy:8888` 23 | * Bypass proxy settings for these hosts & domains: `127.0.0.1` 24 | 25 | 3. Normally, on Windows and macOS, the settings above will be reflected in ~/.docker/config.json, but if not they can be added there as shown in [Docker docs](https://docs.docker.com/network/proxy/). Again, you need to add the HTTP and HTTPS proxyes, and add ``"noProxy": 127.0.0.1`. 26 | 27 | 4. Individual images may need to be set up to make apt work inside them. This is optional, because if you do your apt-get work at container build time (in a .ddev/web-build/Dockerfile) then everything works using the host configuration. See the [example .ddev/web-build/Dockerfile](Dockerfile). 28 | 29 | ## Lab-testing a proxied environment 30 | 31 | I used Parallels on macOS for the test lab. 32 | 33 | * Created a Parallels VM proxy server with a simple tiny Ubuntu 18.04 server running [tinyproxy](https://tinyproxy.github.io/), which was shockingly simple to install and configure (`apt-get install tinyproxy`), very small configuration changes ([example /etc/tinyproxy/tinyproxy.conf](tinyproxy.conf)). I'll call this machine "proxy". 34 | * Added an additional "host-only" interface in Parallels and added it to the proxy VM 35 | * Used an existing (different) Ubuntu 18.04 Parallels VM as the ddev/docker environment and added the host only interface to it. I'll call this machine "workstation". 36 | * Turned off the primary network interface in the workstation, so it had no direct network connectivity, verified that ping of internet addresses failed. 37 | * Configured the workstation VM with system-wide proxy settings using the regular Ubuntu network setting GUI (in this case HTTP/HTTPS proxies using 10.37.129.4). 38 | * Configured the Firefox browser on "workstation" to use the system-configured proxy and verified that it could now operate. 39 | * Verified that curl against internet https locations now worked on the "workstation". 40 | * Configured the docker server as in step 2 above, and verified that `docker pull ubuntu` now worked on "workstation" using the proxy. 41 | * Configured the docker client as in step 3 above and verified that proxy setup was now right in the container by `ddev start`, `ddev ssh`, and using curl inside the container against an HTTPS website. 42 | * Added the .ddev/web-build/Dockerfile from step 4 into the ddev project on the "workstation" and `ddev start`, then `ddev ssh` and `sudo apt-get update` and saw the update happen successfully, all using the proxy. 43 | -------------------------------------------------------------------------------- /recipes/proxy/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxies": 3 | { 4 | "default": 5 | { 6 | "httpProxy": "http://10.37.129.4:8888", 7 | "httpsProxy": "http://10.37.129.4:8888", 8 | "noProxy": "*.ddev.site,localhost,127.0.0.1" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /recipes/proxy/http-proxy.conf: -------------------------------------------------------------------------------- 1 | [Service] 2 | Environment="HTTP_PROXY=http://10.37.129.4:8888/" 3 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/README.md: -------------------------------------------------------------------------------- 1 | # Puppeteer Headless Chrome support 2 | 3 | Npm packages like codeceptjs or critical-css-webpack-plugin which depend on [Puppeteer](https://github.com/puppeteer/puppeteer/) will not be able to run from within the web container because of some missing Linux libraries. 4 | 5 | You can add Puppeteer support by setting the following extra Debian packages to your ddev `config.yaml` file: 6 | 7 | ```yaml 8 | webimage_extra_packages: [gconf-service, libasound2, libatk1.0-0, libcairo2, libgconf-2-4, libgdk-pixbuf2.0-0, libgtk-3-0, libnspr4, libpango-1.0-0, libpangocairo-1.0-0, libx11-xcb1, libxcomposite1, libxcursor1, libxdamage1, libxfixes3, libxi6, libxrandr2, libxrender1, libxss1, libxtst6, fonts-liberation, libappindicator1, libnss3, xdg-utils] 9 | ``` 10 | 11 | ## Puppeteer CSS Demo 12 | 13 | You will find a proof of concept in the [demo](demo/) folder. 14 | 15 | It is based on the [Tailwind CSS Landing Page starter project](https://github.com/tailwindtoolbox/Landing-Page) and demonstrate how to use [Webpack Encore](https://symfony.com/doc/current/frontend.html) to compile javascript and css resources and extract critical CSS with critical-css-webpack-plugin from within the ddev web container. 16 | 17 | Obviously, the PHP part is quite minimalistic and is just used to read the webpack manifest file to inject relevant javascript and css files and inline the critical css file in the landing page. However, the overall workflow can easily be adapted in a more complex PHP project using a CMS or a framework. 18 | 19 | ### Startup 20 | 21 | For the root of the [demo](demo/) folder, start the ddev environment: 22 | 23 | ``` 24 | ddev start 25 | ``` 26 | 27 | The provided `.ddev/config.yaml` is pre-configured to include the needed webimage_extra_packages in order to run the critical-css-webpack-plugin. 28 | 29 | ### Installation 30 | 31 | This project comes with a custom yarn command for convenience. To install the node dependencies, run `ddev yarn install` 32 | 33 | ### Generate the webpack assets and the critical CSS file 34 | 35 | Run `ddev yarn build` 36 | 37 | This will generate optimized javascript and css files in `web/webpack-assets` folder along with the critical css file in the `web/criticalcss` folder using the critical-css-webpack-plugin. 38 | 39 | Under the hood, critical-css-webpack-plugin will instantiate a headless Chrome using Puppeteer to access the landing page hosted by ddev in order to extact relevant critical css. 40 | 41 | At that stage you should be able to view the landing page at `https://demo.ddev.site`. 42 | 43 | You can see how the plugin is triggered by opening the `webpack.config.js` configuration file. 44 | 45 | A `yarn dev` and `yarn watch` scripts are also provided as examples. 46 | 47 | ## Original Author: [@juban](https://github.com/juban) 48 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/.ddev/commands/web/yarn: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Description: Run yarn command inside the web container 4 | ## Usage: yarn [flags] [args] 5 | 6 | yarn $@ 7 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/.ddev/config.yaml: -------------------------------------------------------------------------------- 1 | name: demo 2 | type: php 3 | docroot: web 4 | php_version: "7.3" 5 | webserver_type: nginx-fpm 6 | router_http_port: "80" 7 | router_https_port: "443" 8 | xdebug_enabled: false 9 | additional_hostnames: [] 10 | additional_fqdns: [] 11 | provider: default 12 | use_dns_when_possible: true 13 | 14 | webimage_extra_packages: [gconf-service, libasound2, libatk1.0-0, libcairo2, libgconf-2-4, libgdk-pixbuf2.0-0, libgtk-3-0, libnspr4, libpango-1.0-0, libpangocairo-1.0-0, libx11-xcb1, libxcomposite1, libxcursor1, libxdamage1, libxfixes3, libxi6, libxrandr2, libxrender1, libxss1, libxtst6, fonts-liberation, libappindicator1, libnss3, xdg-utils] 15 | 16 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@fullhuman/postcss-purgecss": "^2.1.0", 4 | "@symfony/webpack-encore": "^0.28.3", 5 | "autoprefixer": "^9.7.4", 6 | "critical": "^1.3.9", 7 | "critical-css-webpack-plugin": "^0.2.0", 8 | "cross-env": "^7.0.2", 9 | "postcss": "^7.0.27", 10 | "postcss-loader": "^3.0.0", 11 | "purgecss": "^2.1.0", 12 | "sane": "^4.1.0" 13 | }, 14 | "dependencies": { 15 | "tailwindcss": "^1.2.0" 16 | }, 17 | "scripts": { 18 | "dev": "cross-env encore dev", 19 | "watch": "cross-env encore dev --watch", 20 | "build": "cross-env NODE_ENV=production encore production --progress" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/postcss.config.js: -------------------------------------------------------------------------------- 1 | const tailwindcss = require('tailwindcss'); 2 | const autoprefixer = require('autoprefixer'); 3 | const purgecss = require("@fullhuman/postcss-purgecss"); 4 | 5 | module.exports = { 6 | from: "src/styles.css", 7 | to: "web/css/styles.css", 8 | plugins: [ 9 | tailwindcss('./tailwind.config.js'), 10 | autoprefixer(), 11 | process.env.NODE_ENV === 'production' && purgecss({ 12 | content: [ 13 | "./web/*.php" 14 | ], 15 | whitelistPatternsChildren: [], 16 | defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) 17 | }) 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/src/main.js: -------------------------------------------------------------------------------- 1 | var scrollpos = window.scrollY; 2 | var header = document.getElementById("header"); 3 | var navcontent = document.getElementById("nav-content"); 4 | var navaction = document.getElementById("navAction"); 5 | var brandname = document.getElementById("brandname"); 6 | var toToggle = document.querySelectorAll(".toggleColour"); 7 | 8 | document.addEventListener('scroll', function () { 9 | 10 | /*Apply classes for slide in bar*/ 11 | scrollpos = window.scrollY; 12 | 13 | if (scrollpos > 10) { 14 | header.classList.add("bg-white"); 15 | navaction.classList.remove("bg-white"); 16 | navaction.classList.add("gradient"); 17 | navaction.classList.remove("text-gray-800"); 18 | navaction.classList.add("text-white"); 19 | //Use to switch toggleColour colours 20 | for (var i = 0; i < toToggle.length; i++) { 21 | toToggle[i].classList.add("text-gray-800"); 22 | toToggle[i].classList.remove("text-white"); 23 | } 24 | header.classList.add("shadow"); 25 | navcontent.classList.remove("bg-gray-100"); 26 | navcontent.classList.add("bg-white"); 27 | } else { 28 | header.classList.remove("bg-white"); 29 | navaction.classList.remove("gradient"); 30 | navaction.classList.add("bg-white"); 31 | navaction.classList.remove("text-white"); 32 | navaction.classList.add("text-gray-800"); 33 | //Use to switch toggleColour colours 34 | for (var i = 0; i < toToggle.length; i++) { 35 | toToggle[i].classList.add("text-white"); 36 | toToggle[i].classList.remove("text-gray-800"); 37 | } 38 | 39 | header.classList.remove("shadow"); 40 | navcontent.classList.remove("bg-white"); 41 | navcontent.classList.add("bg-gray-100"); 42 | 43 | } 44 | 45 | }); 46 | 47 | /*Toggle dropdown list*/ 48 | /*https://gist.github.com/slavapas/593e8e50cf4cc16ac972afcbad4f70c8*/ 49 | 50 | var navMenuDiv = document.getElementById("nav-content"); 51 | var navMenu = document.getElementById("nav-toggle"); 52 | 53 | document.onclick = check; 54 | 55 | function check(e) { 56 | var target = (e && e.target) || (event && event.srcElement); 57 | 58 | //Nav Menu 59 | if (!checkParent(target, navMenuDiv)) { 60 | // click NOT on the menu 61 | if (checkParent(target, navMenu)) { 62 | // click on the link 63 | if (navMenuDiv.classList.contains("hidden")) { 64 | navMenuDiv.classList.remove("hidden"); 65 | } else { 66 | navMenuDiv.classList.add("hidden"); 67 | } 68 | } else { 69 | // click both outside link and outside menu, hide menu 70 | navMenuDiv.classList.add("hidden"); 71 | } 72 | } 73 | 74 | } 75 | 76 | function checkParent(t, elm) { 77 | while (t.parentNode) { 78 | if (t == elm) { 79 | return true; 80 | } 81 | t = t.parentNode; 82 | } 83 | return false; 84 | } 85 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/src/styles.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700'); 2 | 3 | /** 4 | * This injects Tailwind's base styles, which is a combination of 5 | * Normalize.css and some additional base styles. 6 | * 7 | * You can see the styles here: 8 | * https://github.com/tailwindcss/tailwindcss/blob/master/css/preflight.css 9 | * 10 | * If using `postcss-import`, use this import instead: 11 | * 12 | * @import "tailwindcss/preflight"; 13 | */ 14 | /*noinspection CssInvalidAtRule*/ 15 | @tailwind base; 16 | 17 | /** 18 | * This injects any component classes registered by plugins. 19 | * 20 | * If using `postcss-import`, use this import instead: 21 | * 22 | * @import "tailwindcss/components"; 23 | */ 24 | /*noinspection CssInvalidAtRule*/ 25 | @tailwind components; 26 | 27 | /** 28 | * Here you would add any of your custom component classes; stuff that you'd 29 | * want loaded *before* the utilities so that the utilities could still 30 | * override them. 31 | * 32 | * Example: 33 | 34 | * .btn { ... } 35 | * .form-input { ... } 36 | * 37 | * Or if using a preprocessor or `postcss-import`: 38 | * 39 | * @import "components/buttons"; 40 | * @import "components/forms"; 41 | */ 42 | 43 | 44 | /** 45 | * This injects all of Tailwind's utility classes, generated based on your 46 | * config file. 47 | * 48 | * If using `postcss-import`, use this import instead: 49 | * 50 | * @import "tailwindcss/utilities"; 51 | */ 52 | /*noinspection CssInvalidAtRule*/ 53 | @tailwind utilities; 54 | 55 | /** 56 | * Here you would add any custom utilities you need that don't come out of the 57 | * box with Tailwind. 58 | * 59 | * Example : 60 | * 61 | * .bg-pattern-graph-paper { ... } 62 | * .skew-45 { ... } 63 | * 64 | * Or if using a preprocessor or `postcss-import`: 65 | * 66 | * @import "utilities/background-patterns"; 67 | * @import "utilities/skew-transforms"; 68 | */ 69 | 70 | .gradient { 71 | background: linear-gradient(90deg, #d53369 0%, #daae51 100%); 72 | } 73 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | theme: { 3 | extend: { 4 | spacing: { 5 | '72': '18rem', 6 | '84': '21rem', 7 | '96': '24rem', 8 | '128': '32rem', 9 | '144': '36rem', 10 | '192': '48rem', 11 | }, 12 | fontFamily: { 13 | 'sans': [ 14 | 'Raleway', 15 | '-apple-system', 16 | 'BlinkMacSystemFont', 17 | '"Segoe UI"', 18 | 'Roboto', 19 | '"Helvetica Neue"', 20 | 'Arial', 21 | '"Noto Sans"', 22 | 'sans-serif', 23 | '"Apple Color Emoji"', 24 | '"Segoe UI Emoji"', 25 | '"Segoe UI Symbol"', 26 | '"Noto Color Emoji"', 27 | ], 28 | } 29 | }, 30 | }, 31 | variants: { 32 | backgroundColor: ['responsive', 'hover', 'focus', 'active'] 33 | }, 34 | plugins: [ 35 | //require('@tailwindcss/custom-forms') 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/web/criticalcss/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/web/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddev/ddev-contrib/d86da073449f5cc57f7734b63f55eeb8652d900d/recipes/puppeteer-headless-chrome-support/demo/web/hero.png -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/web/webpack-assets/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /recipes/puppeteer-headless-chrome-support/demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | var Encore = require('@symfony/webpack-encore'); 2 | var CriticalCssPlugin = require('critical-css-webpack-plugin'); 3 | 4 | const sane = require("sane"); 5 | const path = require("path"); 6 | 7 | Encore 8 | // directory where compiled assets will be stored 9 | .setOutputPath('web/webpack-assets/') 10 | // public path used by the web server to access the output path 11 | .setPublicPath('/webpack-assets') 12 | // only needed for CDN's or sub-directory deploy 13 | .setManifestKeyPrefix('') 14 | 15 | /* 16 | * ENTRY CONFIG 17 | * 18 | * Add 1 entry for each "page" of your app 19 | * (including one that's included on every page - e.g. "app") 20 | * 21 | * Each entry will result in one JavaScript file (e.g. app.js) 22 | * and one CSS file (e.g. app.css) if your JavaScript imports CSS. 23 | */ 24 | .addEntry('main', './src/main.js') 25 | .addStyleEntry('styles', './src/styles.css') 26 | 27 | // will require an extra script tag for runtime.js 28 | // but, you probably want this, unless you're building a single-page app 29 | .enableSingleRuntimeChunk() 30 | 31 | .cleanupOutputBeforeBuild() 32 | .enableSourceMaps(!Encore.isProduction()) 33 | // enables hashed filenames (e.g. app.abc123.css) 34 | .enableVersioning(Encore.isProduction()) 35 | .enablePostCssLoader() 36 | 37 | // uncomment if you use TypeScript 38 | //.enableTypeScriptLoader() 39 | 40 | // uncomment if you use Sass/SCSS files 41 | //.enableSassLoader() 42 | 43 | // uncomment if you're having problems with a jQuery plugin 44 | //.autoProvidejQuery() 45 | ; 46 | 47 | if (Encore.isProduction()) { 48 | Encore.addPlugin(new CriticalCssPlugin({ 49 | base: './web/criticalcss/', 50 | src: 'https://demo.ddev.site/', 51 | dest: 'critical.min.css', 52 | extract: false, 53 | inline: false, 54 | minify: true, 55 | width: 1200, 56 | height: 1200, 57 | })) 58 | } 59 | 60 | module.exports = Encore.getWebpackConfig(); 61 | -------------------------------------------------------------------------------- /recipes/redaxo-cms/README.md: -------------------------------------------------------------------------------- 1 | # Install [REDAXO CMS](https://redaxo.org) with DDEV 2 | 3 | ## What is REDAXO 4 | 5 | [REDAXO](https://redaxo.org) is an open source content managment system devleoped by the German web agency [Yakamara](https://www.yakamara.de/). 6 | 7 | REDAXO is for people who love the flexibility of a content managment system; you have easy control of your code and also of the content that you want to create. 8 | 9 | ## Install REDAXO code 10 | 11 | In general, REDAXO setup is exactly the same as any other generic PHP project 12 | 13 | * Clone the REDAXO repository: `git clone https://github.com/redaxo/redaxo.git` 14 | 15 | ## Configure ddev 16 | 17 | * Use `ddev config --project-type=php --webserver-type=apache-fpm` to configure the project. REDAXO expects an apache webserver; `php` is the default/generic project type. 18 | 19 | ## Start ddev and visit the REDAXO URL to configure the project 20 | 21 | * `ddev start` 22 | * Visit the selected URL (like `https://redaxo.ddev.site`) to choose language, license terms, etc. 23 | * Configure site and database settings. (Database name is `db`, mysql host is `db`, database username is `db`, and password is `db`) 24 | * Complete setup 25 | * To see complete ddev project information, use `ddev describe`. 26 | 27 | ## Original Author: [@simonwestghost](https://twitter.com/simonwestghost) 28 | -------------------------------------------------------------------------------- /recipes/sshd/README.md: -------------------------------------------------------------------------------- 1 | # Adding a "real" sshd server to web container 2 | 3 | There's also a recent add-on for this with a more robust approach. 4 | 5 | https://github.com/hanoii/ddev-sshd 6 | 7 | ---- 8 | 9 | Although most people do fine with `ddev ssh` and `ddev exec`, they don't actually use ssh, but are wrappers on `docker exec`. In the vast majority of cases, you don't need anything like this, but if you have an application that needs to *actually* use the real ssh protocols to access the web container, this recipe is for you. 10 | 11 | 1. Copy [config.sshd.yaml](config.sshd.yaml) and [docker-compose.sshd.yaml](docker-compose.sshd.yaml) into your project's .ddev folder. (Note that you can also incorporate the contents of config.ssshd.yaml into your config.yaml.) 12 | 2. Authorize your ssh client to access the web container's ssh server by adding a global `~/.ddev/homeadditions/.ssh/authorized_keys`, which will be copied into the ~/.ssh directory in the web container. The easiest way to do this, assuming your ssh pubkey is ~/.ssh/id_rsa.pub, is 13 | ``` 14 | mkdir -p ~/.ddev/homeadditions/.ssh 15 | cp ~/.ssh/id_rsa.pub ~/.ddev/homeadditions/.ssh/authorized_keys 16 | ``` 17 | (You can also create the authorized_keys file in the project `.ddev/homeadditions/.ssh` folder on a project by project basis but this command takes care of authorized_keys for all of your projects at once and can be executed from any directory.) 18 | 3. `ddev restart` 19 | 4. Access the web container with `ssh -p 2222 -o StrictHostKeyChecking=no localhost` 20 | 21 | (The StrictHostKeyChecking=no is required because every time you restart the container it comes up with a new "host" identity.) 22 | 23 | * Note: If you are running DDEV from a domain connected Windows PC, you may need to specify a username. 24 | 25 | 1. First, check if your account is tied to a domain. From a command prompt, type `whoami` 26 | 27 | ```shell 28 | > whoami 29 | work\user13 30 | ``` 31 | 32 | The above shows the current user `user13` is connected to the `work` domain. 33 | 34 | 2. If your account is tied to a domain, as above, you need to specify a username when connecting: `@localhost`, replace username with your user (Eg. user13); 35 | 36 | ```shell 37 | ssh -p 2222 -o StrictHostKeyChecking=no @localhost 38 | ``` 39 | -------------------------------------------------------------------------------- /recipes/sshd/config.sshd.yaml: -------------------------------------------------------------------------------- 1 | hooks: 2 | post-start: 3 | - exec: sudo chown -R $(id -un) /etc/ssh && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys && /usr/sbin/sshd -p 2222 4 | webimage_extra_packages: [openssh-server] 5 | -------------------------------------------------------------------------------- /recipes/sshd/docker-compose.sshd.yaml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | web: 4 | ports: 5 | - "127.0.0.1:2222:2222" 6 | -------------------------------------------------------------------------------- /web-container-dockerfiles/grpc/Dockerfile: -------------------------------------------------------------------------------- 1 | ENV PHP_VERSION=$DDEV_PHP_VERSION 2 | RUN \ 3 | (apt-get update || true) && apt-get install -y libz-dev php-dev php-pear && \ 4 | pecl install grpc && \ 5 | pecl install protobuf && \ 6 | echo "extension=grpc.so" > /etc/php/$DDEV_PHP_VERSION/cli/conf.d/grpc.ini && \ 7 | echo "extension=protobuf.so" > /etc/php/$DDEV_PHP_VERSION/cli/conf.d/protobuf.ini && \ 8 | echo "extension=grpc.so" > /etc/php/$DDEV_PHP_VERSION/fpm/conf.d/grpc.ini && \ 9 | echo "extension=protobuf.so" > /etc/php/$DDEV_PHP_VERSION/fpm/conf.d/protobuf.ini 10 | -------------------------------------------------------------------------------- /web-container-dockerfiles/grpc/README.md: -------------------------------------------------------------------------------- 1 | # PHP gRPC 2 | 3 | Adds protobuf and grpc PHP modules to web-container. 4 | This allows to create clients to interact with external gRPC services. 5 | 6 | The installation can take some minutes, because the modules are compiled during the Docker image creation. 7 | 8 | ## Verify installation 9 | 10 | The following command should print the two compiled modules. 11 | 12 | ```bash 13 | ddev exec php -m | grep -i 'grpc\|protobuf' 14 | ``` 15 | 16 | ## Example Project 17 | 18 | An example project can be found here: 19 | 20 | **Contributed by [@cmuench](https://github.com/cmuench)** 21 | -------------------------------------------------------------------------------- /web-container-dockerfiles/laravel-queue-worker/Dockerfile: -------------------------------------------------------------------------------- 1 | ADD laravel-worker.conf /etc/supervisor/conf.d/ 2 | 3 | -------------------------------------------------------------------------------- /web-container-dockerfiles/laravel-queue-worker/README.md: -------------------------------------------------------------------------------- 1 | # Laravel Queue Worker 2 | 3 | ## Run using supervisor 4 | 5 | Run the Laravel queue worker as a process using supervisor. The included configuration file has been minimally changed from the example in the [Laravel docs](https://laravel.com/docs/7.x/queues#supervisor-configuration). 6 | 7 | Copy `Dockerfile` and `laravel-worker.conf` to `.ddev/web-build` and restart using `ddev restart`. 8 | 9 | Keep in mind that using this approach will modify your web image, so read the caveats in the DDEV docs under "[Customizing Docker Images](https://ddev.readthedocs.io/en/stable/users/extend/customizing-images/)" > "[Adding extra Dockerfiles for webimage and dbimage](https://ddev.readthedocs.io/en/stable/users/extend/customizing-images#adding-extra-dockerfiles-for-webimage-and-dbimage)." 10 | 11 | ## Run in background using `nohup` 12 | 13 | Copy `config.laravel-worker.conf` to `.ddev`. When the container is restarted, the queue worker will run in the background with no change to the Docker image. 14 | 15 | **Contributed by [@karlshea](https://github.com/karlshea)** 16 | -------------------------------------------------------------------------------- /web-container-dockerfiles/laravel-queue-worker/config.laravel.yaml: -------------------------------------------------------------------------------- 1 | hooks: 2 | post-start: 3 | - exec: "nohup bash -c '/var/www/html/artisan queue:work --sleep=3 --tries=3 &'" 4 | -------------------------------------------------------------------------------- /web-container-dockerfiles/laravel-queue-worker/laravel-worker.conf: -------------------------------------------------------------------------------- 1 | [program:laravel-worker] 2 | process_name=%(program_name)s_%(process_num)02d 3 | command=/usr/bin/php /var/www/html/artisan queue:work --sleep=3 --tries=3 4 | autostart=true 5 | autorestart=true 6 | numprocs=8 7 | redirect_stderr=true 8 | stdout_logfile=/proc/self/fd/2 9 | stopwaitsecs=3600 10 | -------------------------------------------------------------------------------- /web-container-dockerfiles/stripe-cli/Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | # Install the Stripe CLI 3 | # Documentation: https://stripe.com/docs/stripe-cli#install 4 | RUN curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | sudo tee /usr/share/keyrings/stripe.gpg 5 | RUN echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.list 6 | RUN (apt update || true) && apt install stripe 7 | -------------------------------------------------------------------------------- /web-container-dockerfiles/stripe-cli/README.md: -------------------------------------------------------------------------------- 1 | # Stripe CLI 2 | 3 | Build, test, and manage your Stripe integration right from the terminal with [Stripe CLI](https://stripe.com/docs/stripe-cli). 4 | 5 | ## Installation 6 | 7 | 1. Copy `Dockerfile` inside your web container configuration `.ddev/web-build/` 8 | 2. Start/Restart your project and you are done! 🙌 9 | 10 | ## Check if it is working 11 | 12 | ```bash 13 | ddev exec stripe --version 14 | ``` 15 | 16 | should output something like this 17 | 18 | ```bash 19 | stripe version 1.18.0 20 | ``` 21 | 22 | Well done. Now you can start to listen to the stripe web hooks. Have fun 🎉 23 | 24 | **Contributed by [@SuddenlyRust](https://github.com/SuddenlyRust)** 25 | --------------------------------------------------------------------------------