॥ श्री ॥

Education & E-Learning

Self-Hosting & Servers 2026-04-22

Self-hosted learning management systems, school administration platforms, collaborative tools, and knowledge-sharing apps. Run your own campus, classroom, or training environment with full data ownership and zero per-seat licensing fees.

Why self-host education tools? GDPR and FERPA compliance, full student data ownership, no vendor lock-in, and the ability to customise the learning environment — these matter whether you are running a school, a homeschool co-op, a corporate training platform, or a private tutoring practice.

---

Key Concepts

LMS architecture — SCORM, xAPI, and LTI

The e-learning interoperability standards define how learning content and tools integrate. SCORM (Sharable Content Object Reference Model) packages courses as ZIP files with a manifest — any SCORM-compliant LMS (Moodle, Canvas) can import and track completion. xAPI (Tin Can) extends this to track any learning experience as subject-verb-object statements ("Alice completed Module 3") sent to a Learning Record Store (LRS). LTI (Learning Tools Interoperability) is the SSO standard for embedding third-party tools (H5P, Google Docs, Zoom) into an LMS with single sign-on and grade passback. LTI 1.3 uses OAuth2 for authentication. Any edtech role requires understanding these three acronyms and which standard solves which problem.

SIS vs LMS — the system boundary

A Student Information System (SIS) manages administrative data — enrollment, timetables, attendance, grades, billing, transcripts. An LMS manages learning delivery — course content, quizzes, discussion forums, assignment submission. They're separate systems that integrate via an API or a standard like OneRoster (CSV/API for syncing roster data between SIS and LMS). ERPNext's Education module is a SIS. Moodle and Canvas are LMSes. Gibbon straddles both for smaller schools. In edtech engineering, the SIS is the source of truth for student identity; the LMS receives roster data from it and publishes grades back.

Accessibility and WCAG compliance

Web Content Accessibility Guidelines (WCAG) 2.1 AA is the standard accessibility target for educational content — legally required in many jurisdictions for public schools. Key criteria relevant to LMS content: sufficient colour contrast (4.5:1 for text), keyboard navigability, alt text for images, captions for videos, and semantic HTML structure. H5P interactive content has variable accessibility — some content types meet WCAG, others don't. Any edtech deployment serving students with disabilities must audit content types. Canvas has stronger built-in accessibility tools than Moodle; Moodle's accessibility depends heavily on the theme and plugins installed.

CalDAV, CardDAV, and school scheduling

School scheduling systems (timetables, room bookings, events) use CalDAV as the standard calendar protocol for exposing data to client apps (iOS Calendar, Google Calendar, Thunderbird). A school server exposes a CalDAV endpoint; student and staff apps subscribe to their personal calendar feeds. The key operational fact: CalDAV is a WebDAV extension — it's stateful HTTP with PROPFIND, REPORT, and PUT methods. Debugging CalDAV sync issues requires reading HTTP traces, not just checking the app. ERPNext and Moodle both expose CalDAV for course events.

FHIR in education — student health records

Schools managing student health data (medications, allergies, immunisations) in a regulated environment increasingly use FHIR (Fast Healthcare Interoperability Resources) for structured health data storage — the same standard used in medical settings. This matters at the intersection of edtech and healthtech, for example in special education systems that store IEP (Individualised Education Plan) health components. Any role building school health record integrations will encounter HL7 FHIR R4.

Moodle

Purpose: The world's most widely deployed open-source Learning Management System (LMS). Supports courses, quizzes, assignments, forums, gradebooks, badges, SCORM packages, H5P interactive content, and deep analytics. Used by universities, schools, and enterprises worldwide.

