A fresh MediaWiki install is deceptively open. The software assumes a trusted administrator will configure additional protection after setup, so out of the box it leaves account registration public, serves the maintenance/ directory to anyone who browses to it, and relies entirely on the web server to protect the one file that contains your database password. On a LiteSpeed shared hosting account, that combination quietly accumulates risk: automated bots probe for open wiki registration within hours of a domain going live, spam accounts begin editing pages, and a single misconfigured directory can leak the contents of LocalSettings.php. None of the fixes below require root, SSH administration, or server-wide changes. Everything is done through cPanel File Manager, phpMyAdmin, .htaccess, and the wiki's own configuration file.

Protecting LocalSettings.php and sensitive directories

The file LocalSettings.php lives in your document root (typically /home/username/public_html/ or a subfolder like /home/username/public_html/wiki/) and holds your database host, username, password, and the secret keys that sign sessions and tokens. PHP normally executes this file rather than displaying it, so visitors see nothing. The danger appears when PHP handling breaks during an upgrade or a misconfiguration, because the server can then fall back to serving the raw file as plain text. Anyone who downloads it gains your database credentials and $wgSecretKey, which is enough to forge login sessions.

Start by correcting permissions in cPanel File Manager. Navigate to the directory containing LocalSettings.php, right-click the file, choose Change Permissions, and set it to 600 (owner read and write only). On CloudLinux the PHP process runs as your own user, so 600 is enough for MediaWiki to read it while blocking any other account. Directories should be 755 and other PHP files 644. Avoid 777 anywhere; it is never required on a CloudLinux account and is a frequent cause of compromise.

Add a defensive rule so that even a broken PHP handler cannot expose the file. Open or create the .htaccess file in your wiki root and add:

<FilesMatch "\.(php~|php\.bak|inc|sql|conf|ini)$">
    Require all denied
</FilesMatch>

<Files "LocalSettings.php">
    Require all denied
</Files>

Blocking LocalSettings.php at the .htaccess level is safe because MediaWiki includes the file through PHP's internal require, which bypasses the web server's access rules entirely. The Require all denied directive only affects direct HTTP requests. Next, seal off the directories that should never be reachable over the web. MediaWiki's maintenance/, includes/, languages/, and serialized/ folders contain scripts and data that have no business being requested directly:

RewriteEngine On
RewriteRule ^(maintenance|includes|languages|serialized|tests|vendor)/ - [F,L]

Finally, confirm that the images/ upload directory cannot execute scripts. Place a dedicated .htaccess inside images/ with php_flag engine off and a rule denying execution of .php, .phtml, and .cgi files, so an attacker who tricks the uploader into accepting a disguised script cannot run it.

Closing open registration and stopping spam

The single most common abuse of a public MediaWiki is automated account creation followed by spam edits and link injection. The defaults permit anyone to register and edit, which suits a large open community but is wrong for the vast majority of private or small wikis. These settings live in LocalSettings.php, which you edit through cPanel File Manager by right-clicking the file and choosing Edit.

To require that only existing accounts can create new ones, and to prevent anonymous and new users from editing, add:

$wgGroupPermissions['*']['createaccount']   = false;
$wgGroupPermissions['*']['edit']            = false;
$wgGroupPermissions['user']['edit']         = true;
$wgGroupPermissions['*']['read']            = true;

If you want a fully private wiki where even reading requires login, set $wgGroupPermissions['*']['read'] = false; instead. For wikis that must keep registration open, install the bundled ConfirmEdit extension and enable a CAPTCHA, which ships with MediaWiki and only needs activation:

wfLoadExtension( 'ConfirmEdit' );
wfLoadExtension( 'ConfirmEdit/QuestyCaptcha' );
$wgCaptchaClass = 'MediaWiki\\Extension\\ConfirmEdit\\QuestyCaptcha\\QuestyCaptcha';
$wgCaptchaQuestions[] = [ 'question' => 'What is two plus three?', 'answer' => '5' ];
$wgCaptchaTriggers['edit']          = true;
$wgCaptchaTriggers['createaccount'] = true;
$wgCaptchaTriggers['addurl']        = true;

QuestyCaptcha avoids external dependencies, which matters on shared hosting where outbound connections to reCAPTCHA services can be slow or blocked. The addurl trigger forces a CAPTCHA whenever an edit introduces an external link, which stops the overwhelming majority of link-spam bots. You can further reduce noise with the SpamBlacklist extension, enabling it the same way and pointing $wgSpamBlacklistFiles at the Wikimedia-maintained list so known spam domains are rejected before they ever save.

Clean up accounts that slipped through earlier by opening phpMyAdmin from cPanel, selecting your wiki database, and reviewing the user table ordered by user_registration descending. Cross-reference suspicious rows against the logging table before removing anything, and always take a database export through phpMyAdmin's Export tab first.

Strengthening authentication and adding HTTP security headers

Admin and login endpoints are the next target for brute-force scripts, which hammer index.php?title=Special:UserLogin with credential lists. MediaWiki includes a throttle you can tighten in LocalSettings.php. The following limits login attempts to five per account every five minutes and rejects weak passwords:

$wgPasswordAttemptThrottle = [
    [ 'count' => 5, 'seconds' => 300 ],
    [ 'count' => 15, 'seconds' => 86400 ],
];

$wgPasswordPolicy['policies']['default']['MinimalPasswordLength'] = 10;
$wgPasswordPolicy['policies']['sysop']['MinimalPasswordLength']   = 12;
$wgPasswordPolicy['policies']['sysop']['PasswordCannotMatchUsername'] = true;

For an extra layer in front of the login and admin pages, you can add HTTP Basic authentication through cPanel. Use the Directory Privacy tool (listed as Password Protect Directories in the Jupiter theme), but apply it carefully: protecting the whole document root breaks the public wiki, so instead create a scoped .htaccess rule only on the sensitive query string. A cleaner approach on LiteSpeed is to rely on the throttle plus a CAPTCHA on login via the ConfirmEdit $wgCaptchaTriggers['loginattempt'] = true; trigger, which avoids interfering with legitimate readers.

HTTP security headers close off a class of browser-side attacks and cost nothing to deploy. LiteSpeed honors standard Header directives, so add these to the wiki root .htaccess:

<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</IfModule>

Only enable Strict-Transport-Security after you have confirmed a valid SSL certificate is installed through cPanel's SSL/TLS Status page and that the site redirects HTTP to HTTPS, because the header will otherwise lock visitors out of an insecure fallback. Set $wgServer = 'https://yourdomain.com'; and $wgForceHTTPS = true; in LocalSettings.php so MediaWiki generates secure URLs consistently. A Content-Security-Policy header is powerful but needs careful tuning against MediaWiki's inline scripts and skin assets; begin in report-only mode and widen the allow-list before enforcing it.

After each change, reload the wiki and watch for problems in the error_log file that appears in your wiki directory through File Manager. A blank page or 500 error after editing LocalSettings.php almost always means a stray syntax error such as a missing semicolon, and the log will name the offending line. Managing trusted hostnames and canonical URLs after a domain move follows the same pattern seen in our ownCloud migration and trusted_domains guide, where the configuration file is the single source of truth. Work through these layers in order, verify the wiki still loads for a normal visitor after each one, and keep a dated export of both files and database so any hardening step can be rolled back cleanly.