Introduction
The no-log-password ansible-lint rule warns when tasks that handle passwords or secrets don't have no_log: true set. Without it, sensitive data appears in plaintext in Ansible's output, log files, and callback plugins — a security risk in CI/CD pipelines and shared terminals.
The Problem
# ⚠️ TRIGGERS no-log-password warning
- name: Create user accounts
ansible.builtin.user:
name: "{{ item.name }}"
password: "{{ item.password | password_hash('sha512') }}"
loop:
- { name: alice, password: secret123 }
- { name: bob, password: hunter2 }
Ansible output exposes the password in the loop item:
TASK [Create user accounts] **************************************************
changed: [web01] => (item={'name': 'alice', 'password': 'secret123'})
changed: [web01] => (item={'name': 'bob', 'password': 'hunter2'})
Lint output:
no-log-password: Tasks that set passwords should use no_log to prevent disclosure.
The Fix: Add no_log: true
- name: Create user accounts
ansible.builtin.user:
name: "{{ item.name }}"
password: "{{ item.password | password_hash('sha512') }}"
loop:
- { name: alice, password: "{{ vault_alice_password }}" }
- { name: bob, password: "{{ vault_bob_password }}" }
no_log: true
Now Ansible output shows:
TASK [Create user accounts] **************************************************
changed: [web01] => (item=CENSORED)
changed: [web01] => (item=CENSORED)
Modules That Trigger This Rule
The rule checks tasks using these parameters:
| Module | Parameter |
|---|---|
ansible.builtin.user | password |
ansible.builtin.lineinfile | line (when contains password) |
ansible.builtin.uri | body, url_password |
ansible.builtin.command / shell | Arguments containing secrets |
community.mysql.mysql_user | password |
community.postgresql.postgresql_user | password |
community.general.ldap_passwd | passwd |
Best Practices
1. Use Ansible Vault for Secrets
Never hardcode passwords. Store them encrypted:
# Create encrypted vars file
ansible-vault create group_vars/all/vault.yml
# group_vars/all/vault.yml (encrypted)
vault_alice_password: "SuperSecret123!"
vault_bob_password: "AnotherSecret456!"
vault_db_password: "DbP@ssw0rd"
Reference in playbooks:
- name: Create database user
community.mysql.mysql_user:
name: app_user
password: "{{ vault_db_password }}"
priv: "app_db.*:ALL"
no_log: true
2. Use no_log Conditionally for Debugging
- name: Create user
ansible.builtin.user:
name: deploy
password: "{{ vault_deploy_password | password_hash('sha512') }}"
no_log: "{{ not ansible_verbosity >= 3 }}"
This hides output normally but shows it with -vvv for debugging.
3. Use no_log at Block Level
- name: Secret operations
no_log: true
block:
- name: Set database password
community.mysql.mysql_user:
name: app
password: "{{ vault_db_password }}"
- name: Create API key file
ansible.builtin.copy:
content: "{{ vault_api_key }}"
dest: /etc/myapp/api.key
mode: '0600'
4. Register Variables Carefully
# ⚠️ Registered result may contain secrets
- name: Get secret from API
ansible.builtin.uri:
url: https://vault.example.com/v1/secret/data/myapp
headers:
X-Vault-Token: "{{ vault_token }}"
register: secret_response
no_log: true
# Safe — only access specific fields
- name: Use the secret
ansible.builtin.debug:
msg: "Secret retrieved successfully"
when: secret_response.status == 200
5. Environment Variables for CI/CD
- name: Deploy with credentials
ansible.builtin.shell: |
deploy --token "$DEPLOY_TOKEN"
environment:
DEPLOY_TOKEN: "{{ vault_deploy_token }}"
no_log: true
When NOT to Use no_log
Don't use no_log: true on every task — it makes debugging very difficult:
# DON'T — this has no secrets
- name: Install packages
ansible.builtin.yum:
name: nginx
no_log: true # Unnecessary, hides useful debug info
# DO — only on tasks with actual secrets
- name: Configure nginx password
ansible.builtin.htpasswd:
path: /etc/nginx/.htpasswd
name: admin
password: "{{ vault_admin_password }}"
no_log: true
Suppressing the Rule
If you've verified no real secret is exposed:
- name: Task with false positive
ansible.builtin.user:
name: testuser
password: "!" # Locked account, not a real password
no_log: false # noqa: no-log-password
Related Articles
- Ansible Vault Guide
- Ansible-Lint Guide
- Ansible Best Practices Guide
- no_log Deep Dive
- Ansible Configuration Settings
Conclusion
Add no_log: true to any task that handles passwords, API keys, or tokens. Store secrets in Ansible Vault — never hardcode them. Use no_log at block level for groups of sensitive tasks, and use conditional no_log (not ansible_verbosity >= 3) when you need debugging capability. Only suppress the lint rule when you've verified no real secrets are exposed.