Users, Permissions Accross Subdomains

DaneAU's picture

Hello,

I am glad to find this group and am hopeful someone has some advice for me. I have been attempting to setup a new site this evening and cannot get it quite right. Just a few things first off about what i am setting out to achieve. Firstly i am attempting to share the users accross mutiple sites along with their permissions. I am also trying to keep certain aspects such as Blocks and menu's separate for each site, although a unified Primary Links would be helpful but not essential. All my attempts have succeed in allowing single user signin on each site however i cannot for instance change the sites slogan for each site.

My setup is as follows, i have created some subdomains via cpanel and pointed all of them to /public_html/ as i have read here ~ helpful article.

I have the following domains i wish to use a single drupal install for.

  • example.com
  • support.example.com
  • projects.example.com

I have then created the relevant directories for them along with the settings.php for each site.

/public_html/sites/default/settings.php
/public_html/sites/example.com/settings.php
/public_html/sites/support.example.com/settings.php
/public_html/sites/projects.example.com/settings.php

I then go on to install the first main site example.com/install.php and remove any of the 'shared' tables before installing the next site support.example.com/install.php and repeating the process until the final site (leaving the required shared tables).

My main question is what tables should i be sharing and what should i not be considering the following list of things i wish to achieve.

  • Single User Table and User Profiles (Signon on any of the sites)
  • Create Custom Blocks on Per Site Basis
  • Create Custom Menus on Per Site Basis
  • Have Custom Site Configuration (Different Site Slogan) Per Site.

I should add that i have customised my settings.php according to the linked article above for the section related to cookies. The part i am struggling with is which tables to share and which not to so that i can achieve the aforementioned goals. If this is something difficult and tedious to do i am up for it, however i require some advice on what it is i should be looking for.

After much reading i discovered that there are certain tables that are highly site specific such as any of the cache* tables, i note the variable table stores the sites information and i have attempted prefixing this on a per site basis however for some very odd reason any changes to the Slogan is reflected site-network wide rather than on a per site basis.

If anyone has some input on this i would be most appreciative.

Kind Regards
DaneAU

Comments

Partially Solved - Solution and Explanation

DaneAU's picture

I have come to a point of solving this setup. I now have 5 sites setup and 6 databases.

They are as follows
Sites

  • example.com
  • site1.example.com
  • site2.example.com
  • site3.example.com
  • site4.example.com

Databases

  • x_shared
  • x_main
  • x_site1
  • x_site2
  • x_site3
  • x_site4

As a starting point i have decided only to share a few things accross all sites. They are

  • 'users'
  • 'sessions'
  • 'role'
  • 'authmap'

I was going to share menu's however the way the DB stores menu's would mean that all Primary and Navigation links would be stored accross sites, despite them having totally different destinations. This would be a nightmare. Subsequently the simplest solution was simple to re-create the menu's for each site. What i mean is my primary links have simple links to the 5 sites.
Home | Site1 | Site2 | Site3 | Site4
Each site then has its own set of custom menus and administration links which would require a lot of work to do properly.

Anway with the points raised thus far in mind i setout to install and setup my site. It worked first time basically. You will need phpMyAdmin because you will be required to drop some tables after each installation.

So i created a directory structure as follows with a settings.php file (Discussed Later) in each.

public_html/sites/default/settings.php
public_html/sites/example.com/settings.php
public_html/sites/site1.example.com/settings.php
public_html/sites/site2.example.com/settings.php
public_html/sites/site3.example.com/settings.php
public_html/sites/site4.example.com/settings.php               

settings.php file setup

My settings file took me some time, in all honesty i am not sure if this is the right way of doing what i was attempting, however it does appear to be working at this current point in time.
For the first file contained within both the sites/default and sites/example.com directory the settings file is as follows.

<?php
$databases
['default']['default'] = array (
 
'driver' => 'mysql',
 
'database' => 'x_main',
 
'username' => 'db_username',
 
'password' => 'db_userpassword',
 
'host' => 'localhost',
 
'prefix' => array (
   
'default' => 'x_main.',
   
'users'    => 'x_shared.',
   
'sessions' => 'x_shared.',
   
'role' => 'x_shared.',
   
'authmap' => 'x_shared.',
  ),
);

