Deploying Wazuh

The Wazuh Ansible repository provides playbooks and roles for installing Wazuh central components and agents. Clone the repository into the Ansible roles directory at /etc/ansible/roles.

Run the following commands on the Ansible server:

# mkdir -p /etc/ansible/roles
# cd /etc/ansible/roles/
# git clone --branch v5.0.0-beta2 https://github.com/wazuh/wazuh-ansible.git
# cd wazuh-ansible
# ansible-galaxy install -r requirements.yml

The following section describes how to use Ansible to install the Wazuh central components and Wazuh agent in your environment:

Installing the Wazuh central components

The Wazuh central components include the Wazuh indexer, Wazuh dashboard, and Wazuh manager. You can deploy these components with Ansible using predefined playbooks or roles, depending on your desired architecture.

The following sections explain how to deploy the Wazuh central components based on the deployment option:

All-in-one deployment

The all-in-one deployment installs the Wazuh indexer, Wazuh dashboard, and Wazuh manager on a single endpoint. You can use predefined playbooks from the Wazuh Ansible repository to deploy these components. Ensure the Ansible control server has SSH access to this endpoint.

Perform the following to deploy the Wazuh manager, indexer, and dashboard:

Access the wazuh-ansible directory

  1. Change to the directory where you cloned the Wazuh Ansible repository and list available roles:

    # cd /etc/ansible/roles/wazuh-ansible/
    # tree roles -d
    
    roles
    ├── package-urls
    │   ├── defaults
    │   └── tasks
    ├── vars
    ├── wazuh-agent
    │   ├── defaults
    │   └── tasks
    ├── wazuh-dashboard
    │   ├── defaults
    │   └── tasks
    ├── wazuh-indexer
    │   ├── defaults
    │   └── tasks
    └── wazuh-manager
        ├── defaults
        └── tasks
    17 directories
    
  2. Run the command below to see the preconfigured playbooks:

    # ls
    
    CHANGELOG.md  LICENSE  README.md  SECURITY.md  VERSION.json  docs  requirements.yml  roles  tools  wazuh-agent.yml  wazuh-aio.yml  wazuh-distributed.yml
    

    The Wazuh manager, dashboard, and indexer roles are used to install and configure the Wazuh manager, dashboard, and indexer components. See below the content of the playbook /etc/ansible/roles/wazuh-ansible/wazuh-aio.yml:

    ---
    
    - name: Wazuh All-in-One Deployment
      hosts: aio
      become: true
      roles:
        - role: package-urls
        - role: wazuh-indexer
        - role: wazuh-manager
        - role: wazuh-dashboard
      vars:
        single_node: true
    

    Where:

    • hosts: indicates the endpoints where the commands of the playbook will be executed.

    • roles: indicates the roles that will be executed on the hosts.

Prepare the playbook

The wazuh-aio.yml file allows you to deploy an all-in-one Wazuh environment. Add the public and private IP addresses of the endpoint where the Wazuh components will be installed to the /etc/ansible/hosts Ansible hosts file.

The contents of the Ansible host file below:

[aio]
aio_node ansible_host=<AIO_PUBLIC_IP> private_ip=<AIO_PRIVATE_IP>

[aio:vars]
ansible_user=<USERNAME>
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ansible_ssh_private_key_file=<PATH_TO_PIVATE_KEY>.pem

Where:

  • ansible_host specifies the public IP address or hostname Ansible uses to connect to the all-in-one node. Replace <AIO_PUBLIC_IP> with the actual public IP address or hostname of the endpoint that hosts the Wazuh central components.

  • private_ip specifies the private IP address used for internal communication between the Wazuh components deployed on the AIO node. Replace <AIO_PRIVATE_IP> with the actual private IP address assigned to the endpoint.

  • If the environment is located in a local subnet, ansible_host and private_ip variables should match.

  • ansible_user specifies the remote user account Ansible uses to connect over SSH. Replace <USERNAME> with a valid user account that has the required privileges on the endpoints.

  • ansible_ssh_private_key_file specifies the SSH private key used by Ansible to connect to the target hosts. Replace <PATH_TO_PRIVATE_KEY> with the directory path where the private key file is stored on the Ansible control node.

Run the playbook

  1. Run the command below from the playbook directory on the Ansible server:

    # ansible-playbook wazuh-aio.yml -e "source=prerelease"
    
  2. Check the status of the Wazuh indexer, dashboard, and manager services.

    • Wazuh indexer:

      # systemctl status wazuh-indexer
      
    • Wazuh dashboard:

      # systemctl status wazuh-dashboard
      
    • Wazuh manager:

      # systemctl status wazuh-manager
      

Note

The Wazuh dashboard can be accessed by visiting https://<AIO_PUBLIC_IP>

