If you’re managing a WordPress site primarily through the browser, there’s a good chance you don’t ever have to think about permissions once your initial setup is in place. Your server has write permissions to your wp-content directory and that’s that. If you need to make changes, you do so using the Web interface, so no conflict arises.

Even then, though, you may occasionally see an error like “Directory /var/www/yoursite/somedir is not writable.” Usually, this is generated by a plugin which wants to dabble in some custom location. If you’re really lucky, the plugin will go on to suggest something dastardly like “Please make the directory world writable: chmod 0777 /var/www/yoursite/somedir“. Do not be tempted. Making directories or files world-writable is highly risky.

Things go wrong more often if you are managing your WordPress site on the command line. This is because your Web server runs as one user (often apache) and you run as another. Without configuration, you are likely to hit conflict. If you have generated wp-content via a git clone, then the Web server may not be able to write to the uploads directory. If you then change the ownership of the directories and files to accommodate the server, you may find that you no longer have the privileges to add a plugin or a file. Generally, then you use sudo (that, is run the command as root) which leaves you with a confusing hybrid environment – writable by root, but only partly writable by the server.

What we need to do then, is organise ownership such that both you AND the server can read, write and execute. I can do this by creating a Unix group that both my user and the Web server can share.

I start by adding a group called webshare

$ sudo groupadd webshare

Next I associate both my user – mattz and the server’s user apache with the webshare user.

$ sudo usermod -a -G webshare mattz
$ sudo usermod -a -G webshare apache

Time for a quick confirmation that something happened.

$ cat /etc/group

Yep, that confirms both that webshare exists and that users mattz and apache are members of the group.

We are not done yet though. Three more issues to solve. First of all just sharing a group is not enough – we need to make sure that all files and directories in wp-content are associated with that group.

$ sudo chgrp -R webshare site/wp-content/

Secondly just belonging to a group is not enough, directories and files must be confirgured so that they can be written by anyone beloning to the webshare. Most of the time you will find files and directories are writable at the user level rather than the group level. We can use chmod to change that:

sudo chmod -R g+rwx site/wp-content/

We can see whether this works by listing site/wp-content from the commandline:

$ ls -al site/wp-content/
total 20
drwxrwxr-x 5 mattz  webshare 4096 Dec 10 05:07 .
drwxrwxr-x 4 mattz  mattz    4096 Dec  6 18:51 ..
drwxrwxr-x 4 mattz  webshare 4096 Dec 10 06:22 plugins
drwxrwxr-x 6 mattz  webshare 4096 Dec 10 04:07 themes
drwxrwxr-x 3 apache webshare 4096 Dec  8 19:27 uploads

That’s what I hoped to see. drwxrwxr-x tells me that:

drwxrwxr-x These are directories

drwxrwxr-x That can be read/written/executed by mattz in some cases, and apache in one case.

drwxrwxr-x They can be read/write/executed by anyone in group webshare.

drwxrwxr-x They can only be read and executed by anyone not already covered (the world)

Since I run as mattz, and the server runs as user apache – this would seem to cover it.

Not quite so fast, though. I changed every file and directory to be group writable with my recursive command. But what about additions?

Here is an edited version of current state of my uploads directory:

$ ls -al site/wp-content/uploads/2016/12/
total 5384
drwxrwxr-x 2 apache webshare    4096 Dec  8 19:27 .
drwxrwxr-x 3 apache webshare    4096 Dec  8 19:27 ..
-rw-rwxr-- 1 apache webshare   23405 Dec  8 19:27 lizard-100x100.png

It’s the new fuzzy shared world. These files are owned by the apache user, but they also belong to the webshare group. That means I can work with them on the command line if I need to. Let’s do a quick upload and see what the directory looks like.

So, I have uploaded the file ten.jpg. Now here is another edited version of the upload directory listing.

$ ls -al site/wp-content/uploads/2016/12/
total 5628
drwxrwxr-x 2 apache webshare    4096 Dec 11 15:54 .
drwxrwxr-x 3 apache webshare    4096 Dec  8 19:27 ..
-rw-rwxr-- 1 apache webshare   23405 Dec  8 19:27 lizard-100x100.png
-rw-rw-r-- 1 apache apache    180671 Dec 11 15:54 ten.jpg

The new file uploaded OK. But look at that group. The file belongs to the apache. Since I don’t belong to that group, I am at least partially locked out from working with it:

$ rm site/wp-content/uploads/2016/12/ten.jpg 
rm: remove write-protected regular file `site/wp-content/uploads/2016/12/ten.jpg'?

I should be able to get round this by recursively setting the group sticky bit for groups on all directories in wp-content and that’s where this article was serenely heading. Annoyingly there is an issue with the way that PHP and WordPress handle file uploads with regard to the sticky bit so I’ll need to return to this issue after some further research! Onward.

photo credit: Mac McCreery No.11 via photopin (license)