The complete Moodle LMS course from zero to expert — 18 core sections covering installation, administration, course design, SCORM/xAPI, grading, plugins, custom API development, security, GDPR compliance, automation scripts, and real project portfolios.
This end-to-end curriculum covers Moodle from zero to production. You will install Moodle, manage users and courses, design interactive learning, configure exams, integrate APIs, secure deployments, and automate with scripts. Each section contains real-world scenarios, worked examples, practical activities, and production-ready code.
| Sections | Focus Area | Skill Level |
|---|---|---|
| 1 – 2 | Foundations — What is LMS, History, Installation | 🟢 Beginner |
| 3 – 5 | Administration, Course Design, E-Learning Standards | 🟡 Intermediate |
| 6 – 9 | Exams, Grading, User Roles, Communication | 🟡 Intermediate |
| 10 – 12 | Reports, Plugins, Custom API Development | 🔴 Advanced |
| 13 – 16 | GDPR, Performance, Security, Moodle Networks | 🔴 Advanced |
| 17 – 18 | Automation, Real Projects & Portfolio | 🔴 Expert |
| 19 – 22 | All Activity Types, Assignment, Workshop, Lesson, Database, Wiki | 🟡 Intermediate |
| 23 – 24 | Badges, Open Badges 2.0, Competency Frameworks, Learning Plans | 🔴 Advanced |
| 25 – 26 | All Enrolment Methods, Calendar, Notifications, Messaging | 🟡 Intermediate |
| 27 – 28 | Moodle Mobile App, Theme Customization, Boost Configuration | 🟡 Intermediate |
| 29 – 30 | Plagiarism Detection, Blocks, Complete CLI Reference | 🔴 Advanced |
Step-by-step visual pipelines for the most common Moodle administrative operations.
Toggle "Edit Mode" switch in the top-right of your course page.
Click "+ Add Activity". Choose File, SCORM, H5P, or Quiz.
Upload binary, set completion tracking, save & return.
php admin/cli/backup.php --courseid=5
Send .mbz snapshot to off-site storage bucket.
php admin/cli/restore_backup.php --file=backup.mbz
mysqldump -u root -p moodle > moodle.sql
rsync -avz /var/moodledata/ newserver:/var/moodledata/
Update config.php + run DB replace CLI tool.
Site Admin → Courses → Manage Courses & Categories.
Click copy icon next to the template course.
Set shortname, start date, exclude enrolments & logs.
Understand the foundations of Learning Management Systems and why Moodle is the world's most popular open-source LMS.
Teacher uploads homework, attendance sheets and lecture videos online. Students complete quizzes, download resources and submit assignments from home.
HR department assigns mandatory cybersecurity awareness training to all 500 employees. Completion certificates are auto-emailed after 80% pass mark.
Students watch recorded classes, download PDF notes and take timed mock tests. Results are sent automatically to parents via email integration.
| Platform | Industry | License | Key Advantage vs Moodle |
|---|---|---|---|
| Moodle | Education, Corporate | Free, Open-Source | Infinite flexibility, plugin ecosystem |
| Canvas | K-12, Higher Ed | Paid / Freemium | Sleeker default UI, native provisioning |
| Blackboard | Higher Education | Commercial Premium | Enterprise hosting, assessment engines |
| TalentLMS | Corporate Training | SaaS Subscription | Fast setup, built-in gamification |
| Teachable | Solopreneurs | SaaS Subscription | Built-in payment processing, simple UX |
Full server requirements and installation methods — from local XAMPP to production VPS and Bitnami stacks.
| Component | Minimum | Recommended (Production) |
|---|---|---|
| PHP | 8.1 | 8.2+ with OPcache enabled |
| Database | MySQL 8.0 / MariaDB 10.6 | MariaDB 10.10+ with InnoDB |
| Web Server | Apache 2.4 | Nginx with FastCGI-PHP |
| RAM | 512 MB | 4 GB+ |
| Disk | 5 GB | 50 GB+ SSD with moodledata mount |
# 1. Download Moodle from moodle.org/downloads
# 2. Extract to your web root:
cp -r moodle /Applications/MAMP/htdocs/
# 3. Create moodledata directory OUTSIDE web root:
mkdir /Applications/MAMP/moodledata
chmod 777 /Applications/MAMP/moodledata
# 4. Create MySQL database:
mysql -u root -p
CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moodleuser'@'localhost' IDENTIFIED BY 'SecurePass123!';
GRANT ALL PRIVILEGES ON moodle.* TO 'moodleuser'@'localhost';
FLUSH PRIVILEGES;
# 5. Visit http://localhost/moodle in browser to run web installer
sudo php admin/cli/install.php \
--wwwroot=https://your-moodle.com \
--dataroot=/var/moodledata \
--dbtype=mariadb \
--dbhost=localhost \
--dbname=moodle \
--dbuser=moodleuser \
--dbpass=SecurePass123! \
--fullname="My Moodle LMS" \
--shortname="MoodleLMS" \
--adminuser=admin \
--adminpass=Admin@1234! \
--adminemail=admin@yourdomain.com \
--non-interactive \
--agree-license
php admin/cli/upgrade.php every time you update Moodle core or install new plugins. Always set chmod 0777 on moodledata and chmod 0755 on the Moodle code directory.
Master the Site Administration panel — manage categories, users, appearance, language packs, notifications and cron.
<?php // config.php
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = 'mariadb';
$CFG->dblibrary = 'native';
$CFG->dbhost = 'localhost';
$CFG->dbname = 'moodle';
$CFG->dbuser = 'moodleuser';
$CFG->dbpass = 'SecurePass123!';
$CFG->prefix = 'mdl_';
$CFG->wwwroot = 'https://your-moodle.com';
$CFG->dataroot = '/var/moodledata';
$CFG->admin = 'admin';
// Performance
$CFG->cachetype = 'memcached';
$CFG->session_handler_class = '\core\session\database';
// Security
$CFG->cookiesecure = true;
$CFG->loginhttps = true;
$CFG->passwordpolicy = true;
require_once(__DIR__ . '/lib/setup.php');
# Open crontab for www-data
crontab -u www-data -e
# Run Moodle cron every 1 minute
* * * * * /usr/bin/php /var/www/html/moodle/admin/cli/cron.php >/dev/null 2>&1
# Or using systemd timer — create file:
# /etc/systemd/system/moodle-cron.service
# /etc/systemd/system/moodle-cron.timer
username,firstname,lastname,email,password,course1,role1
john_doe,John,Doe,john@example.com,Temp@1234,CS101,student
jane_smith,Jane,Smith,jane@example.com,Temp@1234,CS101,teacher
admin_bob,Bob,Admin,bob@example.com,Temp@1234,CS101,editingteacher
Upload via: Site Admin → Users → Accounts → Upload Users. Supports auto-enrolment, custom profile fields and password policy enforcement.
Create, design, and manage courses — categories, sections, activities, completion tracking, and conditional access.
| Format | Layout | Best For |
|---|---|---|
| Topics | Numbered topics sections | Subject-organized content |
| Weekly | Dates-based weekly sections | Fixed-schedule semester courses |
| Social | Single discussion forum | Community discussion boards |
| Single Activity | One activity (quiz/SCORM) | Standalone assessment portals |
| Grid (Plugin) | Icon grid layout | Visual learner dashboards |
# Backup a specific course (courseid=5)
php admin/cli/backup.php \
--courseid=5 \
--destination=/var/backups/moodle/
# List available backup files
ls -lh /var/backups/moodle/
# Restore backup to category (categoryid=1)
php admin/cli/restore_backup.php \
--file=/var/backups/moodle/backup-moodle2-course-5-CS101.mbz \
--categoryid=1 \
--userid=2
SCORM, xAPI (Tin Can), H5P, IMS Content Packages — standards for interoperable, trackable learning content.
| Standard | Offline | Mobile | Detailed Tracking | Complexity |
|---|---|---|---|---|
| SCORM 1.2 | No | No | Basic pass/fail | Low — drag & drop |
| SCORM 2004 | No | No | Detailed sequencing | Medium |
| xAPI (Tin Can) | Yes | Yes | Any verb/object | Requires LRS setup |
| H5P | No | Yes | Built-in reports | Very Low — browser editor |
| IMS CP | No | No | Basic navigation | Low |
Build quiz activities, question banks, GIFT format imports, timed exams, safe exam browser, and randomised question pools.
| Type | Auto-Grade | Use Case |
|---|---|---|
| Multiple Choice | ✅ Yes | Theory knowledge checks |
| True / False | ✅ Yes | Quick concept verification |
| Short Answer | ⚠️ Partial | Keyword-based text answers |
| Numerical | ✅ Yes | Math/formula answers |
| Essay | ❌ Manual | Long-form written responses |
| Drag & Drop | ✅ Yes | Ordering, matching diagrams |
| Calculated | ✅ Yes | Variables-based formulas |
GIFT (General Import Format Technology) lets you write questions in a plain text file and import hundreds at once.
// Multiple Choice — correct answer marked with =
What is Moodle? {
~An operating system
~A database engine
=An open-source Learning Management System
~A cloud hosting provider
}
// True/False
Moodle supports REST web service protocols. {TRUE}
// Short Answer (case-insensitive)
The default Moodle database prefix is: {=mdl_}
// Numerical with tolerance
What is 15% of 200? {#30:2}
// Matching
Match the protocol to its purpose: {
=REST -> Stateless HTTP API calls
=SOAP -> XML-based structured messaging
=WebSocket -> Real-time bidirectional streams
}
// Essay (no auto-grade)
Describe the Moodle plugin installation process. {}
.txt file → Choose destination category → Import.
.seb) to the quizConfigure grade categories, weighted averages, letter grades, outcomes, rubrics, marking guides and grade exports.
| Method | Structure | Best For |
|---|---|---|
| Rubric | Criteria × Level grid with descriptors | Essays, presentations, projects |
| Marking Guide | Criteria with max points + comments | Open-ended submissions |
| Simple Direct | Single score entry | Quick manual grading |
SELECT
u.username,
u.firstname,
u.lastname,
u.email,
c.shortname AS course,
gi.itemname AS grade_item,
gg.finalgrade,
gg.timemodified
FROM mdl_grade_grades gg
JOIN mdl_grade_items gi ON gi.id = gg.itemid
JOIN mdl_user u ON u.id = gg.userid
JOIN mdl_course c ON c.id = gi.courseid
WHERE c.shortname = 'CS101'
AND gi.itemtype = 'mod'
ORDER BY u.lastname, gi.sortorder;
Built-in roles, custom role creation, capabilities, context levels, cohort sync, and authentication methods.
| Role | Default Context | Key Capabilities |
|---|---|---|
| Administrator | Site | Everything — full site control |
| Course Creator | Course Category | Create, delete, restore courses |
| Editing Teacher | Course | Add/edit content, grade, manage enrolments |
| Teacher | Course | Grade and communicate, cannot edit content |
| Student | Course | View and complete activities |
| Guest | Course | View-only (no submissions) |
| Method | Use Case | Setup Complexity |
|---|---|---|
| Manual Accounts | Small teams, testing | None |
| Email-based self-registration | Open enrollment portals | Low |
| LDAP / Active Directory | Corporate internal SSO | Medium-High |
| OAuth 2.0 (Google, MS) | Modern social login | Medium |
| SAML 2.0 | Enterprise federated identity | High |
| CAS (Central Auth Service) | University SSO portals | Medium |
Forums, messaging, Announcements, Groups, Groupings, BigBlueButton virtual classrooms, and email notifications.
| Forum Type | Structure | Best For |
|---|---|---|
| Standard Forum | Anyone can start topics | Open discussion |
| News Forum | Teacher announcements only | Course-wide notifications |
| Q&A Forum | Must answer before seeing others | Independent thinking exercises |
| Single Simple Discussion | One shared thread | Weekly discussion topic |
| Each Person Posts One | One topic per user | Peer review introductions |
Built-in reports, live logs, course participation, Moodle Analytics API, custom SQL reports and scheduled exports.
SELECT
u.username,
u.firstname,
u.lastname,
c.fullname AS course,
FROM_UNIXTIME(MAX(l.timecreated)) AS last_access
FROM mdl_logstore_standard_log l
JOIN mdl_user u ON u.id = l.userid
JOIN mdl_course c ON c.id = l.courseid
WHERE l.action = 'viewed'
AND l.component = 'core'
AND c.id != 1
GROUP BY u.id, c.id
ORDER BY c.fullname, u.lastname;
Explore the Moodle plugin directory — theme plugins, activity modules, authentication, enrollment, admin tools and blocks.
.zip from moodle.org/plugins/mod/, /blocks/, /theme/ directory via FTP/SCPphp admin/cli/upgrade.php to trigger DB schema migration| Plugin | Type | Function |
|---|---|---|
| Attendance | Activity Module | Record student attendance per session |
| Configurable Reports | Block | Custom SQL report builder |
| Level Up! | Block | Gamification — XP points and levels |
| BigBlueButton | Activity Module | Integrated virtual classroom |
| Boost Union | Theme | Enterprise-grade Boost child theme |
| Checklist | Activity Module | Student self-checklist for tasks |
| Group Choice | Activity Module | Self-enroll into groups with capacity limits |
Build, register, and deploy custom Moodle web service functions inside local plugins — complete workflow from db/services.php to external class.
/moodle/local/courseprogress/
├── version.php # Plugin version metadata
├── lib.php # Plugin library hooks
├── db/
│ ├── services.php # Register web service functions
│ └── access.php # Define capabilities
├── classes/
│ └── external/
│ └── progress.php # External function class
└── lang/
└── en/
└── local_courseprogress.php # Language strings
<?php
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_courseprogress';
$plugin->version = 2024010100; // YYYYMMDDXX
$plugin->requires = 2022041900; // Minimum Moodle version
$plugin->maturity = MATURITY_STABLE;
$plugin->release = '1.0.0';
<?php
defined('MOODLE_INTERNAL') || die();
$functions = [
'local_courseprogress_get_user_course_progress' => [
'classname' => 'local_courseprogress\external\progress',
'methodname' => 'get_user_course_progress',
'description' => 'Get user course progress details',
'type' => 'read',
'ajax' => true,
'capabilities'=> 'moodle/user:viewdetails',
'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE],
],
'local_courseprogress_get_all_courses' => [
'classname' => 'local_courseprogress\external\progress',
'methodname' => 'get_user_all_courses_progress',
'description' => 'Get all enrolled course progress for a user',
'type' => 'read',
'ajax' => true,
'capabilities'=> 'moodle/user:viewdetails',
],
'local_courseprogress_get_course_details' => [
'classname' => 'local_courseprogress\external\progress',
'methodname' => 'get_course_progress_details',
'description' => 'Get detailed progress breakdown per course activity',
'type' => 'read',
'ajax' => true,
'capabilities'=> 'moodle/course:view',
],
];
$services = [
'Course Progress API Service' => [
'functions' => [
'local_courseprogress_get_user_course_progress',
'local_courseprogress_get_all_courses',
'local_courseprogress_get_course_details',
],
'restrictedusers' => 0,
'enabled' => 1,
'shortname' => 'courseprogress_api',
],
];
<?php
namespace local_courseprogress\external;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/externallib.php');
class progress extends \external_api {
// ─── get_user_course_progress ────────────────────────────
public static function get_user_course_progress_parameters() {
return new \external_function_parameters([
'userid' => new \external_value(PARAM_INT, 'User ID'),
'courseid' => new \external_value(PARAM_INT, 'Course ID'),
]);
}
public static function get_user_course_progress($userid, $courseid) {
global $DB;
$params = self::validate_parameters(
self::get_user_course_progress_parameters(),
['userid' => $userid, 'courseid' => $courseid]
);
$completion = new \completion_info($DB->get_record('course', ['id' => $params['courseid']], '*', MUST_EXIST));
$activities = $completion->get_activities();
$completed = 0;
foreach ($activities as $activity) {
$data = $completion->get_data($activity, false, $params['userid']);
if ($data->completionstate == COMPLETION_COMPLETE || $data->completionstate == COMPLETION_COMPLETE_PASS) {
$completed++;
}
}
$total = count($activities);
$percent = $total > 0 ? round(($completed / $total) * 100, 2) : 0;
return [
'userid' => $params['userid'],
'courseid' => $params['courseid'],
'completed' => $completed,
'total' => $total,
'percent' => $percent,
];
}
public static function get_user_course_progress_returns() {
return new \external_single_structure([
'userid' => new \external_value(PARAM_INT, 'User ID'),
'courseid' => new \external_value(PARAM_INT, 'Course ID'),
'completed' => new \external_value(PARAM_INT, 'Completed activities'),
'total' => new \external_value(PARAM_INT, 'Total activities'),
'percent' => new \external_value(PARAM_FLOAT, 'Completion percentage'),
]);
}
}
/moodle/local/courseprogress/php admin/cli/upgrade.php --non-interactivecurl -X POST "https://your-moodle.com/webservice/rest/server.php" \
-d "wstoken=YOUR_TOKEN_HERE" \
-d "wsfunction=local_courseprogress_get_user_course_progress" \
-d "moodlewsrestformat=json" \
-d "userid=5" \
-d "courseid=3"
# Expected Response:
# {
# "userid": 5,
# "courseid": 3,
# "completed": 7,
# "total": 10,
# "percent": 70.0
# }
Configure cookie policy banners, data retention, user data export, account deletion, and Moodle's Privacy API.
-- Find all log entries for a specific user
SELECT l.timecreated, l.action, l.component, l.target, l.contextlevel
FROM mdl_logstore_standard_log l
WHERE l.userid = :userid
ORDER BY l.timecreated DESC
LIMIT 100;
-- Check profile data
SELECT * FROM mdl_user WHERE id = :userid;
-- Check messages sent
SELECT * FROM mdl_messages WHERE useridfrom = :userid;
-- Proper deletion should be done via Privacy API, not raw SQL
OPcache, Memcached, Redis session store, MUC (Moodle Universal Cache), CDN integration, load balancing, and database tuning.
| Cache Store | Type | Recommended For |
|---|---|---|
| File | Disk-based | Default — single server setups |
| Memcached | In-memory distributed | Multi-server clusters |
| Redis | In-memory + persistence | Session storage, high-traffic |
| APCu | PHP shared memory | Application-level caching per server |
// Redis for sessions
$CFG->session_handler_class = '\core\session\redis';
$CFG->session_redis_host = '127.0.0.1';
$CFG->session_redis_port = 6379;
// Enable Memcached caching
$CFG->cachetype = 'memcached';
// Disable theme designer mode in production
$CFG->themedesignermode = false;
// Enable JavaScript combination & compression
$CFG->yuicomboloading = true;
// Boost performance on load
$CFG->debug = 0; // Disable debug in production
$CFG->debugdisplay = 0;
A high-performance Moodle cluster relies on multi-tier caching. If Level 1 or 2 hits, database access is skipped entirely.
PHP local shared memory. Sub-millisecond reads, local to worker node.
Shared distributed memory cache. Shared across all autoscaling web servers.
Relational DB storage and physical disk files. Loaded only on cache miss.
SSL/TLS enforcement, password policies, failed login lockout, brute-force protection, file upload restrictions, and security report auditing.
$CFG->loginhttps = true; + redirect in Apache/Nginx$CFG->showcampaigncontent = false;server {
listen 443 ssl http2;
server_name your-moodle.com;
# Force HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';" always;
# Block direct access to sensitive dirs
location ~ ^/moodle/(config\.php|lib|classes|db|admin/cli)/ {
deny all;
return 404;
}
}
Connect multiple Moodle instances — share enrollments, enable cross-site SSO, and configure Moodle Network Host trust relationships.
| Scenario | Benefit |
|---|---|
| University + Library portal | Students log in once to access both systems |
| Parent company + subsidiaries | Share compliance training across all entities |
| School district network | Central reporting with per-school Moodle instances |
Python, cURL, PHP, and Bash scripts to automate user provisioning, grade exports, course enrollment, and bulk operations via the Moodle REST API.
import requests
import csv
TOKEN = "your_moodle_token_here"
DOMAIN = "https://your-moodle.com"
URL = f"{DOMAIN}/webservice/rest/server.php"
def create_user(i, username, firstname, lastname, email, password):
payload = {
"wstoken": TOKEN,
"wsfunction": "core_user_create_users",
"moodlewsrestformat": "json",
f"users[{i}][username]": username,
f"users[{i}][password]": password,
f"users[{i}][firstname]": firstname,
f"users[{i}][lastname]": lastname,
f"users[{i}][email]": email,
}
res = requests.post(URL, data=payload)
return res.json()
# Read from CSV and create
with open("users.csv") as f:
reader = csv.DictReader(f)
for i, row in enumerate(reader):
result = create_user(i, row['username'], row['firstname'],
row['lastname'], row['email'], row['password'])
print(f"Created: {row['username']} → {result}")
import requests
TOKEN = "your_moodle_token_here"
DOMAIN = "https://your-moodle.com"
URL = f"{DOMAIN}/webservice/rest/server.php"
ROLE_ID = 5 # 5 = Student
COURSE_ID = 3 # Target course
def enrol_user(user_id):
payload = {
"wstoken": TOKEN,
"wsfunction": "enrol_manual_enrol_users",
"moodlewsrestformat": "json",
"enrolments[0][roleid]": ROLE_ID,
"enrolments[0][userid]": user_id,
"enrolments[0][courseid]": COURSE_ID,
}
res = requests.post(URL, data=payload)
return res.json()
# Enrol a list of user IDs
user_ids = [12, 13, 14, 15, 16]
for uid in user_ids:
result = enrol_user(uid)
print(f"Enrolled user {uid}: {result}")
#!/bin/bash
# Nightly Moodle Backup Script
set -e
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR="/var/backups/moodle"
MOODLE_DIR="/var/www/html/moodle"
DB_NAME="moodle"
DB_USER="moodleuser"
DB_PASS="SecurePass123!"
mkdir -p "$BACKUP_DIR/$DATE"
# 1. Database dump
echo "[$(date)] Dumping database..."
mysqldump -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" | gzip > "$BACKUP_DIR/$DATE/moodle_db.sql.gz"
# 2. Course file backups
echo "[$(date)] Backing up courses..."
php "$MOODLE_DIR/admin/cli/backup.php" \
--courseid=all \
--destination="$BACKUP_DIR/$DATE/courses/"
# 3. Compress moodledata
echo "[$(date)] Compressing moodledata..."
tar -czf "$BACKUP_DIR/$DATE/moodledata.tar.gz" /var/moodledata/
# 4. Push to S3
aws s3 sync "$BACKUP_DIR/$DATE" "s3://your-bucket/moodle-backups/$DATE/"
# 5. Clean up local backups older than 7 days
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
echo "[$(date)] Backup complete: $BACKUP_DIR/$DATE"
0 2 * * * /bin/bash /opt/scripts/nightly_backup.sh >> /var/log/moodle_backup.log 2>&1
<?php
// Run: php export_grades.php --courseid=3
define('CLI_SCRIPT', true);
require('/var/www/html/moodle/config.php');
require_once($CFG->libdir . '/gradelib.php');
require_once($CFG->libdir . '/grade/grade_item.php');
$courseid = (int)($argv[1] ?? 3);
$course = $DB->get_record('course', ['id' => $courseid], '*', MUST_EXIST);
$items = grade_item::fetch_all(['courseid' => $courseid]);
$users = get_enrolled_users(context_course::instance($courseid));
echo "username,firstname,lastname,email,grade\n";
foreach ($users as $user) {
$gi = grade_item::fetch(['courseid' => $courseid, 'itemtype' => 'course']);
$grade = new grade_grade(['itemid' => $gi->id, 'userid' => $user->id]);
echo implode(',', [
$user->username, $user->firstname, $user->lastname,
$user->email, round($grade->finalgrade ?? 0, 2)
]) . "\n";
}
End-to-end guided projects to demonstrate mastery of Moodle LMS to employers and clients.
Build a complete exam portal with 3 courses, 100 GIFT questions, randomised quizzes, SEB lockdown, automated grade export, and custom certificates.
Deploy Moodle on Ubuntu VPS with Nginx + Redis + Memcached. Integrate LDAP for Active Directory SSO. Create Department Auditor custom role. Configure automated nightly backups to S3.
Build a local_courseprogress Moodle plugin with 5 custom web service functions. Integrate with a React Native mobile app. Display live progress bars, completion status, and badges.
Write an Ansible playbook that: installs Moodle from scratch on a fresh Ubuntu server, configures Nginx + MariaDB, creates admin user, installs plugins, enables web services, and runs smoke-tests.
Every activity and resource type available in Moodle core — what each does, when to use it, and key configuration options.
| Resource | Purpose | Key Option |
|---|---|---|
| File | Upload single file (PDF, DOCX, MP4) | Force download vs display in browser |
| Folder | Group multiple files in one place | Display inline or as expandable folder |
| URL | Link to any external website | Open in new window / same window |
| Page | Rich text HTML page within Moodle | Embeds images, video, formatted text |
| Book | Multi-chapter content with table of contents | Chapter numbering, print entire book |
| Label | Inline text/image inside course section | No click needed — always visible |
| IMS Content Package | Import SCORM-like zipped content | Standardized eLearning package |
| Activity | Type | Auto-Grade | Key Feature |
|---|---|---|---|
| Quiz | Assessment | ✅ Yes | Randomised questions, timed, SEB lockdown |
| Assignment | Submission | ❌ Manual | File upload, text, PDF annotation, team submission |
| Workshop | Peer Review | ⚠️ Partial | 5-phase peer assessment with calibration |
| Lesson | Branching | ✅ Yes | Conditional content pages based on answers |
| SCORM | Package | ✅ Yes | External eLearning packages (SCORM 1.2/2004) |
| H5P | Interactive | ✅ Yes | 50+ content types, no software needed |
| Database | Data collection | ⚠️ Optional | Custom fields, templates, peer approval |
| Glossary | Dictionary | ⚠️ Optional | Auto-link terms across course, peer entries |
| Wiki | Collaborative | ⚠️ Optional | Individual or group wiki pages |
| Forum | Discussion | ⚠️ Optional | 5 types, peer ratings, digest emails |
| Chat | Real-time | ❌ No | Synchronous text chat with session logs |
| Choice | Poll/Vote | ❌ No | Single question, group sign-up |
| Feedback | Anonymous survey | ❌ No | Course evaluation, non-graded feedback |
| Survey | Research survey | ❌ No | COLLES, ATTLS, Critical Incidents instruments |
| BigBlueButton | Virtual class | ❌ No | Breakout rooms, recordings, whiteboard |
| LTI (External Tool) | Integration | ✅ Yes | Connect any LTI 1.3 tool (Turnitin, Kahoot, etc.) |
The Assignment module is Moodle's most powerful grading tool. Master all submission types, marking workflows, PDF annotation, team submissions, and plagiarism integration.
| Type | What Students Submit | Notes |
|---|---|---|
| File Submissions | Upload files (PDF, DOCX, ZIP, images) | Set max files (1–20), max size, allowed types |
| Online Text | Rich text editor in browser | Word count limits, paste from Word |
| Online Audio Recording | Record audio in browser | Requires microphone, saves as .ogg |
| Online Video Recording | Record video via webcam | Requires camera, saves as .webm |
# Step 1: In Assignment grader → Download grading worksheet (.csv)
# It contains: Identifier, Full name, Email, Status, Grade, Maximum Grade, Feedback
# Step 2: Fill in Grade and Feedback columns in Excel/LibreOffice
Identifier, Full name, Grade, Feedback
"Participant 1", John Doe, 85, "Good analysis but missing citations"
"Participant 2", Jane Smith, 92, "Excellent work — well structured"
# Step 3: Upload CSV back → Grades and feedback applied automatically
# Assignment → View All Submissions → Upload grading worksheet
The Workshop module enables powerful peer-review assessments in 5 distinct phases. Students submit work, review peers, and receive an aggregated grade.
Teacher defines submission instructions, assessment form, and grading strategy.
Students upload their work within the submission deadline.
Each student reviews N peers' submissions using the assessment form.
Teacher grades student assessments for accuracy vs their own marking.
Final grades published. Students see received reviews and their grades.
| Strategy | How It Works | Best For |
|---|---|---|
| Accumulative | Criteria with points, weighted average | Most assignments |
| Comments Only | Text comments, no numeric grade | Formative feedback only |
| Number of Errors | Yes/No checklist — points deducted per error | Technical tasks with clear requirements |
| Rubric | Full rubric with criteria × levels | Essays, projects, presentations |
Advanced activity types for branching content, collaborative data collection, group wikis, and auto-linking terminology.
Lesson: "Fire Safety Compliance" (Branching)
├── [Content] Introduction to Fire Safety
├── [Question] Where is the nearest fire exit? (MCQ)
│ ├── ✅ Correct → [Content] Emergency Evacuation Procedures
│ └── ❌ Wrong → [Content] Study the Floor Map Again → Loop back
├── [Question] Who do you call first in a fire?
│ ├── ✅ Correct → [Content] Final Summary
│ └── ❌ Wrong → [Content] Emergency Contact Procedures → Loop back
└── [End of Lesson] Grade = % questions correct
| Mode | Who Edits | Use Case |
|---|---|---|
| Collaborative | All students share one wiki | Group knowledge base, class glossary |
| Individual | Each student has their own wiki | Personal learning journal, portfolio |
Motivate learners with digital achievement badges and issue verifiable completion certificates that are portable across the web.
| Criterion | Trigger |
|---|---|
| Manual Award | Teacher manually awards badge to specific students |
| Course Completion | Student completes the course (meets all completion requirements) |
| Activity Completion | Student completes specific activity (quiz passed, assignment submitted) |
| Grade | Student achieves minimum grade in grade item |
| Badge Award | Student already has another badge (badge chains) |
| Profile Completion | Student fills all required profile fields |
| Cohort Membership | Student belongs to specific cohort |
# Download from moodle.org/plugins/mod_customcert
unzip mod_customcert.zip -d /var/www/html/moodle/mod/
# Set permissions
chown -R www-data:www-data /var/www/html/moodle/mod/customcert/
# Run upgrade
php admin/cli/upgrade.php --non-interactive
# Verify it appears in: Course → Add Activity → Custom Certificate
Moodle's built-in Competency-Based Education (CBE) system — define skills frameworks, map activities to competencies, and create personalised learning plans.
Moodle supports 10+ enrolment plugins. Understand every method, when to use it, and how to configure it for your institution.
| Method | How Students Join | Best For |
|---|---|---|
| Manual Enrolment | Teacher/admin manually adds users | Small controlled groups |
| Self Enrolment | Student clicks "Enrol Me" button | Open access courses |
| Self Enrolment + Key | Enrol with secret key (password) | Restricted access with shared key |
| Guest Access | View only — no submission allowed | Public preview / demo courses |
| Cohort Sync | Auto-enrol all members of a cohort | Year-group or department courses |
| Meta Enrolment | Students in Course A auto-join Course B | Combined/linked courses |
| LDAP Enrolment | Sync enrolments from Active Directory | Corporate HRMS integration |
| Payment (PayPal/Stripe) | Pay course fee to auto-enrol | Commercial course sales |
| Flat File | CSV import runs via cron | Batch enrolment from SIS |
| IMS Enterprise | XML-based enterprise data sync | University SIS integration |
| Database Enrolment | Direct DB query to external system | Custom ERP/HRMS sync |
| LTI Provider | Remote platform auto-enrols via LTI | Being enrolled from another LMS |
# format: action, role, username, course_shortname
add, student, john_doe, CS101
add, student, jane_smith, CS101
add, editingteacher, prof_williams, CS101
del, student, old_student, CS101
# Upload via: Site Admin → Plugins → Enrolments → Flat file
# Set the path to this file — cron processes it automatically
Enterprise single sign-on (SSO) automates account creation, security group mappings, and instant course enrollments upon secure login.
Student clicks SSO button. Moodle redirects browser to identity provider (IdP).
IdP validates user and sends secure SAML Assertion / ID Token to Moodle endpoint.
Moodle matches attributes, auto-creates user record, logs them in, and triggers cohort sync.
Manage course events, set automated reminders, configure email notifications, and control messaging preferences across the platform.
| Event Type | Visible To | Created By |
|---|---|---|
| Site Event | All users on the site | Site administrators |
| Category Event | Users in the category | Category managers |
| Course Event | All enrolled students | Course teachers/admins |
| Group Event | Members of specific group | Teachers (group mode enabled) |
| User Event | Only the creator | Any user (personal calendar) |
| Activity Deadline | Enrolled students | Auto-created when activity has due date |
.ics file for Google Calendar / Outlook / Apple CalendarConfigure your Moodle site to work with the official Moodle mobile app — enable push notifications, offline access, and QR code login.
| Feature | App Support | Notes |
|---|---|---|
| Course dashboard | ✅ Full | All enrolled courses visible |
| Quiz | ✅ Full | Timed, with offline attempt sync |
| Assignment submission | ✅ Full | File upload, online text, audio/video recording |
| Forum participation | ✅ Full | Reply, rate, attach files |
| SCORM | ⚠️ Limited | Basic playback — no adaptive navigation |
| H5P | ✅ Full | Most content types supported |
| Offline mode | ✅ Yes | Download course sections for offline viewing |
| Push notifications | ✅ Yes | Requires FCM (Android) / APNs (iOS) setup |
| QR code login | ✅ Yes | Scan from User Profile → QR login code |
| Messaging | ✅ Full | Real-time chat with sound notifications |
| BigBlueButton | ✅ Yes | Join sessions from mobile (BBB app opens) |
# Step 1: Create Firebase project at console.firebase.google.com
# Step 2: Add Android App → download google-services.json
# Step 3: Get Server Key:
# Firebase Console → Project Settings → Cloud Messaging → Server Key
# Step 4: Add to Moodle:
# Site Admin → Mobile App → Push Notifications
# Android → Server API Key: [your FCM server key]
# iOS → Certificate file (.p12) + password
# Step 5: Test
# Send test push notification from Moodle to your app
Customize the look and feel of your Moodle site — configure Boost theme, brand colors, custom CSS, logos, layouts, and create child themes.
/* Add in: Site Admin → Appearance → Boost Settings → Raw SCSS */
/* Brand colors */
$brand-color: #1a56db;
$body-bg: #f8fafc;
$navbar-bg: #0f172a;
/* Typography */
body { font-family: 'Inter', system-ui, sans-serif; }
.h1, .h2, .h3 { font-weight: 800; }
/* Course cards */
.card { border-radius: 1rem; box-shadow: 0 4px 20px rgba(0,0,0,0.06); }
.card:hover { transform: translateY(-2px); transition: all 0.3s ease; }
/* Login page */
#page-login-index .card { backdrop-filter: blur(10px); background: rgba(255,255,255,0.9); }
Moodle theme rendering is divided between template processing and real-time SCSS compilation pipelines.
PHP script declares output context, registering assets and layout targets via $PAGE.
Mustache engine reads layout files, merges contextual variables, and outputs static HTML blocks.
SCSS compiler processes Boost brand presets, custom SCSS variables, and outputs fully cached CSS files.
Integrate Turnitin for plagiarism checking, master all core Moodle blocks, and configure advanced grading scales, outcomes and grade letters.
plagiarism_turnitin pluginplagiarism_urkund pluginplagiarism_compilatio| Block | Function | Where Used |
|---|---|---|
| Calendar | Show upcoming events | Dashboard, course page |
| Upcoming Events | List of next N events | Dashboard, course page |
| Course Overview | Enrolled courses summary | Dashboard (default) |
| Recently Accessed | Last-viewed items | Dashboard |
| Timeline | Assignment deadlines timeline | Dashboard |
| Activity Completion | Progress tracker | Course page |
| Completion Status | Green/red criteria checklist | Course page (student view) |
| Latest Announcements | Recent forum news posts | Course page |
| Online Users | Who's online in past N minutes | Course page |
| Search Forums | Full-text search in forums | Course page |
| Random Glossary Entry | Display random term from Glossary | Course page |
| Remote RSS Feeds | Pull external RSS into Moodle | Dashboard, course |
| HTML Block | Custom HTML/CSS widget | Anywhere |
| Navigation | Full site navigation tree | Anywhere |
| Administration | Quick admin links | Site admin pages |
SELECT
gl.courseid,
c.shortname,
gl.lowerboundary,
gl.letter
FROM mdl_grade_letters gl
JOIN mdl_course c ON c.id = gl.courseid
WHERE gl.courseid = 5
ORDER BY gl.lowerboundary DESC;
-- Example output:
-- 90.0 → A+
-- 80.0 → A
-- 70.0 → B
-- 60.0 → C
-- 50.0 → D
-- 0.0 → F
-- In Gradebook Setup, a Calculated Grade Item uses formula syntax:
-- Reference grade items by their idnumber set in edit screen
-- Example: Final Grade = (Quiz 40%) + (Assignment 40%) + (Attendance 20%)
= ([[quiz_grade]] * 0.4) + ([[assignment_grade]] * 0.4) + ([[attendance_grade]] * 0.2)
-- Minimum grade enforcement
= max([[final]], 0)
-- Round to 2 decimals
= round(([[quiz_grade]] * 0.6) + ([[assignment_grade]] * 0.4), 2)
-- Conditional pass/fail (pass if quiz >= 50 AND assignment >= 50)
= if(and([[quiz_grade]]>=50, [[assignment_grade]]>=50), 100, 0)
Every official CLI script in Moodle — what it does, when to use it, and working command examples with flags.
# ── INSTALLATION & UPGRADE ────────────────────────────────────
php admin/cli/install.php --help # Fresh install wizard
php admin/cli/upgrade.php --non-interactive # Upgrade Moodle core/plugins
php admin/cli/install_database.php # Install DB schema only
# ── MAINTENANCE & CACHE ───────────────────────────────────────
php admin/cli/purge_caches.php # Clear all Moodle caches
php admin/cli/maintenance.php --enable # Enable maintenance mode
php admin/cli/maintenance.php --disable # Disable maintenance mode
php admin/cli/cron.php # Run cron manually (all tasks)
# ── USERS ─────────────────────────────────────────────────────
php admin/cli/create_user.php # Create a single user
php admin/cli/reset_password.php # Reset user password
# --username=admin --password=NewPass123!
php admin/cli/delete_user.php # Permanently delete user
php admin/cli/suspend_user.php # Suspend/unsuspend user
# ── COURSES & BACKUP ──────────────────────────────────────────
php admin/cli/backup.php \
--courseid=5 \
--destination=/var/backups/ # Backup single course
php admin/cli/restore_backup.php \
--file=/backups/course.mbz \
--categoryid=1 \
--userid=2 # Restore course
php admin/cli/delete_course.php \
--courseid=5 # Delete course permanently
# ── DATABASE ──────────────────────────────────────────────────
php admin/tool/replace/cli/replace.php \
--search=http://old.com \
--replace=https://new.com # URL search-replace in DB
# ── PLUGINS ───────────────────────────────────────────────────
php admin/cli/uninstall_plugins.php \
--plugins=mod_quiz \
--run # Uninstall a plugin
# ── WEB SERVICES ──────────────────────────────────────────────
php admin/cli/generate_ws_token.php \
--userid=2 \
--service=moodle_mobile_app # Generate API token
# ── TESTING ───────────────────────────────────────────────────
php admin/tool/behat/cli/init.php # Init Behat acceptance tests
php admin/tool/phpunit/cli/init.php # Init PHPUnit unit tests
vendor/bin/phpunit --testsuite=core # Run PHPUnit suite
# ── PERFORMANCE TESTING ───────────────────────────────────────
php admin/tool/generator/cli/maketestcourse.php \
--shortname=BIGTEST \
--size=XL # Generate large test course
Moosh is an unofficial but widely used CLI toolkit that adds 200+ commands for rapid Moodle management.
# Install Moosh
composer global require moosh/moosh
# User management
moosh user-create --password=Pass123! --email=john@ex.com john_doe
moosh user-list --search=john
moosh user-delete john_doe
moosh user-getidbyname john_doe
# Course management
moosh course-create --fullname="PHP Masterclass" --shortname=PHP101 --category=1
moosh course-list
moosh course-enrol -r student 5 12 # enrol userid=12 in courseid=5 as student
moosh course-unenrol 5 12
# Grades
moosh grade-get --userid=12 --courseid=5
moosh grade-set --userid=12 --courseid=5 --idnumber=quiz1 --grade=85
# Cache & maintenance
moosh cache-clear
moosh config-set maintenance_enabled 1
moosh config-set maintenance_message "Upgrading — back at 3pm"
# Plugin management
moosh plugin-list
moosh plugin-install-fromzip /path/to/plugin.zip
| Function | Action | Type |
|---|---|---|
| core_user_create_users | Create one or more users | write |
| core_user_get_users | Search/retrieve users | read |
| core_user_update_users | Update user profile fields | write |
| core_user_delete_users | Permanently delete users | write |
| enrol_manual_enrol_users | Enrol users in a course | write |
| enrol_manual_unenrol_users | Unenrol users | write |
| core_course_get_courses | Get list of all courses | read |
| core_course_create_courses | Create courses programmatically | write |
| core_course_delete_courses | Delete courses | write |
| core_course_get_contents | Get course sections & activities | read |
| gradereport_user_get_grade_items | Get all grade items for a user | read |
| mod_assign_get_assignments | Get assignment data | read |
| mod_assign_get_submissions | Get student submissions | read |
| mod_quiz_get_quizzes_by_courses | Get quizzes in a course | read |
| mod_forum_get_forums_by_courses | Get forums in a course | read |
| core_group_create_groups | Create course groups | write |
| core_group_add_group_members | Add users to groups | write |
| message_send_instant_messages | Send a message to a user | write |
| core_badges_get_user_badges | Get all badges for a user | read |
| core_completion_get_activities_completion | Get activity completion status | read |
Complete these hands-on exercises in your local MAMP/XAMPP Moodle sandbox.
Install Moodle locally using MAMP and create the moodledata directory outside the web root.
Create 3 course categories (Engineering, Business, Healthcare) with subcategories.
Upload 20 users via CSV — including teachers and students.
Build a Topics-format course with 5 sections, each containing a File and a URL resource.
Create a Forum activity and post 3 discussion threads.
Enable completion tracking on all activities and configure Course Completion.
Generate an Activity Completion Report and export it to CSV.
Explore the Site Administration panel — document every top-level menu item.
Import 15 GIFT-format quiz questions including MCQ, True/False, Matching and Short Answer types.
Create a timed 10-question randomised quiz drawing from a question bank of 30 questions.
Configure a Rubric grading method for an Essay assignment — 4 criteria, 4 levels each.
Create an H5P Interactive Video with embedded quiz questions at 3 timestamps.
Create a SCORM package using Articulate Rise (free trial) and deploy it to a Moodle course.
Configure Separate Groups in a Forum activity — test isolation between Group A and Group B.
Set up an OAuth 2.0 Google login integration for your local Moodle instance.
Configure and run the Automated Course Backup for 2 courses and verify .mbz files.
Restore a course backup from .mbz to a different category.
Write a custom SQL report using the Configurable Reports plugin to show students' last login.
Create a full local plugin: local_attendance with 2 web service functions registered in db/services.php.
Test your API via cURL — get_course_attendance and get_user_sessions.
Write a Python script that bulk-enrols 50 users to 3 courses via the REST API.
Write a Python script that exports grades for all courses and saves results to a CSV file.
Configure Redis as the session store and Memcached as the MUC cache on your local setup.
Configure Nginx security headers (CSP, HSTS, X-Frame-Options) for your Moodle instance.
Activate the Privacy Data Request workflow — request export and deletion for a test user.
Configure Moodle Analytics → train the "Students at risk" model and view predictions.
Write an Ansible playbook to deploy Moodle on a fresh Ubuntu 22.04 droplet end-to-end.
Build a nightly backup bash script that exports DB + moodledata + course backups to AWS S3.
Integrate BigBlueButton virtual classroom — host a live lecture with 5 test students.
Implement 2 Moodle Network (MNet) connections between two local Moodle instances.
php admin/cli/upgrade.php
php admin/cli/purge_caches.php
php admin/cli/backup.php \ --courseid=5 \ --destination=/backups/
php admin/tool/replace/cli/\ replace.php \ --search=http://old.com \ --replace=https://new.com
chown -R www-data:www-data /moodle chmod -R 755 /moodle chmod -R 777 /moodledata
mdl_user — All user accountsmdl_course — Course definitionsmdl_course_modules — Activities per coursemdl_grade_grades — Final gradesmdl_quiz_attempts — Quiz session datamdl_logstore_standard_log — Activity logmdl_enrol — Enrollment pluginsmdl_user_enrolments — Who is in what coursemdl_course_completions — Completion statusmdl_external_tokens — API tokens