The default credentials are:

  • Username: admin

  • Password: admin

Wazuh cluster deployment

A Wazuh cluster is a distributed deployment where multiple Wazuh manager and indexer nodes work together to provide horizontal scalability, performance, and high availability. In a clustered setup, data and workloads are shared across nodes, ensuring redundancy and load balancing.

You can deploy a Wazuh cluster using Ansible playbooks from the Wazuh Ansible repository.

To install a Wazuh cluster, perform the following steps:

Access the wazuh-ansible directory

Change to the directory where you cloned the Wazuh Ansible repository and list available playbooks:

# cd /etc/ansible/roles/wazuh-ansible/
# tree roles -d
roles
├── package-urls
│   ├── defaults
│   └── tasks
├── vars
├── wazuh-agent
│   ├── defaults
│   └── tasks
├── wazuh-dashboard
│   ├── defaults
│   └── tasks
├── wazuh-indexer
│   ├── defaults
│   └── tasks
└── wazuh-manager
    ├── defaults
    └── tasks

You can see the preconfigured playbooks by running the command below:

# ls
CHANGELOG.md  docs  LICENSE  README.md  requirements.yml  roles  SECURITY.md  tools  VERSION.json  wazuh-agent.yml  wazuh-aio.yml  wazuh-distributed.yml

Using the wazuh-distributed.yml playbook, we deploy a Wazuh manager and indexer cluster using Ansible. Below is the content of the /etc/ansible/roles/wazuh-ansible/wazuh-distributed.yml file:

# cat wazuh-distributed.yml
---

- name: Configure package URLs
  hosts: localhost
  roles:
    - role: package-urls
  run_once: true
  become: false

- name: Configure Wazuh Indexer cluster
  hosts: wi_cluster
  roles:
    - role: wazuh-indexer
  become: true
  vars:
    # generate_certs: false                    # Set to false if you are using your own certificates
    instances:
      wi1:                                     # Must be same as inventory hostname
        name: node-1
        ip: "{{ hostvars.wi1.private_ip }}"
        role: indexer
      wi2:
        name: node-2
        ip: "{{ hostvars.wi2.private_ip }}"
        role: indexer
      wi3:
        name: node-3
        ip: "{{ hostvars.wi3.private_ip }}"
        role: indexer
      manager:
        name: node-4
        ip: "{{ hostvars.manager.private_ip }}"
        role: manager
        node_type: master
      worker:
        name: node-5
        ip: "{{ hostvars.worker.private_ip }}"
        role: manager
        node_type: worker
      dashboard:
        name: node-6
        ip: "{{ hostvars.dashboard.private_ip }}"
        role: dashboard

- name: Configure Wazuh Manager
  hosts: manager
  roles:
    - role: wazuh-manager
  become: true
  vars:
    node_type: "master"
    manager_node_name: "node-4"
    wazuh_indexer_hosts:
      - host: "{{ hostvars.wi1.private_ip }}"
        port: 9200
      - host: "{{ hostvars.wi2.private_ip }}"
        port: 9200
      - host: "{{ hostvars.wi3.private_ip }}"
        port: 9200

- name: Configure Wazuh Worker
  hosts: worker
  roles:
    - role: wazuh-manager
  become: true
  vars:
    node_type: "worker"
    manager_node_name: "node-5"
    wazuh_indexer_hosts:
      - host: "{{ hostvars.wi1.private_ip }}"
        port: 9200
      - host: "{{ hostvars.wi2.private_ip }}"
        port: 9200
      - host: "{{ hostvars.wi3.private_ip }}"
        port: 9200

- name: Configure Wazuh Dashboard
  hosts: dashboard
  roles:
    - role: wazuh-dashboard
  become: true
  vars:
    dashboard_node_name: "node-6"
    wazuh_manager_master_address: "{{ hostvars.manager.private_ip }}"
    indexer_cluster_nodes:
      - "{{ hostvars.wi1.private_ip }}"
      - "{{ hostvars.wi2.private_ip }}"
      - "{{ hostvars.wi3.private_ip }}"

Where:

  • hosts: specifies the Ansible inventory group name that the playbook will target. The playbook runs on the hosts defined under that group in the inventory file.

  • roles: section indicates the roles that will be executed on the hosts mentioned above.

Prepare the playbook

The wazuh-distributed.yml file allows you to deploy a distributed Wazuh environment. For this guide, the architecture includes 2 Wazuh manager nodes, 3 Wazuh indexer nodes, and a Wazuh dashboard node. Add the public and private IP addresses of the endpoints where the various components of the cluster will be installed to the /etc/ansible/hosts Ansible hosts file.

The contents of the Ansible host file below:

