# Wazuh

Wazuh is a free and open source security platform that unifies XDR and SIEM capabilities. It protects workloads across on-premises, virtualized, containerized, and cloud-based environments.

Wazuh helps organizations and individuals to protect their data assets against security threats. It is widely used by thousands of organizations worldwide, from small businesses to large enterprises.

# Enabling Docker Listerner in Wazuh

### <video controls="" height="399" style="width:801px;height:399px;" width="801"><source src="https://wazuh.com/wp-content/themes/wazuh-v3/assets/images/home/wazuh-dashboard-wide.mp4?ver=1715238972"> </source></video>

### To Enable Docker Listener in Wazuh

To maintain the security and compliance of your Docker environment, it is crucial to proactively monitor both your Docker server and containers. The Docker server is the backbone of your container infrastructure and manages the deployment of containers and resource allocation. By monitoring the Docker server, you can keep track of resource usage, unauthorized access attempts, performance issues, and other security concerns.

However, it is not enough to monitor only the Docker server, you also need to monitor the containers themselves. Container monitoring provides insight into the activities of your containers, such as network connections, file system changes, and process executions. Monitoring these activities helps to detect suspicious behavior, identify malware or malicious processes, and respond to security incidents in real-time.

By monitoring both the Docker server and the containers, you can proactively detect and respond to security threats, ensuring the security and compliance of your Docker environment to regulatory standards.



### Wazuh agent configuration

##### **1. Install the dependencies on the docker server :**

<p class="callout warning">**Run each line Separately**  
</p>

```
sudo apt-get update && sudo apt-get install python3 -y
sudo apt-get install python3-pip -y
pip3 install docker==4.2.0 urllib3==1.26.18
```

##### **2. Edit the File using `sudo nano /var/ossec/etc/ossec.conf` and add the following:**   


```
<!-- Docker Container Runtime configuration -->
<wodle name="docker-listener">
  <interval>10m</interval>
  <attempts>5</attempts>
  <run_on_start>yes</run_on_start>
  <disabled>no</disabled>
</wodle>
```

#####   
**3. To monitor the logs of the container add the text below to the `"<!-- Log analysis -->"` section:**

```
<localfile>
  <log_format>syslog</log_format>
  <location>/var/lib/docker/containers/*/*-json.log</location>
</localfile>
```

##### **4. Restart the wazuh-agent service:**

```
sudo systemctl restart wazuh-agent
```



### Wazuh server configuration

#####   
**1. Edit the Decoder File in /var/ossec/etc/decoders/local\_decoder.xml on the Wazuh Server and add:**

```
 <decoder name="web-accesslog-docker">
  <parent>json</parent>
  <type>web-log</type>
  <use_own_name>true</use_own_name>
  <prematch offset="after_parent">^log":"\S+ \S+ \S+ \.*[\S+ \S\d+] \.*"\w+ \S+ HTTP\S+" \d+</prematch>
  <regex offset="after_parent">^log":"(\S+) \S+ \S+ \.*[\S+ \S\d+] \.*"(\w+) (\S+) HTTP\S+" (\d+)</regex>
  <order>srcip,protocol,url,id</order>
</decoder>

<decoder name="json">
  <parent>json</parent>
  <use_own_name>true</use_own_name>
  <plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>
```

##### **2.Restart the Wazuh-Manager:**

```
sudo systemctl restart wazuh-manager
```





## Wazuh Docker listener dashboard

The Wazuh Docker listener dashboard offers a centralized and user-friendly interface that allows you to monitor the security of your Dockerized infrastructure. With real-time insights and actionable information, the Wazuh Docker listener dashboard empowers system administrators and security teams to detect and respond to potential threats, ensuring the integrity and reliability of containerized applications. From monitoring container events to analyzing logs and implementing custom rules, this dashboard streamlines the security management process, enhancing the overall protection of your Docker environment.

Take the following steps to enable the Wazuh Docker listener dashboard:

1. Click on the **Wazuh** menu icon, and select **Settings** &gt; **Modules**.
2. Scroll down to the **Threat Detection and Response** section and enable **Docker listener**.
3. Click on the **Wazuh** menu icon, and select **Modules** &gt; **Docker listener** to view the Docker listener dashboard.

The animation below is a graphical representation of the steps you need to take to enable the Wazuh Docker listener dashboard.