# ~/moodle/compose.yaml
services:
  moodle:
    image: bitnami/moodle:latest
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - /home/user/moodle/data:/bitnami/moodle:Z
      - /home/user/moodle/moodledata:/bitnami/moodledata:Z
    environment:
      MOODLE_DATABASE_HOST: host.containers.internal
      MOODLE_DATABASE_PORT_NUMBER: 3306
      MOODLE_DATABASE_USER: moodleuser
      MOODLE_DATABASE_PASSWORD: changeme
      MOODLE_DATABASE_NAME: moodle
      MOODLE_SITE_NAME: "My Moodle"
      MOODLE_USERNAME: admin
      MOODLE_PASSWORD: changeme
      MOODLE_EMAIL: admin@example.com
    restart: unless-stopped
cd ~/moodle && podman-compose up -d

Moodle requires a database. Run MariaDB first from the Databases wiki.

Recommended plugins to install via admin panel

  • H5P — rich interactive content (drag-and-drop, interactive videos, flashcards)
  • BigBlueButton — integrated live video conferencing and virtual classrooms
  • Attendance — mark and track student attendance per session
  • Collapsed Topics — cleaner course layout for large courses
  • Boost Union — enhanced Boost theme with extra customisation options

Cron job (required for Moodle background tasks)

# Add to a systemd timer — every minute
podman exec moodle php /opt/bitnami/moodle/admin/cli/cron.php

Common operations

# Run Moodle cron (required — run every minute via systemd timer)
podman exec -u www-data moodle php /bitnami/moodle/admin/cli/cron.php

# Purge all caches
podman exec -u www-data moodle php /bitnami/moodle/admin/cli/purge_caches.php

# Upgrade Moodle database after version update
podman exec -u www-data moodle php /bitnami/moodle/admin/cli/upgrade.php --non-interactive

# Install a plugin from the plugins directory
podman exec -u www-data moodle php /bitnami/moodle/admin/cli/install_plugin.php   --pluginzip=/tmp/myplugin.zip

# Create a new user via CLI
podman exec -u www-data moodle php /bitnami/moodle/admin/cli/create_user.php   --username=newuser --password=changeme --email=user@example.com --firstname=John --lastname=Doe

# View logs
podman logs -f moodle

# Check Moodle status
curl http://localhost:8080/admin/index.php

SCORM, xAPI, and the LMS content standard landscape

SCORM (Sharable Content Object Reference Model) is the legacy e-learning packaging standard — a zip file with HTML, JS, and an XML manifest. The LMS launches SCORM content in an iFrame and receives completion/score data via a JavaScript API. Widely supported but limited: no mobile-first support, requires a browser, and tracking is binary (passed/failed). xAPI (Tin Can) is the modern replacement — sends structured JSON statements (actor, verb, object — "John completed Module 3") to a Learning Record Store (LRS). Moodle supports both. xAPI enables tracking outside the LMS (mobile apps, simulators, on-the-job activities).

Moodle's grading system and gradebook design

Moodle's gradebook aggregates activity grades into course totals using configurable aggregation methods: weighted mean of grades (each activity has a weight), natural weighting (based on max grade points), or highest grade. Grade categories allow grouping activities — "Assignments" (30%), "Quizzes" (40%), "Final Exam" (30%). Grade letters map percentages to letters. A common mistake: setting up a complex gradebook after students have submitted work. Design the gradebook before the course opens — retroactive changes cause visible anomalies in the gradebook.

Single Sign-On in educational platforms

Schools often run multiple systems (Moodle, Nextcloud, Gitea, BigBlueButton) that should share the same login. OIDC (via Authentik or Keycloak) is the modern standard: students log in once, and all SSO-enabled services accept the token. LTI (Learning Tools Interoperability) is the education-specific standard for embedding external tools directly inside Moodle — a quiz tool, a video platform, or a coding environment appears as a Moodle activity, grades flow back automatically, and the student never leaves the LMS. LTI 1.3 uses OAuth2/OIDC under the hood.

Accessibility in e-learning — WCAG and ATAG

WCAG (Web Content Accessibility Guidelines) 2.1 Level AA is the legal requirement in most jurisdictions for educational platforms receiving public funding. Key requirements relevant to LMSes: sufficient colour contrast (4.5:1 for body text), all functionality keyboard-accessible, all images have alt text, all videos have captions, forms have associated labels. Moodle 4.x is largely WCAG 2.1 AA compliant out of the box; third-party themes and plugins may not be. ATAG (Authoring Tool Accessibility Guidelines) additionally requires that the authoring tools (course editors) produce accessible content by default.

