This article covers a version of Ubuntu that is no longer supported. If you are currently operate a server running Ubuntu 12.04, we highly recommend upgrading or migrating to a supported version of Ubuntu:
Reason: Ubuntu 12.04 reached end of life (EOL) on April 28, 2017 and no longer receives security patches or updates. This guide is no longer maintained.
See Instead: This guide might still be useful as a reference, but may not work on other Ubuntu releases. If available, we strongly recommend using a guide written for the version of Ubuntu you are using. You can use the search functionality at the top of the page to find a more recent version.
WordPress is the most popular CMS (content management system) used on the internet today. While many people use it because it is powerful and simple, sometimes people make a trade-off for convenience at the expense of security.
This is the case in how you choose to assign directory ownership and permissions, and how you choose to perform upgrades. There are a variety of different methods to do this. We will choose what we consider a relatively secure way of upgrading and installing themes and plugins.
In this guide, we assume that you have gone through your initial server setup. You will also need to install a LAMP stack on your VPS.
We will also assume that you have installed WordPress on Ubuntu 12.04. You can follow our guide on how to install WordPress on Ubuntu 12.04 here.
Once you have the user and required software, you can start following this guide.
If you do not have key-based updates and installations configured, you will get a prompt for connection information whenever you attempt to do either of these tasks.
It will ask you to provide FTP credentials, such as a hostname, FTP username, and FTP password:
FTP is an inherently insecure protocol, so we do not recommend you using it in most cases. We will be configuring our installation to use a secure alternative.
If you followed the guide on installing WordPress above, you will notice that you gave permission of the web directory to the Apache web user. This is a very quick way to get started, but can potentially be a security risk. In an ideal situation, you would separate the content owner from the web process. We will do this as part of our preparation for allowing SSH updates.
We will create a user called wp-user
to own our WordPress installation.
sudo adduser wp-user
You will be asked a lot of question, including the password you want to set. We do not want to set a password, so press “ENTER” through all of the prompts, including the repeated password questions.
Next, change to the /var/www/html
directory, where our WordPress files are being served.
cd /var/www/html
We will give our new user ownership over everything under this directory, changing it from the www-data
Apache web user that we configured during installation.
sudo chown -R wp-user:wp-user /var/www/html
We now need to create an SSH key pair for our WordPress user. Log into the WordPress user by issuing the following command:
sudo su - wp-user
We will create a key pair with the ssh-keygen
command:
ssh-keygen -t rsa -b 4096
You will be asked where to store your keys and what to call them. Choose /home/wp-user/wp_rsa
. You will also be asked to choose a passphrase. Press “ENTER” through the prompt to create a key without password authentication.
Exit out into your normal user account:
exit
We need to do some maintenance to get the permissions secure. We want to give the WordPress user ownership, but set the www-data
group as the group owner. We then want to lock down the other access:
sudo chown wp-user:www-data /home/wp-user/wp_rsa*
sudo chmod 0640 /home/wp-user/wp_rsa*
You need to create the ~/.ssh
directory and give it appropriate permissions and ownership so that the web process can log in.
sudo mkdir /home/wp-user/.ssh
sudo chown wp-user:wp-user /home/wp-user/.ssh/
sudo chmod 0700 /home/wp-user/.ssh/
Now, we can input the public key into our authorized keys file so that the user can log in using those credentials. Since we do not have this file already, we can simply copy the public key.
sudo cp /home/wp-user/wp_rsa.pub /home/wp-user/.ssh/authorized_keys
Again, we need to adjust the permissions and ownership of these files to ensure that they can be accessed, while remaining secure:
sudo chown wp-user:wp-user /home/wp-user/.ssh/authorized_keys
sudo chmod 0644 /home/wp-user/.ssh/authorized_keys
Since these keys will only be used for logging in from within the WordPress site, which is on the same computer, we can restrict the login to this server:
sudo nano /home/wp-user/.ssh/authorized_keys
At the very beginning of the file, before any of the other text, add the portion in red to restrict the key usage to the local computer:
<pre> <span class=“highlight”>from=“127.0.0.1”</span> ssh-rsa… </pre>
Save and close the file.
Now, we can install the packages necessary for WordPress to authenticate SSH logins:
sudo apt-get update
sudo apt-get install php5-dev libssh2-1-dev libssh2-php
Now that we have the utilities, we can edit the configuration file and set the values that we configured.
sudo nano /var/www/html/wp-config.php
Towards the end of the file, add these lines:
define('FTP_PUBKEY','/home/wp-user/wp_rsa.pub');
define('FTP_PRIKEY','/home/wp-user/wp_rsa');
define('FTP_USER','wp-user');
define('FTP_PASS','');
define('FTP_HOST','127.0.0.1:22');
Save and close the file.
Now, we should restart Apache to take advantage of our new update procedures:
sudo service apache2 restart
Now, we can test to see if our configuration is correct. Log into your WordPress site as an administrator by visiting your site in a browser at the following URL:
<pre> <span class=“highlight”>your_domain.com</span>/wp-admin </pre>
We can check that our settings are configured correctly by attempting to install a new theme. Click on “Appearance” and then “Themes”.
At the top, click on “Install Themes”:
Search for a theme or click on the “Featured” themes. Click “Install” to install the theme on your site. It should successfully log in, download, and install your package using the key files you specified:
You can click on “Activate” to switch to the new theme and then click “visit site” to see the results.
There are some issues that you may run into if you’ve configured your SSH keys incorrectly.
One common error that you may see when trying to push a change through the web interface is:
<pre> Public and Private keys incorrect for <span class=“highlight”>user</span> </pre>
This error is frustratingly unspecific. It can be caused for a variety of reasons, some of which are:
Improper permissions on the public key, private key, and the directories that contain them.
The web process needs to be able to read each of these files, so if the web-server group is the owner, then each file needs to have at least 640 permissions.
On the other hand, the ~.ssh
directory only needs to be accessible to the user that will be logging in. This means the wp-user
user in our example. The contents of the directory should be similarly owned by this user and not writable by anyone else.
Improper file ownership. These same keys need to be owned by the correct parties. Between owner and group-owner, this is often a mixture of the user being logged in and the web process user.
In our example, the wp-user
owns both the private and public keys, while the www-data group is the group-owner. This allows us to associate them with the correct user while allowing the server to read the files.
Improper file formatting. If your public or private key has formatting issues, WordPress will reject the key and refuse to use it. The same goes for the ~/.ssh/authorized_keys
file.
The portion that you added to the authorized_keys file, from="127.0.0.1" ...
should not exist in the public key. Even though SSH will consider it a valid file, WordPress will reject it as invalid before even sending the attempt to the SSH daemon.
Another common error during the process of updating or installing themes and plugins is:
Could not create directory...
This is usually an issue with incorrect web-directory ownership. If you are going to be updating the files with the wp-user
account, the upload directories also need to be owned and accessible by this user.
This means that you need to give the files and folders within the /var/www/html
directory to the wp-user
account. If you followed the instructions above and are still having problems, make sure you passed the -R
option to the chown
command.
Another thing to check is that the upload directories have write permissions for the WordPress user. Change to the document root:
cd /var/www/html
If we check the permissions of the files in this folder, we should see write permissions for the owner (first column), but not for the second or third columns:
ls -l
total 180
-rw-r--r-- 1 wp-user wp-user 177 Nov 18 15:21 index.html
-rw-r--r-- 1 wp-user wp-user 418 Sep 24 20:18 index.php
-rw-r--r-- 1 wp-user wp-user 20 Nov 18 15:24 info.php
-rw-r--r-- 1 wp-user wp-user 19929 Jan 18 2013 license.txt
-rw-r--r-- 1 wp-user wp-user 7128 Oct 23 16:08 readme.html
-rw-r--r-- 1 wp-user wp-user 4892 Oct 4 10:12 wp-activate.php
drwxr-xr-x 9 wp-user wp-user 4096 Oct 29 16:08 wp-admin/
-rw-r--r-- 1 wp-user wp-user 271 Jan 8 2012 wp-blog-header.php
-rw-r--r-- 1 wp-user wp-user 4795 Sep 5 21:38 wp-comments-post.php
-rw-r--r-- 1 wp-user wp-user 3350 Nov 19 12:23 wp-config.php
-rw-r--r-- 1 wp-user wp-user 3177 Nov 1 2010 wp-config-sample.php
drwxr-xr-x 5 wp-user wp-user 4096 Nov 19 12:25 wp-content/
. . .
As you can see, the file permissions that read -rw-r--r--
and the directory permissions that read drwxr-xr-x
indicate that the wp-user
, who owns the files and directories, has write permissions and others do not.
A similar check within the wp-content
directory, which contains themes, plugins, etc, will show us whether these directories are owned by and writeable by the wp-user
user.
cd /var/www/html/wp-content
ls -l
total 16
-rw-r--r-- 1 wp-user wp-user 28 Jan 8 2012 index.php
drwxr-xr-x 3 wp-user wp-user 4096 Oct 29 16:08 plugins
drwxr-xr-x 6 wp-user wp-user 4096 Nov 19 13:10 themes
drwxr-xr-x 2 wp-user wp-user 4096 Nov 19 13:10 upgrade
These directories are correctly configured.
While WordPress is convenient and can be configured and managed relatively easily, it does not mean that security should not be a primary concern for your site.
Something as simple as updating your installation, which should be done immediately upon any security release, should be simple. It also should not be a procedure that forces you to use insecure protocols or set insecure directory permissions.
Securing your update procedure and correct directory permissions is one easy task that can prevent a rather large security concern.
<div class=“author”>By Justin Ellingwood</div>
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Nice tutorial. After following your procedure. while trying to install a theme, i am asked to provide the location to my private key. After doing that i get the error “Public and Private keys incorrect for wp-user” Please advice. Secondly what is the right chmod values for files and folders in my wordpress installation. because i ones alter the the chmod recursively to allow installation and upgrade. i believe this might be a security flaw/ Please i can i restore this and get the ssh method right.
I think there’s a mistake defining the FTP_PUBKEY twice, it should be like this: define(‘FTP_PUBKEY’,‘/home/wp-user/wp_rsa.pub’); define(‘FTP_PRIKEY’,‘/home/wp-user/wp_rsa’);
psalido: Yep! I’ve updated the article. Thanks for catching that.
Does this tutorial works if i use Nginx?
no.
Yes… It works!!!
Yes, it works on LEMP (NGINX)
Yes it does. Just followed this tutorial with a LEMP stack on Ubuntu 14.04.
It does, just ran through it!
@sgrenger i just did this in Nginx. I guess we are doing the same thing on Christmas Eve! It works.
although i am seeing this error: The uploaded file could not be moved to wp-content/uploads/2013/12
When adding themes or importing backup files. Permissions seem to be correct from steps above :(
@digisal: What’s the output of <pre>stat /path/to/wp-content /path/to/wp-content/uploads /path/to/wp-content/uploads/2013 /path/to/wp-content/uploads/2013/12</pre>? (<a href=“http://pastebin.com/”>pastebin</a>)
Here its Kamal, http://pastebin.com/ArjBiHfd
me too working in ngnix , but unfortunately not working
me too working in ngnix , but unfortunately not working
Do these instructions apply to the one-click Wordpress installations on Ubuntu 12.10? The WP files are served from /home/wordpress/public_html in the one-click—so instead of using /var/www, should we use the /home/wordpress/public_html directory as the starting point under the “Changing Permissions” step?
jason: Yes, the permissions step can apply to whichever directory you are using as your document root. There are many different ways to configure WordPress, and our one-click image uses the path that you specified.
You can safely apply the steps to that directory if you are using the one-click installation as your starting point.
You can also use the existing “wordpress” user in the one-click image instead of creating a new user called ‘wp-user’.
Worked like a charm, thanks! Forgot to put in my custom SSH port in the wp-config.php so I was wondering what was going on. After I fixed that it worked. :)
I have tried following these steps verbatim multiple times and I always end up with the Public and Private keys incorrect for wp-user error. I am using a LEMP stack with multiple wordpress sites. The only things that I do differently is change the name of “wp-user” (and I am very sure that I properly change the name all the way through the steps) and I apply the 3rd step (sudo chown -R wp-user:wp-user *) to /var/www/mydomain.com/public_html rather than /var/www to support multiple wordpress websites. Any ideas for me? The suggestions in the common issues are helpful, but I’m fairly new and I don’t understand how to check a few of those things. Any help is appreciated!
I am having the exact same problem. Did you solve this?
Edit: Found the solution in a later comment:
You must have changed your port number and **also added AllowUsers parameter in the /etc/ssh/sshd_config file. ** Add wp-user to the AllowUsers parameter in sshdconfig file.
Remember, you must also add a relevant AllowGroups clause in the sshd_config file after the AllowUsers file. In my case, I added AllowUsers wp-user, and AllowGroups wp-user.
If you don’t do that, it may still block you!
In short, how would this tutorial need to be modified to support multiple wordpress installs as outlined by this tutorial: https://www.digitalocean.com/community/articles/how-to-set-up-multiple-wordpress-sites-on-a-single-ubuntu-vps ? Thanks!
Hi Collin, Did you ever figure this out? I get the error
Which I am assuming is related to this.
I am having same issues.
Same issue here… on a LEMP install on 16.04
Same here. LAMP on 16.04
Hi, I have a question with regards to creating another user (wp-user) in terminal.
I followed initial server setup tutorial (https://www.digitalocean.com/community/articles/initial-server-setup-with-ubuntu-12-04) and in there, I already create another non-root user called demo. For this demo user, I have already activated SSH keys.
My question is, will security be compromised if I were to use this demo user and it’s SSH keys for wordpress updates? i.e. do you think it is better I create a different user (wp-user) and different SSH keys just for wordpress updates? thanks!!!
I decided to create a different user with another SSH key instead. let me know if this is ok.
next question: if i login to wordpress using 2 different computers, should I skip this portion of adding "from=“127.0.0.1” into /home/wp-user/.ssh/authorized_keys? Or what should I do for just allowing these 2 computers? thanks
For quite a long while I was unable to get this to work. I had used the 1-click Wordpress installation.
It turns out that ssh2 wasn’t installing correctly within php by
<code>sudo apt-get install php5-dev libssh2-1-dev libssh2-php</code>
This had created a ssh2.ini file but in the wrong location. By using phpinfo(), I was able to find the correct location and copy the ssh2.ini file there. The correct location for me was /etc/php5/apache2/conf.d/ssh2.ini
I hope that saves someone some time. :-)
I have followed your previous tutorials and have a LLMP stack on Ubuntu, withy Lighttpd in place of Apache.
After following this setup, I get this in wordpress when installing a theme:
<code>Failed to connect to SSH2 Server 127.0.0.1:22</code>
Try with
You must have changed your port number and also added
AllowUsers
parameter in the/etc/ssh/sshd_config
file. Make sure you change the port number heredefine('FTP_HOST','127.0.0.1:PORT_NUMBER');
to the one you specified in sshd_config file. Also add wp-user to theAllowUsers
parameter in sshd_config file.Hi Justin! Nice tutorial. Hi all!
I have some issues when i tried to install a new theme or update a plugin. i get the error “Public and Private keys incorrect for wp-user”
When i run sudo tail /var/log/auth.log i catch an ip desauthorizaton error.
I solve this removing from=“127.0.0.1” ssh-rsa… from authorized_keys I´m using Lamp and Ubuntu 15.04
Thank you and thank you all for the clues. Warm regards.
Hello, If this is supposed to be for beginners, then please be clear about the directory system and ownership specifications. What do you do if you have a domain owned by another user with WP in a sub-directory while the secure user is in another directory, and how does the WP-Admin user fit into this, or does it matter?
This is a great tutorial to start with, but the OP is leaving several details hanging that is costing people a lot of time. If any body runs across this and knows what they are doing, please add some critical (presumably simple) details.
from=“127.0.0.1”
Local computer IP? or hostname IP?
@Marga: Simply 127.0.0.1 which is your droplet’s local/loopback IP address.
If wp-user owns all the files and directories, how can I use sftp with this user? If I login under my account and use sftp to upload files, it says it doesn’t have the correct permissions. If I try to login as wp-user, it asks for a password, which I did not set per above instructions.
Hi Kempdogg
was wondering if you figure out how to sftp with the wp-user? I’m having the same issue too.
Thank you :D
This comment has been deleted
This works great for doing theme installations and core updates. But it broke my ability to upload image files from the wordpress web interface. Any idea how to resolve this?
“image-file.png” has failed to upload due to an error The uploaded file could not be moved to wp-content/uploads/2014/04.
Thanks!
This works great for doing theme installations and core updates. (I agree)
But it broke my ability to upload image files from the wordpress web interface. ( I FIXED THAT PART)
But I don’t have the ability to access general settings, delete plugins…anymore.
I get a “connection rest” message.
Ok I think I might have found a solution keep in mind I’m running 14.04 lte… After I did everything I could upload themes and add plugins… However, I notice that I could no longer access general settings, delete plugins etc… I would get an connection rest… For whatever reason until www-data was the owner of wp-admin I could not access general settings. However I still wasn’t able to delete plugins I would get some type of error… This is what I did… please let me know if there is anything wrong with this
chown -R www-data:wp-user /var/www chmod 770 -R /var/www
I’m still very knew to this but everything seems to be working now. If I have chown -R wp-user:www-data /var/www it does not work the same for whatever reason
I’ve just started working with the linux system 2 days ago… have only had about 7 hours of sleep but that problem was annoying me soooooooo much"
by the way I’m running wordpress 4.1
I’m also having difficulties accessing /wp-admin/options-general.php with error “the connection was reset” after following this tutorial.
I tried making www-data:www-data and wp-user:www-data the owner of wp-admin, I’ve tried relaxing the permission to 775 for www and the problem persists.
The only way I could get general options to load is to remove the authentication settings from wp-config.php.
Ok I reverted the group ownership on the uploads directory to www-data, and uploads are working again. Is this an ok solution?
sudo chown wp-user:www-data /path/to/wp-content/uploads -R
Everything works as expected, thanks to these instructions, on my Ubuntu 12.04 localhost laptop. Updated wordpress, added plugins, added themes, all with one-click. However, like dbchristopher, can’t upload new content into wp-content/uploads. File permission errors. So I tried messing around with chmod to see what file permissions may work. Keeping the user and group as my wp-user, I finally had to resort to a full chmod 777. Not even a 775 works. I conjecture perhaps because uploading makes calls to my directories through drag-and-drop and other processes as the logged in user that I am on my laptop? Is there a saner, safer way of doing this please? Is handing over ownership to www-data better? Help much appreciated. Thanks Regards Niyam
Hi,
Thanks for your article… but to me not working yet… the server configuration is some different… I’m use an Stack LAMP of Bitnami…
I complete all steps but shown the “Connection Information” form only with all fill fileds.
I think that not work the SSH support, some idea? I have re-build my php configuration?
Thanks very much…
Hi All,
I had the same problem too re. “public and private key incorrect for user” confusion. and the image upload failure.
What worked for me was: the “wp-user” and the wordpress login are the same user name. That is, if my wordpress login is janesmith, then the wp-user described on on the instruction above must be janesmith as well.
I also change the group owner of the wp-content to www-data
sudo chown -R janesmith:www-data wp-content
and had to chmod 775 just for that directory. Don’t know if this an acceptable practice, but it solved that upload problem.
I would like to add something that helped me resolve the “Public and Private keys incorrect for user” error. I ended up cracking down to the code that generates that error and finding an @ symbol in front of may of those commands. The @ symbol before a function name suppresses errors for that function. Removing the @ symbol temporarily allowed me to see what the heck was going on. In my case, the key files were not accessible due to open_basedir restrictions. Once I saw that error, the problem was easy to resolve.
I was following the tutorial and saw this error. sudo nano /var/www/wp-config.php should be: sudo nano /var/www/html/wp-config.php
I don’t know if this was changed with a newer version of wordpress; however, I thought i’d let you know. Thanks for the tutorial!
atishpatel2012: The difference between the file path that you are noticing is the difference in the default document root configured for Apache.
In Ubuntu 12.04 (which this guide was initially created for), the document root was
/var/www
. In newer versions of Ubuntu (like 14.04), the path to the default document root for Apache is set to/var/www/html
. This is simply a choice that the package maintainers at Ubuntu made. You’ll have to adjust the paths, as you’ve found, in steps that deal with the document root if you are using a newer version of Ubuntu.Thanks for pointing that out to other users and for keeping an eye out! Let us know if you find anything else!
@dave: I have now idea what you are saying, but I think it might help if it was dumbed down further. I am having issues with incorrect Public and Private keys. The site I got on the LAN can’t upload FTP/SSH either, I drag and drop everything in the /var/www/ to install it on localhost. But, I don’t know how to do a work around on a virtual server, so an help would be appreciated.
I got rid of the incorrect Public and Private keys error. Just wanted to help if I could anyone that has the same issue. Changed php.ini file using
sudo nano -w /etc/php5/apache2/php.ini
. Then added the lineextension=ssh2.so
saved and exited. Thensudo service apache2 restart
. I found the info on <a href=“http://www.htpcbeginner.com/enable-wordpress-ssh-access/”>HTPC Beginner</a>For anyone with the “Public and Private keys incorrect for user” error
Double check your /etc/ssh/sshd_config
If you previously secured your ssh (as recommended in a guide on DO) to only one account you will need to add the wp-user as well. In the below example I have used demo to represent the first allowed account, wp-user is the second.
Authentication:
AllowUsers demo wp-user
As others have mentioned also I had to change group ownership for the uploads folder to www-data
Hope that helps
Well i am using ubuntu with Nginx as proxy and Apache for server for my wordpress blog. It works for me
I am really thankful for such a wonderful article. Thank you.
For me I just get shown the ftp details screen prefilled with the content of my config.php file, on ubuntu 14.04 x64
hi when do this cd /var/www/wp-content i get this -bash: cd: /var/www/wp-content: No such file or directory i’m losing my mind