Drupal 10, the latest version of the open-source digital experience platform with even more features, is here.Problem/Motivation
Now that we've adopted Composer as a build tool for Drupal, we're left with some features of drupal that still need adaptation and engineering to work.
Multisite Drupal is an extremely useful feature for many sites, and the consensus is that its a critical feature that cannot be replaced with multiple single sites.
Let's use this issue to do 2 things:
1. Document what multisite is, and the use cases people use it for. i.e *why* do people need it, and *how* do they use it?
2. Brainstorm potential solutions and look for a path forward that allows a multisite user to be able to use any of the modules that have 3rd party composer dependencies, and allow them to update and mange their site with composer.
Proposed resolution
Still TBD. The trickiest use case to support with Composer seems to be a multisite where there are variations of modules/themes on a per-site basis. (For example, someband.com and someotherband.com offer the same features [photo gallery, discography, tour], but have vastly different designs, and/or someotherband.com has an integration module with some one-off analytics application that no other sites want/need.)
This gets tricky because modules + themes are individual projects in Composer, and Composer assumes there is only one location all dependencies are going into. (By default /vendor) This is incompatible with the idea that there are multiple places to look for extension code (sites/all + sites/someotherband.com)
Possible ideas that have been tossed around:
- #17: Move forward with the Composer initiative, not accounting for this use case for now (and documenting such), and work upstream with the Composer project to handle it in a generic way for more than just Drupal.
- #20: Use Composer's ability to override installer paths on an individual package level, along with custom magic in our autoloader, to place some code in different directories. However, there are quite a few downsides to this plan, as documented in #22.
- #36: Add a composer.lock and vendor/ directory to each /sites directory, similar to how you can add a per-site /modules or /themes directory currently. Requires adjustment to the autoloader, possibly other things, but is consistent with the current approach.
- Others?
Remaining tasks
Document use cases for multisite that need to be supported in a Composer-y worldCaptured at https://www.drupal.org/docs/8/multisite/use-cases-for-drupal-multisite- Brainstorm potential solutions and look for a path forward










