Web interface to manage multiple Moodle development instances without touching a single environment variable.
Built on top of moodle-docker by MoodleHQ.
Vibe coding disclosure — This project was built with Claude Code (Anthropic) using a vibe coding approach: the architecture, features and code were developed through a conversational flow with an AI assistant. The codebase is fully readable and maintained by humans, but I want to be transparent about how it was created.
Moodle Manager is a web-based control panel that sits on top of moodle-docker. Instead of remembering which environment variables to set, which .yml files to combine, or which commands to run, everything is done from a clean browser interface.
It is designed for development teams working with multiple Moodle versions in parallel — different PHP versions, databases, testing configurations — all running simultaneously on the same machine.
This project does not replace moodle-docker. It requires it. moodle-docker must be cloned on the host machine and Moodle Manager will use it as the base to build and run all instances.
This project is a wrapper around moodle-docker, the official Docker setup for Moodle developers maintained by MoodleHQ.
moodle-docker provides:
- The
moodlehq/moodle-php-apacheDocker images for each PHP version - A modular set of Compose files (
base.yml,db.pgsql.yml,service.mail.yml, etc.) - The
config.docker-template.phpused to configure each Moodle instance
Moodle Manager reads the path to your local moodle-docker clone and dynamically assembles the right docker compose -f ... commands and environment variables for each instance you create.
| Category | Feature |
|---|---|
| Instances | Create, edit and delete instances with a guided form |
| Control | Start, stop, destroy and restart containers with one click |
| Monitoring | Dashboard with real-time status, auto-refresh every 6 s |
| Logs | Live log streaming (SSE) for any service (webserver, db, selenium, mailpit) |
| Terminal | Interactive bash terminal to the webserver container from the browser |
| Moodle actions | Install database, init PHPUnit/Behat, purge caches |
| Xdebug | Install, enable and disable Xdebug for any PHP version (2.x and 3.x handled automatically) |
| Containers | Active containers view with status and mapped ports |
| Multi-instance | Run as many instances as your machine allows, each fully isolated |
Backend → Python 3.12 + FastAPI + Uvicorn
Frontend → HTMX 2.0 + Alpine.js + Tailwind CSS
Terminal → xterm.js (WebSocket)
Logs → Server-Sent Events (SSE)
Docker → Python docker SDK + Docker CLI
Data → JSON (data/instances.json)
- Docker with the Compose v2 plugin (
docker compose) - moodle-docker cloned on the host machine
- Moodle source code available on the host (one directory per instance/version)
# 1. Clone this repository
git clone https://github.com/jjgalvezmolinero/moodle-manager.git
cd moodle-manager
# 2. Start the manager
docker compose up -d --build
# 3. Open in the browser
open http://localhost:9000Then go to Settings and set the path to your moodle-docker clone. After that, create your first instance.
When you create an instance you need to provide:
| Field | Description | Example |
|---|---|---|
| moodle-docker path | Path to the moodle-docker repo on the host | /home/user/moodle-docker |
| MOODLE_DOCKER_WWWROOT | Path to the Moodle source code | /home/user/moodle42 |
| COMPOSE_PROJECT_NAME | Unique prefix for the Docker containers | moodle42 |
| Web port | HTTP port to access Moodle | 8042 |
| PHP version | PHP version to use | 8.3 |
| Database | Database engine | pgsql, mariadb, mysql... |
All other options (Xdebug, Selenium, PHPUnit external services, BBB mock, Mailpit, etc.) are optional and can be changed at any time by editing the instance.
moodle-docker does not include Xdebug in its base images. Moodle Manager handles this by providing an Install Xdebug action that runs inside the running webserver container:
- Updates the PECL channel
- Installs the right Xdebug version for your PHP version:
- PHP ≥ 8.0 →
xdebug(3.x latest) - PHP 7.3–7.4 →
xdebug-3.1.6 - PHP 7.0–7.2 →
xdebug-2.9.8 - PHP 5.6 →
xdebug-2.5.5
- PHP ≥ 8.0 →
- Writes the config (mode, client host, port) to the PHP ini file
- Restarts Apache
Note: the installation is lost when the container is destroyed (
down). It persists acrossstop/start.
┌─────────────────────────────────────────────┐
│ Moodle Manager │
│ (Docker container) │
│ │
│ FastAPI ──► compose.py ──► docker compose │
│ │ │
└────────────────────────────────────┼────────┘
│ /var/run/docker.sock
▼
Docker daemon (host)
│
┌────────────────┼────────────────┐
▼ ▼ ▼
webserver_1 webserver_2 webserver_3
db_1 db_2 db_3
... ... ...
The manager mounts the host Docker socket (/var/run/docker.sock), allowing it to run docker compose commands that execute directly on the host daemon. Paths (moodle-docker, wwwroot) are resolved on the host filesystem, so they must exist there.
The /home directory is also mounted inside the container so that all path checks and file operations work correctly against the host filesystem.
moodle-manager/
├── Dockerfile
├── compose.yml
├── requirements.txt
├── data/
│ ├── instances.json # Instance persistence (auto-generated)
│ └── overrides/ # Generated compose files (xdebug, etc.)
└── app/
├── main.py # FastAPI routes
├── models.py # Pydantic models
├── store.py # JSON CRUD
├── compose.py # docker compose command builder + SSE logs
├── docker_ops.py # Docker SDK (status, containers, exec)
└── templates/
├── base.html # Main layout + toasts + modal
├── index.html # Dashboard
├── form.html # Create / edit instance
├── instance.html # Instance detail (tabs: containers, logs, terminal, actions)
├── settings.html # Global settings
└── fragments/
└── containers.html # Containers table (HTMX fragment)
| Variable | Default | Description |
|---|---|---|
DATA_DIR |
/data |
Directory where instances.json is persisted |
cd app
pip install -r ../requirements.txt
DATA_DIR=../data uvicorn main:app --reload --port 9000Requires docker CLI in PATH and access to the host Docker socket.
- Authentication — Login with username/password configured via environment variables
- Async operations — Job ID + real-time progress for
upandpull - Operation history — Action log per instance
- Dark mode — Toggle with persistent preference
- Search and filter on the dashboard
- Container metrics — Real-time CPU and memory usage
- SQLite migration — To replace JSON as data volume grows
- Backup/restore — Export and import configurations as JSON
- Remote agents — Lightweight API running on each remote host
- Multi-host dashboard — Unified view of instances across all machines
- Remote deployment — Start/stop instances on remote hosts
AGPL-3.0 — see LICENSE for details.