At the time of writing, there aren’t that many resources online on how to install and use mod_macro
in Gentoo Linux. There are some posts about mod_macro
for Ubuntu, meaning it isn’t the most known feature of Apache 2.4.
This module allows the systems administrator to define a macro, that can be used many times over to define parameters such as complete virtual hosts.
I discovered mod_macro
when doing research on how to implement many SSL and non-SSL virtual hosts with the same Apache server.
mod_macro
became a part of Apache from version 2.4.5.
If you are getting this blocker, the solution is pretty simple. One does not emerge mod_macro, it has to be configured as a module when building Apache.
[ebuild N ~] www-apache/mod_macro-1.2.1::gentoo 17 KiB
[blocks B ] www-apache/mod_macro ("www-apache/mod_macro" is blocking www-servers/apache-2.4.39)
Total: 1 package (1 new), Size of downloads: 17 KiB
Conflict: 1 block (1 unsatisfied)
* Error: The above package list contains packages which cannot be
* installed at the same time on the same system.
The ebuild for Apache 2.4, uses an environment variable called APACHE2_MODULES
to configure what modules to build with Apache.
To add modules, edit /etc/make.conf
and if APACHE2_MODULES
is already there, add the following line just below.
APACHE2_MODULES="${APACHE2_MODULES} macro"
If APACHE2_MODULES
is not present, add this line.
APACHE2_MODULES="macro"
Emerge Apache with emerge
.
emerge -av apache
Wait some minutes.
-D MACRO
Open /etc/conf.d/apache2
, and add -D MACRO
to APACHE2_OPTS
.
Reload Apache.
/etc/init.d/apache2 restart
This is the macros I’ve implmented with mod_macro
, for SSL and non-SSL virtual hosts.
Using recommended ciphers from.
<Macro SSLHost $host $email $documentroot $userid>
<VirtualHost *:443>
ServerName $host
ServerAlias www.$host
ServerAdmin $email
DocumentRoot "$documentroot"
CustomLog /var/log/apache2/$host-ssl_access_log combined
ErrorLog /var/log/apache2/$host-ssl_error_log
<IfModule log_config_module>
TransferLog /var/log/apache2/$host-ssl_xfer_log
</IfModule>
SSLEngine on
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
# Disable TLS compression
SSLCompression off
# Necessary for Perfect Forward Secrecy (PFS)
SSLSessionTickets off
SSLHonorCipherOrder On
SSLCertificateFile /etc/letsencrypt/live/$host/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/$host/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/$host/fullchain.pem
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "$documentroot">
AllowOverride All
Require all granted
</Directory>
<IfModule mpm_itk_module>
AssignUserId $userid $userid
</IfModule>
</VirtualHost>
</Macro>
<Macro VHost $host $email $documentroot $userid>
<VirtualHost *:80>
ServerName $host
ServerAlias www.$host
ServerAdmin $email
DocumentRoot "$documentroot"
CustomLog /var/log/apache2/$host-access_log combined
ErrorLog /var/log/apache2/$host-error_log
<Directory "$documentroot">
AllowOverride All
Require all granted
</Directory>
<IfModule mpm_itk_module>
AssignUserId $userid $userid
</IfModule>
</VirtualHost>
</Macro>
Usage.
Include "/etc/apache2/vhosts.d/sslconfig.include"
Use VHost example.com joe@example.com "/var/www/example.com/htdocs" examplecom
Use SSLHost example.com joe@example.com "/var/www/example.com/htdocs" examplecom
Use VHost other.example.com other@example.com "/var/www/other.example.com/htdocs" otherexamplecom
Use SSLHost other.example.com other@example.com "/var/www/other.example.com/htdocs" otherexamplecom
The macro will replicate with the parameters used, making sure the virtual hosts have identical definitions.
In my experience, there are no difference between using quotation mark or not. The only time it’s required is when using special characters or the variable have spaces, say, a folder path.
There are multiple tools for getting and maintaining certificates, but I’m using Gentoo Linux, and certbot
is one of those tools.
Emerge certbot with emerge -av certbot
.
Create a script, which will call certbot for each site your are hosting:
certbot certonly -n -d example.com --webroot --webroot-path /var/www/letsencrypt -m joe@example.com --agree-tos
certbot certonly -n -d other.example.com --webroot --webroot-path /var/www/letsencrypt -m joe@example.com --agree-tos
Set it to run weekly with crontab.
crontab -e
Add the following to crontab.
0 0 * * 6 /root/update_certs.sh
This script will run every saturday at 00:00. If you add a post-action hook, it’s possible to automatically restart Apache if there are any changes.
One of the problems with Apache and SSL certificates, is that it isn’t possible to start a virtual host without an existing certificate. There are two solutions to this problem, start the vhost with a dummy certificate, or use the default site to catch all certificate requests.
To get the second option to work, a global alias must be declared before any other virtual hosts in the Apache configuration.
Add this before any virtual hosts are loaded.
Alias /.well-known/acme-challenge/ /var/www/letsencrypt/.well-known/acme-challenge/
#Bypass Auth
<Directory /var/www/letsencrypt/.well-known/acme-challenge/>
Require all granted
</Directory>
#Redirect before other rewrite rules
RewriteCond %{REQUEST_URI} /\.well\-known/acme\-challenge/
RewriteRule (.*) /.well-known/acme-challenge/$1 [L,QSA]
If the /var/www/letsencrypt/
directory does not exist, create it
mkdir -p /var/www/letsencrypt/
The next post will be about mod_md
. It implemets the ACME protocal Let’s Encrypt uses in Apache itself. In theory, it will request new certificates for new hosts, and renew certificates when it’s time to renew.