Provision Users dynamically with variables
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
---
- 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
$