I needed a way to manage Apache VirtualHosts and mod_rewrite rules. There are a handful of Ansible Roles available at Ansible Galaxy to manage Apache VirtualHosts, but none of them also manage mod_rewrite rules.
After figuring out how to include additional content in an Ansible Template file, I was able to quickly put together an Ansible Playbook and Ansible Template to manage my Apache VirtualHosts and their particular mod_rewrite rules.
Ansible Directory
My Ansible environment exists within directory ~/Development/ansible-lab/ on my workstation. Any files or directories created in this post will be created within this directory.
Ansible Inventory File
In my particular case, all of my websites run on two web servers with a load balancer in front of them, so I created file ~/Development/ansible-lab/hosts with the following contents:
[web-servers]
webserver1.example.com
webserver2.example.com
Ansible Files
The mod_rewrite rules are simple text files stored in directory ~/Development/ansible-lab/files/apache/mod_rewrite/. The files are named vhost1.example.com.conf, vhost2.example.com.conf (after the actual FQDN of the website) and each contains the following contents (these are just examples, the actual text files contain many more mod_rewrite rules):
vhost1.example.com.conf
RewriteEngine On
RewriteRule /documentation/2013/01/03/example-post1.html http://vhost1.example.com/2013/01/03/example-post1.html [R=permanent,L]
RewriteRule /documentation/2013/03/05/example-post2.html http://vhost1.example.com/2013/03/05/example-post2.html [R=permanent,L]
vhost2.example.com.conf
RewriteEngine On
RewriteRule /documentation/2014/02/10/example-post3.html http://vhost2.example.com/2014/02/10/example-post3.html [R=permanent,L]
RewriteRule /documentation/2014/05/20/example-post4.html http://vhost2.example.com/2014/05/20/example-post4.html [R=permanent,L]
vhost3.example.com.conf
In this example, the vhost3.example.com Apache VirtualHost never had any mod_rewrite rules, so file vhost3.example.com.conf will not exist in the ~/Development/ansible-lab/files/apache/mod_rewrite/ directory.
Ansible Template
I created Ansible Template ~/Development/ansible-lab/templates/apache_vhost.conf.j2 with the following contents:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName {{ item.servername }}
DocumentRoot /var/www/html/{{ item.documentrootdir }}
ServerAdmin {{ item.serveradmin }}
ErrorLog logs/{{ item.errorlog }}-error_log
CustomLog logs/{{ item.customlog }}-access_log common
<Directory /var/www/html/{{ item.documentrootdir }}>
Options None
</Directory>
{% include "files/apache/mod_rewrite/" + item.documentrootdir + ".conf" ignore missing %}
</VirtualHost>
When Ansible is generating the Apache VirtualHost file for vhost1.example.com.conf, the include line (which is Jinja2 syntax) would check if there is a file named vhost1.example.com.conf in the ~/Development/ansible-lab/files/apache/mod_rewrite/ directory. If the file exists, its contents would be included in the generated Apache VirtualHost file, or, if the file does not exist, the Apache VirtualHost file would be generated without any additional content (the ignore missing parameters on the include line enables this).
Take note, the Ansible Playbook was originally stored in directory ~/Development/ansible-lab/playbooks/. But, for all of this to work, it had to be moved to ~/Development/ansible-lab/. There appears to be a path problem with Ansible Templates if the Ansible Playbook is in a directory other than the root Ansible directory. Supposedly this was fixed, but I have not investigated the issue further.
Ansible Playbook
The Ansible Playbook is the last piece to put together. Below are the contents of that playbook.
In this particular example, the Apache VirtualHost parameters are stored within the Ansible Playbook. As the number of Apache VirtualHosts increases, it would be better to move them out of the Ansible Playbook into their own variable file and reference that file within the Ansible Playbook as shown in the Example Playbook section in geerlingguy’s Ansible Apache Role.
Take note that the following Ansible Playbook is written to manage Apache on RHEL/CentOS. Some of the file paths and service names will need to be changed to make it work on Debian/Ubuntu.
---
- hosts: web-servers
vars:
apache_vhosts_enabled:
- servername: "vhost1.example.com"
serveradmin: "admin@example.com"
documentrootdir: "vhost1.example.com"
errorlog: "vhost1.example.com"
customlog: "vhost1.example.com"
- servername: "vhost2.example.com"
serveradmin: "admin@example.com"
documentrootdir: "vhost2.example.com"
errorlog: "vhost2.example.com"
customlog: "vhost2.example.com"
apache_vhosts_disabled:
- servername: "vhost3.example.com"
serveradmin: "admin@example.com"
documentrootdir: "vhost3.example.com"
errorlog: "vhost3.example.com"
customlog: "vhost3.example.com"
tasks:
- name: Install Apache
yum:
pkg={{ item }}
state=present
with_items:
- httpd
- name: Ensure httpd is running
service:
name=httpd
state=started
- name: Ensure httpd is enabled
service:
name=httpd
enabled=yes
- name: Create sites.d directory
file:
path=/etc/httpd/conf.d/sites.d
state=directory
owner=root
group=root
mode=0755
- name: Add sites.d Include to httpd.conf
lineinfile:
dest=/etc/httpd/conf/httpd.conf
state=present
line='Include conf.d/sites.d/*.conf'
notify:
- restart httpd
- name: Create a VirtualHost file for each enabled VirtualHost
template:
src=templates/apache_vhost.conf.j2
dest=/etc/httpd/conf.d/sites.d/{{ item.documentrootdir }}.conf
owner=root
group=root
mode=0644
with_items: apache_vhosts_enabled
notify:
- restart httpd
- name: Create web directories for each enabled VirtualHost
file:
path=/var/www/html/{{ item.documentrootdir }}
state=directory
owner=apache
group=apache
mode=0755
with_items: apache_vhosts_enabled
- name: Remove VirtualHost file for each disabled VirtualHost
file:
path=/etc/httpd/conf.d/sites.d/{{ item.documentrootdir }}.conf
state=absent
with_items: apache_vhosts_disabled
notify:
- restart httpd
- name: Remove web directories for each disabled VirtualHost
file:
path=/var/www/html/{{ item.documentrootdir }}
state=absent
with_items: apache_vhosts_disabled
handlers:
- name: restart httpd
service:
name=httpd
state=restarted
As Apache VirtualHosts are enabled or disabled or more mod_rewrite rules are needed, modify the Ansible Playbook and, if necessary, the mod_rewrite text files and re-run the playbook to apply all of the changes.