Reverse proxy settings for multisite cannot work

Created on 11 September 2018, about 6 years ago
Updated 22 February 2024, 7 months ago

Problem/Motivation

Bug:
If you have multiple sites and if your Drupal is behind a reverse proxy, the matching site path is not resolved, the settings are not initialized, and you always end up on the install page (with wrong urls generated).

Why?
1) When the request is handled, one of the first function to be called is DrupalKernel->initializeSettings().
2) To initialize the settings, Drupal needs to determine the site path to read the settings.php file so the functionDrupalKernel::findSitePath() is called.
3) In this function, when you have multiple sites, the function Request->getHttpHost() is called on the request (the http host is needed to match it with the mapping (dir => http host) you have made in the sites.php file).

Problem:
1) The http host depends on the trusted proxies configuration (cf Symfony Request->getHttpHost() code).
2) The trusted proxies are only set by the ReverseProxyMiddleware middleware so they have not yet been set in the request. The container has not yet been initialized.

Note:
This cannot be resolved easily because there is a circular dependency (cf attached schema).
1) To find the site path, Drupal needs the valid http host (so the trusted proxies must have been set on the request).
2) To set the trusted proxies, the settings must have been initiliazed (because currently the reverse proxy settings are in the site settings.php file).
3) To initialize the site settings, Drupal needs the site path.

My two cents:
1) Setting the request trusted proxies in a HttpKernel middleware is a design error.
2) The reverse proxy settings can only be global and not by site. As long as Drupal depends on the http host to find the site, a configuration by site is not possible. I geuss that's ok for the vast majority of project using multiple sites and reverse proxy.

Proposed resolution

Ideas:
1) Set the trusted proxies on the Request as soon as possible. We need to make sure that the trusted proxies are set before any real usage of the Request. The safest solution is to do it at the very beginning of the request handle. If you look at Symfony doc about how to configure Symfony to work behind a reverse proxy (https://symfony.com/doc/current/deployment/proxies.html), they advise the user to set the trusted proxies directly in the front controller (so asap).
2) Deprecate the ReverseProxyMiddleware class.

Proposed patch:
Now:
1) Introduce a new configuration file sites/reverse_proxy_settings.php that behaves exactly like the current reverse proxy settings.
2) Introduce a new method DrupalKernel::setTrustedProxies() that is called as soon as the request is handled.
3) The new method reads the new configuration file and set the trusted proxies on the request.
4) The new method uses the ReverseProxyMiddleware::setSettingsOnRequest() method during the deprecation period (so the same configuration options are used and the behavior is exactly the same).
5) Deprecate the ReverseProxyMiddleware class and trigger a deprecation notice when the reverse proxy settings still come from the site settings.php file (this is the case when you have only one site).

Once the deprecation period is over:
1) Remove the ReverseProxyMiddleware class.
2) Copy the code of the ReverseProxyMiddleware::setSettingsOnRequest() method in the new DrupalKernel::setTrustedProxies() method.
3) Remove the call to ReverseProxyMiddleware::setSettingsOnRequest() in the install.core.inc file as it will not be needed anymore.

Alternatives:
1) Maybe introducing a new configuration file is not the best solution and that the reverse proxy configuration could be in the existing sites.php file directly?
2) Maybe we should remove all reverse proxy configuration from Drupal and and let the users manage the trusted proxy themselves in their front controller (like in Symfony projects).

Remaining tasks

1) Discuss the issue.
2) Review the proposed resolution and patch.
3) Eventually Write tests and update the documentation.

Going further:

Instead of creating a new specific file just for the reverse proxy settings, this could be an opportunity to create a global settings file that all sites settings would inherit. The settings of each site would be merged with the global ones. Those general settings could be used before the site path has been resolved for other purposes. It is already common to create a settings.common.php file that you require in all the sites settings.php files.

๐Ÿ› Bug report
Status

Needs work

Version

11.0 ๐Ÿ”ฅ

Component
Baseย  โ†’

Last updated about 3 hours ago

Created by

๐Ÿ‡ซ๐Ÿ‡ทFrance fancyweb

Live updates comments and jobs are added and updated live.
  • Needs reroll

    The patch will have to be re-rolled with new suggestions/changes described in the comments in the issue.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024