We are an open source project and we have an Apache web server with a MediaWiki 1.25. Its a stand alone installation, so we don't have the complications of shared hosting a varying userids. After 20 years or so and a few migrations we had a fair amount files owned by "no user" and "no group".

We cleaned up the file system permissions by effectively setting permissions on files and directories to root:apache, where owner was entitled with rw and group was entitled with r. It was not haphazard; rather we identified missing permissions with commands like find /var/www -nouser, find /var/www -nogroup, find /var/www \! -user root and find /var/www \! -group apache.

We also identified two special cases: root:root and apache:apache and reset the permissions. root:root was reset because it meant the file was not accessible to the web server. apache:apache was reset because it meant a high risk component had write permissions.

Problem: We managed to break MediaWiki uploads and thumbnails, which I believe was caused by the apache:apache reset. It is mostly OK because admins use the feature and we know what caused the break. I'm now trying to correct the break, but I can't determine what the file system permissions are supposed to be. Searching is revealing the application level permissions for items like LocalSettings.php and $wgGroupPermissions. And the MediaWiki Architecture docs don't discuss it.

Question: What are the filesystem permission supposed to be for a MediaWiki installation in a non-shared configuration?

For completeness, "non-shared" means the "single user" use case from the cited What permissions should my website files/folders have on a Linux webserver? The VM is dedicated to us, and there's a single Apache, MediaWiki and MySQL user (MediaWiki appears to piggy-back on Apache, so there are only Apache and MySQL users).

We are not in a shared hosting environment with different instances of Apache and MediaWiki running under different user contexts or with different file permissions for each distinct subscriber.

Here is the exception when I attempt to upload a file. I used to be able to upload it when filesystem permissions were "fast and loose":

[724f5260] /wiki/Special:Upload MWException from line 1856 of /var/www/html/w/includes/filerepo/file/LocalFile.php: Could not acquire lock for 'Vs2005-dynamic.zip.'


#0 /var/www/html/w/includes/filerepo/file/LocalFile.php(1148): LocalFile->lock()
#1 /var/www/html/w/includes/upload/UploadBase.php(715): LocalFile->upload(string, string, boolean, integer, array, boolean, User)
#2 /var/www/html/w/includes/specials/SpecialUpload.php(476): UploadBase->performUpload(string, boolean, boolean, User)
#3 /var/www/html/w/includes/specials/SpecialUpload.php(195): SpecialUpload->processUpload()
#4 /var/www/html/w/includes/specialpage/SpecialPage.php(384): SpecialUpload->execute(NULL)
#5 /var/www/html/w/includes/specialpage/SpecialPageFactory.php(582): SpecialPage->run(NULL)
#6 /var/www/html/w/includes/MediaWiki.php(267): SpecialPageFactory::executePath(Title, RequestContext)
#7 /var/www/html/w/includes/MediaWiki.php(566): MediaWiki->performRequest()
#8 /var/www/html/w/includes/MediaWiki.php(414): MediaWiki->main()
#9 /var/www/html/w/index.php(41): MediaWiki->run()
#10 {main}

Here are the users contexts for the running web server.

$ sudo ps aux | egrep -i '(apache|http|media|wiki)'
root       127  0.0  1.2 552216 13424 ?        Ss   01:35   0:12 /usr/sbin/httpd -DFOREGROUND
apache    7318  0.5  2.5 564804 27140 ?        S    11:57   0:05 /usr/sbin/httpd -DFOREGROUND
apache    7346  0.3  2.4 565124 25548 ?        S    11:58   0:03 /usr/sbin/httpd -DFOREGROUND
apache    7351  0.6  3.4 574220 36580 ?        S    11:58   0:05 /usr/sbin/httpd -DFOREGROUND
apache    7477  0.1  1.3 554088 14012 ?        S    12:10   0:00 /usr/sbin/httpd -DFOREGROUND
apache    7487  0.9  2.9 571148 30632 ?        S    12:11   0:00 /usr/sbin/httpd -DFOREGROUND

