Introduction

RabbitMQ is the most widely deployed open-source message broker, supporting AMQP, MQTT, and STOMP protocols. Ansible's community.rabbitmq collection provides modules for managing every aspect — installation, clustering, virtual hosts, users, permissions, exchanges, queues, policies, and plugins. This guide covers single-node through production clustered deployments.

Prerequisites

ansible-galaxy collection install community.rabbitmq

Install RabbitMQ

---
- name: Deploy RabbitMQ
  hosts: rabbitmq_servers
  become: true
  vars:
    rabbitmq_admin_user: admin
    rabbitmq_admin_password: "{{ vault_rabbitmq_admin_password }}"
  tasks:
    - name: Install Erlang and RabbitMQ (Debian)
      block:
        - name: Add RabbitMQ signing key
          ansible.builtin.apt_key:
            url: https://github.com/rabbitmq/signing-keys/releases/download/3.0/rabbitmq-release-signing-key.asc
            state: present

        - name: Add Erlang repository
          ansible.builtin.apt_repository:
            repo: "deb https://ppa1.novemberain.com/rabbitmq/rabbitmq-erlang/deb/ubuntu {{ ansible_distribution_release }} main"
            filename: erlang
            state: present

        - name: Add RabbitMQ repository
          ansible.builtin.apt_repository:
            repo: "deb https://ppa1.novemberain.com/rabbitmq/rabbitmq-server/deb/ubuntu {{ ansible_distribution_release }} main"
            filename: rabbitmq
            state: present

        - name: Install packages
          ansible.builtin.apt:
            name:
              - erlang-base
              - erlang-nox
              - rabbitmq-server
            state: present
      when: ansible_os_family == 'Debian'

    - name: Start RabbitMQ
      ansible.builtin.service:
        name: rabbitmq-server
        state: started
        enabled: true

    - name: Enable management plugin
      community.rabbitmq.rabbitmq_plugin:
        names: rabbitmq_management
        state: enabled
      notify: restart rabbitmq

    - name: Create admin user
      community.rabbitmq.rabbitmq_user:
        user: "{{ rabbitmq_admin_user }}"
        password: "{{ rabbitmq_admin_password }}"
        tags: administrator
        permissions:
          - vhost: /
            configure_priv: .*
            read_priv: .*
            write_priv: .*
        state: present

    - name: Remove default guest user
      community.rabbitmq.rabbitmq_user:
        user: guest
        state: absent

  handlers:
    - name: restart rabbitmq
      ansible.builtin.service:
        name: rabbitmq-server
        state: restarted

Virtual Hosts and Users

- name: Create virtual hosts
  community.rabbitmq.rabbitmq_vhost:
    name: "{{ item }}"
    state: present
  loop:
    - production
    - staging
    - monitoring

- name: Create application users
  community.rabbitmq.rabbitmq_user:
    user: "{{ item.name }}"
    password: "{{ item.password }}"
    tags: "{{ item.tags | default('') }}"
    permissions:
      - vhost: "{{ item.vhost }}"
        configure_priv: "{{ item.configure | default('') }}"
        read_priv: "{{ item.read | default('.*') }}"
        write_priv: "{{ item.write | default('.*') }}"
    state: present
  loop:
    - name: webapp
      password: "{{ vault_rabbitmq_webapp_password }}"
      vhost: production
      configure: "^webapp\\."
      read: ".*"
      write: "^webapp\\."
    - name: worker
      password: "{{ vault_rabbitmq_worker_password }}"
      vhost: production
      configure: ""
      read: "^(webapp\\.|tasks\\.)"
      write: "^tasks\\."
    - name: monitor
      password: "{{ vault_rabbitmq_monitor_password }}"
      vhost: production
      tags: monitoring
      configure: ""
      read: ".*"
      write: ""
  no_log: true

Exchanges and Queues

- name: Declare exchanges
  community.rabbitmq.rabbitmq_exchange:
    name: "{{ item.name }}"
    type: "{{ item.type }}"
    vhost: production
    durable: true
    login_user: "{{ rabbitmq_admin_user }}"
    login_password: "{{ rabbitmq_admin_password }}"
  loop:
    - { name: events, type: topic }
    - { name: tasks, type: direct }
    - { name: notifications, type: fanout }
    - { name: dlx, type: direct }

- name: Declare queues
  community.rabbitmq.rabbitmq_queue:
    name: "{{ item.name }}"
    vhost: production
    durable: true
    arguments: "{{ item.args | default({}) }}"
    login_user: "{{ rabbitmq_admin_user }}"
    login_password: "{{ rabbitmq_admin_password }}"
  loop:
    - name: tasks.email
      args:
        x-dead-letter-exchange: dlx
        x-dead-letter-routing-key: dead.email
        x-message-ttl: 86400000
    - name: tasks.process
      args:
        x-dead-letter-exchange: dlx
        x-max-length: 100000
    - name: dead.letters
      args: {}

- name: Bind queues to exchanges
  community.rabbitmq.rabbitmq_binding:
    name: tasks
    destination: "{{ item.queue }}"
    destination_type: queue
    routing_key: "{{ item.key }}"
    vhost: production
    login_user: "{{ rabbitmq_admin_user }}"
    login_password: "{{ rabbitmq_admin_password }}"
  loop:
    - { queue: tasks.email, key: email }
    - { queue: tasks.process, key: process }

