Deploying an IOMAD App
Introduction
IOMAD is an open-source multi-tenant LMS built on Moodle. Deploying IOMAD with a Dockerfile on Klutch.sh gives you reproducible builds, managed secrets, and durable storage for course content and user uploads—all managed from klutch.sh/app. This guide covers installation, repository prep, a production-ready Dockerfile, deployment steps, Nixpacks overrides, and best practices for enterprise learning environments.
Prerequisites
- A Klutch.sh account (create one)
- A GitHub repository containing your IOMAD/Moodle code (GitHub is the only supported git source)
- Docker and PHP familiarity (IOMAD typically uses PHP-FPM/Apache with MySQL or MariaDB)
- Database credentials (MySQL/MariaDB) and optional Redis cache endpoint
- Optional object storage for large file backups
For basics on connecting GitHub, review the Quick Start.
Architecture and ports
- Serve IOMAD over HTTP; set the internal container port to
8080. - Run MySQL/MariaDB (and Redis if used) as separate Klutch.sh TCP apps. Expose them on port
8000and connect internally on their native ports (3306for MySQL/MariaDB,6379for Redis). - Persistent storage is required for
moodledataand recommended for logs.
Repository layout
iomad/├── config.php.example # Template config├── moodledata/ # Must be on persistent storage├── local/ # Custom plugins├── theme/ # Custom themes├── Dockerfile # Must be at repo root for auto-detection├── composer.json # If using Composer-managed plugins└── README.mdKeep secrets out of Git; manage them via Klutch.sh environment variables.
Installation (local) and starter commands
Install dependencies and run IOMAD locally before pushing to GitHub:
php admin/cli/checks.phpphp admin/cli/install.php --chmod=2770 \ --lang=en \ --wwwroot=http://localhost:8080 \ --dataroot=/var/www/html/moodledata \ --dbtype=mysqli --dbhost=localhost --dbname=iomad --dbuser=iomad --dbpass=secret \ --fullname="IOMAD" --shortname="IOMAD" --adminuser=admin --adminpass=AdminPass123!php -S 0.0.0.0:8080 -t .Optional helper start.sh for portability and Nixpacks fallback:
#!/usr/bin/env bashset -euo pipefailphp admin/cli/upgrade.php --non-interactiveexec php -S 0.0.0.0:8080 -t .Make it executable with chmod +x start.sh.
Dockerfile for IOMAD (production-ready)
Place this Dockerfile at the repository root; Klutch.sh auto-detects it (no Docker selection in the UI):
FROM php:8.2-apache
RUN apt-get update && apt-get install -y \ libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libicu-dev libxml2-dev libonig-dev \ ghostscript graphviz aspell git unzip && \ docker-php-ext-configure gd --with-freetype --with-jpeg && \ docker-php-ext-install gd intl zip mysqli opcache soap xml && \ a2enmod rewrite && \ rm -rf /var/lib/apt/lists/*
WORKDIR /var/www/html
# Copy applicationCOPY . /var/www/html
# Moodle/IOMAD needs a writable dataroot; keep it on a volumeRUN mkdir -p /var/www/html/moodledata && chown -R www-data:www-data /var/www/html
ENV APACHE_DOCUMENT_ROOT=/var/www/html \ MOODLE_DOCKER_WWWROOT=/var/www/html \ PORT=8080
EXPOSE 8080CMD ["apache2-foreground"]Notes:
- Pin PHP and extension versions to match your IOMAD release.
- If you front with Nginx + PHP-FPM, swap the base image and keep
EXPOSE 8080consistent.
Environment variables (Klutch.sh)
Set these in the Klutch.sh app settings (Secrets tab) before deploying:
PORT=8080MOODLE_DOCKER_WWWROOT=/var/www/htmlMOODLE_DOCKER_DATAROOT=/var/www/html/moodledataDB_TYPE=mysqliDB_HOSTDB_PORT=3306DB_NAMEDB_USERDB_PASSSSLPROXY=true(if terminating TLS before the app)REDIS_HOSTandREDIS_PORT(if using Redis)PHP_MEMORY_LIMIT=512M(optional)
If you deploy without a Dockerfile and want Nixpacks overrides:
NIXPACKS_BUILD_CMD=composer install --no-dev --optimize-autoloaderNIXPACKS_START_CMD=php -S 0.0.0.0:8080 -t .NIXPACKS_INSTALL_PKGS="php82 php82Extensions.pdo_mysql php82Extensions.intl php82Extensions.gd php82Extensions.zip"
These keep IOMAD compatible with the Nixpacks build pipeline when a Dockerfile is absent.
Attach persistent volumes
In Klutch.sh storage settings, add mount paths and sizes (no volume names required):
/var/www/html/moodledata— mandatory for file storage, cache, and sessions./var/www/html/theme— optional if you manage custom themes at runtime./var/www/html/local— optional for runtime-installed plugins.
Ensure these paths are writable by the web user inside the container.
Deploy IOMAD on Klutch.sh (Dockerfile workflow)
- Push your repository (with the Dockerfile at the root) to GitHub.
- Open klutch.sh/app, create a project, and add an app.
- Connect the GitHub repository; Klutch.sh automatically detects the Dockerfile.
- Choose HTTP traffic for IOMAD.
- Set the internal port to
8080. - Add the environment variables above (database, Redis, Moodle/IOMAD settings, and any
NIXPACKS_*overrides if you temporarily deploy without the Dockerfile). - Attach persistent volumes for
moodledata(andtheme/localif needed), choosing sizes that fit your content. - Deploy. Your LMS will be reachable at
https://example-app.klutch.sh; attach a custom domain if desired.
For MySQL/MariaDB or Redis on Klutch.sh, create separate TCP apps, expose them on port 8000, and point DB_HOST or REDIS_HOST to those endpoints (internal ports 3306/6379).
Health checks and production tips
- Add a lightweight
/healthendpoint or use Moodle’s built-in status checks for monitoring. - Back up the database and
moodledataregularly; do not rely on container filesystems for durability. - Pin PHP and dependency versions; avoid unexpected upgrades between deploys.
- Enable HTTPS at the edge; set
SSLPROXY=truewhen traffic is terminated before reaching the app. - Monitor disk usage on volumes and resize before they fill.
IOMAD on Klutch.sh combines reproducible Docker builds with managed secrets, persistent volumes for moodledata, and flexible HTTP/TCP routing. With the Dockerfile at the repo root and ports set to 8080 for the app (8000 externally for TCP databases or caches), you can deliver multi-tenant learning experiences reliably without extra YAML or workflow overhead.