TutorLoom

Self-hosted learning platform for institutes and training teams.

  • ghcr.io/hsinghhira/tutorloom:latest
  • v1.0.0
  • Updated 30 Oct 2026
  • port 6177
  • amd64
  • Productivity
  • 53 stars

Screenshots

TutorLoom screenshot 1: Institute admin dashboardTutorLoom screenshot 2: Course builderTutorLoom screenshot 3: Trainer dashboardTutorLoom screenshot 4: Student dashboardTutorLoom screenshot 5: Course roadmapTutorLoom screenshot 6: Progress and certificates

Open the app

Web App

http://localhost:6177/

API Docs

http://localhost:6177/api/docs/

Django Admin

http://localhost:6177/admin/

About TutorLoom

TutorLoom is a learning management system (LMS) for training institutes and teams: build courses, enrol learners in batches, grade their work and follow their progress. This is TutorLoom in a single container, with the Django API, the background worker, the web app, PostgreSQL and Redis inside, one port and one data folder. The secret key, database passwords and the first admin account are made for you on first start.

Features

  • Course builder with levels, chapters and steps: videos, documents, tasks and quizzes, with prerequisites
  • Batches of learners, with invites one by one or in bulk from CSV or Excel
  • Portals for institute admins, trainers and students
  • Grading queue with scores and written feedback, progress export to Excel and certificates
  • Many organizations in one install, each with its own people and courses
  • REST API with Swagger docs at /api/docs/

How to use

  1. Open TutorLoom from your dashboard.
  2. Sign in with ADMIN_EMAIL and the password from the app logs (the line "TutorLoom login is").
  3. Add trainers and students, make courses in the course builder and put learners in batches.
  4. Trainers grade submissions; students follow their roadmap.
  5. The Django admin is at http://[ZIMAOS-IP-ADDRESS]:6177/admin/, with the same login.

Before you install

Set ADMIN_EMAIL to your own email first: on the first start it becomes the admin of a new organization (named by TUTORLOOM_ORG_NAME, "My Academy" if you leave it out). Leave ADMIN_PASSWORD empty to get a new password; it is in the app logs on the line "TutorLoom login is" and in admin-password.txt in the data folder. PUBLIC_URL starts as http://localhost:6177; change localhost to your ZimaOS IP, like http://192.168.1.20:6177, so links in invite emails work on other devices. The web app itself opens from any address. Until you add email settings, invite and password-reset emails are only written to the app logs. The first start takes about three minutes. Email, S3 storage and the other settings are in the Variables tab; add them in the app settings. The image is amd64 only.

The settings in the first table are already in the app settings. To use any other one, open the app settings, add the variable with your value, save, and the app restarts with it. A setting you leave out uses its default.

In the app settings

VariableDefault valueDescription
TZ$TZYour time zone. It is filled in from your ZimaOS time zone. Leave it unless you need another.
PUBLIC_URLhttp://localhost:6177The address you open TutorLoom at, like http://192.168.1.20:6177. Used for the links in invite and password-reset emails. Change localhost to your ZimaOS IP so those links work from other devices.
ADMIN_EMAIL[email protected]Your email. It becomes the first admin account (Institute Admin and Django admin). Set it before the first start.
ADMIN_PASSWORD—The password for that account. Leave it empty and one is made for you; it is in the app logs on the line "TutorLoom login is". Only used on the first start.

First start

VariableDefault valueDescription
TUTORLOOM_ORG_NAMEMy AcademyThe name of the first organization. Only used on the very first start; rename it later in TutorLoom.
TUTORLOOM_BATCH_NAMEBatch 1The name of the first batch of learners. Only used on the very first start.

Email (SMTP)

VariableDefault valueDescription
EMAIL_HOST—Your mail server, like smtp.gmail.com. Leave it out to only write emails to the app logs.
EMAIL_PORT587Your mail server's port.
EMAIL_USE_TLSTrueSet to False for a mail server without STARTTLS.
EMAIL_HOST_USER—The user name for your mail server.
EMAIL_HOST_PASSWORD—The password for your mail server.
DEFAULT_FROM_EMAIL[email protected]The sender address on invite and password-reset emails.

