Multi-tenant global config loader for Nextcloud: resolves $CONFIG per request
host from a domain config matrix.
A single Nextcloud instance serving multiple domains (e.g.
domain01.example.coop, domain02.example.coop) may need different settings
per domain: database (dbname, dbhost, ...), SMTP (mail_smtphost), data
directory (datadirectory), etc. Nextcloud has no structured way to load
configuration based on the request host.
Nextcloud automatically loads and merges every config/*.config.php file into
the global $CONFIG (see OC\Config::readData()). This module leverages that:
multitenancy.database.php -> multitenancy.config.php -> Nextcloud global config
(tenant matrix, NOT (auto-loaded loader, (merged per request)
auto-loaded by Nextcloud) calls this module)
- The tenant matrix lives in
config/multitenancy.database.php. The file name intentionally does not end inconfig.php, so Nextcloud does not load it directly. - The loader
config/multitenancy.config.php(auto-loaded by Nextcloud) reads the request host ($_SERVER['HTTP_HOST']) and hands it toManager::getConfigFromHost(), which matches it against the regex keys of the matrix and returns the matching tenant config — or an empty array when nothing matches. Reading the superglobal is the loader's job, so theManageritself stays free of global state.
This module is location-agnostic: clone it (or add it as a git submodule)
anywhere the PHP process can read — inside or outside the Nextcloud webroot —
and adjust the require path in the loader accordingly.
git clone https://github.com/LibreCodeCoop/multitenancy-global-config.git- Copy
examples/multitenancy.config.phpto your Nextcloudconfig/directory and adjust therequire_oncepath to where you cloned this repository. - Create
config/multitenancy.database.phpwith your tenant matrix (seeexamples/multitenancy.database.php).
Keys are complete regular expressions (with delimiters) matched against the
request host. The first matching key wins. Values are regular Nextcloud
$CONFIG arrays merged over the global config.
<?php
$CONFIG = [
'/^domain01\.example\.coop$/' => [
'dbname' => 'tenant01',
'mail_smtphost' => 'smtp01.example.coop',
],
];The matrix file name can be overridden with the MULTITENANCY_CONFIG_FILE
environment variable (relative to the config/ directory).
A matrix key that is not a valid regex raises a RuntimeException: a broken
matrix fails loudly instead of silently routing tenants to the base config.
The Host header is fully client-controlled. Anchored regex keys (/^...$/)
prevent one tenant from selecting another tenant's config, but a host that
matches no key falls through to the base Nextcloud config. Configure your
reverse proxy to route only known tenant hosts to this instance.
CLI processes have no Host header, so they fall back to localhost and run
against the base config. To run a command as a specific tenant, set HTTP_HOST
in the environment (PHP CLI exposes environment variables in $_SERVER):
HTTP_HOST=domain01.example.coop php occ maintenance:mode --oncomposer install
composer test