---

Canvas LMS

Purpose: Enterprise-grade LMS used by hundreds of universities. Cleaner UI than Moodle, superior mobile apps, strong API, and first-class support for rubrics, SpeedGrader, outcome tracking, and video feedback. Higher resource requirements than Moodle.

# ~/canvas/compose.yaml
services:
  canvas:
    image: instructure/canvas-lms:latest
    ports: ["127.0.0.1:3000:3000"]
    environment:
      CANVAS_LMS_ADMIN_EMAIL: admin@example.com
      CANVAS_LMS_ADMIN_PASSWORD: changeme
      CANVAS_LMS_ACCOUNT_NAME: "My Canvas"
      CANVAS_LMS_STATS_COLLECTION: opt_out
      DATABASE_URL: postgresql://canvas:changeme@db:5432/canvas
      REDIS_URL: redis://redis:6379
    depends_on: [db, redis]
    volumes:
      - /home/user/canvas/uploads:/usr/src/app/tmp/files:Z
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: canvas
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: canvas
    volumes: [pg_data:/var/lib/postgresql/data]
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  pg_data:
cd ~/canvas && podman-compose up -d

Canvas is resource-heavy — plan for at least 4 GB RAM dedicated to the stack.

---

BigBlueButton (Virtual Classroom)

Purpose: Open-source web conferencing designed specifically for education. Features include multi-user whiteboards, breakout rooms, polling, shared notes, learning analytics, recordings with automatic transcription, and deep LMS integration (Moodle, Canvas).

# ~/bbb-demo/compose.yaml
services:
  bbb-demo:
    image: bigbluebutton/demo:latest
    ports:
      - 127.0.0.1:8090:8090
    restart: unless-stopped
cd ~/bbb-demo && podman-compose up -d

BBB needs ports 443/tcp and 16384-32768/udp open for WebRTC media. It works best on a server with at least 8 GB RAM.

---

Greenlight (BigBlueButton Front End)

Purpose: A simple, polished web interface for BigBlueButton. Manages rooms, recordings, and user accounts — without the complexity of a full LMS. Ideal as a standalone virtual meeting room system for schools or teams.

# ~/greenlight/compose.yaml
services:
  greenlight:
    image: bigbluebutton/greenlight:v3
    ports: ["127.0.0.1:5050:80"]
    environment:
      BIGBLUEBUTTON_ENDPOINT: https://bbb.example.com/bigbluebutton/
      BIGBLUEBUTTON_SECRET: your-bbb-secret
      SECRET_KEY_BASE: changeme-run-openssl-rand-hex-64
      DATABASE_URL: postgresql://greenlight:changeme@db:5432/greenlight
    depends_on: [db]
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: greenlight
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: greenlight
    volumes: [pg_data:/var/lib/postgresql/data]
    restart: unless-stopped

volumes:
  pg_data:
cd ~/greenlight && podman-compose up -d

---

ERPNext / Frappe (School ERP)

Purpose: ERPNext includes a full Education module — student admissions, enrollment, fee management, timetables, attendance, assessments, certificates, and parent portals. Built on the Frappe framework, it is a complete school management system alongside a full-featured ERP (HR, payroll, accounts, inventory).

# ~/erpnext/compose.yaml — use the official Frappe Docker setup
# git clone https://github.com/frappe/frappe_docker
# cd frappe_docker
# cp example.env .env
# Edit .env: set FRAPPE_BRANCH=version-15, APPS_JSON_BASE64 to include erpnext

