How to Secure MediaWiki with SSL and HSTS
Why HTTPS matters for MediaWiki
MediaWiki stores user passwords, edit tokens and personal data in clear‑text when it is accessed via HTTP. An attacker on the same network can intercept those values, hijack sessions and even rewrite page content. Enforcing HTTPS encrypts the traffic between the browser and the server and lets the browser verify the server’s identity. Once HTTPS is in place, adding HSTS tells browsers to never fall back to HTTP again, protecting you from SSL‑stripping attacks.
StepÊf1Êf–ÊfObtain an SSL certificate
For most wikis a free Let’s Encrypt certificate is sufficient. The certificate can be obtained with certbot (or any ACME client) and will be automatically renewed every 60Êfdays.
sudo apt-get install certbot python3–certbot–nginx # or -apache if you use Apache
sudo certbot --nginx -d wiki.example.com
After a successful run you will have /etc/letsencrypt/live/wiki.example.com/fullchain.pem and /etc/letsencrypt/live/wiki.example.com/privkey.pem ready for the web–server configuration.
StepÊf2Êf–ÊfConfigure MediaWiki for HTTPS
The MediaWiki core already knows how to work over HTTPS. The only things you need to set in LocalSettings.php are:
# Force every request to HTTPS and set the Secure flag on cookies
$wgForceHTTPS = true;
# The canonical URL of the wiki – must start with https://
$wgServer = "https://wiki.example.com";
# (optional) Tell MediaWiki that the web server may be behind a reverse proxy
$wgInternalServer = "https://wiki.example.com";
# Ensure cookies are sent only over HTTPS
$wgCookieSecure = true;
These settings are described on the Manual:HTTPS page.
StepÊf3Êf–ÊfWeb–server HTTPS configuration
Below are minimal configurations for Apache and Nginx. They both install the certificate, enable TLSÊf1.2/1.3, and redirect any HTTP request to HTTPS.
Apache (mod_ssl)
<VirtualHost *:80>
ServerName wiki.example.com
Redirect permanent / https://wiki.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName wiki.example.com
DocumentRoot /var/www/mediawiki
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/wiki.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/wiki.example.com/privkey.pem
# Recommended TLS settings
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH"
SSLHonorCipherOrder on
# MediaWiki specific directives – allow .htaccess overrides
<Directory /var/www/mediawiki>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Nginx
server {
listen 80;
server_name wiki.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name wiki.example.com;
root /var/www/mediawiki;
index index.php;
ssl_certificate /etc/letsencrypt/live/wiki.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wiki.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH";
ssl_prefer_server_ciphers on;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php7.4-fpm.sock; # adjust version
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Both examples include a permanent redirect from portÊf80 to portÊf443, which satisfies the requirement of $wgForceHTTPS and prevents any accidental HTTP access.
StepÊf4Êf–ÊfAdd HSTS protection
There are two ways to send the Strict-Transport-Security header: directly from the web server or via the MediaWiki Extension:HSTS. The extension gives you per–user control and a convenient way to enable the header for anonymous users, logged–in users, or both.
OptionÊfAÊf–ÊfWeb–server header (simplest)
Add the header to the HTTPS virtual host.
# Apache example – add inside the <VirtualHost *:443> block
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Nginx example – add inside the HTTPS server block
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
This sends HSTS to all visitors, including bots and crawlers. Choose a short max–age (e.g. 300Êfseconds) for testing, then increase to one year (31Êf536Êf000Êfs) once you are confident the site works over HTTPS.
OptionÊfBÊf–ÊfInstall the HSTS extension
The extension is useful when you want a beta feature or want to let users opt out. Installation steps:
Configure the desired behaviour (example forces HSTS for everyone and includes sub–domains):
$wgHSTSForAnons = true; // anonymous users get the header
$wgHSTSForUsers = true; // logged–in users get the header
$wgHSTSIncludeSubdomains = true;
$wgHSTSMaxAge = 365 * 24 * 60 * 60; // one year
$wgHSTSBetaFeature = false; // not a beta – always on
Add the loader line at the end of LocalSettings.php:
wfLoadExtension( 'HSTS' );
Download the extension into extensions/HSTS (or clone from Git):
cd extensions
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/HSTS
After saving the file, visit Special:Version to confirm the extension is loaded.
StepÊf5Êf–ÊfTesting the configuration
Use an external SSL–test service (e.g. Qualys SSL Labs) to verify the certificate chain, protocol support and HSTS header.
curl -I https://wiki.example.com | grep -i strict-transport-security
You should see a line similar to:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Check that cookies have the Secure flag:
curl -I https://wiki.example.com | grep -i set-cookie
Look for Secure in the output.
StepÊf6Êf–ÊfMaintenance (certificate renewal and HSTS updates)
Let’s Encrypt certificates expire after 90Êfdays. Set up a cron job (certbot already does this) to renew automatically:
0 3 * * * /usr/bin/certbot renew --quiet --renew-hook "systemctl reload nginx"
If you ever need to change the HSTS max–age, update $wgHSTSMaxAge (or the header in the web server) and reload the service. Reducing the max–age is safe; increasing it is permanent for browsers that have already seen the header.
When you are ready to submit the domain to the HSTS preload list, make sure:
- HTTPS works on every sub–domain.
- The header includes
preloadandincludeSubDomains. - The max–age is at least 31536000 (one year).
Then submit the domain at hstspreload.org. Preloading removes the “first–visit” weakness of HSTS, making the wiki safe even for users who have never visited it before.
Conclusion
Securing a MediaWiki installation is a three–step process:
- Obtain and install a valid SSL/TLS certificate (Let’s Encrypt is free and easy).
- Tell MediaWiki to operate only over HTTPS (
$wgForceHTTPS,$wgCookieSecure, proper$wgServervalues). - Enable HSTS, either via the web server or the Extension:HSTS, and consider preloading the domain.
With those settings in place the wiki is protected against eavesdropping, session hijacking and SSL–stripping attacks. Regularly test the configuration, keep the certificate renewed, and you will have a robust, production–ready MediaWiki installation.