Email (Amazon SES)

VariableDefault valueDescription
AWS_SES_ACCESS_KEY_ID—An Amazon SES access key, to send emails through SES instead of SMTP.
AWS_SES_SECRET_ACCESS_KEY—The Amazon SES secret key.
AWS_SES_REGIONap-south-1The Amazon SES region, like us-east-1.

File storage

VariableDefault valueDescription
USE_S3FalseSet to True to keep uploads in Amazon S3 instead of the data folder.
AWS_S3_ACCESS_KEY_ID—The S3 access key, when USE_S3 is True.
AWS_S3_SECRET_ACCESS_KEY—The S3 secret key.
AWS_STORAGE_BUCKET_NAME—The S3 bucket name.
AWS_S3_REGION_NAMEap-south-1The S3 region, like us-east-1.

Security

VariableDefault valueDescription
THROTTLE_RATE_LOGIN5/minuteHow many sign-in tries one address may make, like 10/minute.
THROTTLE_RATE_PASSWORD_RESET_EMAIL5/hourHow many password-reset emails one address may ask for.
THROTTLE_RATE_AUTH_TOKEN10/minuteHow often one address may renew its sign-in token.
ALLOWED_HOSTS*The addresses TutorLoom may be opened at, comma separated, like lms.example.com,192.168.1.20. Leave it out to allow any address.
NUM_PROXIES1How many reverse proxies are in front of TutorLoom, counting the one inside the container. Set to 2 behind your own proxy, so sign-in limits see the real visitor address.

Performance

VariableDefault valueDescription
TUTORLOOM_WEB_WORKERS3How many web processes answer requests. Raise it for many people at once; each one needs about 100 MB of memory.
TUTORLOOM_WORKER_CONCURRENCY2How many background jobs (bulk uploads, emails, certificates) run at once.
docker-compose.yml
name: tutorloom

