This article was written by team members Shimul Chowdhury and Guruprasad Lakshmi Narayanan.

An Open edX “site” presents a catalog of courses and course content in an individual way. A vanilla Open edX instance features a main, single site by default, but — did you know the platform could support multiple sites, all hosted on the same instance? All sites can be configured independently of each other: for example, you can assign a different visual theme to each site, along with a unique homepage URL, and a specific course catalog.

Deploying multiple sites requires a little work. The official documentation is a great start, but things get complicated fast if your platform uses additional services such as eCommerce and Course-Discovery. Additional services require additional configuration to be able to work in the context of a custom site.

We’ll start by listing the steps needed to configure a site manually. Then we will recommend an easier way to achieve the same via Sites Generator, a neat automation tool that we built at OpenCraft.

LMS

The following configuration should be added to the LMS:

Organization

If we want to create a separate site for each organization offering courses on the instance, we need to create that organization at – <LMS_ROOT>/admin/organizations/organization

Site

Then we can set up a site using the Django sites framework by adding a new site here –  <LMS_ROOT>/admin/sites/site/

SiteConfiguration

With the SiteConfiguration model, we can tailor different aspects of each site according to our needs. We can add/update SiteConfiguration values for a site from <LMS_ROOT>/admin/site_configuration/siteconfiguration/

The Open edX documentation has a pretty comprehensive list of available parameters that we can tweak using the SiteConfiguration model. We need to make sure we set up the following configurations for the custom site to work correctly –

  • course_org_filter – only show courses from one or more specific organizations on a particular site.
  • SITE_NAME & LMS_BASE – LMS domain name.
  • LMS_ROOT_URL – LMS URL.
  • PREVIEW_LMS_BASE – LMS preview site domain.
  • ECOMMERCE_PUBLIC_URL_ROOT – e-commerce site URL.
  • COURSE_CATALOG_API_URL – Discovery service API URL.

eCommerce OAuth Redirect URI

To have eCommerce work independently for each site under its custom sub-domain, we need to add an OAuth2 redirect URL from – <LMS_ROOT>/admin/oauth2_provider/application/ 

  • Find and edit ‘ecommerce-sso’ application 
  • add <ECOMMERCE_PUBLIC_URL_ROOT>/complete/edx-oauth2/ to Redirect URIs field. 

This ECOMMERCE_PUBLIC_URL_ROOT has to be the new eCommerce site that we will be creating in a moment.

The default ‘ecommerce-sso’ application gets overwritten every time we deploy our instance via Ansible. So, we have to apply the above changes after every redeployment. To avoid this, we can create a separate OAuth2 application for setting up the SSO for custom eCommerce sites.

The site-generator application does this automatically.

Course-Discovery

We have to configure the following models to allow using a custom discovery site corresponding to each LMS site.

Site

For each custom site in LMS (with course_org_filter applied), we need a separate Discovery Site. Add a new Site from – <DISCOVERY_ROOT>/admin/sites/site/. The domain name should be the same domain as COURSE_CATALOG_API_URL in LMS SiteConfiguration for our custom site.

Partner

Create a Partner for each custom site from – <DISCOVERY_ROOT>/admin/core/partner/

  • Select the Site we’ve just created.
  • Add LMS, Studio, LMS admin URLs corresponding to our custom site domain
  • Course API URL – <LMS_CUSTOM_SITE>/api/courses/v1/
  • Organizations API URL – <LMS_CUSTOM_SITE>/api/organizations/v0/
  • Ecommerce API URL – <ECOMMERCE_PUBLIC_URL_ROOT>/api/v2/

eCommerce

We have to add the following configuration in eCommerce for each custom LMS site.

Site

We can create a new site from – <ecommerce_domain>/admin/sites/site/add/

The domain name of the created site should be the same as the value of ECOMMERCE_PUBLIC_URL_ROOT specified in the SiteConfiguration instance of the corresponding custom LMS site.

Partner

We can create a partner for the custom site from – <ecommerce>/admin/partner/partner/add/ and select the site we created above.

Site Configuration

