PKG, Chroot, PHP oh my!
Welcome back to Installing WordPress 4.9.4 on OpenBSD 6.2. In this installment we are going to look into enabling the httpd web server on OpenBSD 6.2, install php-7.0.23 and its associated components needed for serving WordPress PHP content. Our goals for this post is to:
- Go over the PKG system for installing applications
- Discuss Chroot and httpd daemon
- Set up the PKG system to pull the binaries we require
- Install the php-7.0.23 components we need
- Configure php
- Configure and test the httpd_config.test file to server both html and php
Much like we did with ssh, we will test our php installs and the web server httpd using a combination of windows. We will be using two terminal sessions in two separate windows today:
- A “VPS” in which we will be starting httpd sessions in debug mode
- A “Maintenance” widow to be used to make any changes to your configuration files etc.
Open a ssh connection using you Client window to your VPS as “bob” and su to root. We will need root privileges to make our changes.
Lets create a test httpd configuration file to try our new changes in. We will call this test httpd config file httpd_config.test. To make the httpd_config.test, simply use “cp” to make a copy of /etc/examples/http.config to a new name and place it into the /etc directory. The /etc/examples directory has a bunch of sample scripts to use as starting points. Just remember to never use one directly, make a copy and place it in /etc before editing.
cp /etc/examples/httpd.config /etc/httpd_config.test
Now edit the /etc/httpd.conf file in your favorite text editor to look like this:
# $OpenBSD: httpd.conf,v 1.14 2015/02/04 08:39:35 florian Exp $ # # Macros # ext_addr="*" # # Global Options # # prefork 3 # # Servers # # A minimal default server server "default" { listen on $ext_addr port 80 root “/htdocs” directory index “index.html” } types { include "/usr/share/misc/mime.types" }
This tells the httpd daemon to listen on all external IP addresses and take http requests on port 80 and process them by executing the index.html file located in /var/www/htdocs using the mime type located in the file /usr/share/misc/mime.types”
We will change the httpd.conf to process requests properly in the future, but for now, this will get us up and testing. Now in your editor create the /var/www/htdocs/index.html file and copy this into it:
<html> <body> <h1>This is my index.html test page</h1> </body> </Html>
And save it. Now it’s time to test.
<Test>
In your VPS window make sure your running as root. Now lets start or httpd in debug (-d) mode with verbosity turned to medium (-vv) using our httpd_config.test (-f /etc/httd_config.test)
httpd -d -vv -f /etc/httpd_config.test
Open up your web browser and point it to http://<IP address of your server>. You should see in rather large letters “This is my index.html test page” displayed. Now shut off the httpd debug session using ctrl+c in the VPS window.
</Test>
As we build up our system we will be performing similar tests to verify we have a working system as we configure each piece.
$PKG_PATH
Before we can install anything we will need to setup the Package Management(PKG) system on our VPS. The PKG system is a collection of application and libraries the OpenBSD Ports Team has ported to the OpenBSD platform. This collection has been vetted to the best of their abilities for security vulnerabilities and to insure compatibility with the OS itself. An application may have dependencies on other binaries. An application package when installed will check for those dependencies and will ask you if it can install them, if you agree, then it does. In this way you get a completely installed program that uses shared dependencies with other programs, so it does not have to install the same file twice. PKG relies on Mirrors which are stores located around the world of applications installs that are downloaded via HTTP or FTP protocol. You must first setup the environment variable $PKG_PATH to a suitable Mirror near you that contains the binaries you are after, and not all Mirrors contain the same applications so sometime you will need to look around. I used the Mirror out of Boulder, Colorado ftp://ftp3.usa.openbsd.org/pub/OpenBSD/.
You need to provide a complete path to the package store which looks something like this “ftp://ftp3.usa.openbsd.org/pub/OpenBSD/6.2/packages/amd64/”. But if you back up your user directories like I do you will want to make this path dynamic incase you upgrade your OpenBSD to a newer version. Restoring your root directory to the new system would point you to the wrong Mirror if this is hardcoded. So lets make this dynamic:
Connect to your VPS with your Maintenance window as bob and su to root and change directory to roots home directory
Cd ~
In your favorite editor open the “.profile”. Add the following lines after the export PATH statement
PKG_PATH=ftp://ftp3.usa.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/ export PKG_PATH
On system startup or login, this loads a PKG_PATH variable for the root user only (because who else should be installing software on a server?) and exports it for use on the system. The `uname -r` sets the current version of the OS and the `name -m` sets the processor sku that was installed dynamically. Now you can copy the root .profile file to any server and the PKG_PATH will point to the correct package location. Now exit out of root and su back in with the login switch (-l) so the .profile is reloaded then echo the PKG_PATH to confirm our change:
exit su root -l echo $PKG_PATH
In my case I get “ftp://ftp3.usa.openbsd.org/pub/OpenBSD/6.2/packages/amd64/” where “6.2” and “and64” are provided by the `uname -r` and `name -m` respectively.
chroot
A quick word about chroot, sometimes referred to as a “sandbox” and often incorrectly referred to as a “jail”. Chroot (short for change root) is a process where a given user or process is constrained to a subtree of a directory structure. Once “chrooted” the process cannot see above the subtree and the top most path is now “/“. This keeps malicious users or bad code from trashing the whole file system as they cannot see or access anything outside of the chroot. The OpenBSD web server httpd runs under /var/www/ and is chrooted to /var/www. From httpds perspective, it runs under /. It cannot see above /var/www. Here is an example:
This is the directory structure of /var. |
This is what httpd chrooted to /var/www sees |
/var |-Account |-audit |-authpf |-backups |-cache |—fontconfig |-crash |-cron |—atjobs |—tabs |-db |—acpi |—ldap |—ns |—pkg |—–colorls-6.0 |—–quirks-2.367 |—xkb |—yubikey |-empty |-games |—hackdir |—–save |—phantasia |—save |-log |—rdist |-nsd |—db |—etc |—run |—–xfr |—zones |—–master |—–slave |-quotas |-run |—rc.d |-spool |—ftp |—–bin |—–etc |—–hidden |—lock |—output |—–lpd |—smtpd |—–corrupt |—–incoming |—–offline |—–purge |—–queue |——-36 |——-9c |—–temporary |-sysmerge |-syspatch |-unbound |—db |—etc |-www |—acme |—bin |—cache |—cgi-bin |—conf |—htdocs |—–bgplg |—logs |—run |-yp |
/ |-acme |-bin |-cache |-cgi-bin |-conf |-htdocs |—bgplg |-logs |-run |
Chroot generally means two things to us. The first thing is that we have greatly reduced the threat surface of a malicious web user. The second thing is, as we will see later, if we need anything outside of the chroot we need to copy it into the chroot to use it. There are exceptions such as sockets but for the most part, you are confined to the chroot. However it is not fool proof and should never be considered a “Jail”.
Ok lets load the PHP packages we need for this project. Here is the list of applications we will need to grab:
php-7.0.23 – base PHP package
php-gd-7.0.23 – PHP image manipulation extensions
php-mysqli-7.0.23 – PHP mysql database access extensions
php-curl-7.0.23 – PHP command line Universal Resource Locator that allows you to connect and communicate to those interfaces
The primary tools we will use for loading packages onto our system are pkg_info and pkg_add.
pkg_info
Pkg_info will allow us to query our Mirror to see whats available among other capabilities. An example of this would be “pkg_info -Q ”<name> searches for all packages with <name> in the name. Do not include the version number in the query. Found one your curious about? Type pkg_info -q <name> and you’ll get a brief synopsis of what it is for. For example:
To find all php packages available on your Mirror…
pkg_info -Q php
Returns a list of applications with “php” in the name:
drupal6-phpmailer-2.2p2 gpsd-php-2.95p8 p5-PHP-Serialization-0.34 p5-PHP-Session-0.27 pear-Date-Holidays_PHPdotNet-0.1.2p1 php-5.5.37p0 php-5.6.23p0 php-7.0.23 …
To find out what, say, php-7.0.23 is all about (mind the “q” – size matters here)…
pkg_info -q php-7.0.23
Returns a synopsis of that package:
server-side HTML-embedded scripting language php-curl-7.0.23 php-gd-7.0.23 php-mysqli-7.0.23 At the most basic level, PHP can do anything any other CGI program can do, such as collect form data, generate dynamic page content, or send and receive cookies. PHP also has support for talking to other services using protocols such as IMAP, SNMP, NNTP, POP3, or even HTTP. You can also open raw network sockets and interact using other protocols. This package installs a stand-alone binary which can be used for command-line scripts, as well as an Apache module. It also contains the pdo_sqlite driver that implements the PHP Data Objects (PDO) interface to enable access to SQLite 3 databases. Maintainer: Robert Nagy <robert@openbsd.org> WWW: http://www.php.net/
Don’t be fooled, the php applications listed in the synopsis are not dependencies, they are just part of the synopsis, included at the authors discretion. If you want to see the dependencies, we have a switch (-f) for that. But it dumps everything about the package, we will need to filter it a bit using grep:
pkg_info -f php-7.0.23 | grep ‘^@depend’ | cut -f 3 -d :
Returns:
gettext-0.19.7 femail-chroot-1.0p2 libxml-2.9.3
Bare in mind each dependency most likely has its own list of dependencies it needs to install.
Now you know what php-7.0.23 is and what it is used for and what will get installed besides php-7.0.23 to make php-7.0.23 work correctly. Kinda cool huh?
pkg_add
Pkg_add will install (or update) an application. It also has some useful switches but I leave those up to you dear reader to explore. To use pkg_add is fairly simple:
pkg_add -n php-7.0.23
Will show what would be installed but does not do the install and list the dependencies of the package to be installed with a extraction progress indicator by %. It will tell you if any new scripts were installed in /etc/rc.d and where to look in /usr/local/share/doc/pkg_readmes for extra documentation
pkg_add php-7.0.23
Installs the package and gives you the same output as pkg_add -n php-7.0.23. You can list several packages on the same call to pkg_add. I prefer to call them one at a time.
Ok onto the installs. This is the easy part because a lot of developers who donate their time to the OpenBSD project have made it that way. In your terminal as root run the following commands:
pkg_add php-7.0.23 pkg_add php-curl-7.0.23 pkg_add php-gd-7.0.23 pkg_add php-mysqli-7.0.23
To see everything that has bee installed on your system, typing pkg_info by itself will give you a list of everything currently installed:
pkg_info
Returns:
colorls-6.0 ls(1) that can use color to display file attributes curl-7.55.1 get files from FTP, Gopher, HTTP or HTTPS servers femail-1.0p1 simple SMTP client femail-chroot-1.0p2 simple SMTP client for chrooted web servers gettext-0.19.8.1p1 GNU gettext runtime libraries and programs jpeg-1.5.1p0v0 SIMD-accelerated JPEG codec replacement of libjpeg libiconv-1.14p3 character set conversion library libxml-2.9.5 XML parsing library mariadb-client-10.0.32v1 multithreaded SQL database (client) nghttp2-1.26.0 library for HTTP/2 php-7.0.23 server-side HTML-embedded scripting language php-curl-7.0.23 curl URL library extensions for php5 php-gd-7.0.23 image manipulation extensions for php5 php-mysqli-7.0.23 mysql database access extensions for php5 png-1.6.31 library for manipulating PNG images quirks-2.367 exceptions to pkg_add rules xz-5.2.3p0 LZMA compression and decompression tools
We now have our php components installed. But before we can use them we have to configure them. To do that we need to:
- Set up an /var/www/htdocs/index.php to test with
- Alter the /etc/httpd_config.test file
- Create the empty /etc/rc.conf.local file
- Enable and start the php daemon.
- Check your work using your web browser
- Configure curl in php7.0.ini
- Check your work using your web browser to see if curl was configured.
Lets create the /var/www/htdocs/index.php by using touch.
touch /var/www/htdocs/index.php
Now using your favorite editor change the empty file contents to:
<?php phpinfo(); ?>
Save Index.php. Now edit /etc/httpd_config.test and change the contents of the server block to the following:
# A minimal default server server "default" { listen on $ext_addr port 80 root "/htdocs" # directory index "index.html" directory { index "index.php" } location "*.php" { fastcgi socket "/run/php-fpm.sock" } }
Save the /etc/httpd_config.test. Now lets enable PHP. We need to make a /etc/rc.conf.local using touch.
Touch /etc/rc.conf.local
Now using rcctl we will enable php fastcgi socket to run
rcctl enable php70_fpm
You can check the /etc/rc.conf.local file, you should see one line in there that looks like this:
pkg_scripts=php70_fpm
Start the php70_fpm using rcctl
rcctl start php70_fpm
Start your httpd debug session in its own window as we did before. Open up your web browser and point it to http://<IP address of your server>. You should see the rather large summary of php components available to your web service. But we are missing the “command line URL” processor or “curl” component. We need to configure that in the /etc/php-7.0.ini. Open the /etc/php-7.0.ini and scroll down to the extension section, it looks a lot like this:
;;;;;;;;;;;;;;;;;;;;;; ; Dynamic Extensions ; ;;;;;;;;;;;;;;;;;;;;;; ; If you wish to have an extension loaded automatically, use the following ; syntax: ; ; extension=modulename.extension ; ; For example, on Windows: ; ; extension=msql.dll ; ; ... or under UNIX: ; ; extension=msql.so ; ; ... or with a path: ; ; extension=/path/to/extension/msql.so ; ; If you only provide the name of the extension, PHP will look for it in its ; default extension directory. ; ; Windows Extensions ; Note that ODBC support is built in, so no dll is needed for it. ; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5+) ; extension folders as well as the separate PECL DLL download (PHP 5+). ; Be sure to appropriately set the extension_dir directive. ; ;extension=php_bz2.dll ;extension=php_curl.dll ;extension=php_fileinfo.dll ;extension=php_ftp.dll ;extension=php_gd2.dll …
Verify the path to the curl.so using find.
find / -name curl.so
Add the following line at the end of the extension section:
extension=/usr/local/lib/php-7.0/modules/curl.so
Save the /etc/php7.0.ini and restart php using rcctl
rcctl restart php70_fpm
Start your httpd debug session in its own window as we did before. Open up your web browser and point it to http://<IP address of your server>. You should see the rather large summary of php components available to your web service, including a section called “Curl”. This good as WordPress uses curl to process requests for plugins and themes.
Ok, enough fun for today. Lets shutdown our httpd by executing a ctrl+c in the window running it. The php daemon will now start automatically when the server is restarted. If you want to shut php down as well, use rcctl.
rcctl stop php70_fpm
The httpd will be enabled later using rcctl after we have a working WordPress install.
It is better to keep your web server offline until you have it secured against malicious intruders.
So today we have accomplished quite a lot. I went over the PKG system, how to configure it and some basic techniques on how to use it. I discussed httpd daemon and the chrooted environment it runs in. We set up the httpd_config.test file for testing our httpd configuration and ran it in debug mode as we tested first HTML file and later PHP file serving. We installed all of our php components, created the rc.conf.local file and enabled php and configured CURL and the php70_fpm fastcgi socket to work in our chrooted httpd environment. All in all a good day.