On March 26, 2019 we launched new MODX Forums. Please join us at the new MODX Community Forums.
Subscribe: RSS
  • I'm posting this here in the hopes that it might save someone else some time, and also in the hopes that someone might point out any potential problems--or even a better way to do it--in our setup before we get too far down the road.

    Perhaps MODX can evolve over time to better support something like this out of the box--although I've got say, it's amazing how well this is all working as is.

    Our goal was to set up a multiple sites with a single MODX core and manager to control them all. After research and whole lot of trial and error, here's how we set things up on our Unix server using MODX 2.3.1 (this would probably look different under IIS):


    STEP 1: INSTALLING THE FILES

    /path/to/www/
    We put the majority of MODX's assets outside any folder accessible on the web. The core, connectors, and manager folders are just the folders from the MODX install.

    • core/
    • connectors/
    • assets/
    • elements/
    • manager/
    • sites/

    /path/to/www/assets/
    Delving into the assets folder, we pre-created the components folder that MODX will use when installing extras, and also created a common folder for assets shared between different sites.

    • components/
    • common/

    /path/to/www/elements/
    We decided that we would do all of our custom snippets, chunks, plugins, and templates as static resources, and this collection of folders serves as a repository for the files.

    • snippets/
    • chunks/
    • plugins/
    • templates/

    /path/to/www/sites/
    Each site gets it's own folder in the sites folder. Nothing outside of each site folder is web-accessible, i.e., the sites folder itself is not web-accessible.

    • site1/
    • site2/
    • site3/
    • etcetera/

    /path/to/www/sites/<website>/
    We created a site template folder which we are able to duplicate for each new site that gets implemented. From there, one only needs to edit the MODX context setting to establish the new site (see step 2).

    • .htaccess <-- from MODX root install folder, support for Friendly URLS
    • config.core.php <-- from MODX root install folder
    • index.php <-- from MODX root install folder
    • assets/ <-- new folder
    • assets/components/ <-- symlink to /path/to/www/assets/components/
    • assets/common/ <-- symlink to /path/to/www/assets/common/
    • connectors/ <-- symlink to /path/to/www/connectors/
    • manager/ <-- symlink to /path/to/www/manager/


    STEP 2: EDIT SOME KEY FILES

    In order to make all of this work properly, you do have to edit some of the files--fewer than you might think, though...

    /path/to/www/sites/<website>/config.core.php
    Since we moved the core, the path relative to a site's root is different (note: the config.core.php files in manager and connecters do not need editing). This will be the same for each site, so you only have to edit it once. The corrected line should read:
    define('MODX_CORE_PATH', dirname(dirname(dirname(__FILE__))) . '/core/');


    /path/to/www/sites/<website>/index.php
    The main index.php file for each site will have to be modified to initialize MODX into the correct context. Look for the line that reads:
    $modx->initialize('web');

    and change "web" to a unique code for each site. You will be entering these codes into the manager later, so take note of what you use. For example:
    $modx->initialize('site2');


    /path/to/www/core/config/config.inc.php
    This one was a little trickier. We have to find a way to tell the config file the path of the site that it's being called from every time it runs. We solved this by creating a variable based on PHP's $_SERVER["SCRIPT_FILENAME"]. Note: we couldn't use __FILE__ as that automatically resolves symlinks and breaks our URLs.

    First: get an array of folder names leading to the path that the script is being called from (which is always going to be somewhere within a website's folder). Add this line near the top of the config file:
    $FOLDERS = explode('/',$_SERVER["SCRIPT_FILENAME"]);


    Second: since we know the path to the <website> folder, we can just explicitly reference it in our path array by grabbing the Nth item of the array, i.e., the name of any particular website will always be the Nth item of the array. In the case of our examples here it's the 5th (1.path, 2.to, 3.www, 4.sites, 5.<website>), so for example: $FOLDERS[5]. Note: There might be a better way to programmatically get the right folder name, but for us it would have been overkill.

    Third: we have to inject that folder name variable into a few lines in the config file to fix our paths. Note: URLs do not need to be fixed; just treat them as if it were a standard, default MODX install.
    $modx_manager_path= '/var/www/sites/'.$FOLDERS[5].'/manager/';
    $modx_base_path= '/var/www/sites/'.$FOLDERS[5].'/';
    $modx_assets_path= '/var/www/sites/'.$FOLDERS[5].'/assets/';


    /path/to/www/manager/min/index.php
    The built-in minify script (using Google Minify) will break on anything in a symlinked folder unless we specify the symlinks.
    // change this line:
    $min_symlinks = array();
    
    // to this:
    $min_symlinks = array(
        '//connectors'=>'/path/to/www/connectors',
        '//manager'=>'/path/to/www/manager',
        '//assets/components'=>'/path/to/www/assets/components',
        '//assets/common'=>'/path/to/www/assets/common'
    );



    STEP 3: SET UP MODX CONTEXTS

    In MODX, create a new context for each site. The context key should be the same ones you used in the index files. For each site you will need to have at least the following 4 settings:

    • base_url <-- the base relative URL for the site, usually just /
    • http_host <-- www.yoursite.com
    • site_url <-- http://www.yoursite.com/ (method + http_host + base_url)
    • site_start <-- the index of the start page/resource for this site in MODX


    STEP 4: (OPTIONAL) COMMON ELEMENTS PATH

    To use the common elements path that we set up at the beginning, we'll need to create a new media source.

    1. On the Media Sources screen, create a new file system media source.
    2. Right click on the new media source, and select "Update Media Source"
    3. Change the basePath field to '/path/to/www/elements/' (trailing slash is important!)
    4. Change basePathRelative to 'No' and save

    Now when you create a snippet/chunk/template/plugin and mark it as static, you can select the "Elements" media source, and browse the files in the elements folder. Just don't try to put any user-facing files there as it will break (that's what assets/common/ is for).

    CLOSING THOUGHTS / OBSERVATIONS / WARNINGS


    • Under this setup, you can get to the manager from any of your sites, e.g., www.site1.com/manager, www.site2.com/manager, etc.
    • Setting things up this way isn't totally without it's hiccups, though. The biggest issue on a day-to-day basis is using MODX's file browser: while you can still see and manage all the sites through the one manager, the file links and file browser will all be pointed to the site you used to log in--resources that live in the components or common folders will be fine, but site-specific stuff will change. For coders/devs this is probably a non-issue, but for clients and non-techy-users this could inadvertently lead to pain and confusion. For those users (and we are going to have to face this problem ourselves eventually), it's probably best to lock accounts down to one context (hiding others) and give them different logins for different sites--treat them like separate managers.
    • Our plan right now is to replicate this across Dev, Staging, and Production servers. For added security, the production server would be stripped of the manager folder. We haven't tested the replication process yet, but I'll update here on how difficult/easy that ends up being and how we go about automating that process.
    • Of course, the idea behind all of this is to have a single common set of files to maintain across several sites. Updating MODX should be as easy as uploading files into the right place (taking care not to blow away our special changes), and then running the setup from any one of the sites, although we haven't tested that yet to see if any problems are encountered by the setup program.
    [ed. note: debussy last edited this post 5 years, 8 months ago.]
    • UPDATE: I managed to fix the file browsing issue--pretty simply actually. I just set up media sources separately for each folder. For example:

      Media Source 1: "Code" <-- for browsing files for use with static elements

      • basePath = /path/to/www/elements/
      • basePathRelative = Yes
      • leave the rest default as these aren't publicly-accessible files anyway

      Media Source 2: "Common" <-- files that are accessible from all websites

      • basePath = /assets/common/
      • basePathRelative = Yes
      • baseUrl = /assets/common/
      • baseUrlRelative = Yes

      Other Media Sources (per site) <-- files that are unique to each site

      • basePath = /path/to/www/sites/<site folder>/assets/site/
      • basePathRelative = No
      • baseUrl = //<site domain>/assets/site/
      • baseUrlRelative = Yes

      Now users will be able to properly see and attach all files regardless of context... which means that it doesn't matter which site you log into the manager through, it should always work the same.
      • Are you running all this under a single DB or separate for each site?
          "One of these days I will get around to my own website... Its only been about 12 years... maybe tomorrow smiley"
        • Quote from: aesmith at Dec 05, 2015, 06:20 PM
          Are you running all this under a single DB or separate for each site?

          we're running this all on a single database
          • I'm doing something similar myself at the moment but I've taken a different approach before reading this..

            I've got one manager/core and I've created resource containers for each site with their own templates and I just intend to point the domains at domain.com/site1 and domain.com/site2 etc at the document root path. Surely this would be a lot more simpler? Is there a reason you chose to adopt your method that I'm missing?

            Thanks in advance.
              ■ email: lk@alienbuild.uk | ■ website: https://alienbuild.uk

              The greatest compliment you can give back to us, is to spend a few seconds leaving a rating at our trustpilot: https://uk.trustpilot.com/review/alienbuild.uk about the service we provided. We always drop mention of services offered by businesses we've worked with in the past to those of interest.
            • techdsco@gmail.com Reply #6, 1 year, 4 months ago
              Hello,
              In Context:
              I'm working already in a multisite modx installation, there are sites running successfully.
              I have found this line of code:
              <a href="[[~[[++site_config.someresourcename]]]]">Appointments</a>

              It works and everything but,

              Help me with this, please:
              I'm not able to find where the ++site_config has been set.
              I've read the documentation, search where it says should be made the system configurations, but with no luck.
              https://docs.modx.com/revolution/2.x/making-sites-with-modx/tag-syntax

              And I need to find this because I've been required to add an extra link like above poiting to another resource name, help please!

              Thank you in advance. [ed. note: techdsco@gmail.com last edited this post 1 year, 4 months ago.]
              • Trying editing the context it may be a setting in there or possibly from an extra like clientconfig
                  ■ email: lk@alienbuild.uk | ■ website: https://alienbuild.uk

                  The greatest compliment you can give back to us, is to spend a few seconds leaving a rating at our trustpilot: https://uk.trustpilot.com/review/alienbuild.uk about the service we provided. We always drop mention of services offered by businesses we've worked with in the past to those of interest.
                • I managed to get everything running.

                  When you are logged in to a specific context, the other context also show up on the menu under Resources.
                  Is there a way to hide or disable them?

                  I was able to hide them via CSS based on which context you are in, but wonder if there is a better way.
                  [ed. note: javster last edited this post 1 year, 2 months ago.]