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)
ddev share
- Add the hostname of the URL to your
$sites
array as described above.
- 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:
- 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.
- 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.
- 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
.
- 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.
ddev share
tells you what it's doing when it runs ngrok, for example,Running /opt/homebrew/bin/ngrok http http://127.0.0.1:33203
. The33203
in my case is the direct bind port. If you have an ngrok paid account, you should be able to dongrok http --domain stage.ddev.site http://127.0.0.1:33203
(fix the port for your own.)cloudflared tunnel --url http://127.0.0.1:53775
only the default site works. I tried different combinations likecloudflared tunnel --url http://stage.ddev.site
(result Not found) orcloudflared tunnel --url http://127.0.0.1:53775 --http-host-header stage.ddev.site
(result Redirect to my local version)