[all]
wi1 ansible_host=<WI1_EC2_PUBLIC_1P> private_ip=<WI1_EC2_PRIVATE_IP> indexer_node_name=node-1
wi2 ansible_host=<WI2_EC2_PUBLIC_1P> private_ip=<WI2_EC2_PRIVATE_IP> indexer_node_name=node-2
wi3 ansible_host=<WI3_EC2_PUBLIC_1P> private_ip=<WI3_EC2_PRIVATE_IP> indexer_node_name=node-3
manager ansible_host=<MANAGER_NODE_PUBLIC_IP> private_ip=<MANAGER_EC2_PRIVATE_IP>
worker  ansible_host=<WORKER_NODE_PUBLIC_IP> private_ip=<WORKER_EC2_PRIVATE_IP>
dashboard  ansible_host=<DASHBOARD_NODE_PUBLIC_IP> private_ip=<DASHBOARD_EC2_PRIVATE_IP>
[wi_cluster]
wi1
wi2
wi3

[all:vars]
ansible_ssh_user=<USERNAME>
ansible_ssh_extra_args='-o StrictHostKeyChecking=no'
ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>.pem

Where:

  • ansible_host specifies the public IP address or hostname Ansible uses to connect to the target node. Replace <WI1_EC2_PUBLIC_IP>, <WI2_EC2_PUBLIC_IP>, <WI3_EC2_PUBLIC_IP>, <MANAGER_NODE_PUBLIC_IP>, <WORKER_NODE_PUBLIC_IP>, and <DASHBOARD_NODE_PUBLIC_IP> with the actual public IP addresses or hostnames of the Wazuh indexer, manager, worker, and dashboard nodes.

  • private_ip variable contains the private IP address/FQDN used for the internal cluster communication. Replace <WI1_EC2_PRIVATE_IP>, <WI2_EC2_PRIVATE_IP>, <WI3_EC2_PRIVATE_IP>, <MANAGER_EC2_PRIVATE_IP>, <WORKER_EC2_PRIVATE_IP>, and <DASHBOARD_EC2_PRIVATE_IP> with the actual private IP addresses assigned to the endpoints.

  • If the environment is within a local subnet, ansible_host and private_ip variables should match.

  • ansible_ssh_private_key_file specifies the SSH private key used by Ansible to connect to the target hosts. Replace <PATH_TO_PRIVATE_KEY> with the directory path where the private key file is stored on the Ansible control node.

  • ansible_ssh_user variable specifies the SSH user for the nodes when it's the same. Replace <USERNAME> with a valid user account that has the required privileges on the endpoints. Specify this variable for each ansible_host if the SSH users are different. For example:

    wi1 ansible_host=<WI1_EC2_PUBLIC_IP> private_ip=<WI1_EC2_PRIVATE_IP> indexer_node_name=node-1 ansible_user=ubuntu
    wi2 ansible_host=<WI2_EC2_PUBLIC_IP> private_ip=<WI2_EC2_PRIVATE_IP> indexer_node_name=node-2 ansible_user=admin
    

Run the playbook

  1. Run the command below from the playbook directory on the Ansible server:

    # ansible-playbook wazuh-distributed.yml -e "source=prerelease"
    
  2. The commands below check the status of Wazuh indexer, Wazuh dashboard, and Wazuh manager services.

    • Wazuh indexer:

      # systemctl status wazuh-indexer
      
    • Wazuh dashboard:

      # systemctl status wazuh-dashboard
      
    • Wazuh manager:

      # systemctl status wazuh-manager
      

Note

The Wazuh dashboard can be accessed by visiting https://<DASHBOARD_SERVER_IP>

The default credentials are:

  • Username: admin

  • Password: admin

Installing the Wazuh agent

The ansible-wazuh-agent role installs Wazuh agents on Linux endpoints. The Ansible control server requires SSH access to each endpoint.

To install the Wazuh agent, perform the following:

Prerequisites

Before deploying Wazuh agents with Ansible, check your Ansible version:

  • Ansible-core 2.10 or later requires installing additional collections from Ansible Galaxy. Without these collections, running the Wazuh agent playbook may fail with an invalid characters error in roles/wazuh/ansible-wazuh-agent/handlers/main.yml:

    # ansible-galaxy collection install ansible.windows community.windows
    
  • Ansible 2.9 or earlier does not require these collections.

Note

  • SSH key-pairing should already be configured between the Ansible control server and the endpoints.

  • Add the endpoints where the agent will be deployed in the /etc/ansible/hosts Ansible hosts file under the [wazuh-agents] hosts group.

    [wazuh-agents]
    agent_1 ansible_host=<WAZUH_AGENT_IP_ADDRESS>
    ansible_ssh_user=<USERNAME>
    

Access the wazuh-ansible directory

