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
$ sudo groupadd webshare
Next I associate both my user –
mattz and the server’s user
apache with the
$ sudo usermod -a -G webshare mattz $ sudo usermod -a -G webshare apache
Time for a quick confirmation that something happened.
$ cat /etc/group ... webshare:x:507:mattz,apache
Yep, that confirms both that
webshare exists and that users
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
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.