Connector configuration
The connector reads /etc/vesper/connector.yaml. The installer writes a
working default. Most installs never need to touch it.
The default configuration
# Vesper Connector configuration.
# Targets default to localhost. The connector runs on the Wazuh node.
# Credentials are LEFT BLANK on purpose: the connector auto-discovers them from
# the local Wazuh install. Indexer creds come from the filebeat keystore, and
# Wazuh API creds from the dashboard config or .kibana. Set them here only to
# override.
# Nothing read here ever leaves this machine.
connect_url: "wss://connect.vesper.wazuh.com"
indexer:
url: "https://localhost:9200"
insecure_skip_verify: true
wazuh_api:
url: "https://localhost:55000"
insecure_skip_verify: true
exec:
enabled: false
upgrade:
enabled: true
download_host: "dl.vesper.wazuh.com"
heartbeat_seconds: 30
request_timeout_seconds: 30
Every key it accepts is listed in the key reference at the foot of this page. A key the file leaves out falls back to its default, so a short file is not an incomplete one.
Credentials: auto-discovered, never uploaded
The indexer and Wazuh API credential fields are intentionally blank. On start, the connector discovers them from the local Wazuh install itself. Set explicit values only to override discovery, for example when the indexer is not local to this node.
Whatever the source, credentials are used on the box to call localhost
services and are never sent to Vesper. They live in this file, on your machine,
and nowhere else. Vesper stores no password for your Wazuh: if you ever need to
change one, you change it here and restart the connector, and there is nothing
to update on our side.
Where it looks, per Wazuh major
Wazuh 5.0 moved both stores, so the connector reads different places depending on what it finds installed. It detects the major from the host itself, not from the API, so it still knows which to look for when no credential works yet.
| Wazuh 4.x | Wazuh 5.x | |
|---|---|---|
| Wazuh API | the dashboard's wazuh.yml, then the .kibana index | wazuh_core.hosts in /etc/wazuh-dashboard/opensearch_dashboards.yml |
| Indexer | the filebeat keystore | no automatic source, as described below |
On Wazuh 5.x there is no filebeat, so there is no keystore to read and the indexer credential has to be set by hand. The connector says so at startup rather than reporting a failure, because on 5.x the missing keystore is the expected state and not a fault:
indexer creds: none discovered (Wazuh 5 has no filebeat keystore) — set
indexer.username/password in the config to enable indexer reads
Set it like any other override, and restart the connector:
indexer:
url: "https://localhost:9200"
insecure_skip_verify: true
username: "admin"
password: "…"
Until it is set the indexer refuses every read with 401 Unauthorized, and both
majors behave the same way once the credential is there. Only the indexer tools
are affected: the alert searches and the index health read report that credential
as the reason and the console repeats it beside the indexer row, while everything
that goes through the Wazuh API keeps working. The agent is told as much, so it
does not read a refused indexer as a broken estate.
When nothing is discovered: "Invalid credentials" on every read
If the connector shows as online and every read still comes back
401 Unauthorized: Invalid credentials, this is why, and it is the one failure
that looks like a broken connector when the connector is fine.
Discovery needs the credential to be written down somewhere on this host, which means it needs the dashboard installed here. On a manager-only node, or when the manager is remote, nothing local knows the API password and the connector cannot invent one. Since v1.16.1 the installer detects this case and asks for the credential on the terminal, see distributed nodes. A connector installed before that, or installed without a terminal, logs a single line at startup naming the file to edit:
wazuh api creds: none discovered — set wazuh_api.username/password in
/etc/vesper/connector.yaml (nothing on this host advertises them)
Set the two fields, restart the connector, and the reads start working:
wazuh_api:
url: "https://localhost:55000"
insecure_skip_verify: true
username: "wazuh-wui"
password: "…"
Until then the console shows the detected Wazuh version next to the connector's
status, with a note pointing at this file. Reads answer 401 Invalid credentials and nothing is changed on the host.
Setting them by hand
Both targets take the same two fields. The indexer's are the ones a Wazuh 5.x host has to fill in, for the reason above:
indexer:
url: "https://localhost:9200"
insecure_skip_verify: true
username: "admin"
password: "…"
Set both fields, or neither. The connector decides whether to discover a
target by looking at its username alone. A username with the password left
blank therefore switches discovery off and authenticates with no password, so
every read fails. Half-filling one target is worse than leaving it alone.
The installer writes this file 0640 and owned by root, so a password put
here is not readable by other accounts on the host. It still goes no further
than the host: the connector uses it to call localhost and returns only the
response.
A node installed through Wazuh Fleet has no such file. Its Wazuh login is typed in Vesper instead, from the Set Wazuh credentials button on that host's node. Vesper sends it to the node and does not store it. The node keeps it only while it stays in that environment: a host that leaves one and is added again asks for the login again. The indexer login and the Wazuh API login are each optional, and a host may have neither. See the install guide's Wazuh Fleet section for that path.
Pointing discovery somewhere else
Three keys move where discovery looks, for an install that keeps these files outside their usual place. Leave a key blank to read the default on the right.
| Key | Default it replaces |
|---|---|
indexer.keystore_path | /var/lib/filebeat/filebeat.keystore |
dashboard_config | /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml |
dashboard_opensearch_yml | /etc/wazuh-dashboard/opensearch_dashboards.yml |
The last two are separate keys rather than one overridable path because the 4.x and 5.x files have different shapes. Moving where one is read from must not quietly redirect the reader for the other.
What the connector discovers about its node
Besides credentials, the connector reads what kind of Wazuh node its host is, from the configuration files already on the disk and without any credential. It re-reads them on every heartbeat, so a worker promoted to master or a component added to a host is reflected in the console without a restart.
| Node kind | What the host runs | What is read |
|---|---|---|
aio | manager, indexer and dashboard together | everything below |
manager-master | a manager whose cluster block is enabled with type master | the cluster block of the manager configuration: cluster name, node name and node type |
manager-worker | a manager whose cluster block is enabled with type worker | the same block |
manager | a manager with the cluster disabled or with no cluster block | the same block, when present |
indexer | an indexer node | cluster.name and node.name from the indexer configuration |
dashboard | a dashboard node | which indexer hosts and which Wazuh API hosts the dashboard points at, addresses only |
agent | only a Wazuh agent | nothing beyond the agent being installed |
bare | nothing is installed on the host yet | nothing |
mixed | any other combination, such as indexer and dashboard on one host | the blocks of the components present |
unknown | a connector from before agent and bare existed, which cannot tell them apart | nothing |
The kind cannot be set by hand, in this file or in the console. What the
connector finds is what is reported. An agent co-installed on a server node does
not change that node's kind: the agent only decides the kind when it is alone. A
host where nothing is installed yet reports bare, and the agent is told not to
look for a layout there. A node that reports unknown gets the same caution:
the agent does not assume any layout for it.
On a manager node the connector also reports the cluster membership as Wazuh
lists it: every manager node with its name, type, version and address. It reads
it through the Wazuh API when a credential is available, and from the manager's
own cluster_control -l when none is, on both majors, so the list is reported
even while the API credential is what is broken. On an indexer node it reports the
indexer nodes from _cat/nodes. Membership is collected every five minutes
rather than on every heartbeat. Only names, types, versions and addresses are
sent. No credential and no cluster key ever leaves the host.
The heartbeat also tells apart a target that is unreachable from one that is
not on this node. A worker has no indexer and an indexer node has no Wazuh
API, so on those hosts the connector does not probe localhost for the missing
component and reports it as absent rather than as down. A target whose url in
this file points at another host is always probed, whatever is installed
locally.
exec: the fix capability
exec.enabled, false by default, lets the agent run shell commands on the
host, which is what turns a diagnosis into a fix. It is the only switch that
lets the agent change anything on the host. With it off, the agent reads and
diagnoses in every mode, including Auto, and changes nothing. It is
arbitrary remote execution by design, so it is off unless the connector was
installed with --enable-exec. On a Wazuh Fleet node it is turned on as
shell commands on a Wazuh Fleet node
describes. Even then every command is:
- gated by Vesper on whether an admin started the conversation,
- gated by the environment's mode ceiling, which is Read only, Manual or Auto,
- subject to human approval in Manual mode, and in every mode when it deletes Wazuh data, keys or packages,
- screened by a catastrophic-command denylist inside Vesper, which the host enforces again here as a last resort.
Read commands are the exception to the second rule. A command Vesper classifies
as read-only runs immediately in every mode, including Read only. A network read
such as curl, ping or dig counts as read-only only toward a local or
private address. See
the agent's modes for exactly which commands qualify.
Enabling exec also installs a systemd drop-in at
/etc/systemd/system/vesper-connector.service.d/exec.conf that strips most of
the unit's hardening, including the read-only filesystem, because a fix that
edits /var/ossec or restarts a service cannot work under it. Delete that
drop-in and set exec.enabled: false to return the connector to its hardened,
read-only state. Install the connector lists exactly which
protections the drop-in removes and which survive.
What the agent may read on this node without a shell
The connector answers five read requests from the agent that need no shell and
no approval: read a file, read the end of a log, list a directory, report a
service's state with the last lines of its journal, and run a component's own
configuration check. They work with exec.enabled set to false, so a
conversation started with Look into it can read the configuration file that
a broken manager's API cannot parse for it.
What can be read is fixed in the connector binary. It is not a setting in this file and it cannot be widened from the console or by Vesper. Only the directories of the Wazuh components are readable, and the secret files inside them are refused by name.
| Component | Readable directories |
|---|---|
| Manager 4.x | /var/ossec/etc/, its rules/, decoders/ and shared/, /var/ossec/logs/, /var/ossec/ruleset/, /var/ossec/integrations/ |
| Manager 5.x | /var/wazuh-manager/etc/, /var/wazuh-manager/logs/ |
| Agent | /var/ossec/etc/, /var/ossec/logs/ |
| Indexer | /etc/wazuh-indexer/ and its certs/, /var/log/wazuh-indexer/ |
| Dashboard | /etc/wazuh-dashboard/ and its certs/, /usr/share/wazuh-dashboard/data/wazuh/config/, /var/log/wazuh-dashboard/ |
| Filebeat | /etc/filebeat/ and its certs/, /var/log/filebeat/ |
Nothing outside those directories can be reached. A manager's queue/, var/,
stats/ and bin/ are outside them. A symbolic link is followed before the
check, so a link inside a readable directory that points outside it is refused
too.
These files are never read, wherever they sit: client.keys, sslmanager.key,
authd.pass, the API's security/ configuration directory, private keys named
*-key.pem or *.key, and any *.keystore, *.p12 or *.jks file.
Secrets inside a readable file are removed on the host before anything leaves
it. In ossec.conf and the other Wazuh XML files, the cluster key, every
password, API keys and hook URLs are replaced with [redacted]. In the YAML
files, the value of any key named after a password, passphrase, key or secret is
replaced the same way. Every read, logs included, also has credential-shaped
values such as password=, token:, bearer tokens and PEM blocks replaced.
The marker stays in place so the reader knows a value was there.
The service state and configuration checks accept only the five Wazuh units:
wazuh-manager, wazuh-indexer, wazuh-dashboard, filebeat and
wazuh-agent. The state check runs systemctl show and reads the journal. It
never starts, stops or restarts a service. The configuration check runs the
component's own validator, such as wazuh-analysisd -t and wazuh-remoted -t
on a manager or filebeat test config and filebeat test output for Filebeat,
and parses the XML or YAML configuration file to name the malformed line.
A connector older than these reads answers that it does not support them. The agent says so in the conversation and continues with the tools it has. Upgrading the connector enables them.
upgrade: the host's veto over a new binary
upgrade.enabled, true by default, decides whether this host accepts a new
binary from Vesper at all. It is not the same decision as the console's, and the
two are allowed to disagree. The console decides whether Vesper asks, by an
admin pressing Upgrade now or by the environment's auto upgrade toggle. This
key decides whether the host says yes, and it is the one that wins: set it to
false and the connector logs and ignores every directive, whatever anybody
presses.
That is deliberate. The person who owns the machine and the person who owns the Vesper workspace are not always the same person, and this binary runs as root.
upgrade.download_host is the only host an upgrade artifact may be fetched
from, which bounds what the control plane can do: Vesper chooses which version,
never where the bytes come from. The installer writes the host it downloaded
from, so a connector installed from an internal mirror goes on upgrading from
that mirror rather than refusing every directive. Blank falls back to
dl.vesper.wazuh.com.
What an upgrade does on the host, and how to undo one, is in Connector lifecycle.
Every key in the file
The whole surface, in the order the file is usually written. Anything left out takes the default in this table.
| Key | Default | Meaning |
|---|---|---|
connect_url | wss://connect.vesper.wazuh.com | The outbound session endpoint. |
enroll_url | derived from connect_url | Where enrollment sends its request. Blank means connect_url with wss swapped for https and /enroll appended, which is right unless you run a mirror. |
data_dir | /var/lib/vesper-connector | Where the connector keeps the identity it enrolled with. Deleting it costs the connector its certificate, so re-enrolling is the only way back, and the node comes back as a new node in the console. |
indexer.url | https://localhost:9200 | The Wazuh indexer to read from. |
indexer.username, indexer.password | blank | Basic auth for the indexer. Blank means discover them; see Credentials. |
indexer.insecure_skip_verify | true | Accept the indexer's certificate without verifying it, which is the default because Wazuh ships a self-signed one. |
indexer.keystore_path | the filebeat keystore | Where the indexer credential is discovered from on Wazuh 4.x. |
wazuh_api.url | https://localhost:55000 | The Wazuh manager API to read from. |
wazuh_api.username, wazuh_api.password | blank | The account the connector authenticates with. Blank means discover them. |
wazuh_api.insecure_skip_verify | true | As for the indexer. |
dashboard_config | the dashboard's wazuh.yml | Where API credentials are discovered from on Wazuh 4.x. |
dashboard_opensearch_yml | the dashboard's opensearch_dashboards.yml | The same, on Wazuh 5.x. |
active_response.enabled | none | Retired. Ignored if present. Files written by older installers still carry it. |
exec.enabled | false | Permits running shell commands on the host. |
upgrade.enabled | true | Permits Vesper to replace this binary. |
upgrade.download_host | dl.vesper.wazuh.com | The only host an upgrade artifact may come from. |
heartbeat_seconds | 30 | How often the connector reports in. Drives the online and offline status. |
request_timeout_seconds | 30 | Per-request timeout against the local indexer and API. |
connect_url is the one line the installer fills in rather than hardcodes. It
wrote the key from the --connect value, which every install command the
console issued carried. A connector installed by hand
without that flag has no connect_url line at all, which is not a fault. The
connector falls back to the built-in default above whenever the key is missing.
After editing the file, restart the service:
sudo systemctl restart vesper-connector