Apache, PHP 7, FPM & Let’s Encrypt TLS certificates on Debian Stretch

This WP blog is running on a small server accompanied by teamobsession.at, the freerunning & parcour team from my brother. The reasoning for WordPress is Divi, which let’s not-so-experienced users build awesome websites, including family members.

Lately I’ve seen many OOM killer messages which sacrificed the MariaDB in most cases. I investigated over the past months, collecting logs, performance metrics and so on.


Apache, PHP and FPM

At some point, MariaDB tuning wasn’t helpful for memory optimizations. Since this box evolved from Debian Wheezy to Jessie to Stretch, I realized that it may be just Apache and PHP, freed mind after a relaxed vacation. I’m not a friend of limiting connections or debugging the mpm_prefork module (great explanation though in this blog post).

a2query -m mpm_prefork

vim /etc/apache2/mods-enabled/mpm_prefork.conf

Recent times with Icinga Web 2 have shown how easy, fast and reliable PHP FPM works. The PHP module is not directly loaded into Apache’s memory and then forked into child processes. Instead, the Apache processes forward the requests via socket to the FPM daemon which just executes given tasks. More tuning tips in this blog post.

While I figured that my box still runs the EOL PHP5 versions (a good indicator for bad performance or leaks), I did the upgrade in two ways:

  • Go for PHP 7 (
  • Go for PHP FPM

WP needs the mbstring & xml PHP modules as otherwise xmlrpc with Jetpack Publicize breaks, Debug: “https://jetpack.com/support/debug/?url=https://www.legendiary.at”.

Debian makes this upgrade super easy with just a couple of CLI commands enabling this globally. “a2enmod” was btw the inspiration for “icinga2 feature enable” ๐Ÿ˜‰

apt-get update
apt-get install php php-mysql php-mbstring php-xml

apt-get install php-fpm

a2enmod proxy_fcgi setenvif
a2enconf php7.0-fpm
systemctl restart apache2

In order to test this, put a test php file somewhere

vim /var/www/html/p.php

<?php echo phpinfo(); ?>

Open it in the browser to check the “Server API” string. Next, delete it immediately as it exposes internal data which are a security risk these days.

rm /var/www/html/p.php 


TLS with Let’s Encrypt

I’m following the Let’s Encrypt evolution closely but always put it back on the TODO list. Modern times prove us right to only use TLS, and so does Google with marking non-https connections as insecure. Recently I’ve learned that the Let’s Encrypt chain is fully trusted by all major root programs, so you don’t need to provide the full CA chain in your web server’s TLS certificate configuration anymore.

Follow these instructions for Debian Stretch, and enable the backports repository first. Hint: I don’t like polluting the sources.list with custom stuff, I just put the configuration into sources.list.d. Then just install the certbot package.

cat >/etc/apt/sources.list.d/backports.list <<EOF
deb http://ftp.debian.org/debian stretch-backports main

apt-get update
apt-get install python-certbot-apache -t stretch-backports

Run the certbot CLI command and provide the request information. I’m just using the default and enforce HTTPS connections.

certbot --authenticator webroot --installer apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer apache
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): michael.friedrich@...

Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
(A)gree/(C)ancel: a

Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
(Y)es/(N)o: n

Which names would you like to activate HTTPS for?
1: legendiary.at
2: web.legendiary.at
3: www.legendiary.at
4: teamobsession.at
5: www.teamobsession.at
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1 3 4 5
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for legendiary.at
http-01 challenge for www.legendiary.at
http-01 challenge for teamobsession.at
http-01 challenge for www.teamobsession.at
Input the webroot for legendiary.at: (Enter 'c' to cancel): /var/www/www.legendiary.at/htdocs

Select the webroot for www.legendiary.at:
1: Enter a new webroot
2: /var/www/www.legendiary.at/htdocs
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Input the webroot for www.legendiary.at: (Enter 'c' to cancel): /var/www/www.legendiary.at/htdocs

Select the webroot for teamobsession.at:
1: Enter a new webroot
2: /var/www/www.legendiary.at/htdocs
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 1
Input the webroot for teamobsession.at: (Enter 'c' to cancel): /var/www/www.teamobsession.at/htdocs

Select the webroot for www.teamobsession.at:
1: Enter a new webroot
2: /var/www/www.teamobsession.at/htdocs
3: /var/www/www.legendiary.at/htdocs
Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/www.legendiary.at-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/www.legendiary.at-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/www.legendiary.at-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/www.legendiary.at-le-ssl.conf
Created an SSL vhost at /etc/apache2/sites-available/www.teamobsession.at-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/www.teamobsession.at-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/www.teamobsession.at-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/www.teamobsession.at-le-ssl.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting vhost in /etc/apache2/sites-enabled/www.legendiary.at.conf to ssl vhost in /etc/apache2/sites-available/www.legendiary.at-le-ssl.conf
Redirecting vhost in /etc/apache2/sites-enabled/www.teamobsession.at.conf to ssl vhost in /etc/apache2/sites-available/www.teamobsession.at-le-ssl.conf

Congratulations! You have successfully enabled https://legendiary.at,
https://www.legendiary.at, https://teamobsession.at, and https://www.teamobsession.at

You should test your configuration at:

- Congratulations! Your certificate and chain have been saved at:
Your key file has been saved at:
Your cert will expire on 2018-11-17. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

The certbot command also automatically installs certificate renewal, so nothing to worry about. One of the domains is not automatically detected, so I needed a small adjustment to fully support the CNAME from www.freerunningacademy.at.

certbot run -d www.teamobsession.at -d teamobsession.at -d www.freerunningacademy.at -d www.legendiary.at -d legendiary.at

Voilร  ๐Ÿ™‚


Since I am using the Google Drive backup for 4+ years now, I’ve just extended its script to include “/etc/letsencrypt” and “/etc/apache2”. Backups are important ๐Ÿ™‚


Future Plans

At one time I might just put everything into containers and let them run on NETWAYS NWS. My feature request with Let’s Encrypt support still stands ๐Ÿ™‚ The other one is an A+ rating which involves more TLS configuration fine tuning. But that’s something for another weekend after another vacation ๐Ÿ™‚

Clear redirect cache in Chrome

Chrome caches 301 redirects in a certain way. This one caused problems when testing redirects with monitoring-portal.org with / to /woltlab (now removed).

There is no direct configuration setting for this, you need to visitย chrome://net-internals/ in Chrome. Then right click on the cursor icon in the right upper corner and select “clear cache”.

Fix pre tags not wrapping text in Divi WP theme

Using the Divi WordPress theme is pretty nice, but sometimes you’ve gotta deal with custom css and fixes. The pre tag uses the entire page width which looks pretty ugly with the menu on the right. Reading over here says that text wrap is not enabled by default.

Thanks Bernd providing me a fix for that!

Add the following to your Divi Theme Options as “Custom CSS” and save it.

pre {
   white-space: pre-wrap;