Run Tasks As Another User
on this page
Use this guide when you need tasks to execute under a specific user identity — for example, configuring a kiosk account’s profile, writing to a user’s APPDATA, or running a command that checks user-scoped registry values.
Prerequisites
- A working playbook and target connection
- The account used for your transport (WinRM or SSH) must have permission to create local users and to execute commands as other users
- For Windows
become: the target user must have a password
Overview
The typical pattern has two phases:
- Create the user account using the
usermodule, running as your transport account. - Add
becometo tasks that must run in that user’s context.
1. Store The Password As A Secret
Avoid hardcoding passwords. Use a named secret reference instead:
preflight secret encrypt exhibit-passwordSee Manage secrets if you have not set up age secrets yet.
2. Provision The User Account
Run a task as your normal transport account to create the user:
tasks:
- name: Create exhibit user
user:
name: exhibit
password: secret:exhibit-password
groups:
- Users
ensure: presentThis task runs as the account your WinRM or SSH transport authenticates with — it does not need become.
3. Configure Autologin (Optional)
If this is a kiosk that should boot directly into the exhibit account:
- name: Configure autologin
uses: preflight/autologin
with:
username: exhibit
password: secret:exhibit-password4. Run Tasks As The New User
Add a become block to any task that must execute under the exhibit account’s identity. On Windows, become uses runas by default:
- name: Set user environment variable
become:
user: exhibit
password: secret:exhibit-password
environment:
name: EXHIBIT_MODE
value: "kiosk"
scope: user
ensure: present
- name: Write user-scoped registry value
become:
user: exhibit
password: secret:exhibit-password
registry:
path: 'HKCU:\Software\ExhibitApp'
values:
StartFullscreen: "1"
ensure: presentbecome is task execution metadata — it does not change the module’s params, only the identity the task runs under.
This is also the recommended way to apply current-user stdlib actions to a kiosk or exhibit account when the action does not expose a user input, or when you need every task in the action to run under that Windows identity.
For preflight/windows-shell, preflight/windows-input, preflight/windows-power, and preflight/debloat, you can set with.user when you only need the action’s supported user-scoped registry settings and do not want to switch the task process identity. The target user’s profile hive must already be loaded, such as while that user is signed in or by running with become.load_profile.
- name: Configure supported shell defaults for exhibit user
uses: preflight/windows-shell
with:
user: exhibit
theme_mode: dark
taskbar_auto_hide: trueSome shell-facing changes persist immediately in the user’s profile but only become visible after sign-out, Explorer restart, or reboot.
5. Use Playbook Defaults To Avoid Repetition
When most tasks in a playbook should run as the exhibit user, set defaults.become at the playbook level:
name: configure-exhibit-user
defaults:
become:
user: exhibit
password: secret:exhibit-password
tasks:
- name: Set environment variable
environment:
name: EXHIBIT_MODE
value: "kiosk"
scope: user
ensure: present
- name: Write registry value
registry:
path: 'HKCU:\Software\ExhibitApp'
values:
StartFullscreen: "1"
ensure: present
- name: Create exhibit user
become:
enabled: false
user:
name: exhibit
password: secret:exhibit-password
ensure: presentThe last task uses enabled: false to run as the transport account instead of inheriting the default become.
6. Load The User Profile
By default, Windows become does not load the user’s full profile (environment variables, APPDATA, USERPROFILE, etc.). Set load_profile: true when the task needs those values:
- name: Configure user shell settings
become:
user: exhibit
password: secret:exhibit-password
load_profile: true
powershell:
script: |
$appData = $env:APPDATA
New-Item -ItemType Directory -Path "$appData\ExhibitApp" -Force | Out-NullTroubleshooting
become: password is required for Windows user
Windows runas requires a password. Make sure password is set and the
secret is configured in the project:
preflight secret listIf the secret exists but holds the wrong value, update it with
preflight secret edit exhibit-password.
become is not taking effect
Check that the task does not have enabled: false and that it is not overriding an inherited default with an empty block. A become: key without user: is an error.
POSIX: Become To Root From An Unprivileged SSH User
On POSIX targets the recommended posture is the reverse of Windows: connect over SSH as an unprivileged user and escalate per task with become. Allowing root SSH login is a stated working alternative (it passes the requires_root check with no become), but an unprivileged session plus become is the default recommendation.
A bare become: {enabled: true} means root on POSIX — you do not need to name user: root.
Password-first: the host-var sudo password pattern
The documented primary path supplies become.password from a secret: reference. Put the become default in the playbook and the per-host sudo password in ordinary host/group vars — Preflight resolves secret: refs in become.password right before execution:
# playbooks/manage-hosts.yml
name: manage-hosts
defaults:
become:
enabled: true # bare become means root on POSIX
password: "{{ sudo_password }}"
tasks:
- name: ensure a package is present
system_package:
packages:
- name: htop
ensure: present# preflight.yml — the sudo password is a per-host secret
inventory:
hosts:
- name: web-01
address: [IP_ADDRESS]
transport: ssh
username: deploy # unprivileged SSH user
password: secret:deploy-password
vars:
sudo_password: secret:deploy-sudo-passwordThe same shape works at the group level — put sudo_password in the group’s vars: and every host in the group inherits it.
NOPASSWD fallback
If a host’s sudoers is configured with NOPASSWD for the SSH user, omit become.password entirely. Preflight runs sudo -n, which fails fast with a sudo-password-required reason code if a password turns out to be required, so a misconfigured NOPASSWD never hangs the run.
requires_root modules
service, user, system_package, and reboot require an effective root user. Preflight probes id -u once per target and fails such a task before Check() with a requires-root-violation reason code when the effective user is not root. Setting become: {enabled: true} (root) or connecting as root satisfies the check; become-to-a-non-root-user is caught by the same check.
Related Docs
- Playbook and action YAML reference — full
becomefield reference - How
becomeworks — mechanics, method selection, inheritance - Manage secrets — store and resolve credentials
- Built-in module reference —
usermodule