Search code examples
dockerdrupalngrokddev

Drupal 10 multisite using "ddev share" or Cloudflare


I need to share my local version of Drupal 10 multisite using "ddev share".

When I run the command ddev share, it only shows me the "default" version of the site (path web/sites/default), but I don't know how to access the other site (web/sites/stage).

If it might be helpful, I am using Windows WSL2 with Docker and DDEV installed.

This is the content of my .ddev/config.yaml:

name: mydrupal.local
type: drupal10
docroot: ""
php_version: "8.1"
webserver_type: nginx-fpm
router_http_port: "80"
router_https_port: "443"
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
database:
  type: mariadb
  version: "10.3"
nfs_mount_enabled: false
mutagen_enabled: false
use_dns_when_possible: true
composer_version: "2"
web_environment: []
nodejs_version: "16"

This is the content of drush/sites/self.site.yml:

public:
  uri: https://mydrupal.local.ddev.site
stage:
  uri: https://stage.ddev.site

Solution

  • The problem here ends up being that Drupal routes to subsites in a multisite using the Host header usually (can also use port and path). So if we try to trick it by changing the Host header, it tricks us back to using the wrong cookies, and eventually redirecting to the wrong site.

    I'll show how to do this with a Drupal 10 multisite and ddev share or with cloudflared. They both work, and work for the same reasons. For each, you have to add a line to your sites.php that directs to the correct subsite. For example, $sites['my-free-ngrok-domain.ngrok-free.app'] = 'subsite';, where my-free-ngrok-domain.ngrok-free.app is the hostname in the URL that ngrok or Cloudflare gives you.

    ddev share (ngrok)

    1. ddev share
    2. Add the hostname of the URL to your $sites array as described above.
    3. Use the subsite.

    This can be a lot easier if you use a free static hostname. I have this in my project configuration:

    ngrok_args: --domain=my-free-ngrok-domain.ngrok-free.app

    With this setup, you can set up the sites array once and it will work. I'm sure if you pay ngrok more than "free", you can also get separate domains for each subsite and each project.

    Cloudflare with cloudflared

    I was able to make this work with a free Cloudflare tunnel, but it was a little more awkward than desired.

    (You do not need a Cloudflare account for this, you just need the cloudflared tool, which is available via brew install cloudflared on systems with Homebrew, or other installation techniques (only installation of cloudflared is required, nothing else, no authentication, nothing.)

    Here's what I did:

    1. Find out the port that ddev-webserver is serving direct http on. This is the http://127.0.0.1 URL typically listed under "All URLs" in ddev describe. In my case, it's http://127.0.0.1:32796 (This is also what ddev share would have used.
    2. Run a free cloudflare tunnel using that URL (WITHOUT --http-header). cloudflared tunnel --url http://127.0.0.1:32796 in my case. This will give a URL that you can visit, and it will by default go to the default Drupal site in your multisite.
    3. Grab the hostname that cloudflare has provided for its proxy URL. In my case, the proxy was https://chairman-spot-cisco-calendars.trycloudflare.com, so I want the hostname chairman-spot-cisco-calendars.trycloudflare.com.
    4. Now the ugly part: In your sites/sites.php add a site for this hostname. In my case that was $sites['chairman-spot-cisco-calendars.trycloudflare.com'] = 'subsite';

    This works perfectly for me in a trivial Drupal 10 multisite. And it makes sense that it does, because Drupal's routing of multisites is, by default, based on the Host header. So that's the reason we couldn't fool it by changing the Host header. When we did, it gets the first page fine, but after that things go wrong; cookies are set wrong, redirects are wrong.

    I'm sure you can set up a preconfigured Cloudflared tunnel (requires authentication to an account that controls a domain's DNS which can be used), which could have a static hostname, which would make this process easier.