I recently setup new server, for experimenting with new technical stacks. I have been planning to use it for comparisons and benchmarks.
So, as a beginner, I decided to have my http server support HTTP/2.
My server has “Centos 7” installed, which has httpd version 2.4
on yum repo. Initially I thought I would just switch on a single module and it will be all over. But it turns out that, latest http server version provided by yum is 2.4.6
, which didn’t have support for http2 module yet.So I decided to build it manually.
First of all, http2 spec does not require https.
But all major browsers require https in order to use HTTP/2. And to support HTTP over TLS,
Apache HTTP server requires mod_ssl
, which needs openssl development libraries when built from source.
HTTP/2 needs certain TLS extension called ALPN, which is provided for
OpenSSL 1.0.2+ versions.
First switch to root user.
sudo su -
bash
yum -y groupinstall "Development Tools"
yum install libnghttp2-devel pcre-devel zlib-devel wget -y
mkdir -p /usr/local/src && cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.0.2-latest.tar.gz
tar -zxf openssl-1.0.2-latest.tar.gz
cd openssl-1.0.2j
./config shared --prefix=/usr/local --openssldir=/usr/local/openssl
make
make test
make install
When installation is complete, confirm new version with command below.
/usr/local/bin/openssl version
APR and APR-Util is required for compiling http server from source.
cd /usr/local/src
wget http://www-eu.apache.org/dist/httpd/httpd-2.4.23.tar.gz
wget http://www-eu.apache.org/dist//apr/apr-1.5.2.tar.gz
wget http://www-eu.apache.org/dist//apr/apr-util-1.5.4.tar.gz
tar -xzf httpd-2.4.23.tar.gz
Copy APR and APR-Util source code into library source directory of httpd source.
cd /usr/local/src/httpd-2.4.23/srclib
cp /usr/local/src/apr-1.5.2.tar.gz . && tar -xzf apr-1.5.2.tar.gz && mv apr-1.5.2 apr
cp /usr/local/src/apr-util-1.5.4.tar.gz . && tar -xzf apr-util-1.5.4.tar.gz && mv apr-util-1.5.4 apr-util
Build httpd
APACHE_DIR=/usr/local/apache
cd /usr/local/src/httpd-2.4.23
./configure \
--prefix=${APACHE_DIR} \
--with-included-apr \
--enable-mpms-shared=all \
--enable-mods-shared=all \
--enable-static-ab \
--enable-static-checkgid \
--enable-static-htdbm \
--enable-static-htdigest \
--enable-static-logresolve \
--enable-static-rotatelogs \
--enable-http2 \
--with-ssl=/usr/local/
make
make install
# add extra library path (mainly openssl), to apache environment variables
echo "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/lib64" \
>> ${APACHE_DIR}/bin/envvars
If some modules are missing from modules
directory, or if you want to build extra manually, you compile them
using apxs
command. For example,
$APACHE_DIR/bin/apxs -i -c ./modules/generators/mod_cgi.c
$APACHE_DIR/bin/apxs -i -c ./modules/filters/mod_deflate.c
For this part you can choose how to configure your Apache server. But for quick guidance, you use commands below.
mv ${APACHE_DIR}/conf/{extra,conf.d}
mkdir ${APACHE_DIR}/conf/conf.d/OLD
mv ${APACHE_DIR}/conf/conf.d/{*.conf,OLD/}
mv ${APACHE_DIR}/conf/httpd.conf{,.OLD}
cp ${APACHE_DIR}/conf/conf.d{/OLD/httpd-default.conf,}
Create a configuration file at ${APACHE_DIR}/conf/modules.conf
for managing loaded modules.
vi ${APACHE_DIR}/conf/modules.conf
And insert following
LoadModule alias_module modules/mod_alias.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule dir_module modules/mod_dir.so
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule status_module modules/mod_status.so
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
# (optional) for centos systemctl (or change httpd.service file manually)
# LoadModule systemd_module modules/mod_systemd.so
# for caching at SSL
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
# SSL
LoadModule ssl_module modules/mod_ssl.so
# HTTP 2.0 Support
LoadModule http2_module modules/mod_http2.so
<IfModule mpm_worker_module>
LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_event_module>
LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
LoadModule cgi_module modules/mod_cgi.so
</IfModule>
Next, for optimizing apache with used MPM, you need to define configuration for each type of MPM.
vi ${APACHE_DIR}/conf/conf.d/optimize.conf
Insert following
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 200
MaxConnectionsPerChild 4500
</IfModule>
<IfModule mpm_worker_module>
ServerLimit 16
StartServers 3
MaxRequestWorkers 200
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxConnectionsPerChild 4500
</IfModule>
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 30
MaxConnectionsPerChild 4500
</IfModule>
And for ssl and http2 modules,
vi ${APACHE_DIR}/conf/conf.d/ssl.conf
Insert
Listen 443
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLProxyCipherSuite HIGH:MEDIUM:!MD5:!RC4
SSLHonorCipherOrder on
SSLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3
SSLPassPhraseDialog builtin
SSLSessionCache "shmcb:/usr/local/apache/logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300
vi ${APACHE_DIR}/conf/conf.d/http2.conf
Protocols h2 h2c http/1.1
Now open main configuration file and insert following
ServerRoot "/usr/local/apache"
Listen 80
Include conf/modules.conf
User apache2
Group apache
ServerName localhost.localdomain
ServerAdmin master@localhost
<Directory />
AllowOverride none
Require all denied
</Directory>
DocumentRoot "/usr/local/apache/htdocs"
<Directory "/usr/local/apache/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
DirectoryIndex index.html
<Files ".ht*">
Require all denied
</Files>
ErrorLog "logs/error_log"
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog "logs/access_log" common
### DON'T ENABLE /CGI-BIN/ EXECUTION UNLESS YOU NEED IT, AND IT IS SECURE
#ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"
#
#<Directory "/usr/local/apache/cgi-bin">
# AllowOverride None
# Options None
# Require all granted
#</Directory>
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
Include conf/conf.d/*.conf
Header unset Server
ServerSignature Off
ServerTokens Min
<Location /server-status>
SetHandler server-status
# Require host .example.com
Require ip 127
</Location>
<Location /server-info>
SetHandler server-info
# Require host .example.com
Require ip 127
</Location>
Now your configuration is all done and http server is rady to run. But before running as server we need to add a unix user and group for apache.
groupadd apache
useradd -d ${APACHE_DIR}/htdocs -M -g apache -s /bin/false apache2
And if firewall service is running, we need to allow http and https services
(registered as port 80,443 at /etc/services
) to go through for incoming connections.
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --reload
Finally, we are ready. We can start the server with
${APACHE_DIR}/bin/apachectl start
And confirm that server is running
ps axu | grep httpd