WordPress SFTP into FreeBSD jail

FreeBSD jail with WordPress SFTP plugin article image

The purpose of this article is to make it easy for WordPress and its 3rd party SFTP plugin to work on a FreeBSD host where the website and web server daemon runs within a jail, but the sshd daemon runs on the host thereby causing problems that prevent the WordPress SFTP plugin from working properly. In this article we enable remote read/write access to the WordPress application to enable it to self-update, using an sftp user who is restricted from seeing or accessing the rest of host’s  filesystem. The jail configuration for WordPress significantly limits the scope of a breach should WordPress or any one of its plugins become compromised by an attacker down the road. This article assumes any modern FreeBSD version is used. The author is using FreeBSD 10 and this very likely works on earlier versions too.

We’ll start by creating a special sftp/ssh user for WordPress on the FreeBSD host.

First create a new group called “chroot”:

pw groupadd chroot

Next, create a new user such as “wordpress-larry” and ensure their primary login group is set to “chroot”. You should likely add the user to an additional, secondary group such as “www” so they can access/edit files for the website.


Run the adduser command and follow the prompts to create a new user with a STRONG password. In our case we’ll create a new user with the username “wordpress-larry”. Now let’s switch to that user and create a new SSH private/public key pair for logging in, since it’s safer to use keys than a password:

su myuser
cd ~
ssh-keygen -t rsa -b 4096

At this point we need to edit the /etc/ssh/sshd_config file to ensure the user is chroot’ed within their home directory only. The goal is to prevent a rogue user from having any access to the rest of the filesystem, we want to keep him in the protected jail. Edit the file and add a new group for chroot, like this:

nano /etc/ssh/sshd_config

  Match group          chroot
    ChrootDirectory    /home/%u
    X11Forwarding      no
    AllowTcpForwarding no
    ForceCommand       internal-sftp

One the configuration has been updated, restart the SSH daemon, sshd:

/etc/rc.d/sshd restart

The user can only navigate within their home directory thanks to the ChrootDirectory configuration. However we do need them to access part of a website with files located elsewhere, so let’s first mirror the directory structure as seen within a jailed login, so it looks like the wordpress location when the user logs in:

mkdir –p /home/myuser/wordpress

Next we’ll use a filesystem mount to mount the website’s directory into the user’s home directory using mount_nullfs, where “source” is the /full/path to the files you want to make available to the user:

mount_nullfs /path/to/wordpress/files /home/myuser/wordpress

Confirm the mount was successful then create an entry in /etc/fstab related to the above, making sure the entry is all on one line:

/path/to/wordpress/files/ /home/myuser/wordpress/ nullfs rw 0 0

For remote access, it’s critical that the user’s directory be owned by “root” and also be part of the “chroot” group, or else SSH/SFTP will not allow the user to even login:

chown –R root:chroot /home/myuser
chmod 755 /home/myuser

Finally, test the connection (using SFTP, not SSH) to make sure it’s working. Logging in manually will let you confirm that the WordPress files are there, in the user’s home directory, and so the SFTP plugin will be able to function in WordPress with the added security of only being able to see and edit files located in the website’s jail.


Kelly’s MySQL quick tutorial

You don’t need tools like MySQLAdmin when basic tasks like creating and deleting databases, adding users and adjusting permissions can easily be done from the command line. I run these commands on a FreeBSD system and is likely the same on Linux, Windows, and other systems.

Basic tasks

Log into mysql:

#mysql –u root –p
password: ******

Welcome to MySQL………

Create database:

>create database Frankenstein;
>use Frankenstein;

Create user:

>GRANT ALL PRIVILEGES ON Frankenstein.* TO Bob@localhost IDENTIFIED BY “bobspassword69” WITH GRANT OPTION;

Then reload the grant tables in the database using flush privileges. If you forget this step you can also run “mysqladmin reload” to reload the grant tables. Then exit.


At this point you should be golden.

On a side note, if you experience a problem where MySQL keeps exiting with an error about mysql.sock on FreeBSD, it’s likely a permissions problem in your system. If you have this problem, try something like this:

“do you already have another mysqld server running on socket: /var/run/mysql/mysql.sock ?”

#chown _mysql /var/run/mysql

What about backup and recovery?

Now that we have amazing content in our database, we must backup the database to keep it safe like this:

mysqldump –u bob –p Frankenstein > frankenstein-backup-01Jan2023.sql

Whew. Now let’s restore the database into a running MySQL server of our choice:

mysql –u bob –p Frankenstein < frankenstein-db-backup-01Jan2023.sql

Anything else? Consult the manual, search the web, or add a comment here.