Skip to main content

Get Started in 5 Minutes

This guide walks you through deploying a complete Moodle LMS instance using ipMoodle’s automated deployment script.
Prerequisites: Docker and Docker Compose installed on your system. See Prerequisites for details.

Installation Steps

1

Clone or Download ipMoodle

Get the ipMoodle source files to your server:
# Option 1: Clone from repository
git clone https://github.com/intiinside/ipMoodle.git /opt/moodleip
cd /opt/moodleip

# Option 2: Download and extract
mkdir -p /opt/moodleip
cd /opt/moodleip
# Extract your ipMoodle files here
2

Configure Environment Variables

Set your site URL and database credentials:
export SITE_URL="http://localhost"
export DB_NAME="moodle"
export DB_USER="moodle"
export DB_PASS="moodle"
For production deployments, use a strong password for DB_PASS and configure HTTPS. See SSL/HTTPS Setup.
The deployment script will automatically generate a .env file with these values:
SITE_URL=http://localhost
DB_NAME=moodle
DB_USER=moodle
DB_PASS=moodle
3

Run the Deployment Script

Make the script executable and run it:
chmod +x deploy.sh
./deploy.sh
The script performs three automated stages:
# Construyendo Imagen Propia (Esto tomará unos minutos)
docker compose build
The first build takes 3-5 minutes as Docker compiles PHP extensions. Subsequent builds use cached layers and are much faster.
4

Access Moodle

Once deployment completes, you’ll see:
--- ¡DESPLIEGUE FINALIZADO! ---
Accede a: http://localhost
Tus archivos están en: /opt/moodleip/html
Open your browser and navigate to your SITE_URL. You’ll see the Moodle installation wizard.
5

Complete Moodle Setup

Follow the Moodle web installer:
  1. Choose language: Select your preferred language
  2. Database configuration: Use these values:
    • Database type: PostgreSQL
    • Host: db
    • Database name: Value of DB_NAME (default: moodle)
    • Username: Value of DB_USER (default: moodle)
    • Password: Value of DB_PASS (default: moodle)
  3. Confirm paths:
    • Web address: Your SITE_URL
    • Moodle directory: /var/www/html
    • Data directory: /var/www/moodledata
  4. Create admin account: Set up your Moodle administrator credentials
  5. Site configuration: Configure site name, description, and settings
The database host is db (not localhost) because it references the Docker Compose service name.

What Just Happened?

The deployment script automated the following:

Environment File

Generated .env with your configuration variables

Docker Image

Built custom PHP 8.2-FPM image with Moodle extensions

Four Containers

Started database, app, cron, and web services

Moodle Code

Downloaded and extracted Moodle 4.3 into ./html

Permissions

Set correct ownership for www-data user

Network

Created isolated moodle-net bridge network

Verify Your Deployment

Check that all services are running:
docker compose ps
You should see four containers:
NAME                IMAGE                    STATUS
moodle_app          ipmoodle-app            Up
moodle_cron         ipmoodle-cron           Up
moodle_db           postgres:16-alpine      Up
moodle_web          nginx:alpine            Up
All containers should show Up status. If any container is restarting, check logs with docker compose logs <service>.

Understanding the Stack

Your Moodle instance runs on four interconnected services:
services:
  db:        # PostgreSQL 16 database
  app:       # PHP-FPM application server
  cron:      # Scheduled task runner
  web:       # Nginx reverse proxy (port 80)

Service Details

Database (db)
  • Image: postgres:16-alpine
  • Data: Persisted to ./db_data
  • Network: Internal moodle-net
Application (app)
  • Image: Custom PHP 8.2-FPM build
  • Code: Mounted from ./html
  • Uploads: Mounted to ./moodledata
  • Environment: Database credentials from .env
Cron (cron)
  • Image: Same as app container
  • Purpose: Runs Moodle’s admin/cli/cron.php every minute
  • Command:
    echo '*/1 * * * * /usr/local/bin/php /var/www/html/admin/cli/cron.php > /dev/null 2>&1' > /var/spool/cron/crontabs/www-data && crond -f -l 8
    
Web Server (web)
  • Image: nginx:alpine
  • Ports: 80:80 (maps host port 80 to container)
  • Config: Custom FastCGI configuration from nginx/default.conf

File Structure

After deployment, your directory structure looks like:
/opt/moodleip/
├── deploy.sh              # Deployment script
├── docker-compose.yml     # Service orchestration
├── Dockerfile             # Custom PHP-FPM image
├── .env                   # Generated environment variables
├── nginx/
│   └── default.conf      # Nginx configuration
├── html/                  # Moodle code (auto-downloaded)
├── moodledata/           # User uploads & cache
└── db_data/              # PostgreSQL data
Never delete db_data or moodledata — they contain your database and user-uploaded files. Always back up these directories.

Next Steps

Configure PHP Settings

Adjust memory limits, upload sizes, and execution timeouts

Set Up SSL/HTTPS

Secure your Moodle instance with TLS certificates

Backup & Restore

Learn how to protect your data with regular backups

Monitoring

Monitor container health and resource usage

Common Commands

# All services
docker compose logs -f

# Specific service
docker compose logs -f app
docker compose logs -f db

Troubleshooting

If another service is using port 80, modify docker-compose.yml:
web:
  ports:
    - "8080:80"  # Change host port to 8080
Then access Moodle at http://localhost:8080.
Check PHP-FPM logs:
docker compose logs app
Common causes:
  • Database connection failed (check DB_* variables)
  • File permissions incorrect (run permission commands from deploy.sh)
  • PHP fatal error (check logs for stack trace)
Ensure the database container is running:
docker compose ps db
Verify database credentials match in .env and Moodle config:
cat .env
docker compose exec app cat /var/www/html/config.php | grep dbhost
Check the cron container logs:
docker compose logs cron
Verify the crontab is installed:
docker compose exec cron cat /var/spool/cron/crontabs/www-data
Expected output: */1 * * * * /usr/local/bin/php /var/www/html/admin/cli/cron.php
For more detailed troubleshooting, see Troubleshooting Guide.

Build docs developers (and LLMs) love