AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible Tags: Run Specific Tasks and Roles Selectively (Guide)

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible tags. Run specific tasks with --tags, skip tasks with --skip-tags, tag roles and includes, use special tags (always, never).

Tags let you run or skip specific parts of a playbook. Instead of running everything, use --tags deploy to only run deployment tasks, or --skip-tags debug to skip debugging output. Essential for large playbooks and iterative development.

Basic Usage

Tag Tasks

tasks:
  - name: Install packages
    ansible.builtin.package:
      name: nginx
      state: present
    tags: install

- name: Deploy configuration ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf tags: configure

- name: Start service ansible.builtin.systemd: name: nginx state: started enabled: true tags: service

Run with Tags

# Run only install tasks
ansible-playbook site.yml --tags install

# Run install and configure tasks ansible-playbook site.yml --tags "install,configure"

# Skip service tasks ansible-playbook site.yml --skip-tags service

# List all tags in a playbook ansible-playbook site.yml --list-tags

# List tasks that would run ansible-playbook site.yml --tags deploy --list-tasks

See also: Ansible Playbook Structure: Anatomy, Best Practices & Examples (2026)

Multiple Tags Per Task

- name: Deploy app config
  ansible.builtin.template:
    src: app.conf.j2
    dest: /etc/app/config.yml
  tags:
    - configure
    - deploy
    - app

# Runs if ANY of its tags match --tags

Special Tags

always — Runs Unless Explicitly Skipped

- name: Gather facts (always runs)
  ansible.builtin.setup:
  tags: always

- name: Show deployment info (always runs) ansible.builtin.debug: msg: "Deploying to {{ inventory_hostname }}" tags: always

- name: Install packages (only with --tags install) ansible.builtin.package: name: nginx state: present tags: install

# "always" tasks run even with --tags install
ansible-playbook site.yml --tags install
# Runs: Gather facts + Show deployment info + Install packages

# Skip "always" tasks explicitly ansible-playbook site.yml --tags install --skip-tags always

never — Only Runs When Explicitly Requested

- name: Dangerous cleanup (never runs by default)
  ansible.builtin.file:
    path: /var/log/app
    state: absent
  tags:
    - never
    - cleanup

- name: Debug dump (never runs by default) ansible.builtin.debug: var: hostvars[inventory_hostname] tags: - never - debug

# Won't run unless you explicitly request it
ansible-playbook site.yml              # Does NOT run cleanup
ansible-playbook site.yml --tags cleanup  # DOES run cleanup

See also: Ansible Variable Precedence: Complete Order of Priority (2026)

Tag Roles

# Tag entire role
- hosts: webservers
  roles:
    - role: common
      tags: common
    - role: nginx
      tags:
        - nginx
        - webserver
    - role: app
      tags: app
# Only run the nginx role
ansible-playbook site.yml --tags nginx

Tag Includes and Imports

# Tags on import_tasks apply to ALL tasks in the file
- name: Import database tasks
  ansible.builtin.import_tasks: database.yml
  tags: database
  # Every task in database.yml gets the "database" tag

# Tags on include_tasks apply to the include itself - name: Include monitoring tasks ansible.builtin.include_tasks: monitoring.yml tags: monitoring # The include is tagged, but tasks inside keep their own tags

See also: Ansible block, rescue, always: Error Handling Complete Guide (2026)

Tag Blocks

- name: Database setup
  tags: database
  block:
    - name: Install PostgreSQL
      ansible.builtin.package:
        name: postgresql
        state: present

- name: Start PostgreSQL ansible.builtin.systemd: name: postgresql state: started

- name: Create database community.postgresql.postgresql_db: name: myapp

Real-World Tag Strategy

---
- hosts: all
  become: true

tasks: # Phase 1: Base system - name: Update apt cache ansible.builtin.apt: update_cache: true cache_valid_time: 3600 tags: [base, packages]

- name: Install base packages ansible.builtin.package: name: "{{ base_packages }}" state: present tags: [base, packages]

# Phase 2: Security - name: Configure firewall ansible.builtin.template: src: iptables.j2 dest: /etc/iptables/rules.v4 tags: [security, firewall] notify: reload firewall

- name: Configure SSH ansible.builtin.template: src: sshd_config.j2 dest: /etc/ssh/sshd_config tags: [security, ssh] notify: restart sshd

# Phase 3: Application - name: Deploy application ansible.builtin.git: repo: "{{ app_repo }}" dest: "{{ app_dir }}" version: "{{ app_version }}" tags: [deploy, app]

- name: Install dependencies ansible.builtin.pip: requirements: "{{ app_dir }}/requirements.txt" virtualenv: "{{ app_dir }}/venv" tags: [deploy, app, deps]

- name: Restart application ansible.builtin.systemd: name: myapp state: restarted tags: [deploy, app, restart]

# Diagnostics - name: Show system status ansible.builtin.command: systemctl status myapp tags: [never, status] changed_when: false

handlers: - name: reload firewall ansible.builtin.command: iptables-restore < /etc/iptables/rules.v4 - name: restart sshd ansible.builtin.systemd: name: sshd state: restarted

# Full run
ansible-playbook site.yml

# Just deploy the app ansible-playbook site.yml --tags deploy

# Security hardening only ansible-playbook site.yml --tags security

# Quick check on app status ansible-playbook site.yml --tags status

# Everything except firewall changes ansible-playbook site.yml --skip-tags firewall

FAQ

How do Ansible tags work?

Tags are labels on tasks. When you run --tags deploy, only tasks tagged deploy execute (plus always tasks). When you run --skip-tags debug, all tasks run except those tagged debug.

What is the difference between always and never tags?

always tasks run regardless of --tags filtering (unless explicitly skipped with --skip-tags always). never tasks never run unless explicitly requested with --tags .

Can a task have multiple tags?

Yes, use a list: tags: [deploy, app, v2]. The task runs if ANY of its tags match --tags. All tags must be in --skip-tags to skip it.

How do tags work with roles?

Tagging a role applies the tag to ALL tasks in that role. You can also tag individual tasks within a role normally. Both approaches work together.

Should I tag every task?

No — tag groups of related tasks for logical operations (deploy, configure, security). Over-tagging makes playbooks harder to read. Use tags for tasks you'll want to run independently.

Conclusion

--tags deploy — Run only tagged tasks • --skip-tags debug — Run everything except tagged tasks • always — Tasks that always run (gather facts, logging) • never — Tasks that only run on explicit request (cleanup, debug) • Tag roles and blocks — Apply tags to groups of tasks • --list-tags — See all available tags before running

Related Articles

Ansible Playbook Structure & Best PracticesAnsible import_tasks vs include_tasksAnsible Check Mode / Dry Run

See also

Ansible Tags: Run Specific Tasks in Playbooks (Complete Guide)

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home