3

The WordPress multisite feature offers two different installation modes: subdomain and subdirectory install. By default both modes allow to manage separate WordPress instances (sites) within one installation and within one primary domain. The obvious difference is the URL schema for all sites (in the example multisite.tld is the primary doman):

  • http://site1.multisite.tld for subdomain install and
  • http://multisite.tld/site1 for subdirectory install.

Since it is possible to map any arbitrary domain to sites after they were created in both modes, I wonder what are the actual differences between both? Also, is there a way to change the mode after the installation?

4

From a user perspective there are two noticeable differences. First of all the GUI for creating new sites. Either it shows an input field for the first segment of the URL path (subdirectory) or an input field for the subdomain you want to use for the new site. (Setting the URL to a completely arbitrary value is only possible when editing an already created site. But it is possible in both modes.)

The other one is not evident on the first sight and and it only affects the subdirectory mode: the permalink structure of the main sites will have a static prefix blog/ that is not meant to be changed. (Even though there might be solutions do change or remove the prefix).

From a technical perspective it is a different system configuration that is defined by configuration constants, configuration values in database and also configuration of the web server. What defines the mode in first place it the constant IS_SUBDOMAIN_INSTALL which can be set to true (subdomain mode) or false (subdirectory mode). But that's not the only place this information is stored. During the install process WordPress stores an integer value as site meta using the key subdomain_install. It can be read (or updated) via WP-CLI:

$ wp site option get subdomain_install
1

Subdirectory mode results further in an additional element on the list of forbidden site slugs: blog. These list is stored in the site meta illegal_names. Thus, in subdirectory mode it looks like this by default:

$ wp site option get illegal_names
array (
      0 => 'www',
      1 => 'web',
      2 => 'root',
      3 => 'admin',
      4 => 'main',
      5 => 'invite',
      6 => 'administrator',
      7 => 'files',
      8 => 'blog',
)

Apache rewrite configuration

As the web server is not responsible for WordPress internals, its configuration is all about routing the requested URL to the correct script or asset file. Primarily it's about the question whether to route request URLs like /site-slug/wp-[admin|content|includes] and /site-slug/wp-*.php to the appropriate directories (/wp-*/) or scripts.

So the default suggested set of rewrite rules for subdirectory mode is this:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

Whereas the set for subdomain mode is suggested as this:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]

What type of rule set is used highly depends on the desired domain schema you're planing for your multisite. The more flexible one of course is the first one (sub directory) as the URL path segment («sub directory») is totally optional.

Sunrising (WordPress routing) and is_subdomain_install() API function

In order to know what mode is configured, WordPress provides the function is_subdomain_install() it returns true if:

  • the constant SUBDOMAIN_INSTALL is defined and set to true or
  • the constant SUBDOMAIN_INSTALL is not defined but VHOST is defined and set to 'yes'

It returns false if SUBDOMAIN_INSTALL is defined and set to false. And it returns anything else if SUBDOMAIN_INSTALL is defined but not of type boolean. The site meta value mentioned above is only used during the mutliste setup process. WordPress core relies only on the value of this constant everywhere else.

However, the value of is_subdomain_install() affects the routing of the requested URL to a specific site in the network only if the constants DOMAIN_CURRENT_SITE and PATH_CURRENT_SITE are not defined. (See ms_load_current_site_and_network()). That means it's possible to use any domain as site URL in both modes (domain mapping).

Switching modes after setup

Switching form subdomain to subdirectory mode

  • Change the value of the constant IS_SUBDOMAIN_INSTALL from true to false
  • Set the value of site meta subdomain_install to 0:

    $wp site option set subdomain_install 0

  • Add the prefix /blog/ to the permalink structure of the main site. It will be fixed after the setting was updated.
  • Add blog to the list of forbidden site slugs. As this list is a serialized value, this should be done via a small PHP script that can be run via WP-CLI:

$ wp eval-file patch-forbidden-slugs.php

// patch-forbidden-slugs.php
<?php
$illegalNames = get_metadata( 'site', SITE_ID_CURRENT_SITE, 'illegal_names', true );
$blogSlug = 'blog';
if ( in_array( $blogSlug, $illegalNames ) ) {
    exit( 'Noting to do' . PHP_EOL );
}
$illegalNames[] = $blogSlug;
update_metadata( 'site', SITE_ID_CURRENT_SITE, 'illegal_names', $illegalNames );
exit( 'Done' . PHP_EOL );

Switching form subdirectory to subdomain mode

  • Change the value of the constant IS_SUBDOMAIN_INSTALL from false to true
  • Set the value of site meta subdomain_install to 1:

    $ wp site option set subdomain_install 1

  • Remove the /blog/ prefix from the permalink structure of the main site

  • Remove the blog slug from the list of forbidden names (adapt the script from above accordingly)

Conclusion

My remarks only consider a clean WordPress installation and an immediate following network installation. Also the latest WordPress version 4.8 is considered. It might be possible that there are implications when doing a multisite installation on an existing system that uses plugins or any older WordPress version.

However, my preferred set up is the subdomain mode with the .htaccess rule set for subdirectories as it offers the most flexibility out of the box. It even works with modern composer-controlled setups like WPStarter (with slight adaption of the .htaccess rules).

  • you obviously can not change a live site because of implications on incoming links ;) I personally would not change it even at development, as it sound easier to just reinstall it with the right setting. – Mark Kaplun Oct 23 '17 at 11:55
  • Well, changing permalink structure always requires a redirect strategy when talking about existing public sites. – David Oct 23 '17 at 12:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.