We can set up the site configuration for the custom ecommerce site created above from – <ecommerce>/admin/core/siteconfiguration/add/

We have to properly configure the OAuth settings here so that the eCommerce login works correctly.


OpenCraft Sites Generator

As we can see, setting up a custom site requires many careful steps. So, imagine setting up 10 or 20 sites manually. No, thank you! Not to mention the risk of forgetting to update a configuration somewhere during edits or updates.

To tackle this problem, we at OpenCraft have created the Sites Generator open source application. It is a set of scripts that automates setting up custom sites in an Open edX installation across the LMS and other Independently Deployed Applications (IDA) like course-discovery and ecommerce. It allows you to use a single configuration file rather than manually maintaining all the relevant configurations in all those services. This single file will be used to generate and update all the required configurations.

Let’s say we have an Open edX instance, and we want to create two sites: ExampleEdu1 and ExampleEdu2. We can create a config like the following –

main_domain: "exampleedu.com"
site_for_each_organization: true
oauth:
  ecommerce_sso_client: custom-sites-ecommerce-sso
organizations:
  exampleedu1:
    name: "Example Edu 1"
  exampleedu2:
    name: "Example Edu 2"
microsites:
  $:
    context_overrides: {}
    overrides:
      ecommerce:
        ecommerce.core.models.SiteConfiguration:
          oauth_settings:
            SOCIAL_AUTH_EDX_OAUTH2_KEY: <ecommerce-sso client id>
            SOCIAL_AUTH_EDX_OAUTH2_SECRET: <ecommerce-sso client> secret
            BACKEND_SERVICE_EDX_OAUTH2_KEY: <ecommerce-backend-service client id>
            BACKEND_SERVICE_EDX_OAUTH2_SECRET: <ecommerce-backend-service client secret>
          payment_processors: paypal,cybersource

  exampleedu1:
    overrides:
      lms:
        openedx.core.djangoapps.site_configuration.models.SiteConfiguration:
          site_values:
            PLATFORM_NAME: Something Special!

Now, let’s break it down –

  • main_domain – This domain will be used for generating domains for different services for those two sites –
    • ExampleEdu1 – 
      • LMS – exampleedu1.exampleedu.com 
      • Preview – preview.exampleedu1.exampleedu.com 
      • Studio – studio.exampleedu1.exampleedu.com 
      • ecommerce – ecommerce.exampleedu1.exampleedu.com 
      • Discovery – discovery.exampleedu1.exampleedu.com
    • ExampleEdu2 – 
      • LMS – exampleedu2.exampleedu.com 
      • Preview – preview.exampleedu2.exampleedu.com 
      • Studio – studio.exampleedu2.exampleedu.com 
      • ecommerce – ecommerce.exampleedu2.exampleedu.com 
      • Discovery – discovery.exampleedu2.exampleedu.com 
  • site_for_each_organization – It is possible in the platform to have multiple organizations in a single site or in multiple sites. If this configuration is true, the generator assumes we want a separate site for each organization. This will simplify the workflow, and we found this to be the most common use case.
  • oauth – As mentioned before, the ecommerce OAuth2 Application will get overwritten every time we redeploy. The script uses a different application instead of the default one. We can, optionally, override the name of that application here.
  • organizations – We list the organizations to be created under this key.
  • microsites – Here we define the custom sites. If ‘site_for_each_organization’ is true, we don’t need to specify each site here. The generator will generate one for each organization, and we can override the configuration for any specific site.
    • $ – is a special key. Any override here will apply to all sites.

To know more about overrides, please check the repository

Once we create the configuration, we can then run the script in an appserver using the  ‘make run’ command.

Conclusion

Setting sites can be tricky business, and we believe that the Sites-Generator application is an excellent tool to effortlessly manage multiple sites in an Open edX installation. It prevents a lot of manual work that would have been needed otherwise. If you find this script useful, feel free to use and contribute to it! If you encounter any issues, please let us know on Github, comment on this post, or email us at contact [at] opencraft.com : )

Cover photo by Omar Flores on Unsplash