Change to the directory where you cloned the Wazuh Ansible repository:

# cd /etc/ansible/roles/wazuh-ansible/
# tree roles -d
roles
├── package-urls
│   ├── defaults
│   └── tasks
├── vars
├── wazuh-agent
│   ├── defaults
│   └── tasks
├── wazuh-dashboard
│   ├── defaults
│   └── tasks
├── wazuh-indexer
│   ├── defaults
│   └── tasks
└── wazuh-manager
    ├── defaults
    └── tasks
17 directories

You can see the preconfigured playbooks by running the command below:

# ls
CHANGELOG.md  LICENSE  README.md  SECURITY.md  VERSION.json  docs  requirements.yml  roles  tools  wazuh-agent.yml  wazuh-aio.yml  wazuh-distributed.yml

The /etc/ansible/roles/wazuh-ansible/wazuh-agent.yml file contains the necessary commands to install a Wazuh agent and register it to the Wazuh manager. Below is the content of the /etc/ansible/roles/wazuh-ansible/wazuh-agent.yml file:

---

- name: Deploy Wazuh agent(s)
  hosts: agents
  strategy: free
  vars:
    wazuh_manager_address: "<Your Wazuh Manager IP>"
  roles:
    - role: package-urls
  tasks:
    - name: Include wazuh-agent role for Linux/MacOS hosts
      when: ansible_facts.system == "Linux" or ansible_facts.system == "Darwin"
      become: true
      become_user: root
      block:
        - name: Include Wazuh agent role for Linux
          ansible.builtin.include_role:
            name: wazuh-agent

    - name: Include wazuh-agent role for Windows hosts
      when: ansible_facts.os_family == "Windows"
      ansible.builtin.include_role:
        name: wazuh-agent

Where:

  • hosts: specifies the Ansible inventory group that contains the endpoints where the Wazuh agent will be installed.

  • roles: section indicates the roles that will be executed on the hosts specified. In this case, the wazuh-agent role will be installed. Replace the <WAZUH_AGENT_IP_ADDRESS> OR <WAZUH_AGENT_GROUP_NAME> with the IP address of the Wazuh agent or the Wazuh agent group name.

  • wazuh_managers: indicates details for the connection with the Wazuh manager. This list overwrites the default configuration. Replace <WAZUH_MANAGER_IP_ADDRESS> with the actual IP address of the Wazuh manager.

Prepare the playbook

Replace the IP address of the Wazuh manager in the wazuh_manager_addresses: section of the /etc/ansible/roles/wazuh-ansible/wazuh-agent.yml file.

---

- name: Deploy Wazuh agent(s)
  hosts: agents
  strategy: free
  vars:
    wazuh_manager_address: "<Your Wazuh Manager IP>"
  roles:
    - role: package-urls
  tasks:
    - name: Include wazuh-agent role for Linux/MacOS hosts
      when: ansible_facts.system == "Linux" or ansible_facts.system == "Darwin"
      become: true
      become_user: root
      block:
        - name: Include Wazuh agent role for Linux
          ansible.builtin.include_role:
            name: wazuh-agent

    - name: Include wazuh-agent role for Windows hosts
      when: ansible_facts.os_family == "Windows"
      ansible.builtin.include_role:
        name: wazuh-agent

Add the public and private IP addresses of the endpoint where the Wazuh components will be installed to the /etc/ansible/hosts Ansible hosts file.

The contents of the Ansible host file below:

[agents]
agent1 ansible_host=<WAZUH_AGENT1_IP>
agent2 ansible_host=<WAZUH_AGENT2_IP>

[agents:vars]
ansible_user=<USERNAME>
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ansible_ssh_private_key_file=<PATH_TO_PRIVATE_KEY>.pem

Where:

  • ansible_host specifies the IP address of the endpoint where the Wazuh agent will be installed. Replace <WAZUH_AGENT1_IP> and <WAZUH_AGENT2_IP> with the actual IP addresses or hostnames of the Wazuh agent endpoints.

  • ansible_ssh_user specifies the remote user account Ansible uses to connect over SSH. Replace <USERNAME> with a valid user account that has the required privileges on the endpoints.

  • ansible_ssh_private_key_file specifies the SSH private key used by Ansible to connect to the target hosts. Replace <PATH_TO_PRIVATE_KEY> with the directory path where the private key file is stored on the Ansible control node.

Run the playbook

  1. Run the command below from the playbook directory on the Ansible server:

    # ansible-playbook wazuh-agent.yml -e "source=prerelease"
    
  2. Check the status of the Wazuh agent:

    • Wazuh agent status on the endpoint:

      # systemctl status wazuh-agent
      
    • Wazuh agent status on the Wazuh manager:

      # /var/ossec/bin/agent_control -l