Clustering

---
- name: Configure RabbitMQ cluster
  hosts: rabbitmq_servers
  become: true
  vars:
    rabbitmq_erlang_cookie: "{{ vault_erlang_cookie }}"
    rabbitmq_cluster_master: "{{ groups['rabbitmq_servers'][0] }}"
  tasks:
    - name: Set Erlang cookie
      ansible.builtin.copy:
        content: "{{ rabbitmq_erlang_cookie }}"
        dest: /var/lib/rabbitmq/.erlang.cookie
        mode: '0400'
        owner: rabbitmq
        group: rabbitmq
      notify: restart rabbitmq

    - name: Set cluster node name
      ansible.builtin.lineinfile:
        path: /etc/rabbitmq/rabbitmq-env.conf
        line: "NODENAME=rabbit@{{ inventory_hostname }}"
        create: true
        mode: '0644'
      notify: restart rabbitmq

    - name: Flush handlers
      ansible.builtin.meta: flush_handlers

    - name: Join cluster (non-master nodes)
      when: inventory_hostname != rabbitmq_cluster_master
      block:
        - name: Stop app
          ansible.builtin.command: rabbitmqctl stop_app

        - name: Reset node
          ansible.builtin.command: rabbitmqctl reset

        - name: Join cluster
          ansible.builtin.command: >
            rabbitmqctl join_cluster rabbit@{{ rabbitmq_cluster_master }}
          register: join_result
          changed_when: "'already_member' not in join_result.stderr"

        - name: Start app
          ansible.builtin.command: rabbitmqctl start_app

Policies

- name: Configure HA policy (quorum queues)
  community.rabbitmq.rabbitmq_policy:
    name: ha-all
    vhost: production
    pattern: ".*"
    tags:
      ha-mode: all
      ha-sync-mode: automatic
    apply_to: queues
    login_user: "{{ rabbitmq_admin_user }}"
    login_password: "{{ rabbitmq_admin_password }}"

- name: Configure message TTL policy
  community.rabbitmq.rabbitmq_policy:
    name: ttl-24h
    vhost: production
    pattern: "^tasks\\."
    tags:
      message-ttl: 86400000
      max-length: 500000
    apply_to: queues
    login_user: "{{ rabbitmq_admin_user }}"
    login_password: "{{ rabbitmq_admin_password }}"

TLS Configuration

- name: Configure RabbitMQ TLS
  ansible.builtin.template:
    src: rabbitmq.conf.j2
    dest: /etc/rabbitmq/rabbitmq.conf
    mode: '0644'
  notify: restart rabbitmq
# templates/rabbitmq.conf.j2
listeners.ssl.default = 5671
ssl_options.cacertfile = /etc/rabbitmq/tls/ca.crt
ssl_options.certfile = /etc/rabbitmq/tls/server.crt
ssl_options.keyfile = /etc/rabbitmq/tls/server.key
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = false

# Management TLS
management.ssl.port = 15671
management.ssl.cacertfile = /etc/rabbitmq/tls/ca.crt
management.ssl.certfile = /etc/rabbitmq/tls/server.crt
management.ssl.keyfile = /etc/rabbitmq/tls/server.key

# Disable non-TLS listeners (production)
# listeners.tcp = none

Monitoring

- name: Enable Prometheus plugin
  community.rabbitmq.rabbitmq_plugin:
    names: rabbitmq_prometheus
    state: enabled
  notify: restart rabbitmq

# Prometheus scrape config:
# - job_name: rabbitmq
#   static_configs:
#     - targets: ['rabbitmq01:15692']

Health Check

- name: RabbitMQ health check
  ansible.builtin.command: rabbitmq-diagnostics check_running
  register: rmq_health
  changed_when: false
  failed_when: rmq_health.rc != 0

- name: Check cluster status
  ansible.builtin.command: rabbitmqctl cluster_status
  register: cluster_status
  changed_when: false
  run_once: true

- name: Check queue depths
  ansible.builtin.uri:
    url: "http://localhost:15672/api/queues/production"
    user: "{{ rabbitmq_admin_user }}"
    password: "{{ rabbitmq_admin_password }}"
    force_basic_auth: true
  register: queues

- name: Alert on deep queues
  ansible.builtin.debug:
    msg: "WARNING: {{ item.name }} has {{ item.messages }} messages"
  loop: "{{ queues.json }}"
  when: item.messages | default(0) > 10000

Troubleshooting

Cluster Partition

- name: Check for partitions
  ansible.builtin.command: rabbitmqctl cluster_status --formatter json
  register: status
  changed_when: false

# Set partition handling in rabbitmq.conf:
# cluster_partition_handling = autoheal

Memory Alarm

- name: Set memory high watermark
  ansible.builtin.lineinfile:
    path: /etc/rabbitmq/rabbitmq.conf
    line: "vm_memory_high_watermark.relative = 0.6"
    regexp: "^vm_memory_high_watermark"
  notify: restart rabbitmq

Conclusion

Ansible's community.rabbitmq collection manages the full RabbitMQ lifecycle — installation, clustering with shared Erlang cookies, virtual hosts for multi-tenancy, users with fine-grained permissions, exchanges and queues with dead-letter routing, HA policies, and TLS encryption. Use quorum queues for durability, Prometheus for monitoring, and policies for automatic message lifecycle management. All configuration is declarative and idempotent.