Using the modified Apache web server in OpenBSD
Apache's httpd is a good web server. OpenBSD is a good operating system. How can we make the combination work even better?
We can add compression of the HTTP data transfer if the client's browser supports it (and unless they are using something truly ancient or bizarre, it should).
This should improve page load time and it may significantly reduce bandwidth utilization at both the server and client ends. How much of an improvement? Since images are already compressed, the improvement you get will depend on how much of a typical page is HTML (the content and the markup, including style details) as opposed to image comment.
But won't this increase the server CPU load? Surprisingly, not nearly as much as you would expect! That is, unless you are dynamically generating your pages, and maybe not even then. Linux Journal had an article about this.
If you are concerned, here is the result of using
to run the command:
top -d 1
on this server as it was generating this page. Really.
last pid: 65813; load averages: 0.19, 0.44, 0.46 up 30+11:17:09 02:57:57 35 processes: 1 running, 34 sleeping Mem: 47M Active, 271M Inact, 54M Laundry, 183M Wired, 65M Buf, 11M Free Swap: 1024M Total, 29M Used, 995M Free, 2% Inuse PID USERNAME THR PRI NICE SIZE RES STATE TIME WCPU COMMAND 35222 www 64 20 0 159M 53512K piperd 3:23 0.00% httpd 640 root 1 20 0 18532K 10436K select 2:59 0.00% ntpd 738 root 1 20 0 20636K 5068K select 0:52 0.00% sendmail 656 root 1 20 0 94316K 10144K piperd 0:43 0.00% python2.7 16387 www 64 30 0 149M 28344K piperd 0:22 0.00% httpd 554 root 1 20 0 10500K 1952K select 0:12 0.00% syslogd 16376 www 1 52 0 36324K 4900K accept 0:09 0.00% php-fpm 16375 www 1 52 0 36324K 4936K accept 0:09 0.00% php-fpm 785 root 1 20 0 12592K 2092K nanslp 0:08 0.00% cron 16374 root 1 20 0 36196K 3988K kqread 0:08 0.00% php-fpm 16383 root 1 20 0 103M 7264K select 0:06 0.00% httpd 65012 www 1 42 0 36324K 5272K piperd 0:06 0.00% php-fpm 768 root 1 20 0 57812K 4724K select 0:06 0.00% sshd 35221 www 64 20 0 135M 30528K piperd 0:04 0.00% httpd 410 root 1 20 0 9560K 80K select 0:02 0.00% devd 741 smmsp 1 20 0 20636K 4732K pause 0:01 0.00% sendmail 16384 www 64 52 0 131M 15324K piperd 0:01 0.00% httpd 35220 www 64 20 0 123M 15780K piperd 0:00 0.00% httpd
You can click the Reload button and you will see that things change slightly. The time (end of first line) is local time at the server, UTC-4. I would expect the CPU to be almost 100% idle, unless you happen to have loaded this page while the server is busy running a scheduled job or some other infrequent task.
What are we working with?
OpenBSD comes with something that isn't exactly Apache's httpd. The web server is the result of an OpenBSD code audit, bug patching, and hardening of something out of the Apache 1.3 web server product line. As the OpenBSD documentation says, "The OpenBSD team has added default chrooting, privilege revocation, and other security-related improvements."
Step 1 — Install the mod_gzip package
The mod_gzip Apache module is not included in the stock
It is part of the
packages and ports system.
If you have downloaded the full set of packages, you
have the file you need.
If not, it can be as simple as this if you use
# setenv PKG_PATH ftp://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m` # pkg_add mod_gzip
# PKG_PATH=ftp://ftp.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m` # pkg_add mod_gzip
Notice that those are backquotes
for command substitution!
uname commands run first,
producing output similar to
Those results are then placed into the assignment of the
Step 2 — Modify your Apache configuration file
has a nice description of how to get mod_gzip to work
in many situations,
click here to see that.
I have based what I did on his work, with some
additions required for OpenBSD or any other similarly
root, start editing
and search for the string
When you installed that package, a post-install script within
the package should have added a line loading that module.
If it did not,
find the area of the file where modules are loaded and
add a similar line (and, to help yourself in the future,
a comment!) like the following:
# Add compression LoadModule gzip_module /usr/lib/apache/modules/mod_gzip.so
Now add a stanza directly below that. It should be similar to the following, but you may want to adjust the minimum and maximum file sizes:
Step 3 — Set up the
Here is the trick required to get this to work on OpenBSD or any other chroot environment, something that isn't frequently mentioned in the documentation.
Remember that you told your compression module to
/tmp as a working area.
However, the OpenBSD web server process is using
to run in an unusual environment
(unless you have changed
to make it behave otherwise).
httpd process is running in a "sandbox" of
Its notion of the root of the file system isn't the real root.
This means that there is no "
no way to go up one level and get out of the
jail (or gaol as it's spelled in Britain).
httpd process thinks is
is really the
So, we have to create something that will appear to
be a proper
/tmp for that process.
# cd /var/www # mkdir tmp # chmod 1777 tmp
Step 4 — Let's see if that works!
Stop the running web server process:
# pkill httpd
Make sure that really worked:
# ps axuww | egrep 'PID|httpd' # lsof -i tcp:80
You may need to give an active request a moment or two to
lsof is in
root doesn't have that in the path.
Once the coast is clear, start a fresh web server process:
Yes, I probably could have done this with a HUP signal, but killing it off and starting a new one makes it a little easier to avoid sysadmin confusion. If you are concerned about not refusing a single request, look into doing it this way:
# pkill -HUP httpd
Who cares about mod_gzip, how did you do that
This page exists as an HTML file on the server containing a block like the below. The web server process executes the PHP code on the server and inserts the output in the page.
<pre style="background: #000000; color: #00ff00; font-size: 85%; padding: 5px 3px 5px 3px; border: medium solid orange;"> <?php @ passthru ('top -d 1 | grep -v "^$"'); ?> </pre> </div>
And, because of the
discussed above I had to do the following on the server
to get those two commands to work:
# cd /var/www # mkdir usr usr/bin # cp /bin/sh bin # cp /usr/bin/grep /usr/bin/top usr/bin # ldd bin/sh usr/bin/* [ ... hmm, need to include some shared libraries ... ] # mkdir usr/lib usr/libexec # cp /usr/lib/libc.so.* /usr/lib/libcurses.so.* /usr/lib/libz.so.* /usr/lib # cp /usr/libexec/ld.so usr/libexec