WordPress SSH2 configuration

Instead of the packaged WordPress I run the version provided by WordPress.  It is installed using a different userid from the userid the web server runs as.  To enable updates from the Admin Dashboard, I enabled sftp (ssh). This is how I did it.

Using the sftp option requires the php ssh module.  This command installs the php ssh module.

apt install php-ssh2

The FTP funtionality includes the sftp (ssh2) option for connectivity.  To enable this the /etc/wordpress/config.php file must be updated to include the following lines.  (Use the appropriate directories for your installation.)

// This value should be ssh2 not ssh
define('FS_METHOD', 'ssh2');
define('FTP_BASE', '/var/www/');
define('FTP_CONTENT_DIR', '/var/www/wp-content/');
define('FTP_PLUGIN_DIR ', '/var/www/wp-content/plugins/');
define('FTP_PUBKEY', '/etc/wordpress/.ssh/id_rsa.pub');
define('FTP_PRIKEY', '/etc/wordpress/.ssh/id_rsa');
// user that owns wordpress install - should not be root
define('FTP_USER', 'wordpress');
// password for FTP_USER username - may be empty
define('FTP_PASS', 'changeme');
// hostname:port combo for your SSH/FTP server
define('FTP_HOST', 'localhost');

The following script creates and poputates the directories required for ssh to work. An ssh key is generated and granted restricted access to the user owning the distribution. The last command verifies the setup.   

# Make the directories
www-data mkdir -p -m 0755 ~www-data/.ssh /etc/wordpress/.ssh
sudo chown www-data /etc/wordpress/.ssh
# Create the known hosts fi
sudo ssh-keyscan -c "localhost > ~www-data/.ssh/known_hosts"
sudo chmod 444 ~www-data/.ssh/known_hosts
# Generate the key file 
sudo -u www-data ssh-keygen -b 4096 -f /etc/wordpress/.ssh/id_rsa -N changeme
# Secure the directories
sudo chown root:www-data /etc/wordpress/.ssh ~www-data/.ssh
# Authorize the key - with restricted access
echo -n 'from=",::1",restrict,pty ' >> ~/.ssh/authorized_keys
sudo cat /etc/wordpress/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
# Test the configuration - should be prompted for the key's password.
sudo -u www-data ssh -i /etc/wordpress/.ssh/id_rsa $(logname)@localhost

I hope this is useful for you. As always, please change the password used above.

My original installation used a key without a password. At the time sftp access was not stable. I have not yet done an upgrade with a password on the key.

init.d for Non-root Processes

When installing third-party applications, they often default to running as root. The server applications for TeamSite/LiveSite are among those. I have applied a simple modification to the init.d scripts that starts them as a non-root user. It also allows the scripts to be run by members of an administration group via sudo. This approach is applicable to other applications. Continue reading “init.d for Non-root Processes”

Geo blocking with tcpwrappers

i recently had an issue with frequent login attempts against on of my services. These were almost all from countries that should not be accessing my service. To resolve the issue I implemented geo blocking with TCP Wrappers. This is how I went about geo blocking connections. Continue reading “Geo blocking with tcpwrappers”

Tuning Java Garbage Collection

I recently completed a garbage collection exercise on a variety of applications. In all, twenty WebLogic application clusters were tuned. A dozen of these are large busy application clusters. These provide a mix of Web Applications and Web Services.

Tuning garbage collection is a matter of trade-offs. Large heaps take longer to garbage collect. Small heaps need to be collected frequently using more CPU time. Continue reading “Tuning Java Garbage Collection”

Securing TLS

A StackExchange question on using HAProxy’s capture feature to pass data from TCP mode to HTTP mode prompted me to update my SSL configuration. This was intended to get an A+ rating from SSL Labs by sending non-SNI capable clients to a server with weaker ciphers. This was to enable clients on WinXP/IE8, Java 6, and an old Android version to connect. I found a solution without having to have two sets of ciphers and handling traffic in both the TCP mode and HTTP mode. I then optimized my settings to a minimal list of cipher specifications.
Continue reading “Securing TLS”

WordPress Tuning

I’ve done a little tuning to my WordPress setup. In order to keep up to date, I’ve switched from the Ubuntu installation to a downloaded installation under /opt/wordpress. This is owned by my user and served by apache running as www-data. Updates are done using the sftp add-on.

Securing /opt/wordpress

I added myself to the www-data group. This allow apache to read any files with group access, but prevents writing if the web-server is compromised.

I set the group sticky bit on all the directories. If required, setting it on the wp-content/upgrade directory should be sufficient.


I generated my key outside the home directory for www-data which is /var/www. The directory I chose is not one I would publish. However, ssh requires a .ssh/known_hosts file in its home directory. This was created and the appropriate security added. The key is password protected.

Outstanding Issues

There are some outstanding issues. I’ll look into these as time permits.

Native ssh

The WordPress ssh2 modules does not work on my server. I’ve found a couple of issues.

  • Passwords on the key don’t work. This is a known issue with a work-around. The initial connection appears to fail, but a second call should resolve the issue.
  • The is_dir function does not work. Returning true for paths that end in a slash (/) is a workaround. This got me as far as trying to install. This may be a result of how the path is constructed and there is a published workaround.
  • The is_file function appear to fail as WordPress reports the download contains no files. This is likely the same issue as for the is_dir function.

Theme upgrades

My modifications to the theme are getting a little old. The theme works reasonably well on mobile devices, but I would like to update to a more streamlined theme. The site statistics I have indicate a surprisingly high percentage of viewers use a mobile device.

Command Line Arguments in Python

When I need a new tool, I often code it in Python.  Often, command line options are useful. Sometimes it is possible to have a fixed set of parameters, but this is not very flexible. Fortunately, Python has standard libraries to handle parsing command lines.  There are three libraries providing varying capabilities.  Some of the systems I run on have older versions like Jython 2.1 or Python 2.6.  This limits which libraries I can use without backporting libraries

This document provides examples for four command line processing options.  The examples are for a program that processes files and has an optional argument to report the execution time. Continue reading “Command Line Arguments in Python”

MX on a Dynamic IP Address

I often see posting asking about running a mail server on a Dynamic IP address.  Twenty years ago I started running my server on a dynamic IP address.  However, times have changed, and it is more difficult to do so.   However, there are mail server roles that work reasonable well on a dynamic IP address.   Continue reading “MX on a Dynamic IP Address”