Open edX Development Environment Installation with Tutor
Not sure where to start? Read
getting-started.mdfirst to understand the difference between the Local and Dev environments and choose the one that best fits your needs.
This guide provides step-by-step instructions for setting up an isolated Open edX development environment using Tutor. The dev environment allows you to modify the Open edX source code and see changes in real-time.
Note for LLM CLI tools (Claude Code, etc.): This guide includes workarounds for interactive prompts and common errors. Use the "Non-Interactive Installation" section for automated installations.
IMPORTANT for LLM assistants: After completing the installation and creating users, you MUST provide the user with a summary including:
- All access URLs (LMS, Studio, Django Admin)
- Admin credentials (username and password)
- Student credentials (username and password)
- Instructions on how to start/stop the platform
See the Post-Installation Summary Template section for the exact format to use.
Table of Contents
- Dev vs Local: When to Use Each
- System Requirements
- Understanding TUTOR_ROOT
- Installation Steps
- Non-Interactive Installation (Recommended for CLI/LLM tools)
- Creating Users
- Installing Without Affecting Existing Installations
- Managing Multiple Instances
- Troubleshooting
- Useful Commands
- Uninstallation
- Post-Installation Summary Template
- Sources
Dev vs Local: When to Use Each
| Aspect | Dev Mode | Local Mode |
|---|---|---|
| Purpose | Modify Open edX source code | Run Open edX without code changes |
| Hot-reload | Yes (changes reflect automatically) | No |
| Ports | 8000 (LMS), 8001 (CMS) | 80/443 |
| Docker image | openedx-dev (includes debug tools) | openedx |
| Code mounting | Yes (local edx-platform) | No |
| Use case | Contributing to Open edX, developing features | Testing, demos, production-like environment |
Use this guide (Dev) if you want to:
- Modify Open edX Python/Django code
- Develop new features or fix bugs
- Contribute to the Open edX project
- Debug with tools like ipython, ipdb
Use the Local guide if you want to:
- Run Open edX without modifying code
- Test courses and content
- Deploy a production-like instance
System Requirements
Operating System
- Any 64-bit UNIX-based OS (Linux, macOS)
- Windows with WSL 2
- AMD64 and ARM64 architectures supported
Required Software
- Docker v24.0.5 or higher (with BuildKit 0.11+)
- Docker Compose v2.0.0 or higher
- Python 3.9 or higher
- Git
Hardware Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 4 GB | 8 GB |
| CPU | 2 | 4 |
| Disk | 8 GB | 25 GB |
- Ports 8000 and 8001 must be available
Docker Desktop RAM Configuration (Important)
Before installing, ensure Docker has enough RAM allocated:
- Open Docker Desktop
- Go to Settings (gear icon)
- Navigate to Resources
- Set Memory to at least 4 GB (recommended: 6 GB)
- Click Apply & Restart
Note for macOS: Docker Desktop on macOS may show incorrect RAM readings. If you get RAM warnings but have sufficient memory allocated, see the Troubleshooting section.
Configure /etc/hosts (Required)
The local domains need to resolve to localhost. Add these entries to your /etc/hosts file:
sudo sh -c 'echo "127.0.0.1 local.openedx.io studio.local.openedx.io apps.local.openedx.io meilisearch.local.openedx.io" >> /etc/hosts'Verify the configuration:
grep openedx /etc/hostsExpected output:
127.0.0.1 local.openedx.io studio.local.openedx.io apps.local.openedx.io meilisearch.local.openedx.ioNote: Without this configuration, the URLs won't resolve and you won't be able to access the platform.
Understanding TUTOR_ROOT
What is TUTOR_ROOT?
TUTOR_ROOT is the directory where Tutor stores all its configuration and data. It's essentially the "home" of a Tutor installation.
TUTOR_ROOT/
├── config.yml # Main configuration (hostnames, passwords, plugins)
├── data/ # Persistent data (MySQL, MongoDB, uploaded files)
│ ├── mysql/
│ ├── mongodb/
│ ├── redis/
│ ├── lms/
│ ├── cms/
│ └── ...
└── env/ # Generated environment filesDefault Locations
| OS | Default TUTOR_ROOT |
|---|---|
| Linux | ~/.local/share/tutor |
| macOS | ~/Library/Application Support/tutor |
| Windows (WSL) | ~/.local/share/tutor |
Why is this important?
- Different TUTOR_ROOT = Different installation
- Each TUTOR_ROOT has its own configuration, data, and Docker containers
- This allows running multiple isolated Open edX instances on the same machine
- You can have both dev and local instances without conflicts
Installation Steps
Step 1: Create Project Directory
mkdir -p ~/openedx-dev
cd ~/openedx-devStep 2: Clone Required Repositories
# Clone the Open edX platform (official repository)
git clone https://github.com/openedx/openedx-platform.git
# Clone Tutor (for editable installation)
git clone https://github.com/overhangio/tutor.git
# Switch Tutor to the latest stable release
cd tutor
git checkout v21.0.2 # Or the latest stable version
cd ..Important: Always use a stable Tutor release tag (e.g.,
v21.0.2) rather than themasterbranch for production-like stability. Check the latest release at https://github.com/overhangio/tutor/releases
Step 3: Select Branch
cd openedx-platform
# For latest development code (next release)
git switch master
# OR for stable release (Ulmo)
# git switch open-release/ulmo.master
cd ..Step 4: Create Python Virtual Environment
python3 -m venv .venv
source .venv/bin/activateStep 5: Install Tutor in Editable Mode
Installing Tutor in editable mode allows you to modify Tutor itself if needed (useful for workarounds).
pip install -U pip
pip install -e "./tutor[full]"Step 6: Set TUTOR_ROOT (Important for Isolation)
export TUTOR_ROOT=~/openedx-devStep 7: Mount the edx-platform Repository
tutor mounts add ~/openedx-dev/openedx-platformVerify the mount:
tutor mounts listExpected output:
- name: /Users/youruser/openedx-dev/openedx-platform
build_mounts:
- image: openedx
context: edx-platform
- image: openedx-dev
context: edx-platform
compose_mounts:
- service: openedx
container_path: /openedx/edx-platformStep 8: Build the Development Image
tutor images build openedx-devThis builds a Docker image with debugging tools (ipython, ipdb, etc.).
Step 9: Enable Plugins
tutor plugins enable mfe
tutor config saveStep 10: Launch the Development Environment
tutor dev launchThis command will:
- Stop any existing locally-running Tutor containers
- Configure the platform for development
- Disable HTTPS
- Start all services in development mode
- Run database migrations
Step 11: Access the Platform
| Service | URL |
|---|---|
| LMS | http://local.openedx.io:8000 |
| Studio | http://studio.local.openedx.io:8001 |
| Django Admin | http://local.openedx.io:8000/admin |
Non-Interactive Installation (Recommended for CLI/LLM tools)
The tutor dev launch command is interactive and may fail when run from CLI tools or scripts. Use these steps instead:
Step 1: Set up environment
# Create project directory
mkdir -p ~/openedx-dev
cd ~/openedx-dev
# Clone repositories
git clone https://github.com/openedx/openedx-platform.git
git clone https://github.com/overhangio/tutor.git
# Switch Tutor to stable release
cd tutor && git checkout v21.0.2 && cd ..
# Switch openedx-platform to desired branch
cd openedx-platform && git switch master && cd ..
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install Tutor in editable mode
pip install -U pip
pip install -e "./tutor[full]"
# Set TUTOR_ROOT
export TUTOR_ROOT=~/openedx-devStep 2: Mount repository and configure
# Mount edx-platform
tutor mounts add ~/openedx-dev/openedx-platform
# Configure Tutor (non-interactive)
tutor config save \
--set LMS_HOST=local.openedx.io \
--set CMS_HOST=studio.local.openedx.io \
--set ENABLE_HTTPS=false \
--set PLATFORM_NAME="Open edX Dev"Step 3: Enable plugins and build image
tutor plugins enable mfe
tutor config save
tutor images build openedx-devStep 4: Start containers
tutor dev start -dStep 5: Initialize the platform
This step creates databases, runs migrations, and sets up the platform. It may take several minutes.
tutor dev do initStep 6: Verify installation
# Check all containers are running
docker ps --format "table {{.Names}}\t{{.Status}}" | grep tutor_devExpected output:
tutor_dev-lms-1 Up X minutes
tutor_dev-cms-1 Up X minutes
tutor_dev-mfe-1 Up X minutes
tutor_dev-mysql-1 Up X minutes
tutor_dev-mongodb-1 Up X minutes
tutor_dev-redis-1 Up X minutes
...Step 7: Verify URLs are accessible
# Check LMS is responding
curl -s -o /dev/null -w "%{http_code}" -H "Host: local.openedx.io" http://127.0.0.1:8000
# Check Studio is responding
curl -s -o /dev/null -w "%{http_code}" -H "Host: studio.local.openedx.io" http://127.0.0.1:8001Expected output: 200 or 302 (redirect to login).
If you get 000 or connection errors:
- Verify
/etc/hostsis configured correctly - Check container logs:
tutor dev logs -f lms - Try restarting:
tutor dev stop && tutor dev start -d
Creating Users
After installation, you need to create users to access the platform.
Create an Admin User (Staff/Superuser)
tutor dev do createuser --staff --superuser --password admin123 admin admin@example.comAdmin credentials:
- Username: admin
- Email: admin@example.com
- Password: admin123
- Permissions: Staff + Superuser (full admin access)
Create a Student User
tutor dev do createuser --password student123 student student@example.comStudent credentials:
- Username: student
- Email: student@example.com
- Password: student123
- Permissions: Regular user (student)
Alternative: Manual user creation
If the createuser command fails, you can create users manually:
tutor dev run lms ./manage.py lms manage_user admin admin@example.com --staff --superuser
tutor dev run lms ./manage.py lms shell -c "
from django.contrib.auth import get_user_model
u = get_user_model().objects.get(username='admin')
u.set_password('admin123')
u.save()
"Access URLs
| User Type | Login URL |
|---|---|
| Admin | http://local.openedx.io:8000/admin |
| All Users | http://local.openedx.io:8000/login |
| Studio (Admin only) | http://studio.local.openedx.io:8001 |
Installing Without Affecting Existing Installations
If you already have a Tutor installation (dev or local) and want to install a new instance without affecting it:
1. Stop the existing instance first (to free ports)
# If you have aliases configured
tutor-local local stop # or tutor-dev dev stop
# Or manually
source ~/existing-instance/.venv/bin/activate
export TUTOR_ROOT=~/existing-instance
tutor local stop # or tutor dev stop2. Create a completely separate directory
mkdir -p ~/openedx-dev-new
cd ~/openedx-dev-new3. Follow the installation steps above
Use a different TUTOR_ROOT:
export TUTOR_ROOT=~/openedx-dev-newWhat stays isolated?
| Resource | Instance 1 | Instance 2 |
|---|---|---|
| Configuration | TUTOR_ROOT_1/config.yml | TUTOR_ROOT_2/config.yml |
| Database | TUTOR_ROOT_1/data/mysql/ | TUTOR_ROOT_2/data/mysql/ |
| Files | TUTOR_ROOT_1/data/ | TUTOR_ROOT_2/data/ |
| Containers | tutor_dev-* | Different prefix if LOCAL_PROJECT_NAME differs |
| Source code | Can share or use different repos | Can share or use different repos |
Managing Multiple Instances
Option 1: Shell Aliases (Recommended)
Add these aliases to your ~/.bashrc or ~/.zshrc:
# Dev instance
alias tutor-dev='source ~/openedx-dev/.venv/bin/activate && TUTOR_ROOT=~/openedx-dev tutor'
# Local instance (if you have one)
alias tutor-local='source ~/tutor-local/.venv/bin/activate && TUTOR_ROOT=~/tutor-local tutor'Then reload your shell:
source ~/.bashrc # or source ~/.zshrcUsage:
tutor-dev dev start # Start dev instance
tutor-dev dev stop # Stop dev instance
tutor-local local start # Start local instanceOption 2: Manual Environment Setup
Each time you want to work with a specific instance:
# Activate the environment
source ~/openedx-dev/.venv/bin/activate
export TUTOR_ROOT=~/openedx-dev
# Now run tutor commands
tutor dev startImportant: Port Conflicts
Dev and local instances use different ports, but two dev instances would conflict:
| Mode | LMS Port | CMS Port |
|---|---|---|
| Dev | 8000 | 8001 |
| Local | 80 | 80 (via Caddy) |
Never run two dev instances simultaneously or you'll get port conflicts.
Troubleshooting
Error: "Could not verify sufficient RAM allocation in Docker"
Error message:
⚠️ Could not verify sufficient RAM allocation in Docker:
Docker is configured to allocate 2048 MiB RAM, less than the recommended 4096 MiB
Tutor may not work if Docker is configured with < 4 GB RAM.
Aborted!Solutions:
Option A: Increase Docker RAM (Recommended)
- Open Docker Desktop → Settings → Resources
- Set Memory to 4 GB or more
- Click Apply & Restart
Option B: Use non-interactive commands (Workaround)
Run the steps separately to bypass the RAM check:
tutor config save
tutor plugins enable mfe
tutor config save
tutor images build openedx-dev
tutor dev start -d
tutor dev do initOption C: Modify Tutor source (Advanced)
Since Tutor is installed in editable mode, you can disable the check:
- Edit
tutor/utils.pyin your tutor clone - Find the function
warn_macos_docker_memory() - Comment out the validation:python
def warn_macos_docker_memory() -> None: try: # check_macos_docker_memory() # <-- Comment this line pass except exceptions.TutorError as e: # ... rest of the function
Error: "AmbiguousPluginError" after git pull
Error message:
xblock.plugin.AmbiguousPluginErrorCause: The Open edX package was renamed from Open_edX to openedx-platform.
Solution:
# Clean up old installation inside the container
docker exec tutor_dev-lms-1 pip uninstall --yes Open_edX
docker exec tutor_dev-lms-1 rm -rf /openedx/edx-platform/Open_edX.egg-info
docker exec tutor_dev-lms-1 pip install -e /openedx/edx-platform
# Restart services
tutor dev restart lms cmsInteractive prompt hangs or fails
Problem: Commands like tutor dev launch require interactive input and fail in automated environments.
Solution: Use the Non-Interactive Installation method.
Containers not starting
Check container status:
docker ps -a --format "table {{.Names}}\t{{.Status}}" | grep tutor_devCheck logs:
tutor dev logs -f lms
tutor dev logs -f cmsRestart all services:
tutor dev stop
tutor dev start -dPort already in use
Error: Bind for 0.0.0.0:8000 failed: port is already allocated
Solution:
- Check what's using the port:
lsof -i :8000 - Stop the conflicting service or other Tutor instances:bash
tutor dev stop tutor local stop
MySQL authentication error after init
Error message:
django.db.utils.OperationalError: (1045, "Access denied for user 'openedx'@'...' (using password: YES)")Cause: Sometimes the MySQL credentials aren't synced properly after the initial setup.
Solution: Stop and restart all services:
tutor dev stop
tutor dev start -dWait a few seconds for MySQL to fully initialize, then verify with:
curl -s -o /dev/null -w "%{http_code}" -H "Host: local.openedx.io" http://127.0.0.1:8000Changes not reflecting (hot-reload not working)
Solution:
- Verify the mount is active:bash
tutor mounts list - Restart the affected service:bash
tutor dev restart lms # or cms - For static files, run:bash
tutor dev run lms npm run build-dev
Useful Commands
Basic Operations
# Check container status
tutor dev status
# Stop the platform
tutor dev stop
# Start the platform (background)
tutor dev start -d
# Restart the platform
tutor dev restart
# Restart specific services
tutor dev restart lms cms
# View logs (all services)
tutor dev logs -f
# View logs (specific service)
tutor dev logs -f lms
tutor dev logs -f cmsDevelopment Commands
# Run bash in LMS container
tutor dev run lms bash
# Run Django shell
tutor dev run lms ./manage.py lms shell
# Run Django management command
tutor dev run lms ./manage.py lms <command>
# Run CMS commands
tutor dev run cms ./manage.py cms <command>
# Build static assets
tutor dev run lms npm run build-dev
# Run tests
tutor dev run lms pytest <path-to-tests>Configuration
# Check current TUTOR_ROOT
tutor config printroot
# View a config value
tutor config printvalue LMS_HOST
# List mounts
tutor mounts list
# List enabled plugins
tutor plugins list
# Enable a plugin
tutor plugins enable <plugin-name>
tutor config saveUser Management
# Create admin user
tutor dev run lms ./manage.py lms manage_user admin admin@example.com --staff --superuser
# Create regular user
tutor dev run lms ./manage.py lms manage_user student student@example.com
# Change user password
tutor dev run lms ./manage.py lms shell -c "
from django.contrib.auth import get_user_model
u = get_user_model().objects.get(username='admin')
u.set_password('newpassword')
u.save()
"Uninstallation
Remove a specific dev instance
# Set the TUTOR_ROOT of the instance to remove
export TUTOR_ROOT=~/openedx-dev
# Stop and remove containers
tutor dev dc down --remove-orphans
# Remove all data and configuration
rm -rf ~/openedx-devComplete cleanup
# Remove containers
tutor dev dc down --remove-orphans
# Remove configuration and data
rm -rf "$(tutor config printroot)"
# Deactivate virtual environment
deactivate
# Remove project directory
rm -rf ~/openedx-dev
# Remove Docker images (optional, frees disk space)
docker rmi $(docker images | grep "openedx" | awk '{print $3}')Post-Installation Summary Template
For LLM assistants: After completing the installation, copy and fill in this template to provide the user with all necessary information:
## Installation Complete
Your Open edX development environment is now running.
### Access URLs
| Service | URL | Description |
|---------|-----|-------------|
| **LMS** | http://local.openedx.io:8000 | Main learning platform |
| **Studio** | http://studio.local.openedx.io:8001 | Course authoring tool |
| **Django Admin** | http://local.openedx.io:8000/admin | Backend administration |
### User Credentials
#### Administrator
| Field | Value |
|-------|-------|
| Username | admin |
| Password | admin123 |
| Email | admin@example.com |
| Access | LMS, Studio, Django Admin |
#### Student
| Field | Value |
|-------|-------|
| Username | student |
| Password | student123 |
| Email | student@example.com |
| Access | LMS only |
### Managing the Platform
#### Start the platform
\`\`\`bash
source ~/openedx-dev/.venv/bin/activate
export TUTOR_ROOT=~/openedx-dev
tutor dev start -d
\`\`\`
#### Stop the platform
\`\`\`bash
source ~/openedx-dev/.venv/bin/activate
export TUTOR_ROOT=~/openedx-dev
tutor dev stop
\`\`\`
#### Or use Docker Desktop
Open Docker Desktop and find the `tutor_dev` container group. Use the Play/Stop buttons to control the platform.
### Development Workflow
1. Make changes to files in `~/openedx-dev/openedx-platform/`
2. Changes to Python files auto-reload (wait a few seconds)
3. For static file changes, run: `tutor dev run lms npm run build-dev`
4. Check logs if needed: `tutor dev logs -f lms`
### Next Steps
1. Log in to Studio and create your first course
2. Test your code changes
3. Run tests with: `tutor dev run lms pytest <path>`Note: Adjust the paths and credentials based on the actual values used during installation.
Quick Reference
Installation Checklist
- [ ] Docker installed and running (v24.0.5+)
- [ ] Docker has 4+ GB RAM allocated
- [ ] Python 3.9+ installed
- [ ] Git installed
- [ ] Created project directory
- [ ] Cloned openedx-platform repository
- [ ] Cloned tutor repository
- [ ] Selected correct branch (master or release)
- [ ] Created Python virtual environment
- [ ] Installed Tutor in editable mode
- [ ] Set TUTOR_ROOT environment variable
- [ ] Mounted edx-platform repository
- [ ] Built openedx-dev image
- [ ] Ran
tutor dev launchor non-interactive steps - [ ] Created admin user
- [ ] Created student user
- [ ] Verified access to LMS and Studio
Default URLs (Dev Mode)
| Service | URL |
|---|---|
| LMS | http://local.openedx.io:8000 |
| Studio | http://studio.local.openedx.io:8001 |
| Admin | http://local.openedx.io:8000/admin |