Getting multisite with domain mapping to work with subdirectory or subdomain

I started out to make a multisite using subDIRECTORY but found problems along the way. The first being the default for a new wordpress install is subDOMAIN after enabling the network setting in my environment. I am not going into all the problems I ran into along the way to arrive at this configuration but I hope that someone can find a problem with this current configuration before it bites me or someone using this configuration.

I ended up with an .htaccess file that I believe supports subDIRECTORY and subDOMAIN at the same time. Additionally hating hardcoding I configured the multisite part of wp-config.php to handle any domain. So I hope this configuration can just be duplicated for the next site.

I don't know if I accomplished a totally working configuration. I am brand new to this platform with most of my experience in the Drupal word.

I now seem to have a working multisite with domain mapping using the wpmu plugin Domain Mapping. The various pieces of info around the web and here in support land helped to cobble together the following files: .ht access and wp-config.php

I am writing this to ask if anyone can find a problem in this configuration going forward actually using and expanding a multisite network and hopefully it will help someone get to here much faster than I did. I plan on using more plugins like pro sites, marketpress ecommerce and multisite content copier and would really like to know if I am going to have problems using these plugins and others.

One thing I have not included in the .htaccess file are these uploaded files lines. Not sure if it is needed but I saw it mentioned in a lot of places. Is it needed?
#uploaded files
RewriteRule ^(.*/)?files/$ index.php [L]
RewriteCond %{REQUEST_URI} !.*wp-content/plugins.*
RewriteRule ^(.*/)?files/(.*) wp-includes/ms-files.php?file=$2 [L]

Here are my current configurations.
################# .htaccess ###############################
.
# BEGIN WordPress
<IfModule mod_rewrite.c>
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

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

RewriteCond %{REQUEST_URI} !^/([_0-9a-zA-Z-]+/)wp-admin$
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

RewriteCond %{REQUEST_URI} ^/([_0-9a-zA-Z-]+/)(wp-(content|admin|includes).*)
RewriteRule ^([_0-9a-zA-Z-]+/)(wp-(content|admin|includes).*) $2 [L]

RewriteCond %{REQUEST_URI} !^/([_0-9a-zA-Z-]+/)(wp-(content|admin|includes).*)
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]

RewriteCond %{REQUEST_URI} ^/([_0-9a-zA-Z-]+/)?(.*\.php)
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]

RewriteCond %{REQUEST_URI} !^/([_0-9a-zA-Z-]+/)?(.*\.php)
RewriteRule ^(.*\.php)$ $1 [L]

RewriteRule . index.php [L]

# END WordPress

</IfModule>

.################## wp-config.php #########################
Just the parts I added

define( 'SUNRISE', 'on' );
define( 'WP_ALLOW_MULTISITE', true );
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
// define('DOMAIN_CURRENT_SITE', 'domain.tld');
define('DOMAIN_CURRENT_SITE', $_SERVER[ 'HTTP_HOST' ]);
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
define( 'COOKIE_DOMAIN', $_SERVER[ 'HTTP_HOST' ] );
// define( 'COOKIE_DOMAIN', 'domain.tld');

I am posting this early since I just got this to work and the testing I have done so far is just on subDIRECTORY setup, adding sites, deleting sites, mapping domains, multiple domain mapping to a single site, visit sites, edit sites all on the default stuff without adding any additional plugins. I have not tested the subDOMAIN setup other than the initial setup to be able to change settings at the time of this writing.

Right now I have 1 multisite with pulgins: WPMU dashboard, snapshot and domain mapping network activated using subDIRECTORY for sites. I am testing 6 sites using 6 different domain.tld and 2 sites using the subdirectory url. I am running on Centos 7, Plesk 12.5, Apache+Nginx , PHP 5.4.16

