Enabling WordPress to Work with SSH2 Upgrades — Without Extravagant Permissions
Part of getting your OS X-based server set up for delivering real websites may involve preparing in advance to support SSH2 upgrades for WordPress. Run-throughs for this process are all over the place, but they almost always involve unnecessarily extravagant permissions on private encryption keys.
Why SSH Upgrades at All? And a Bit About Shifting the Problem Elsewhere…
FTP as a protocol is inherently insecure — the main reason being that usernames and passwords are passed in plain text form, making them vulnerable to eavesdropping. Thus the rationale for providing SSH2-based upgrades as an alternative: give WordPress access to the necessary keys, and it can grab files and place them on your server without passwords ever having to be exchanged.
So far, so good. But unfortunately, the WordPress approach to implementation makes it all too tempting to open up other potential attack vectors which — while entirely different in character — are arguably no less a problem. The approach I describe below tries to make it at least a little less extreme than the common advice to make private keys readable for anyone who wants them.
Making SSH2 Upgrades Ready and Accessible for WordPress
There are least two different ways of enabling WordPress to work with SSH2 upgrades. You can use a plugin that relies on
phpseclib, such as SSH SFTP Updater Support, or you can install
libssh directly and use the built-in WordPress functionality. This article covers the latter.
Assuming you’ve already installed the Xcode tools as explained in a previous article (“Basic Configuration and Preparing the Way for Extra Software OS X Server Needs”), let’s start by installing
autoconf. From the command line, you can download, extract, and install like so (replacing 2.69 with whatever the current version winds up being):
curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz
tar xvfz autoconf-latest.tar.gz
sudo make install
Next we need
libssh2, so either
cd .. to go back up out of the
autoconf source directory, or open a new Terminal window (replacing 2-1.4.2 with whatever is the current version):
curl -O http://www.libssh2.org/download/libssh2-1.4.2.tar.gz
tar xvfz libssh2-1.4.2.tar.gz
sudo make install
Next up is installing the SSH2 PHP extension itself, but to do that, we’ll first install and update the pear which comes with Mac OS X:
sudo php -d detect_unicode=0 /usr/lib/php/install-pear-nozlib.phar
sudo pear upgrade
That will then enable us to do the following to install SSH2.
sudo pecl install -f ssh2
When prompted for the
libssh2 prefix, just press enter for autodetection:
libssh2 prefix? [autodetect] :
(If you encounter sites recommending that when asked, you should enter
/opt/local, note that those instructions are probably assuming you’re using MacPort to install things. We’re specifically steering clear of installing anything extra whenever possible.)
To connect this with PHP, we now need to add the following line to
php.ini, which normally lives in
However, if you’ve been following along with the earlier articles in this series and completed these steps in just the order suggested — and in particular if you’ve not yet even launched Server.app — you may not have an editable
php.ini file yet. You can, in principle, create one from the supplied default file:
sudo cp /private/etc/php.ini.default /private/etc/php.ini
But — and this is a big ‘but’ — it’s best to hold off at this stage. Why? Because the first time you launch Server.app, it will populate
/private/etc with a new
php.ini file based on the server default which it will also place there. If you create and edit a
php.ini file now, you’ll need to go back and reconcile the two later; better to leave it for now and come back later to add the
ssh2 extension line.
Although you can edit the
php.ini file from the command line again using
vi or another editor if you wish, by the way, for making any significant changes to your configuration, I personally turn to SublimeText 2. (For example, you might wish to add pear to the PHP include path, turn on the display of errors just while you’re getting things set up, etc.)
If Apache were already running, we’d now restart it with one of the two:
sudo apachectl graceful
sudo apachectl restart
But in terms of the steps in this series of articles, we’re not that far yet! You can also double-check to make sure ssh is installed:
php -m | grep ssh2
Last but not least, if you’re using the suggestion to consolidate website management under one user (“Basic Configuration and Preparing the Way for Extra Software OS X Server Needs”), you may as well set up the encryption keys for that user now. If not — i.e., if you’ll be using separate accounts to manage each website — then you can just repeat this exercise for each one later on. You can start either by logging in using your web manager account, or just
su to be that user and navigate into their home directory (assuming you began in your own home directory):
Just hit ‘enter’ when prompted for passwords. Alternatively, you can do it all in one line as follows:
ssh-keygen -b 1024 -t rsa -f id_rsa -P ''
cp id_rsa.pub authorized_keys
And finally, you’ll need to set permissions that will enable the web server to grab what it needs from these keys. One quick and loose way — widely recommended but not necessarily very good — is to do this:
chmod 755 .ssh
chmod 644 .ssh/*
However, this is somewhat crazy, since we’re giving everybody read access to the public key. (Actually, the whole WordPress attitude toward making upgrades ‘secure’ is, in my view, significantly less than half-baked and more than a little disingenuous.) But since WordPress is designed on the assumption that you ought to be happy giving it — and every other web process running on the whole server — unfettered access to your unencrypted private key, you’re going to be stuck with some less-than-optimal solution. A still not great but much better approach than opening it up to the world is just to change the group on
.ssh and the owner on the private key, enabling significantly tighter overall privileges:
chgrp _www .ssh
chmod 750 .ssh
chown _www .ssh/id_rsa
chmod 600 .ssh/id_rsa
id_rsa permissions should already be at 600 by default, but I’ve included this explicitly in the above anyway, so as to cover cases where you might have already applied the more liberal privileges suggested earlier. (The more liberal settings are by far the most common suggestion I’ve encountered while reading on other sites about setting up WordPress for SSH2.)
Now later on, if you’re running WordPress on a particular site, and you’d like to take advantage of SSH2 upgrades, you can add something along the following lines to that site’s
define('FTP_PUBKEY','/Users/webuseraccount/.ssh/id_rsa.pub'); define('FTP_PRIKEY','/Users/webuseraccount/.ssh/id_rsa'); define('FTP_USER','webuseraccount'); define('FTP_HOST','example_domain_name.com:22');
Depending on the rest of your setup, you may need or prefer the following as the last line, rather than above:
If you are using a single web overseer account, an extra advantage of using ‘localhost’ rather than the full domain name is that this same code can then be repeated throughout all of your
wp-config.php files, without stopping to change the domain name for each one.
In addition, if you have changed the default SSH port and disabled SSH over port 22 (generally a good idea, which as I’ve described in detail separately: “Changing the Default SSH Port on Mac OS X Server”), then ’22’ should be changed to the appropriate port number for your own setup.
All material on this site is carefully reviewed, but its accuracy cannot be guaranteed, and some suggestions offered here might just be silly ideas. For best results, please do your own checking and verifying. This specific article was last reviewed or updated by Greg on .