services:
  backend:
    image: frappe/erpnext:v15
    environment:
      DB_HOST: db
      DB_PORT: 3306
      REDIS_CACHE: redis-cache:6379
      REDIS_QUEUE: redis-queue:6379
      SOCKETIO_PORT: 9000
    volumes: [sites:/home/frappe/frappe-bench/sites]
    depends_on: [db, redis-cache, redis-queue]
    restart: unless-stopped

  frontend:
    image: frappe/erpnext:v15
    command: nginx-entrypoint.sh
    ports: ["127.0.0.1:8080:8080"]
    environment:
      BACKEND: backend:8000
      SOCKETIO: websocket:9000
      FRAPPE_SITE_NAME_HEADER: $host
    volumes: [sites:/home/frappe/frappe-bench/sites]
    restart: unless-stopped

  db:
    image: mariadb:10.11
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    environment:
      MYSQL_ROOT_PASSWORD: changeme
    volumes: [mariadb_data:/var/lib/mysql]
    restart: unless-stopped

  redis-cache:
    image: redis:7-alpine
    restart: unless-stopped

  redis-queue:
    image: redis:7-alpine
    restart: unless-stopped

  websocket:
    image: frappe/erpnext:v15
    command: node /home/frappe/frappe-bench/apps/frappe/socketio.js
    volumes: [sites:/home/frappe/frappe-bench/sites]
    restart: unless-stopped

volumes:
  sites:
  mariadb_data:
cd ~/erpnext && podman-compose up -d
Create a new site
podman exec backend bench new-site erp.example.com \
  --mariadb-root-password changeme \
  --admin-password changeme \
  --install-app erpnext \
  --install-app education

---

Gibbon (School Management System)

Purpose: Lightweight, purpose-built school information system. Timetables, attendance, gradebooks, student profiles, parent communication, notices, and planner — all in one. Lower resource footprint than ERPNext; easier to operate for a single school.

# ~/gibbon/compose.yaml
services:
  gibbon:
    image: andrewm/gibbon:latest
    ports: ["127.0.0.1:8082:80"]
    environment:
      DB_HOST: db
      DB_NAME: gibbon
      DB_USERNAME: gibbon
      DB_PASSWORD: changeme
      INSTALL_TYPE: new
    volumes:
      - /home/user/gibbon/uploads:/var/www/html/uploads:Z
      - /home/user/gibbon/private:/var/www/html/private:Z
    depends_on: [db]
    restart: unless-stopped

  db:
    image: mariadb:10.11
    environment:
      MYSQL_DATABASE: gibbon
      MYSQL_USER: gibbon
      MYSQL_PASSWORD: changeme
      MYSQL_ROOT_PASSWORD: rootpass
    volumes: [db_data:/var/lib/mysql]
    restart: unless-stopped

volumes:
  db_data:
cd ~/gibbon && podman-compose up -d

Access at http://localhost:8082. Complete setup via the web installer on first run.

---

Chamilo (LMS / E-Learning)

Purpose: Simple, accessible LMS targeted at schools and training centres in developing regions. Lower resource requirements than Moodle, easier to administer, and multilingual from the ground up. Supports courses, assignments, quizzes, certificates, and social learning tools.

# ~/chamilo/compose.yaml
services:
  chamilo:
    image: chamilo/chamilo:latest
    ports:
      - 127.0.0.1:8083:80
    volumes:
      - /home/user/chamilo/app:/var/www/html/app:Z
      - /home/user/chamilo/web:/var/www/html/web:Z
    environment:
      CHAMILO_DATABASE_HOST: host.containers.internal
      CHAMILO_DATABASE_USER: chamilo
      CHAMILO_DATABASE_PASSWORD: changeme
      CHAMILO_DATABASE_NAME: chamilo
    restart: unless-stopped
cd ~/chamilo && podman-compose up -d

---

Kolibri (Offline Learning)

Purpose: Open-source educational platform from Learning Equality, designed for low-bandwidth and offline use. Hosts Khan Academy content, ebooks, videos, and interactive exercises locally. Ideal for remote schools or learning environments without reliable internet access.

