Skip to content

Wazuh — Authentik edge SSO (proxy auth)

Wazuh Dashboard uses OpenSearch Security login by default. When the stack is deployed, configure proxy authentication so Traefik forward-auth headers satisfy the dashboard.

URL: https://wazuh.infra.realemail.app Stack: services/wazuh/ on infra-services (edge SSO live — see infra-single-login).


Prerequisites

  • Wazuh stack up: docker compose --env-file compose.env up -d
  • Traefik authentik@file on the Wazuh router (already in compose)
  • Authentik outpost passes X-authentik-username (see services/traefik/config/dynamic/authentik.yml)

Repo configuration

File Purpose
services/wazuh/config/wazuh_dashboard/opensearch_dashboards.yml auth.type: proxy + proxycache headers (not proxycache — unsupported on Wazuh 4.11)
services/wazuh/config/wazuh_indexer/config.yml Indexer proxy auth domain + internal proxy CIDRs
services/wazuh/config/wazuh_indexer/roles_mapping.yml Map Authentik admins group → OpenSearch roles

compose.yml mounts the dashboard config. Indexer needs config.yml (proxy auth domain + trusted proxy CIDRs) and roles_mapping.yml (map Authentik admins group). Apply after deploy:

bash scripts/post-deploy-wazuh.sh

Or manually:

bash scripts/sync-internal-users-from-env.sh
bash scripts/sync-wazuh-yml.sh
docker compose --env-file compose.env up -d --force-recreate wazuh-manager wazuh-dashboard
bash scripts/ensure-wazuh-apid.sh

Komodo deploy-infra only runs docker compose up — it does not run post-deploy-wazuh.sh unless the wazuh stack hooks in services/komodo/resources.toml are synced. After a Wazuh redeploy without hooks, run bash scripts/post-deploy-wazuh.sh manually.


Verify

Incognito → https://wazuh.infra.realemail.app → Authentik → Wazuh home (no OpenSearch login).

Then verify the containers stay healthy:

cd /opt/homelab/services/wazuh
docker compose --env-file compose.env ps
docker logs --since=10m wazuh-dashboard | grep -iE 'error|fatal' || true

Internal user rotation

The repo keeps only the two required internal users: admin and kibanaserver. Before treating Wazuh as production-ready, the owner must replace the upstream bootstrap hashes with owner-chosen passwords.

Recommended (scripted): passwords live in secrets.sops.yaml (encrypted in git). compose.env is rendered from SOPS; bcrypt hashes in internal_users.yml are derived from the rendered file — you cannot reverse hashes back into passwords.

  1. Edit services/wazuh/secrets.sops.yaml with sops (or VS Code SOPS extension).
  2. Render and apply:
bash /opt/homelab/scripts/render-wazuh-compose-env.sh
bash scripts/sync-internal-users-from-env.sh
bash scripts/sync-wazuh-yml.sh
docker compose --env-file compose.env up -d --force-recreate wazuh-manager wazuh-dashboard
  1. Commit and push the encrypted secrets.sops.yaml.

Manual alternative: generate bcrypt with the indexer hash.sh tool, edit internal_users.yml by hand, set the same plaintext in secrets.sops.yaml, re-render compose.env, then run bash scripts/apply-security-config.sh and recreate manager/dashboard.


Troubleshooting

Symptom Check
OpenSearch login still shown Dashboard config not mounted — docker exec wazuh-dashboard grep auth.type
401 after Authentik Indexer config.yml proxy domain; indexer logs
Dashboard won't start SSL settings — server.ssl.enabled must be false behind Traefik
Dashboard healthcheck failing / endless starting /api/status returns 401 under proxy auth — run post-deploy-wazuh.sh after deploy-infra
Filebeat or dashboard 401 to wazuh.indexer:9200 Running containers have stale env after hash sync — bash scripts/post-deploy-wazuh.sh
securityadmin permission denied on admin-key.pem TLS keys still owned by uid 1001 — bash scripts/fix-cert-permissions.sh