How to create a new config file in Ansible playbook

Posted on in Categories , , , , , , , last updated February 19, 2017

I wanted to create a file named /etc/apt/apt.conf.d/1000-force-ipv4-transport with the value set to ‘Acquire::ForceIPv4 true;’ on 20 cloud servers hosted in AWS. I already setup Ansible playbook to automate stuff. How do I create a new file using Ansible playbook? Is it possible to create a complex file with many lines of text (say squid.conf) using Ansible IT automation tool?

You can use any one of the following module to create a new file:

  1. copy module – Copies files to remote locations.
  2. template module – Templates a file out to a remote server.

How to write a single line content on remote server and create a file

The syntax is pretty simple:

    - copy:
           content: "your config line here"
           dest: "/path/to/file"

As per the documentation:

When used instead of ‘src’, sets the contents of a file directly to the specified value. This is for simple values, for anything complex or with formatting please switch to the template module.

So here is a sample create-file.yml file:

# create a file to force apt-get to use IPv4 only
  - copy:
         content: "Acquire::ForceIPv4 true;"
         dest: "/etc/apt/apt.conf.d/1000-force-ipv4-transport"

Where,

  1. content: "Acquire::ForceIPv4 true;" – Sets the contents of a file directly to the specified string
  2. dest: "/etc/apt/apt.conf.d/1000-force-ipv4-transport" – Set remote absolute path where the file should be copied/created to
  3. backup: yes – Remote absolute path where the file should be copied to.
  4. owner: root – Set the user that should own the file/directory
  5. group: root – Set the group that should own the file/directory
  6. mode: 0600 – Set the file permission using octal numbers

So here is a sample inventory file:
$ cat ~/hosts
[kvmhost]
192.168.2.45 ansible_user=root
192.168.2.46 ansible_user=root

Here is my updated create-file.yml for you:

---
# same config file
- hosts: kvmhost
  remote_user: root
  tasks:
          # create a new file on each host
          - copy: 
                  content: "Acquire::ForceIPv4 true;" 
                  dest: "/etc/apt/apt.conf.d/1000-force-ipv4-transport"
                  backup: yes
                  owner: root
                  group: root
                  mode: 0644
          # run apt-get too using IPv4 
          - apt:
                  update_cache: yes
                  cache_valid_time: 3600
                  upgrade: dist

You can run it as usual:
$ ANSIBLE_HOSTS=~/hosts; ansible-playbook create-file.yml
Sample outputs:

Fig.01: Playbook in action
Fig.01: Playbook in action

How to create a blank file in Ansible playbook

The syntax is pretty simple:

  file: 
       path: /usr/local/etc/my.conf
       state: touch
       owner: root
       group: root
       mode: 0600

Where,

  1. path: /usr/local/etc/my.conf – Set path to the file being managed
  2. state: touch – Create a file set by path
  3. owner: root – Set the user that should own the file/directory
  4. group: root – Set the group that should own the file/directory
  5. mode: 0600 – Set the file permission using octal numbers

How to create a complex file using ansible

If you need to add multiple lines consider using templates module. Templates are processed by the Jinja2 templating language and a file created out to a remote server.

Step – 1 Create Ansible Playbook called squid.yml

$ cat squid.yml
Sample outputs:

# Create squid.conf
- hosts: kvmhost
  remote_user: root
  tasks:
          - template:
                  src: squid.conf.j2
                  dest: /etc/squid/squid.conf
                  owner: root
                  group: root
                  mode: '0644'
                  validate: '/usr/sbin/squid -k check'
                  backup: yes
          - service:
                  name: squid
                  state: restarted

Step – 2 Create Jinja2 template called squid.conf.j2

$ cat squid.conf.j2
Sample outputs:

acl mylan src {{ nixcraft_vlan_lan_subnet }}
acl SSL_ports port 443
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access allow mylan
http_access deny all
http_port {{ nixcraft_http_port }}
tcp_outgoing_address {{ nixcraft_cloud_server_ip }}
cache_mem {{ nixcraft_memory }} MB
cache_dir diskd /var/spool/squid 1024 16 256 Q1=72 Q2=64
access_log daemon:/var/log/squid/access.log squid
coredump_dir /var/spool/squid
refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
refresh_pattern (Release|Packages(.gz)*)$      0       20%     2880
refresh_pattern .		0	20%	4320
forwarded_for delete
via off
forwarded_for off
follow_x_forwarded_for deny all
request_header_access X-Forwarded-For deny all

Step – 3 Update inventory file called ~/hosts

Updated your inventory file with variables for your squid.conf.j2 template:
$ cat ~/hosts
### my hosts ##
[kvmhost]
192.168.2.45 ansible_user=root
192.168.2.46 ansible_user=root
## variables with values ##
[kvmhost:vars]
nixcraft_vlan_lan_subnet=10.8.0.0/24
nixcraft_http_port=10.8.0.1:3128
nixcraft_cloud_server_ip=72.xxx.yyy.zzz
nixcraft_memory=1024

Step 4 – Run your playbook to create complex squid.conf file on remote servers

Type the following command:
$ ANSIBLE_HOSTS=~/hosts; ansible-playbook squid.yml

For more info see copy, template and file module documentation.

2 comment

  1. Hi,
    there is a small glitch:
    backup: yes – Remote absolute path where the file should be copied to. (NO)
    The backup parameter tells Ansible to make a backup file before copying the new file.
    The backup file is named like this [email protected]:09~
    By the way:
    There is no option to keep only a certain number o backups, say last three backups.
    http://docs.ansible.com/ansible/copy_module.html

    You might mention that the validate command is executed before copying and must return exit code 0;
    validate: ‘/usr/sbin/squid -k check’

Leave a Comment