Task

Provision Users dynamically with variables

Ansible · 10 min · Practical

A clean example of making playbooks reusable. Instead of hardcoding names and paths, this playbook uses Jinja2 variables to define the user and target directory, making it highly adaptable for future runs.

Why variables matter

Hardcoding values directly into tasks creates rigid, fragile playbooks. By lifting the data into a vars block, the logic becomes a template. You can now use this exact same file to provision 50 different users just by overriding the variables.

Write Once, Run Anywhere

Need to create a different user? You don't have to rewrite the tasks. Just update the vars dictionary or pass them at runtime using the CLI.

Eliminate Typos

Because the directory path, owner, and group all reference the exact same {{ username }} variable, it is impossible for them to mismatch.

The full task list

dynamic_user.yml
---
- name: create user with variable
  hosts: localhost
  become: yes
  vars:
    username: shannn
    dirname: avalothan
  tasks:
    - name: user with variable
      user:
        name: "{{ username }}"
        state: present
        create_home: yes

    - name: create directory
      file:
        path: "/home/{{ username }}/{{ dirname }}"
        state: directory
        owner: "{{ username }}"
        group: "{{ username }}"
        mode: '0755'

Run order

  • define Declares the variables at the play level, making them available to all subsequent tasks.

    vars

  • identity Creates the system user, relying on Jinja2 templating to inject the name.

    user

  • scaffold Constructs the full directory path dynamically by concatenating variables and static text.

    file

Check the templated output

To ensure the variables evaluated correctly, you can check both the user's system record and the directory ownership properties.

terminal

$ id shannn
uid=1002(shannn) gid=1002(shannn) groups=1002(shannn)

$ ls -la /home/shannn
total 12
drwxr-x--- 3 shannn shannn 4096 Jul  8 19:16 .
drwxr-xr-x 5 root   root   4096 Jul  8 19:16 ..
drwxr-xr-x 2 shannn shannn 4096 Jul  8 19:16 avalothan

$

Lessons from running this in production