$databases['default']['default'] = array (
 
'driver' => 'mysql',
 
'database' => 'x_shared',
 
'username' => 'db_username',
 
'password' => 'db_userpassword',
 
'host' => 'localhost',
 
'prefix' => array(
   
'default' => 'x_main.',
   
'users' => 'x_shared.',
   
'sessions' => 'x_shared.',
   
'role' => 'x_shared.',
   
'authmap' => 'x_shared.',
  ), 
);

$update_free_access = FALSE;
$drupal_hash_salt = '';
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);
ini_set('session.gc_maxlifetime', 200000);
ini_set('session.cookie_lifetime', 2000000);

/* This is important, change to your domain name */
$cookie_domain = 'example.com';
?>

So basically what this does is make connections to both the x_shared and x_main database. The x_main is for the root website or that running on the example.com domain. The $cookie_domain is important and will aid in keeping users logged in across all sites running on subdomains. I am not sure how to do this if you are running multiple TLD's.

For the x_shared (first database connection) database we instruct drupal using prefix to select the correct database for the fields. For instance the default prefix is set to 'x_main.' notice the ( . ) as its important, this means everything is to be stored in the x_main database as the format is [database].[table] ~ Except for the extra prefixes which are the tables we want shared. We instruct drupal to use the x_shared database using 'users' => 'x_shared.', note the ( . ) once again as its important.

For the x_main (second database connection) database we instruct drupal using prefixes again to select the correct database for each of the fields. This will ensure we can connect to both databases and that we update and select from the correct tables.

First Installation

Now that you have this setting.php in both the sites/default and sites/example.com directory its time to begin part of the installation.
Go to example.com/install.php and go through the installation, you shouldn't need to put any database information in inclusive of prefixes as you have done it in the settings.php file. Once complete view your site and create a user. You will be repeating this a few times depending on how many sites you are seeking to run together.

Once complete open up phpMyAdmin or your choice and go to the scheme x_shared ~ Drop All Tables

Now you are ready to install site two. For the second site site1.example.com you will need to alter the settings.php, the alterations are minimal as all we are doing is ensuring that we have access to the x_shared database and that anything else is stored in the x_site1 database.

Below is an example of the settings.php

<?php
$databases
['default']['default'] = array (
 
'driver' => 'mysql',
 
'database' => 'x_site1',
 
'username' => 'db_username',
 
'password' => 'db_userpassword',
 
'host' => 'localhost',
 
'prefix' => array (
   
'default' => 'x_site1.',
   
'users'  => 'x_shared.',
   
'sessions' => 'x_shared.',
   
'role' => 'x_shared.',
   
'authmap' => 'x_shared.',
  ),
);

$databases['default']['default'] = array (
 
'driver' => 'mysql',
 
'database' => 'x_shared',
 
'username' => 'db_username',
 
'password' => 'db_userpassword',
 
'host' => 'localhost',
 
'prefix' => array(
   
'default' => 'x_site1.',
   
'users' => 'x_shared.',
   
'sessions' => 'x_shared.',
   
'role' => 'x_shared.',
   
'authmap' => 'x_shared.',
  ), 
);

$update_free_access = FALSE;
$drupal_hash_salt = '';
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);
ini_set('session.gc_maxlifetime', 200000);
ini_set('session.cookie_lifetime', 2000000);

/* This is important, change to your domain name */
$cookie_domain = 'example.com';
?>

If you have not dropped the x_shared tables do so or you will get Drupal spitting up errors about the installation being complete when it attempts to create the tables in the x_shared database.

Now go to your second install site1.example.com/install.php

Follow the installation till completion.

If you are simply running 2 sites then you can leave it at this and configure your sites now. If you are intending to install another site then you will need to drop the x_shared tables again and alter the lines of the settings.php for the next site. You can repeat this process, on the last installation you don't drop the x_shared tables as they are sitewide now and utilised by all your installs. If you do drop them your entire batch of sites won't function.

You can now go through and configure your sites, for instance as an example which is one of the things i was setting out to achieve. I can have the same SiteName however change the Slogan for each site.

I chose not to share menu's so you will need to manually create them and so forth.

afterthoughts
Adding A Site Later On:
I was thinking about this, have no real solution yet, however i believe that one may be able to edit the install scripts to ensure that the tables usually created i.e. the ones we are sharing are not attempted to be created, this would avert the errors and so long as the settings.php is correct we should be able to tap into the relevant user base and ensure our site remains functional and users are able to utilise the new service created for them?

