Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Creating an Open edX LMS instance with Docker through Tutor

profile picture
Author
Stefan Nikolaj
Published
2023-09-19
Time to read
10 minutes reading time

About the author- A very curious student currently studying Aerospace Engineering. Whatever I do, I find myself in some kind of cloud.

Introduction

Running a Learning Management System (LMS) can be very difficult for server administrators, since LMSs are usually made up of multiple components and require significant resources, as they are made to serve many people simultaneously in vastly different configurations. This tutorial will focus on how to host an LMS instance which can handle a few hundred or thousand users at most (highly dependent on the workload). As a result, this deployment is most appropriate for small educational environments with limited processing resources which nevertheless need an LMS.

Open edX is a good LMS solution because it is free, open source and is supported by many educational institutions. Docker is an excellent choice for deploying Open edX through the Tutor set of scripts. Tutor drastically simplifies the deployment of Open edX through the use of a unified interface for accessing configuration variables and the ability to one-click-install. Without it, administrators would have to handle over 780 configuration files. Docker further allows portability, upgradeability and decoupling of the many parts it takes to build an LMS.

This tutorial was tested on Ubuntu 22.04 running on an Arm64 instance. It will use apt as the package manager, so make sure to replace it with your distro's package manager if you are using something else.

Prerequisites

  • A VPS that meets the hardware requirements:

    • Minimum configuration: 4 GB RAM, 2 CPU, 8 GB disk space
    • Recommended configuration: 8 GB RAM, 4 CPU, 25 GB disk space
  • Any 64-bit Linux OS (x86-64 or Arm64)

  • A domain and the ability to edit DNS records (through your domain name provider)

Example terminology

  • Username: holu
  • Domain: example.com
  • Subdomain: tutor.example.com

Step 1 - Installing Docker and Docker Compose

First, do a full system update and upgrade:

sudo apt update
sudo apt upgrade -y

If you do not have Docker yet, you can set it up now:

sudo apt install docker.io    # Install Docker
sudo usermod -aG docker holu  # Add your user to the docker group; replace "holu" with your own username

Log out and back in to update your groups. Then run the command groups to see if your user is now in the "docker" group.

As of v16.0.0, the local deployment of Tutor requires Docker Compose v2, so you do not need to install docker-compose (hyphenated). However, you will need to have the new docker compose (non-hyphenated) command which is installed separately. The following commands will install the new Docker Compose as a Docker plugin:

mkdir -p ~/.docker/cli-plugins/

You can use uname -srm to check your architecture before you choose one of the releases below.

  • VPS with x86 architecture

    curl -SL https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose
  • VPS with Arm64 architecture

    curl -SL https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-linux-aarch64 -o ~/.docker/cli-plugins/docker-compose

Make sure to replace v2.21.0 with the most recent version of Docker Compose, which you can find on the official releases page.

To be able to use the downloaded binary through Docker, you need to make it executable with this command:

chmod +x ~/.docker/cli-plugins/docker-compose

To test if docker compose works, simply run:

docker compose version

This command should return the version of docker compose that you installed, which in my case is:

Docker Compose version v2.21.0

Now we can move on to the installation.

Step 2 - Installing the required packages

If you do not have the required packages, install them with the following command (on Ubuntu):

sudo apt install python3 python3-pip libyaml-dev

For other Linux distros, replace apt install with the appropriate package manager for the distro.

Once you have the required packages, you can install the latest version of Tutor with the following command:

pip install "tutor[full]"

Using the syntax "tutor[full]==16.1.1", you can install a specific version of Tutor. You can replace 16.1.1 with any version you want. You can find Tutor releases on the official GitHub page.

To check if the installation worked, run tutor --version. You might need to log out and back in again.

Step 3 - Configuring the ports

Tutor uses Caddy as a web proxy. This makes adding SSL easy, but the default ports are 80 (for HTTP) and 443 (for HTTPS). These ports are often in use by other websites running on the same server, so Tutor has a command to change the default port. In my case, ports 80 to 83 were taken, so I had to use port 84. If you use different ports than the defaults, you only need to open up one port for both HTTP and HTTPS. All of this can be done with the following command:

To check which ports are in use, run:
sudo lsof -i -P -n | grep LISTEN

tutor config save --set ENABLE_WEB_PROXY=false --set CADDY_HTTP_PORT=84

Make sure to replace CADDY_HTTP_PORT=84 with the port you want to use.

Step 3.1 - Configuring firewalls

Since many firewalls exist, this tutorial will only cover two popular options — Hetzner Cloud Firewall and Ubuntu's default firewall ufw (which is automatically installed).