# ~/kolibri/compose.yaml
services:
  kolibri:
    image: learningequality/kolibri:latest
    ports:
      - 127.0.0.1:8090:8080
    volumes:
      - /home/user/kolibri/data:/root/.kolibri:Z
    restart: unless-stopped
cd ~/kolibri && podman-compose up -d

Kolibri can serve an entire classroom over Wi-Fi from a single Raspberry Pi or mini PC — no internet required after content import.

---

Overleaf (Collaborative LaTeX Editor)

Purpose: Self-hosted collaborative LaTeX document editor. Essential for academic writing, research papers, theses, and technical documentation. The Community Edition gives you the same real-time collaborative experience as Overleaf.com, running on your own server.

# ~/overleaf/compose.yaml
services:
  sharelatex:
    image: sharelatex/sharelatex:latest
    ports: ["127.0.0.1:5000:80"]
    environment:
      SHARELATEX_APP_NAME: "Overleaf CE"
      SHARELATEX_MONGO_URL: mongodb://mongo/sharelatex
      SHARELATEX_REDIS_HOST: redis
      SHARELATEX_SITE_URL: https://overleaf.home.local
      SHARELATEX_ADMIN_EMAIL: admin@example.com
    volumes:
      - /home/user/overleaf/data:/var/lib/sharelatex:Z
    depends_on: [mongo, redis]
    restart: unless-stopped

  mongo:
    image: mongo:7
    volumes: [mongo_data:/data/db]
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    restart: unless-stopped

volumes:
  mongo_data:
cd ~/overleaf && podman-compose up -d
Create an admin user
podman exec sharelatex /bin/bash -c \
  "cd /var/www/sharelatex && node modules/server-ce-scripts/scripts/create-user.js \
  --email=admin@example.com --admin"
Install full TeX Live

(optional, adds all LaTeX packages):

podman exec sharelatex tlmgr install scheme-full

---

Anki Sync Server

Purpose: Self-hosted synchronisation server for the Anki flashcard app (desktop and mobile). All your decks, scheduling data, and review history sync between devices through your own server — no AnkiWeb account required.

# ~/anki-sync/compose.yaml
services:
  anki-sync:
    image: noxinc/anki-sync-server:latest   # Official Anki sync server; supports SYNC_USER1
    ports:
      - 127.0.0.1:27701:8080
    volumes:
      - /home/user/anki-sync/data:/anki_data:Z
    environment:
      SYNC_USER1: user:password             # Add more users: SYNC_USER2, SYNC_USER3, …
    restart: unless-stopped
cd ~/anki-sync && podman-compose up -d
Configure Anki desktop

Tools → Preferences → Network → Self-hosted sync server → enter your server URL.

---

ITflow (IT Documentation)

Purpose: IT documentation and ticketing platform popular in school IT departments. Asset tracking, password vault, network documentation, and ticket management — all in one self-hosted tool.

# ~/itflow/compose.yaml
services:
  itflow:
    image: itflow/itflow:latest
    ports: ["127.0.0.1:8091:80"]
    environment:
      DB_HOST: db
      DB_NAME: itflow
      DB_USER: itflow
      DB_PASS: changeme
      APP_URL: https://itflow.home.local
    volumes:
      - /home/user/itflow/uploads:/var/www/html/uploads:Z
      - /home/user/itflow/backups:/var/www/html/backups:Z
    depends_on: [db]
    restart: unless-stopped

  db:
    image: mariadb:10.11
    environment:
      MYSQL_DATABASE: itflow
      MYSQL_USER: itflow
      MYSQL_PASSWORD: changeme
      MYSQL_ROOT_PASSWORD: rootpass
    volumes: [db_data:/var/lib/mysql]
    restart: unless-stopped

volumes:
  db_data:
cd ~/itflow && podman-compose up -d

---

H5P (Interactive Learning Content)

Purpose: Create rich, interactive HTML5 learning content — quizzes, drag-and-drop exercises, interactive videos, flashcards, branching scenarios, and 50+ other content types — without writing code. H5P content runs in the browser and integrates directly with Moodle, Canvas, and Open edX as a plugin. The standalone server lets you host H5P content independently and embed it in any website via iframes.

