Ansible skip_tags — Exclude Tasks When Running Playbooks
Introduction
--skip-tags lets you exclude tagged tasks from a playbook run without modifying the playbook. Skip slow tests in dev, bypass database tasks during frontend deploys, or exclude destructive operations in check mode. Combined with --tags, it gives fine-grained control over what executes.
Quick Reference
# Skip tasks tagged "slow"
ansible-playbook site.yml --skip-tags slow
# Skip multiple tags
ansible-playbook site.yml --skip-tags "tests,monitoring,backup"
# Run only "deploy" but skip "notifications"
ansible-playbook site.yml --tags deploy --skip-tags notifications
Basic Usage
---
- name: Full deployment
hosts: webservers
tasks:
- name: Install packages
ansible.builtin.apt:
name: nginx
state: present
tags: install
- name: Deploy application
ansible.builtin.copy:
src: app.tar.gz
dest: /opt/app/
tags: deploy
- name: Run database migration
ansible.builtin.command: /opt/app/migrate.sh
tags: [deploy, database]
- name: Run integration tests
ansible.builtin.command: /opt/app/test.sh
tags: tests
- name: Send Slack notification
community.general.slack:
token: "{{ slack_token }}"
msg: "Deployed to {{ inventory_hostname }}"
tags: notifications
- name: Create backup
ansible.builtin.command: /opt/scripts/backup.sh
tags: backup
# Deploy without running tests or notifications
ansible-playbook site.yml --skip-tags "tests,notifications"
# Everything except database migration
ansible-playbook site.yml --skip-tags database
# Only deploy, skip backup
ansible-playbook site.yml --tags deploy --skip-tags backup
Tag Inheritance
---
- name: Web deployment
hosts: webservers
tags: web # All tasks inherit this tag
tasks:
- name: Task 1
ansible.builtin.debug:
msg: "This has tag: web"
- name: Task 2
ansible.builtin.debug:
msg: "This has tags: web, extra"
tags: extra
# Block-level tags
- block:
- name: Block task 1
ansible.builtin.debug:
msg: "Has: web, database"
- name: Block task 2
ansible.builtin.debug:
msg: "Has: web, database"
tags: database
# Skip entire play
ansible-playbook site.yml --skip-tags web
# Skip just the database block
ansible-playbook site.yml --skip-tags database
Special Tags
- name: Always runs (cannot be skipped with --skip-tags)
ansible.builtin.debug:
msg: "I always run"
tags: always
- name: Never runs unless explicitly --tags never
ansible.builtin.debug:
msg: "I never run by default"
tags: never
# "always" tag runs even when skipped... unless explicitly skipped:
ansible-playbook site.yml --skip-tags always # This DOES skip "always" tasks
# "never" tasks only run with explicit --tags
ansible-playbook site.yml --tags never,deploy
Role Tags
---
- name: Full stack
hosts: all
roles:
- role: common
tags: common
- role: nginx
tags: [web, nginx]
- role: postgresql
tags: [database, postgresql]
- role: monitoring
tags: monitoring
# Deploy without monitoring setup
ansible-playbook site.yml --skip-tags monitoring
# Skip database role entirely
ansible-playbook site.yml --skip-tags database
Common Patterns
Development vs Production
- name: Run security hardening
ansible.builtin.include_role:
name: hardening
tags: [security, production_only]
- name: Install debug tools
ansible.builtin.apt:
name: [strace, tcpdump, htop]
state: present
tags: [debug, dev_only]
# Production: skip dev tools
ansible-playbook site.yml --skip-tags dev_only
# Development: skip hardening
ansible-playbook site.yml --skip-tags production_only
Destructive Operations
- name: Drop and recreate database
community.postgresql.postgresql_db:
name: myapp
state: absent
tags: [database, destructive]
- name: Wipe old deployments
ansible.builtin.file:
path: /opt/old-releases
state: absent
tags: [cleanup, destructive]
# Safe run — skip anything destructive
ansible-playbook site.yml --skip-tags destructive
CI/CD Pipeline
# CI: Fast deploy, skip slow operations
ansible-playbook site.yml --skip-tags "tests,backup,monitoring"
# Nightly: Full run with tests
ansible-playbook site.yml
# Hotfix: Only deploy, skip everything else
ansible-playbook site.yml --tags deploy --skip-tags "tests,notifications"
List Available Tags
# See all tags in a playbook
ansible-playbook site.yml --list-tags
# Output:
# playbook: site.yml
# play #1 (webservers): Full deployment TAGS: []
# TASK TAGS: [backup, database, deploy, install, monitoring, notifications, tests]
ansible.cfg Default Skip Tags
# ansible.cfg — always skip these tags
[tags]
skip = slow,experimental
Troubleshooting
| Issue | Solution |
|---|---|
| Task runs despite skip-tags | Check if task has tags: always |
| Entire play skipped | Play-level tag matches skip-tags |
| Handler not triggered | Handler's tag is skipped, or notifying task was skipped |
--skip-tags and --tags conflict | --skip-tags wins — if a task matches both, it's skipped |
Best Practices
- Tag by function —
install,deploy,configure,test,backup - Tag destructive tasks — easy to skip in dry runs
- Use
alwayssparingly — only for truly mandatory tasks (facts gathering) - Document your tags — teammates need to know what to skip
- Don't over-tag — every task doesn't need 5 tags
- CI/CD profiles — define standard skip-tag sets for different pipeline stages
Conclusion
Use --skip-tags to exclude tasks without editing playbooks. Tag by function (deploy, test, backup, destructive) and skip what you don't need per run. Combine with --tags for precise control. In CI/CD, define tag profiles for fast deploys vs full runs. Document available tags with --list-tags.