Running WordPress on OpenBSD 6.5 with OpenBSD's HTTPD

Published on: Fri, Aug 9, 2019 at 11:36 am EST
BSD Blogging CMS Server Apps

Introduction

The closer you keep your OpenBSD install to the default and without as many added packages, the more secure it will be. While the more common setup for WordPress is to use Apache and PHP, it is definitely possible (and preferable) to use OpenBSD's built-in httpd. This tutorial will get you started with a complete setup of a Let's Encrypt certificate, a web server, and WordPress. You will need root access in order to be able to do this.

Initial Configuration

If you have not already done so, you will need to create a /etc/doas.conf file. The doas command is OpenBSD's easy replacement for sudo.

su -
echo "permit nopass keepenv :wheel" > /etc/doas.conf

We have to tell OpenBSD where the packages are located. This happens in the /etc/installurl file.

doas su
echo "https://cdn.openbsd.org/pub/OpenBSD" > /etc/installurl
exit

Now we have to add PHP and some extra modules that WordPress will need in order to handle things like images and encryption. When prompted, choose to install the newest package of PHP. One thing you have to do is to copy the module ini files from the sample directory to the main one. This has to be done in order to enable the additional PHP modules.

doas pkg_add -r mariadb-client mariadb-server php php-curl php-mysqli pecl73-mcrypt pecl73-imagick 
doas su -
cp /etc/php-7.3.sample/* /etc/php-7.3/.

Obtain Let's Encrypt Certificates

OpenBSD has a great application called acme-client. This little innovation is what will generate your account key, private key, and obtain a certificate for you. The acme-client depends upon having a web server in place so we define a quick default server definition.

With your favorite editor, create /etc/httpd.conf. We will add the other server definitions to the file later. What we need to do now is prepare httpd to perform the challenge-response to obtain a free, valid SSL certificate.

prefork 5
types { include "/usr/share/misc/mime.types" }

server "default" {
    listen on egress port 80
    root "/htdocs"
    directory index "index.html"

    location "/.well-known/acme-challenge/*" {
        request strip 2
        root "/acme"
    }
}

Also using your favorite editor, create /etc/acme-client.conf.

authority letsencrypt {
    api url "https://acme-v01.api.letsencrypt.org/directory"
    account key "/etc/acme/letsencrypt-privkey.pem"
}

authority letsencrypt-staging {
    api url "https://acme-staging.api.letsencrypt.org/directory"
    account key "/etc/acme/letsencrypt-staging-privkey.pem"
}

domain example.com {
    alternative names { www.example.com }
    domain key "/etc/ssl/private/example.com.key"
    domain full chain certificate "/etc/ssl/example.com.fullchain.pem"
    sign with letsencrypt
}

Enable and start httpd, then get a certificate issued. You will see that a certificate has been issued.

doas rcctl enable httpd php73_fpm
doas rcctl start httpd
doas acme-client -ADFv example.com
doas rcctl stop httpd

Adding the Server Definitions

Add the following configuration lines to /etc/httpd.conf, just after the Let's Encrypt definitions. Setup httpd to perform a redirect from http to https because you have a free SSL certificate and you never want to risk sending a login and password over an insecure link. Take note of the line, location "/posts/*" This is the piece that makes the WordPress permalinks look pretty. Also, this config contains a way to help prevent brute-force attempts to login to the WordPress admin site.

server "example.com" {
    listen on egress port 80
    alias "www.example.com"
    block return 302 "https://$SERVER_NAME$REQUEST_URI"
}

server "example.com" {
    listen on egress tls port 443
    alias "www.example.com"
    root "/htdocs/example.com
    directory index "index.php"

     location "/posts/*" {
        fastcgi {
             param SCRIPT_FILENAME "/htdocs/example.com/index.php"
             socket "/run/php-fpm.sock"
        }
     }

     location "/wp-json/*" {
        fastcgi {
           param SCRIPT_FILENAME "/htdocs/example.com/index.php"
            socket "/run/php-fpm.sock"
        }
     }

    location "/wp-login.php*" {
        authenticate "WordPress" with "/htdocs/htpasswd"
        fastcgi socket "/run/php-fpm.sock"
     }

    #Uncomment the following lines to disable xmlrpc. You increase security 
    #at the expense of being able to use to use 
    #the Android and iPhone WordPress App.
    #location "xmlrpc.php*" {
    #    block return 404
    #}        

    location "*.php*" {
        fastcgi socket "/run/php-fpm.sock"
     }

    tls {
        certificate "/etc/ssl/example.com.fullchain.pem"
        key "/etc/ssl/private/example.com.key"
    }
}

Create the username and password file for an additional level of security to the WordPress admin site. Choose a good password. This will prompt you for a username and password in order to run the wp-login.php script.

doas su
cd /var/www/htdocs
htpasswd htpasswd wp_user
chown www:www htpasswd
chmod 0640 htpasswd

Prepare and Configure MariaDB

MariaDB is a drop-in replacement fork of MySQL. We need to do some initial configuration and database preparation work for WordPress.

Before we can use MariaDB effectively, we need to allow the mysql daemon to use more resources than the default. In order to do this, make the following changes to/etc/login.conf by adding this entry at the bottom.

mysqld:\
    :openfiles-cur=1024:\
    :openfiles-max=2048:\
    :tc=daemon:

Enable and start MariaDB. This procedure will set a root password and optionally drop the test database. It's a good idea to follow the suggestions in the secure installation stage.

 doas mysql_install_db
 doas rcctl enable mysqld
 doas rcctl start mysqld
 doas mysql_secure_installation

Create the WordPress database and database user.

mysql -u root -p 
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost' IDENTIFIED BY '<password>';
FLUSH PRIVILEGES;
EXIT

Install and Configure WordPress

WordPress has not had an official OpenBSD port for quite some time because it pretty much works right out of the box. Download, extract, and move the WordPress installation folder.

cd /tmp
wget https://wordpress.org/latest.tar.gz
tar xvfz latest.tar.gz
doas mv wordpress /var/www/htdocs/example.com
chown -R www:www /var/www/htdocs/example.com

We have to copy /etc/resolve.conf and /etc/hosts to /var/www/etc. This is so that WordPress can successfully reach the marketplace. You will need this in order to download plugins and themes via the WordPress admin site.

doas mkdir /var/www/etc
doas cp /etc/hosts /var/www/etc/.
doas cp /etc/resolv.conf /var/www/etc/.

Start httpd and php73_fpm.

doas rcctl start httpd php73_fpm

Browse to the url that you used in your server definition. You will see the WordPress installation wizard. For the Database server option, replace localhost with 127.0.0.1.

Once WordPress has been installed, it's time to set up the permalinks so that they look more SEO friendly. From the WordPress admin screen, go to Settings -> Permalinks. Click on Custom Structure and type /posts/%postname%. After making this change, click the Save Changes button. You now have much nicer looking links. For example, a permalink will look like this: https://example.com/posts/example-blog-post

Want to contribute ?

You could earn up to $300 by adding new articles