Multisite
v7.4+ Single-installation
Intro
Since v7.4+, XalokNext supports a simpler variant of multisite - a single installation can serve different sites. This benefits from a simplified configuration.
Configuration
The single-installation configuration is done through .env
files, to enable loading it from this file:
# app/config/parameters/local.yml
wf_cms_admin.multisite:
env: true
Then add a .env
file in the root directory with a WF_CMS_MULTISITE
variable that contains the json encoded definition of sites:
WF_CMS_MULTISITE='{
"defaultSite": "site1",
"sites": {
"site1":{
"title": "Site number 1",
"base_url": "https://admin.common.tld",
"public_url": "https://site1.tld",
"images_domain": "https://imagenes.site1.tld",
"imghandler_url": "https://imghandler.site1.url",
"environment": {
"S3_BUCKET": "site1-bucket",
"S3_BUCKET_THUMBS": "site1-bucket-thumbs"
}
},
"site2":{
"title": "Site number 2",
"base_url": "https://admin.common.tld",
"public_url": "https://site2.tld",
"images_domain": "https://imagenes.site2.tld",
"imghandler_url": "https://imghandler.site2.url",
"environment": {
"S3_BUCKET": "site2-bucket",
"S3_BUCKET_THUMBS": "site2-bucket-thumbs"
}
},
}
}'
Note: Since this file is not part of the normal configuration files for Symfony, every change to this file must be followed by clearing the Symfony cache. Note: If using a non-default port (e.g.: 8000), this must be part of the URLs configured above (e.g.: "base_url": "http://site1.localhost:8000"
)
defaultSite
: the name (key) of the site to be used when a site cannot be determined, e.g.: when using Symfony commands.sites
: an array with sites definition, indexed by a key. Note, the key should be kept fairly short (below 10 chars), as it's being used amongst other things in naming site-specific Redis keys.
For each site, its definition can include:
title
: the name of the site that is displayed in the admin site selector (dropdown menu next to the Xalok logo)base_url
: the base admin URL - note that for single-installations there is a unique admin domain for all sitespublic_url
: the base public URLimages_domain
: keeps the_domain
name for historical reasons, but it's actually the base URL for the images - used to prefix the images' URL.imghandler_url
: the base URL for the "imghandler" - the domain under which thumbnails that are not already created are being servedenvironment
: a list of environment variables that are site-specific. Read the Site-specific environment variables section for details.
Loading sites
The sites are also stored in the database, to allow separating the entities (e.g.: categories, articles) by site. After changing the sites in the WF_CMS_MULTISITE
environment variable, one needs to run:
./app/admin/console --env=prod wf:cms:multisite:load
Note: Only the site key is kept in the database, so any other changes don't require running this. Note: Remember to clear Symfony's cache before running this command. Note: This command adds the sites to the database only if they don't exist, so running it multiple times won't have negative consequences
Migrating data
If there's already a database that holds the data for one of the sites and the project needs to migrate to multisite single-installation, XalokNext offers a command to assign existing entities to one of the sites:
./app/admin/console --env=prod wf:cms:multisite:switch https://site1.tld
For performance reasons, this updates the database through SQL queries directly, that is - it doesn't hydrate entities. So one must follow this with a reindex of ElasticSearch.
Site-specific environment variables
Each site can define its own environment variables (see the sites[X].environment
configuration above. Note that in order to avoid duplication, all the main keys are also registered (uppercased) as environment variables, e.g.: BASE_URL
, PUBLIC_URL
, IMAGES_DOMAIN
- without the need to specify them (also) in sites[X].environment
.
To use the values of these variables as parameters:
# app/config/parameters/local.yml
parameters:
images_domain: '%env(IMAGES_DOMAIN)%' # this comes from `sites[X].images_domain
s3_bucket: '%env(S3_BUCKET)%' # this comes from `sites[X].environment.S3_BUCKET
s3_bucket_thumbs: '%env(S3_BUCKET_THUMBS)%'
Configuring the parameters using environment variables means that their value will be determined at request time, depending on which site is being served (public/images URLs) or depending on which site has been chosen to work on in the admin.
Note: The S3 buckets must be configured for each site independent of each-other in order to ease the redirection (imagenes.site1.tld -> imghandler.site1.tld) when a thumbnail wasn't previously created.
Multi-installation
Intro
The multi-installation variant supposes that each project will get its own installation (different repositories/projects). This relies on the wf_user
tables being in sync across the different projects. That means that when starting a subsequent project, the wf_user
table must be copied as it is in the first project. Once the multisite multi-installation is setup, changes to the users of one site are synced automatically to other installations.
nginx
nginx
must be configured to switch the document root based on the value of wf_cms_site
cookie:
map $cookie_wf_cms_site $site {
default "site1dir";
site1 site1dir;
site2 site2dir;
}
server {
listen 80;
server_name admin.multisite.tld;
root /var/www/$site/web;
}
In addition to the admin.multisite.tld
, each of the installations must be accessible separately (admin.site1.tld
, admin.site2.tld
), for tools that don't send the cookie, like make wf_assets
.
.make-config
The ADMIN_HOST
is used for make wf_assets
, which doesn't send the wf_cms_site
cookie. Thus, it must be set to the individual CMS installation host (admin.site1.tld
, etc.)
CMS parameters
Sessions
All installations must be configured to read/write sessions in the same directory:
# app/admin/config/config_prod.yml
framework:
session:
save_path: /tmp/wfcms_session
admin_url
The admin_url
parameter is used by the client-side application, so it needs to point to the "joint" domain (https://admin.multisite.tld/
)
wf_cms_admin.multisite
wf_cms_admin.multisite
parameter must be configured on all sites with a list of available sites
# app/config/parameters/local.yml
wf_cms_admin.multisite:
multiinstallation: true
sites:
site1:
base_url: admin.site1.tld
public_url: site1.tld
images_domain: img.site1.tld
images_base_url: /files
site2:
base_url: admin.site2.tld
public_url: site2.tld
images_domain: img.site2.tld
images_base_url: /files
The base_url
is used to display (for example) in site1
, when searching for images from site2
. The user already has the wf_cms_site
set to site1
, so nginx would point to the /uploads
directory of site1
. To solve this, the images have the full path https://site2_base_url/uploads/...
Troubleshooting
Out of sync users table
If a site was added to the multisite config without importing the users table first, the easiest way to sync the users table is to load the fixtures and import the users table from an existing website:
make load_fixtures
Warning: This will delete the entire content from the DB - it should only be ran in DEV or PRE environments.
Note: this command refuses to run if the ADMIN_SF_ENV
variable is set to prod
in .make-config
. Change it to dev
temporarily, before running the command. Don't forget to set it back to prod
once the fixtures are reloaded.
After reloading the fixtures, import a dump of the wf_users
table from the currently running project.