Skip to content

DevOps Day 85: Create Files on App Servers using Ansible

This document outlines the solution for DevOps Day 85, where the objective was to use Ansible to create a specific file with distinct ownership permissions on multiple application servers.

Table of Contents


Task Overview

Objective: The Nautilus DevOps team needs to create a blank file /opt/appdata.txt on all three application servers (stapp01, stapp02, stapp03).

Requirements: 1. Inventory Creation: Create /home/thor/playbook/inventory listing all app servers. 2. Playbook Creation: Create /home/thor/playbook/playbook.yml. 3. File Creation: Create /opt/appdata.txt. 4. Permissions: Set file permissions to 0655. 5. Ownership: * stapp01: Owner/Group tony * stapp02: Owner/Group steve * stapp03: Owner/Group banner 6. Validation: Execute with ansible-playbook -i inventory playbook.yml.


Step-by-Step Solution

1. Create the Inventory File

The key to solving the "different owner per server" requirement efficiently is to use the ansible_user variable in our inventory. Since we already define ansible_user to connect (tony, steve, banner), we can reuse this variable in the playbook!

Command:

mkdir -p ~/playbook
cd ~/playbook
vi inventory

Content:

[app]
stapp01 ansible_user=tony ansible_ssh_pass=Ir0nM@n
stapp02 ansible_user=steve ansible_ssh_pass=Am3ric@
stapp03 ansible_user=banner ansible_ssh_pass=BigGr33n

[all:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=no'

2. Create the Playbook

We use the file module. To set the owner dynamically, we use the {{ ansible_user }} variable. This means when Ansible runs on stapp01, it uses tony. When on stapp02, it uses steve.

Command:

vi playbook.yml

Content:

---
- name: create file with specific ownership
  hosts: all
  become: true  # Required to write to /opt
  tasks:
    - name: create a blank file /opt/appdata.txt
      file:
        path: /opt/appdata.txt
        state: touch
        mode: '0655'
        owner: "{{ ansible_user }}"
        group: "{{ ansible_user }}"

3. Execution and Validation

Run the playbook against the inventory.

Command:

ansible-playbook -i inventory playbook.yml

Output Analysis:

PLAY [create file with specific ownership] ******************************************

TASK [Gathering Facts] **************************************************************
ok: [stapp02]
ok: [stapp03]
ok: [stapp01]

TASK [create a blank file /opt/appdata.txt] *****************************************
changed: [stapp02]
changed: [stapp03]
changed: [stapp01]

PLAY RECAP **************************************************************************
stapp01 : ok=2    changed=1    unreachable=0    failed=0 ...
stapp02 : ok=2    changed=1    unreachable=0    failed=0 ...
stapp03 : ok=2    changed=1    unreachable=0    failed=0 ...


Deep Dive: Ansible Concepts Used

The file Module

This module manages file properties. * state: touch: Creates an empty file or updates timestamps. * mode: Sets permissions. Note that 0655 is unusual (Read/Write owner, Read/Execute group/others), but we must follow the task requirements exactly.

Dynamic Ownership with Variables

Instead of writing three separate tasks (one for tony, one for steve, etc.), we used the power of Ansible variables. * {{ ansible_user }}: This is a "magic variable" or connection variable defined in the inventory. * By setting owner: "{{ ansible_user }}", the playbook automatically adapts to whichever server it is currently running on.


Troubleshooting

Issue: "Permission Denied" * Cause: Writing to /opt requires root privileges. * Fix: Ensure become: true is present at the play level or task level.

Issue: "Invalid User" * Cause: If ansible_user is not defined in the inventory, the playbook will fail. * Fix: Check your inventory file to ensure ansible_user=... is correctly set for every host.

Issue: "Syntax Error" in YAML * Cause: Indentation issues. * Fix: Ensure file: is indented under tasks:, and properties like path: are indented under file:. YAML forbids tabs; use spaces.