Ansible from scratch¶
1 - ansible command and configuration¶
Create ansible directory.
> mkdir ~/guisam_ansible_tuto && \
cd ~/guisam_ansible_tuto
Create ansible configuration file, ansible.cfg
.
> cp /etc/ansible/ansible.cfg .
> grep -v "^#.*\|^$\|^\[" ansible.cfg
inventory = ./hosts
remote_user = root
Create inventory file, hosts
.
echo -e "duncan.guisam.xyz\nmalone.guisam.xyz\n" > hosts
Use ping
module to test connections.
> ansible -m ping duncan.guisam.xyz
[WARNING]: Platform linux on host duncan.guisam.xyz is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
duncan.guisam.xyz | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Update ansible.cfg
.
> grep -v "^#.*\|^$\|^\[" ansible.cfg
interpreter_python = auto_silent
inventory = ./hosts
remote_user = root
Use ping
module.
> ansible -m ping duncan.guisam.xyz
duncan.guisam.xyz | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
> ansible -m ping all
malone.guisam.xyz | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
duncan.guisam.xyz | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
Use setup
module to get facts.
> ansible -m setup duncan.guisam.xyz
duncan.guisam.xyz | SUCCESS => {
"ansible_facts": {
[...]
> ansible -m setup all -a "filter=ansible_distribution*"
duncan.guisam.xyz | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "Debian",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/os-release",
"ansible_distribution_file_variety": "Debian",
"ansible_distribution_major_version": "10",
"ansible_distribution_release": "buster",
"ansible_distribution_version": "10",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
malone.guisam.xyz | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "Debian",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/os-release",
"ansible_distribution_file_variety": "Debian",
"ansible_distribution_major_version": "10",
"ansible_distribution_release": "buster",
"ansible_distribution_version": "10",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
Use shell
module to execute commands.
> ansible -m shell all -a "apt update"
malone.guisam.xyz | CHANGED | rc=0 >>
Atteint :1 http://security.debian.org/debian-security buster/updates InRelease
Atteint :2 http://deb.debian.org/debian buster InRelease
Atteint :3 http://deb.debian.org/debian buster-updates InRelease
Atteint :4 http://deb.debian.org/debian buster-backports InRelease
Lecture des listes de paquets…
Construction de l'arbre des dépendances…
Lecture des informations d'état…
Tous les paquets sont à jour.
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
duncan.guisam.xyz | CHANGED | rc=0 >>
Atteint :1 http://security.debian.org/debian-security buster/updates InRelease
Atteint :2 http://deb.debian.org/debian buster InRelease
Atteint :3 http://deb.debian.org/debian buster-updates InRelease
Atteint :4 http://deb.debian.org/debian buster-backports InRelease
Lecture des listes de paquets…
Construction de l'arbre des dépendances…
Lecture des informations d'état…
Tous les paquets sont à jour.
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
2 - variables¶
Create variables directories, host_vars
and group_vars
.
> mkdir {host,group}_vars
Create common variables, group_vars/all.yml
.
---
common_pkgs:
- iftop
- tcpdump
- tree
- vim
...
Create host variables, host_vars/duncan.guisam.xyz.yml
.
---
hostname: duncan.guisam.xyz
...
Create host variables, host_vars/malone.guisam.xyz.yml
.
---
hostname: malone.guisam.xyz
...
Working directory in tree-like format.
guisam_ansible_tuto
../guisam_ansible_tuto
├── ansible.cfg
├── group_vars
│ └── all.yml
├── hosts
└── host_vars
├── duncan.guisam.xyz.yml
└── malone.guisam.xyz.yml
3 - playbooks¶
Create playbooks
directory.
> mkdir playbooks
Create a playbook, playbooks/common.yml
.
---
- name: common tasks
hosts: all
gather_facts: false
tasks:
- name: set hostname
hostname:
name: "{{ hostname }}"
- name: install common pkgs
apt:
pkg: "{{ common_pkgs }}"
...
Usage¶
ansible-playbook
command options.
> awk '/^\s{2}-[DC]/' <(ansible-playbook --help)
-C, --check don't make any changes; instead, try to predict some
-D, --diff when changing (small) files and templates, show the
Execute playbook in check mode.
> ansible-playbook playbooks/common.yml -D -C
PLAY [common tasks] **********************************************************************************************
TASK [set hostname] **********************************************************************************************
--- before
+++ after
@@ -1 +1 @@
-hostname = malone
+hostname = malone.guisam.xyz
changed: [malone.guisam.xyz]
--- before
+++ after
@@ -1 +1 @@
-hostname = duncan
+hostname = duncan.guisam.xyz
changed: [duncan.guisam.xyz]
TASK [install common pkgs] ***************************************************************************************
The following additional packages will be installed:
libpcap0.8
The following NEW packages will be installed:
iftop libpcap0.8 tcpdump tree
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
changed: [duncan.guisam.xyz]
The following additional packages will be installed:
libpcap0.8
The following NEW packages will be installed:
iftop libpcap0.8 tcpdump tree
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
changed: [malone.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
malone.guisam.xyz : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Execute playbook.
> ansible-playbook playbooks/common.yml -D
PLAY [common tasks] **********************************************************************************************
TASK [set hostname] **********************************************************************************************
--- before
+++ after
@@ -1 +1 @@
-hostname = duncan
+hostname = duncan.guisam.xyz
changed: [duncan.guisam.xyz]
--- before
+++ after
@@ -1 +1 @@
-hostname = malone
+hostname = malone.guisam.xyz
changed: [malone.guisam.xyz]
TASK [install common pkgs] ***************************************************************************************
The following additional packages will be installed:
libpcap0.8
The following NEW packages will be installed:
iftop libpcap0.8 tcpdump tree
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
changed: [duncan.guisam.xyz]
The following additional packages will be installed:
libpcap0.8
The following NEW packages will be installed:
iftop libpcap0.8 tcpdump tree
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
changed: [malone.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
malone.guisam.xyz : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
> ansible-playbook playbooks/common.yml -D
PLAY [common tasks] **********************************************************************************************
TASK [set hostname] **********************************************************************************************
ok: [duncan.guisam.xyz]
ok: [malone.guisam.xyz]
TASK [install common pkgs] ***************************************************************************************
ok: [duncan.guisam.xyz]
ok: [malone.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
malone.guisam.xyz : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Working directory in tree-like format.
guisam_ansible_tuto
├── ansible.cfg
├── group_vars
│ └── all.yml
├── hosts
├── host_vars
│ ├── duncan.guisam.xyz.yml
│ └── malone.guisam.xyz.yml
└── playbooks
└── common.yml
4 - roles¶
Update ansible.cfg
.
-#roles_path = /etc/ansible/roles
+roles_path = ./roles:/etc/ansible/roles
Create roles
directory.
> mkdir -p roles/common/tasks
Create roles/common/tasks/main.yml
.
---
- name: set hostname
hostname:
name: "{{ hostname }}"
- name: install common pkgs
apt:
pkg: "{{ common_pkgs }}"
...
Update playbooks/common.yml
.
---
- name: common tasks
hosts: all
gather_facts: false
roles:
- common
...
Check playbook execution.
> ansible-playbook playbooks/common.yml -D
PLAY [common tasks] **********************************************************************************************
TASK [common : set hostname] *************************************************************************************
ok: [malone.guisam.xyz]
ok: [duncan.guisam.xyz]
TASK [install common pkgs] ***************************************************************************************
ok: [malone.guisam.xyz]
ok: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
malone.guisam.xyz : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Working directory in tree-like format.
guisam_ansible_tuto
├── ansible.cfg
├── group_vars
│ └── all.yml
├── hosts
├── host_vars
│ ├── duncan.guisam.xyz.yml
│ └── malone.guisam.xyz.yml
├── playbooks
│ └── common.yml
└── roles
└── common
└── tasks
└── main.yml
5 - galaxy roles¶
Create galaxy roles directory.
> mkdir -p galaxy/roles
Create install_requirements.sh
.
#!/bin/bash
error()
{
echo >&2 "[ERROR]: ${*}"
exit 1
}
typeset -r ROLES_PATH="galaxy/roles"
ansible-galaxy role install -p ${ROLES_PATH} -r requirements.yml || error "Failed to install roles"
# EOF
Add role in requirements.yml
.
---
roles:
# apache
- src: https://github.com/geerlingguy/ansible-role-apache.git
version: master
name: geerlingguy.apache
# mysql
- src: https://github.com/geerlingguy/ansible-role-mysql.git
version: master
name: geerlingguy.mysql
...
Install galaxy roles.
> bash -x install_requirements.sh
+ typeset -r ROLES_PATH=galaxy/roles
+ ansible-galaxy role install -p galaxy/roles -r requirements.yml
- extracting geerlingguy.apache to /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.apache
- geerlingguy.apache (master) was installed successfully
- extracting geerlingguy.mysql to /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.mysql
- geerlingguy.mysql (master) was installed successfully
Working directory in tree-like format over three levels.
guisam_ansible_tuto
├── ansible.cfg
├── galaxy
│ └── roles
│ ├── geerlingguy.apache
│ └── geerlingguy.mysql
├── group_vars
│ └── all.yml
├── hosts
├── host_vars
│ ├── duncan.guisam.xyz.yml
│ └── malone.guisam.xyz.yml
├── install_requirements.sh
├── playbooks
│ └── common.yml
├── requirements.yml
└── roles
└── common
└── tasks
6 - roles and galaxy roles¶
Update roles_path
in ansible.cfg
.
> grep "^roles_path" ansible.cfg ⏎
roles_path = ./roles:./galaxy/roles:/etc/ansible/roles
Create web
group in inventory, hosts
.
malone.guisam.xyz
[web]
duncan.guisam.xyz
Create apache role, roles/apache/tasks/main.yml
.
---
- include_role:
name: geerlingguy.apache
...
Create playbook, playbooks/install_apache.yml
.
---
- name: install apache2
hosts: web
gather_facts: true
roles:
- apache
...
Execute playbook, playbooks/install_apache.yml
.
> ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [duncan.guisam.xyz]
TASK [include_role : geerlingguy.apache] *************************************************************************
TASK [geerlingguy.apache : Include OS-specific variables.] *******************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include variables for Amazon Linux.] **************************************************
skipping: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Define apache_packages.] **************************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : include_tasks] ************************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.apache/tasks/setup-Debian.yml for duncan.guisam.xyz
TASK [geerlingguy.apache : Update apt cache.] ********************************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Ensure Apache is installed on Debian.] ************************************************
The following additional packages will be installed:
apache2-bin apache2-data libapr1 libaprutil1 libaprutil1-dbd-sqlite3
libaprutil1-ldap libbrotli1 libcurl4 libjansson4 liblua5.2-0 ssl-cert
Suggested packages:
apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser
openssl-blacklist
The following NEW packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapr1 libaprutil1
libaprutil1-dbd-sqlite3 libaprutil1-ldap libbrotli1 libcurl4 libjansson4
liblua5.2-0 ssl-cert
0 upgraded, 13 newly installed, 0 to remove and 0 not upgraded.
changed: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Get installed version of Apache.] *****************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Create apache_version variable.] ******************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include Apache 2.2 variables.] ********************************************************
skipping: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include Apache 2.4 variables.] ********************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Configure Apache.] ********************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.apache/tasks/configure-Debian.yml for duncan.guisam.xyz
TASK [geerlingguy.apache : Configure Apache.] ********************************************************************
ok: [duncan.guisam.xyz] => (item={'regexp': '^Listen ', 'line': 'Listen 80'})
TASK [geerlingguy.apache : Enable Apache mods.] ******************************************************************
--- before
+++ after
@@ -1,4 +1,4 @@
{
"path": "/etc/apache2/mods-enabled/rewrite.load",
- "state": "absent"
+ "state": "link"
}
changed: [duncan.guisam.xyz] => (item=rewrite.load)
--- before
+++ after
@@ -1,4 +1,4 @@
{
"path": "/etc/apache2/mods-enabled/ssl.load",
- "state": "absent"
+ "state": "link"
}
changed: [duncan.guisam.xyz] => (item=ssl.load)
TASK [geerlingguy.apache : Disable Apache mods.] *****************************************************************
TASK [geerlingguy.apache : Check whether certificates defined in vhosts exist.] **********************************
TASK [geerlingguy.apache : Add apache vhosts configuration.] *****************************************************
--- before
+++ after: /home/gsamson/.ansible/tmp/ansible-local-122853kfmsqxkt/tmppua023h7/vhosts.conf.j2
@@ -0,0 +1,15 @@
+DirectoryIndex index.php index.html
+
+
+<VirtualHost *:80>
+ ServerName local.dev
+ DocumentRoot "/var/www/html"
+
+ <Directory "/var/www/html">
+ AllowOverride All
+ Options -Indexes +FollowSymLinks
+ Require all granted
+ </Directory>
+</VirtualHost>
+
+
changed: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Add vhost symlink in sites-enabled.] **************************************************
--- before
+++ after
@@ -1,4 +1,4 @@
{
"path": "/etc/apache2/sites-enabled/vhosts.conf",
- "state": "absent"
+ "state": "link"
}
changed: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Remove default vhost in sites-enabled.] ***********************************************
skipping: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Ensure Apache has selected state and enabled on boot.] ********************************
ok: [duncan.guisam.xyz]
RUNNING HANDLER [geerlingguy.apache : restart apache] ************************************************************
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=16 changed=5 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0
Create apache role vars directory, roles/apache/vars
.
> mkdir roles/apache/vars
Update apache role vars to disable default vhost, roles/apache/vars/main.yml
.
---
apache_remove_default_vhost: true
...
Execute playbook, playbooks/install_apache.yml
.
ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
[...]
TASK [geerlingguy.apache : Remove default vhost in sites-enabled.] ***********************************************
--- before
+++ after
@@ -1,4 +1,4 @@
{
"path": "/etc/apache2/sites-enabled/000-default.conf",
- "state": "link"
+ "state": "absent"
}
changed: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Ensure Apache has selected state and enabled on boot.] ********************************
ok: [duncan.guisam.xyz]
RUNNING HANDLER [geerlingguy.apache : restart apache] ************************************************************
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=17 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Check webserver response.
> curl -I http://duncan.guisam.xyz
HTTP/1.1 200 OK
Date: Tue, 27 Oct 2020 10:15:49 GMT
Server: Apache/2.4.38 (Debian)
Last-Modified: Tue, 27 Oct 2020 09:57:47 GMT
ETag: "29cd-5b2a4143a698b"
Accept-Ranges: bytes
Content-Length: 10701
Vary: Accept-Encoding
Content-Type: text/html
Update apache role to mask version, roles/apache/tasks/main.yml
.
---
- include_role:
name: geerlingguy.apache
- name: update security configuration > ServerTokens
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerTokens '
line: ServerTokens Prod
notify: restart apache
- name: update security configuration > ServerSignature
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerSignature '
line: ServerSignature Off
notify: restart apache
...
Execute playbook, playbooks/install_apache.yml
.
> ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
[...]
TASK [geerlingguy.apache : Ensure Apache has selected state and enabled on boot.] ********************************
ok: [duncan.guisam.xyz]
TASK [apache : update security configuration > ServerTokens] *****************************************************
--- before: /etc/apache2/conf-available/security.conf (content)
+++ after: /etc/apache2/conf-available/security.conf (content)
@@ -22,7 +22,7 @@
# Set to one of: Full | OS | Minimal | Minor | Major | Prod
# where Full conveys the most information, and Prod the least.
#ServerTokens Minimal
-ServerTokens OS
+ServerTokens Prod
#ServerTokens Full
#
changed: [duncan.guisam.xyz]
TASK [apache : update security configuration > ServerSignature] **************************************************
--- before: /etc/apache2/conf-available/security.conf (content)
+++ after: /etc/apache2/conf-available/security.conf (content)
@@ -33,7 +33,7 @@
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of: On | Off | EMail
#ServerSignature Off
-ServerSignature On
+ServerSignature Off
#
# Allow TRACE method
changed: [duncan.guisam.xyz]
RUNNING HANDLER [geerlingguy.apache : restart apache] ************************************************************
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=19 changed=4 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Create apache role templates directory, roles/apache/templates
.
> mkdir roles/apache/templates
Create our own vhosts template, roles/apache/templates/guisam_vhosts.conf.j2
.
{% for server_item in apache_vhosts %}
<VirtualHost *:80>
ServerName {{ server_item.servername }}
ServerAlias {{ server_item.serveralias }}
DocumentRoot {{ server_item.documentroot }}
<Directory {{ server_item.documentroot }}>
Options -Indexes +FollowSymLinks +MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/{{ server_item.servername }}-error.log
CustomLog ${APACHE_LOG_DIR}/{{ server_item.servername }}-access.log combined
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* – [F]
{% if server_item.httpredirect is defined and server_item.sslcertificatefile is defined and server_item.sslcertificatekeyfile is defined %}
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
{% endif %}
</VirtualHost>
{% if server_item.sslcertificatefile is defined and server_item.sslcertificatekeyfile is defined %}
<VirtualHost *:443>
ServerName {{ server_item.servername }}
ServerAlias {{ server_item.serveralias }}
DocumentRoot {{ server_item.documentroot }}
<Directory {{ server_item.documentroot }}>
Options -Indexes +FollowSymLinks +MultiViews
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/{{ server_item.servername }}-error.log
CustomLog ${APACHE_LOG_DIR}/{{ server_item.servername }}-access.log combined
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* – [F]
SSLEngine on
SSLCertificateFile "{{ server_item.sslcertificatefile }}"
SSLCertificateKeyFile "{{ server_item.sslcertificatekeyfile }}"
</VirtualHost>
{% endif %}
{% endfor %}
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
Create our vhost variable, host_vars/duncan.guisam.xyz.yml
.
---
# common
hostname: duncan.guisam.xyz
# apache
apache_vhosts:
- servername: "duncan.guisam.xyz"
serveralias: "www.duncan.guisam.xyz,test.duncan.guisam.xyz"
documentroot: "/var/www/duncan.guisam.xyz"
...
Deploy.
ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
[...]
TASK [geerlingguy.apache : Add apache vhosts configuration.] *****************************************************
--- before: /etc/apache2/sites-available/vhosts.conf
+++ after: /home/gsamson/.ansible/tmp/ansible-local-242080w_hdjvti/tmpowl9aeuj/guisam_vhosts.conf.j2
@@ -1,15 +1,21 @@
-DirectoryIndex index.php index.html
+<VirtualHost *:80>
+ ServerName duncan.guisam.xyz
+ ServerAlias www.duncan.guisam.xyz,test.duncan.guisam.xyz
+ DocumentRoot /var/www/duncan.guisam.xyz
+ <Directory /var/www/duncan.guisam.xyz>
+ Options -Indexes +FollowSymLinks +MultiViews
+ AllowOverride All
+ Require all granted
+ </Directory>
-<VirtualHost *:80>
- ServerName local.dev
- DocumentRoot "/var/www/html"
+ ErrorLog ${APACHE_LOG_DIR}/duncan.guisam.xyz-error.log
+ CustomLog ${APACHE_LOG_DIR}/duncan.guisam.xyz-access.log combined
- <Directory "/var/www/html">
- AllowOverride All
- Options -Indexes +FollowSymLinks
- Require all granted
- </Directory>
+ RewriteEngine on
+ RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
+ RewriteRule .* – [F]
+
</VirtualHost>
-
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
changed: [duncan.guisam.xyz]
[...]
RUNNING HANDLER [geerlingguy.apache : restart apache] ************************************************************
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=19 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Update apache role to create documentroot and index.html, roles/apache/tasks/main.yml
.
---
- include_role:
name: geerlingguy.apache
- name: update security configuration > ServerTokens
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerTokens '
line: ServerTokens Prod
notify: restart apache
- name: update security configuration > ServerSignature
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerSignature '
line: ServerSignature Off
notify: restart apache
- name: create vhosts documentroot
file:
path: "{{ item.documentroot }}"
mode: '0755'
owner: www-data
group: www-data
state: directory
loop: "{{ apache_vhosts }}"
when: not ansible_check_mode
- name: create index.html pages
template:
src: ./templates/index.html.j2
dest: "{{ item.documentroot }}/index.html"
mode: '0644'
owner: www-data
group: www-data
loop: "{{ apache_vhosts }}"
when: not ansible_check_mode
...
Create apache role index.html template, roles/apache/templates/index.html.j2
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>The HTML5 Herald</title>
<meta name="description" content="The HTML5 Herald">
<meta name="author" content="SitePoint">
<link rel="stylesheet" href="css/styles.css?v=1.0">
</head>
<body>
Hello fucking bullshit world !
</body>
</html>
Deploy.
> ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
[...]
TASK [apache : create vhosts documentroot] ***********************************************************************
--- before
+++ after
@@ -1,6 +1,6 @@
{
- "group": 0,
- "owner": 0,
+ "group": 33,
+ "owner": 33,
"path": "/var/www/duncan.guisam.xyz",
- "state": "absent"
+ "state": "directory"
}
changed: [duncan.guisam.xyz] => (item={'servername': 'duncan.guisam.xyz', 'serveralias': 'www.duncan.guisam.xyz,test.duncan.guisam.xyz', 'documentroot': '/var/www/duncan.guisam.xyz'})
TASK [apache : create index.html pages] **************************************************************************
--- before
+++ after: /home/gsamson/.ansible/tmp/ansible-local-351745uoaoa3f1/tmp0es6vxw9/index.html.j2
@@ -0,0 +1,18 @@
+<!doctype html>
+
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+
+ <title>Hello world</title>
+ <meta name="description" content="The HTML5 Herald">
+ <meta name="author" content="SitePoint">
+
+ <link rel="stylesheet" href="css/styles.css?v=1.0">
+
+</head>
+
+<body>
+ Hello fucking bullshit world !
+</body>
+</html>
changed: [duncan.guisam.xyz] => (item={'servername': 'duncan.guisam.xyz', 'serveralias': 'www.duncan.guisam.xyz,test.duncan.guisam.xyz', 'documentroot': '/var/www/duncan.guisam.xyz'})
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=20 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Working directory in tree-like format over four levels.
guisam_ansible_tuto
├── ansible.cfg
├── galaxy
│ └── roles
│ ├── geerlingguy.apache
│ │ ├── defaults
│ │ ├── handlers
│ │ ├── LICENSE
│ │ ├── meta
│ │ ├── molecule
│ │ ├── README.md
│ │ ├── tasks
│ │ ├── templates
│ │ └── vars
│ └── geerlingguy.mysql
│ ├── defaults
│ ├── handlers
│ ├── LICENSE
│ ├── meta
│ ├── molecule
│ ├── README.md
│ ├── tasks
│ ├── templates
│ └── vars
├── group_vars
│ └── all.yml
├── hosts
├── host_vars
│ ├── duncan.guisam.xyz.yml
│ └── malone.guisam.xyz.yml
├── install_requirements.sh
├── playbooks
│ ├── common.yml
│ └── install_apache.yml
├── requirements.yml
└── roles
├── apache
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ │ ├── guisam_vhosts.conf.j2
│ │ └── index.html.j2
│ └── vars
│ └── main.yml
└── common
└── tasks
└── main.yml
7 - roles a step beyond¶
Update apache role main task, roles/apache/tasks/main.yml
.
---
- include_role:
name: geerlingguy.apache
- name: update security configuration > ServerTokens
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerTokens '
line: ServerTokens Prod
notify: restart apache
- name: update security configuration > ServerSignature
lineinfile:
path: /etc/apache2/conf-available/security.conf
regexp: '^ServerSignature '
line: ServerSignature Off
notify: restart apache
- name: create vhosts documentroot
file:
path: "{{ item.documentroot }}"
mode: '0755'
owner: www-data
group: www-data
state: directory
loop: "{{ apache_vhosts }}"
when: not ansible_check_mode
- name: create index.html pages
include: index.yml
loop: "{{ apache_vhosts }}"
loop_control:
loop_var: apache_vhost
when: not ansible_check_mode
...
Create apache role task, roles/apache/tasks/index.yml
.
---
- name: create index.html pages
template:
src: ./templates/index.html.j2
dest: "{{ apache_vhost.documentroot }}/index.html"
mode: '0644'
owner: www-data
group: www-data
...
Update apache role template, roles/apache/templates/index.html.j2
.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ apache_vhost.servername }}</title>
<meta name="description" content="{{ apache_vhost.servername }}">
<meta name="author" content="SitePoint">
<link rel="stylesheet" href="css/styles.css?v=1.0">
</head>
<body>
<h1>{{ apache_vhost.servername }} vhost summary</h1>
servername: {{ apache_vhost.servername }}<br>
serveralias: {{ apache_vhost.serveralias }}<br>
documentroot: {{ apache_vhost.documentroot }}<br>
</body>
</html>
Deploy.
> ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
[...]
TASK [apache : create index.html pages] **************************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/roles/apache/tasks/index.yml for duncan.guisam.xyz
TASK [apache : create index.html pages] **************************************************************************
--- before: /var/www/duncan.guisam.xyz/index.html
+++ after: /home/gsamson/.ansible/tmp/ansible-local-420650kb73cplm/tmp00g5yq73/index.html.j2
@@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
- <title>Hello world</title>
- <meta name="description" content="Hello world">
+ <title>duncan.guisam.xyz</title>
+ <meta name="description" content="duncan.guisam.xyz">
<meta name="author" content="SitePoint">
<link rel="stylesheet" href="css/styles.css?v=1.0">
@@ -13,6 +13,9 @@
</head>
<body>
- Hello fucking bullshit world !
+ <h1>duncan.guisam.xyz vhost summary</h1>
+ servername: duncan.guisam.xyz<br>
+ serveralias: www.duncan.guisam.xyz,test.duncan.guisam.xyz<br>
+ documentroot: /var/www/duncan.guisam.xyz<br>
</body>
</html>
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=21 changed=1 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Then just add some vhost, host_vars/duncan.guisam.xyz.yml
.
---
# common
hostname: duncan.guisam.xyz
# apache
apache_vhosts:
- servername: "duncan.guisam.xyz"
serveralias: "www.duncan.guisam.xyz,test.duncan.guisam.xyz"
documentroot: "/var/www/duncan.guisam.xyz"
- servername: "toto.guisam.xyz"
serveralias: "www.toto.guisam.xyz,test.toto.guisam.xyz"
documentroot: "/var/www/toto.guisam.xyz"
- servername: "titi.guisam.xyz"
serveralias: "www.titi.guisam.xyz,test.titi.guisam.xyz"
documentroot: "/var/www/titi.guisam.xyz"
...
Deploy.
ansible-playbook playbooks/install_apache.yml -D
PLAY [install apache2] *******************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [duncan.guisam.xyz]
TASK [include_role : geerlingguy.apache] *************************************************************************
TASK [geerlingguy.apache : Include OS-specific variables.] *******************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include variables for Amazon Linux.] **************************************************
skipping: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Define apache_packages.] **************************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : include_tasks] ************************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.apache/tasks/setup-Debian.yml for duncan.guisam.xyz
TASK [geerlingguy.apache : Update apt cache.] ********************************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Ensure Apache is installed on Debian.] ************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Get installed version of Apache.] *****************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Create apache_version variable.] ******************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include Apache 2.2 variables.] ********************************************************
skipping: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Include Apache 2.4 variables.] ********************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Configure Apache.] ********************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/galaxy/roles/geerlingguy.apache/tasks/configure-Debian.yml for duncan.guisam.xyz
TASK [geerlingguy.apache : Configure Apache.] ********************************************************************
ok: [duncan.guisam.xyz] => (item={'regexp': '^Listen ', 'line': 'Listen 80'})
TASK [geerlingguy.apache : Enable Apache mods.] ******************************************************************
ok: [duncan.guisam.xyz] => (item=rewrite.load)
ok: [duncan.guisam.xyz] => (item=ssl.load)
TASK [geerlingguy.apache : Disable Apache mods.] *****************************************************************
TASK [geerlingguy.apache : Check whether certificates defined in vhosts exist.] **********************************
TASK [geerlingguy.apache : Add apache vhosts configuration.] *****************************************************
--- before: /etc/apache2/sites-available/vhosts.conf
+++ after: /home/gsamson/.ansible/tmp/ansible-local-443758d1i1twbf/tmp_442nj5a/guisam_vhosts.conf.j2
@@ -17,5 +17,43 @@
RewriteRule .* – [F]
</VirtualHost>
+<VirtualHost *:80>
+ ServerName toto.guisam.xyz
+ ServerAlias www.toto.guisam.xyz,test.toto.guisam.xyz
+ DocumentRoot /var/www/toto.guisam.xyz
+
+ <Directory /var/www/toto.guisam.xyz>
+ Options -Indexes +FollowSymLinks +MultiViews
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ ErrorLog ${APACHE_LOG_DIR}/toto.guisam.xyz-error.log
+ CustomLog ${APACHE_LOG_DIR}/toto.guisam.xyz-access.log combined
+
+ RewriteEngine on
+ RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
+ RewriteRule .* – [F]
+
+</VirtualHost>
+<VirtualHost *:80>
+ ServerName titi.guisam.xyz
+ ServerAlias www.titi.guisam.xyz,test.titi.guisam.xyz
+ DocumentRoot /var/www/titi.guisam.xyz
+
+ <Directory /var/www/titi.guisam.xyz>
+ Options -Indexes +FollowSymLinks +MultiViews
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ ErrorLog ${APACHE_LOG_DIR}/titi.guisam.xyz-error.log
+ CustomLog ${APACHE_LOG_DIR}/titi.guisam.xyz-access.log combined
+
+ RewriteEngine on
+ RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
+ RewriteRule .* – [F]
+
+</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
changed: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Add vhost symlink in sites-enabled.] **************************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Remove default vhost in sites-enabled.] ***********************************************
ok: [duncan.guisam.xyz]
TASK [geerlingguy.apache : Ensure Apache has selected state and enabled on boot.] ********************************
ok: [duncan.guisam.xyz]
TASK [apache : update security configuration > ServerTokens] *****************************************************
ok: [duncan.guisam.xyz]
TASK [apache : update security configuration > ServerSignature] **************************************************
ok: [duncan.guisam.xyz]
TASK [apache : create vhosts documentroot] ***********************************************************************
ok: [duncan.guisam.xyz] => (item={'servername': 'duncan.guisam.xyz', 'serveralias': 'www.duncan.guisam.xyz,test.duncan.guisam.xyz', 'documentroot': '/var/www/duncan.guisam.xyz'})
--- before
+++ after
@@ -1,6 +1,6 @@
{
- "group": 0,
- "owner": 0,
+ "group": 33,
+ "owner": 33,
"path": "/var/www/toto.guisam.xyz",
- "state": "absent"
+ "state": "directory"
}
changed: [duncan.guisam.xyz] => (item={'servername': 'toto.guisam.xyz', 'serveralias': 'www.toto.guisam.xyz,test.toto.guisam.xyz', 'documentroot': '/var/www/toto.guisam.xyz'})
--- before
+++ after
@@ -1,6 +1,6 @@
{
- "group": 0,
- "owner": 0,
+ "group": 33,
+ "owner": 33,
"path": "/var/www/titi.guisam.xyz",
- "state": "absent"
+ "state": "directory"
}
changed: [duncan.guisam.xyz] => (item={'servername': 'titi.guisam.xyz', 'serveralias': 'www.titi.guisam.xyz,test.titi.guisam.xyz', 'documentroot': '/var/www/titi.guisam.xyz'})
TASK [apache : create index.html pages] **************************************************************************
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/roles/apache/tasks/index.yml for duncan.guisam.xyz
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/roles/apache/tasks/index.yml for duncan.guisam.xyz
included: /home/gsamson/gsamson_docs/guisam_ansible_tuto/roles/apache/tasks/index.yml for duncan.guisam.xyz
TASK [apache : create index.html pages] **************************************************************************
ok: [duncan.guisam.xyz]
TASK [apache : create index.html pages] **************************************************************************
--- before
+++ after: /home/gsamson/.ansible/tmp/ansible-local-443758d1i1twbf/tmpbge9809z/index.html.j2
@@ -0,0 +1,21 @@
+<!doctype html>
+
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+
+ <title>toto.guisam.xyz</title>
+ <meta name="description" content="toto.guisam.xyz">
+ <meta name="author" content="SitePoint">
+
+ <link rel="stylesheet" href="css/styles.css?v=1.0">
+
+</head>
+
+<body>
+ <h1>toto.guisam.xyz vhost summary</h1>
+ servername: toto.guisam.xyz<br>
+ serveralias: www.toto.guisam.xyz,test.toto.guisam.xyz<br>
+ documentroot: /var/www/toto.guisam.xyz<br>
+</body>
+</html>
changed: [duncan.guisam.xyz]
TASK [apache : create index.html pages] **************************************************************************
--- before
+++ after: /home/gsamson/.ansible/tmp/ansible-local-443758d1i1twbf/tmpm5yu97l7/index.html.j2
@@ -0,0 +1,21 @@
+<!doctype html>
+
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+
+ <title>titi.guisam.xyz</title>
+ <meta name="description" content="titi.guisam.xyz">
+ <meta name="author" content="SitePoint">
+
+ <link rel="stylesheet" href="css/styles.css?v=1.0">
+
+</head>
+
+<body>
+ <h1>titi.guisam.xyz vhost summary</h1>
+ servername: titi.guisam.xyz<br>
+ serveralias: www.titi.guisam.xyz,test.titi.guisam.xyz<br>
+ documentroot: /var/www/titi.guisam.xyz<br>
+</body>
+</html>
changed: [duncan.guisam.xyz]
RUNNING HANDLER [geerlingguy.apache : restart apache] ************************************************************
changed: [duncan.guisam.xyz]
PLAY RECAP *******************************************************************************************************
duncan.guisam.xyz : ok=26 changed=5 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0