Ansible Provisioning

Last Update:

Author: Christoph Stoettner
Read in about 5 min · 975 words

Fountain pen and a notebook

Photo by Aaron Burden | Unsplash

In the first two parts of this little devops series, I showed build templates with Packer and deploying virtual-machines with Terraform .

Now we want to install some more packages on our new servers.


I started using Ansible for deployments some years ago. For example I showed deploying IBM Connections at Social Connections 12 in Vienna .

For more details on the functionality, have a look at the post How Ansible Works

Ansible uses plain ssh and doesn’t need any additional server or client component.

You can run Ansible as a separate task in your deployment pipeline, or add it as post-provisioning task to Terraform. So it runs automatically when Terraform deploys your systems.


You can use Ansible to deploy Windows Servers too. More interesting is running Ansible from a Windows machine to deploy Linux and Windows servers.

For Windows you can use WinRM or SSH to connect for remote management. The SSH support is experimental AFAIK.



Ansible is available for all major Linux distributions. Check the documentation for installation instructions .

Little project

Directory structure of a little Ansible example

├── group_vars
│   └── all
│       └── main.yml
├── inventory
├── roles
│   ├── common
│   │   └── tasks
│   │       └── main.yml
│   └── ldap
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
├── site.yml
└── templates
    ├── base.ldif.j2
    ├── db.ldif.j2
    ├── monitor.ldif.j2
    └── user-ldap.ldif.j2

In the inventory file you define your servers and group them together.




So gpn19-server1 is only in the group gpn19, server gnp19-server2 is part of gpn19 and ldap. There is always a group all with all servers of an inventory file.

The Ansible playbook itself is defined as an Yaml-file:


- hosts: all
    - common

- hosts: ldap
    - role: ldap

So for all hosts the role common will run and on group ldap the role ldap.

To make the roles independent of the environment, we use some variables. So it’s enough to just change the variable and the deployment will use different domain and passwords.


  domain: dc=devops,dc=example,dc=com
  passwordencrypted: "{SSHA}CdGAzVNlrqgLbKo6pebBxuDBBkxokkHm"
  passwordclear: "password"

To keep it simple, the password is defined here in the variable file. Have a look at Ansible Vault to keep your passwords encrypted.

Using template files

For the ldap deployment we need to change some files on the target server. These are already prepared in the directory templates and use Jinga2 template engine .


#!/usr/bin/env bash

cd /etc/openldap/slapd.d
ldapmodify -Y EXTERNAL  -H ldapi:/// -f db.ldif
ldapmodify -Y EXTERNAL  -H ldapi:/// -f monitor.ldif
sleep 5
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
sleep 5
ldapadd -x -w {{ ldap.passwordclear }} -D "cn=ldapadm,{{ ldap.domain }}" -f /etc/openldap/slapd.d/base.ldif   
sleep 10
ldapadd -x -w {{ ldap.passwordclear }} -D "cn=ldapadm,{{ ldap.domain }}" -f /etc/openldap/slapd.d/user-ldap.ldif
  • We can use our variable in Jinga2 and these will be replaced during deployment


# Disable Firewall during Installation
- name: Disable Firewall  

# Disabe SELinux, most IBM Software is not supported with it
- name: Disable SELinux
    state: disabled

# Increase limits.conf for IBM products
- name: Change limits.conf    
    domain: root
    limit_type: '-'
    limit_item: nproc
    value: '16384'
- pam_limits:
    domain: root
    limit_type: '-'
    limit_item: nofile
    value: '65536'
- pam_limits:
    domain: root
    limit_type: '-'
    limit_item: stack
    value: '10240'

# Install Unzip
- name: Install unzip to support unarchive function of ansible, add xauth
    name={{ item }}       
    - unzip
    - xauth
    - vim

