{"id":5605,"date":"2026-05-04T08:32:13","date_gmt":"2026-05-04T08:32:13","guid":{"rendered":"https:\/\/www.cmsgalaxy.com\/blog\/?p=5605"},"modified":"2026-05-04T08:32:13","modified_gmt":"2026-05-04T08:32:13","slug":"complete-tutorial-upgrade-moodle-to-5-2-on-cpanel-shared-hosting-step-by-step","status":"publish","type":"post","link":"https:\/\/www.cmsgalaxy.com\/blog\/complete-tutorial-upgrade-moodle-to-5-2-on-cpanel-shared-hosting-step-by-step\/","title":{"rendered":"Complete Tutorial: Upgrade Moodle to 5.2 on cPanel \/ Shared Hosting Step by Step"},"content":{"rendered":"\n<p>This tutorial explains how to upgrade an existing Moodle site to <strong>Moodle 5.2<\/strong>, especially on a cPanel server where the main domain document root cannot be changed.<\/p>\n\n\n\n<p>This guide is based on a real upgrade scenario:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Domain: https:\/\/www.devopsschool.xyz\nMoodle root: \/home\/devopsschoolxyz\/public_html\nMoodle data: \/home\/devopsschoolxyz\/ds-moodledata\nPHP version: ea-php83\nDatabase: MariaDB\/MySQL\nHosting: cPanel \/ Apache\n<\/code><\/pre>\n\n\n\n<p>Moodle 5.2 requires Moodle <strong>4.4 or later<\/strong> as the upgrade source, PHP <strong>8.3 or later<\/strong>, 64-bit PHP, and the <code>sodium<\/code> PHP extension. Moodle 5.1+ also introduced the new <code>public\/<\/code> webroot structure, meaning the web server should serve the <code>public<\/code> directory rather than the full Moodle application directory. (<a href=\"https:\/\/moodledev.io\/general\/releases\/5.2?utm_source=chatgpt.com\">Moodle Developer Resources<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">1. What changed in Moodle 5.2?<\/h1>\n\n\n\n<p>Moodle 5.2 is not just a normal file replacement upgrade. The important change is the <strong>new public directory layout<\/strong>.<\/p>\n\n\n\n<p>Older Moodle versions usually worked like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/user\/public_html\/index.php\n\/home\/user\/public_html\/config.php\n\/home\/user\/public_html\/admin\/\n\/home\/user\/public_html\/lib\/\n\/home\/user\/public_html\/theme\/\n<\/code><\/pre>\n\n\n\n<p>Moodle 5.2 works like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/user\/public_html\/          \u2190 Moodle application root\n\/home\/user\/public_html\/public\/   \u2190 web-accessible document root\n\/home\/user\/config.php            \u2190 real Moodle config in some deployments\n<\/code><\/pre>\n\n\n\n<p>The root <code>index.php<\/code> in Moodle 5.2 intentionally blocks direct access outside the public webroot. This is expected behavior, not a broken package. Moodle documentation says Apache should point the document root to the <code>public<\/code> directory, and router support should be configured using <code>FallbackResource \/r.php<\/code> when possible. (<a href=\"https:\/\/docs.moodle.org\/en\/Apache?utm_source=chatgpt.com\">Moodle Docs<\/a>)<\/p>\n\n\n\n<p>On cPanel, the main domain often cannot be changed from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/user\/public_html\n<\/code><\/pre>\n\n\n\n<p>to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/user\/public_html\/public\n<\/code><\/pre>\n\n\n\n<p>So we use an <code>.htaccess<\/code> routing workaround.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">2. Before You Start<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">2.1 Check current Moodle version<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\ngrep '$release' version.php\ngrep '$branch' version.php\ngrep '$version' version.php\n<\/code><\/pre>\n\n\n\n<p>Example old output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$release  = '5.0.1 (Build: 20250609)';\n$branch   = '500';\n<\/code><\/pre>\n\n\n\n<p>If your database is already newer than your code, Moodle may show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ERROR!!! The code you are using is OLDER than the version that made these databases!\n<\/code><\/pre>\n\n\n\n<p>That means you must upgrade the Moodle files to match or exceed the database version.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2.2 Check database version from Moodle DB<\/h2>\n\n\n\n<p>First check DB name and prefix:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep dbname config.php\ngrep prefix config.php\n<\/code><\/pre>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$CFG-&gt;dbname = 'devopsschoolxyz_lms';\n$CFG-&gt;prefix = 'mdl_';\n<\/code><\/pre>\n\n\n\n<p>Then in phpMyAdmin, run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT name, value\nFROM mdl_config\nWHERE name IN ('version','release','branch');\n<\/code><\/pre>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>branch  = 500\nrelease = 5.0.1\nversion = 2025041401\n<\/code><\/pre>\n\n\n\n<p>If database says 5.0.1 but files say 4.2.5, you must install Moodle 5.0.1 or newer files.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">3. Backup Everything<\/h1>\n\n\n\n<p>Do not skip this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3.1 Backup Moodle code and config<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\nmkdir -p ~\/moodle-backups\n\ntar -czf ~\/moodle-backups\/moodle-files-before-52-$(date +%F-%H%M%S).tar.gz \\\n  ~\/public_html \\\n  ~\/config.php \\\n  ~\/public_html\/config.php \\\n  ~\/public_html\/.htaccess 2&gt;\/dev\/null\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3.2 Backup Moodle database<\/h2>\n\n\n\n<p>If your real config is in <code>~\/config.php<\/code>, use this command to read DB details from the config and create a dump:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -r '$c=file_get_contents(getenv(\"HOME\").\"\/config.php\"); foreach(&#91;\"dbname\",\"dbuser\",\"dbpass\"] as $k){ if(!preg_match(\"\/\\\\$CFG-&gt;$k\\s*=\\s*'\\''(&#91;^'\\'']*)'\\'';\/\",$c,$m)){fwrite(STDERR,\"Missing $k\\n\"); exit(1);} $$k=$m&#91;1]; } $out=getenv(\"HOME\").\"\/moodle-db-\".date(\"Ymd-His\").\".sql.gz\"; $cmd=\"mysqldump --single-transaction --quick --routines --triggers -u\".escapeshellarg($dbuser).\" -p\".escapeshellarg($dbpass).\" \".escapeshellarg($dbname).\" | gzip &gt; \".escapeshellarg($out); passthru($cmd,$code); if($code===0){echo \"DB dump created: $out\\n\";} else {echo \"DB dump failed\\n\"; exit($code);}'\n<\/code><\/pre>\n\n\n\n<p>Expected output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DB dump created: \/home\/devopsschoolxyz\/moodle-db-20260503-193000.sql.gz\n<\/code><\/pre>\n\n\n\n<p>If your real config is still inside <code>~\/public_html\/config.php<\/code>, change this part:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>getenv(\"HOME\").\"\/config.php\"\n<\/code><\/pre>\n\n\n\n<p>to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>getenv(\"HOME\").\"\/public_html\/config.php\"\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">4. Prepare PHP 8.3<\/h1>\n\n\n\n<p>Moodle 5.2 requires PHP 8.3 or newer. Moodle 5.2 also requires a modern PHP environment, including <code>sodium<\/code>; common Moodle extensions include <code>mysqli<\/code>, <code>pdo_mysql<\/code>, <code>mbstring<\/code>, <code>intl<\/code>, <code>curl<\/code>, <code>zip<\/code>, <code>gd<\/code>, <code>soap<\/code>, <code>fileinfo<\/code>, <code>exif<\/code>, <code>iconv<\/code>, XML extensions, and OpenSSL. (<a href=\"https:\/\/moodledev.io\/general\/releases\/5.2?utm_source=chatgpt.com\">Moodle Developer Resources<\/a>)<\/p>\n\n\n\n<p>Check PHP version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -v\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PHP 8.3.x\n<\/code><\/pre>\n\n\n\n<p>Check required PHP extensions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -m | grep -Ei \"mysqli|mysqlnd|pdo_mysql|iconv|intl|mbstring|xml|simplexml|dom|curl|zip|gd|soap|sodium|fileinfo|exif|openssl\"\n<\/code><\/pre>\n\n\n\n<p>Good output example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl\ndom\nexif\nfileinfo\ngd\niconv\nintl\nmbstring\nmysqli\nmysqlnd\nopenssl\npdo_mysql\nSimpleXML\nsoap\nsodium\nxml\nxmlreader\nxmlwriter\nzip\n<\/code><\/pre>\n\n\n\n<p>If some extensions are missing, enable them in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cPanel \u2192 Select PHP Version \u2192 Extensions\n<\/code><\/pre>\n\n\n\n<p>or:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cPanel \u2192 MultiPHP INI Editor\n<\/code><\/pre>\n\n\n\n<p>If you have WHM\/root access, install EasyApache packages for PHP 8.3.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">5. Set PHP Handler in <code>.htaccess<\/code><\/h1>\n\n\n\n<p>Check current PHP handler:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -i \"AddHandler\" ~\/public_html\/.htaccess\n<\/code><\/pre>\n\n\n\n<p>For PHP 8.3, you want something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AddHandler application\/x-httpd-ea-php83 .php .php8 .phtml\n<\/code><\/pre>\n\n\n\n<p>If needed, update <code>.htaccess<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ~\/public_html\/.htaccess &lt;&lt;'EOF'\n# Moodle 5.2 public directory routing\n&lt;IfModule mod_rewrite.c&gt;\n  RewriteEngine On\n\n  # Block Git files\n  RewriteRule (^|\/)\\.git(\/|$) - &#91;F,L]\n  RewriteRule (^|\/)\\.gitignore$ - &#91;F,L]\n  RewriteRule (^|\/)\\.gitmodules$ - &#91;F,L]\n\n  # Route all web requests to Moodle public directory\n  RewriteRule ^$ public\/ &#91;L]\n  RewriteRule ^((?!public\/).*)$ public\/$1 &#91;L]\n&lt;\/IfModule&gt;\n\n# php -- BEGIN cPanel-generated handler, do not edit\n&lt;IfModule mime_module&gt;\n  AddHandler application\/x-httpd-ea-php83 .php .php8 .phtml\n&lt;\/IfModule&gt;\n# php -- END cPanel-generated handler, do not edit\nEOF\n<\/code><\/pre>\n\n\n\n<p>This is needed when cPanel does not allow changing the main domain document root to <code>public_html\/public<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">6. Download Moodle 5.2<\/h1>\n\n\n\n<p>Download the Moodle 5.2 package outside <code>public_html<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\nrm -rf moodle moodle-5.2.tgz\nwget -O moodle-5.2.tgz https:\/\/download.moodle.org\/download.php\/direct\/stable502\/moodle-latest-502.tgz\ntar -xzf moodle-5.2.tgz\n<\/code><\/pre>\n\n\n\n<p>Verify package:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls -la ~\/moodle\/version.php\ngrep '$release' ~\/moodle\/version.php\ngrep '$branch' ~\/moodle\/version.php\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$release = '5.2+ ...'\n$branch  = '502'\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">7. Copy Moodle 5.2 Files Into Existing <code>public_html<\/code><\/h1>\n\n\n\n<p>If your hosting has low memory, <code>rsync<\/code> may fail with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>rsync error: error allocating core memory buffers\n<\/code><\/pre>\n\n\n\n<p>Use <code>tar<\/code> streaming instead.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/moodle\ntar --exclude='.\/config.php' --exclude='.\/.git' --exclude='.\/.htaccess' -cf - . | (cd ~\/public_html &amp;&amp; tar -xpf -)\n<\/code><\/pre>\n\n\n\n<p>Verify:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep '$release' ~\/public_html\/version.php\ngrep '$branch' ~\/public_html\/version.php\nls ~\/public_html\/admin\/cli\/upgrade.php\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$release = '5.2+ ...'\n$branch  = '502'\n\/home\/devopsschoolxyz\/public_html\/admin\/cli\/upgrade.php\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">8. Understand the Moodle 5.2 Config File Layout<\/h1>\n\n\n\n<p>In Moodle 5.2, <code>public_html\/config.php<\/code> may be a loader file that loads the real config from one directory above:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/config.php\n<\/code><\/pre>\n\n\n\n<p>Your real Moodle config should contain database settings and these paths:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$CFG-&gt;wwwroot   = 'https:\/\/www.devopsschool.xyz';\n$CFG-&gt;dataroot  = '\/home\/devopsschoolxyz\/ds-moodledata';\n$CFG-&gt;dirroot   = '\/home\/devopsschoolxyz\/public_html';\n$CFG-&gt;libdir    = $CFG-&gt;dirroot . '\/lib';\n$CFG-&gt;admin     = 'admin';\n\nrequire_once($CFG-&gt;dirroot . '\/lib\/setup.php');\n<\/code><\/pre>\n\n\n\n<p>Check real config:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nl -ba ~\/config.php | sed -n '1,60p'\n<\/code><\/pre>\n\n\n\n<p>If <code>dirroot<\/code> is missing, add it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"CFG-&gt;dirroot\" ~\/config.php || sed -i \"\/CFG-&gt;dataroot\/a \\$CFG-&gt;dirroot   = '\/home\/devopsschoolxyz\/public_html';\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>If <code>libdir<\/code> is missing, add it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"CFG-&gt;libdir\" ~\/config.php || sed -i \"\/CFG-&gt;dirroot\/a \\$CFG-&gt;libdir    = \\$CFG-&gt;dirroot . '\/lib';\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Make sure <code>require_once<\/code> uses <code>$CFG-&gt;dirroot<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep \"require_once\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Correct:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>require_once($CFG-&gt;dirroot . '\/lib\/setup.php');\n<\/code><\/pre>\n\n\n\n<p>Wrong:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>require_once(__DIR__ . '\/lib\/setup.php');\n<\/code><\/pre>\n\n\n\n<p>If wrong, fix:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sed -i \"s#require_once(__DIR__ . '\/lib\/setup.php');#require_once(\\$CFG-&gt;dirroot . '\/lib\/setup.php');#\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Now clean the loader file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ~\/public_html\/config.php &lt;&lt;'EOF'\n&lt;?php\n$configfile = __DIR__ . '\/..\/config.php';\nif (!file_exists($configfile)) {\n    header(\"Location: install.php\");\n    die;\n}\nrequire_once($configfile);\nEOF\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">9. Configure Moodle 5.2 Public Webroot Routing<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Best option<\/h2>\n\n\n\n<p>If you can change the domain document root, set it to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/public_html\/public\n<\/code><\/pre>\n\n\n\n<p>But on many cPanel main domains, this is not possible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">cPanel workaround<\/h2>\n\n\n\n<p>Keep this in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/public_html\/.htaccess\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># Moodle 5.2 public directory routing\n&lt;IfModule mod_rewrite.c&gt;\n  RewriteEngine On\n\n  # Block Git files\n  RewriteRule (^|\/)\\.git(\/|$) - &#91;F,L]\n  RewriteRule (^|\/)\\.gitignore$ - &#91;F,L]\n  RewriteRule (^|\/)\\.gitmodules$ - &#91;F,L]\n\n  # Route all web requests to Moodle public directory\n  RewriteRule ^$ public\/ &#91;L]\n  RewriteRule ^((?!public\/).*)$ public\/$1 &#91;L]\n&lt;\/IfModule&gt;\n\n# php -- BEGIN cPanel-generated handler, do not edit\n&lt;IfModule mime_module&gt;\n  AddHandler application\/x-httpd-ea-php83 .php .php8 .phtml\n&lt;\/IfModule&gt;\n# php -- END cPanel-generated handler, do not edit\n<\/code><\/pre>\n\n\n\n<p>Then configure router fallback inside:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/public_html\/public\/.htaccess\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ~\/public_html\/public\/.htaccess &lt;&lt;'EOF'\nDirectoryIndex index.php\nFallbackResource \/r.php\nEOF\n<\/code><\/pre>\n\n\n\n<p>Add router flag in Moodle config:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"routerconfigured\" ~\/config.php || sed -i \"\/CFG-&gt;libdir\/a \\$CFG-&gt;routerconfigured = true;\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Moodle\u2019s upgrade\/router docs recommend <code>FallbackResource \/r.php<\/code> for Apache routing; if you cannot configure Apache globally, Moodle says the fallback can be placed in an override file such as <code>.htaccess<\/code> where allowed. (<a href=\"https:\/\/docs.moodle.org\/en\/Upgrading?utm_source=chatgpt.com\">Moodle Docs<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">10. Run Moodle Upgrade<\/h1>\n\n\n\n<p>Run upgrade:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/upgrade.php\n<\/code><\/pre>\n\n\n\n<p>Possible good output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>No upgrade needed for the installed version 5.2+ ...\n<\/code><\/pre>\n\n\n\n<p>or it may run database upgrade steps.<\/p>\n\n\n\n<p>Then purge Moodle caches:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<p>Clear file caches:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -rf \/home\/devopsschoolxyz\/ds-moodledata\/cache\/*\nrm -rf \/home\/devopsschoolxyz\/ds-moodledata\/localcache\/*\nrm -rf \/home\/devopsschoolxyz\/ds-moodledata\/temp\/*\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">11. Fix <code>max_input_vars<\/code><\/h1>\n\n\n\n<p>Moodle environment check may show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PHP setting max_input_vars must be at least 5000.\n<\/code><\/pre>\n\n\n\n<p>Create <code>.user.ini<\/code> files:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat &gt; ~\/public_html\/.user.ini &lt;&lt;'EOF'\nmax_input_vars = 5000\nEOF\n\ncat &gt; ~\/public_html\/public\/.user.ini &lt;&lt;'EOF'\nmax_input_vars = 5000\nEOF\n<\/code><\/pre>\n\n\n\n<p>Also set it in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cPanel \u2192 MultiPHP INI Editor \u2192 devopsschool.xyz\n<\/code><\/pre>\n\n\n\n<p>Add:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>max_input_vars = 5000\n<\/code><\/pre>\n\n\n\n<p>Verify CLI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -i | grep max_input_vars\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>max_input_vars =&gt; 5000 =&gt; 5000\n<\/code><\/pre>\n\n\n\n<p>Note: Moodle\u2019s browser environment check uses <strong>web PHP<\/strong>, so cPanel MultiPHP INI Editor is usually the most reliable place to set it.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">12. Fix Composer Installed Data Warning<\/h1>\n\n\n\n<p>Moodle may show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Composer installed data not found\nComposer dependencies were not found.\nMake sure the \"composer install --no-dev --classmap-authoritative\" command has been run.\n<\/code><\/pre>\n\n\n\n<p>If <code>composer<\/code> uses PHP 8.2 by default, you may get:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Root composer.json requires php &gt;=8.3.0 but your php version (8.2.30) does not satisfy that requirement.\n<\/code><\/pre>\n\n\n\n<p>Run Composer using PHP 8.3:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\nCOMPOSER_MEMORY_LIMIT=-1 \/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php $(which composer) install --no-dev --classmap-authoritative\n<\/code><\/pre>\n\n\n\n<p>If Composer path is unknown:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>which composer\ntype composer\nfind \/usr\/local\/bin \/usr\/bin \/opt\/cpanel -name composer -o -name composer.phar 2&gt;\/dev\/null\n<\/code><\/pre>\n\n\n\n<p>Then run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\nCOMPOSER_MEMORY_LIMIT=-1 \/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php \/path\/to\/composer install --no-dev --classmap-authoritative\n<\/code><\/pre>\n\n\n\n<p>After Composer finishes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<p>If Composer fails due to hosting memory limits, run Composer on another server or local machine using the same Moodle 5.2 files, then upload the generated <code>vendor\/<\/code> directory to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/public_html\/vendor\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">13. Fix Router Not Configured Warning<\/h1>\n\n\n\n<p>If Moodle shows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Router not configured\n<\/code><\/pre>\n\n\n\n<p>Make sure this exists:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat ~\/public_html\/public\/.htaccess\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DirectoryIndex index.php\nFallbackResource \/r.php\n<\/code><\/pre>\n\n\n\n<p>Make sure config has:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep routerconfigured ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$CFG-&gt;routerconfigured = true;\n<\/code><\/pre>\n\n\n\n<p>If missing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"routerconfigured\" ~\/config.php || sed -i \"\/CFG-&gt;libdir\/a \\$CFG-&gt;routerconfigured = true;\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<p>Then purge caches:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">14. Enable Asynchronous Backups<\/h1>\n\n\n\n<p>Moodle may show:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Asynchronous backups disabled\n<\/code><\/pre>\n\n\n\n<p>Enable it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/cfg.php --name=enableasyncbackup --set=1\n<\/code><\/pre>\n\n\n\n<p>Purge caches:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<p>Important: asynchronous backups depend on cron. If cron is broken, backups may queue but not process.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">15. Run Moodle Environment Checks<\/h1>\n\n\n\n<p>Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/checks.php\n<\/code><\/pre>\n\n\n\n<p>Also check in browser:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Site administration \u2192 Server \u2192 Environment\n<\/code><\/pre>\n\n\n\n<p>Common issues and fixes:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Check<\/th><th>Fix<\/th><\/tr><\/thead><tbody><tr><td><code>max_input_vars<\/code> too low<\/td><td>Set <code>max_input_vars = 5000<\/code><\/td><\/tr><tr><td>Composer data missing<\/td><td>Run Composer with PHP 8.3<\/td><\/tr><tr><td>Router not configured<\/td><td>Add <code>FallbackResource \/r.php<\/code> and <code>$CFG-&gt;routerconfigured = true<\/code><\/td><\/tr><tr><td>Async backups disabled<\/td><td>Set <code>enableasyncbackup = 1<\/code><\/td><\/tr><tr><td>Cron not running<\/td><td>Add cPanel cron job<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">16. Configure Cron<\/h1>\n\n\n\n<p>Moodle cron should run every minute.<\/p>\n\n\n\n<p>In cPanel Cron Jobs, add:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>* * * * * \/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php \/home\/devopsschoolxyz\/public_html\/admin\/cli\/cron.php &gt;\/dev\/null 2&gt;&amp;1\n<\/code><\/pre>\n\n\n\n<p>Manual test:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php admin\/cli\/cron.php\n<\/code><\/pre>\n\n\n\n<p>If you see memory errors like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mmap() failed: Cannot allocate memory\n<\/code><\/pre>\n\n\n\n<p>check limits:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>free -m\nulimit -a\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -i | grep -i \"memory_limit\\|opcache\"\n<\/code><\/pre>\n\n\n\n<p>On shared hosting, CloudLinux\/LVE memory limits can break cron even if the server itself has free RAM. In that case, increase account memory limits or move Moodle to a VPS.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">17. Verify Site From Command Line<\/h1>\n\n\n\n<p>Test homepage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -k -I 'https:\/\/www.devopsschool.xyz\/'\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 200\n<\/code><\/pre>\n\n\n\n<p>Test login page:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -k -I 'https:\/\/www.devopsschool.xyz\/login\/index.php'\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 200\n<\/code><\/pre>\n\n\n\n<p>If you see <code>500<\/code>, check logs.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">18. Check Logs<\/h1>\n\n\n\n<p>For cPanel, there may be more than one error log.<\/p>\n\n\n\n<p>Check common logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tail -n 80 ~\/public_html\/error_log\ntail -n 80 \/home\/devopsschoolxyz\/logs\/devopsschool_xyz.php.error.log\n<\/code><\/pre>\n\n\n\n<p>Find recent logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>find \/home\/devopsschoolxyz -type f \\( -name \"error_log\" -o -name \"*.log\" \\) -mmin -20 -printf \"%TY-%Tm-%Td %TH:%TM %p\\n\" 2&gt;\/dev\/null | sort\n<\/code><\/pre>\n\n\n\n<p>To clear logs before testing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>: &gt; ~\/public_html\/error_log\n: &gt; \/home\/devopsschoolxyz\/logs\/devopsschool_xyz.php.error.log\n<\/code><\/pre>\n\n\n\n<p>Then hit the failing URL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -k -I 'https:\/\/www.devopsschool.xyz\/login\/index.php'\n<\/code><\/pre>\n\n\n\n<p>Then read logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tail -n 80 ~\/public_html\/error_log \/home\/devopsschoolxyz\/logs\/devopsschool_xyz.php.error.log\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">19. Install a Moodle 5.2-Compatible Theme: Moove<\/h1>\n\n\n\n<p>Moove is a good theme for training LMS sites. It has a Moodle 5.2-compatible version, and it works well for learner-focused course portals.<\/p>\n\n\n\n<p>Install Moove:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\n\necho \"===== Backup current Moodle config + theme folder =====\"\nmkdir -p ~\/moodle-theme-backups\ntar -czf ~\/moodle-theme-backups\/before-moove-$(date +%F-%H%M%S).tar.gz \\\n  ~\/config.php \\\n  ~\/public_html\/config.php \\\n  ~\/public_html\/theme \\\n  ~\/public_html\/.htaccess\n\necho \"===== Download Moove theme =====\"\nrm -rf \/tmp\/moove.zip \/tmp\/moodle-theme_moove-main \/tmp\/moove-install\nmkdir -p \/tmp\/moove-install\n\nwget -O \/tmp\/moove.zip https:\/\/github.com\/willianmano\/moodle-theme_moove\/archive\/refs\/heads\/main.zip\n\necho \"===== Extract Moove =====\"\nunzip -q \/tmp\/moove.zip -d \/tmp\/moove-install\n\necho \"===== Install into Moodle theme directory =====\"\nrm -rf ~\/public_html\/theme\/moove\nmv \/tmp\/moove-install\/moodle-theme_moove-main ~\/public_html\/theme\/moove\n\necho \"===== Permissions =====\"\nfind ~\/public_html\/theme\/moove -type d -exec chmod 755 {} \\;\nfind ~\/public_html\/theme\/moove -type f -exec chmod 644 {} \\;\n\necho \"===== Verify theme version =====\"\ngrep \"plugin-&gt;component\\|plugin-&gt;version\\|plugin-&gt;requires\\|plugin-&gt;supported\" ~\/public_html\/theme\/moove\/version.php\n\necho \"===== Run Moodle upgrade =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/upgrade.php --non-interactive\n\necho \"===== Set Moove as active theme =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/cfg.php --name=theme --set=moove\n\necho \"===== Purge caches =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n\necho \"===== Test site =====\"\ncurl -k -I 'https:\/\/www.devopsschool.xyz\/'\ncurl -k -I 'https:\/\/www.devopsschool.xyz\/login\/index.php'\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HTTP\/2 200\nHTTP\/2 200\n<\/code><\/pre>\n\n\n\n<p>If the theme does not appear in Moodle UI, force plugin scan:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\n\nfind theme\/moove -type d -exec chmod 755 {} \\;\nfind theme\/moove -type f -exec chmod 644 {} \\;\n\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php admin\/cli\/upgrade.php --non-interactive\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<p>Then check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Site administration \u2192 Plugins \u2192 Plugins overview\n<\/code><\/pre>\n\n\n\n<p>Search for:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Moove\n<\/code><\/pre>\n\n\n\n<p>Then select it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Site administration \u2192 Appearance \u2192 Theme selector\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">20. Final Verification Checklist<\/h1>\n\n\n\n<p>Run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"===== Moodle version =====\"\ngrep '$release' ~\/public_html\/version.php\ngrep '$branch' ~\/public_html\/version.php\n\necho \"===== PHP version =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -v\n\necho \"===== PHP modules =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -m | grep -Ei \"mysqli|pdo_mysql|iconv|intl|mbstring|curl|zip|gd|soap|sodium|fileinfo|exif|xml|dom|simplexml\"\n\necho \"===== Moodle CLI checks =====\"\n\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/checks.php\n\necho \"===== URLs =====\"\ncurl -k -I 'https:\/\/www.devopsschool.xyz\/'\ncurl -k -I 'https:\/\/www.devopsschool.xyz\/login\/index.php'\n<\/code><\/pre>\n\n\n\n<p>Good final result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Moodle 5.2+\nBranch 502\nPHP 8.3.x\nHomepage HTTP\/2 200\nLogin HTTP\/2 200\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">21. Common Errors and Fixes<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Error: <code>Moodle requires the iconv PHP extension<\/code><\/h2>\n\n\n\n<p>Check CLI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -m | grep iconv\n<\/code><\/pre>\n\n\n\n<p>If missing, enable <code>iconv<\/code> for PHP 8.3 in cPanel.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Error: <code>database driver problem detected<\/code><\/h2>\n\n\n\n<p>Usually missing MySQL extensions.<\/p>\n\n\n\n<p>Check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php -m | grep -Ei \"mysqli|mysqlnd|pdo_mysql\"\n<\/code><\/pre>\n\n\n\n<p>Expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mysqli\nmysqlnd\npdo_mysql\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Error: <code>Undefined property: stdClass::$libdir<\/code><\/h2>\n\n\n\n<p>Your real config is missing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$CFG-&gt;libdir = $CFG-&gt;dirroot . '\/lib';\n<\/code><\/pre>\n\n\n\n<p>Add:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -q \"CFG-&gt;libdir\" ~\/config.php || sed -i \"\/CFG-&gt;dirroot\/a \\$CFG-&gt;libdir    = \\$CFG-&gt;dirroot . '\/lib';\" ~\/config.php\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Error: root index throws <code>rootdirpublic<\/code><\/h2>\n\n\n\n<p>This is expected in Moodle 5.2 if Apache serves the wrong directory.<\/p>\n\n\n\n<p>Fix by either:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DocumentRoot \u2192 \/home\/user\/public_html\/public\n<\/code><\/pre>\n\n\n\n<p>or use <code>.htaccess<\/code> rewrite in <code>public_html<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Error: Homepage works but login gives 500<\/h2>\n\n\n\n<p>Check:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tail -n 80 \/home\/devopsschoolxyz\/logs\/devopsschool_xyz.php.error.log ~\/public_html\/error_log\n<\/code><\/pre>\n\n\n\n<p>Common causes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>missing PHP extension\nwrong config.php loader\nmissing $CFG-&gt;libdir\nmissing Composer vendor files\nrouting not configured\ntheme\/plugin issue\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Error: <code>Composer installed data not found<\/code><\/h2>\n\n\n\n<p>Run Composer using PHP 8.3:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/public_html\nCOMPOSER_MEMORY_LIMIT=-1 \/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php $(which composer) install --no-dev --classmap-authoritative\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">22. Rollback Plan<\/h1>\n\n\n\n<p>If upgrade fails badly:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Restore files<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\ntar -xzf ~\/moodle-backups\/moodle-files-before-52-YYYY-MM-DD-HHMMSS.tar.gz -C \/\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Restore database<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>gunzip &lt; ~\/moodle-db-YYYYMMDD-HHMMSS.sql.gz | mysql -u DBUSER -p DBNAME\n<\/code><\/pre>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gunzip &lt; ~\/moodle-db-20260503-193000.sql.gz | mysql -u devopsschoolxyz_user -p devopsschoolxyz_lms\n<\/code><\/pre>\n\n\n\n<p>Then purge cache:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/purge_caches.php\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">23. Security Cleanup After Upgrade<\/h1>\n\n\n\n<p>If you pasted or exposed the DB password during troubleshooting, rotate it.<\/p>\n\n\n\n<p>Steps:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cPanel \u2192 MySQL Databases \u2192 MySQL Users \u2192 Change Password\n<\/code><\/pre>\n\n\n\n<p>Then update:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/config.php\n<\/code><\/pre>\n\n\n\n<p>Change:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$CFG-&gt;dbpass = 'NEW_PASSWORD_HERE';\n<\/code><\/pre>\n\n\n\n<p>Then test:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/opt\/cpanel\/ea-php83\/root\/usr\/bin\/php ~\/public_html\/admin\/cli\/upgrade.php\ncurl -k -I 'https:\/\/www.devopsschool.xyz\/'\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">24. Summary<\/h1>\n\n\n\n<p>You upgraded Moodle successfully when these conditions were true:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Moodle files: 5.2+\nBranch: 502\nPHP: 8.3\nRequired PHP extensions: installed\npublic\/ routing: configured\nrouter: configured\nComposer dependencies: installed or vendor exists\nhomepage: HTTP 200\nlogin page: HTTP 200\n<\/code><\/pre>\n\n\n\n<p>The biggest Moodle 5.2 lesson:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Do not flatten Moodle 5.2.\nDo not copy public\/ contents into root.\nDo not edit Moodle core files.\nConfigure Apache\/cPanel routing correctly.\n<\/code><\/pre>\n\n\n\n<p>For cPanel shared hosting, the practical final structure is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/devopsschoolxyz\/public_html          Moodle application root\n\/home\/devopsschoolxyz\/public_html\/public   Moodle public webroot\n\/home\/devopsschoolxyz\/config.php           real Moodle config\n\/home\/devopsschoolxyz\/ds-moodledata        Moodle data directory\n<\/code><\/pre>\n\n\n\n<p>That gives you a clean Moodle 5.2 upgrade path without changing core Moodle code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial explains how to upgrade an existing Moodle site to Moodle 5.2, especially on a cPanel server where the<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5605","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/comments?post=5605"}],"version-history":[{"count":1,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5605\/revisions"}],"predecessor-version":[{"id":5606,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/posts\/5605\/revisions\/5606"}],"wp:attachment":[{"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/media?parent=5605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/categories?post=5605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cmsgalaxy.com\/blog\/wp-json\/wp\/v2\/tags?post=5605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}