As part of the holiday season - I thought it would be interesting to pilot a learning management system for close friends and family to post content about something they are passionate about (e.g. photography, books, tech, knitting, etc.). There are several options out there which are open source and able to be self hosted.

I was curious about a couple - the main criteria being easily self hosted with docker. This lets me tweak the docker-compose spec to work with pangolin and lets me manage the reverse proxy usign traefik (supplied by pangolin). This has been my workflow for other self hosted apps and it works quiet nicely.

The system itself shouldn’t be too complicated, I am not planning on scaling the LMS to 30k users - it will be a group of < 10 people. In that regard I really only need rudimentary roles and concepts - basically it should be a couse composed of a series of blogs, videos, or voice-vers with limited content. Not planning on doing assessements and grading.

You may say that a private Youtube would be the best solution for hosting the videos, and while technically that would suffice the video portion of it, I think the value-add is really spending the time typing out the textual representation similar to a blog. We may end up using Youtube to host the videos rather than paying for the storage in an AWS S3 bucket or similar. Looking at some of the solutions out there, it’s also possible to embed presentations into the course which will be great for a “live classroom” setting.

The other functionality that is interesting is the mass email notifications (e.g. no-reply@learn.kenyon.app). There are some interesting services out there to achieve this type of functionality, one of the ones I found which seems easy, free and straightforward is resend.com. I linked it to my github and we are off to the races - the free tier has 3,000 email limit (send/receive) which is plenty for my use case.

LMS Platforms

Looking at the candidates there are a number of suitable alternaives I wanted to evaluate.

Clasroom.io

Classroom.io is a open source education platform that can be used for self hosting training material.

There is some existing documentation for a self hosted setup here in the docs: https://classroomio.com/docs/quickstart/self-hosting

Notes:

  • Interesting platform and the first I can across searching for an open-source alternative to google classroom
  • Developed out of nigeria (very cool)
  • Not very easy to self host
  • The setup used supabase which was the first time I have heard of the tool, it is an open source version of firebase which I have used in the past for some app development.
  • Led me to learn about SMTP and resend.com which was good to know a provider for the other LMS
  • Docs in general are pretty good but under-construction
  • Maintained by a few developers on their free time

Conclusion: Due to the inability to self host this was shelved after a couple hours of investigation.

Learnhouse

Learnhouse is a more self-hosted friendly project.

Notes

  • It provides a simple intuitive UI, aligned with my use case
  • docker compose friendly, somewhat easy to understand the environment variables and setup
  • Disliked the frontend and the backend were hosted in the same container with an nginx reverse proxy
  • No dark mode :/

Conclusion: Overall easy to customize, but the nginx reverse proxy and lack of separation for frontend/backend poses issues hosting with pangolin - haulted after about an hour of investigation.

OpenEdx

The flagship app for open source education - it is a beast.

Notes

  • Comprehensive LMS - overkill for my use case, intended to be used at scale. Many user roles, etc.
  • Recommended tool tutor for self hosting, takes away the complexity of setup (able to host local instance out of the box)
  • Uses Caddy as the reverse proxy
  • Ability to import courses using an open XML spec (OLX)

Conclusion: Very comprehensive, likely too complex for what is required. May be made to work if no other suitable solution. Tutor is a nice abstraction, but may make self hosting with pangolin more difficult.

Canvas

Canvas LMS is a widely used LMS in the United States - the institution I attended for university used Canvas.

Notes

  • Open source
  • Complicated setup

Frappe

https://github.com/frappe/lms

Easy setup, built on the frappe framework (https://github.com/frappe/lms).

  • Dark mode :smiley-face:
  • There is the abilty to add in programming language assessments :party:
  • no arm images :/

Unsplash for API development

Setup:

# Build the custom image with: 
export APPS_JSON_BASE64=$(base64 -w 0 apps.json)
# content of app.json
#[
#  {
#    "url": "https://github.com/frappe/lms",
#    "branch": "develop"
#  }
#]

# build the image
docker build  --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe  --build-arg=FRAPPE_BRANCH=version-15  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64  --tag=custom:15  --file=images/layered/Containerfile .

# create the compose spec
docker compose --env-file example.env     -f compose.yaml     -f overrides/compose.mariadb.yaml     -f overrides/compose.redis.yaml     -f overrides/compose.noproxy.yaml     config > compose.custom.yaml

# Add in the pangolin network & replace amd64 with arm64

# bring up the app
docker compose -f compose.custom.yaml up -d --pull never

# Create a new project at the desired subdomain
docker compose exec backend bench new-site learn.kenyon.app --mariadb-user-host-login-scope='172.%.%.%'

# Install lms (which was baked into the base image)
docker compose exec backend bench --site learn.kenyon.app install-app lms

Sources: https://github.com/frappe/lms https://github.com/frappe/frappe_docker/blob/main/docs/getting-started.md

Docs: https://docs.frappe.io/learning/introduction

may be able to add resend functionality:

Connect with pangolin (e.g. change the network to pangolin).

This is a rabbit hole - since the app still uses an nginx reverse proxy. I am unsure how to go about getting the server to resolve correctly when using traefik supplied by pangolin. Basically the request hits nginx, but it will respond with a 404 on any resources due to an invalid host (e.g. learn.kenyon.app does not exist).

I also went through the whole process of creating our own docker file using the overrides. There is supposidly a pwd.yml file tin the repository that has a good minimal setup and uses the host frontend.

This option is the most appropriate due to the balance of support, complexity to deploy, and extensibility for in-app programming evaluation.

Adding an email account - need to set the settings for the smtp server (e.g. smtp.resend.com) with the password being the API key. For SSL - need to use port 465.

Google drive integration: https://docs.frappe.io/framework/user/en/integration/google_drive (This didn’t seem to be applicable)

More info on adding a lesson: https://docs.frappelms.com/course-creation/add-a-lesson.html

  • You can insert a google slides presentation into a lesson by copying the sharable link (permissions likely need to be open).

There’s a set of open standards for elearning: scorm. The Frappe LMS supports importing as this format, which should ease the burden of porting courses from other platforms. Frappe has a CSV or XLSX import and export. (There is also a full-on backup which can be run weekly to back up course content)

If you configure the Frappe desk to use the google api for backing up the data (needed to add some an http redirect uri) - likely due to routing the traffic through pangolin.

  • update the API key (restricted to google drive api access)
  • update the test users of the application (cannot publish while there is a http redirect)
  • authorize the google drive access in the Frappe /app/google-drive settings

Files are then periodically backed-up to the google drive, and can be restored with the bench restore api: https://docs.frappe.io/framework/user/en/bench/reference/restore

Summary

Overall, the solution that best fit my use case is frappe - the user management is not too cumbersome, the docker setup was sufficient for the purposes of hosting small learning management system, although it took a minute to sift through the content to determine what the “advised” method of setting up the app should be. After adding it into my pangolin network, everything is running smoothly. resend works great for sending out service emails for purposes such as account creation.