Problem/Motivation

We are trying to set up a Drupal 10 multisite environment using subfolders (e.g., /site1, /site2) instead of subdomains within a DDEV local environment. However, when we access the URLs like http://my-drupal-multisite.ddev.site/site1, we receive a "Page not found" error.

Steps to reproduce

1. Set up the Drupal 10 project using DDEV.

2. Created web/sites/site1 and web/sites/site2 directories, each with their own settings.php and services.yml.

3. Updated sites.php with the following configuration:

$ddev_hostname = getenv('DDEV_HOSTNAME') ?: 'my-drupal-multisite.ddev.site';
// Map the default site (optional, but good practice)
$sites[$ddev_hostname] = 'default';
// Map your subfolder sites
// Example: http://my-drupal-multisite.ddev.site/site1 will use sites/site1
$sites[$ddev_hostname . '.site1'] = 'site1';
// Example: http://my-drupal-multisite.ddev.site/site2 will use sites/site2
$sites[$ddev_hostname . '.site2'] = 'site2';

4. Created a custom NGINX config file at .ddev/nginx/nginx-site.conf with the following content:

# .ddev/nginx/nginx-site.conf
# This file adds custom Nginx configuration for your DDEV project.
# This entire block handles requests for your subfolder multisites.
location ~ ^/(site1|site2)(/.*)?$ {
root /var/www/html/web;
index index.php;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $drupal_path_info $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param DRUPAL_SUBDIR $1;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; # <--- THIS MUST BE UNCOMMENTED
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
}
location ~ /\. {
deny all;
}
location ~ \.(engine|inc|info|install|make|module|profile|test|po|sh|sql|theme|twig|tpl(\.php)?|xtm|yml|html|json|md|txt|xml|js|css|gif|png|jpg|jpeg|ico|svg|map)$ {
deny all;
log_not_found off;
}
}

Proposed resolution

We expect http://my-drupal-multisite.ddev.site/site1 and http://my-drupal-multisite.ddev.site/site2 to correctly serve content from their respective site directories.

Actual Result:
Visiting /site1 or /site2 results in a "Page not found" error.
There are no errors in ddev logs web.

Troubleshooting Done:
1. Verified NGINX custom config is loaded and DDEV restarted.
2. Confirmed the folder structures and permissions are correct.
3. Verified settings.php database credentials and configuration.
4. Checked logs (ddev logs, PHP logs, NGINX logs) – no errors reported.

Request:
Could anyone help identify what might be missing or incorrect in this setup? Is subfolder-based multisite fully supported in DDEV with NGINX, or are there alternative configurations required?

Environment:
Drupal version: 10.4.8
DDEV version: v1.24.6
PHP version: 8.3.21
Web server: NGINX (via DDEV)

Thank you in advance for your help!

CommentFileSizeAuthor
#6 files.png26.29 KBvinodhini.e
Multisite_error.png91.33 KBvinodhini.e

Issue fork drupal-3529122

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

vinodhini.e created an issue. See original summary.

vinodhini.e’s picture

Issue summary: View changes
cilefen’s picture

Priority: Critical » Normal

First, you may have a better support experience on Slack.

Was the DDEV software documentation helpful or did you have to make the customizations based on your own knowledge of Drupal and nginx?

What does the DDEV configuration file look like?

Is this answer helpful?

nicxvan’s picture

Ddev support is currently in discord too.

cilefen’s picture

At a glance it is because the default site exists and the web server hasn't been configured to handle that.

vinodhini.e’s picture

StatusFileSize
new26.29 KB

Hi @cilefen #3,
Thanks for the quick response and for sharing the article. We're currently working on implementing a multisite setup using subfolders, and while the article you provided covers basic subfolder configurations, our specific need is for a folder-wise structure within the sites path.

Here's our DDEV configuration, and you'll find the folder-wise structure reflected in the sites path. Our goal is that when we access http://my-drupal-multisite.ddev.site/site1, it should correctly redirect to site1.

DDEV Configuration
----------------------------------
name: my-drupal-multisite
type: drupal
docroot: web
php_version: "8.3"
webserver_type: nginx-fpm
xdebug_enabled: false
additional_hostnames:
- "my-drupal-multisite.ddev.site.site1"
- "my-drupal-multisite.ddev.site.site2"
additional_fqdns: []
database:
type: mariadb
version: "10.11"
use_dns_when_possible: true
composer_version: "2"
web_environment: []
corepack_enable: true
default_container_timeout: "240"

Any suggestions you might have would be greatly appreciated.

Thanks in advance!

mpmano made their first commit to this issue’s fork.

manokaran.m’s picture

Status: Active » Needs review

Prepare the Multisite Directory Structure

Create folders for each subsite under web/sites/:

bash

mkdir -p web/sites/site1/files
mkdir -p web/sites/site2/files

cp web/sites/example.settings.php web/sites/site1/settings.php
cp web/sites/example.settings.php web/sites/site2/settings.php

Create Symlinks for Subdirectory Access Important Step

This is the key step that enables subdirectory access:

cd web
# Symlink site paths to index.php
ln -s . site1
ln -s . site2

Note: Use ddev ssh and create symlink using the above command if you are using ddev environment.

Configure sites.php
Create a sites.php file using this command ->
touch web/sites/sites.php
Edit or create web/sites/sites.php:
php

<?php

$sites = [
  'example.ddev.site.site1' => 'site1',
  'example.ddev.site.site2' => 'site2',
];

Drupal converts subdirectory URLs like /site1 into example.ddev.site.site1 internally for multisite resolution.

Configure Database Connections

Edit each site's settings.php to define the correct database.
Example: web/sites/site1/settings.php

$databases['default']['default'] = [
'database' => 'site1',
'username' => 'db',
'password' => 'db',
'host' => 'db',
'port' => 3306,
'driver' => 'mysql',
];

Repeat similarly for site2.

Set File Permissions

chmod -R 775 web/sites/site1/files
chmod -R 775 web/sites/site2/files

Enable .htaccess Rewrite Rules for Subdirectory Sites
Drupal’s default .htaccess is designed for single-site setups. For multisite with subdirectories, we need to ensure Apache knows how to handle requests like /site1/node/1 properly.

Add Rewrite Rules to Top-Level .htaccess
Edit or append to the top of your web/.htaccess:
apache

# Multisite Subdirectory Rewrite Rules


RewriteEngine on

RewriteBase / # Uncomment this line

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} ^/site1
RewriteRule ^ site1/index.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} ^/site2
RewriteRule ^ site2/index.php [L]

This ensures:
example.ddev.site/site1/node/1 → routed through site1/index.php (symlinked to ../index.php)

Clean URLs (like /site1/about) resolve properly.

Don't Remove Existing Drupal .htaccess Rules

Run:
ddev/apache restart

Apache will now recognize .htaccess changes.

Install Each Site via Browser

Visit each site in your browser to begin installation:
http://example.ddev.site/site1/core/install.php

http://example.ddev.site/site2/core/install.php

Follow the on-screen prompts to complete installation.

Test the Multisite Setup
After installing:

Go to http://example.ddev.site/site1 — should load Site 1.

Go to http://example.ddev.site/site2 — should load Site 2.

Hope this will help.

vinodhini.e’s picture

Status: Needs review » Fixed

@Mano, I followed your steps and was able to set up the multisite successfully. Thanks.

vinodhini.e’s picture

vinodhini.e’s picture

Status: Fixed » Closed (fixed)
vinodhini.e’s picture

This issue is fixed and closed now.