Ansible
Contents
Installation
Installation of the development machine
pip install ansible brew install hudochenkov/sshpass/sshpass
Installation of ubuntu server
sudo apt update sudo apt install ansible sudo apt install sshpass
Running playbooks
To run all playbooks write this command in the ansible folder.
Be sure SSH Key based authentication is sorted before. See below.
ansible-playbook ./playbooks/all.yml -i ./inventory/hosts
Folders and files
Hosts
Add / update servers to ./inventory/hosts file with either name or ip addresses
They can be grouped by tags like
[web_servers] 192.168.1.200 192.168.1.201 [database_servers] 192.168.1.204
They can be used as below in the playbook
- hosts: web_servers
Test it by
ansible -i ./inventory/hosts servers -m ping --user logicmade --ask-pass
servers is the name of the group in hosts logicmade is the username
Setting variables next to server names
[web_servers] 192.168.1.200 apache_package=apache2 php_package=libapache-mod-php 192.168.1.201 apache_package=https php_package=php [database_servers] 192.168.1.204
then we can use them in playbooks like
- hosts: all
become: true
tasks:
- name install apache and php
package:
name:
- "{{ apache_package }}"
- "{{ php_package }}"
state : latest
update_cache: yes
Playbooks
In a playbook yaml file become: true means it runs as sudo
To run a playbook :
ansible-playbook ./playbooks/apt.yml --user logicmade --ask-pass --ask-become-pass -i ./inventory/hosts
Ad-Hoc Commands
it starts with ansible and the command after -m flag
ansible all --key-file ~/.ssh/ansible -i inventory -m ping
Modules
Modules are pre-defined tasks in Ansible. Like apt, debug, git, file etc. see all module list for detail.
Conditions
"when" is used for conditions.
gather_facts
To get the facts for the nodes (or just one of them / 192.168.1.204 like below) we can run
ansible all -m gather_facts --limit 192.168.1.204
Then we can use any of them like
when: ansible_distribution == "Ubuntu"
or combine them like
when: ansible_distribution == "Ubuntu" and ansible_distribution_version == "24.0"
Templates
Create "templates" folder in the root. When we use them in playbook templates are relative to playbook path.
Template files have the extension of .j2
Variables used in moustache format.
Example template for nginx site
site_name = {{ site_name}}
server {
listen 80;
server_name {{ site_name}}.{{ site_type}}.bookitfor.me.uk;
location / {
proxy_pass http://localhost:{{ internal_port }};
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_cache_bypass \$http_upgrade;
}
}
Using template in playbook and variables
variables can be defined in playbook before tasks like
- name : Site creation
hosts: all
become: true
vars:
site_name: somesite
site_type: api
internal_port: 3001
tasks:
or we can pass them from cli like
ansible-playbook playbook.yml -e "site_name=example.com site_type=api internal_port:3001"
Key base Authentication
Setting Up SSH Key-Based Authentication
Generate Key Pair: On the Ansible controller, run command below to create keys.
ssh-keygen -t rsa -f ~/.ssh/ansible-keys
Distribute Public Key
Copy the public key to managed nodes using
ssh-copy-id -i ~/.ssh/ansible-keys.pub user@node.
Configure Ansible Inventory
Specify the private key in your inventory file:
[servers] node1 ansible_host=192.168.1.10 ansible_user=admin ansible_ssh_private_key_file=~/.ssh/ansible-keys
Fixing sudo issue
In the server run sudo visudo and add this line
logicmade ALL=(ALL) NOPASSWD: ALL
logicmade is the username to be escalated
To be safe, you can also create a dedicated file:
sudo visudo -f /etc/sudoers.d/logicmade
Now we can run a playbook like this
ansible-playbook ./playbooks/apt.yml -i ./inventory/hosts
Add:
logicmade ALL=(ALL) NOPASSWD: ALL
Interactive prompts
- name: Example playbook with prompts
hosts: all
become: yes
vars_prompt:
- name: username
prompt: "Enter the username"
private: no
- name: password
prompt: "Enter the password"
private: yes
tasks:
- name: Create a user
user:
name: "{{ username }}"
password: "{{ password }}"
with defaults
vars_prompt:
- name: domain_name
prompt: "Enter domain"
private: no
default: "example.com"
Pass vairables via CLI
ansible-playbook playbook.yml -e "domain_name=example.com email=test@example.com"
Block, Rescue, Always
We can use them for error handling or logging
tasks:
- name: Attempt and graceful roll back demo
block:
- name: Print a message
ansible.builtin.debug:
msg: 'I execute normally'
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- name: Print when errors
ansible.builtin.debug:
msg: 'I caught an error'
- name: Force a failure in middle of recovery! >:-)
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I also never execute :-('
always:
- name: Always do this
ansible.builtin.debug:
msg: "This always executes"
Tips
Vault
- No blank lines
- No special characters in password like (+)
- In playbook it's relative to playbook's folder.
like :
/playbooks/test.yml /aws_vault.yml
then
- name: Show AWS key from vault
hosts: localhost
gather_facts: false
vars_files:
- ../aws_vault.yml
tasks:
- name: Display the AWS Access Key ID
debug:
msg: "aws_access_key_id = {{ aws_access_key_id }}"
Create Vault
ansible-vault create group_vars/all/vault.yml
Edit Vault
ansible-vault edit group_vars/all/vault.yml
Verify Vault file
ansible all -i inventory/hosts -m debug -a "var=aws_access_key_id" --ask-vault-pass
aws_access_key_id is a key in the vault.
Vault Password File
Choose a location outside your repo, e.g.:
mkdir -p ~/.ansible echo "MySuperSecretVaultPassword" > ~/.ansible/.vault_pass chmod 600 ~/.ansible/.vault_pass
Create vault with password file
ansible-vault create playbooks/vault_aws.yml --vault-password-file ~/.ansible/.vault_pass
Run your playbook using the password file
ansible-playbook -i inventory/hosts playbooks/install_aws.yml \ --vault-password-file ~/.ansible/.vault_pass