services:
  tutorloom:
    image: ghcr.io/hsinghhira/tutorloom:latest
    container_name: tutorloom
    restart: unless-stopped
    stop_grace_period: 90s
    privileged: true
    environment:
      - TZ=$TZ
      - PUBLIC_URL=http://localhost:6177
      - [email protected]
      - ADMIN_PASSWORD=
    ports:
      - target: 8080
        published: "6177"
        protocol: tcp
    volumes:
      - type: bind
        source: /DATA/AppData/$AppID/data
        target: /data
        bind:
          create_host_path: true
    healthcheck:
      test: ["CMD", "curl", "-fsS", "-o", "/dev/null", "http://127.0.0.1:8080/admin/login/"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 180s
    deploy:
      resources:
        limits:
          cpus: "2.00"
          memory: 2048M
        reservations:
          cpus: "0.25"
          memory: 512M
    labels:
      icon: https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/icon.png
    x-casaos:
      id: com.icestore.tutorloom
      envs:
        - container: TZ
          description:
            en_US: >-
              Your time zone. It is filled in from your ZimaOS time zone.
              Leave it unless you need another.
        - container: PUBLIC_URL
          description:
            en_US: >-
              The address you open TutorLoom at, like http://192.168.1.20:6177.
              Used for the links in invite and password-reset emails. Change
              localhost to your ZimaOS IP so those links work from other
              devices.
        - container: ADMIN_EMAIL
          description:
            en_US: >-
              Your email. It becomes the first admin account (Institute Admin
              and Django admin). Set it before the first start.
        - container: ADMIN_PASSWORD
          description:
            en_US: >-
              The password for that account. Leave it empty and one is made
              for you; it is in the app logs on the line "TutorLoom login is".
              Only used on the first start.
      ports:
        - container: "8080"
          description:
            en_US: TutorLoom web app, API (/api), API docs (/api/docs/) and Django admin (/admin/), published on host as 6177
      volumes:
        - container: /data
          description:
            en_US: >-
              The database (organizations, courses, people, progress),
              uploads in media/, Redis data, secret keys
              (state/secrets.env) and the first password
              (admin-password.txt). Back it up.

x-casaos:
  id: com.icestore.tutorloom
  architectures:
    - amd64
  main: tutorloom
  author: HSinghHira
  category: Productivity
  developer: Pace Wisdom
  icon: https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/icon.png
  thumbnail: https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-1.png
  screenshot_link:
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-1.png
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-2.png
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-3.png
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-4.png
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-5.png
    - https://cdn.jsdelivr.net/gh/HSinghHira/IceStore@main/Apps/tutorloom/screenshot-6.png
  title:
    en_US: TutorLoom
  tagline:
    en_US: Self-hosted learning platform for institutes and training teams.
  description:
    en_US: >-
      Visit: [https://icestore.hsinghhira.me/app/tutorloom/](https://icestore.hsinghhira.me/app/tutorloom/) for full details


      TutorLoom is a learning management system (LMS) for training
      institutes and teams: build courses, enrol learners in batches, grade
      their work and follow their progress. This is TutorLoom in a single
      container, with the Django API, the background worker, the web app,
      PostgreSQL and Redis inside, one port and one data folder. The secret
      key, database passwords and the first admin account are made for you
      on first start.


      **Features**


      - Course builder with levels, chapters and steps: videos, documents,
        tasks and quizzes, with prerequisites

      - Batches of learners, with invites one by one or in bulk from CSV or
        Excel

      - Portals for institute admins, trainers and students

      - Grading queue with scores and written feedback, progress export to
        Excel and certificates

      - Many organizations in one install, each with its own people and
        courses

      - REST API with Swagger docs at /api/docs/


      **How to use?**


      1. Open TutorLoom from the Zima OS dashboard.

      2. Sign in with ADMIN_EMAIL and the password from the app logs (the
         line "TutorLoom login is").

      3. Add trainers and students, make courses in the course builder and
         put learners in batches.

      4. Trainers grade submissions; students follow their roadmap.
  tips:
    before_install:
      en_US: >-
        1. Open the app configuration before you install.


        2. Change ADMIN_EMAIL to your own email. It becomes the first admin
           account.


        3. Leave ADMIN_PASSWORD empty to get a new password, or type your
           own.


        4. Find PUBLIC_URL. It starts as http://localhost:6177. Change
           localhost to your ZimaOS IP, like http://192.168.1.20:6177, so
           links in emails work on other devices.


        5. Emails are only written to the app logs at first. To send real
           emails, add the email settings. They are listed on the TutorLoom
           page at https://icestore.hsinghhira.me/app/tutorloom/ (Variables
           tab), with the name of your first organization and other
           settings. You can add them now or later in the app settings.


        6. Start the installation.


        7. Wait about three minutes. The first start sets up the database.


        8. Open the app logs and find the line that says "TutorLoom login
           is". It shows your email and the password.


        9. Open http://[ZIMAOS-IP-ADDRESS]:6177 and sign in with them.


        10. The Django admin is at http://[ZIMAOS-IP-ADDRESS]:6177/admin/,
            with the same login.
  index: /
  port_map: "6177"
  scheme: http
  is_uncontrolled: false
  version: "v1.0.0"
  update_at: "2026-10-30"
  release_notes:
    en_US: |-
      - First version in IceStore, on port 6177
      - Single container: TutorLoom's Django API (gunicorn), Celery worker and web app, with PostgreSQL 16 and Redis inside
      - Built from upstream release v1.0.0 (upstream publishes no image), on python 3.14.10-slim and node 22.23.4-slim
      - Database migrations run on every start; the first organization, batch and admin account are made on the first start
      - Secret key and database passwords are made on first start and kept in /data/state/secrets.env
      - The web app calls the API on the same address, so it works from any address you open it at
      - amd64 only for now: the Python build is too slow and fragile under arm64 emulation
      - Left out: the mobile app (build it from upstream's student_mobile_app folder and point it at this server)
  repo: "https://github.com/pacewisdomhq/TutorLoom"
  support: "https://github.com/pacewisdomhq/TutorLoom/issues"
  docs: "https://github.com/pacewisdomhq/TutorLoom#readme"

Install TutorLoom

Something not working with TutorLoom? Report a problem or request another app.

More Productivity apps

See all