# ansible / provisioning / users

Provision Users & Workspaces from scratch

A foundational playbook that installs prerequisites, provisions a new system user, scaffolds their home directory, and safely seeds it with configuration files in a single pass.

$ tree /home/ai
Output/home/ai
├── shan
│   └── welcome.txt
└── update.yml
tree
package
ai
user
5 tasks
playbook
# overview

Why this playbook holds up

When onboarding new services or users, manual folder creation and permission setting frequently leads to "Access Denied" errors down the road. This playbook locks down the configuration as code, guaranteeing the environment is built perfectly every time.

permissions

Strict Ownership

Every file and directory explicitly defines owner, group, and mode, ensuring the new user has exact access without relying on default umasks.

predictable

Idempotent Scaffolding

If the user or files already exist, Ansible simply verifies their permissions rather than overwriting or duplicating them, preventing accidental data loss.

# playbook

The full task list

setup_env.ymlYAML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
---
- name: Install package and setup user environment
  hosts: localhost
  become: yes
  tasks:
    - name: Install tree
      apt:
        name: tree
        state: present

    - name: Create user
      user:
        name: ai
        state: present
        create_home: yes
        shell: /bin/bash

    - name: Create directory
      file:
        path: /home/ai/shan
        state: directory
        owner: ai
        group: ai
        mode: '0755'

    - name: Create file
      file:
        path: /home/ai/shan/welcome.txt
        state: touch
        mode: '0644'

    - name: Copy file
      copy:
        src: /home/ak/Downloads/update.yml
        dest: /home/ai/update.yml
        owner: ai
        group: ai
        mode: '0644'

Run order

  • package

    Installs the tree command-line utility via the APT package manager.

    apt
  • identity

    Provisions the ai user, generates their home directory, and assigns bash as their shell.

    user
  • scaffold

    Creates a nested directory (shan) and touches an empty placeholder file inside it.

    file
  • seed

    Copies a playbook from the host's download folder into the new user's environment.

    copy
# verify

Check the user environment

To ensure the playbook executed correctly, you can verify the user's existence and use the newly installed tree package to inspect the file hierarchy and permissions.

terminal
$ id ai
uid=1001(ai) gid=1001(ai) groups=1001(ai)
 
$ su - ai -c "tree -p ~"
/home/ai
├── [drwxr-xr-x] shan
│   └── [-rw-r--r--] welcome.txt
└── [-rw-r--r--] update.yml
 
1 directory, 2 files
 
$
# notes

Lessons from running this in production

WARN

YAML indentation is strict! Your original copy task had misaligned spacing on the src and dest lines. I have fixed it in this generated playbook to ensure it runs without errors.

INFO

Using state: touch with the file module works identically to the Linux touch command: it creates an empty file if it doesn't exist, but only updates the timestamp if it does.

OK

Declaring owner and group on the copy module is a great best practice to prevent files copied by root from becoming unreadable to the destination user.