As explained in another article the default Apache’s configuration at compile time sets its multi-processing module (MPM for short) to the pre-fork configuration setting. This is not the best performant configuration for Apache. Out of the box Apache comes compiled in its safest form, from the processing mode perspective since the pre-fork setting will open a process for each connection, so that process will run independently from others; as well as from the legacy perspective because old perl or shell scripts sill surely run.
However it is quite possible you want to squeeze the maximum of your web server as well as from your hardware. So if you happen to have a threading capable CPU (any modern hardware does this) and your operating system has some sort of support for thread-safe polling (kqueue or epoll), just change the configuration of your Apache and use the mpm_event module instead of the pre-fork one.
This is a how to set Apache’s MPM Event and PHP-FPM on FreeBSD, so you do not only get the best of Apache but you configure your FAMP stack to run PHP applications with it. In this article we will basically recreate that FAMP stack (similar to the LAMP) but with a faster configuration.
If you find the articles in Adminbyaccident.com useful to you, please consider making a donation.
Use this link to get $200 credit at DigitalOcean and support Adminbyaccident.com costs.
Get $100 credit for free at Vultr using this link and support Adminbyaccident.com costs.
Mind Vultr supports FreeBSD on their VPS offer.
You may be confused by the threading capability of your CPU. Let’s check that out first and forget about it. Almost every CPU on the AMD64 world (that includes Intel’s x86-64) since 2005 has that capability. But there is a command you can use to clear the doubt. Why this? Read Apache’s official documentation on the matter or skip this first part entirely.
root@Event:~ # dmesg | grep 'SMP'
FreeBSD/SMP: Multiprocessor System Detected: 4 CPUs
FreeBSD/SMP: 1 package(s) x 4 core(s)
SMP: AP CPU #3 Launched!
SMP: AP CPU #1 Launched!
SMP: AP CPU #2 Launched!
root@Event:~ #
This CPU in use here has got SMP (symmetrical multi-processing) and it’s got 4 cores. Chances are this CPU is threading capable. Let’s see if the CPU is Hyper-Threading capble.
[root@Event ~]$ dmesg | grep 'HTT'
Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,
SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,
PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
[root@Event ~]$
Yes, indeed. But just in case you want it to see before your eyes. Let’s grab a process ID and see if there are threads into that process. That would be the deffinitive indicator of a threading capable CPU. If you have an Apache already running it’s as easy as find the number of httpd processes running and then looking for threads.
We will first look for one process.
root@Event:~ # ps aux | grep httpd
root 7795 0,0 0,0 11124 5852 - SsJ 17:44 0:00,06 /usr/local/sbin/httpd -DNOHTTPACCEPT
www 7796 0,0 0,0 18680 7060 - IJ 17:44 0:00,00 /usr/local/sbin/httpd -DNOHTTPACCEPT
www 7797 0,0 0,0 16632 6612 - IJ 17:44 0:00,00 /usr/local/sbin/httpd -DNOHTTPACCEPT
www 7798 0,0 0,0 16632 6640 - IJ 17:44 0:00,00 /usr/local/sbin/httpd -DNOHTTPACCEPT
root 7956 0,0 0,0 6740 2596 0 S+J 18:20 0:00,00 grep httpd
root@Event:~ #
Let’s now look for threads inside one of those processes. Let’s grab the ID 7797.
root@Event:~ # procstat -t 7797
PID TID COMM TDNAME CPU PRI STATE WCHAN
7797 100595 httpd - -1 152 sleep piperd
7797 100719 httpd - -1 152 sleep uwait
7797 100722 httpd - -1 152 sleep uwait
7797 100767 httpd - -1 152 sleep uwait
7797 100783 httpd - -1 152 sleep uwait
7797 100805 httpd - -1 152 sleep uwait
7797 100809 httpd - -1 152 sleep uwait
7797 100814 httpd - -1 152 sleep uwait
7797 100817 httpd - -1 152 sleep uwait
7797 100819 httpd - -1 152 sleep uwait
7797 100827 httpd - -1 152 sleep uwait
7797 100898 httpd - -1 152 sleep uwait
7797 100901 httpd - -1 152 sleep uwait
7797 100905 httpd - -1 152 sleep uwait
7797 100957 httpd - -1 152 sleep uwait
7797 101074 httpd - -1 152 sleep uwait
7797 101094 httpd - -1 152 sleep uwait
7797 101095 httpd - -1 152 sleep uwait
7797 101099 httpd - -1 152 sleep uwait
7797 101203 httpd - -1 152 sleep uwait
7797 101229 httpd - -1 152 sleep uwait
7797 101548 httpd - -1 152 sleep uwait
7797 101668 httpd - -1 152 sleep uwait
7797 101692 httpd - -1 152 sleep uwait
7797 101705 httpd - -1 152 sleep uwait
7797 101707 httpd - -1 152 sleep uwait
7797 101709 httpd - -1 152 sleep kqread
root@Event:~ #
The TID column are all the threads associated with the process 7797. So as you can see this is a threading capable CPU. Again, almost every CPU from 2005 onwards is capable of this.
Now the very fundamental CPU capabilities that make the mpm_event module profitable have been confirmed on our hardware let’s really go for this how to set Apache’s MPM Event and PHP-FPM on FreeBSD.
Again, since I am a fan of FreeBSD Jails I will demonstrate this configuration running on a Jail. As those already familiar with this kind of OS virtualization technology know, the same configuration applies to a bare-metal, one OS instance installation, the only difference will be in creating the jail and loggin in to it. The rest remains exactly the same.
Let’s create a Jail.
[Free@Catalonia ~]$ sudo iocage create -r 11.2-RELEASE -n Event ip4_addr="em0| 192.168.1.180/24"
Password:
Event successfully created!
[Free@Catalonia~]$
Let’s now fire it up and login to it.
[Free@Catalonia ~]$ sudo iocage start Event
* Starting Event
+ Started OK
+ Using devfs_ruleset: 5
+ Starting services OK
+ Executing poststart OK
[Free@Catalonia ~]$ sudo iocage console Event
FreeBSD 11.2-RELEASE-p9 (GENERIC) #0: Tue Feb 5 15:30:36 UTC 2019
Welcome to FreeBSD!
Release Notes, Errata: https://www.FreeBSD.org/releases/
Security Advisories: https://www.FreeBSD.org/security/
FreeBSD Handbook: https://www.FreeBSD.org/handbook/
FreeBSD FAQ: https://www.FreeBSD.org/faq/
Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
FreeBSD Forums: https://forums.FreeBSD.org/
Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with: pkg install en-freebsd-doc
For other languages, replace "en" with a language code like de or fr.
Show the version of FreeBSD installed: freebsd-version ; uname -a
Please include that output and any error messages when posting questions.
Introduction to manual pages: man man
FreeBSD directory layout: man hier
Edit /etc/motd to change this login announcement.
root@Event:~ #
If you are interested on checking FreeBSD Jails out, you can read this other guide and make your own testing.
From here on, you can follow the very same steps if you are not using a Jail and you are using a single OS instance, be your server at home, a VM on your favourite cloud provider, etc.
Let’s install the first piece, the Apache HTTP server.
root@Event:~ # pkg install apache24
Updating FreeBSD repository catalogue...
pkg: Repository FreeBSD load error: access repo file(/var/db/pkg/repo-FreeBSD.sqlite) failed: No such file or directory
[Event] Fetching meta.txz: 100% 944 B 0.9kB/s 00:01
[Event] Fetching packagesite.txz: 100% 6 MiB 556.9kB/s 00:12
Processing entries: 100%
FreeBSD repository update completed. 32026 packages processed.
All repositories are up to date.
Updating database digests format: 100%
The following 12 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
apache24: 2.4.38
libnghttp2: 1.37.0
libxml2: 2.9.8
expat: 2.2.6_1
perl5: 5.28.1_1
pcre: 8.43
apr: 1.6.5.1.6.1_1
gdbm: 1.18.1
indexinfo: 0.3.1
readline: 7.0.5
gettext-runtime: 0.19.8.1_2
db5: 5.3.28_7
Number of packages to be installed: 12
The process will require 151 MiB more space.
35 MiB to be downloaded.
Proceed with this action? [y/N]: y
Some output later...
/!\ ================================================================== /!\
Message from apache24-2.4.38:
To run apache www server from startup, add apache24_enable="yes"
in your /etc/rc.conf. Extra options can be found in startup script.
Your hostname must be resolvable using at least 1 mechanism in
/etc/nsswitch.conf typically DNS or /etc/hosts or apache might
have issues starting depending on the modules you are using.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- apache24 default build changed from static MPM to modular MPM
- more modules are now enabled per default in the port
- icons and error pages moved from WWWDIR to DATADIR
If build with modular MPM and no MPM is activated in
httpd.conf, then mpm_prefork will be activated as default
MPM in etc/apache24/modules.d to keep compatibility with
existing php/perl/python modules!
Please compare the existing httpd.conf with httpd.conf.sample
and merge missing modules/instructions into httpd.conf!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
root@Event:~ #
It’s been installed but it is not running yet. To make it run at boot time we need to at one line into the /etc/rc.conf file. We can do that manually with our favourite editor or just do as shown below:
root@Event:~ # sysrc apache24_enable="YES"
apache24_enable: -> YES
root@Event:~ #
The second piece of the stack is a MySQL database. I am, as many others, fan of MariaDB, developed by the main author of the former.
root@Event:~ # pkg install mariadb103-server
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 8 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
mariadb103-server: 10.3.13
libedit: 3.1.20181209_2,1
unixODBC: 2.3.7
mariadb103-client: 10.3.13
libiconv: 1.14_11
galera: 25.3.25_1
boost-libs: 1.69.0_1
icu: 63.1_1,1
Number of packages to be installed: 8
The process will require 456 MiB more space.
54 MiB to be downloaded.
Proceed with this action? [y/N]: y
Some output later...
Message from mariadb103-server-10.3.13:
************************************************************************
Remember to run mysql_upgrade (with the optional --datadir=<dbdir> flag)
the first time you start the MySQL server after an upgrade from an
earlier version.
MariaDB respects hier(7) and doesn't check /etc and /etc/mysql for
my.cnf. Please move existing my.cnf files from those paths to
/usr/local/etc and /usr/local/etc/mysql.
This port does NOT include the mytop perl script, this is included in
the MariaDB tarball but the most recent version can be found in the
databases/mytop port
************************************************************************
root@Event:~ #
We will now add the start up capacity for MariaDB at boot time.
root@Event:~ # sysrc mysql_enable="YES"
mysql_enable: -> YES
root@Event:~ #
Now, let’s go install the third layer of the stack, the PHP language.
root@Event:~ # pkg install php73
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 3 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
php73: 7.3.3
libargon2: 20171227_1
pcre2: 10.32
Number of packages to be installed: 3
The process will require 31 MiB more space.
5 MiB to be downloaded.
Proceed with this action? [y/N]: y
Some output later...
root@Event:~ #
Since it is very possible you need some extensions on PHP for the particular application you want to run on this server we’ll also install the related package.
root@Event:~ # pkg install php73-extensions
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 20 package(s) will be affected (of 0 checked):
New packages to be INSTALLED:
php73-extensions: 1.0
php73-session: 7.3.3
php73-opcache: 7.3.3
php73-xmlwriter: 7.3.3
php73-xmlreader: 7.3.3
php73-dom: 7.3.3
php73-xml: 7.3.3
php73-simplexml: 7.3.3
php73-ctype: 7.3.3
php73-posix: 7.3.3
php73-hash: 7.3.3
php73-filter: 7.3.3
php73-tokenizer: 7.3.3
php73-json: 7.3.3
php73-sqlite3: 7.3.3
sqlite3: 3.27.1
php73-pdo_sqlite: 7.3.3
php73-pdo: 7.3.3
php73-iconv: 7.3.3
php73-phar: 7.3.3
Number of packages to be installed: 20
The process will require 8 MiB more space.
2 MiB to be downloaded.
Proceed with this action? [y/N]: y
Some output later...
root@Event:~ #
And let’s configure the whole thing to be able to work with FastCGI, the PHP-FPM (PHP-FastCGI Process Manager) part of this how to set Apache’s MPM Event and PHP-FPM on FreeBSD.
First we will set up PHP-FPM to be run at boot time.
root@Event:~ # sysrc php-fpm_enable="YES"
php_fpm_enable: fpm_enable -> fpm_enable
root@Event:~ #
Then we will edit one file to load the FastCGI module into Apache. First read the README file so you know better.
root@Event:~ # cat /usr/local/etc/apache24/modules.d/README_modules.d
# ===================================================
# Directory for third party module config files.
#
# Modules can be disabled by adding a '#' in front
# of the "LoadModule" line e.g. "#LoadModule"
#
# Files are automatically included if the name
# begins with a three digit number followed by '_'
# and ending in '.conf' e.g. '080_mod_php.conf'
#
# Maintainers can also include instructions how to
# use the module (instead pkg-message).
#
root@Event:~ #
Let’s add the file.
root@Event:~ # vi /usr/local/etc/apache24/modules.d/030_php-fpm.conf
This is what we're going to put into that file:
<IfModule proxy_fcgi_module>
<IfModule dir_module>
DirectoryIndex index.php
</IfModule>
<FilesMatch "\.(php|phtml|inc)$">
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
</IfModule>
root@Event:~ #
Now we do enable the FastCGI module in the main Apache HTTP configuration file. We look for its entry:
root@Event:~ # cat /usr/local/etc/apache24/httpd.conf | nl -ba | egrep 'fcgi'
82 #LoadModule authnz_fcgi_module libexec/apache24/mod_authnz_fcgi.so
133 #LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
root@Event:~ #
We now edit Line 133 and remove the # sign at the beginning of the line.
root@Event:~ # vi +133 /usr/local/etc/apache24/httpd.conf
Before:
#LoadModule proxy_ftp_module libexec/apache24/mod_proxy_ftp.so
#LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
#LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
#LoadModule proxy_scgi_module libexec/apache24/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module libexec/apache24/mod_proxy_uwsgi.so
After:
#LoadModule proxy_ftp_module libexec/apache24/mod_proxy_ftp.so
#LoadModule proxy_http_module libexec/apache24/mod_proxy_http.so
LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
#LoadModule proxy_scgi_module libexec/apache24/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module libexec/apache24/mod_proxy_uwsgi.so
We do also edit line 129 in order to load the proxy_module:
root@Event:~ # cat /usr/local/etc/apache24/httpd.conf | nl -ba | egrep 'proxy_module'
129 #LoadModule proxy_module libexec/apache24/mod_proxy.so
root@Event:~ #
root@Event:~ # vi +129 /usr/local/etc/apache24/httpd.conf
Before:
#LoadModule remoteip_module libexec/apache24/mod_remoteip.so
#LoadModule proxy_module libexec/apache24/mod_proxy.so
#LoadModule proxy_connect_module libexec/apache24/mod_proxy_connect.so
After:
#LoadModule remoteip_module libexec/apache24/mod_remoteip.so
LoadModule proxy_module libexec/apache24/mod_proxy.so
#LoadModule proxy_connect_module libexec/apache24/mod_proxy_connect.so
Last, but not least, after having enabled the PHP-FPM bit of this configuration, we will now swith the MPM configuration from the ‘pre-fork’ setting to the ‘event’ one.
Let’s first find out the exact location of these directives in the main Apache’s HTTP config file:
root@Event:~ # cat /usr/local/etc/apache24/httpd.conf | nl -ba | egrep 'mpm'
66 #LoadModule mpm_event_module libexec/apache24/mod_mpm_event.so
67 LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so
68 #LoadModule mpm_worker_module libexec/apache24/mod_mpm_worker.so
164 <IfModule !mpm_prefork_module>
167 <IfModule mpm_prefork_module>
490 #Include etc/apache24/extra/httpd-mpm.conf
root@Event:~ #
As we can see in line 67 we find the mpm_prefork activated. We want to change this to event.
root@Event:~ # vi +66 /usr/local/etc/apache24/httpd.conf
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
#LoadModule mpm_event_module libexec/apache24/mod_mpm_event.so
LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so
#LoadModule mpm_worker_module libexec/apache24/mod_mpm_worker.so
LoadModule authn_file_module libexec/apache24/mod_authn_file.so
#LoadModule authn_dbm_module libexec/apache24/mod_authn_dbm.so
Result should be like:
LoadModule mpm_event_module libexec/apache24/mod_mpm_event.so
#LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so
#LoadModule mpm_worker_module libexec/apache24/mod_mpm_worker.so
Let’s test our configuration before firing things up.
root@Event:~ # apachectl configtest
Performing sanity check on apache24 configuration:
Syntax OK
root@Event:~ #
It is possible you see some ‘silly’ error showing up like:
root@Event:~ # apachectl configtest
Performing sanity check on apache24 configuration:
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 192.168.1.180. Set the 'ServerName' directive globally to suppress this message
Syntax OK
root@Event:~ #
As you can read the syntax is ok and Apache will start up correctly. If you want to get rid of this ‘silly’ error just do as follows:
Look for the ‘SeverName’ directive in the main configuration file.
root@Event:~ # cat /usr/local/etc/apache24/httpd.conf | nl -ba | egrep 'ServerName'
219 # ServerName gives the name and port that the server uses to identify itself.
225 #ServerName www.example.com:80
root@Event:~ # vi +225 /usr/local/etc/apache24/httpd.conf
Edit the file so it doesn’t bother again because it is correctly configured. Just replace the www.example.com with the website name or the IP you’re serving the content from.
root@Event:~ # vi +225 /usr/local/etc/apache24/httpd.conf
219 # ServerName gives the name and port that the server uses to identify itself.
225 ServerName 192.168.1.180:80
root@Event:~ #
It’s time to fire up things. First we’ll start Apache, then MariaDB and last but not least PHP-FPM.
root@Event:~ # service apache24 start
Performing sanity check on apache24 configuration:
Syntax OK
Starting apache24.
root@Event:~ #
root@Event:~ # service mysql-server start
Starting mysql.
root@Event:~ #
root@Event:~ # service php-fpm start
Performing sanity check on php-fpm configuration:
[24-Mar-2019 19:05:38] NOTICE: configuration file /usr/local/etc/php-fpm.conf test is successful
Starting php_fpm.
root@Event:~ #
No error messages should appear. Read carefully if any appear. Now, since everything is ok, let’s look if Apache is really running with the mpm_event module enabled.
root@Event:~ # apachectl -M | grep event
mpm_event_module (shared)
root@Event:~ #
And yes it is.
To now check if PHP is really running on PHP-FPM we will make a little test with a very small PHP script.
We’ll add a file called ‘info.php’ in the Apache’s content path, where ‘<?php phpinfo(); ?>’ is the content of the file.
root@Event:~ # vi /usr/local/www/apache24/data/info.php
<?php phpinfo(); ?>
root@Event:~ #
We’ll now visit our website through a web browser.
By visiting http://192.168.1.180/info.php I get this result, where the important line to read is ‘Server API’.
As you can see PHP with FPM capability is now enabled, along with the MPM Event this concludes this How to set Apache’s MPM Event and PHP-FPM on FreeBSD.
Now, if you are doing this over the internet, I recommend you first enable SSL/TLS on your Apache, and then do this configuration here.
If you find the articles in Adminbyaccident.com useful to you, please consider making a donation.
Use this link to get $200 credit at DigitalOcean and support Adminbyaccident.com costs.
Get $100 credit for free at Vultr using this link and support Adminbyaccident.com costs.
Mind Vultr supports FreeBSD on their VPS offer.