Wazuh
Server install
(Taken from the quick start guide)
curl -sO https://packages.wazuh.com/4.x/wazuh-install.sh && sudo bash ./wazuh-install.sh -a
As install finishes, keep an eye out for your default admin password. If you miss it:
sudo tar -O -xvf wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt
Make groups for your endpoints to drop into
/var/ossec/bin/agent_groups -a -g Windows -q
/var/ossec/bin/agent_groups -a -g macOS -q
/var/ossec/bin/agent_groups -a -g Linux -q
Add agents
Head to https://your.wazuh-server.com/app/endpoints-summary#/agents-preview/deploy to fill out the connection info to generate an install file for the appropriate OS.
Check if Wazuh is running
systemctl status wazuh-manager
Main config file to edit
sudo nano /var/ossec/etc/ossec.conf
Review server logs/statuses
systemctl status wazuh-manager
systemctl status wazuh-indexer
sudo tail -f /var/ossec/logs/ossec.log
sudo cat /var/log/wazuh-indexer/wazuh-cluster.log
sudo filebeat test output
Starting/restarting services if necessary
sudo systemctl restart wazuh-indexer
sudo systemctl restart wazuh-manager
Reset all passwords
Read more about password resets here.
For single-node Wazuh deployments (4.x). Resets all indexer passwords and updates the dashboard so it can still authenticate.
Pre-flight checks
Before running the password tool, the indexer cluster must be healthy (yellow or green, not red). If it's red, the tool will hang on "wait for YELLOW clusterstate" forever.
# Verify indexer is running and listening
sudo systemctl status wazuh-indexer
sudo ss -tlnp | grep 9200
# Verify cluster health (must be yellow or green)
sudo curl -k --cert /etc/wazuh-indexer/certs/admin.pem \
--key /etc/wazuh-indexer/certs/admin-key.pem \
https://127.0.0.1:9200/_cluster/health?pretty
Also verify ownership on the backup directory — root-owned files here cause silent failures:
sudo ls -la /etc/wazuh-indexer/ | grep backup
# Should show: drwxr-x--- wazuh-indexer wazuh-indexer
# If owned by root, fix it:
sudo chown -R wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/backup
sudo chmod 750 /etc/wazuh-indexer/backup
Step 1: Reset all indexer passwords
sudo /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh -a -v 2>&1 | sudo tee /root/wazuh-pw-reset-$(date +%Y%m%d-%H%M).log
What the flags mean:
-a— change ALL internal users (auto-generate new passwords)-v— verbose-A— also rotate the Wazuh API admin password (requires current API creds; skip if unknown)-u USER -p PASS— change a single user to a specific password
Save these from the output to your password manager:
admin← used for browser loginkibanaserver← used by dashboard service to talk to indexerkibanaro,logstash,readall,snapshotrestore,anomalyadmin← rarely used directly, but save them
The script also auto-updates the filebeat keystore for you (no manual step needed).
After saving passwords:
sudo shred -u /root/wazuh-pw-reset-*.log
Step 2: Update dashboard keystore (required after admin/kibanaserver password change)
The dashboard authenticates to the indexer using credentials in its keystore. After a password reset, this keystore is stale.
# Update the dashboard's stored username (should be kibanaserver, not admin)
sudo /usr/share/wazuh-dashboard/bin/opensearch-dashboards-keystore remove opensearch.username --allow-root
sudo /usr/share/wazuh-dashboard/bin/opensearch-dashboards-keystore add opensearch.username --allow-root
# At prompt: kibanaserver
# Update the password
sudo /usr/share/wazuh-dashboard/bin/opensearch-dashboards-keystore remove opensearch.password --allow-root
sudo /usr/share/wazuh-dashboard/bin/opensearch-dashboards-keystore add opensearch.password --allow-root
# At prompt: paste the kibanaserver password
Important: the dashboard service uses kibanaserver to query the indexer, NOT admin. Browser login uses admin, but that's separate.
Step 3: Restart services in the right order
sudo systemctl restart filebeat
sudo systemctl restart wazuh-dashboard
wazuh-indexer and wazuh-manager don't need restarting after password changes.
Step 4: Verify
# Filebeat → indexer connection
sudo filebeat test output
# Dashboard logs (look for "Server running at" — no [ResponseError] floods)
sudo journalctl -u wazuh-dashboard -n 30 --no-pager
# Browser login: https://<wazuh-ip> as admin
Resetting the Wazuh API admin password (separate procedure)
The Wazuh API (port 55000) has its OWN users, separate from the indexer:
wazuh— API admin used by external tools, scripts, integrations (n8n, etc.)wazuh-wui— service account the dashboard uses to talk to the manager API
Either user can authenticate the rotation tool, but wazuh-wui is preferred because its current password is always recoverable from the dashboard config (see Method A).
Password rules: 8–64 chars, must contain upper + lower + number + at least one of .*+?-. No !@#$%^&*() etc.
⚠️ Avoid these characters in new passwords:
'(single quote),"(double quote),\(backslash), or a leading-. The password tool fails silently on these — see the gotcha below.
Method A: rotate via wazuh-wui (recommended)
The wazuh-wui password is stored in plaintext in the dashboard config:
sudo grep -A1 'username: wazuh-wui' /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
# Use the UNCOMMENTED block — the ones starting with # are template examples
Capture passwords interactively with read so they never appear as command-line literals (this avoids most shell-escaping pitfalls):
read -rsp "Current wazuh-wui password: " WUIPASS; echo
read -rsp "New wazuh password: " NEWPASS; echo
echo "WUI length: ${#WUIPASS}, NEW length: ${#NEWPASS}" # sanity check
sudo bash /usr/share/wazuh-indexer/plugins/opensearch-security/tools/wazuh-passwords-tool.sh \
-A \
-au wazuh-wui -ap "$WUIPASS" \
-u wazuh -p "$NEWPASS"
Always verify — the tool prints INFO: The password for Wazuh API user wazuh is <newpass> even when the change failed. Confirm with an actual auth attempt:
TOKEN=$(curl -sk -u wazuh:"$NEWPASS" \
-X POST "https://localhost:55000/security/user/authenticate?raw=true")
echo "Token length: ${#TOKEN} (should be 300+, starting with 'eyJ')"
echo "Start: ${TOKEN:0:30}"
# A failure looks like: {"title": "Unauthorized", "detail": "Invalid credentials"}
unset WUIPASS NEWPASS
If verification fails, you can re-run the rotation immediately — wazuh-wui is still working since you haven't touched it.
Method B: emergency recovery (no working API admin)
If neither wazuh nor wazuh-wui are known, you'll need to edit the API user file directly. See Wazuh docs — involves editing /var/ossec/api/configuration/security/users.yaml and running a Python tool.
After rotation: update dashboard config (only if you rotated wazuh-wui)
If you rotated wazuh-wui (not just wazuh), the dashboard needs the new password:
sudo cp /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml{,.bak-$(date +%F)}
sudo nano /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
# Update the password field for the API connection
sudo systemctl restart wazuh-dashboard
Rotating only wazuh (the typical case) requires no dashboard changes.
Common password reset gotchas
ERR: Seems there is no OpenSearch running on 127.0.0.1:9200— indexer is down or unhealthy. Don't proceed; fix indexer first.- Tool hangs on "wait for YELLOW clusterstate" — cluster is red OR memory-starved (check heap via
ps -ef | grep Xmx). Fix cluster first. AccessDeniedException: /etc/wazuh-indexer/backup— directory ownership wrong.chown -R wazuh-indexer:wazuh-indexer.- Dashboard "Server is not ready yet" +
[ResponseError]loop — keystore credentials don't match what's in the indexer. Re-run the keystore update with kibanaserver creds. - Don't reuse passwords across users — script auto-generates strong unique ones, just save them.
- Password tool fails silently on certain characters in API rotations — single quotes (
'), double quotes ("), backslashes (\), or a leading-in new passwords cause an internalcurlerror buried mid-output, followed by a misleadingINFO: The password for Wazuh API user X is <newpass>line. The change does NOT take effect. Always verify with a token request after rotation. Useread -rspto capture passwords interactively rather than pasting them as command-line literals.
Upgrading Wazuh central components
Single-node, in-place upgrade procedure for wazuh-indexer, wazuh-manager, wazuh-dashboard, plus a Filebeat module/template refresh. Procedure tested upgrading 4.12.0 → 4.14.5 on Ubuntu Noble. The version-specific bits (the CDB list edit, the Filebeat module version) may not apply to every upgrade — read the official release notes for your target version first.
⚠️ No indexer downgrade past 4.12. Apache Lucene format changed. A VM/host snapshot is your real rollback. Index snapshots are the documented protection if you want to recover data without rolling the whole VM back.
Pre-flight
Take a VM/host snapshot first (Proxmox, ESXi, etc.). This is your rollback path.
Then on the Wazuh box, confirm starting state:
# Currently running version (sudo required — wazuh-control isn't world-executable)
sudo /var/ossec/bin/wazuh-control info | head -3
# All four services healthy
systemctl is-active wazuh-manager wazuh-indexer wazuh-dashboard filebeat
# Indexer cluster green
read -rsp "Indexer admin password: " IPASS; echo
curl -sk -u "admin:$IPASS" https://localhost:9200/_cluster/health?pretty
# Confirm package versions and target is available
dpkg -l | grep -E '^ii\s+(wazuh-manager|wazuh-indexer|wazuh-dashboard|filebeat)' | awk '{print $2, $3}'
sudo apt-get update
apt-cache policy wazuh-indexer | head -10
You should see your target version listed as Candidate. The default Wazuh apt repo (packages.wazuh.com/4.x/apt/) auto-tracks the latest 4.x release; if you've pinned to a specific minor, update the repo file before continuing.
Note Filebeat-OSS version. It often stays the same across Wazuh upgrades (e.g. 7.10.2 spans many Wazuh 4.x releases). Only the wazuh-filebeat module and template need refresh in that case, not the Filebeat package itself.
Step 1: Prepare the indexer
Stop Filebeat and the dashboard. Indexer keeps running so we can prep it via the API.
sudo systemctl stop filebeat wazuh-dashboard
# Backup security configuration (re-applied after upgrade if needed)
sudo /usr/share/wazuh-indexer/bin/indexer-security-init.sh \
--options "-backup /etc/wazuh-indexer/opensearch-security -icl -nhnv"
# Look for: "Clusterstate: GREEN" and a list of "SUCC: ..." lines
# Disable shard replication during the restart
curl -sk -X PUT "https://localhost:9200/_cluster/settings" \
-u "admin:$IPASS" \
-H 'Content-Type: application/json' \
-d '{"persistent":{"cluster.routing.allocation.enable":"primaries"}}'
# Flush translog to disk
curl -sk -X POST "https://localhost:9200/_flush" -u "admin:$IPASS"
Step 2: Upgrade the indexer
sudo apt-get install wazuh-indexer=<NEW_VERSION>-1
⚠️ Answer
N(or just press Enter) to every dpkg config prompt during the upgrade. Keeping your current configs preserves: heap size injvm.options, RBAC mappings inroles_mapping.yml, hashed passwords ininternal_users.yml, TLS cert paths, and any other customizations. Accepting the maintainer's version onjvm.optionsresets the indexer to a 1GB heap and will likely OOM on restart.
The postinst script auto-restarts the indexer.
# Verify the package landed
systemctl is-active wazuh-indexer
dpkg -l wazuh-indexer | tail -1
# Fix backup directory ownership if it got recreated as root
sudo ls -ld /etc/wazuh-indexer/backup 2>/dev/null
sudo chown -R wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/backup
sudo chmod 750 /etc/wazuh-indexer/backup
After the indexer comes up, expect cluster status to be RED with many unassigned shards — that's the shard allocation override we set in Step 1. Re-enable allocation:
curl -sk -X PUT "https://localhost:9200/_cluster/settings" \
-u "admin:$IPASS" \
-H 'Content-Type: application/json' \
-d '{"persistent":{"cluster.routing.allocation.enable":null}}'
# Watch recovery (Ctrl+C when status is green and unassigned_shards is 0)
watch -n 5 "curl -sk -u 'admin:\$IPASS' https://localhost:9200/_cluster/health?pretty"
Recovery time depends on shard count. Hundreds of shards on a single node typically take 2–5 min.
⚠️ The
watchcommand above puts your password in the terminal scrollback because the variable expands at invocation. After the upgrade is done:history -c && history -w && clear(or just close the terminal session).
Step 3: Upgrade the manager
sudo apt-get install wazuh-manager=<NEW_VERSION>-1
Same prompt rules — N to keep your existing configs (especially ossec.conf if it shows up, though dpkg often won't prompt on it).
The postinst auto-restarts the manager. Verify:
systemctl is-active wazuh-manager
sudo /var/ossec/bin/wazuh-control info | head -3
Manager-side post-upgrade tasks
If upgrading from 4.12.x or earlier, manually add the new malicious-IOC CDB lists to your <ruleset> block in ossec.conf. The package install drops the data files in /var/ossec/etc/lists/malicious-ioc/ but doesn't register them in your config.
# Backup first
sudo cp /var/ossec/etc/ossec.conf /var/ossec/etc/ossec.conf.bak-pre-cdb-$(date +%F)
# Confirm IOC files shipped with the package
sudo ls /var/ossec/etc/lists/malicious-ioc/
# Insert the three <list> entries after the existing security-eventchannel line
sudo sed -i '/<list>etc\/lists\/security-eventchannel<\/list>/a\ <list>etc/lists/malicious-ioc/malware-hashes</list>\n <list>etc/lists/malicious-ioc/malicious-ip</list>\n <list>etc/lists/malicious-ioc/malicious-domains</list>' /var/ossec/etc/ossec.conf
# Verify the patch landed
sudo grep -n -A 12 '<ruleset>' /var/ossec/etc/ossec.conf | head -20
# Restart manager and watch the log for errors
sudo systemctl restart wazuh-manager
sudo tail -30 /var/ossec/logs/ossec.log
You're looking for clean INFO lines — modules starting, indexer-connector links to inventory indices, SCA scan finishing. Any ERROR or CRITICAL lines, especially ones that mention parsing the new <list> entries, mean roll back to the backup.
Step 4: Refresh Filebeat module + template
The Filebeat package often stays the same version across Wazuh releases. The Wazuh module (parsing logic) and alerts template (index mapping) must match the new Wazuh version.
# Replace the module version with the one current to your target Wazuh release
# (verify at packages.wazuh.com/4.x/filebeat/)
curl -s https://packages.wazuh.com/4.x/filebeat/wazuh-filebeat-0.5.tar.gz \
| sudo tar -xvz -C /usr/share/filebeat/module
# Replace v<NEW_VERSION> with your target tag (e.g. v4.14.5)
sudo curl -so /etc/filebeat/wazuh-template.json \
https://raw.githubusercontent.com/wazuh/wazuh/v<NEW_VERSION>/extensions/elasticsearch/7.x/wazuh-template.json
sudo chmod go+r /etc/filebeat/wazuh-template.json
# Start Filebeat and test
sudo systemctl start filebeat
sudo systemctl is-active filebeat
sudo filebeat test output
filebeat test output should end with talk to server... OK.
Step 5: Upgrade the dashboard
sudo apt-get install wazuh-dashboard=<NEW_VERSION>-1
⚠️
Nto all config prompts. Critical: the maintainer'sopensearch_dashboards.ymlhas generic cert paths — accepting it breaks HTTPS access. The maintainer'swazuh.ymlhas default API creds — accepting it points the dashboard at non-existent credentials and breaks login.
The dashboard's .service file in /etc/systemd/system/ does get replaced silently (it's not a tracked config file). Reload systemd before starting. Postinst does not auto-start the dashboard:
sudo systemctl daemon-reload
sudo systemctl start wazuh-dashboard
# Dashboard takes 30-60 sec to fully come up
sleep 30
sudo systemctl is-active wazuh-dashboard
sudo journalctl -u wazuh-dashboard -n 40 --no-pager
Look for http server running at https://0.0.0.0:443 and an absence of [ResponseError] floods. The agentkeepalive:deprecated warnings are bundled-Node-library noise — ignore them.
Step 6: Verify in browser
Critical: use incognito or clear your browser cache. Dashboard plugin assets get aggressively cached and you'll see the old UI even though the server is on the new version.
- Hit
https://<wazuh-ip>and log in asadmin - Click
?(top-right) → confirm new version is shown - Endpoints Summary → all agents listed
- Server management → Status → all manager daemons running
- Discover / alerts → recent alerts arriving (Filebeat shipping confirmed)
Final cleanup
# Re-enable autostart on services that may have been stopped during upgrade
sudo systemctl is-enabled wazuh-indexer wazuh-manager wazuh-dashboard filebeat
# Anything that says 'disabled', enable: sudo systemctl enable <service>
# Eyeball dpkg leftover .new and .dpkg-* files (the maintainer versions you declined)
sudo find /etc/wazuh-* /etc/filebeat -name '*.dpkg-*' -o -name '*.new' 2>/dev/null
# Diff against your live configs to see if there are useful new defaults to merge,
# then delete them when you're satisfied
# Scrub terminal scrollback (your indexer admin password was visible during 'watch')
history -c && history -w
clear
unset IPASS
Common upgrade gotchas
- Always
Non dpkg config prompts. Accepting maintainer versions during an upgrade nukes your customizations. The most expensive mistakes:jvm.options(heap → 1GB → OOM on restart),internal_users.yml(resets all internal user passwords),opensearch_dashboards.yml(TLS cert paths break),wazuh.yml(API service account creds reset). - Cluster goes RED right after indexer restart. Expected — you set allocation to "primaries" only in pre-flight. Set it back to
null(default) and wait for recovery. - Browser cache lies. After dashboard upgrade, the version banner may show old until you incognito or hard-refresh. Plugin assets cache aggressively.
agentkeepalive:deprecatedwarnings in dashboard logs. Bundled Node library deprecations. Not errors.- Filebeat package version != Filebeat module version. The Filebeat package may stay at 7.10.2 across many Wazuh releases. The wazuh-filebeat module and alerts template still need refreshing per upgrade.
- CDB list registration is manual when crossing 4.12.x. Coming from 4.12 or earlier, the new malicious-ioc lists drop on disk but don't get registered in
ossec.confautomatically. Add the three<list>entries by hand. - No indexer downgrade past 4.12. Apache Lucene format change is one-way. VM snapshot is your rollback, not
apt-get install <older-version>. /etc/wazuh-indexer/backupownership. May get recreated as root by the indexer-security-init script or postinst. Should bewazuh-indexer:wazuh-indexer.- Dashboard postinst doesn't auto-start the service. Indexer and manager postinst scripts auto-start; dashboard does not.
systemctl start wazuh-dashboardis on you.
Agents
Starting/restarting services
Linux:
sudo systemctl daemon-reload
sudo systemctl enable wazuh-agent
sudo systemctl start wazuh-agent
sudo tail -f /var/ossec/logs/ossec.log
Macs:
sudo /Library/Ossec/bin/wazuh-control restart
Windows:
NET STOP WazuhSvc
NET START WazuhSvc
Upgrading agents
Agents are upgraded after central components, in a separate pass. A 4.x manager can manage agents up to several minor versions older, so this isn't urgent — keep the manager ahead, agents will follow. Don't rush an agent upgrade pass during a client engagement; pick a quiet hour. Procedure tested upgrading a mixed Linux / macOS / Windows fleet from 4.12.0 → 4.14.5.
Pre-flight
In the dashboard, Endpoints Summary shows all agents with current versions (red dot = outdated) and connection status. Before kicking off:
- Disconnected agents won't take a remote upgrade. Either bring them online first, decommission them with
manage_agents, or skip them and come back later. - Identify a low-stakes canary first — a utility/dev box, not a production-critical or client-data box. Test the procedure on the canary before fanning out.
- Note the agent IDs you want to upgrade. Each row in Endpoints Summary shows the ID (e.g., 001, 003).
Method A: Remote upgrade via the manager CLI (preferred for Linux & Windows)
Run from the manager box. No SSH/console access to the agent needed — the manager pushes a WPK package to the agent over the existing 1514 channel and the agent self-installs and restarts.
# Upgrade a single agent
sudo /var/ossec/bin/agent_upgrade -a <AGENT_ID>
# In another terminal, watch the manager log to confirm
sudo tail -f /var/ossec/logs/ossec.log | grep -iE 'upgrade|agent_upgrade'
Expected synchronous output:
Upgrading...
Upgraded agents:
Agent <ID> upgraded: Wazuh v<OLD> -> Wazuh v<NEW>
A few seconds later, async confirmation in the manager log:
wazuh-modulesd:agent-upgrade: INFO: (8164): Received upgrade notification from agent '<ID>'. Error code: '0', message: 'Upgrade was successful'
Whole thing takes ~30 sec per agent. Verify in the dashboard that the version flips and status stays active.
⚠️ The CLI's
-aflag does NOT accept comma-separated lists on current versions —-a 004,008is parsed as a single agent ID"004,008"and fails withError 1701 - Agent does not exist. Run sequentially:sudo /var/ossec/bin/agent_upgrade -a 004 sudo /var/ossec/bin/agent_upgrade -a 008If you need batch parallelism, use Method B.
⚠️ macOS agents fail/hang on remote WPK upgrades in current versions (especially in mixed AMD64/ARM64 environments — see wazuh#26455). For Macs, use Method C.
Method B: Remote upgrade via the API (batch / programmatic)
The API accepts comma-separated agent lists cleanly, useful for fanning out:
read -rsp "wazuh-wui password: " WUIPASS; echo
TOKEN=$(curl -sk -u wazuh-wui:"$WUIPASS" \
-X POST "https://localhost:55000/security/user/authenticate?raw=true")
# Upgrade multiple agents at once
curl -sk -H "Authorization: Bearer $TOKEN" \
-X PUT "https://localhost:55000/agents/upgrade?agents_list=<ID1>,<ID2>,<ID3>"
# Or all eligible agents (macOS gets skipped automatically)
sudo /var/ossec/bin/agent_upgrade -a all
unset WUIPASS
Method C: Local upgrade (required for macOS, fallback for any failed remote)
Re-run the platform installer over the existing agent. Configuration (manager IP, agent key, groups) is preserved.
Linux
# On the agent box
sudo apt-get install wazuh-agent=<NEW_VERSION>-1 # Debian/Ubuntu
# or
sudo yum install wazuh-agent-<NEW_VERSION>-1 # RHEL/CentOS/Rocky
macOS
Pick the right architecture: arm64 for Apple Silicon (M-series), intel64 for Intel.
# Confirm arch
uname -m # arm64 or x86_64
# Download
cd /tmp
curl -O https://packages.wazuh.com/4.x/macos/wazuh-agent-<NEW_VERSION>-1.arm64.pkg
# or wazuh-agent-<NEW_VERSION>-1.intel64.pkg
# Verify Apple-issued signature before installing
pkgutil --check-signature wazuh-agent-<NEW_VERSION>-1.arm64.pkg | head -5
# Look for: "signed by a developer certificate issued by Apple for distribution"
# "Notarization: trusted by the Apple notary service"
# Install — DO NOT set WAZUH_MANAGER (that's for fresh enrollments only)
sudo installer -pkg wazuh-agent-<NEW_VERSION>-1.arm64.pkg -target /
# Verify version
sudo /Library/Ossec/bin/wazuh-control info
⚠️ macOS quirk: daemons don't auto-start after install. The
installercommand exits successfully and reports "The upgrade was successful," butwazuh-control statuswill show all 5 daemons as "not running." Always start them manually:sudo /Library/Ossec/bin/wazuh-control start sudo /Library/Ossec/bin/wazuh-control status # confirm all 5 are "is running"If
wazuh-control startdoesn't take, fall back to:sudo launchctl bootstrap system /Library/LaunchDaemons/com.wazuh.agent.plist
⚠️ Don't pass
WAZUH_MANAGERenv var on upgrades. That variable is for fresh enrollments — it tells the installer which manager to register against. On an upgrade with an existingclient.keys, setting it can confuse the registration state. Plaininstaller -pkg ... -target /preserves enrollment.
Cleanup after success:
rm /tmp/wazuh-agent-<NEW_VERSION>-1.arm64.pkg
Windows
If Method A failed for Windows, RDP/console to the box and:
:: From an Admin cmd prompt
cd %TEMP%
curl -O https://packages.wazuh.com/4.x/windows/wazuh-agent-<NEW_VERSION>-1.msi
msiexec /i wazuh-agent-<NEW_VERSION>-1.msi /q
sc query WazuhSvc
Service auto-restarts on Windows; no manual start step needed.
Common agent upgrade gotchas
- CLI
-adoesn't accept comma lists. Use the API for batches, or run the CLI sequentially per agent ID. - Disconnected agents skip remote upgrade. They sit on the old version until they reconnect; re-issue
agent_upgradeonce they're back online (or just leave it — they'll catch up on next sync if the manager queues the task). - macOS remote (WPK) upgrade is unreliable. Use local install on Macs.
- macOS daemons don't auto-start post-upgrade. Always run
wazuh-control startafterinstaller. - Don't include
WAZUH_MANAGERenv var on macOS upgrades. It's a fresh-install thing; can confuse the existing enrollment. - Windows remote upgrade works fine (per our testing), but if it fails, local MSI install over the top is a clean fallback.
- Agent log warning
No rootcheck_trojans file: 'etc/shared/rootkit_trojans.txt'is unrelated to the upgrade. It's a config push from the manager; if it persists, check the agent's group is configured correctly on the manager side. - Sub-version compatibility: an agent can be older than the manager (back several minor versions), but never newer. Don't install a 4.15 agent against a 4.14 manager.