Comments
Comment #2
MixologicComment #3
MixologicSome initial things:
Comment #4
MixologicComment #5
MixologicComment #6
Mile23Just to point out that both Simpletest and functional PHPUnit-based tests make use of multisite features in order to run tests.
So short of refactoring all that away in preference for something else, all the multisite stuff that tests touch are solid base use-cases and need-very-much features.
Comment #7
catchWhile this works for modules, it doesn't work for core, and updating one multisite can be done with a separate check out. Given the necessity to run database updates immediately after updating code (especially core minor updates) I'm not sure how larger multisites handle this at all.
The last site I worked on that did this was on Drupal 7 iirc, and it caused a lot of trouble, while we still technically support it, it would be good to know what the up-to-date use cases are and what exactly is being shared.
Comment #8
geerlingguy CreditAttribution: geerlingguy at Midwestern Mac, LLC commentedThey can do it in parallel; I have a job that basically kicks off
drush updbon each site in parallel after the updated code is deployed. Assuming you don't have thousands of sites on one small database cluster, the use case is handled well. Any errors bubble up in the build as a failure, then you can fix those individual sites that had update issues as needed (this rarely happens, though, at least in my situation).Re: Shared tables. I'm not sure why we still support this... it was originally meant for environments where a customer has one database (e.g. on shared hosting or something) and they want to install a bunch of sites into that one database. I haven't seen that usage pattern almost anywhere recently, though. Most shared hosting providers capable of hosting a Drupal site nowadays also have the ability for users to click a button and add a new database as needed, with a lower limit of 5 databases usually. (I could be proven wrong here though, but that's how it is for most shared hosting plans I encounter nowadays.)
Comment #9
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedComment #10
MixologicI think that the testing framework probably relies on the shared database table stuff at the very least. Maybe its used to share users between sites? or maybe used for sharing content? Taxonomies? dunno.
Comment #11
dawehnerThe testing framework uses different prefixes, but it doesn't share some of the tables. We are save here.
Like @geerlingguy just said, you can solve problems with multisite with automation. You can though also replicate multisites using automation in the first place. I am wondering whether we could introduce in a minor release some way of tracking that a site is executed in multi-site mode. I would expect its a really small number.
Historically I've used it to share users indeed, but for example for that usecase, there are much better single sign on solutions out there for example. Also for sharing content between sites there are various tools out there already.
In feels like in general with multisite, no matter which usecase you have, there is a better solution/alternative out there.
Comment #12
MixologicExcept, perhaps, this one:
Comment #13
geerlingguy CreditAttribution: geerlingguy at Midwestern Mac, LLC commentedThis is precisely why I use it, and pretty much the only reason many of the sites I run are Drupal. If I couldn't run a dozen or so sites in the memory footprint of a small 512 MB VPS (owing to the fact that they all run in shared opcache space so it's highly memory efficient), there would be at least a few dozen fewer Drupal 7 sites in the world, and about 5 fewer Drupal 8 sites in the world ;-)
No way I can pay for the memory to host all the small business, personal and non-profit sites I currently run on Drupal if each codebase needed its own memory allocation.
I definitely agree that automation solves the problem, but at an ongoing monetary cost. Enterprise level, it hardly matters, but for thousands of smaller sites, .edu sites (many unis host hundreds or thousands of sites in one multisite install), etc. the cost of hosting would go through the roof based on memory requirements alone.
Comment #14
catchShared tables should be considered unsupported at this point - it's writing to the database without going through core APIs (for the site that doesn't trigger the database write). We should open an issue to document this somehow. Prefixing itself is a bit wider. Similarly core updates aren't written to be re-entrant, so a schema change to a shared table would be made twice. I would not rule out a site using shared tables, but there can't be many at this point, and if similar functionality is needed (like sessions or something) it could be achieved by replacing the storage entirely to use a shared database.
opcache takes symlinks into account (whereas apc did not), this means that if 100 symlinks point to the same directory, opcache will cache a single directory, not 100.
It should therefore be possible to build a 'multisite' deployment where everything except the /sites directory for each site is a symlink, and get the same memory benefit.
Comment #15
anavarreShould this be a target issue for Drupal 9? Also, should it live under the 'Drupal core ideas' project for now? It doesn't strike me ATM that we know exactly what we want to do with multisite just yet.
Based on the very interesting debates in #2306013: Multisite is a valued feature that will not be deprecated. and other related issues I kept a few highlights worth sharing here. They're primarily outlining the cons to keeping multisite (as we know it) which is where progress needs to be made the most.
#2306013-18: Multisite is a valued feature that will not be deprecated.
#2306013-23: Multisite is a valued feature that will not be deprecated.
#2306013-38: Multisite is a valued feature that will not be deprecated.
#2306013-43: Multisite is a valued feature that will not be deprecated.
#2306013-57: Multisite is a valued feature that will not be deprecated.
#2845379-24: Provide optional composer integration but don't force users to understand how to use composer
#2996988: Consider adding "Domain Access" (or equivalent) to core (IS)
#2958021-80: Proposal: Composer Support in Core initiative
---
I keep on reading Drupal is no longer friendly for hobbysts, EDU and shared hosts on the one hand, and on the other hand those thinking that Drupal should catch up with the rest of the PHP community and fully embrace Composer everywhere at the risk of making radical decisions, like removing multisites. It looks like with such a wide spectrum nobody will be happy as we look at different personas with different needs and a different skill set.
To measure success with this plan, IMHO we should make sure to prevent the bike shed and antagonistic arguments like those often made in #2306013: Multisite is a valued feature that will not be deprecated. where multisite users felt betrayed or feared that something was going to be taken away from them.
Comment #16
catchOn composer, these are the limitations compared to tarballs:
Because you can only have a single version of a dependency, and it will always be installed to the same location (as configured in composer.json installer-paths). Given contrib modules are installed by composer, this means you can only have a single version of a contrib module.
Site-specific modules and themes could be put in sites/SITENAME directories via configuring composer.json to do so, that's an extra manual step but not a massive one in the scheme of things. You could also commit site-specific modules directly.
The thing that composer doesn't allow, but tarballs do, for multisite, is the following then:
1. Install a contrib module for sites/sitename1, sites/sitename2 but not sites/sitename3
2. Install a contrib module globally as 8.x-3.x, but have sites/sitename4 use the 8.x-4.x version.
So really you're OK as long as the modules and themes you're using are either in a 1-all or 1-1 ratio to sites, what composer doesn't support is 1-some.
Those two use-cases are really quite minor though, and the solution to it would for people to have two multisites instead of one to handle those cases.
The other consideration is that the 'optimized' composer classloader (and composer in general) does not have any concept of installed/uninstalled, and therefore trying to use it on a multisite would mean every single class in the installation being available to every other site, but this is already a problem for single-site installs too.
Comment #17
AaronMcHaleSome really good reading here, and thanks @anavarre for the summary.
Perhaps we could do the following:
To me that seems like the only way forward at this point, we can't not use Composer because of multi-site, but we also can't not have multi-site because of Composer.
Comment #18
user1252762 CreditAttribution: user1252762 commentedto answer *why* do people need it, and *how* do they use it?
i am site manager of one institute, with over 20 sites, running with multisite feature in drupal8 and 20 users with high level permission and without shared database ( we really wanted shared user but it seems it so tricky in drupal8 and there are better solution like LDAP )
why we don't use one site for all 20 departments?
1- most important thing is stability:
it happens lot of times that a misconfiguration or bad setting in blocks, path, menus or even bad content damage one site while other sites works perfectly, specially main site.
2- i am not sure if i can separate departments in one site and handle access for 20 users with core features (access to menus, taxonomies and ....). when we decide to go with drupal8, domain access had alpha release and what if there is no release of domain access for next drupal version?
3- every department is kind of independent, they really want a subdomain of main institute domain, and IMHO dept1.domain.com is more cleaner and feels more independent than domain.com/dept1 ( also when we compare dept1.domain.com/section1/page1 and domain.com/dept1/section1/page1) and i think it's tricky to have one instance of drupal site and address all pages of different departments with different subdomain.
why we don't have 20 different sites for all 20 departments?
- this sites have very similar functionality and modules are same, even theme is same for all sites. during one year it happens lot of times that i have to change theme a little bit to adjust things, it means i have to change code for all 20 sites individually.
also for core and modules updates, multisite solution is much simpler that separate sites.
- at last one day if there is not a perfect solution like multisite and i am forced to select one solution between 20 different sites or one site with 20 different section separated with built-in feature or module like domain access, i think i go with 20 different sites because more important thing to every organization is stability of site, even though this makes my life miserable with lots of updates and ...
Comment #19
joachim CreditAttribution: joachim as a volunteer commented> 1. Document what multisite is, and the use cases people use it for. i.e *why* do people need it, and *how* do they use it?
I often use multisite during development. It's really quick to spin up a new subsite to work on a specific issue.
Comment #20
joachim CreditAttribution: joachim as a volunteer commentedIt's possible to override installer paths on an individual package level. This allows you to place some modules or libraries into a profile's modules/ folder, eg:
(Note the brokenness of using a format that doesn't allow comments... :( )
That's pretty fiddly though, as you have to specify each module. Also, I'm having to do that in the top-level composer.json. It would be nice to be able to do it in the profile's composer.json, and rely on merging but: 1) installer-paths that override single packages MUST go above the package type path declaration, and 2) Composer merge-plugin doesn't document the order in which the data is merged, so that all seems a bit brittle to me.
> Because you can only have a single version of a dependency, and it will always be installed to the same location (as configured in composer.json installer-paths). Given contrib modules are installed by composer, this means you can only have a single version of a contrib module.
Just thinking aloud, probably totally wacky: write a Composer plugin that minimally bootstraps Drupal, figures out which profile you currently mean (by a command line parameter? by your current folder location like Drush does?), and then does the same sort of work as Composer merge-plugin to merge that profile's composer.json into the root, AND add into the Composer data the location overrides for that profile's modules. You'd then need to run 'composer install' once for each profile.
Hmm but at runtime we'd still need multiple autoload folders for the different combinations of Composer packages... which means we'd need to load the Composer autoloader for core packages, figure out the profile, then load the profile's Composer autoloader...
Comment #21
DamienMcKennaI've used multisite on every single Drupal site I ever work on, simply because of the hostname configuration files. There was only one project I ever worked on that has per-hostname modules or themes, and even then in hindsight they should have been shared and just kept in separate sites/all/modules/[project] directories. I don't think we need to work out a way of shoe-horning composer to let sites have multiple copies of the same files in the same repository, I think we could just drop that piece of functionality while still allowing the per-hostname configurations.
Comment #22
Mile23No, that's pretty close to the solution to allowing different dependencies based on different sub-sites. That is, we'd have multiple vendor directories and there'd be some very early boot phase that figures out which one to load based on request. Except that might be hard if we're using
Symfony\Component\HttpFoundation\Request(since we can't autoload it yet). That's solvable (I mean, there was a time before Symfony), but who wants to? Anyway...So in this scenario, the Composer install phase would be a plugin that knows how multisite works, can determine where to merge a composer.json file from, per sub-site, and then individually runs
composer installper sub-site to generate a vendor directory. This means a few things:composer require drupal/addressat the top level, even if you know that all sites need it. You'll have to edit a composer.json file per sub-site and then re-install.That's a complex spec to implement before 8.7.0 is released. :-)
Zactly. Just to use the plugin, we'd need some parts of core and core's dependencies. It might do us good to refactor to allow determining profile and/or subsite without any dependencies on the rest of core, but again: Who wants to?
So now, in the interest of staying on topic: This conversation is off topic. :-) What are the use-cases?
Comment #23
joachim CreditAttribution: joachim at Skunk Works commented> So now, in the interest of staying on topic: This conversation is off topic. :-) What are the use-cases?
The summary says:
> 2. Brainstorm potential solutions and look for a path forward that allows a multisite user to be able to use any of the modules that have 3rd party composer dependencies, and allow them to update and mange their site with composer.
I thought this was brainstorming :) Should we stick to use cases for now?
Comment #24
mmjvb CreditAttribution: mmjvb as a volunteer commented>1. Document what multisite is, and the use cases people use it for. i.e *why* do people need it, and *how* do they use it?
How embarrassing, this issue starts to look like window dressing! How to inform people that don't want to listen?
Documented here: https://www.drupal.org/docs/7/multisite/multi-site-sharing-the-same-code...
Additional use cases provided in #2306013: Multisite is a valued feature that will not be deprecated.
Comment #25
colanI've been avoiding this issue for far too long, especially since none of the other Aegir maintainers have chimed in yet. Apologies for not getting to this sooner.
But first, a little bit of background...
Aegir is the proper way to manage multi-site set-ups
If you're using multi-site, and not Aegir, I can only think of four (4) reasons why. (If I had 9 more, this could be a Netflix show.)
Basically, not using Aegir for multi-site is nuts.*
Now that that's out of the way...
Composer in Aegir
Aegir core has native support for Composer. After a new platform (Aegir-speak for a codebase) is provisioned, a build happens if necessary. (Technically, it's running
composer create-project --no-dev --no-interaction --no-progress.) So any sites that are deployed to the platform (i.e. have their site directory created or moved tosites/) can take advantage of it, even though they can still keep whatever they want in their site-specific folders (which are properly maintained).Additional functionality to support Composer on platform creation is handled by Aegir Deploy (which hasn't made it to Aegir core yet). This allows for, what we believe, to be all of the options necessary for the base case: All sites are using the exact same code.
Narrowing focus
As was alluded to earlier, the base case for this issue is: All sites are using the same code, and there are no modules, themes, or libraries in site-specific folders. For situations where that's not the case, we (the Aegir maintainers) haven't figured out a good way to handle this with Composer yet either, and would love to be part of that discussion.
But let's not have that discussion here now. Let's restrict our focus to the base case for now, and leave the site-specific asset handling/overrides for a future phase of this endeavour. Make it a follow-up issue.
Shared tables
I agree 100% on not supporting this. Aegir doesn't support this, and since I've been around, nobody's asked for it. I would actually create a Drupal core issue to officially un-support it, but do we really need to? Do we have support for it anywhere? If we do, let's create the ticket. Otherwise, let's simply drop it from the scope here. As everyone else here has said already, it's asking for trouble, and there are far better solutions for that (which we don't need to worry about here).
Moving forward
I believe #17 is definitely the way to go. Does anyone have a problem with that plan? If not, let's update the IS, and move forward with it. We can handle discussion like #20 and #22 in the follow-up issue.
I'm assuming by now that we've heard enough use cases. But please add more if we're missing anything.
* Not to be taken seriously.
Comment #26
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedI've got nothing against you or Aegir, but did you check with the entire community before declaring everyone not using Aegir "nuts"? It comes off a bit aggressive. There are reasons you haven't thought of not to use it.
Comment #27
colanThat's wasn't meant to be taken seriously. I'll edit to make it explicit. (Thanks for the tip.)
Comment #28
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedGot it!
Comment #29
gr8tkicks CreditAttribution: gr8tkicks as a volunteer and at University of California commentedI don't think Aegir adds anything here, the main issues I see with Multi-site under Drupal 8 are things that seem solvable, I just don't have the capacity to fix it myself. We are running 50 websites using Drupal 8 and Multi-site here at UCSF.
The key issues we run into are as follows:
https://www.drupal.org/project/drupal/issues/1356276
Comment #30
BerdirDidn't read everything, but we already agreed a while ago to drop support for sharing tables in 9.x, there should be an issue somewhere.
Looking for the issue... here we go: #2551549: Deprecate per-table prefixing. Committed and documented. End of (that part of the) discussion :)
Comment #31
mmjvb CreditAttribution: mmjvb as a volunteer commentedAgree with Shared Tables being off topic. It is not something that belongs in this discussion. You don't need multisite for Shared Tables, you need multiple sites.
For the same reason #2551549: Deprecate per-table prefixing should be reverted. Per table prefixing can be used for Shared Tables, but there are other uses as well. Per table prefixes allows you to integrate with data in other databases. It is very silly to have the requirement for data that you want to integrate with to be in the same database. DBA'ers will have a laugh at you and probably say no to that.
And if the above is not bad enough, you are taking something away. That is not how D9 is marketed. No need to give them a reason not to go to D9.
Comment #32
BerdirI think you misunderstand what per-table prefixes/shared tables are.
It's perfectly fine to have multiple database connections configured to different databases, nobody wants to take that way. That's how migrate works, among many other things.
Shared tables is about e.g. having different drupal sites share some of the tables, for example use the same user tables so users can log in on all "connected" sites. That concept is flawed and conflicts with a lot of things like caching and invalidation, dynamic table management and more. As others commented, it just doesn't work in D8, never did, so we shouldn't offer it. It will not be reverted.
Despite removing that, if you have a specific use case, you could still offer a specific API/service that would connect to the same database/table and share data through that, it's just no longer available transparently/magically for anything that uses the database API.
That said, I do agree on it not being related to multisite, it equally works/doesn't work wheter or not your multiple sites have the same code base or not.
Comment #33
mmjvb CreditAttribution: mmjvb as a volunteer commentedI think you misunderstand proper release management. It should be unacceptable to remove functionality without reason. Another reason it should be reverted. It is not about multiple connections to possible different datasets or even database servers. For which you need to write code. This about removing existing functionality just because you can. Leaving those that use it without alternative. That is not what deprecation is about. First you provide a better alternative and once most have adapted you can deprecate the old way.
Forcing current users into coding solutions maybe acceptable for you as developer. It is unacceptable for those who were promised an easy upgrade to D9.
In addition you seem to misunderstand what I said about per table prefix and shared tables. Just because a dog is an animal, it doesn't mean an animal is a dog. You needs to use per table prefix to to have shared tables. Shared tables is a working but risky solution. Agree on advising more stable solutions. As mentioned shared tables is not the only use of per table prefix. My current understanding is that combining data from different connections require coding. It is not transparent as it is with per table prefix.
Looks like this needs an issue re-scope. Suggest to remove the offending and condescending introduction and point to the available documentation. Its scope should be the identification of the shortcomings of managing your codebase with composer for building a site with Drupal. #16 by catch is a good start although I disagree on his classification of them. So, after identification they should be classified. The assumption should be that the question is what needs to be done to have the benefit of composer without loosing current capabilities.
Suggest to have an unrelated issue for improving Shared Tables and considering the poor understanding mention it is not related to managing the codebase.
Comment #34
Mile23The scope here is collecting use-cases to try and support with Composer.
Thanks @colan for #25... I'd point out that #22 is a rough sketch for something I hope we never have to do.
Added #3022403: Warn users about per-table prefix in multisite during requirements hook so that we can signal people that per-table prefixes are deprecated.
Comment #35
mmjvb CreditAttribution: mmjvb as a volunteer commentedRead again:
Which is why I requested a re-scope. The scope should be how to fix composer to support managing the codebase for Drupal sites.
The requirements are clear already:
- Needs a GUI in addition to cmdline
- composer.json needs to be maintainable via composer subcommands
- Needs configuration option for --no-dev
- Needs to support: composer require vendor/package --dry-run
- Needs command like composer outdated, but then respecting version constraints
- Need to be able to specify a destination for the dependency (both direct and indirect)
- Need to be able to specify the scope of dependency
- Needs to resolve dependencies per site
- Needs to autoload per site
Comment #36
joachim CreditAttribution: joachim at Skunk Works commented> Your lock file is meaningless.
> - Needs to autoload per site
Sudden thought: we use the sites/* folders to segregate our settings, file, and code between different multisites. So why not put a composer.lock and vendor/ folder in there as well?
Then, each lock file and vendor folder is segregated. Composer sees each one as a completely separate thing.
This wouldn't be simple -- we'd need various Composer plugins to do things such as:
1. add command-line options to Composer to tell it which multisite you're currently doing things to, or figure it out from your current location
2. put composer.lock somewhere other than it usually does
3. put packages somewhere else if they're not core
This would be all rather complex, but it's reasonably sane and logical at least.
Comment #37
mmjvb CreditAttribution: mmjvb as a volunteer commentedThat is indeed what comes closest to the way composer works currently. It fails to deliver on the concept DRY which is implemented with multisite. You don't want to repeat yourself if you don't have to. As mentioned the most common use case is the same code for multiple sites. When more than 80% of the code is the same you don't want that duplicated. That might be possible to implement with the current merge plugin.
On the other hand composer is already familiar with multiple requirements (require, require-dev). Unfortunately, that is of little use for Drupal, only developers need the require-dev. Which is why there needs to be a configuration option to negate the default --dev for all those sites that don't want that crap on their live servers. If require-dev complements require already, it can't be that difficult to have domain requires to specify the exceptions for particular sites.
So, the question is: do we want to make composer work for drupal or do the site builders need to work for composer. In my opinion it should be making composer workable for drupal. It is drupal that provides more than 95% of desired functionality. Otherwise they wouldn't have chosen drupal to build their sites. Currently composer creates more problems that it solves for site builders.
The most inferior solution would probably be to extend Ludwig with the capacity to produce a ludwig.json for those not providing that service. That would allow site builders not having the problems composer claims to solve to stay away from it. They can keep the workflow they are familiar with.
Comment #38
Mile23Comment made in error.
Comment #39
webchickWe're now about 40 comments in, so attempting an issue summary update (please feel free to tweak; not sure I captured all the nuances here). Looks like we're quite covered in terms of goal #1 and outlining use cases for multisite that Composer builds need to support. Ideally, these would be captured somewhere less ephemeral than a random issue, however, so documented at https://www.drupal.org/docs/8/multisite/use-cases-for-drupal-multisite for posterity. (Feel free to edit/add to this.) As this is a pretty critical feature for many sites/use cases, I've escalated the issue priority to major.
As far as shared tables use cases go, I agree there are better workarounds, but here are some common reasons I've used this in the past (D6 and earlier):
1. Shared users + sessions tables: allows for a really cheap single-sign on (as others have mentioned, there are more robust options available in contrib)
2. Shared roles + permissions tables: ensures access control is consistent across sub-sites, at least where they're all using the same modules (nowadays roles/perms are in config, so you'd sync that vs. sharing the tables)
3. Shared taxonomy / menu / etc. tables; ensures consistency in navigation, tagging, etc. (could be accomplished with something like Migrate or Feeds module these days)
Basically, anything where there's a crap-ton of initial set up / ongoing tweaking involved, and you want to enforce consistency across all of your sites. Works best in a model where the sub-sites only vary by something very small, like theme or site name.
But anyway, it seems this is rather moot since we're not planning on supporting that capability into the future. (Leaving the multisite feature in tact, though.)
Do we want to close this issue and move onto a new one for solution-eering? Or keep the discussion going here?
Comment #40
colanThe reason I think we don't need to prioritize this stuff right away and continue with #17 (without worrying about it too much) is that you could simply take all modules and themes that all of the sites need, and place them in the shared codebase at the root that's currently supported by Composer. Sites that don't need other sites' extensions simply won't enable them. While it's true that you won't be able to put these things in site-specific directories, you generally shouldn't have to. This should suffice for now, as an initial phase.
In any case, I'd like to see us move forward with solutioneering, yes. (And thanks for the IS update!)
Comment #41
webchickThe one use case I can think of that that approach breaks, which has come up only once in my own experience with multisite, is where someotherband.com is using that crazy one-off analytics package, and it requires a different version of, say, the jQuery Update module, compared to all the other sites. The sites/foo location will override sites/all and allows for this use case, which of course everything being in sites/all would not. It's not a super recommended use case, since it can bring all kinds of hard-to-debug problems, and leave you potentially open to security vulnerabilities if you're stuck on an older version of a library, but it does come up. It is possible to document this limitation, however.
Comment #42
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedIf the module in sites/foo with a different version does not have differing dependencies to the one in sites/all, I think that would work. You just can't install it to sites/foo with Composer, but it could be placed there by other means.
Comment #43
AaronMcHaleThanks for taking the time to summaries the use cases @webchick
When thinking about shared tables and their use cases a thought came to mind that I wanted to share to at the very least plant the seed of a possible idea to explore.
With the initiatives to improve the configuration management and synchronisation features as well as the new Workspaces module, maybe there's some kind of scope there to use that functionality to provide some or all of the benefits of shared tables. Not so much around session management, I think you'd still want some kind of more advanced single-sign-on functionality, but for entities (such as Users, Taxonomy Terms and Vocabularies, even Nodes) and other configuration looking at those existing tools and concepts as possible solutions could be an interesting path to explore.
Just a thought.
Comment #44
hansfn CreditAttribution: hansfn commentedRemoving the ending period so it looks better when using automatic linking - [#nid]. (Sorry about the "useless" title change.)
Comment #46
ndobromirov CreditAttribution: ndobromirov at FFW Agency commentedSome of the main reasons in using a multi-site are:
1. Scalability - PHP opcache is reused on all multisite instances, and it will multiply if we go with per-site-sintallations. I've had cases of sites with 300+ sites running in production on a multi-site platform. This monstrosity needed somthing in the range of 128-256 MB of opcache. If this was site per installation it would have needed 5-10 GB RAM per webserver just for the the PHP's opcache. This is translating directly to monthly costs for operations and running the platform.
2. Consistency - you know the limitations before making it - all code is the same. You might change configs between multi-site instances and that is it. You could have a module enabled or not, but never 2 different versions of the same module.
3. Ease of new site provisioning - new database, new site declaration (sites.php) + v-host and you are ready.
Comment #47
jukka792 CreditAttribution: jukka792 as a volunteer commentedI have a virtual machine which has 2GB of memory.
It contains 35 Drupal 7 sites sharing same codebase in a multisite setup.
The sites are not related to each other, some are light with few modules and some are huge eCommerce sites.
Some sites have their own modules in the /sites/all/sitename/modules folder, but some sites does not have any "own" modules. Maintaining many years these kind of setups have been really easy.
I don't want to even guess how much memory I would need more to run these same 35 sites in a separate Drupal installations (non multisite) on a same server. Would even 32GB be enough?
Also that would be a catastrophe to me to update all these sites cores separately.
So for me, and for many others, the multisite feature is a must.
If I understood correctly, D8 and composer can work currently with D8 multi-site only so that all sites share all modules? For me, this is not a problem, I think I could live with a D8 multi-site where all the sites shares exactly same modules. But this is mainly because I am alone hosting these and don't care if all the modules are visible to each sites. I understand that usually
separate sites needs their own versions.
I have just started to install a D8 multisite setup, and got a little scared about this problem with composer and multisite, but I will try to find out how it works.
Instead of thinking how to get rid of multisite in the next Drupal versions, why not to think how to get rid of this awful composer? When composer is a must, it removes the possibility to host Drupal sites on a hosting companies which does not provide shell access. It's a small con compared to other CMS. But I understand Drupal is for pros.
(Those Aegir advertises do not belong here?)
Comment #48
mmjvb CreditAttribution: mmjvb as a volunteer commentedConsider that incorrect. It is composer that limits the management of packages to one destination. It also resolves to only one version of a package. It is these limitations that makes you choose all/modules as the destination for those having external requirements and optional for others that fit there naturally. You can still manage individual site/modules in the traditional Drupal way. That includes different versions or exceptional modules for particular sites. As long as they don't require composer due to their dependencies.
For downloading you need to move away from Drush or create the missing commands. You can use Composer or Drupal Console for downloading.
Comment #49
jukka792 CreditAttribution: jukka792 as a volunteer commentedSo with D8 multisite and composer, if I want to download a site specific module to /sites/site1/modules/ -folder, I can't use Drush anymore but just copy it manually there?
With D7 I just go to that specific site folder like /sites/site1/ and type "Drush dl modulename" and it downloads the module to /sites/site1/modules folder. So you mean this is not possible with D8 and composer combination anymore?
Comment #50
joachim CreditAttribution: joachim as a volunteer commented> So you mean this is not possible with D8 and composer combination anymore?
That's correct, it's no longer possible:
- Drush no longer does any downloading of modules.
- Composer wants to put all modules in modules/contrib.
There is a way of telling Composer to put specific modules in other places, but it's fiddly -- see one of my earlier comments.
Comment #51
Morbus IffJust throwing my use case into the mix:
Over the past six months (and for many months in the coming future), we've been working on the move to Drupal 8/9. Using composer (and drupal-composer/drupal-project) has been working just fine for us because of how we've structured things above already (i.e., all contrib and custom modules available for all sites, and distribution administrators turn on the ones we need as needed). We don't "need" the concept of sites/SITE/modules in our distribution and, if we did, we'd use it only for custom code that wouldn't be handled by composer anyways.
Comment #52
cilefen CreditAttribution: cilefen at Institute for Advanced Study commentedIt's not only that Composer cannot install site-specific extensions, there is also #2985199: Extensions in Multisite Directories Not Registered When Rebuilding Cache.
Comment #53
mmjvb CreditAttribution: mmjvb as a volunteer commented@jukka792 Actually, you can still use an old version of Drush 8 to do your download. You do need Drush 9 for other commands on your D8 site.
Indeed, it is possible to configure composer to put things where you want. It still doesn't provide the flexibility of Drupal itself and the configuration is very clumsy. It requires editing json before you require the module. Also, there is only one destination for a module.
Comment #54
MixologicCombining composer with drush to manage downloading will eventually lead to a path of ruin. You should not mingle strategies, because in order for composer to be able to perform its dependency resolution, it needs to know what you have on your site. If you add modules using an old version of drush, you may eventually end up in a scenario where composer doesn't recognize that the module is installed and may try reinstalling it, in its particular place.
Comment #55
Charlie ChX NegyesiI have an idea which covers the problems here and more -- needs minimal composer support although it is possible it's totally scriptable.
First of all, I believe Drupal now recovers fully on cache rebuild if you move your module to a different directory (check this).
Let's presume composer is somehow magically capable of installing to
modules/contrib/foo-1.10instead ofmodules/contrib/foo(orfoo-8.x-dev-defa123you get what I mean). Now add a mechanism viaSettingsand a conflict resolution model during project scanning instead of the current blind override -- ie iffoo.info.ymlis found atfoo-1.10andfoo-1.9as well and said settings containfoo-1.9then that one wins. Additionally we could have a list of potential projects also via Settings where the UI doesn't show other projects and module installer throws an exception if said Settings exist and project is not listed.This would allow keeping multiple versions across projects with fairly minimal work in codebase and in maintenance both. For a project with multiple versions, change the package version in central settings.php after an update and keep the local version in the local settings.php.
I hope the "magical composer capability" can be achieved by a script listening on
pre-package-install/update. https://stackoverflow.com/a/27293479/308851Comment #56
joachim CreditAttribution: joachim as a volunteer commented> Let's presume composer is somehow magically capable of installing to modules/contrib/foo-1.10 instead of modules/contrib/foo (or foo-8.x-dev-defa123 you get what I mean).
That sounds pretty simple and probably doable.
One potential problem is if we have:
- module foo-1.6 requires composer package (ie not a module) bar 1.0
- module foo-2.0 requires composer package bar 2.0
I have a rather wackier idea than @Charlie ChX Negyesi's. Composer currently has a notion of two different requirement trees: require normal and require --dev. Could we hack into that concept and create further trees, one for each site?
Comment #57
webchickThere are apparently rampant rumours circling around that we're getting rid of multisite in Drupal 8/9 despite #2306013: Multisite is a valued feature that will not be deprecated. was closed 2 years ago as "works as designed" (meaning we're NOT doing that), and despite the issue summary here further enforces that it's a critical feature of Drupal.
Trying a title change here in case that is possibly contributing to the misunderstanding.
Comment #58
MixologicSo, the only issue I have with the title change is that we're getting off the rails entirely with "composer support", or exploring solutions.
The *primary* scope of this issue is to Identify all the ways the multisite feature is used, and among those features determine which ones we must continue support for, and which ones we can confidently say "thats too rare of an edge case to be worth supporting"
An example is the solutioning in #55/#56. There is always some possibility to make multisite and composer work with multiple versions of the same code. The question I want to ask before we even look at the solutions is *should we*.
I.e. I really want to define what it is that multisite means in d9 and beyond, and more specifically what it doesnt.
Then we can open issues to solve whatever is outstanding.
Comment #59
webchickThere were some use cases already written up in https://www.drupal.org/docs/8/multisite/use-cases-for-drupal-multisite based on this and the previous thread. Is this sufficient for what you need, or does it need additional detail?
Given how late in the game we are with Drupal 8, the only sane answer is we need to support all of these, at least until Drupal 10; like all other critical features in core, we need to provide feature parity/BC.
If one or more of these individual use cases can't be supported for various challenging technical reasons, then we should drill in on that, which AFAICS is what #55/#56 are attempting to do.
Comment #60
webchickIn case further anecdotal data / user interviews is needed, some of the replies in https://twitter.com/webchick/status/1161379581208612864 are detailing what specifically they benefit from / use out of multisite. (And also from others what they don't like about it. ;))
Comment #61
jerdavisHistorically, we've used Multisite in our hosting platform in what you might call a "reverse" multisite configuration, in order to provide control over when each individual site in the multi-site was updated.
The web hosts would have multiple versions of Drupal and a set of contributed modules configured in a directory like this:
/www/drupal-7/drupal-7.65/drupal/
This would be a docroot for sites using that release. Inside of the sites directory, we'd have simlinks to each site on that release, IE:
/www/drupal-7/drupal-7.65/drupal/sites/example.com (symlink) -> /www/example.com/drupal/example.com/
We'd control the management of what release a site was on and the creation of the sym-links automatically through our provisioning system. That'd allow us to push out a new release of Drupal to our web hosts and then update the release for each site in the infrastructure individually, either manually or scripted.
Comment #62
jerdavisTo the comments in #55 / #56 - The old inheritance model of putting per-site modules in that site's module directory makes a lot more sense from a ease of understanding perspective. Having multiple versions of a module piled up in /modules/contrib/ with some reference somewhere else to control which version is used for each site seems far more difficult to manage and understand at-a-glance than figuring out how to put modules in sites/example.com/modules/contrib, sites/example2.com/modules/contrib. If we could use something like require-example.com in composer to control locations of specific modules that would seem preferable. I've used the installer-paths option on one multisite to install a module for a specific sub-site, IE:
Comment #63
MixologicThe fundamental problem is that, except for the most basic/simple use case, we currently do not support *any* of those in drupal 8 if you require any module that has a 3rd party composer dependency. We're essentially attempting to reintroduce multisite functionality for users that require composer to build their site, which is a significant portion of the userbase and only continuing to grow.
The use cases documented in https://www.drupal.org/docs/8/multisite/use-cases-for-drupal-multisite are a mixture of technical requirements and values that people get out of utilizing multisite, and is a helpful start, but isn't quite a clear 'spec' for what multisite really is, and also contains things that are already deprecated/don't work in d8 like shared database tables.
If the requirements are "It needs to do everything that current multisite does, no matter how rarely used", then my concern is that it's either not going to happen, or we'll spend an inordinate amount of time adding support and continuing to maintain mechanisms that very few end users gain value out of.
Given that multisite support barely exists in a composer context, are we able to rule out rarely needed features so that we can avoid the need for anything "magical, wacky, hacky' ?
Comment #64
webchickFair point. Do you have an example of an existing document that's more "speccy" that you'd like those use cases reformulated as?
And can we turn your question around? What of the documented use cases do you feel are "rarely" used and you propose we should be able to drop? We can then try and validate those assumptions with actual multisite users, vs. arguing amongst ourselves. :)
One way to help validate assumptions might be to put out a survey via DA channels about multisite usage, if that's where the stalemate is.
Comment #65
jerdavisIs there some way of adjusting usage statistics gathering to identify if there's more than one site present in /sites/*?
Comment #66
webchickOooooOoh. That's a GREAT question. Though it sounds like we'd ideally need a bit more detail than that as well, if possible, to dig in on specific sub-features. (per-site modules/themes; shared tables; etc.)
Comment #67
BerdirShared tables has been deprecated and it's impossible to use for anything meaningful in D8 (like user tables), the interactions between entity, cache and other systems are way too complex for that to work: https://www.drupal.org/node/2768219. You can't just update the user table and expect another site to pick up that change, it's going to be a mess, with queries against it reflecting the change but then actually loading entities would load them from cache, saving wouldn't invalidate cache tags for rendered elements and so on and so on.
Some people aren't happy about it as discussed here, but there really is no point in keeping it, it just doesn't work.
It has technically also nothing to do with multisite, in that doesn't matter if multiple sites sharing tables are actually multisite or separate installations. I think I've mentioned there before as well ;)
Comment #68
MixologicI think the main issue, with regards to composer is how we handle extensions.
1. All extensions shared between all sites on the multisite. (sites/all/modules)
2. Some sites have different extensions specific to the that site only (sites/example.com/modules)
3. Some sites have *different versions* of the *same extension*
Supporting #1 is essentially already supported.
Supporting #2 is difficult, and really isn't very different from. #1 other than the extensions shown in the admin Interface
Supporting #3 is extremely difficult, and would potentially subvert some of the nicer features that multisite like having a shared opcaches.
It seems that every use case for #3 is attempting to use multisite as a form of deployment mechanism, which isn't really what it was meant to do, but how it was utilized.
So it's that #3 and somewhat #2 that I hope we can not support going forward.
The usage stats we have don't give us an easy way to know if a site is a multisite or not. We can see multiple site keys with the same IP address, but that could just be a shared host with many individual sites.
I can poke around and see if fingerprinting a site might reveal instances of #1, but mostly it's unlikely that we have the proper telemetry data to inform this decision.
Comment #69
webchick@Berdir: Oh, right, I forgot that we already deprecated shared tables in D8. (I knew they were unpopular with various core devs for various valid reasons, but couldn't remember formally making that decision.) But yes, there are documented workarounds, and while it's a feature that some multisite installs use, it isn't part of the multisite architecture itself, nor what I believe most site owners mean when they say "I rely on multisite."
@Mixologic: Versus unfortunately my "spidey sense" is that #68.2 is much more commonly something people rely on, though #68.3 does indeed "feel" more "edge casey," and even when you did it successfully in D7 and below, you often opened yourself up to weird side-effects. So my utterly non-scientifically backed opinion is that we need per-multisite modules/themes but we do not natively need to support multiple versions of the same extension in the same site, at least as long as there's some other workaround people can do (symlinks or whatever).
Do you want to work together to put some kind of quantifiable data together on this? (I'm guessing survey is our only option, since it sounds like hacking at the usage stats telemetry for it is out.)
Comment #70
webchickPinged the other thread with this question, too, to help point multisite users over here. #2306013-95: Multisite is a valued feature that will not be deprecated.
Comment #71
webchickAnd re-pinged the Twitter thread of DooOOOOOom. :) https://twitter.com/webchick/status/1161714301549174785
That's about all I have at my disposal for data gathering, unfortunately. :(
Comment #72
Mile23The issue is: #68.2 and #68.3 are vanishingly similar, from a complexity standpoint.
The #2 scenario: If we have two subsites and they want two different modules, one per subsite. And each of these Drupal modules has a Composer dependency that would ordinarily conflict with the other. We would expect that they wouldn't conflict, because they're never used at the same time per request. But Composer doesn't know how to set that up, and core doesn't know how to autoload differently per site.
This is just about the same as the #3 scenario in terms of making it work.
That's why I'm generally +1 on #68 (ie, please for the love of all that is good, can we not need to support that), but thumbs way down on this description: "Supporting #2 is difficult, and really isn't very different from. #1 other than the extensions shown in the admin Interface"
It's very, very different.
Comment #73
webchickI think he means the similarity from an end-user perspective.
Like, one of the largest multisites I ever worked on was something like 2,000+ artist websites all run off the same code base. Each one had its own theme in its own sites directory. When you went to configure the theme at admin/themes, you just saw the default themes Drupal ships with + the base theme we were using + "Artist Name Theme." So, like 6 options.
Versus if all of these were in sites/all/themes, I'd have 2,000+ options on the themes page and would need to scroll past all of them to find "Artist Name Theme." Which is super not helpful. :\ (And woe be to you if you accidentally set Death Metal Band's theme on Super Happy Pop Artist Band's site, lol.)
That said, these themes were all obviously custom themes, and in that case I don't think there's a problem with putting them in sites/XXX/themes, because there's no composer.json to trip them up? (Unless they were using composer.json to track dependencies for the theme, maybe, hmmm.)
Anyway. That's an example use case currently solved by per-site modules/themes directories. And there might be other ways to tackle that, e.g. via Drupal UI configuration (some means of setting hidden = true on everything but this one, for example).
Comment #74
seanBEven though #68.2 is something I have used and seen often, I guess sharing all modules and simply not enabling them on certain sites could be good enough. Although adding a module specifically for one site reduces risks of sites enabling the modules when they shouldn't. Most of the times it would be custom modules that were not managed by composer though.
I have not seen different versions of the same module in subsites yet as #68.3 mentions. This seems very dangerous imho, I would hate to debug issues coming from this in complex multisites.
I could live with only supporting #68.1.
Comment #75
Mile23Re: #73
Right, but what I'm saying is that for the purposes of using Composer to manage that, we have to assume that:
...is true, and that all the dependencies conflict with each other x 2000. :-)
That's a great use case, BTW.
Comment #76
m.stentaUse-case to throw into the mix: farmOS is a Drupal distribution for farm record keeping. I host it for farmers, and use multisite to share the common distro code, but occasionally put custom modules for individual farms into
sites/[farm-url]/modules.So for me, the requirements described by #68.2 above apply.
Personally, a solution along the lines of #36 seems to make some sense, simply because I consider everything in
sites/*/modulesto be "downstream" from the distro/core considerations.Eg: I might move a site to a different server, so it's handy to be able to just move the
sites/*/modulesdirectory, and not have to touch anything in parent directories (like an "upstream"composer.json).I haven't given any thought to how that would work in practice, though - so I'm not sure of the feasibility. Just my 2 cents as a distro maintainer. :-)
Comment #77
geerlingguy CreditAttribution: geerlingguy at Midwestern Mac, LLC commentedI think the greatest chance where you'd run into some of the edge cases is a situation where you're not running a 'distribution' per-se (whether custom or contrib, like farmOS, Lightning, etc.), but you're running one codebase + module set on a variety of wildly different sites.
This is what I currently do for a set of Drupal 7 sites—each with a custom theme, and a few with custom modules—on a shared Drupal codebase.
Over time I've found that it's more painful this way than having separate codebases, especially with Drupal 8 and the composer issues with theme dependencies (so helpfully highlighted by @webchick above), but it _is_ nice to be able to run 5 moderate traffic D7 sites on one $5/month 1 GB VPS without worrying about PHP memory issues (I could not run 5 separate codebases on the same server).
So the 133% price reduction ($5/month instead of $25/month for these 5 sites) is worth the pain for me, since it's an upfront/one-time cost of getting all the custom stuff to play nice in the shared codebase.
Comment #78
Pasquallehmm, really? This does not work in D8?
I am using multisite with D8 and composer, and also with D7 and composer, and actually I do not have any issues.
In D8 we have a simple setup, using the exact same modules on every website, maybe that is why we do not have issues.
In D7 we went even over the edge with multisite setup. We are using a set of custom modules on a set of websites, like
set1 (module A + module B) is visible only to site1 and site2
set2 (module C + module D) is visible only to site3 and site4
and there is only 1 instance of every module.
The usecase is: multiple countries with multiple websites per country. The websites should not see modules from other countries.
The trick is we install the custom modules outside the web folder and use symlinks from sites/x. The drupal-custom-module composer package is not 1 module but a set of modules, therefore we only need 2 symlinks per site (1 link to country specific modules, 1 link to site specific modules and theme).
And on top we use openshift (similar software as kubernetes), we can scale up as needed. It is not true that multisite does not scale.
Not sure if you needed more convincing or more use cases for multisite, just wanted to say, for me the multisite is good as it is..
Comment #79
Mile23Core can autoload different *modules* per subsite, just like always.
Core can't autoload different *Composer-only dependencies* per subsite, which is a big technical problem that we'd have to solve for some of the use cases.
This is mainly for D8, but your D7 situation looks like one that would be reasonably common in D8, too.
Comment #80
PasqualleIt seems like I will need an example to understand the problem.
As I understand there is only 1 composer.json file even in multisite setup, and almost every package is installed in the /vendor folder. If site1 needs for example the "sebastian/diff" package, then the autoloader can find it in the vendor folder, if site2 needs a "symfony/dotenv" package, then the autoloader can find it also in the vendor folder.
Comment #81
Mile23Well, without getting too technical in this use-case issue....
Let's say siteA needs moduleA which needs the external Composer-based package
mile23/composer-package, but only version 1.x and not 2.x.siteB needs moduleB which needs
mile23/composer-package2.x but not 1.x.Now we have a conflict. We can't reconcile both of these at the same time because they have mutually-exclusive Composer requirements. So they can't both live in the same vendor directory. Composer won't let us even start.
However, as Drupal people, we'd expect this to not be a conflict, because in Drupal-land these two sets of dependencies are independent of each other at runtime. We expect that we'd be able to fix it so that sometimes we'd use
mile23/composer-package1.0 and sometimes 2.0, depending on which subsite should handle the request.Any solution to fix that issue would be a big ol' pain, and probably require things like refactoring the kernel. So the question is: What use cases can we support without, for instance, refactoring the kernel, vs otherwise.
Comment #82
PasqualleThanks for the explanation, this is quite clear this option does not work with composer.
But if you try the example without saying siteA and siteB, single site setup, then the example still does not work.
Multisite Drupal installation is a 1 composer project, and must be without version conflicts, otherwise composer will not able to install. There could be only 1 instance of a package.
I understand why Drupal developers might expect it to work. But as I see no package manager can support such setup, and we should not even try to support it.
Comment #83
Pasqualle(edit) double comment removed..
Comment #84
mmjvb CreditAttribution: mmjvb as a volunteer commentedThat is correct, it is no different from a single site. Composer imposes that limitation. Same thing for multiple composer.json in drupal multisite or multiple single sites. Assuming you use a virtual package based on the shared composer.lock to prevent having different versions of a dependency. That is the same logic used by webflo/drupal-core-strict, only the scope is different (sites/all instead of core).
Comment #85
AaronMcHaleSo I've been following this discussion for a while, and I'd like to reference back to what @Mixologic said in #68
A lot of the discussion in recent comments seems to be around scenario #3 above, or more specifically what happens when Drupal extensions installed across a multisite require different versions of the same Composer package.
When it comes down to it the problem that is being discussed is simply this: how do we handle Drupal extensions which have dependencies on the same Composer package but requiring that package at different versions.
Now, correct me if I'm wrong, but that problem is not technically restricted to just multisite, you might come across that same issue in a single site setup, it's just that chances are if you were going to experience that issue it would be with a multisite setup.
That being said if we can agree that the problem is not necessarily specific to multisite, but more of a general Composer support problem, maybe that reduces some blockers here. Maybe we can simple note that as an unlikely edge case which isn't currently supported in a multisite Composer setup, and discuss that specific problem in a different issue.
A final thought, it's possible that to achieve full Composer support for multisite, we might have to open issues on the Composer side and start contributing code changes there. I'm not sure if we will actually need to do that or not, but it's worth remembering that we don't have to solve this problem entirely within Drupal itself, and for some of the harder blockers, contributing changes to Composer itself might be the easiest approach.
Comment #86
MixologicThe difference is subtle, but on a single site setup, composer has access to the versions of all dependencies, and if a conflict arises, it is able to report to the user that there is a conflict, and it will not continue. In this situation the end user would have to decide how to proceed, but a conflict is detectd.
In a hypothetical multisite situation where composer is only concerning itself with the dependency map of a particular site, but sharing its /vendor directory between all sites, there is a possibility for an *undetected* conflict between the different sites because it cant account for all the needs of all the sites dependencies. This could cause composer to say there is no conflict, and keep flip flopping between two different versions of a dependency, breaking one site in order to make another site work.
If we attempt to solve that in a way that *doesnt* share vendor directories, then the issue becomes that a huge portion of our code (/vendor) ends up being duplicated amongst every site, dramatically increasing memory usage and disk space, reducing one of the main benefits of having a multisite in the first place.
Re #73 That's exactly the kind of 'edge case' I was imagining might exist, but didn't know for sure. But yeah, thats an awful experience. I believe that there is a way that we could still support #68.2, but not do it by "where a module is stored on the filesystem" and instead use some other mechanism to filter modules/themes by site. This could potentially be accomplished with a composer plugin that allows us to add a --sitename flag when a file is required, and stores that metadata somewhere that drupal then leverages to be able to display only the relevant modules. Situation #68.2 really only has a conflict with composer in the fact that we're using filesystem locations as a kind of database to inform the product of our intentions.
Re #76 I think that the *existing* multisite functionality would still continue to work, and that this problem only occurs once you are trying to use composer to install contrib modules from drupal.org. Unless you have custom modules that you want to reuse on multiple sites, that are not published, that have third party dependencies on packagist libraries, you should still be able to write a custom module, put it in sites/mysite.com/modules and it should continue to work the way it always has. Custom modules are only an issue once they too, have 3rd party composer libs. (which is definitely something possible).
As far as upstreaming some things to composer, in general if something is useful for the greater php ecosystem, they would be amenable to that, but we would probably have to work with several other web projects to come up with an ecosystem wide strategy for how to handle "running multiple sites off of one codebase that offers variants of that codebase per site" and It's very likely that if we collaborated on something like that, that it would end up being dramatically different from our current multisite implementation, and would take a great while to get something like that agreed upon.
TL;DR: I think we can come up with a technical solution to #68.2 that is compatible with composer. I think that even if we *can* solve #68.3, we should not, as it would come at a cost that makes multisite valueable in the first place.
Comment #87
AaronMcHaleRe #86
In a multisite setup, is there a reason Composer then couldn't be aware of every site.
What I mean by this is say for example we implement something like the approach described in #62 of:
The root composer.json is aware of every extension installed in every site, so that would avoid that subtle issue @Mixologic described above. We could then add support for the
--sitenameflag which could be used when installing a extension to place it in the correct location in the file system.I can though see a couple of limitations here, one which I think we might be able to solve:
I think this might be a better solution than the previous one involving the
--sitenameflag, because it preserves the benefits of having extensions physically located under the site they are being used on.Comment #88
hart0554 CreditAttribution: hart0554 at University of Minnesota commentedTo add a bit from my experience of supporting multiple codebases that did have multiple versions of modules in different site folders, I've found that to be *extremely* problematic with apcu. We've ultimately ended up disallowing that approach as a part of our build process (at least not allowing a site to keep an alternate version of a module that is in /modules - we don't have a good way to restrict sites that have competing versions of something in /site-a/modules and /site-b/modules that is *not* in /modules). So for the scenarios presented in #68 I have already been working toward a situation where 1 & 2 are fine but 3 is deprecated for my users, and I think that's somewhat optimal.
Comment #89
Mile23Please pardon me for getting a little technical here.
Here is a sort of back-of-napkin diagram for some of these use-cases.
This is not a solution, but an estimation of how much work would have to happen at minimum to support #68.2/#68.3.
Let's tackle #68.3 first (and I'd argue, also #68.2, but maybe that's just me). I call it:
The Isolated Multisite Front Controller Model
(AKA: The Lovecraftian Horror Of Process-Isolated Subsites)
From the perspective of how a request is handled:
MultisiteKernel. (This means refactoringDrupalKernelto separate concerns.)sites/default/.DrupalKernelmuch like we do now.sites/example.com/autoload.php, and usesDrupalKernelto handle the request. This is why it's in an isolated process.Based on this request handling process, we have to retool Composer to work like this:
composer install.Now we essentially have a series of almost completely independent Composer-based projects in subsite folders, that share the filesystem of the root Drupal. They can have mutually exclusive dependencies as needed. A thin front controller figures out which one to boot at request time.
Using this technique, we will have lost the benefits of opcaching, memory footprint, and disk space as mentioned in #86, for sites which have mutually-exclusive dependencies.
Scaling back, we could then also design #68.2, which I will call:
The Multisite Requires All Dependencies To Resolve Model
For this model, we have one vendor directory as we do now. From the perspective of a request to our HTTP server, it works the same as it does now.
However, we must tool Composer in this way:
In this version, we keep the opcache, memory, and disk space benefits, while allowing Composer dependencies to be declared per-subsite. This means you can have a custom extension in
sites/example.com/modules/bespoke_moduleand if it needs a Composer-based package you'd declare that insites/example.com/composer.json. However it also means that all subsites use the same classloader, so a subsite which doesn't require a Composer package could (and maybe in some cases, will) still use it anyway. (For instance, one subsite wants PHP's yaml extension, and another wants symfony/yaml. Symfony probably wins that one.)Clever readers will notice that the work for the All Dependencies Must Resolve model is to some degree a subset of the work for the Isolated Front Controller model. However, if we allow users to declare their dependencies per-subsite, then switching to the Isolated Front Controller model later is tricky because we lose the memory and disk space benefits.
It’s also possible that there is a better solution than any of this. :-)
Comment #90
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedI wouldn't want to have to implement something like #68.3, but if I were to do so, I'd do something like this:
sites/*/composer.jsoncomposer updateruns on the composer.json file at the project root, then a Composer script or plugin also runscomposer updateon each of the multisite composer.json files. However, we will patch out the install operation, so the composer.lock file is generated, but nothing else.composer installon each multisite directory. The result is that we will have onevendor/autoload.phpfile at the project root, and one morevendor/autoload.phpfile in each multisite directory.While this would be a bit of a pain to implement, it has loads of advantages. It maintains the benefits of opcaching and disk footprint, and each multisite may have different versions of the same modules if they really want to. What's more, the two autoload files can be merged together freely (which is to say that any ONE multisite autoloader may be mixed in with the root autoloader), so there is no need to make a special reduced Kernel, and there is no need to alter the way multisite bootstrapping works. The only thing that needs to happen at request time is to include
sites/*/vendor/autoload.phpif it exists as soon as the specific multisite is identified during bootstrap.The main downsides of this plan is that it needs special knowledge about the composer.lock internal format. There probably are not Composer APIs to help out here, but I did not investigate.
This idea is unproven, but I'm reasonably confident that it would work.
Comment #91
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedAs an added reference, I will point out that the first steps described in #90 are very similar to what is already being done by the Composer Test Scenarios Composer plugin.
Comment #92
AaronMcHaleIf we do go with the approach in #90 and if the above is true then of course we also have the option of contributing those missing API endpoints directly to Composer, it would take more time but would probably be better in the long run.
Comment #93
greg.1.anderson CreditAttribution: greg.1.anderson at Pantheon commentedAnother reference: the code that generates the webflo/drupal-core-strict metapackage relies on special knowledge of the composer.lock format.
Comment #95
andypostIn related autoloader changing #3020296: Remove Symfony's classloader as it does not exist in Symfony 4
Comment #98
PCate CreditAttribution: PCate commentedI'm curious, does anyone know if Composer 2.0 opens up any new/improved ways to better support multisite installations?
Comment #99
joachim CreditAttribution: joachim as a volunteer commentedI've had a read through and I don't see anything new that would help.
Comment #101
KartagisI skimmed through all the comments and what I would like to ask is how multisite feature affects exporting of config files. Suppose we have a /config/sync folder outside of docroot and also a sites/default/files in .gitignore. Naturally files/ therefore config_/sync will not be committed. So, Drupal should change the location of the default /config/sync folder I think.
Comment #102
BerdirThis was discussed before, the default location was chosen to be in files to avoid having yet another installation step. The composer template could possibly provide a default config setting that changes that, but it's really not related to this issue, that problem is not related to composer and is exactly the same issue for a single site installation.