What is Ansible no_log?
no_log: true prevents Ansible from displaying task input and output in the console and logs. Use it whenever a task handles passwords, API keys, tokens, or any sensitive data that shouldn't appear in plain text.
Basic Usage
# Without no_log — password visible in output!
- name: Set user password
ansible.builtin.user:
name: deploy
password: "{{ vault_password | password_hash('sha512') }}"
# Output shows: "password": "$6$abc..."
# With no_log — output censored
- name: Set user password
ansible.builtin.user:
name: deploy
password: "{{ vault_password | password_hash('sha512') }}"
no_log: true
# Output shows: "censored": "the output has been hidden due to the fact that 'no_log: true' was set"
When to Use no_log
# ✅ Passwords
- name: Set database password
ansible.builtin.mysql_user:
name: app
password: "{{ db_password }}"
no_log: true
# ✅ API keys and tokens
- name: Call API with token
ansible.builtin.uri:
url: https://api.example.com/deploy
headers:
Authorization: "Bearer {{ api_token }}"
body_format: json
body:
version: "{{ app_version }}"
no_log: true
# ✅ Environment variables with secrets
- name: Run app with secrets
ansible.builtin.shell: /opt/myapp/start.sh
environment:
DB_PASSWORD: "{{ vault_db_password }}"
API_KEY: "{{ vault_api_key }}"
no_log: true
# ✅ Writing secrets to files
- name: Create .env file
ansible.builtin.copy:
content: |
SECRET_KEY={{ vault_secret_key }}
DB_URL=postgres://user:{{ vault_db_password }}@localhost/myapp
dest: /opt/myapp/.env
mode: "0600"
no_log: true
Conditional no_log
# Log in development, hide in production
- name: Deploy with credentials
ansible.builtin.uri:
url: "{{ deploy_url }}"
headers:
Authorization: "Bearer {{ deploy_token }}"
no_log: "{{ env == 'production' }}"
# Disable no_log for debugging
- name: Set password
ansible.builtin.user:
name: deploy
password: "{{ vault_password | password_hash('sha512') }}"
no_log: "{{ not debug_mode | default(true) }}"
no_log on Variables
# Mark variable as no_log at set_fact level
- name: Store secret
ansible.builtin.set_fact:
api_response: "{{ result.json }}"
no_log: true
# In vars
vars:
db_connection:
host: db.example.com
password: "{{ vault_db_pass }}"
For platform & security teams
Handling secrets across shared automation?
no_log reduces accidental output, but production automation also needs credential boundaries, Vault/controller integration, auditability, and repository controls.
Fixed-scope review · typically €1,500–€3,000 · prioritized findings and a remediation plan.
Block-Level no_log
# Apply to entire block
- block:
- name: Create service account
ansible.builtin.user:
name: svc_myapp
password: "{{ vault_svc_password | password_hash('sha512') }}"
- name: Write credentials
ansible.builtin.copy:
content: "{{ vault_credentials }}"
dest: /etc/myapp/credentials
mode: "0600"
- name: Configure API key
ansible.builtin.lineinfile:
path: /etc/myapp/config.yml
line: "api_key: {{ vault_api_key }}"
no_log: true
Debug with no_log
When no_log: true hides errors, temporarily disable it:
# Can't see what went wrong!
- name: API call
uri:
url: https://api.example.com
body: "{{ secret_payload }}"
no_log: true # Change to false to debug
# Or use environment variable
# ANSIBLE_NO_LOG=false ansible-playbook site.yml
What no_log Hides
| Hidden | Not Hidden |
|---|---|
| Task arguments (input) | Task name |
| Task output (stdout/stderr) | Host name |
| Registered variables | Changed/OK status |
| Loop items | Task duration |
| Callback plugin data | Play name |
TASK [Set password] ***************
ok: [web-01] => {"censored": "the output has been hidden due to the fact that 'no_log: true' was set", "changed": false}
Common Mistakes
Forgetting no_log on Debug
# ❌ BAD — exposes secret in output
- debug:
msg: "Password is {{ vault_password }}"
# ✅ GOOD — hide the debug output
- debug:
msg: "Password is {{ vault_password }}"
no_log: true
# ✅ BETTER — don't debug secrets at all
- debug:
msg: "Password has been set for {{ username }}"
Loop Items Visible
# ❌ Loop items shown even with registered var
- name: Create users
ansible.builtin.user:
name: "{{ item.name }}"
password: "{{ item.pass | password_hash('sha512') }}"
loop:
- { name: alice, pass: "{{ vault_alice_pass }}" }
- { name: bob, pass: "{{ vault_bob_pass }}" }
no_log: true # ← Must add this
Registered Result Leaks
# ❌ The register captures the secret
- name: Get API token
uri:
url: https://auth.example.com/token
body: "client_secret={{ vault_secret }}"
register: auth_result
no_log: true
# ❌ Then debug exposes it
- debug: var=auth_result # Shows the token!
# ✅ Only show non-sensitive parts
- debug:
msg: "Auth status: {{ auth_result.status }}"
ansible-lint Rule
ansible-lint warns when no_log is missing on tasks that appear to handle secrets:
WARNING no-log-password: task uses password without no_log
Fix: add no_log: true to any task with password parameters.
Related Articles
Conclusion
Use no_log: true on every task that handles passwords, tokens, API keys, or sensitive data. Apply it to blocks for groups of sensitive tasks. Use conditional no_log to enable logging in dev but hide in production. Remember that registered variables can leak secrets — don't debug them. Combine no_log with Ansible Vault for end-to-end secret protection. The rule is simple: if the output could contain a secret, add no_log: true.