Multisite¶
Warning
This is an advanced feature of RDMO.
RDMO can be operated in a multi site setup, connecting several different rdmo-apps
with different URLs and Themes, on one Server with one common Database. The different Sites will share their Catalogs, Views, etc., but the availability of this Content can be restricted among the Sites. Users can log in into any of the sites (if the authentication method allows) and projects can be shared among sites. Each of these RDMO Sites has its own rdmo-app
directory and its own configuration (config/settings/local.py
).
Setup¶
To setup such a multi site installation, you need to start with a regular RDMO instance as described in installation. In principle, an existing RDMO instance can be extended to a multi site installation, but in this documentation we assume a fresh installation.
Create the virtual environment outside the
rdmo-app
, e.g. in/srv/rdmo/env
. In a multi site setup all RDMO sites use the same virtual environment. RDMO and the other python dependencies need to be updated only once for the whole installation.Otherwise, follow the instructions as usual, but add
MULTISITE = True
toconfig/settings/local.py
. This enables the multi site features in the user interface.After the installation, login to the admin interface and add your additional sites in the Sites section as described here. Note the numerical ID of the different Sites as shown in the URL when editing the Site (e.g.
http://localhost:8000/admin/sites/site/2/change/
).Then clone a second
rdmo-app
next to the first one, but use the same virtual environment as before (so nopip install
is required). Setuprdmo-app2/config/settings/local.py
as usual. IncludeMULTISITE = True
andSITE_ID = X
inrdmo-app2/config/settings/local.py
, whereX
is the ID of the site from the step before. ForDATABASE
use the same settings as inrdmo-app
.
If you now run ./manage.py runserver 0.0.0.0:8000
in rdmo-app
and ./manage.py runserver 0.0.0.0:8002
in rdmo-app2
, the two sites should be working already.
Deployment¶
The two sites are deployed separately, regardless if using Apache or nginx. Create separate virtual host configurations which map the particular site url to the corresponding rdmo-app
. E.g. for Apache:
<VirtualHost *:443>
ServerName example.com
...
Alias /static /srv/rdmo/rdmo-app/static_root/
<Directory /srv/rdmo/rdmo-app/static_root/>
Require all granted
</Directory>
WSGIDaemonProcess rdmo_app user=rdmo group=rdmo \
home=/srv/rdmo/rdmo-app python-home=/srv/rdmo/env
WSGIProcessGroup rdmo_app
WSGIScriptAlias / /srv/rdmo/rdmo-app/config/wsgi.py process-group=rdmo_app
WSGIPassAuthorization On
<Directory /srv/rdmo/rdmo-app/config/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
and
<VirtualHost *:443>
ServerName example.org
...
Alias /static /srv/rdmo/rdmo-app2/static_root/
<Directory /srv/rdmo/rdmo-app2/static_root/>
Require all granted
</Directory>
WSGIDaemonProcess rdmo_app2 user=rdmo group=rdmo \
home=/srv/rdmo/rdmo-app2 python-home=/srv/rdmo/env
WSGIProcessGroup rdmo_app2
WSGIScriptAlias / /srv/rdmo/rdmo-app2/config/wsgi.py process-group=rdmo_app2
WSGIPassAuthorization On
<Directory /srv/rdmo/rdmo-app2/config/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
For gunicorn
, two seperate systemd service files need to be configured. For reasons unkown to us, the service files must use different RuntimeDirectory
locations, e.g. gunicorn/app1
and gunicorn/app2
. GUNICORN_BIND
and GUNICORN_PID_FILE
need to be adjusted accordingly.
Shibboleth¶
In order to run multiple separate sites on one machine the Service Provider needs to be configured differently. For each site but the first one, an ApplicationOverride
needs to be configured in /etc/shibboleth/shibboleth2.xml
, e.g.
<SPConfig xmlns="urn:mace:shibboleth:3.0:native:sp:config"
xmlns:conf="urn:mace:shibboleth:3.0:native:sp:config"
clockSkew="180">
<OutOfProcess tranLogFormat="%u|%s|%IDP|%i|%ac|%t|%attr|%n|%b|%E|%S|%SS|%L|%UA|%a" />
<ApplicationDefaults entityID="https://sp.test.rdmo.org/shibboleth"
REMOTE_USER="eppn"
cipherSuites="DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1">
<Sessions lifetime="28800" timeout="3600" relayState="ss:mem"
checkAddress="false" handlerSSL="true" cookieProps="https">
<SSO entityID="https://idp.test.rdmo.org/idp/shibboleth"
discoveryProtocol="SAMLDS" discoveryURL="https://ds.example.org/DS/WAYF">SAML2</SSO>
...
</Sessions>
...
<AttributeFilter type="XML" validate="true" path="attribute-policy.xml"/>
<CredentialResolver type="File" use="signing" key="sp-key.pem" certificate="sp-cert.pem"/>
<CredentialResolver type="File" use="encryption" key="sp-key.pem" certificate="sp-cert.pem"/>
<MetadataProvider type="XML" validate="true" path="idp-metadata.xml"/>
<ApplicationOverride id="sp2" entityID="https://sp2.test.rdmo.org/shibboleth">
<Sessions lifetime="28800" timeout="3600" relayState="ss:mem"
checkAddress="false" handlerSSL="true" cookieProps="https">
<SSO entityID="https://idp2.test.rdmo.org/idp/shibboleth"
discoveryProtocol="SAMLDS" discoveryURL="https://ds.example.org/DS/WAYF">SAML2</SSO>
...
</Sessions>
<CredentialResolver type="File" use="signing" key="sp2-key.pem" certificate="sp2-cert.pem"/>
<CredentialResolver type="File" use="encryption" key="sp2-key.pem" certificate="sp2-cert.pem"/>
<MetadataProvider type="XML" validate="true" path="idp2-metadata.xml"/>
</ApplicationOverride>
</ApplicationDefaults>
...
</SPConfig>
where https://idp.test.rdmo.org
und https://idp2.test.rdmo.org/idp/shibboleth
are two different IdP for the two RDMO sites. Again, your Shibboleth setup might differ.
In the virtual host configuration for each but the first site, ShibRequestSetting applicationId <id>
needs to be added to both <Location /Shibboleth.sso>
and <LocationMatch /(...)>
. <id>
is the id
attribute of the ApplicationOverride
node, e.g.:
<Location /Shibboleth.sso>
SetHandler shib
ShibRequestSetting applicationId example.org
</Location>
<LocationMatch /(account|domain|options|projects|questions|tasks|conditions|views)>
AuthType shibboleth
require shibboleth
ShibRequireSession On
ShibUseHeaders On
ShibRequestSetting applicationId example.org
</LocationMatch>