# Configure SSH X11Forward
- name: Update SSH configuration to be more secure.
    dest: "/etc/ssh/sshd_config"
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
    state: present
    - regexp: "^X11Forwarding"
      line: "X11Forwarding yes"
    - regexp: "^X11UseLocalhost"
      line: "X11UseLocalhost no"
- name: Restart SSH
  • Stop Firewalld and set to disabled

  • Configure some limits in limits.conf

  • Install additional packages (independent of yum or apt)


- name: Install system packages for OpenLDAP
    name={{ item }}
    - openldap-servers
    - openldap-clients

- name: Enable Slapd service    

- name: Initial ldap config, copy templates db.ldif   
  template: src=db.ldif.j2 dest=/etc/openldap/slapd.d/db.ldif
  tags: parse

- name: Initial ldap config, copy templates monitor.ldif
  template: src=monitor.ldif.j2 dest=/etc/openldap/slapd.d/monitor.ldif
  tags: parse

- name: Create base.ldif
  template: src=base.ldif.j2 dest=/etc/openldap/slapd.d/base.ldif
  tags: parse

- name: Create user.ldif
  template: src=user-ldap.ldif.j2 dest=/etc/openldap/slapd.d/user-ldap.ldif
  tags: parse

- name: Copy sample db config
    src: "/usr/share/openldap-servers/DB_CONFIG.example"
    dest: "/var/lib/ldap/DB_CONFIG"
    remote_src: yes
    directory_mode: yes
    owner: ldap
    group: ldap

- name: Create LDAP Config Script
    dest: /tmp/
    mode: 0755
  tags: parse

- name: Configure LDAP and Import Users
  shell: "/tmp/"

- name: Remove config script
    path: /tmp/
    state: absent
  • Enable slapd service

  • Copy db.ldif.j2 from templates to dest

Run Ansible Playbook

To run this playbook with our inventory file, just run:

ansible-playbook -i inventory site.yml

So now you’re prepared to build new servers and deploy software on it. Have fun!

Ansible Galaxy

On Ansible Galaxy you can share and download Ansible roles. So start new projects searching there, don’t start from scratch.

Galaxy is a hub for finding and sharing Ansible content.

Use Galaxy to jump-start your automation project with great content from the Ansible community. Galaxy provides pre-packaged units of work known to Ansible as Roles, and new in Galaxy 3.2, Collections.

Roles can be dropped into Ansible PlayBooks and immediately put to work. You’ll find roles for provisioning infrastructure, deploying applications, and all of the tasks you do everyday. The new Collection format provides a comprehensive package of automation that may include multiple playbooks, roles, modules, and plugins.

Gulasch Programmiernacht

The content of this series was part of my talk at the GPN19. So you can watch a video of the talk too:

<iframe width=“1024” height=“576” src=“" frameborder=“0” allowfullscreen></iframe>

Add a comment
There was an error sending your comment, please try again.
Thank you!
Your comment has been submitted and will be published once it has been approved.

Your email address will not be published. Required fields are marked with *

Suggested Reading
Aaron Burden: Fountain pen and a notebook

My last article showed how to build a server template with Packer .

Now we want to use this template to create some servers on VMware vSphere. DNS will be registered manually and all IP addresses will be defined as fixed in the config files.

Last Update:
Read in about 6 min
Card image cap

In the post Create A Test Environment with Terraform and KVM I created the first three virtual machines, now we configure a DNS server so name resolution works as expected.

Since HCL Connections started to add Kubernetes to the stack, we need to use proper name resolution instead of just editing /etc/hosts. That’s a bit of an effort, but in the end it is way easier than checking several hosts if the hosts file is uptodate.

Last Update:
Read in about 7 min
Aaron Burden: Fountain pen and a notebook

For GPN19 I prepared a second talk on Documentation with any Editor . The talk was based on a previous one from Froscon 13, but the pipeline tooling changed.

This time there was a technical issue during the recording and so there are only the slides available, but you can still watch the video of the Froscon talk: Froscon 13: Documentation with any Editor

Last Update:
Read in about 8 min