{"id":13517955,"url":"https://github.com/jellesiderius/ddev-magento2-setup","last_synced_at":"2026-03-11T14:38:50.851Z","repository":{"id":160912373,"uuid":"611249828","full_name":"jellesiderius/ddev-magento2-setup","owner":"jellesiderius","description":"DDEV for Magento 2 including cache watching, styles watching \u0026 multi store","archived":false,"fork":false,"pushed_at":"2024-12-03T10:00:34.000Z","size":96,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-03T10:36:54.131Z","etag":null,"topics":["ddev","development-environment","magento2"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jellesiderius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-08T12:45:28.000Z","updated_at":"2024-12-03T10:00:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"8fbb1469-e387-48a8-a6eb-183941d564b4","html_url":"https://github.com/jellesiderius/ddev-magento2-setup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellesiderius%2Fddev-magento2-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellesiderius%2Fddev-magento2-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellesiderius%2Fddev-magento2-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jellesiderius%2Fddev-magento2-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jellesiderius","download_url":"https://codeload.github.com/jellesiderius/ddev-magento2-setup/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246446807,"owners_count":20778875,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ddev","development-environment","magento2"],"created_at":"2024-08-01T05:01:39.045Z","updated_at":"2026-03-11T14:38:50.829Z","avatar_url":"https://github.com/jellesiderius.png","language":null,"funding_links":[],"categories":["Others","Magento"],"sub_categories":[],"readme":"# DDEV for Magento 2 and sharing my own configuration files\n\n## Before you start\nInstall DDEV through installation guide: https://ddev.readthedocs.io/\n\n## Setting up DDEV configuration files\nAfter installing DDEV, follow the following steps\n\n### Setting up .bashrc for your DDEV shell environment\n1. Navigate to `~/.ddev`\n2. If the folder `~/.ddev/homeadditions` is not present yet, create this\n3. Now navigate to `~/.ddev/homeadditions`\n4. Create a `~/.ddev/homeadditions/.bashrc` file, containing the following:\n```bash\nparse_git_branch() {\n     git branch 2\u003e /dev/null | sed -e '/^[^*]/d' -e 's/* \\(.*\\)/[\\1]/'\n}\nexport PS1='\\[\\e[00;33m\\][\\t]\\[\\e[0m\\]\\[\\e[00;37m\\]-\\[\\e[0m\\]\\[\\e[00;36m\\][\\h]\\[\\e[0m\\]\\[\\e[00;37m\\]-$(parse_git_branch)-\\[\\e[0m\\]\\[\\e[00;31m\\][\\w]\\[\\e[0m\\]\\[\\e[0m\\]$ \\[\\e[0m\\]'\nexport LS_COLORS='rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:'\nalias ls='ls --color=auto'\n```\n\n### Setting up custom commands for DDEV \nNow navigate to `~/.ddev/commands/web`. If this folder structure is not present yet, create this. You should create the following files:\n\n`~/.ddev/commands/web/magerun`:\n```bash\n#!/bin/bash\n\n#ddev-generated\n## Description: Run Magerun CLI inside the web container\n## Usage: magerun [flags] [args]\n## Example: \"ddev magerun list\" or \"ddev magerun maintenance:enable\" or \"ddev magerun sampledata:reset\"\n## ProjectTypes: magento2\n## ExecRaw: true\n\nif [ ! -f bin/magento ]; then\n  echo 'bin/magento does not exist in your project root directory.'\n  echo 'Please verify that you installed the shop in your project directory.'\n  exit 1\nfi\n\nmagerun \"$@\"\n```\n\n`~/.ddev/commands/web/magerun2`:\n```bash\n#!/bin/bash\n\n#ddev-generated\n## Description: Run Magerun2 CLI inside the web container\n## Usage: magerun2 [flags] [args]\n## Example: \"ddev magerun2 list\" or \"ddev magerun2 maintenance:enable\" or \"ddev magerun2 sampledata:reset\"\n## ProjectTypes: magento2\n## ExecRaw: true\n\nif [ ! -f bin/magento ]; then\n  echo 'bin/magento does not exist in your project root directory.'\n  echo 'Please verify that you installed the shop in your project directory.'\n  exit 1\nfi\n\nmagerun2 \"$@\"\n```\n\n`~/.ddev/commands/web/configure-magento-env`:\n```bash\n#!/bin/bash\n\n#ddev-generated\n## Description: Configures the env.php file\n## Usage: configure-magento-env\n## Example: \"configure-magento-env\"\n## ProjectTypes: magento2\n## ExecRaw: true\n\nif [ ! -f bin/magento ]; then\n  echo 'bin/magento does not exist in your project root directory.'\n  echo 'Please verify that you installed the shop in your project directory.'\n  exit 1\nfi\n\nbin/magento setup:config:set --db-host=db \\\n--db-name=db \\\n--db-user=db \\\n--db-password=db \\\n--cache-backend-redis-server=redis \\\n--cache-backend-redis-port=6379 \\\n--cache-backend-redis-db=0 \\\n--session-save=redis \\\n--session-save-redis-host=redis \\\n--session-save-redis-port=6379 \\\n--session-save-redis-log-level=3 \\\n--session-save-redis-db=1 \\\n--session-save-redis-disable-locking=1 \\\n--backend-frontname=admin \\\n-n;\n```\n\n`~/.ddev/commands/web/watch-cache`:\n```bash\n#!/bin/bash\n\n# ddev generated\n## Description: Magento 2 Cache Watcher\n## Usage: watch-cache [flags] [args]\n## Example: \"ddev watch-cache\"\n## ProjectTypes: magento2\n## ExecRaw: true\n\nif [ ! -f ~/.composer/vendor/mage-os/magento-cache-clean/bin/cache-clean.js ]; then\n    composer global require mage-os/magento-cache-clean\nfi\n\n~/.composer/vendor/mage-os/magento-cache-clean/bin/cache-clean.js --watch\n```\n\n`~/.ddev/commands/web/watch-styles`:\n```bash\n#!/bin/bash\n\n#ddev-generated\n## Description: Watches LESS changes for your Magento project\n## Usage: watch-styles --THEME_NAME\n## Example: \"ddev watch-styles\"\n## ProjectTypes: magento2\n## ExecRaw: true\n\ngulp exec --$@;\ngulp less --$@;\ngulp watch-styles --$@ --live;\n```\n\nYou have now added the following commands for DDEV:\n- `ddev magerun`\n- `ddev magerun2`\n- `ddev configure-magento-env`\n- `ddev watch-cache`\n- `ddev watch-styles`\n\n### Setting up GULP style watching + LiveReload\n1. Download and unzip the [google-chrome-extension-livereload-for-ddev.zip](google-chrome-extension-livereload-for-ddev.zip) file and install this for your Chrome Browser: https://support.google.com/chrome_webstore/answer/2664769?hl=en \n2. For your Magento 2 project, download https://github.com/bobmotor/magento-2-gulp and configure according to guide in the repo. Make sure to get at least version 1.5.2\n3. Now after setting up step 1 \u0026 2, your browser extension should be available to watch your style changes in Magento. Click on the LiveReload chrome extension button after your project is fired up and `ddev watch-styles YOURTHEMENAME` is started\n\n### Configuring your Magento 2 project\nNow that the global settings are done, you can start to configure a DDEV environment for a Magento 2 project, you can run these commands:\n```shell\nddev config --project-type=magento2 --php-version=8.3 --docroot=pub --disable-settings-management --database=mysql:8.0\nddev get ddev/ddev-elasticsearch\nddev get ddev/ddev-redis\n```\n\nAfter setting up the config files, add this to your project's `MAGENTO_ROOT_FOLDER/.ddev/config.yaml`:\n```yaml\nweb_extra_exposed_ports:\n  - name: LiveReload\n    container_port: 35729\n    http_port: 35729\n    https_port: 35730\n```\n\nMake sure to add a `app/etc/env.php` file with the correct database settings:\n```php\n'db' =\u003e [\n    'table_prefix' =\u003e '',\n    'connection' =\u003e [\n        'default' =\u003e [\n            'host' =\u003e 'db',\n            'dbname' =\u003e 'db',\n            'username' =\u003e 'db',\n            'password' =\u003e 'db',\n            'model' =\u003e 'mysql4',\n            'engine' =\u003e 'innodb',\n            'initStatements' =\u003e 'SET NAMES utf8;',\n            'active' =\u003e '1',\n            'driver_options' =\u003e [\n                1014 =\u003e false\n            ]\n        ]\n    ]\n]\n```\n\n### Starting up your DDEV project\nNow that everything is set up, you can start the project by running `ddev start`\n\n### Configuring Redis for your project\nRun `DDEV configure-magento-env`. This will automatically setup your `app/etc/env.php` file with Redis configured\n\n### Configuring Varnish for your project\n1. Run `ddev get ddev/ddev-varnish`\n2. Add VCL file to `.ddev/varnish/default.vcl:`\n```bash\n# VCL version 5.0 is not supported so it should be 4.0 even though actually used Varnish version is 6\nvcl 4.0;\n\nimport std;\n# The minimal Varnish version is 6.0\n# For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https'\n\nbackend default {\n    .host = \"web\";\n    .port = \"80\";\n    .first_byte_timeout = 600s;\n}\n\nacl purge {\n    \"web\";\n}\n\nsub vcl_recv {\n    if (req.restarts \u003e 0) {\n        set req.hash_always_miss = true;\n    }\n\n    if (req.method == \"PURGE\") {\n        if (client.ip !~ purge) {\n            return (synth(405, \"Method not allowed\"));\n        }\n        # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header\n        # has been added to the response in your backend server config. This is used, for example, by the\n        # capistrano-magento2 gem for purging old content from varnish during it's deploy routine.\n        if (!req.http.X-Magento-Tags-Pattern \u0026\u0026 !req.http.X-Pool) {\n            return (synth(400, \"X-Magento-Tags-Pattern or X-Pool header required\"));\n        }\n        if (req.http.X-Magento-Tags-Pattern) {\n          ban(\"obj.http.X-Magento-Tags ~ \" + req.http.X-Magento-Tags-Pattern);\n        }\n        if (req.http.X-Pool) {\n          ban(\"obj.http.X-Pool ~ \" + req.http.X-Pool);\n        }\n        return (synth(200, \"Purged\"));\n    }\n\n    if (req.method != \"GET\" \u0026\u0026\n        req.method != \"HEAD\" \u0026\u0026\n        req.method != \"PUT\" \u0026\u0026\n        req.method != \"POST\" \u0026\u0026\n        req.method != \"TRACE\" \u0026\u0026\n        req.method != \"OPTIONS\" \u0026\u0026\n        req.method != \"DELETE\") {\n          /* Non-RFC2616 or CONNECT which is weird. */\n          return (pipe);\n    }\n\n    # We only deal with GET and HEAD by default\n    if (req.method != \"GET\" \u0026\u0026 req.method != \"HEAD\") {\n        return (pass);\n    }\n\n    # Bypass customer, shopping cart, checkout\n    if (req.url ~ \"/customer\" || req.url ~ \"/checkout\") {\n        return (pass);\n    }\n\n    # Bypass health check requests\n    if (req.url ~ \"^/(pub/)?(health_check.php)$\") {\n        return (pass);\n    }\n\n    # Set initial grace period usage status\n    set req.http.grace = \"none\";\n\n    # normalize url in case of leading HTTP scheme and domain\n    set req.url = regsub(req.url, \"^http[s]?://\", \"\");\n\n    # collect all cookies\n    std.collect(req.http.Cookie);\n\n    # Remove all marketing get parameters to minimize the cache objects\n    if (req.url ~ \"(\\?|\u0026)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=\") {\n        set req.url = regsuball(req.url, \"(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+\u0026?\", \"\");\n        set req.url = regsub(req.url, \"[?|\u0026]+$\", \"\");\n    }\n\n    # Static files caching\n    if (req.url ~ \"^/(pub/)?(media|static)/\") {\n        # Static files should not be cached by default\n        return (pass);\n\n        # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines\n        #unset req.http.Https;\n        #unset req.http.X-Forwarded-Proto;\n        #unset req.http.Cookie;\n    }\n\n    # Bypass authenticated GraphQL requests without a X-Magento-Cache-Id\n    if (req.url ~ \"/graphql\" \u0026\u0026 !req.http.X-Magento-Cache-Id \u0026\u0026 req.http.Authorization ~ \"^Bearer\") {\n        return (pass);\n    }\n\n    return (hash);\n}\n\nsub vcl_hash {\n    if ((req.url !~ \"/graphql\" || !req.http.X-Magento-Cache-Id) \u0026\u0026 req.http.cookie ~ \"X-Magento-Vary=\") {\n        hash_data(regsub(req.http.cookie, \"^.*?X-Magento-Vary=([^;]+);*.*$\", \"\\1\"));\n    }\n\n    # To make sure http users don't see ssl warning\n    if (req.http.X-Forwarded-Proto) {\n        hash_data(req.http.X-Forwarded-Proto);\n    }\n\n\n    if (req.url ~ \"/graphql\") {\n        call process_graphql_headers;\n    }\n}\n\nsub process_graphql_headers {\n    if (req.http.X-Magento-Cache-Id) {\n        hash_data(req.http.X-Magento-Cache-Id);\n\n        # When the frontend stops sending the auth token, make sure users stop getting results cached for logged-in users\n        if (req.http.Authorization ~ \"^Bearer\") {\n            hash_data(\"Authorized\");\n        }\n    }\n\n    if (req.http.Store) {\n        hash_data(req.http.Store);\n    }\n\n    if (req.http.Content-Currency) {\n        hash_data(req.http.Content-Currency);\n    }\n}\n\nsub vcl_backend_response {\n\n    set beresp.grace = 3d;\n\n    if (beresp.http.content-type ~ \"text\") {\n        set beresp.do_esi = true;\n    }\n\n    if (bereq.url ~ \"\\.js$\" || beresp.http.content-type ~ \"text\") {\n        set beresp.do_gzip = true;\n    }\n\n    if (beresp.http.X-Magento-Debug) {\n        set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;\n    }\n\n    # cache only successfully responses and 404s that are not marked as private\n    if ((beresp.status != 200 \u0026\u0026 beresp.status != 404) || beresp.http.Cache-Control ~ \"private\") {\n        set beresp.uncacheable = true;\n        set beresp.ttl = 86400s;\n        return (deliver);\n    }\n\n    # validate if we need to cache it and prevent from setting cookie\n    if (beresp.ttl \u003e 0s \u0026\u0026 (bereq.method == \"GET\" || bereq.method == \"HEAD\")) {\n        # Collapse beresp.http.set-cookie in order to merge multiple set-cookie headers\n        # Although it is not recommended to collapse set-cookie header,\n        # it is safe to do it here as the set-cookie header is removed below\n        std.collect(beresp.http.set-cookie);\n        # Do not cache the response under current cache key (hash),\n        # if the response has X-Magento-Vary but the request does not.\n        if ((bereq.url !~ \"/graphql\" || !bereq.http.X-Magento-Cache-Id)\n         \u0026\u0026 bereq.http.cookie !~ \"X-Magento-Vary=\"\n         \u0026\u0026 beresp.http.set-cookie ~ \"X-Magento-Vary=\") {\n           set beresp.ttl = 0s;\n           set beresp.uncacheable = true;\n        }\n        unset beresp.http.set-cookie;\n    }\n\n    # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass\n    if (beresp.ttl \u003c= 0s ||\n        beresp.http.Surrogate-control ~ \"no-store\" ||\n        (!beresp.http.Surrogate-Control \u0026\u0026\n        beresp.http.Cache-Control ~ \"no-cache|no-store\") ||\n        beresp.http.Vary == \"*\") {\n        # Mark as Hit-For-Pass for the next 2 minutes\n        set beresp.ttl = 120s;\n        set beresp.uncacheable = true;\n    }\n\n    # If the cache key in the Magento response doesn't match the one that was sent in the request, don't cache under the request's key\n    if (bereq.url ~ \"/graphql\" \u0026\u0026 bereq.http.X-Magento-Cache-Id \u0026\u0026 bereq.http.X-Magento-Cache-Id != beresp.http.X-Magento-Cache-Id) {\n        set beresp.ttl = 0s;\n        set beresp.uncacheable = true;\n    }\n\n    return (deliver);\n}\n\nsub vcl_deliver {\n    if (obj.uncacheable) {\n        set resp.http.X-Magento-Cache-Debug = \"UNCACHEABLE\";\n    } else if (obj.hits) {\n        set resp.http.X-Magento-Cache-Debug = \"HIT\";\n        set resp.http.Grace = req.http.grace;\n    } else {\n        set resp.http.X-Magento-Cache-Debug = \"MISS\";\n    }\n\n    # Not letting browser to cache non-static files.\n    if (resp.http.Cache-Control !~ \"private\" \u0026\u0026 req.url !~ \"^/(pub/)?(media|static)/\") {\n        set resp.http.Pragma = \"no-cache\";\n        set resp.http.Expires = \"-1\";\n        set resp.http.Cache-Control = \"no-store, no-cache, must-revalidate, max-age=0\";\n    }\n\n    if (!resp.http.X-Magento-Debug) {\n        unset resp.http.Age;\n    }\n    unset resp.http.X-Magento-Debug;\n    unset resp.http.X-Magento-Tags;\n    unset resp.http.X-Powered-By;\n    unset resp.http.Server;\n    unset resp.http.X-Varnish;\n    unset resp.http.Via;\n    unset resp.http.Link;\n}\n\nsub vcl_hit {\n    if (obj.ttl \u003e= 0s) {\n        # Hit within TTL period\n        return (deliver);\n    }\n    if (std.healthy(req.backend_hint)) {\n        if (obj.ttl + 300s \u003e 0s) {\n            # Hit after TTL expiration, but within grace period\n            set req.http.grace = \"normal (healthy server)\";\n            return (deliver);\n        } else {\n            # Hit after TTL and grace expiration\n            return (restart);\n        }\n    } else {\n        # server is not healthy, retrieve from cache\n        set req.http.grace = \"unlimited (unhealthy server)\";\n        return (deliver);\n    }\n}\n```\n3. Run\n```bash\nddev exec bin/magento setup:config:set --http-cache-hosts=varnish:80;\nddev exec bin/magento config:set system/full_page_cache/caching_application 2;\n```\n4. Run `ddev restart` to restart the project. Varnish should now be set up.\n\n\n### Setting up multistore configuration\nIn your project folder `MAGENTO_ROOT_FOLDER/.ddev/nginx_full` add a `magento-stores.conf` containing the following:\n```nginx\nmap $http_host $mage_run_code {\n    default '';\n    store1.ddev.site storecode1;\n    store2.ddev.site storecode2;\n    store3.ddev.site storecode3;\n}\n```\nNext, open up your project's `MAGENTO_ROOT_FOLDER/.ddev/config.yaml` and add additional hostnames:\n```yaml\nadditional_hostnames:\n  - store1\n  - store2\n  - store3\n```\nIf you're using [Mage-DB-Sync](https://github.com/jellesiderius/mage-db-sync), your can add a `.mage-db-sync-config.json` to your Magento root folder:\n```json\n{\n  \"core_config_data\": {\n    \"0\": {\n      \"web/unsecure/base_url\": \"https://store.ddev.site/\",\n      \"web/secure/base_url\": \"https://store.ddev.site/\"\n    },\n    \"1\": {\n      \"web/unsecure/base_url\": \"https://store1.ddev.site/\",\n      \"web/secure/base_url\": \"https://store1.ddev.site/\"\n    },\n    \"2\": {\n      \"web/unsecure/base_url\": \"https://store2.ddev.site/\",\n      \"web/secure/base_url\": \"https://store2.ddev.site/\"\n    },\n    \"3\": {\n      \"web/unsecure/base_url\": \"https://store3.ddev.site/\",\n      \"web/secure/base_url\": \"https://store3.ddev.site/\"\n    }\n  }\n}\n```\n_Note: The \"1\", \"2\", \"3\" are your store codes._\n\n### Synchronising databases through SSH\n[Mage-DB-Sync](https://github.com/jellesiderius/mage-db-sync) is compatible with DDEV. Install this with documentation given at https://github.com/jellesiderius/mage-db-sync and your environment will be easily synchronized\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellesiderius%2Fddev-magento2-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjellesiderius%2Fddev-magento2-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjellesiderius%2Fddev-magento2-setup/lists"}