Certificate Management
Watchdog uses a shared PKI to secure its own HTTPS API, the Kafka external listener, and Elasticsearch with a single CA and server certificate. The PKI is generated by init-pki.sh during install and lives at /opt/watchdog/pki/ on the host.
This page covers the two changes operators most commonly need to make after install:
- Replace the TLS certificate (with your own, or a freshly rotated one).
- Rotate the Kafka SASL password.
PKI Layout
| File | Purpose |
|---|---|
ca.crt, ca.key |
Self-signed root CA (10-year validity) |
server.crt, server.key |
Server certificate signed by the CA — used by Watchdog, Kafka, and Elasticsearch |
kafka.keystore.p12 |
PKCS12 bundle (server cert + key) consumed by Kafka |
kafka.truststore.p12 |
PKCS12 bundle (CA cert) consumed by Kafka |
kafka_store_pass.env |
PKCS12 store password — read by watchdog-installer.sh and written to .env as KAFKA_STORE_PASS so Compose can substitute it into the Kafka container config |
The same /opt/watchdog/pki directory is mounted read-only into all three containers.
What the Bundled Certificate Covers
The certificate generated during installation includes the following Subject Alternative Names (SANs):
| Type | Values |
|---|---|
| DNS | localhost, watchdog, kafka, kafka-connect, elasticsearch, mongo |
| IP | 127.0.0.1 |
These cover internal connections between containers and connections from the same VM. They do not include the customer-reachable hostname or IP that BrowserMon controllers connect to over the network.
By default BrowserMon controllers connect to Watchdog with strict TLS verification disabled (verify=false), so the bundled certificate works out of the box without further configuration. If you turn verify=true on the controller side, the controller will check that the hostname or IP it dialed against appears in the certificate's SAN list — and the bundled certificate will fail that check unless your reachable address is present.
You have two options:
1. Add your address to the certificate (recommended). Edit the SAN entries in ssl_config.ini:
[SSLConfig]
subject.CN = localhost
san.dns = watchdog.example.com, watchdog-2.internal
san.ip = 10.0.0.42, 192.168.1.10
Both keys accept comma-separated lists. The bundled internal hostnames stay in place — your entries are appended to them.
The right file to edit depends on when you make the change:
-
Before installing (recommended): open
ssl_config.inifrom the TUI's Edit config dropdown during the first-boot setup. The TUI edits/opt/watchdog-release/deps/watchdog/ssl_config.ini, which is the same file the installer reads when it generates the certificate. Save and click Install — the SANs are baked in automatically. -
After installing: the certificate has already been generated, so editing alone has no effect. You must regenerate it. Edit
/opt/watchdog-release/deps/watchdog/ssl_config.inidirectly (not the runtime copy at/opt/watchdog/watchdog/ssl_config.ini— that one is only used as a container mount target and is ignored by the certificate generator), then run:cd /opt/watchdog-release sudo docker compose -f docker-compose.base.yml down sudo ./scripts/init-pki.sh --out-dir /opt/watchdog/pki --config ./deps/watchdog/ssl_config.ini --force sudo docker compose -f docker-compose.base.yml up -dAdd the other compose files (
-f docker-compose.kafka.yml -f docker-compose.elastic.yml -f docker-compose.eti.yml -f docker-compose.ucs.yml) to both commands if those services are running. The PKCS12 store password is reused, so.envdoes not need updating.
2. Replace the certificate with one issued by your internal or public CA whose SANs include your reachable hostname/IP. See Replacing the TLS Certificate below.
Replacing the TLS Certificate
Use this when you want to install a certificate signed by your own internal or public CA, or when rotating the existing one.
All commands assume you are in the release directory (the directory containing the compose files and .env). On the OVA this is /opt/watchdog-release. Adjust the list of -f flags to match the compose files you have installed.
-
Stop the running containers.
-
Replace
server.crtandserver.keywith your new pair. -
Rebuild the Kafka PKCS12 bundle (Kafka cannot read PEM directly).
source /opt/watchdog/pki/kafka_store_pass.env # exports KAFKA_STORE_PASS sudo openssl pkcs12 -export \ -in /opt/watchdog/pki/server.crt \ -inkey /opt/watchdog/pki/server.key \ -certfile /opt/watchdog/pki/ca.crt \ -name kafka \ -out /opt/watchdog/pki/kafka.keystore.p12 \ -passout "pass:$KAFKA_STORE_PASS" -
Start the stack again with the same set of compose files used in step 1.
Note: If your replacement certificate was signed by an external CA, also copy that CA's cert over
/opt/watchdog/pki/ca.crtand rebuildkafka.truststore.p12the same way (useopenssl pkcs12 -export -nokeys).
Quick rotation (keep the bundled CA)
If you just want to rotate the server cert and keep using the bundled CA, run init-pki.sh with --force from the release directory (/opt/watchdog-release on the OVA):
cd /opt/watchdog-release
sudo docker compose -f docker-compose.base.yml down
sudo ./scripts/init-pki.sh --out-dir /opt/watchdog/pki --config ./deps/watchdog/ssl_config.ini --force
sudo docker compose -f docker-compose.base.yml up -d
Add the other compose files (-f docker-compose.kafka.yml -f docker-compose.elastic.yml -f docker-compose.eti.yml -f docker-compose.ucs.yml) to both commands if those services are running.
--force regenerates server.crt and server.key and rebuilds the Kafka PKCS12 stores. The existing ca.crt is preserved. Re-running init-pki.sh --force reuses the existing PKCS12 store password from kafka_store_pass.env, so .env does not need updating.
Watchdog logs WD1011 as a WARNING when fewer than 60 days remain on the certificate — this is your cue to rotate.
Rotating the Kafka SASL Password
The Kafka external listener (8092/tcp) uses SASL_SSL with PLAIN authentication. Default credentials:
| Field | Value |
|---|---|
| Username | browsermon |
| Password | browsermon |
The credentials are defined inline in /opt/watchdog-release/docker-compose.kafka.yml:
KAFKA_LISTENER_NAME_EXTERNAL_PLAIN_SASL_JAAS_CONFIG: |
org.apache.kafka.common.security.plain.PlainLoginModule required
username="browsermon" password="browsermon" user_browsermon="browsermon";
To rotate the password:
-
Edit
/opt/watchdog-release/docker-compose.kafka.ymland change all three occurrences of the password (username=,password=, anduser_browsermon=) to the same new value. -
Recreate the kafka container.
-
Update each BrowserMon controller's Kafka password configuration to match before the controllers reconnect, otherwise they will fail to authenticate. Refer to the BrowserMon controller documentation for the exact setting name.
Note:
/opt/watchdog/pki/kafka_store_pass.envand theKAFKA_STORE_PASSline in.envare the PKCS12 store password — not the SASL password. They are managed byinit-pki.shandwatchdog-installer.shand do not need to be touched when rotating SASL.