Hetzner Cloud Firewall

In the Hetzner Cloud Console, select your server and in the navigation bar select "Firewalls". Select the active Firewall, click the three dots on the right and click "Edit Firewall". Then, in the top right of the site click on the "Add rule" button and select "Inbound". A box will appear where you need to add a description of the new Firewall rule, the type of IP you want to be able to access the site and the port. Leave the protocol on the default TCP. If you want to limit who can access the LMS, such as limiting it only to a certain IP range (only IPs on a particular campus, for example), you can do that here. The final box should look like the table below:

IPs Protocol Port Port range
Any IPv4 Any IPv6 TCP <YOUR-PORT-NUMBER>

ufw
  • Check if ufw is active
    To check if ufw is active, run:

    sudo ufw status

    The exact output will be different depending on whether you have any rules added.

    • Active
      The command should return the following output:

      Status: active
      
      To                         Action      From
      --                         ------      ----
      OpenSSH                    ALLOW       Anywhere
      OpenSSH (v6)               ALLOW       Anywhere (v6)
    • Inactive
      The command should return the following output:

      Status: inactive

      To activate ufw, simply run sudo ufw enable after you have finished the steps below. Make sure you allow OpenSSH before you enable ufw: sudo ufw allow OpenSSH.

  • Allow incoming traffic to port
    To allow incoming traffic to your port, you need to add it as a ufw rule with the following command:

    sudo ufw allow proto tcp to any port <YOUR-PORT-NUMBER>
  • Check if the rule was added
    If the firewall was inactive, you can activate it now. Check if the rule was added with the following command:

    sudo ufw status

    Example output:

    Status: active
    
    To                          Action      From
    --                          ------      ----
    OpenSSH                     ALLOW       Anywhere
    <YOUR-PORT-NUMBER>/tcp      ALLOW       Anywhere
    OpenSSH (v6)                ALLOW       Anywhere (v6)
    <YOUR-PORT-NUMBER>/tcp (v6) ALLOW       Anywhere (v6)

If you are using another firewall, the steps to opening up the port will likely be similar.

Step 4 - The one-click-install

Now that you have downloaded Tutor and optionally set up the ports, simply run:

tutor local launch

First the command will ask you to answer a few questions about a contact email and the subdomains used for users and administrators/course creators. The final question will ask about SSL ("Activate SSL/TLS certificates for HTTPS access?"), which I highly recommend you answer yes ("y") to. After this, the installation will begin. This should take 5-15 minutes, depending on your VPS's CPU power and download speed. This one command will create the aforementioned 780+ configuration files, download and install all the necessary Docker containers.

If you get an error such as Command failed with status 1: docker compose ..., you might not have enough RAM.

Step 5 - DNS setup

For this step you need to have a domain name. This tutorial will use the example domain example.com. If you want your domain to be publicly accessible, you need to add DNS records which state that all subdomains of your main Open edX instance are associated with your domain name. Browsers treat each subdomain as a completely separate website, so you need to add records which both point the subdomain to your server, and show that all subdomains are associated with Open edX. This process is different for all domain name providers. I use Namecheap, and it is a common provider, so I will illustrate the process for adding records.

  • Run this command to get the main subdomain for Open edX:

    tutor config printvalue LMS_HOST
  • Run this command to get the IP address of your server:

    curl -4 https://ip.hetzner.com

In my example, my subdomain is tutor.example.com. This is the value that you set at the beginning of Step 4. Additionally, you need the IP address associated with the server you are hosting Open edX on. You will need to add an A record associated with the main subdomain you found from the command above. You will also need to add a CNAME record associated with all subdomains of the main subdomain. In the Namecheap UI, this will look like the following:

Type Host Value TTL
A record tutor <YOUR-IP-ADDRESS> Automatic
CNAME record *.tutor tutor.example.com Automatic

After setup, these records may take up to 30 minutes to start working, so be patient if your domain does not work immediately.

Conclusion

This is likely the shortest possible LMS setup which results in a production-ready and high-quality service. Open edX, as a platform, is a great LMS and combining it with Docker gives it another level of flexibility. Compared to Moodle, the other dominant free and open-source LMS, Open edX also works on Arm64 servers, which are becoming increasingly appealing due to their generally lower price and higher core count. Even Hetzner's lowest cost Arm server offer can run the minimum configuration of Open edX, while Docker allows very quick transitions to more resource-rich cloud or on-premise servers if needed.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get 20€ free credit!

Valid until: 31 December 2024 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more