The MediaWiki 1.27 migration is planned. We are holding off until we get the permissions correct.

  • 1
    Can you explain what you mean by non-shared configuration?... Are you running different Apache Processes under a different user group for each? if so then you need to do chmod -R 0700 this will allow only the owner to read, write and excute. – Simon Hayter May 28 '16 at 17:37
  • 1
    @SimonHayter, "... what do you mean by non-shared configuration..." - My bad; I added additional information. The short of it is there's a single Apache user, a single MySQL user, etc. There are no hardships created from multiple subscribers. "... then you need to do chmod -R 0700..." - OK, thanks. Where do these tweaks need to be performed? (This is my pain point - I can't find a governing document for best practices or guide to loosening security from a firmer posture). – user40589 May 28 '16 at 18:01
  • @jww It might be in scope to ask this on ServerFault if you want to give that a try, given you manage your own server. (Check posting rules there first though, and let us know here if you do) – Tim Malone May 30 '16 at 22:35
  • @Tim - the problem is we are not professional admins. Its been my experience that questions that appear to fall under server fault are not well received when its something a non-professional asks (like and Open Source project). I've had so many bad interactions with the site I don't even like to visit them. Its why I treat [my] "Open Source project running a web server" questions as the hobbyist question more suited for Super User or Pro Webmasters. Also, I don't ask on Pro Webmaster unless its a production server. – user40589 May 30 '16 at 23:22

The following picks up on a fresh working LAMP installation under Red Hat 7 or clone (CentOS 7, Scientific Linux 7, Orcale 7, etc). Set Selinux to permissive for the installation.

setenforce 0

First get the Mediawiki version you want from https://releases.wikimedia.org/mediawiki/ , at time of writing latest is https://releases.wikimedia.org/mediawiki/1.27/mediawiki-1.27.0.tar.gz and unpack it in /var/www/html/w.

Navigate to https://www.example.com/w and follow on-screen instructions to generate content used for LocalSettings.php. Create LocalSettings.php with

vi /var/www/html/w/LocalSettings.php

and paste content into file (i -> enter insert mode, CTRL+SHIFT+v to paste content, ESC -> to exit insert mode, ZZ (twice letter Z) to save and exit vi). Now secure LocalSettings.php with

chown root:apache /var/www/html/w/LocalSettings.php
chmod 640 /var/www/html/w/LocalSettings.php

Delete mw-config if it exists, since it is only used for first time setup of mediawiki.

rm -rf /var/www/html/w/mw-config

Enable use of .htaccess files by creating custom configuration file for Apache httpd.

cat >> /etc/httpd/conf.d/custom.conf << EOF
<Directory "/var/www/html/w">
 AllowOverride All

Now one should customize LocalSettings.php to one's taste. Here an overview of variables that can be customized: https://www.mediawiki.org/wiki/Manual:Configuration_settings

Since we want to access our Mediawiki installation under https://www.example.com/wiki we need to set $wgArticlePath in LocalSettings.php. Just add the following line a the bottom of LocalSettings.php

$wgArticlePath = "/wiki/$1";

and update /etc/httpd/conf.d/ssl.conf by adding one line.

<VirtualHost _default_:443>
Alias /wiki /var/www/html/w/index.php  # <-- only add this line

Captchas are annoying but if configured properly, effective to reduce SPAM. See https://www.mediawiki.org/wiki/Extension:ConfirmEdit for configuration options.

Now we want to have a blacklist of words that cannot be used in any article.

$wgSpamRegex = "/".
$wgSummarySpamRegex = "/".

For small to medium sites the extension "Moderation", https://www.mediawiki.org/wiki/Extension:Moderation is quite effective to fight SPAM. Add the following lines at the end of LocalSettings.php

$wgGroupPermissions['user']['move']                = false;
$wgGroupPermissions['user']['upload']              = false;
$wgGroupPermissions['user']['purge']               = false;
$wgGroupPermissions['user']['SpecialPages']        = false;
$wgGroupPermissions['bureaucrat']['move']          = true;
$wgGroupPermissions['bureaucrat']['upload']        = true;
$wgGroupPermissions['bureaucrat']['purge']         = true;
$wgGroupPermissions['bureaucrat']['SpecialPages']  = true;