Installing multisites

manuel_mra's picture

Hi:
Thank you very much for your help. I'm gonna try and then if it doesn't work i hope you get some time to help me to fix errors.
Would you like to explain me why do say "partially solved" ?
Thanks.

Manuel.

Glad for the help if you

DaneAU's picture

Glad for the help if you found it as such. I may be able to guide you on errors, however if you follow the directions you shouldn't encounter any.

As for partially solved, i am referring to the fact there are some aspects that have not been tested enough as of yet. For instance i would like some of the module's information and settings to be shared accross all sites, meaning i can set the captcha settings in once place and it will be reflected across all sites. Where the problem lies in this is that there are other modules which are to be kept separate, for instance if i was to have ubercart on store.example.com i would like to keep that contained within x_store database only, however the captcha module settings i would like within the x_shared database.

Although this is not of major concern as of course it just means more lifting when adapting settings and i can still unify the module files within the sites/all directory to limit the codebase, the distinction between that and settings is harder to unify. Although permissions are united accross all sites.

Another small issue i am encountering has to do with cron.php - now if i run cron from site1.example.com administration it does not show up as having been run on any of the other sites, despite the fact that there is only one cron.php in my public_html directory. This is something i need to sort out and research before claiming that i have it all working perfectly.

If you would like to have a look over the site i have running at the moment you can do so here.

Kind Regards

duplicate assignment

diddledan's picture

you're assigning twice using the following code:

$databases['default']['default'] = array (
..<snip>
);

This means that the second use of this assignment will OVERWRITE your first assignment. It appears you're trying to use multiple databases with prefixes. In essence your configuration as stands will put ALL tables into the x_shared database. It works ok, because you have your prefixes set up to not cause issues. According to your other posts on this topic you're trying to get multiple databases for performance reasons but, as far as I can tell, your current configuration will not do so.

royhink's picture

Thank you for this well written guide!

I am new to Drupal, so I apologize in advance if the question is basic.

With your setup, are you able to restrict user access to certain sites and allow access to others?

Permissions Across Databases

lithium's picture

Hi DaneAU,

What you have here looks good for the other info I've read on the topic about sharing users and sessions across muti-sites. I'm going to be doing this myself and I was wondering if you knew what the minimum set of permissions are to grant the database user of x_site1 to the database of the x_shared for it to work correctly? Thanks.

Cheers,

Brad

Oopps i forgot to add the

DaneAU's picture

Oopps i forgot to add the following lithium, I have used a single user for all databases. I have given the users all the permissions on each of the database. As for the minimum permissions i am really not quite sure on what is required. Like you i setout to do this blind and have read my way through all the documentation to arrive at a solution. I would say that because each settings.php has a connection to a minimum of 2 databases that you may be able to limit permissions for instance by revoking UPDATE or INSERT on some of the sites, meaning for instance you could have a dedicated site users.example.com and it is here than any profile adjustments are done. Other than that i am not sure and i appologise for this :(

I'd suggest to give normal

rpsu's picture

I'd suggest to give normal Drupal usage permissions to each database/user that your site need to get access. That would be something like

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES, CREATE TEMPORARY TABLES ON databasename.* TO 'username'@'localhost' IDENTIFIED BY 'password';

If you want to have all user data modification (password and so on) in one site, for example through secure site, you may simply redirect all /user, /user/login, /user/password etc. urls to your secure site. I've done this simply using apache rewriting in .htaccess -file (see http://en.wikipedia.org/wiki/Mod_rewrite).
For example:

  RewriteRule ^(user)$ https://users.example.com/$1 [R=permanent,L]
  RewriteRule ^(user/login)$ https://users.example.com/$1 [R=permanent,L]
  RewriteRule ^(user/register)$ https://users.example.com/$1 [R=permanent,L]
  RewriteRule ^(user/password)$ https://users.example.com/$1 [R=permanent,L]

--
Perttu Ehn

You can also use the Domain

CPJS's picture

You can also use the Domain Access Module.

More details on a case study.

any update concerning adding new site

raphael waeselynck's picture

Hi,
Any clues about adding a new website in this multisite configuration ?