1. Introduction
The Apache HTTP Server (Apache) is ubiquitous among Web servers for many reasons:
- stable
- open-source
- cross-platform
- extensible
On the last point, Apache comes with multiple modules, supports even more, and provides a way to build and install new ones. Perhaps the best way to do so is the APache eXtenSion tool (apxs).
In this tutorial, we explore apxs and how to install it on different Linux distributions. First, we briefly refresh our knowledge about Apache modules. After that, we go over the standard tool to build and install such modules: apxs.
While Debian-based distributions use apache2, a special structure, and scripts, the server binary in RPM-based versions is called httpd and only employs regular configuration files.
We tested the code in this tutorial on Debian 12 (Bookworm) and Rocky 9 (Blue Onyx) with Apache 2.4. Unless otherwise specified, it should work in most POSIX-compliant environments.
2. Apache Modules
Apache modules are at the core of the Apache HTTP Server. In fact, the core module provides the main features.
Indeed, this encapsulation of even the most basic functionality shows how Apache was implemented as an extensible product from the ground up.
2.1. Example Modules and Naming
On top of the primitive functions, there are many modules for more complex features. Let’s see some examples:
- ssl_module: SSL and TLS support
- auth*_module: different authentication modules
- dir_module: trailing slash redirections and directory indices
- so_module: load executable code and modules dynamically
Usually, the names of module files start with mod_, while the module name ends with _module.
2.2. Hardcoded Functionality
To begin with, we can see how Apache was compiled via the -l flag.
Let’s check that in Debian:
$ apache2 -l
Compiled in modules:
core.c
mod_so.c
mod_watchdog.c
http_core.c
mod_log_config.c
mod_logio.c
mod_version.c
mod_unixd.c
RPM-based distributions often have versions with fewer hardcoded modules:
$ httpd -l
Compiled in modules:
core.c
mod_so.c
http_core.c
Still, the core, http_core, and mod_so parts are common. Notably, without the mod_so component, we wouldn’t be able to extend the installation with the use of modules.
2.3. List Enabled Modules
Let’s employ apache2ctl to check the [-M]odules available in a basic installation on most Debian-based distributions:
$ apache2ctl -M
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
unixd_module (static)
access_compat_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_core_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
filter_module (shared)
mime_module (shared)
mpm_event_module (shared)
negotiation_module (shared)
reqtimeout_module (shared)
setenvif_module (shared)
socache_shmcb_module (shared)
ssl_module (shared)
status_module (shared)
On the other hand, we can use the same flag with the httpd tool on RPM-based distributions:
$ httpd -M
Loaded Modules:
core_module (static)
so_module (static)
http_module (static)
access_compat_module (shared)
actions_module (shared)
alias_module (shared)
allowmethods_module (shared)
auth_basic_module (shared)
auth_digest_module (shared)
authn_anon_module (shared)
authn_core_module (shared)
authn_dbd_module (shared)
authn_dbm_module (shared)
authn_file_module (shared)
authn_socache_module (shared)
authz_core_module (shared)
authz_dbd_module (shared)
authz_dbm_module (shared)
authz_groupfile_module (shared)
[...]
cgid_module (shared)
http2_module (shared)
proxy_http2_module (shared)
Some modules are static, meaning they are integrated deep within the binaries, while others are shared, so we can disable and remove them at will. Regardless, each module ends with the _module suffix.
Notably, what we see above are only the enabled modules.
2.4. Check Available Modules
In Debian-based systems, we can usually see the available modules under /etc/apache2/mods-available/:
$ ls /etc/apache2/mods-available/
access_compat.load cgi.load log_debug.load ratelimit.load
actions.conf charset_lite.load log_forensic.load reflector.load
actions.load data.load lua.load remoteip.load
alias.conf dav_fs.conf macro.load reqtimeout.conf
alias.load dav_fs.load md.load reqtimeout.load
allowmethods.load dav.load mime.conf request.load
asis.load dav_lock.load mime.load rewrite.load
auth_basic.load dbd.load mime_magic.conf sed.load
auth_digest.load deflate.conf mime_magic.load session_cookie.load
auth_form.load deflate.load mpm_event.conf session_crypto.load
authn_anon.load dialup.load mpm_event.load session_dbd.load
authn_core.load dir.conf mpm_prefork.conf session.load
authn_dbd.load dir.load mpm_prefork.load setenvif.conf
[...]
However, their .so* files are in */usr/lib/apache2/modules/:
$ ls /usr/lib/apache2/modules/
httpd.exp mod_cache_socache.so mod_lbmethod_bybusyness.so mod_proxy_wstunnel.so
mod_access_compat.so mod_case_filter_in.so mod_lbmethod_byrequests.so mod_ratelimit.so
mod_actions.so mod_case_filter.so mod_lbmethod_bytraffic.so mod_reflector.so
mod_alias.so mod_cern_meta.so mod_lbmethod_heartbeat.so mod_remoteip.so
mod_allowmethods.so mod_cgid.so mod_ldap.so mod_reqtimeout.so
mod_asis.so mod_cgi.so mod_log_debug.so mod_request.so
mod_auth_basic.so mod_charset_lite.so mod_log_forensic.so mod_rewrite.so
mod_auth_digest.so mod_data.so mod_lua.so mod_sed.so
mod_auth_form.so mod_dav_fs.so mod_macro.so mod_session_cookie.so
[...]
Meanwhile, RPM-based systems usually store the .so files under /usr/lib64/httpd/modules/ with symbolic links at /etc/httpd/modules/:
$ ls /usr/lib64/httpd/modules/
mod_access_compat.so mod_cgi.so mod_log_config.so mod_reflector.so
mod_actions.so mod_cgid.so mod_log_debug.so mod_remoteip.so
mod_alias.so mod_charset_lite.so mod_log_forensic.so mod_reqtimeout.so
mod_allowmethods.so mod_data.so mod_logio.so mod_request.so
mod_asis.so mod_dav.so mod_lua.so mod_rewrite.so
mod_auth_basic.so mod_dav_fs.so mod_macro.so mod_sed.so
mod_auth_digest.so mod_dav_lock.so mod_mime.so mod_setenvif.so
mod_authn_anon.so mod_dbd.so mod_mime_magic.so mod_slotmem_plain.so
mod_authn_core.so mod_deflate.so mod_mpm_event.so mod_slotmem_shm.so
[...]
Notably, the .so files are usually considerably more than the enabled modules.
2.5. Toggle Modules
Debian-based systems use a special hierarchy for configuration:
$ ls /etc/apache2/
apache2.conf conf-available envvars mods-available ports.conf sites-enabled
apache2.conf.dpkg-dist conf-enabled magic mods-enabled sites-available
The a2* commands control symbolic links under the conf-*, mods-*, and sites-* directories above:
$ a2[Tab]
a2disconf a2dismod a2dissite a2enconf a2enmod a2ensite a2query a2x
In particular, a2enmod* and a2dismod create and remove symbolic links in mods-enabled that point to *mods-available.
On the other hand, RPM-based distributions work directly with the httpd.conf configuration file to load and unload modules:
$ cat /etc/httpd/conf/httpd.conf
[...]
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
Include conf.modules.d/*.conf
[...]
Further, we can place .conf files that contain LoadModule statements in /etc/httpd/conf.modules.d/.
After any configuration changes, we restart the service via a manager like systemctl or manually.
3. APache eXtenSion (apxs)
The apxs Apache eXtenSion tool is the standard way to build and install modules for Apache.
3.1. Install
To install the apxs utility, we use the httpd-devel package in RPM-based distributions and apache2-dev for Debian-based ones.
First, let’s perform the installation on Debian:
$ apt install apache2-dev
On the Linux RPM side, we employ dnf or yum:
$ dnf install httpd-devel
Sometimes, RPM-based distributions may require special repository configurations such as Extra Packages for Enterprise Linux (EPEL), also called Extras.
To verify whether we have it configured, we can use the repolist subcommand:
$ dnf repolist
repo id repo name
appstream Rocky Linux 9 - AppStream
baseos Rocky Linux 9 - BaseOS
extras Rocky Linux 9 - Extras
If not available, to install EPEL, we use online sources:
$ dnf config-manager --set-enabled crb
$ dnf install \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm \
https://dl.fedoraproject.org/pub/epel/epel-next-release-latest-9.noarch.rpm
Thus, we should be able to install httpd-devel.
Notably, some RPM distributions like Rocky don’t require configuration on top of the default to do that.
3.2. Basic Usage
To use apxs, we run it with a set of options and a module base or source file:
$ apxs -i -a -c mod_<MODNAME>.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_<MODNAME>.c
ld -Bshareable -o mod_<MODNAME>.so mod_<MODNAME>.o
cp mod_<MODNAME>.so /path/to/apache/modules/mod_<MODNAME>.so
chmod 755 /path/to/apache/modules/mod_<MODNAME>.so
[activating module `<MODNAME>' in /path/to/apache/etc/httpd.conf]
Let’s break this common option set down:
- -c: compile supplied .c source file
- -i: install module after a successful build
- -a: activate module after installation
Alternatively, we can use -o to directly specify any module object file to work with. Usually, apxs recognizes the .c, .o, and .a extensions, so it can act on them accordingly.
Further, we can already see that build tools are required for the -c option. A further consideration is that gcc* always uses *-fpic, so we should ensure any compiled objects use position independent code (PIC)
Once we have the resulting file, we can use it like any other module.
4. Summary
In this article, we talked about the Apache HTTP Server modules and the standard tool to compile and install them.
In conclusion, Apache is a versatile Web server built to be extensible from the ground up.