Wazuh Backup and Recovery - SIEM Data Protection
Wazuh backups cover component configuration, custom rules and decoders, agent keys, API settings, and indexed data. Losing any of these elements requires a full platform reconfiguration or results in the loss of historical incident data. This guide details all critical elements to back up, available backup methods, and restore procedures.
What to Back Up
Wazuh Server (Manager)
| Element | Path | Description |
|---|---|---|
| Main configuration | /var/ossec/etc/ossec.conf | Manager configuration |
| Custom rules | /var/ossec/etc/rules/local_rules.xml | Detection rules |
| Custom decoders | /var/ossec/etc/decoders/local_decoder.xml | Log parsing decoders |
| CDB lists | /var/ossec/etc/lists/ | IoC lists and lookup tables |
| Shared agent configuration | /var/ossec/etc/shared/ | Centralized group configurations |
| Agent keys | /var/ossec/etc/client.keys | Agent authentication keys |
| API configuration | /var/ossec/api/configuration/ | RESTful API settings |
| SSL certificates | /var/ossec/etc/sslmanager.* | Agent communication certificates |
| Keystore | /var/ossec/etc/keystore/ | Stored credentials |
| Active response | /var/ossec/active-response/bin/ | Custom response scripts |
| Integrations | /var/ossec/integrations/ | Custom integration scripts |
Wazuh Indexer
| Element | Path | Description |
|---|---|---|
| Configuration | /etc/wazuh-indexer/opensearch.yml | Main configuration |
| JVM settings | /etc/wazuh-indexer/jvm.options | JVM parameters |
| Security configuration | /etc/wazuh-indexer/opensearch-security/ | Roles, users, security settings |
| SSL certificates | /etc/wazuh-indexer/*.pem | TLS certificates |
| Index data | /var/lib/wazuh-indexer/ | Indexed data (alerts, events) |
Wazuh Dashboard
| Element | Path | Description |
|---|---|---|
| Configuration | /etc/wazuh-dashboard/opensearch_dashboards.yml | Main configuration |
| SSL certificates | /etc/wazuh-dashboard/*.pem | TLS certificates |
| Plugin configuration | /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml | Wazuh plugin settings |
Filebeat
| Element | Path | Description |
|---|---|---|
| Configuration | /etc/filebeat/filebeat.yml | Main configuration |
| Index template | /etc/filebeat/wazuh-template.json | Wazuh template for the indexer |
| SSL certificates | /etc/filebeat/*.pem | TLS certificates |
Backup Methods
Filesystem Backup
The simplest method is copying critical files and directories directly.
Full manager configuration backup:
#!/bin/bash
BACKUP_DIR="/backup/wazuh/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Manager
tar czf "$BACKUP_DIR/manager-config.tar.gz" \
/var/ossec/etc/ossec.conf \
/var/ossec/etc/rules/ \
/var/ossec/etc/decoders/ \
/var/ossec/etc/lists/ \
/var/ossec/etc/shared/ \
/var/ossec/etc/client.keys \
/var/ossec/etc/sslmanager.* \
/var/ossec/etc/keystore/ \
/var/ossec/api/configuration/ \
/var/ossec/active-response/bin/ \
/var/ossec/integrations/ \
2>/dev/null
# Indexer
tar czf "$BACKUP_DIR/indexer-config.tar.gz" \
/etc/wazuh-indexer/opensearch.yml \
/etc/wazuh-indexer/jvm.options \
/etc/wazuh-indexer/opensearch-security/ \
/etc/wazuh-indexer/*.pem \
2>/dev/null
# Dashboard
tar czf "$BACKUP_DIR/dashboard-config.tar.gz" \
/etc/wazuh-dashboard/opensearch_dashboards.yml \
/etc/wazuh-dashboard/*.pem \
/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml \
2>/dev/null
# Filebeat
tar czf "$BACKUP_DIR/filebeat-config.tar.gz" \
/etc/filebeat/filebeat.yml \
/etc/filebeat/wazuh-template.json \
/etc/filebeat/*.pem \
2>/dev/null
echo "Backup completed: $BACKUP_DIR"
ls -lh "$BACKUP_DIR"Index Snapshots
For backing up indexed data (alerts, events), use the OpenSearch snapshot mechanism. This approach is far more efficient than copying data files and supports incremental snapshots.
Configuring a snapshot repository:
- Define the repository path in the indexer configuration (
/etc/wazuh-indexer/opensearch.yml):
path.repo: ["/mnt/snapshots"]- Create the directory and set permissions:
mkdir -p /mnt/snapshots
chown wazuh-indexer:wazuh-indexer /mnt/snapshots- Restart the indexer:
systemctl restart wazuh-indexer- Register the repository:
curl -sk -u admin:<PASSWORD> \
-X PUT "https://localhost:9200/_snapshot/wazuh_backup" \
-H "Content-Type: application/json" \
-d '{
"type": "fs",
"settings": {
"location": "/mnt/snapshots",
"compress": true
}
}'Creating a snapshot:
# Snapshot of all Wazuh indices
curl -sk -u admin:<PASSWORD> \
-X PUT "https://localhost:9200/_snapshot/wazuh_backup/snapshot_$(date +%Y%m%d)" \
-H "Content-Type: application/json" \
-d '{
"indices": "wazuh-alerts-*,wazuh-archives-*,wazuh-monitoring-*,wazuh-statistics-*",
"ignore_unavailable": true,
"include_global_state": false
}'Checking snapshot status:
curl -sk -u admin:<PASSWORD> \
"https://localhost:9200/_snapshot/wazuh_backup/snapshot_$(date +%Y%m%d)?pretty"Listing available snapshots:
curl -sk -u admin:<PASSWORD> \
"https://localhost:9200/_snapshot/wazuh_backup/_all?pretty"API-Based Backup
The Wazuh API enables programmatic export of configuration and data.
Exporting the agent list:
TOKEN=$(curl -sk -u wazuh-wui:<PASSWORD> \
-X POST "https://localhost:55000/security/user/authenticate?raw=true")
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/agents?limit=500" \
| jq '.data.affected_items' > /backup/wazuh/agents.jsonExporting group configuration:
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/groups" \
| jq '.data.affected_items' > /backup/wazuh/groups.jsonExporting custom rules:
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules/files?status=custom" \
| jq '.data.affected_items' > /backup/wazuh/custom-rules.jsonRestoring from Backups
Restoring Manager Configuration
- Stop the manager service:
systemctl stop wazuh-manager- Extract the backup:
tar xzf /backup/wazuh/20250101_120000/manager-config.tar.gz -C /- Validate the configuration:
/var/ossec/bin/wazuh-control config-test- Start the service:
systemctl start wazuh-managerRestoring Indices from a Snapshot
- Close the target index (if it exists):
curl -sk -u admin:<PASSWORD> \
-X POST "https://localhost:9200/wazuh-alerts-4.x-2025.01.01/_close"- Restore the snapshot:
curl -sk -u admin:<PASSWORD> \
-X POST "https://localhost:9200/_snapshot/wazuh_backup/snapshot_20250101/_restore" \
-H "Content-Type: application/json" \
-d '{
"indices": "wazuh-alerts-*",
"ignore_unavailable": true,
"include_global_state": false
}'- Monitor the restore progress:
curl -sk -u admin:<PASSWORD> \
"https://localhost:9200/_cat/recovery?v&active_only=true"Restoring Indexer Configuration
- Stop the service:
systemctl stop wazuh-indexer- Extract the configuration:
tar xzf /backup/wazuh/20250101_120000/indexer-config.tar.gz -C /- Restore the security configuration:
systemctl start wazuh-indexer
/usr/share/wazuh-indexer/bin/indexer-security-init.shDisaster Recovery Plan
In the event of a complete server loss, follow these steps:
- Install all Wazuh components from scratch (see installation )
- Stop all services
- Restore configuration from backups (manager, indexer, Dashboard, Filebeat)
- Start components in the standard order: indexer, manager, Filebeat, Dashboard
- Restore index data from snapshots
- Verify agent connectivity - agents will reconnect automatically if
client.keyshas been restored
For recovery to a different environment (different IP address):
- Update IP addresses in each component’s configuration
- Reissue SSL certificates if necessary
- Update agent configuration with the new manager address
Backup Automation
Daily Backup Script
Create the script at /usr/local/bin/wazuh-backup.sh:
#!/bin/bash
set -euo pipefail
BACKUP_BASE="/backup/wazuh"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_BASE/$DATE"
ADMIN_PASS="<PASSWORD>"
mkdir -p "$BACKUP_DIR"
# Manager configuration
tar czf "$BACKUP_DIR/manager-config.tar.gz" \
/var/ossec/etc/ossec.conf \
/var/ossec/etc/rules/ \
/var/ossec/etc/decoders/ \
/var/ossec/etc/lists/ \
/var/ossec/etc/shared/ \
/var/ossec/etc/client.keys \
/var/ossec/etc/sslmanager.* \
/var/ossec/api/configuration/ \
2>/dev/null || true
# Indexer configuration
tar czf "$BACKUP_DIR/indexer-config.tar.gz" \
/etc/wazuh-indexer/opensearch.yml \
/etc/wazuh-indexer/jvm.options \
/etc/wazuh-indexer/opensearch-security/ \
2>/dev/null || true
# Index snapshot
curl -sk -u admin:"$ADMIN_PASS" \
-X PUT "https://localhost:9200/_snapshot/wazuh_backup/snapshot_$DATE" \
-H "Content-Type: application/json" \
-d '{
"indices": "wazuh-alerts-*,wazuh-archives-*",
"ignore_unavailable": true,
"include_global_state": false
}' > /dev/null 2>&1
# Remove old backups
find "$BACKUP_BASE" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
# Remove old snapshots
for snap in $(curl -sk -u admin:"$ADMIN_PASS" \
"https://localhost:9200/_snapshot/wazuh_backup/_all" \
| jq -r '.snapshots[] | select(.start_time < "'$(date -d "-${RETENTION_DAYS} days" +%Y-%m-%dT%H:%M:%S)'") | .snapshot'); do
curl -sk -u admin:"$ADMIN_PASS" \
-X DELETE "https://localhost:9200/_snapshot/wazuh_backup/$snap" > /dev/null 2>&1
done
echo "$(date): Backup completed successfully" >> /var/log/wazuh-backup.logCron Configuration
chmod +x /usr/local/bin/wazuh-backup.sh
# Daily backup at 02:00
echo "0 2 * * * root /usr/local/bin/wazuh-backup.sh" > /etc/cron.d/wazuh-backupTroubleshooting
Snapshot Creation Fails
Verify the repository registration:
curl -sk -u admin:<PASSWORD> \
"https://localhost:9200/_snapshot/wazuh_backup?pretty"Confirm that the snapshot directory exists and is writable by the wazuh-indexer user.
Snapshot Restore Fails
The most common cause is that an index with the same name is already open. Close or delete the existing index before restoring:
curl -sk -u admin:<PASSWORD> \
-X POST "https://localhost:9200/wazuh-alerts-4.x-2025.01.01/_close"Agents Do Not Connect After Restore
Verify that client.keys was restored correctly and contains entries for all agents:
wc -l /var/ossec/etc/client.keysIf necessary, re-register agents through the agent management API .
Related Sections
- Upgrading Wazuh - creating backups before upgrades
- Troubleshooting - diagnosing issues after restore
- Indexer Cluster - snapshots in cluster configurations