#Moderation (This section to be placed at the bottom of LocalSettings.php)
require_once "$IP/extensions/Moderation/Moderation.php";
$wgGroupPermissions['sysop']['moderation'] = true; # Allow sysops to use Special:Moderation
$wgGroupPermissions['sysop']['skip-moderation'] = true; # Allow sysops to skip moderation
$wgGroupPermissions['bot']['skip-moderation'] = true; # Allow bots to skip moderation
$wgGroupPermissions['bureaucrat']['skip-moderation'] = true; # Allow bureaucrat to skip moderation
#$wgGroupPermissions['checkuser']['moderation-checkuser'] = false; # Don't let checkusers see IPs on Special:Moderation
$wgAddGroups['sysop'][] = 'automoderated'; # Allow sysops to assign "automoderated" flag
$wgRemoveGroups['sysop'][] = 'automoderated'; # Allow sysops to remove "automoderated" flag
$wgLogRestrictions["newusers"] = 'moderation';

Get Moderation extension with

git clone https://github.com/edwardspec/mediawiki-moderation.git

and copy the files to "/var/www/html/w/extensions/Moderation". Now run the mediawiki update script with

cd /var/www/html/w
php maintenance/update.php

Now finish securing the Mediawiki installation. This may be needed for Selinux, e.g. database on different server, etc.

setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1

This is needed for Selinux to run Mediawiki

setsebool -P httpd_builtin_scripting 1
setsebool -P httpd_execmem 1

Set userrights and special Selinux rights, so Apache httpd has read access, but other users beside root don't.

chown -R root:apache /var/www/html/
find /var/www/html/w -type d -exec chmod 750 {} \;
find /var/www/html/w -type f -exec chmod 640 {} \;

Mediawiki writes to images and cache, so they need special write premissions.

chown -R apache:apache /var/www/html/w/images
chown -R apache:apache /var/www/html/w/cache
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/w/cache(/.*)?"
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/w/images(/.*)?"
restorecon -R /var/www/html/w

Found Selinux complaining about hugetlbfs, so add an exception.

cd /var/log/audit
grep hugetlbfs audit.log | audit2allow -M hugetlbfs
semodule -i hugetlbfs.pp

Now restart Apache httpd and set Selinux back to enforcing.

setenforce 1
systemctl restart httpd

Understandably this covers only the basics and Mediawiki offers thousands of ways to customize it further to one's taste and security needs.

Don't forget to make regular backups.

Further suggestions can be found here https://www.pozzo-balbi.com/help/Mediawiki .

  • 1
    This is a good start. I have not come across information that /var/www/html/w/cache needs 0660. I also like the SElinux stuff. Can you break each line down and explain the requirement or reasoning for our benefit and the benefit of future visitors? Also, don't send people to http://www.pozzo-balbi.com/... We want the answer to be alive after http://www.pozzo-balbi.com dies. – user40589 Jul 3 '16 at 17:17

An explanation for the SELinux portion.

I know next to nothing about mediawiki but use SELinux daily so I figured I would help explain what you are setting. I got the definitions from various man pages.

httpd_can_network_connect_db (HTTPD Service)

Allow HTTPD scripts and modules to network connect to databases.

httpd_can_network_connect (HTTPD Service)

Allow HTTPD scripts and modules to connect to the network.

httpd_builtin_scripting (HTTPD Service)

Allow HTTPD to support built-in scripting

setsebool -P httpd_execmem 1

Allow httpd scripts and modules execmem/execstack. I would set this back to 0 and watch audit log to see if media wiki actually needs this setting. Enabling this Boolean is not recommended from a security standpoint, as it reduces the protection against buffer overflows.

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/w/cache(/.*)?"
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/w/images(/.*)?"
restorecon -R /var/www/html/w

Semanage fcontext command is adding, -a, the selinux type, -t, httpd_sys_rw_content_t (basically means allows httpd to rw to the directory and anything under the directory by default) to the folders /var/www/html/w/{cache,images}

The restorecon -R /var/www/html/w adds the new directory type to the SELinux DB, I would run this as restorecon -Rv /var/www/html/w/* so I can see the changes made.

I tried to keep definitions brief, if you need more details I can provide more.

grep hugetlbfs audit.log | audit2allow -M hugetlbfs
semodule -i hugetlbfs.pp

This handy command generates SELinux policy rules from the audit.log. The audit2allow creates the policy file which semodule uses to add to the SELinux policy module. More info can be found in the man pages for audit2allow and semodule. I don't want to get into too much detail with those 2 since it can be a rabbit hole.

  • Mediawiki needs (sadly) "setsebool -P httpd_execmem 1", otherwise audit.log is full of errors. – Pozzo-Balbi Jul 6 '16 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy