Three jobs that look like one. Upgrading agents in 5.0 means pushing a signed WPK from the manager, and it has a version-path constraint that catches older estates. Backing up means configuration in one place and indexed data in another, through snapshots to a registered repository. Retention means Index State Management policies that the Setup plugin creates for you, with defaults measured in minutes for raw events and 90 days for findings. Get the retention defaults wrong and you will look for data that was deleted an hour after it arrived.
What you need
- Root on the manager and indexer nodes.
- Shell or API access to the manager. The API route is covered in the Wazuh API with Python.
- Dashboard access with Index Management rights, to see and edit ISM policies.
- Somewhere to put snapshots: a local directory on every indexer node, or an NFS share.
- If you run the stack in containers, the Docker deployment has its own upgrade path, covered at the end of the upgrade section.
Upgrade agents remotely
The manager sends a Wazuh signed package, a WPK file, to each enrolled agent. The WPK contains the files needed to upgrade that agent, and Wazuh publishes a WPK repository for each release.
The version path constraint
Read this before planning anything. The documentation states: “Direct upgrades to Wazuh agent 5.0.0 are not supported from Wazuh agent 4.14.0 or earlier. Upgrade the Wazuh agent in this order: 4.14.0 or earlier > 4.14.x > 5.0.0.”
That is two hops for most estates, and each hop is a separate change window with its own verification. Budget for it. A rollout plan that assumed one hop will be wrong by a factor of two in elapsed time and worse in coordination cost.
Find what needs upgrading
/var/wazuh-manager/bin/agent_upgrade -l
The documented output lists the ID, name and version of each outdated agent, with a total at the end.
Upgrade
Against the online repository, by agent ID:
/var/wazuh-manager/bin/agent_upgrade -a 011
Several at once:
/var/wazuh-manager/bin/agent_upgrade -a 002 003
With a WPK you downloaded yourself, which is what you do for an air-gapped or version-pinned rollout:
/var/wazuh-manager/bin/agent_upgrade -a 002 -f /var/wazuh-manager/tmp/wazuh_agent_v5.0.0_linux_amd64.deb.wpk
The documentation recommends downloading WPK files to /var/wazuh-manager/tmp/. The published package names follow a clear pattern:
| Platform | Package |
|---|---|
| Linux deb, x86_64 | wazuh_agent_v5.0.0_linux_amd64.deb.wpk |
| Linux deb, ARM64 | wazuh_agent_v5.0.0_linux_arm64.deb.wpk |
| Linux rpm, x86_64 | wazuh_agent_v5.0.0_linux_x86_64.rpm.wpk |
| Linux rpm, ARM64 | wazuh_agent_v5.0.0_linux_aarch64.rpm.wpk |
| Windows, 32/64-bit | wazuh_agent_v5.0.0_windows.wpk |
| macOS, Intel 64 | wazuh_agent_v5.0.0_macos_intel64.pkg.wpk |
| macOS, ARM64 | wazuh_agent_v5.0.0_macos_arm64.pkg.wpk |
The flags worth knowing: -v pins a version, -r points at a different repository, --package_type selects rpm or deb, -F forces the upgrade past version validation, and -x names the executable inside a custom WPK, defaulting to upgrade.sh.
Verify
From the manager, check the dashboard or re-run agent_upgrade -l. From the endpoint:
/var/ossec/bin/wazuh-control info
The documented output is three lines giving WAZUH_VERSION, WAZUH_REVISION and WAZUH_TYPE.
Control it from the manager side
Remote upgrade is configured in the manager’s <agent-upgrade> section, which has two options:
<agent-upgrade>
<enabled>yes</enabled>
</agent-upgrade>
enabled defaults to yes. wpk_repository sets the base URL for downloads, and if it is not set the manager builds the URL as packages.wazuh.com/<major>.x/wpk/ from its own major version. The section works with <task-manager>, which handles upgrade task status, timeouts and record cleanup.
Upgrading the Docker deployment
For a containerised stack, stop with docker compose down, edit the image tag on every Wazuh service in docker-compose.yml, and bring it back with docker compose up -d. Data and certificates survive because they live in mounted volumes. In the multi-node file that means every indexer node too, not just the manager.
Back up the configuration
Backup in 5.0 splits cleanly in two, and conflating them is how people discover on restore day that they have configuration and no data.
Indexer configuration
The documented procedure preserves file permissions, ownership and directory structure, and is explicit that it “does not back up the data stored in the Wazuh indexer”. Run it on every indexer node you want to back up.
First, back up the security configuration through the plugin’s own tool:
/usr/share/wazuh-indexer/bin/indexer-security-init.sh --options "-backup /etc/wazuh-indexer/opensearch-security -icl -nhnv"
Then create a dated destination and capture host information:
bkp_folder=~/wazuh_files_backup/$(date +%F_%H:%M) && mkdir -p $bkp_folder && echo $bkp_folder
Then copy the certificates, JVM options, log4j configuration, opensearch.yml, the keystore, the observability, security, notifications, reports scheduler and security analytics directories, and the sysctl drop-in. The full rsync -aREz command is on the backup and restore page and in the companion files for this lesson as a script.
Restore is the mirror image: stop wazuh-indexer, copy each path back, chown -R wazuh-indexer:wazuh-indexer on each one, start the service. The documentation notes the procedure is for restoring from a backup of the same version, and that in a multi-node deployment you restore the corresponding backup on each node.
Manager configuration
The 5.0 beta documentation has no manager files-backup page; that section is absent from the beta tree. What a manager backup must contain is still determinable from the rest of the documentation, and the list is short:
| Path | Why |
|---|---|
/var/wazuh-manager/etc/wazuh-manager.conf |
the manager configuration |
/var/wazuh-manager/etc/client.keys |
agent identities and keys; losing this means re-enrolling every agent |
/var/wazuh-manager/etc/authd.pass |
the enrolment password |
/var/wazuh-manager/etc/shared/ |
every group’s shared agent.conf |
| certificates | whatever the installation assistant or your own CA issued |
Do not back up merged.mg inside the shared directories: the manager regenerates it, and the migration documentation excludes it explicitly.
Snapshot the indexed data
Configuration backups do not include data. For data you register a snapshot repository and take snapshots into it.
Register a repository
On every indexer node, create the directory and give it to the service user:
mkdir /mnt/snapshots && chown wazuh-indexer:wazuh-indexer /mnt/snapshots
Add the path to /etc/wazuh-indexer/opensearch.yml:
path.repo: /mnt/snapshots
The documented example configuration also carries the two settings that make snapshot restore work with the security plugin enabled:
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.enable_snapshot_restore_privilege: true
Restart the indexer:
systemctl restart wazuh-indexer
Then register it on the dashboard: Index management > Snapshot Management > Repositories > Create repository, type Shared file system, location /mnt/snapshots.
Take and move a snapshot
Take it at Index management > Snapshot Management > Snapshots > Take snapshot, naming the snapshot and selecting the index pattern, for example wazuh-findings*. Under Advanced options you can include the cluster state and ignore unavailable indices.
To move a snapshot to another cluster, archive the repository directory and copy it:
tar -C /mnt/snapshots -cvf snapshots.tar .
On the destination node, extract into its own repository directory, restart the indexer so it picks the files up, refresh the Snapshots page, select the snapshot and Restore. The restore dialog offers all indices or specific ones, with renaming options.
For a shared repository rather than a copy, the same page covers an NFS setup with a dedicated export mounted on both clusters.
Change index retention
This is the section that surprises people, so here are the numbers first.
Wazuh rolls over a data stream when either limit is reached: 20 GB primary shard size or 200 million documents. The default retention periods are:
| Data stream | Policy | Retention |
|---|---|---|
wazuh-events-raw-v5 |
stream-raw-events-policy |
10 minutes |
wazuh-events-v5-* |
stream-events-policy |
1 hour |
wazuh-findings-v5-* |
stream-findings-policy |
90 days |
wazuh-active-responses |
stream-active-responses-policy |
3 days |
wazuh-metrics-* |
stream-metrics-policy |
30 days |
wazuh-ai-assistant-sessions |
ai-assistant-sessions-policy |
1 day, then 7 |
Those are not the documented figures, they are the shipped ones. Reading the ISM policies off a 5.0.0-beta5 install returns:
"policy_id" : "ai-assistant-sessions-policy",
"min_doc_count" : 200000000,
"min_index_age" : "1d",
"min_index_age" : "7d"
"policy_id" : "stream-active-responses-policy",
"min_doc_count" : 200000000,
"min_index_age" : "3d"
"policy_id" : "stream-events-policy",
"min_doc_count" : 200000000,
"min_index_age" : "1h"
"policy_id" : "stream-findings-policy",
"min_doc_count" : 200000000,
"min_index_age" : "90d"
"policy_id" : "stream-metrics-policy",
"min_doc_count" : 200000000,
"min_index_age" : "30d"
"policy_id" : "stream-raw-events-policy",
"min_doc_count" : 200000000,
"min_index_age" : "10m"
Six policies, one rollover document count, and the whole retention design of the platform in six numbers. The AI assistant sessions policy is the only one with two age conditions, because it moves through an intermediate state before deletion.
Ten minutes of raw events and one hour of normalised events. Those are not typos. In 5.0 the durable record is the finding; the event streams exist for triage close to the moment. If your incident process assumes you can go back a week and read the original log, that assumption does not survive a default install.
How the policies work
Rollover and retention are managed by Index State Management policies created by the Setup plugin. Each policy moves an index through two states. A new index enters the active stage and accepts data until a rollover condition is met, at which point a new active index is created and the old one stops accepting writes. The old index is kept until its retention period expires, then moves to delete and is removed, with failed deletions retried three times.
The documented policy shape is:
{
"policy": {
"policy_id": "<index-name>-policy",
"default_state": "hot",
"states": [
{
"name": "hot",
"actions": [
{
"retry": { "count": 3, "backoff": "exponential", "delay": "1m" },
"rollover": { "min_doc_count": 200000000, "min_primary_shard_size": "20gb" }
}
],
"transitions": [
{ "state_name": "delete", "conditions": { "min_index_age": "<RETENTION_TIME>" } }
]
},
{
"name": "delete",
"actions": [
{
"retry": { "count": 3, "backoff": "exponential", "delay": "1m" },
"delete": {}
}
],
"transitions": []
}
],
"ism_template": [
{ "index_patterns": ["wazuh-<pattern>-*"], "priority": <PRIORITY_INT> }
]
}
}
min_index_age on the transition into delete is the retention knob. Everything else is rollover sizing.
Policy names follow the stream, with one wrinkle: the policy that manages wazuh-events-raw-v5 is stream-raw-events-policy, not stream-raw-events-v5-policy. Verified on the 5.0.0-beta5 lab, along with the rest of the names in the table above.
Change a retention period
On the dashboard: Indexer Management > Index Management > State management policies, open the policy, and edit the min_index_age condition on the transition into the delete state.
Two notes from the OpenSearch ISM documentation, which applies directly because the indexer is an OpenSearch fork. ISM runs its job every 5 minutes by default, so conditions are evaluated on that cadence and not continuously, and it does not run at all while the cluster state is red. And an ism_template applies only to indices created after it, so a policy change does not retroactively re-manage indices that already exist.
Turn raw event indexing off
If storage is the constraint rather than retention, there is a switch. The Setup module exposes engine.index_raw_events, which controls whether raw events are indexed into wazuh-events-raw-v5 at all:
curl -sk -u <WAZUH_INDEXER_USERNAME>:<WAZUH_INDEXER_PASSWORD> -X PUT "https://127.0.0.1:9200/_plugins/_setup/settings" -H 'Content-Type: application/json' -d '{ "engine": { "index_raw_events": true } }'
Set it to false and the raw stream stops filling. The documented success response is {"message": "Settings updated successfully.", "status": 200}.
Think carefully before switching it off. Raw events are what you read when a decoder is wrong, and a decoder being wrong is the most common reason a detection does not fire. Ten minutes of raw retention is already tight; zero means you debug a decoder by reproducing the log, which is a poor position when writing a custom decoder for a source you do not control. Sizing this properly is covered in system requirements.
Common errors
agent_upgrade reports the agent is already up to date
Version validation is comparing against the repository’s latest, not against what you intended. Pin with -v, or point -r at the repository holding the version you want.
The upgrade never completes and the agent stays on the old version
Check the task manager side. <agent-upgrade> works with <task-manager>, which owns task status, timeouts and record cleanup. A stalled task is a task-manager question, not a WPK question.
A 4.x agent refuses to upgrade to 5.0.0
Expected. Direct upgrades to 5.0.0 are not supported from 4.14.0 or earlier. Go to 4.14.x first.
Snapshot repository registration fails
Three usual causes: path.repo is not set in opensearch.yml on every node, the directory is not owned by wazuh-indexer:wazuh-indexer, or the indexer was not restarted after the change. Confirm ownership with ls -l /mnt/snapshots, which the documentation calls out specifically.
The snapshot does not appear on the destination cluster
Restart the indexer on the destination after extracting the files, then refresh the Snapshots page. The repository is read at startup.
Data disappeared after an hour
That is wazuh-events-v5-* doing what it is configured to do. Findings are the durable record at 90 days. If you need events for longer, raise min_index_age on the events policy and size the disk first.
Retention reverted after an upgrade
A Wazuh-managed index template was edited instead of an ISM policy, and the Setup module rewrote it on restart. Keep changes in the policies and keep a record outside the cluster.
Next: Wazuh Cluster and Distributed Architecture.
Files for this lesson
Every file this lesson refers to, exactly as used. Open a file to read it in the browser, or download the set as a zip. Download wazuh-upgrade-backup-retention.zip. The full set for all lessons is at wazuh-tutorial-files.zip.
README.md4.3 KBbackup-indexer-config.sh1.9 KBbackup-manager-config.sh1.9 KBfindings-retention-policy.json1.4 KB
Frequently asked questions
How long does Wazuh keep data by default?
Far less than most people assume. Verified on a 5.0.0-beta5 install: 10 minutes for wazuh-events-raw-v5, 1 hour for wazuh-events-v5-*, 90 days for wazuh-findings-v5-*, 3 days for wazuh-active-responses and 30 days for the metrics streams. Data streams also roll over at 20 GB primary shard size or 200 million documents.
How do I change Wazuh index retention?
Edit the ISM policy that manages the data stream. On the dashboard, go to Indexer Management, Index Management, State management policies, and change the min_index_age condition on the transition into the delete state. Policies are named after the stream, for example stream-findings-policy.
How do I upgrade a Wazuh agent remotely?
With the agent_upgrade tool on the manager, at /var/wazuh-manager/bin/agent_upgrade, or with PUT /agents/upgrade on the manager API. Both push a signed WPK package to the agent. Use agent_upgrade -l to list outdated agents first.
Can I upgrade a 4.13 agent straight to 5.0?
No. The documentation states that direct upgrades to Wazuh agent 5.0.0 are not supported from 4.14.0 or earlier. The order is 4.14.0 or earlier, then 4.14.x, then 5.0.0. Plan two hops for any estate still on an older 4.x.
Does backing up the Wazuh indexer back up my data?
No. The documented indexer backup covers configuration only: certificates, opensearch.yml, the keystore, the security configuration and the plugin configuration directories. Indexed data needs a snapshot to a registered repository, which is a separate procedure.