# ~/h5p/compose.yaml
services:
  h5p:
    image: tutor/h5p:latest
    ports:
      - 127.0.0.1:8100:8080
    volumes:
      - /home/user/h5p/content:/var/www/html/content:Z
      - /home/user/h5p/libraries:/var/www/html/libraries:Z
    environment:
      H5P_EDITOR_DOMAIN: h5p.home.local
    restart: unless-stopped
cd ~/h5p && podman-compose up -d

Access at http://localhost:8100. Download H5P content types from the H5P Hub (built into the editor), create content, and embed it in any LMS or web page:

<iframe src="https://h5p.home.local/h5p/embed/1"
  width="800" height="450" frameborder="0" allowfullscreen>
</iframe>

For Moodle integration, install the H5P plugin from the Moodle Plugin Directory — no separate container needed. The standalone server is useful when you want to embed H5P content in non-LMS sites (WordPress, Ghost, custom apps).

---

Caddy Configuration

moodle.home.local      { tls internal; reverse_proxy localhost:8080 }
canvas.home.local      { tls internal; reverse_proxy localhost:3000 }
bbb.example.com        { reverse_proxy localhost:8090 }
greenlight.home.local  { tls internal; reverse_proxy localhost:5050 }
erp.home.local         { tls internal; reverse_proxy localhost:8080 }
kolibri.home.local     { tls internal; reverse_proxy localhost:8090 }
overleaf.home.local    { tls internal; reverse_proxy localhost:5000 }
anki.home.local        { tls internal; reverse_proxy localhost:27701 }
h5p.home.local         { tls internal; reverse_proxy localhost:8100 }

---

Choosing the Right Stack

| Scenario | Recommended Stack | |----------|------------------| | University-scale MOOC platform | Open edX (Tutor) | | School or training centre LMS | Moodle (with H5P + BBB) | | Cleaner LMS with great mobile apps | Canvas LMS | | Virtual classrooms only | BigBlueButton + Greenlight | | Full school ERP (fees, timetables, HR) | ERPNext Education | | Lightweight school admin (single school) | Gibbon | | Offline / low-bandwidth classrooms | Kolibri | | Academic writing (LaTeX) | Overleaf CE | | Flashcard sync | Anki Sync Server |

---

Troubleshooting

| Issue | Solution | |-------|----------| | Moodle cron not running | Verify the cron command runs as the correct user inside the container; check Site Administration → Server → Cron for last run time | | Moodle Cannot connect to database | Confirm MariaDB is running and MOODLE_DATABASE_HOST uses host.containers.internal not localhost | | Canvas asset pipeline errors | Ensure the uploads volume has write permissions; run podman exec canvas bundle exec rake canvas:compile_assets | | Open edX Tutor launch fails | Check Docker/Podman socket is accessible; run tutor local logs for errors; ensure at least 4 GB RAM free | | BigBlueButton WebRTC fails | Verify 16384-32768/udp is open in firewalld; BBB requires a real public IP or TURN server for NAT traversal | | ERPNext site not loading | Check all services are up with podman-compose ps; run bench clear-cache inside the backend container | | Overleaf PDF compilation fails | TeX Live may be incomplete — install scheme-full via tlmgr install scheme-full inside the container | | Kolibri import fails | Ensure outbound internet access is available during importchannel; check disk space (channels can be several GB) | | Anki sync AuthFailed | Verify username/password in SYNC_USER1 matches exactly what the client sends; Anki is case-sensitive |

💡 Tip: For Moodle and Canvas, enable Redis as a caching backend (set under config.php$CFG->cache_*) to significantly improve page load times and handle more concurrent users.

| H5P content type missing | Download content types from the H5P Hub inside the editor — libraries must be installed before content of that type can be created | | H5P iframe not loading | Ensure H5P_EDITOR_DOMAIN matches the domain used in the iframe src; check CSP headers aren't blocking the embed |