Recipe to Deploy Tutor from Scratch on a Small VM

While Tutor deployment instructions are well documented, I figured it would be worth documenting the process I went through to do it with a third-party plugin (the Library Authoring MFE) on a smallish AWS VM.

Prerequisites

This howto was tested on a VM in AWS with the following characteristics:

  • CPU: 2 cores

  • RAM: 8GB

  • Local storage: 100GB

This is essentially a t3a.large type, which seems to be the more economical one. As for instance configuration:

  • OS: Ubuntu 22.04

  • Firewall: Ports 22, 80, and 443 open

  • IP: A public address (here, 1.2.3.4)

  • DNS: a domain (here, example.org) that points to the above IP

  • SSH: an SSH key deployed to it

And if you want activation emails (or any kind of email) to be properly sent out, it is a good idea for your VM to be configured with IPv6 in dual-stack mode. Here’s the AWS VPC guide on how to do it.

Initial update

Connect to the VM via SSH, using the ubuntu user.

ssh ubuntu@example.org

Then proceed to update all packages, reboot, and remove extraneous ones:

sudo apt update && sudo apt full-upgrade -y sudo reboot sudo apt autoremove --purge

Add other SSH keys

If you have other team members, add their SSH keys from, for instance, Github:

user=exampleuser wget -O - https://github.com/${user}.keys >> ~/.ssh/authorized_keys

Install docker

Because Tutor 16 now supports Docker’s new BuildKit, which does more intelligent caching and more efficient builds (which will come in handy when rebuilding the tutor-mfe image), we'll be installing it directly from upstream (as opposed to just apt installing it.) This process is documented elsewhere, but here are the actual steps that were used.

First, remove any pre-existing Docker packages:

sudo apt remove docker.io docker-doc docker-compose podman-docker containerd runc

Next, add the upstream GPG keys and the repository, then update the package list.

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update

Install the required packages:

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Add the ubuntu user to the docker group so it can manage containers without being root, then exit the SSH session and reconnect:

sudo usermod -aG docker ubuntu exit

Install Tutor

After reconnecting, install Tutor as follows:

sudo apt install python3 python3-pip libyaml-dev pip install tutor

If this is the first time running pip, exit the SSH session and reconnect. This is so the PATH environment variable is updated to include pip-installed binaries:

exit

Configure

At this point, create the base Tutor environment via:

tutor config save --interactive

Answer the questions as follows, replacing values with your own:

Are you configuring a production platform? [Y] Your website domain name for students (LMS) [https://openedx.example.org] Your website domain name for teachers (CMS) [https://studio.openedx.example.org ] Your platform name/title [Open edX Palm] Your public contact email address [admin@example.org] The default language code for the platform [en] Activate SSL/TLS certificates for HTTPS access? [Y]

Plugins

Install the tutor plugins you need. In this case, we’ll install tutor-mfe, tutor-forum, and the (at time of writing) experimental tutor-contrib-library-authoring-mfe.

Start with the official ones:

tutor plugins update tutor plugins install mfe forum

Then proceed with the plugin for the Library Authoring MFE:

pip install git+https://github.com/openedx/openedx-tutor-plugins.git#subdirectory=plugins/tutor-contrib-library-authoring-mfe

If you need to alter LMS configuration - a common practice - create a local site-config plugin (the name is arbitrary) to contain it.

mkdir -p "$(tutor plugins printroot)/site-config.py" cat >"$(tutor plugins printroot)/site-config.py" <<EOF from tutor import hooks hooks.Filters.ENV_PATCHES.add_item( ( "openedx-lms-common-settings", """ REGISTRATION_EMAIL_PATTERNS_ALLOWED = [ "^.@example\\\\.org$", "^.@other\\\\.org$" ] """ ), ) EOF

(In the example above we’re simply specifying which email domains are allowed to self-register.)

Finally, enable the installed plugins and regenerate the environment:

tutor plugins enable forum library-authoring-mfe site-config tutor config save

Rebuild MFE image

Because we installed a custom MFE plugin, we won’t be able to use the pre-built MFE image provided by the Tutor team. Here we’ll build a new one.

However, while the new Docker BuildKit is great for several reasons, it tries to build all MFEs in parallel. Given the number of MFEs that Tutor currently supports together with the relatively small size of this VM, this would grind the build process to a halt. To avoid it, we create a new build container limited to one thread:

cat >buildkitd.toml <<EOF [worker.oci] max-parallelism = 1 EOF docker buildx create --use --name=singlecpu --config=./buildkitd.toml

We can then finally rebuild the image.

tutor images build mfe

On an instance of this type, the process takes around 40 minutes.

Launch!

Finally, it’s time to launch! Run the following command. Feel free to take the default values, as you already filled them in earlier:

tutor local launch

This will take a little while, as the Docker images need to be fetched and the MySQL migrations to be r un.

Further configuration

You’ll likely want to create an administrator user for yourself. Do so as follows:

tutor local do createuser --staff --superuser ${username} ${useremail}

And if you want to import the demonstration course, there’s a command for that, too:

tutor local do importdemocourse

Finally, if you’re going to try out Libraries v2 you should also create a default organization in the admin dashboard. Log in as your admin user, then head on to https://openedx.example.org/admin/organizations/organization/ and add at least one. It will be needed when creating a library.