thanks in advance.

  • Adam Czajczyk

    Hello wpmudevorg24,

    I hope you're well today and thank you for your post!

    Would you mind if I ask you for some additional explanation on this before we go any further? You mentioned that you now have a setup that "supports both sub-domain and sub-directory" multisite at once. That makes me really confused.

    By default, WordPress Multisite wants you to use it as a sub-domain setup but setting

    define('SUBDOMAIN_INSTALL', false);

    in wp-config.php file makes it a sub-directory install. Just to make sure that we're on the same side here:

    - the "sub-domain" install doesn't mean that WP is installed under a sub-domain but that all sub-sites will be set under sub-domains of your mainsite (e.g. mysite.domain.com, yoursite.domain.com, othersite.domain.com etc)

    the "sub-folder" install, accordingly, doesn't mean that WP is installed in sub-folder but that all sub-sites will be available via URL's like e.g. "domain.com/mysite", "domain.com/yoursite", "domain.com/othersite".

    By design, there's no way to use both options at once so it's always one or another. Forgive me please if I'm saying something obvious to you, but I'd like to avoid confusion here.

    That said, could you please shed some light on this for me?

    Thanks!

    Have a nice day,
    Adam

  • Lee

    Correct i did not mean that you could use sub domain and sub directory at the same time only that you should be able to use either by making one change setting SUB DOMAIN INSTALL to true or false. I should have been more clear on that point.

    In my mind it was always a URL assigned to access a site package. I used sub directory language because of what i have read piecing this together. I had the impression others thought of these sub directories.

    In Drupal it would just be a PATH (url) not called a sub directory. We could set any PATH to any internal point like a view, page, directory etc. I see plugin Domain Mapping calls it Site Address.

    Sorry for the confusion.

  • Adam Czajczyk

    Hello wpmudevorg24,

    Thanks for your response.

    I thought so but I just wanted to make sure. I'm not much familiar with Drupal (I think I installed it once in my life) so I'm not sure how much different it is apart the terminology but it seems you got it working. That said, let me put it this way (though that's not the best answer, I know): if it is working, it is working :slight_smile:

    One part of your config though makes me wondering a bit:

    define('DOMAIN_CURRENT_SITE', $_SERVER[ 'HTTP_HOST' ]);

    I understand that it's not causing any troubles so far, is that right? This should substitute the "DOMAIN_CURRENT_SITE" constant with the domain that's been used to access your site so I'm not sure if this will take any effect here: for mapped domain the "Domain Mapping" plugin is handling all domain "mapping and rewrites" and for the main site - there's only one domain and it should be defined there. Actually, I'm not even sure if it does take any effect in "wp-config.php" file.

    Having said that, I think that if your setup is currently working, it would mean that it's configured "well enough" for Wordpress so is there any specific that I could help you with?

    Best regards,
    Adam

  • Lee

    I don't know what i don't know about future plugins thats why i ask if their might be or that i was missing something.

    Dynamic domain assignment: I would think there are less problems resovling redirects, links and callbacks when you have the correct domain names. Well at least it is not giving me a problem right now.

    Htaccess: I am used to seeing extensive. Htaccess files and config files for a multisite in drupal that are auto generated at install and for the most part never need changed. The skimpy incomplete htaccess file i see on a new wordpress install makes me think many issues are going to show up latter when i start installing more plugins.

    The htaccess file shown at install is totally absent of any security protections for running a web site. Is there a complete secure htaccess file example?

    Thanks.

  • Adam Czajczyk

    Hello wpmudevorg24,

    I don't know what i don't know about future plugins thats why i ask if their might be or that i was missing something.

    I see you point though as much as I'd love to I'm not able to foresee how your setup would play with plugins/themes in future as it's pretty uncommon.

    Dynamic domain assignment: I would think there are less problems resovling redirects, links and callbacks when you have the correct domain names. Well at least it is not giving me a problem right now.

    The default WordPress Multisite setup shouldn't cause many trouble of that kind. The difficulty here is that I'm really not aware what issues exactly it was causing. I suppose some of them would be solved/fixed in quite a different way. At this point I don't think I could diagnose those unless you'd be willing to revert entire setup to default one and start "from scratch". I suppose your Drupal experience paradoxically got a bit "in a way" here (forgive me my boldness please!) as from what I can see (after a short research over the web) Drupal is really different if it comes to "tweaking things".

    Htaccess: I am used to seeing extensive. Htaccess files and config files for a multisite in drupal that are auto generated at install and for the most part never need changed. The skimpy incomplete htaccess file i see on a new wordpress install makes me think many issues are going to show up latter when i start installing more plugins.

    WordPress doesn't work like Drupal and that "skimpy incomplete" htaccess is all it needs in most cases. It can handle everything else on a script level and the .htaccess should be kept here as simple as possible (unless there's no other way to do something than changing it). Furthermore, many issues with plugins come from modified .htaccess rather than the default one :slight_smile:

    The htaccess file shown at install is totally absent of any security protections for running a web site. Is there a complete secure htaccess file example?

    With that I would agree. That's why there are plugins such as e.g. our own Defender that add additional security level to WP, including some modifications on .htaccess level.

    Best regards,
    Adam

  • Lee

    Thank you for the reply but there really is a lot more to htaccess than script play. I really think Wordpress Core install should address many of these things. There is very little problem installing Drupal on any environment with a carefully crafted htaccess file. I think I will leave this discussion with a Drupal 7 core install of .htaccess file for your amusement. Thank you for your time.

    #
    # Apache/PHP/Drupal settings:
    #

    # Protect files and directories from prying eyes.
    <FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock))$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
    Order allow,deny
    </FilesMatch>

    # Don't show directory listings for URLs which map to a directory.
    Options -Indexes

    # Follow symbolic links in this directory.
    Options +FollowSymLinks

    # Make Drupal handle any 404 errors.
    ErrorDocument 404 /index.php

    # Set the default handler.
    DirectoryIndex index.php index.html index.htm

    # Override PHP settings that cannot be changed at runtime. See
    # sites/default/default.settings.php and drupal_environment_initialize() in
    # includes/bootstrap.inc for settings that can be changed at runtime.

    # PHP 5, Apache 1 and 2.
    <IfModule mod_php5.c>
    php_flag magic_quotes_gpc off
    php_flag magic_quotes_sybase off
    php_flag register_globals off
    php_flag session.auto_start off
    php_value mbstring.http_input pass
    php_value mbstring.http_output pass
    php_flag mbstring.encoding_translation off
    </IfModule>

    # Requires mod_expires to be enabled.
    <IfModule mod_expires.c>
    # Enable expirations.
    ExpiresActive On

    # Cache all files for 2 weeks after access (A).
    ExpiresDefault A1209600

    <FilesMatch \.php$>
    # Do not allow PHP scripts to be cached unless they explicitly send cache
    # headers themselves. Otherwise all scripts would have to overwrite the
    # headers set by mod_expires if they want another caching behavior. This may
    # fail if an error occurs early in the bootstrap process, and it may cause
    # problems if a non-Drupal PHP file is installed in a subdirectory.
    ExpiresActive Off
    </FilesMatch>
    </IfModule>

    # Various rewrite rules.
    <IfModule mod_rewrite.c>
    RewriteEngine on

    # Set "protossl" to "s" if we were accessed via https://. This is used later
    # if you enable "www." stripping or enforcement, in order to ensure that
    # you don't bounce between http and https.
    RewriteRule ^ - [E=protossl]
    RewriteCond %{HTTPS} on
    RewriteRule ^ - [E=protossl:s]

    # Make sure Authorization HTTP header is available to PHP
    # even when running as CGI or FastCGI.
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Block access to "hidden" directories whose names begin with a period. This
    # includes directories used by version control systems such as Subversion or
    # Git to store control files. Files whose names begin with a period, as well
    # as the control files used by CVS, are protected by the FilesMatch directive
    # above.
    #
    # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is
    # not possible to block access to entire directories from .htaccess, because
    # <DirectoryMatch> is not allowed here.
    #
    # If you do not have mod_rewrite installed, you should remove these
    # directories from your webroot or otherwise protect them from being
    # downloaded.
    RewriteRule "(^|/)\." - [F]

    # If your site can be accessed both with and without the 'www.' prefix, you
    # can use one of the following settings to redirect users to your preferred
    # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
    #
    # To redirect all users to access the site WITH the 'www.' prefix,
    # (http://example.com/... will be redirected to http://www.example.com/...)
    # uncomment the following:
    # RewriteCond %{HTTP_HOST} .
    # RewriteCond %{HTTP_HOST} !^www\. [NC]
    # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    #
    # To redirect all users to access the site WITHOUT the 'www.' prefix,
    # (http://www.example.com/... will be redirected to http://example.com/...)
    # uncomment the following:
    # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]

    # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
    # VirtualDocumentRoot and the rewrite rules are not working properly.
    # For example if your site is at http://example.com/drupal uncomment and
    # modify the following line:
    # RewriteBase /drupal
    #
    # If your site is running in a VirtualDocumentRoot at http://example.com/,
    # uncomment the following line:
    # RewriteBase /

    # Pass all requests not referring directly to files in the filesystem to
    # index.php. Clean URLs are handled in drupal_environment_initialize().
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !=/favicon.ico
    RewriteRule ^ index.php [L]

    # Rules to correctly serve gzip compressed CSS and JS files.
    # Requires both mod_rewrite and mod_headers to be enabled.
    <IfModule mod_headers.c>
    # Serve gzip compressed CSS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.css $1\.css\.gz [QSA]

    # Serve gzip compressed JS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.js $1\.js\.gz [QSA]

    # Serve correct content types, and prevent mod_deflate double gzip.
    RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
    RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]

    <FilesMatch "(\.js\.gz|\.css\.gz)$">
    # Serve correct encoding type.
    Header set Content-Encoding gzip
    # Force proxies to cache gzipped & non-gzipped css/js files separately.
    Header append Vary Accept-Encoding
    </FilesMatch>
    </IfModule>
    </IfModule>

    # Add headers to all responses.
    <IfModule mod_headers.c>
    # Disable content sniffing, since it's an attack vector.
    Header always set X-Content-Type-Options nosniff
    </IfModule>

  • Adam Czajczyk

    Hello wpmudevorg24!

    That .htaccess - it's a really nice addition to a WP security discussion, thank you for that! I wish it'd be in my power to introduce it to WordPress but sadly nor we (WPMU DEV) are makers of WordPress neither am I involved in its development :slight_smile:

    Yet, the .htaccess looks nice and I'll make our Defender plugin developer look at it so hopefully it'll inspire him.

    Thanks!

    Have a nice day,
    Adam

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.