[![image.png](https://documentation.wazuh.com/current/_images/enable-wazuh-docker-listener-dashboard1.gif)](https://book.msls.tech/uploads/images/gallery/2024-05/image.png)

<section id="bkmrk-wazuh-docker-listene-1">### Wazuh Docker listener configuration options

In this section, we provide more information about the Wazuh Docker listener and all possible configuration options. The Docker listener has the main options and the scheduling options.

<section id="bkmrk-main-options-the-mai">#### Main options

The main options allow you to enable or disable the Docker listener, and to configure the number of attempts to rerun the listener in case it fails. The two main options are `<span class="pre">disabled</span>` and `<span class="pre">attempts</span>`.

<section id="bkmrk-disabled-the%C2%A0disable">

##### disabled

The `<span class="pre">disabled</span>` option allows you to enable or disable the Docker listener.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>no

</td></tr><tr class="row-even"><td>Allowed values

</td><td>yes, no

</td></tr></tbody></table>

</section><section id="bkmrk-attempts-the%C2%A0attempt">

##### attempts

The `<span class="pre">attempts</span>` option specifies the number of attempts to execute the listener in case it fails.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>5

</td></tr><tr class="row-even"><td>Allowed values

</td><td>A positive number

</td></tr></tbody></table>

</section></section><section id="bkmrk-scheduling-options-t">

### Scheduling options

The scheduling options allow you to configure when the Docker listener should execute. The available scheduling options are `<span class="pre">run_on_start</span>`, `<span class="pre">interval</span>`, `<span class="pre">day</span>`, `<span class="pre">wday</span>`, and `<span class="pre">time</span>`. The Docker listener runs on start by default when enabled without any scheduling options.

<section id="bkmrk-run_on_start-run-the">
##### run\_on\_start

Run the Docker listener immediately when the Wazuh agent starts.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>yes

</td></tr><tr class="row-even"><td>Allowed values

</td><td>yes, no

</td></tr></tbody></table>

</section><section id="bkmrk-interval-waiting-tim">
##### interval

Waiting time to rerun the Docker listener in case it fails.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>1m

</td></tr><tr class="row-even"><td>Allowed values

</td><td>A positive number that should contain a suffix character indicating a time unit, such as s (seconds), m (minutes), h (hours), d (days), M (months).

</td></tr></tbody></table>

</section><section id="bkmrk-day-day-of-the-month">
##### day

Day of the month to run the scan.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>n/a

</td></tr><tr class="row-even"><td>Allowed values

</td><td>Day of the month \[1..31\]

</td></tr></tbody></table>

<p class="callout info">Note  
When the `<span class="pre">day</span>` option is set, the interval value must be a multiple of months. By default, the interval is set to a month.</p>

</section><section id="bkmrk-wday-day-of-the-week">
##### wday

Day of the week to run the scan. This option is *not compatible* with the `<span class="pre">day</span>` option.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>n/a

</td></tr><tr class="row-even"><td>Allowed values

</td><td>Day of the week:

- sunday/sun
- monday/mon
- tuesday/tue
- wednesday/wed
- thursday/thu
- friday/fri
- saturday/sat

</td></tr></tbody></table>

<p class="callout info">Note  
When the `<span class="pre">wday</span>` option is set, the interval value must be a multiple of weeks. By default, the interval is set to a week.</p>

</section><section id="bkmrk-time-time-of-the-day">
##### time

Time of the day to run the scan. It has to be represented in the format hh:mm.

<table class="docutils align-default"><tbody><tr class="row-odd"><td>Default value

</td><td>n/a

</td></tr><tr class="row-even"><td>Allowed values

</td><td>Time of day *\[hh:mm\]*

</td></tr></tbody></table>

<p class="callout info">Note  
When only the `<span class="pre">time</span>` option is set, the interval value must be a multiple of days or weeks. By default, the interval is set to a day.</p>

</section></section></section><section id="bkmrk-example-configuratio">
## Example configuration

The example configuration below shows an enabled Docker listener. The listener attempts to execute five times at ten-minute intervals if it fails

```
<wodle name="docker-listener">
  <interval>10m</interval>
  <attempts>5</attempts>
  <run_on_start>no</run_on_start>
  <disabled>no</disabled>
</wodle>
```

</section>

# Docker container security monitoring with Wazuh

Docker has become a popular framework for application deployment since its development due to its benefits. For example, it makes it easier for organizations to enhance the portability of their applications and operational resilience. Docker is an open source technology used to package applications into containers. **Docker containers** are lightweight, standalone, and runnable instances of a Docker image that isolate software running in the container from the operating system environment. With these benefits, many organizations have adopted the technology to quickly package their software in standard units for development, shipment, and deployment.

The increased usage of containerized software has increased the attack surface for organizations. This provides an additional asset for cyber threat actors to target in their attacks. Therefore, it is crucial to continuously monitor containers to gain complete visibility of their environment and events during execution.

In this blog post, we demonstrate how to do the following:

- Monitor Docker events such as `pull`, `create`, `start`, `mount`, `connect`, `exec_start`, `detach`, `die`, `exec_create`, `exec_detach`, etc.
- Monitor *Docker container* resources such as CPU, memory, and network traffic utilization.
- Detect when container CPU and memory usage exceed predefined thresholds.
- Monitor the health status and uptime of Docker containers.

## Docker Container: Infrastructure setup

The following setup is used to illustrate the capability of Wazuh to monitor Docker container events and their metrics:

- A Centos 7 endpoint running the Wazuh 4.3.10. The Wazuh central components can be installed using this [Quickstart installation guide](https://documentation.wazuh.com/current/quickstart.html).
- An Ubuntu 22.04 endpoint running the Wazuh agent 4.3.10. This endpoint also hosts the Docker container infrastructure. This Wazuh [guide](https://documentation.wazuh.com/current/installation-guide/wazuh-agent/wazuh-agent-package-linux.html) is used to install the Wazuh agent.

## Monitoring with Wazuh

Wazuh has the Docker listener and command monitoring modules that can be used to collect security and runtime events from Docker containers. The Docker listener module communicates with the Docker API to collect events related to Docker containers. The command monitoring module is used to monitor the output of specific commands and trigger alerts if they match a rule.

### Ubuntu endpoint configuration

Follow these steps on the monitored endpoint:

Note

<div class="wp-block-column wazuh-admonition note" id="bkmrk-%C2%A0"> </div>You need root user privileges to execute all the commands described below.

1\. Install Python and pip:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-apt-install-python"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">apt install python3 python3-pip</span></div></div></div></div></div>2\. Install Docker and the Python Docker Library to run the containers:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-curl--ssl-https%3A%2F%2F"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">curl -sSL https://get.docker.com/ | sh</span></div></div><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">pip3 install docker==4.2.0</span></div></div></div></div></div>3\. Enable the Wazuh agent to receive remote commands from the Wazuh server. By default, remote commands are disabled in agents for security reasons.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-echo-%22logcollector"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">echo "logcollector.remote\_commands=1" &gt;&gt; /var/ossec/etc/local\_internal\_options.conf</span></div></div></div></div></div>4\. Restart the Wazuh agent to apply the above changes:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-systemctl-restart-"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">systemctl restart wazuh-agent</span></div></div></div></div></div>### Wazuh server configuration

Follow these steps on the Wazuh server:

Note

<div class="wp-block-column wazuh-admonition note" id="bkmrk-%C2%A0-1"> </div>You need root user privileges to execute all the commands described below.

1\. Create a Wazuh agent group called container:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-%2Fvar%2Fossec%2Fbin%2Fage"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">/var/ossec/bin/agent\_groups -a -g container -q</span></div></div></div></div></div>2\. Obtain the ID of all Wazuh agents using the following command:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-%2Fvar%2Fossec%2Fbin%2Fman"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">/var/ossec/bin/manage\_agents -l</span></div></div></div></div></div>3\. Assign the Wazuh agent hosting the Docker containers to the container group. Multiple agents can be assigned to the group. This ensures all agents running Docker containers in your environment receive the same configuration.

Replace `<AGENT_ID>` with the agent’s ID of the endpoint hosting the Docker container.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-%2Fvar%2Fossec%2Fbin%2Fage-1"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">/var/ossec/bin/agent\_groups -a -i &lt;AGENT\_ID&gt; -g container -q</span></div></div></div></div></div>4\. Add the following settings to the `/var/ossec/etc/shared/container/agent.conf` configuration file. This enables the Docker listener module and sets the commands to execute on the monitored endpoint for Docker container information gathering.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-xml enlighter-hover" id="bkmrk-%3Cagent_config%3E-%3C%21---"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">agent</span><span class="enlighter-text">\_config</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-c1">&lt;!-- Configuration to enable Docker listener module. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">wodle</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"docker-listener"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">interval</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">10m</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">interval</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">attempts</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">5</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">attempts</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">run</span><span class="enlighter-text">\_on\_start</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">yes</span><span class="enlighter-x1">&lt;/run\_on\_start&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">disabled</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">no</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">disabled</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">wodle</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Command to extract container resources information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">localfile</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">log</span><span class="enlighter-text">\_format</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">command</span><span class="enlighter-x1">&lt;/log\_format&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">command</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker stats --format "{{.Container}} {{.Name}} {{.CPUPerc}} {{.MemUsage}} {{.MemPerc}} {{.NetIO}}" --no-stream</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">command</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">alias</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker container stats</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">alias</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">frequency</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">120</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">frequency</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">out</span><span class="enlighter-text">\_format</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">$(timestamp) $(hostname) docker-container-resource: $(log)</span><span class="enlighter-x1">&lt;/out\_format&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">localfile</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Command to extract container health information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">localfile</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">log</span><span class="enlighter-text">\_format</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">command</span><span class="enlighter-x1">&lt;/log\_format&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">command</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker ps --format "{{.Image}} {{.Names}} {{.Status}}"</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">command</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">alias</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker container ps</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">alias</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">frequency</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">120</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">frequency</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">out</span><span class="enlighter-text">\_format</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">$(timestamp) $(hostname) docker-container-health: $(log)</span><span class="enlighter-x1">&lt;/out\_format&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">localfile</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-x1">&lt;/agent\_config&gt;</span></div></div></div></div></div>Note

<div class="wp-block-column wazuh-admonition note" id="bkmrk-%C2%A0-2"> </div>The `<frequency>` tag defines how often the command will be run in seconds. You can configure a value that suits your environment.

The commands to extract information configured above can get logs like in the following samples:

- Log for container resources:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-raw enlighter-hover" id="bkmrk-nov-2-14%3A11%3A38-ubunt"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-text">Nov 2 14:11:38 ubuntu-2204 docker-container-resource: ossec: output: 'docker container stats': bbc95edda452 nginx-container 21.32% 3MiB / 1.931GiB 0.15% 1.44kB / 0B</span></div></div></div></div></div>- Log for container health:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-raw enlighter-hover" id="bkmrk-nov-1-13%3A47%3A12-ubunt"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-text">Nov 1 13:47:12 ubuntu-2204 docker-container-health: ossec: output: 'docker container ps': nginx nginx-container Up 48 minutes (healthy)</span></div></div></div></div></div>5\. Create a decoders file `docker_decoders.xml` in the `/var/ossec/etc/decoders/` directory and add the following decoders to decode the logs received from the Wazuh agent:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-xml enlighter-hover" id="bkmrk-%3C%21---decoder-for-con"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-c1">&lt;!-- Decoder for container resources information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoder</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"docker-container-resource"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">program</span><span class="enlighter-text">\_name</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^docker-container-resource</span><span class="enlighter-x1">&lt;/program\_name&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">decoder</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoder</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"docker-container-resource-child"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">parent</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker-container-resource</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">parent</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">prematch</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">ossec: output: 'docker container stats':</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">prematch</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">regex</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">(\\S+) (\\S+) (\\S+) (\\S+) / (\\S+) (\\S+) (\\S+) / (\\S+)</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">regex</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">order</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_id, container\_name, container\_cpu\_usage, container\_memory\_usage, container\_memory\_limit, container\_memory\_perc, container\_network\_rx, container\_network\_tx</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">order</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">decoder</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Decoder for container health information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoder</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"docker-container-health"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">program</span><span class="enlighter-text">\_name</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^docker-container-health</span><span class="enlighter-x1">&lt;/program\_name&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">decoder</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoder</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"docker-container-health-child"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">parent</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker-container-health</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">parent</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">prematch</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">ossec: output: 'docker container ps':</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">prematch</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">regex</span> <span class="enlighter-x2">offset</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"after\_prematch"</span> <span class="enlighter-x2">type</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"pcre2"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">(\\S+) (\\S+) (.\*?) \\((.\*?)\\)</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">regex</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">order</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_image, container\_name, container\_uptime, container\_health\_status</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">order</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">decoder</span><span class="enlighter-g1">&gt;</span></div></div></div></div></div>Note

<div class="wp-block-column wazuh-admonition note" id="bkmrk-%C2%A0-3"> </div>The custom decoder file `docker_decoders.xml` might be removed during an upgrade. Ensure to back up the file before you perform upgrades.

6\. Create a rules file `docker_rules.xml` in the `/var/ossec/etc/rules/` directory and add the following rules to alert the container information:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-xml enlighter-hover" id="bkmrk-%3Cgroup-name%3D%22contain"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container,"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-c1">&lt;!-- Rule for container resources information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100100"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"5"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoded</span><span class="enlighter-text">\_as</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker-container-resource</span><span class="enlighter-x1">&lt;/decoded\_as&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) Resources</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_resource,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Rule to trigger when container CPU and memory usage are above 80%. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100101"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"12"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">if</span><span class="enlighter-text">\_sid</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">100100</span><span class="enlighter-x1">&lt;/if\_sid&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">field</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container\_cpu\_usage"</span> <span class="enlighter-x2">type</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"pcre2"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^(0\*\[8-9\]\\d|0\*\[1-9\]\\d{2,})</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">field</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">field</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container\_memory\_perc"</span> <span class="enlighter-x2">type</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"pcre2"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^(0\*\[8-9\]\\d|0\*\[1-9\]\\d{2,})</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">field</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) CPU usage ($(container\_cpu\_usage)) and memory usage ($(container\_memory\_perc)) is over 80%</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_resource,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Rule to trigger when container CPU usage is above 80%. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100102"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"12"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">if</span><span class="enlighter-text">\_sid</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">100100</span><span class="enlighter-x1">&lt;/if\_sid&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">field</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container\_cpu\_usage"</span> <span class="enlighter-x2">type</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"pcre2"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^(0\*\[8-9\]\\d|0\*\[1-9\]\\d{2,})</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">field</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) CPU usage ($(container\_cpu\_usage)) is over 80%</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_resource,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Rule to trigger when container memory usage is above 80%. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100103"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"12"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">if</span><span class="enlighter-text">\_sid</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">100100</span><span class="enlighter-x1">&lt;/if\_sid&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">field</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container\_memory\_perc"</span> <span class="enlighter-x2">type</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"pcre2"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^(0\*\[8-9\]\\d|0\*\[1-9\]\\d{2,})</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">field</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) memory usage ($(container\_memory\_perc)) is over 80%</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_resource,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Rule for container health information. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100105"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"5"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">decoded</span><span class="enlighter-text">\_as</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">docker-container-health</span><span class="enlighter-x1">&lt;/decoded\_as&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) is $(container\_health\_status)</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_health,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-c1">&lt;!-- Rule to trigger when a container is unhealthy. --&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">rule</span> <span class="enlighter-x2">id</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"100106"</span> <span class="enlighter-x2">level</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"12"</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">if</span><span class="enlighter-text">\_sid</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">100105</span><span class="enlighter-x1">&lt;/if\_sid&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">field</span> <span class="enlighter-x2">name</span><span class="enlighter-k3">=</span><span class="enlighter-s0">"container\_health\_status"</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">^unhealthy$</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">field</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">Docker: Container $(container\_name) is $(container\_health\_status)</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">description</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span><span class="enlighter-text">container\_health,</span><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">rule</span><span class="enlighter-g1">&gt;</span></div></div><div><div><span class="enlighter-g1">&lt;/</span><span class="enlighter-x1">group</span><span class="enlighter-g1">&gt;</span></div></div></div></div></div>Note

<div class="wp-block-column wazuh-admonition note" id="bkmrk-%C2%A0-4"> </div>The custom rules file `docker_rules.xml` might be removed during an upgrade. Ensure to back up the file before you perform upgrades.

7\. Restart the Wazuh manager to apply the above changes:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-systemctl-restart--1"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">systemctl restart wazuh-manager</span></div></div></div></div></div>### Testing the configuration

To showcase the use cases mentioned above, Nginx, Redis, and Postgres images are used to create a containerized environment on the monitored endpoint.

1\. Create and switch into a project directory `/container_env` for the container environment using the following command:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%24-mkdir-container_en"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">$ </span><span class="enlighter-text">mkdir container\_env &amp;&amp; cd </span><span class="enlighter-k7">$\_</span></div></div></div></div></div>2\. Create a Docker compose file `docker-compose.yml` and add the following configurations to it. The Docker compose file helps to manage multiple containers at once. The configuration performs the following Docker actions:

- Pulls Nginx, Redis, and Postgres container images from Docker Hub.
- Creates and starts `nginx-container`, `redis-container`, and `postgres-container` containers from the respective Docker images.
- Creates and connects to a network called `container_env_network`.
- Creates and mounts volumes `container_env_db` and `container_env_cache`.
- Performs health checks on the created containers every three minutes.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-raw enlighter-hover" id="bkmrk-version%3A-%273.8%27-servi"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-text">version: '3.8'</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-text">services:</span></div></div><div><div><span class="enlighter-text"> db:</span></div></div><div><div><span class="enlighter-text"> image: postgres</span></div></div><div><div><span class="enlighter-text"> container\_name: postgres-container</span></div></div><div><div><span class="enlighter-text"> restart: always</span></div></div><div><div><span class="enlighter-text"> environment:</span></div></div><div><div><span class="enlighter-text"> - POSTGRES\_USER=postgres</span></div></div><div><div><span class="enlighter-text"> - POSTGRES\_PASSWORD=postgres</span></div></div><div><div><span class="enlighter-text"> healthcheck:</span></div></div><div><div><span class="enlighter-text"> test: \["CMD-SHELL", "pg\_isready"\]</span></div></div><div><div><span class="enlighter-text"> interval: 3m</span></div></div><div><div><span class="enlighter-text"> timeout: 5s</span></div></div><div><div><span class="enlighter-text"> retries: 1</span></div></div><div><div><span class="enlighter-text"> ports:</span></div></div><div><div><span class="enlighter-text"> - '8001:5432'</span></div></div><div><div><span class="enlighter-text"> dns:</span></div></div><div><div><span class="enlighter-text"> - 8.8.8.8</span></div></div><div><div><span class="enlighter-text"> - 9.9.9.9</span></div></div><div><div><span class="enlighter-text"> volumes:</span></div></div><div><div><span class="enlighter-text"> - db:/var/lib/postgresql/data</span></div></div><div><div><span class="enlighter-text"> networks:</span></div></div><div><div><span class="enlighter-text"> - network</span></div></div><div><div><span class="enlighter-text"> mem\_limit: "512M"</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-text"> cache:</span></div></div><div><div><span class="enlighter-text"> image: redis</span></div></div><div><div><span class="enlighter-text"> container\_name: redis-container</span></div></div><div><div><span class="enlighter-text"> restart: always</span></div></div><div><div><span class="enlighter-text"> healthcheck:</span></div></div><div><div><span class="enlighter-text"> test: \["CMD", "redis-cli", "--raw", "incr", "ping"\]</span></div></div><div><div><span class="enlighter-text"> interval: 3m</span></div></div><div><div><span class="enlighter-text"> timeout: 5s</span></div></div><div><div><span class="enlighter-text"> retries: 1</span></div></div><div><div><span class="enlighter-text"> ports:</span></div></div><div><div><span class="enlighter-text"> - '8002:6379'</span></div></div><div><div><span class="enlighter-text"> dns:</span></div></div><div><div><span class="enlighter-text"> - 8.8.8.8</span></div></div><div><div><span class="enlighter-text"> - 9.9.9.9</span></div></div><div><div><span class="enlighter-text"> volumes:</span></div></div><div><div><span class="enlighter-text"> - cache:/data</span></div></div><div><div><span class="enlighter-text"> networks:</span></div></div><div><div><span class="enlighter-text"> - network</span></div></div><div><div><span class="enlighter-text"> mem\_limit: "512M"</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-text"> nginx:</span></div></div><div><div><span class="enlighter-text"> image: nginx</span></div></div><div><div><span class="enlighter-text"> container\_name: nginx-container</span></div></div><div><div><span class="enlighter-text"> restart: always</span></div></div><div><div><span class="enlighter-text"> healthcheck:</span></div></div><div><div><span class="enlighter-text"> test: \["CMD-SHELL", "stat /etc/nginx/nginx.conf || exit 1"\]</span></div></div><div><div><span class="enlighter-text"> interval: 3m</span></div></div><div><div><span class="enlighter-text"> timeout: 5s</span></div></div><div><div><span class="enlighter-text"> retries: 1</span></div></div><div><div><span class="enlighter-text"> ports:</span></div></div><div><div><span class="enlighter-text"> - '8003:80'</span></div></div><div><div><span class="enlighter-text"> - '4443:443'</span></div></div><div><div><span class="enlighter-text"> dns:</span></div></div><div><div><span class="enlighter-text"> - 8.8.8.8</span></div></div><div><div><span class="enlighter-text"> - 9.9.9.9</span></div></div><div><div><span class="enlighter-text"> networks:</span></div></div><div><div><span class="enlighter-text"> - network</span></div></div><div><div><span class="enlighter-text"> mem\_limit: "512M"</span></div></div><div><div>  
</div></div><div><div><span class="enlighter-text">volumes:</span></div></div><div><div><span class="enlighter-text"> db: {}</span></div></div><div><div><span class="enlighter-text"> cache: {}</span></div></div><div><div><span class="enlighter-text">networks:</span></div></div><div><div><span class="enlighter-text"> network:</span></div></div></div></div></div>3\. Execute the following command in the path containing the docker-compose.yml file to create and start the containers:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%24-sudo-docker-compos"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">$ </span><span class="enlighter-text">sudo docker compose up -d</span></div></div></div></div></div>4\. we use the `stress-ng` utility program to test for high CPU and memory utilization. Perform this test on one of the containers, for instance, the `nginx-container`.

- Execute the following commands to enter the container shell and install the stress-ng utility:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-docker-exec--it-ng"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">docker exec -it nginx-container /bin/bash</span></div></div><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">apt update &amp;&amp; apt install stress-ng -y</span></div></div></div></div></div>- Execute the following command to trigger a high-level alert when both CPU and memory utilization exceeds 80%. The command runs for 3 minutes.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-stress-ng--c-1--l-"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">stress-ng -c 1 -l 80 -vm 1 --vm-bytes 500m -t 3m</span></div></div></div></div></div>- Execute the following command to trigger a high-level alert when memory usage exceeds 80%. The command runs for 3 minutes.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-stress-ng--vm-1---"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">stress-ng -vm 1 --vm-bytes 500m -t 3m</span></div></div></div></div></div>- Execute the following command to trigger a high-level alert when CPU usage exceeds 80%. The command runs for 3 minutes.

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-stress-ng--c-1--l--1"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">stress-ng -c 1 -l 80 -t 3m</span></div></div></div></div></div>5\. The health check for the `nginx-container` verifies whether the configuration file `/etc/nginx/nginx.conf` exists. While inside the container shell, delete the configuration file to trigger a high-level alert when the container becomes unhealthy:

<div class="enlighter-default enlighter-v-standard enlighter-t-wazuh-theme enlighter-l-shell enlighter-hover" id="bkmrk-%23-rm-%2Fetc%2Fnginx%2Fngin"><div class="enlighter-code"><div class="enlighter"><div><div><span class="enlighter-no-copy">\# </span><span class="enlighter-text">rm /etc/nginx/nginx.conf</span></div></div></div></div></div>### Alert visualization

Visualize the triggered alerts by visiting the Wazuh dashboard.

- **Container actions alerts:** Navigate to the **Discover** section and add the `rule.groups: docker` filter in the search bar to query the alerts. Also, use the **Filter by type** search field and apply the `agent.name`, `data.docker.from`, `data.docker.Actor.Attributes.name`, `data.docker.Type`, `data.docker.Action`, and `rule.description`, filters. Save the query as **Docker Events**.

<figure class="wp-block-image size-full" id="bkmrk-figure-1%3A-custom-vis">![](https://wazuh.com/uploads/2022/11/docker-events-1.gif)<figcaption class="wp-element-caption">Figure 1: Custom visualization with detected Docker events.  
</figcaption></figure>- **Container resources alerts:** Navigate to the **Discover** section and add the `rule.id: (100100 OR 100101 OR 100102 OR 100103)` filter in the search bar to query the alerts. Also, use the **Filter by type** search field and apply the `agent.name`, `data.container_name`, `data.container_cpu_usage`, `data.container_memory_usage`, `data.container_memory_limit`, `data.container_network_rx`, and `data.container_network_tx` filters. Save the query as **Container Resources**.

<figure class="wp-block-image size-full" id="bkmrk-figure-2%3A-custom-vis">![Docker Container Security](https://wazuh.com/uploads/2022/11/01-3.png "Docker Container Security")<figcaption class="wp-element-caption">Figure 2: Custom visualization showing container resources usage.</figcaption></figure>- **Container health alerts:** Navigate to the **Discover** section and add the `rule.id: (100105 OR 100106)` filter in the search bar to query the alerts. Also, use the **Filter by type** search field and apply the `agent.name`, `data.container_image`, `data.container_name`, `data.container_health_status`, and `data.container_uptime` filters to show the status information. Save the query as **Container Health**.

<figure class="wp-block-image size-full" id="bkmrk-figure-3%3A-health-sta">![Docker Container](https://wazuh.com/uploads/2022/11/02-2.png "Docker Container")<figcaption class="wp-element-caption">Figure 3: Health status of containers on the custom visualization.  
</figcaption></figure>- **Container threshold events:** Navigate to the **Wazuh** &gt; **Security events** section and add the `rule.id: (100101 OR 100102 OR 100103 OR 100106)` filter in the search bar to query the alerts.

<figure class="wp-block-image size-full" id="bkmrk-figure-4%3A-container-">![Docker container security monitoring](https://wazuh.com/uploads/2022/11/03-1.png "Docker container security monitoring")<figcaption class="wp-element-caption">Figure 4: Container threshold events on the Wazuh dashboard.  
</figcaption></figure>To have a single display of the visualizations, create a custom dashboard with the above templates. Navigate to **OpenSearch Dashboards** &gt; **Dashboard** &gt; **Create New Dashboard**, then select **Add an existing** link and click the saved visualizations (Docker Events, Container Resources, and Container Health). This will add the visualizations to the new dashboard. Save the dashboard as **Container-resource-health-events**.

<figure class="wp-block-image size-full" id="bkmrk-figure-5%3A-custom-das">![Docker container dashboard](https://wazuh.com/uploads/2022/11/Container-resource-health-events.gif "Docker container dashboard")<figcaption class="wp-element-caption">Figure 5: Custom dashboard displaying container resources, health, and events.  
</figcaption></figure>## Conclusion

High visibility of containers in Dockerized environments allows you to maintain a secure and efficient environment. This way, organizations can quickly identify and respond to issues and minimize disruptions. With Wazuh, we can spot abnormalities in containers, get an overview of their resource utilization, and easily analyze their health.

In this blog post, we ensured complete coverage of our Dockerized environment by monitoring Docker container events, resource utilization, and health to improve overall security.

## References

1. [Monitoring Docker container events](https://documentation.wazuh.com/current/container-security/docker-monitor/monitoring-containers-activity.html).
2. [Docker reference documentation](https://docs.docker.com/reference/).
3. [Creating Wazuh decoders and rules from scratch](https://wazuh.com/blog/creating-decoders-and-rules-from-scratch/).

# Wazuh Agent Deployment & Troubleshooting Guide

#   


This guide documents the procedures for maintaining Wazuh agents on Ubuntu 22.04/24.04, with specific instructions for Docker monitoring and manual ID preservation.

---

## 1. Agent Version Control (Critical)

**Constraint:** The Wazuh Manager version must always be <u>equal to or higher</u> than the Agent version.

- **Manager Version:** v4.9.0
- **Target Agent Version:** v4.9.0

```
# Download the specific matching version
wget https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_4.9.0-1_amd64.deb
sudo dpkg -i wazuh-agent_4.9.0-1_amd64.deb

```

---

## 2. Preserving Existing Agent IDs (e.g., ID 015)

Use this process when reinstalling an agent to ensure it keeps its historical data and ID.

### Step A: Extract Key from Manager

Run this on the **Wazuh Manager** terminal:

```
sudo /var/ossec/bin/manage_agents -e 015
```

*Copy the long alphanumeric string provided.*

### Step B: Import Key to Agent

Run this on the **Bookstack-LXC** terminal:

```
sudo /var/ossec/bin/manage_agents -i [PASTE_KEY_HERE]
```

---

## 3. Monitoring Authentik &amp; Docker Containers

To populate the Docker dashboard and monitor Authentik logs, three components are required.

### Step A: Python Dependencies (Ubuntu 24.04 Fix)

Ubuntu 24.04 prevents global pip installs by default. Use `--break-system-packages` to allow the agent's internal scripts to run.

```
sudo apt update && sudo apt install python3-pip -y
pip3 install docker==7.1.0 requests==2.32.2 --break-system-packages
sudo usermod -aG docker wazuh
```

### Step B: Config Changes (ossec.conf)

Open `/var/ossec/etc/ossec.conf` and add these blocks before the final `</ossec_config>`.

```
<!-- Monitor Container Events (Starts/Stops) -->
<wodle name="docker-listener">
  <interval>1m</interval>
  <attempts>5</attempts>
  <run_on_start>yes</run_on_start>
  <disabled>no</disabled>
</wodle>

<!-- Monitor Authentik Container Logs -->
<localfile>
  <log_format>syslog</log_format>
  <location>/var/lib/docker/containers/*/*-json.log</location>
</localfile>
```

---

## 4. Troubleshooting Checklist

<table id="bkmrk-error-in-ossec.log-f"><tbody><tr><th>Error in ossec.log</th><th>Fix Action</th></tr><tr><td>Invalid server address: 'MANAGER\_IP'</td><td>Update `<address>` in ossec.conf to `wazuh.msls.tech`.</td></tr><tr><td>Error reading XML file (line 0)</td><td>Check for nested or unclosed `<ossec_config>` tags.</td></tr></tbody></table>

## Handling Duplicate Agents for the Same VM

If a VM appears twice (e.g., with two different IDs), follow these steps to keep the ID with historical data:

1. **Identify:** Find the ID you want to keep (ID\_KEEP) and the one to delete (ID\_DEL).
2. **Delete on Manager:** `sudo /var/ossec/bin/manage_agents -r [ID_DEL]`.
3. **Stop Agent Service:** `sudo systemctl stop wazuh-agent` on the VM.
4. **Refresh Key:** Extract the key for ID\_KEEP from the manager (`-e`) and import it to the agent (`-i`).
5. **Restart:** `sudo systemctl restart wazuh-agent`.

# 🛠️ Fixing Wazuh Dashboard Migration Loops

#   


If you keep seeing **“Wazuh dashboard server is not ready yet”** in a loop, the Wazuh Dashboard is almost always stuck on a **migration lock**. This typically happens after an interrupted upgrade or restart.

### 🔐 Security Warning

Never store real credentials in documentation. If a password was previously exposed on this page, **rotate it immediately**.

---

## 📋 Overview

- **Symptom:** Dashboard never finishes loading
- **Root cause:** Stuck `.kibana` migration index
- **Fix:** Remove the corrupted index and allow a clean rebuild

---

## ① Stop the Wazuh Dashboard

Stop the service to ensure no active writes occur during cleanup.

```bash
sudo systemctl stop wazuh-dashboard
```

---

## ② Remove the stuck Kibana index

This deletes the partially migrated UI index that causes the loop.

### ⚠️ Impact

<div class="callout warning" id="bkmrk-saved-dashboards-and">- Saved dashboards and visualizations may be reset
- Wazuh alerts and event data are **not** removed

</div>### Option A — Simple (placeholder password)

```bash
curl -k -u admin:'<PASSWORD>' -X DELETE "https://localhost:9200/.kibana*"
```

### Option B — Recommended (secure password prompt)

```bash
read -s -p "Password: " WAZUH_PASS; echo
curl -k -u "admin:${WAZUH_PASS}" -X DELETE "https://localhost:9200/.kibana*"
unset WAZUH_PASS
```

# 🛠️ Breaking the Migration Lockge

#   


The "Another process is migrating" error occurs when the dashboard service is interrupted while recreating its internal indices. Follow these steps **in exact order** to clear the lock.

<div class="page-content" id="bkmrk-1" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">1</div><div>  
</div></div></div></div>### Stop the Dashboard Service

You must stop the service to ensure no active processes are attempting to write to the index during the cleanup.

```
sudo systemctl stop wazuh-dashboard
```

<div class="page-content" id="bkmrk-2" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div>  
</div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">2</div><div>  
</div></div></div></div>### Clear the Stuck System Index

This removes the "half-finished" index that is causing the `resource_already_exists_exception` and migration lock.

```
curl -k -u admin:'<password>' -X DELETE https://localhost:9200/.kibana*
```

<div class="page-content" id="bkmrk-3" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div>  
</div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">3</div><div>  
</div></div></div></div>### Start and Allow Initialization

Restart the service. The dashboard will now see that the index is missing and recreate it cleanly.

```
sudo systemctl start wazuh-dashboard
```

#### ⚠️ The "5-Minute Rule"

<div class="page-content" id="bkmrk-" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;">  
</div></div><div style="margin-top:32px;padding:16px;background-color:#fffbdd;border:1px solid #d1d5da;border-left:6px solid #e36209;">**Do not refresh your browser for 5 minutes.** The dashboard is performing a heavy background migration. Interrupting this will recreate the migration lock, forcing you back to Step 1.</div></div>####   

# 📜 Clean Dashboard Log Viewing

#   


The default dashboard logs are dense JSON strings. Use these filtered commands to see exactly what is happening during a migration without the "noise".

<div class="page-content" id="bkmrk-1" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">1</div><div>  
</div></div></div></div>### Filter for Migration Progress

This command hides the repetitive warnings and only shows messages related to the index migration and server status.

```
sudo journalctl -u wazuh-dashboard -f | grep -iE "migration|savedobjects|server running"
```

<div class="page-content" id="bkmrk-2" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div></div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">2</div><div>  
</div></div></div></div>### Pretty-Print with JQ

If you have `jq` installed, this command parses the JSON into a structured, readable format with timestamps.

```
sudo journalctl -u wazuh-dashboard -f | grep --line-buffered "{" | jq '.'
```

<div class="page-content" id="bkmrk-3" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div></div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">3</div><div>  
</div></div></div></div>### The "Finish Line" Message

Regardless of the format, you are looking for this specific log entry. Once you see it, the migration is complete.

<div class="page-content" id="bkmrk-%22message%22%3A%22http-serv" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div><div style="background-color:#f1f8ff;border-left:4px solid #0366d6;padding:12px;font-family:monospace;font-size:0.9rem;">"message":"http server running at https://0.0.0.0:5601"</div></div></div></div><div style="margin-top:32px;padding:16px;background-color:#e7f3ff;border:1px solid #d1d5da;border-left:6px solid #206afb;">  
</div></div>#### 💡 Installing JQ

If the `jq` command is not found, install it with: `sudo apt update && sudo apt install jq -y`

# 🛠️ Wazuh Logs Advanced Log Troubleshooting (with JQ)

#   


The Wazuh Dashboard logs are JSON-formatted, but standard `journalctl` prepends timestamps that break JSON parsers. Use these commands to see perfectly formatted, readable logs.

<div class="page-content" id="bkmrk-1" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">1</div><div>  
</div></div></div></div>### View Pretty-Printed JSON

The `-o cat` flag removes the OS timestamps, allowing `jq` to parse the dashboard's internal JSON correctly.

```
sudo journalctl -u wazuh-dashboard -o cat -f | jq '.'
```

<div class="page-content" id="bkmrk-2" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div>  
</div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">2</div><div>  
</div></div></div></div>### Extract Only Timestamps and Messages

If you want a very clean list of just the time and the action being performed, use this `jq` filter.

```
sudo journalctl -u wazuh-dashboard -o cat -f | jq -r '"[\(."@timestamp")] \( .message)"'
```

<div class="page-content" id="bkmrk-3" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div>  
</div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">3</div><div>  
</div></div></div></div>### Handling Non-JSON Errors

Sometimes the system outputs non-JSON errors (like service start failures). If the commands above fail, fall back to the raw log.

```
sudo journalctl -u wazuh-dashboard -e --no-pager
```

<div class="page-content" id="bkmrk-" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div>  
</div></div></div><div style="margin-top:32px;padding:16px;background-color:#e7f3ff;border:1px solid #d1d5da;border-left:6px solid #206afb;">  
</div></div>#### ✅ Resulting Output

By using `-o cat`, you ensure that every line passed to `jq` starts with `{`, eliminating the `parse error` you encountered.

# 📡 Fixing Disconnected Agents

#   


When an agent shows as **Disconnected**, it is usually due to a service failure on the endpoint or a network/firewall block between the endpoint and the Wazuh Manager.

<div class="page-content" id="bkmrk-1" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">1</div><div>  
</div></div></div></div>### Restart Service on Hestia VM

Log into the Hestia VM and restart the agent. This often restores the connection after a server-side outage.

```
sudo systemctl restart wazuh-agent
```

<div class="page-content" id="bkmrk-2" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div></div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">2</div><div>  
</div></div></div></div>### Verify Connection Status

Check the agent logs on the Hestia VM to see if it is successfully "handshaking" with the Manager.

```
sudo tail -f /var/ossec/logs/ossec.log | grep -iE "error|warn|connected"
```

<div class="page-content" id="bkmrk-3" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div></div></div><div style="margin-bottom:24px;"><div style="background-color:#206afb;color:#FFFFFF;width:32px;height:32px;font-weight:bold;margin-right:12px;">3</div><div>  
</div></div></div></div>### Test Connectivity to Port 1514

Wazuh agents communicate via **TCP Port 1514**. Run this from the Hestia VM to ensure the port is open on the SIEM server.

```
# Replace with your Wazuh Manager IP
nc -zv wazuh.msls.tech 1514
```

<div class="page-content" id="bkmrk-" style="font-family:'-apple-system', BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;line-height:1.5;color:#24292e;"><div style="margin-top:24px;"><div style="margin-bottom:24px;"><div></div></div></div><div style="margin-top:32px;padding:16px;background-color:#fffbdd;border:1px solid #d1d5da;border-left:6px solid #e36209;">  
</div></div>#### ⚠️ Connection Issues in Oracle Cloud

Since Hestia is in Oracle Cloud, ensure your **VCN Ingress Rules** and the **OS Firewall (ufw/iptables)** on both sides allow traffic on Port 1514.