Wazuh is an open-source security platform that takes pride in delivering robust endpoint security, advanced threat intelligence, streamlined security operations, and comprehensive cloud security. It’s a one-stop that provides a detailed breakdown of security issues for your on-premise and cloud resources. Read more here. This article aims to provide a straightforward guide for setting up Wazuh using Docker, securing the Wazuh Dashboard domain with Let’s Encrypt, and deploying the necessary agents on a virtual machine (VM). Prerequisites: Docker and Docker Compose installed on your server. A registered domain name for the Wazuh Dashboard. A Kubernetes Cluster. Wazuh is made up of three services, the Wazuh Manager, the Wazuh Indexer, and the Wazuh Dashboard. All three components will be installed using a Docker Compose file. Before the installation process, ensure the following ports are open in the VM; 443 for HTTPS connection 5601 Wazuh Dashboard port 1514, 1515, 514/udp, 55000 used by Wazuh Manager for communication 9200 Wazuh Indexer port It is recommended to increase the `max_map_count` on the VM, because of the many memory-mapped areas created by the Wazuh Indexer. To increase this count, run this command on the VM: sysctl -w vm.max_map_count=262144 If you don’t set the max_map_count on your host, the Wazuh indexer will NOT work properly. To get started, clone the official Wazuh repository with this command: git clone https://github.com/wazuh/wazuh-docker.git Here's a refined version of the instruction: In the single-node/ folder, update the version tags for the wazuh/wazuh-manager, wazuh/wazuh-indexer, and wazuh/wazuh-dashboard images to 4.8.1 in the docker-compose.yml file. As I write this guide, the available docker version for the Wazuh images is 4.8.1. The next phase is creating the certificates needed by Wazuh’s resources for proper communication. In the single-node/ folder, there’s a generate-indexer-certs.yml which is a docker compose file used for generating the certificates. To create the Wazuh certificates, run the command below from the single-node/ folder: docker-compose -f generate-indexer-certs.yml run --rm generator The generated certificates are stored in the wazuh_indexer_ssl_certs/ folder which is used by Wazuh resources in the volumes section of the docker-compose.yml file. To start the Wazuh deployment run this command from the single-node/ folder: docker-compose up The startup process takes about a minute. You can access the Wazuh dashboard at: https://virtual-machine-ip At this point, when you visit https://virtual-machine-ip you’ll be greeted with: This means our dashboard is insecure. To secure it, we will use Let’s Encrypt to generate certificates and enable HTTPS. Before we get into securing the URL, we need to link the VM IP where Wazuh is hosted to a registered domain. Linking an IP to a domain is beyond the scope of this article but if you are using a domain with Namecheap, you can learn how to do so here. Once you’ve done this, return to this article to create the Let’s Encrypt Certificate. An excellent article by the Wazuh team on how to create the Let’s Encrypt certificate for the Wazuh dashboard will guide you to create a certificate for Wazuh deployed directly on the VM. Continue reading once the certificate has been created. Because Wazuh is deployed with docker, the steps specified in this section of the article don’t apply. To configure the created certificates with the Wazuh dashboard, docker volumes are used to map the generated certificates to the locations that are needed by the Wazuh dashboard container. Follow these steps to map the generated certificates to the Wazuh dashboard container: Change the user and permission of the archive files: # change owner to UID used in running the docker compose command sudo chown -R 1000:1000 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/ # change permission of the files sudo chmod -R 500 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/fullchain1.pem sudo chmod 440 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/privkey1.pem Use a soft link to link the generated certificates to a location mapped to the container certificates’ location: # change into the single-node/config folder cd single-node/config # create letsencrypt/ folder mkdir letsencrypt # change into the letsencrypt cd letsencrypt # link the certificate ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem privkey.pem ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem fullchain.pem Stop the docker containers from running: docker compose down Add the fullchain.pem and privkey.pem files in the volumes of the Wazuh dashboard container: # create a backup for your docker compose file (wazuh/single-node) cp docker-compose.yml docker-compose-bk.yml # edit dicker-compose file - ./config/letsencrypt/privkey.pem:/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem # New certificate added - ./config/letsencrypt/fullchain.pem:/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem # New certificate added - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom Edit the opensearch_dashboards.yml file to reference the created certificates: server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: https://wazuh.indexer:9200 opensearch.ssl.verificationMode: certificate opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"] opensearch_security.multitenancy.enabled: false opensearch_security.readonly_mode.roles: ["kibana_read_only"] server.ssl.enabled: true server.ssl.key: "/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem" # Newly referenced certificate server.ssl.certificate: "/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem" # Newly referenced certificate opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"] uiSettings.overrides.defaultRoute: /app/wz-home Setup Certificate Auto-renewal: # Edit the /etc/letsencrypt/renewal/<YOUR_DOMAIN_NAME>.conf file # renew_before_expiry = 30 days version = 2.11.0 archive_dir = /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME> cert = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/cert.pem privkey = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem chain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>chain.pem fullchain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem # Options used in the renewal process [renewalparams] account = 4a622a9****************c authenticator = standalone server = https://acme-v02.api.letsencrypt.org/directory key_type = ecdsa renew_hook = docker restart wazuh_dashboard Test the renewal hook by running the command below: certbot renew --dry-run Restart the Wazuh deployment: # wazuh/single-node/ docker-compose up The dashboard should be secured after the restart of the deployment. The default username and password for the dashboard are admin and SecretPassword respectively. Deploying Wazuh Agent Deploying the Wazuh Manager, Indexer, and Dashboard, along with securing its domain, is just one aspect of the setup. To effectively monitor virtual machines, a Wazuh agent must be installed on each machine. For more detailed information on Wazuh agents, you can read this article. To deploy this agent in a Kubernetes cluster, a daemonset is utilized, ensuring an agent runs in all the cluster’s nodes. To kick start the deployment process, a daemonset.yml is created whose values can be gotten from this gist. Before creating the daemonset, a couple of environment variables have to be assigned values: JOIN_MANAGER_MASTER_HOST: This is the domain/IP where the Wazuh deployment is running. JOIN_MANAGER_WORKER_HOST: This has same value as the JOIN_MANAGER_MASTER_HOST variable. JOIN_MANAGER_PASSWORD: This is the API password. The default value is MyS3cr37P450r.*- if wish to change this password, you can check out this article. JOIN_MANAGER_USER: This the API Username. The default value is wazuh-wui Once the above variables have been assigned their values, you can run this command in your Kubernetes cluster: kubectl apply -f daemonset.yml From your Wazuh dashboard, you should have something similar to the image below. If you follow the above steps, you should be able to successfully deploy a Wazuh application using docker, securing its domain, and also deploy agents on VMs to be monitored on Kubernetes. Thanks for reading! References https://documentation.wazuh.com/current/user-manual/wazuh-dashboard/configuring-third-party-certs/ssl.html#configuring-lets-encrypt-ssl-certificates-in-the-wazuh-dashboard https://documentation.wazuh.com/current/deployment-options/docker/wazuh-container.html https://documentation.wazuh.com/current/user-manual/api/securing-api.html https://github.com/pyToshka/docker-wazuh-agent/blob/main/wazuh-daemonset.yaml Wazuh is an open-source security platform that takes pride in delivering robust endpoint security, advanced threat intelligence, streamlined security operations, and comprehensive cloud security. It’s a one-stop that provides a detailed breakdown of security issues for your on-premise and cloud resources. Read more here . here This article aims to provide a straightforward guide for setting up Wazuh using Docker , securing the Wazuh Dashboard domain with Let’s Encrypt, and deploying the necessary agents on a virtual machine (VM). Docker Prerequisites: Prerequisites: Docker and Docker Compose installed on your server. A registered domain name for the Wazuh Dashboard. A Kubernetes Cluster. Docker and Docker Compose installed on your server . server A registered domain name for the Wazuh Dashboard. A Kubernetes Cluster. Wazuh is made up of three services, the Wazuh Manager, the Wazuh Indexer, and the Wazuh Dashboard. All three components will be installed using a Docker Compose file. Before the installation process, ensure the following ports are open in the VM; 443 for HTTPS connection 5601 Wazuh Dashboard port 1514, 1515, 514/udp, 55000 used by Wazuh Manager for communication 9200 Wazuh Indexer port 443 for HTTPS connection 443 5601 Wazuh Dashboard port 5601 1514 , 1515 , 514 /udp, 55000 used by Wazuh Manager for communication 1514 1515 514 55000 9200 Wazuh Indexer port 9200 It is recommended to increase the `max_map_count` on the VM, because of the many memory-mapped areas created by the Wazuh Indexer. To increase this count, run this command on the VM: sysctl -w vm.max_map_count=262144 sysctl -w vm.max_map_count=262144 If you don’t set the max_map_count on your host, the Wazuh indexer will NOT work properly. If you don’t set the max_map_count on your host, the Wazuh indexer will NOT work properly. max_map_count To get started, clone the official Wazuh repository with this command: git clone https://github.com/wazuh/wazuh-docker.git git clone https://github.com/wazuh/wazuh-docker.git Here's a refined version of the instruction: In the single-node/ folder, update the version tags for the wazuh/wazuh-manager , wazuh/wazuh-indexer, and wazuh/wazuh-dashboard images to 4.8.1 in the docker-compose.yml file. single-node/ wazuh/wazuh-manager wazuh/wazuh-indexer, wazuh/wazuh-dashboard 4.8.1 docker-compose.yml As I write this guide, the available docker version for the Wazuh images is 4.8.1. As I write this guide, the available docker version for the Wazuh images is 4.8.1 . docker version 4.8.1 The next phase is creating the certificates needed by Wazuh’s resources for proper communication. In the single-node/ folder, there’s a generate-indexer-certs.yml which is a docker compose file used for generating the certificates. single-node/ generate-indexer-certs.yml To create the Wazuh certificates, run the command below from the single-node/ folder: single-node/ docker-compose -f generate-indexer-certs.yml run --rm generator docker-compose -f generate-indexer-certs.yml run --rm generator The generated certificates are stored in the wazuh_indexer_ssl_certs/ folder which is used by Wazuh resources in the volumes section of the docker-compose.yml file. wazuh_indexer_ssl_certs/ docker-compose.yml To start the Wazuh deployment run this command from the single-node/ folder: single-node/ docker-compose up docker-compose up The startup process takes about a minute. You can access the Wazuh dashboard at: https://virtual-machine-ip https://virtual-machine-ip At this point, when you visit https://virtual-machine-ip you’ll be greeted with: https://virtual-machine-ip This means our dashboard is insecure. To secure it, we will use Let’s Encrypt to generate certificates and enable HTTPS. Before we get into securing the URL, we need to link the VM IP where Wazuh is hosted to a registered domain. Linking an IP to a domain is beyond the scope of this article but if you are using a domain with Namecheap, you can learn how to do so here . Once you’ve done this, return to this article to create the Let’s Encrypt Certificate. here An excellent article by the Wazuh team on how to create the Let’s Encrypt certificate for the Wazuh dashboard will guide you to create a certificate for Wazuh deployed directly on the VM. article Continue reading once the certificate has been created. Continue reading once the certificate has been created. Because Wazuh is deployed with docker, the steps specified in this section of the article don’t apply. To configure the created certificates with the Wazuh dashboard, docker volumes are used to map the generated certificates to the locations that are needed by the Wazuh dashboard container. section Follow these steps to map the generated certificates to the Wazuh dashboard container: Follow these steps to map the generated certificates to the Wazuh dashboard container: Change the user and permission of the archive files: # change owner to UID used in running the docker compose command sudo chown -R 1000:1000 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/ # change permission of the files sudo chmod -R 500 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/fullchain1.pem sudo chmod 440 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/privkey1.pem Change the user and permission of the archive files: # change owner to UID used in running the docker compose command sudo chown -R 1000:1000 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/ # change permission of the files sudo chmod -R 500 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/fullchain1.pem sudo chmod 440 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/privkey1.pem Change the user and permission of the archive files: # change owner to UID used in running the docker compose command sudo chown -R 1000:1000 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/ # change permission of the files sudo chmod -R 500 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/fullchain1.pem sudo chmod 440 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/privkey1.pem # change owner to UID used in running the docker compose command sudo chown -R 1000:1000 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/ # change permission of the files sudo chmod -R 500 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/fullchain1.pem sudo chmod 440 /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME>/privkey1.pem Use a soft link to link the generated certificates to a location mapped to the container certificates’ location: # change into the single-node/config folder cd single-node/config # create letsencrypt/ folder mkdir letsencrypt # change into the letsencrypt cd letsencrypt # link the certificate ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem privkey.pem ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem fullchain.pem Use a soft link to link the generated certificates to a location mapped to the container certificates’ location: # change into the single-node/config folder cd single-node/config # create letsencrypt/ folder mkdir letsencrypt # change into the letsencrypt cd letsencrypt # link the certificate ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem privkey.pem ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem fullchain.pem Use a soft link to link the generated certificates to a location mapped to the container certificates’ location: # change into the single-node/config folder cd single-node/config # create letsencrypt/ folder mkdir letsencrypt # change into the letsencrypt cd letsencrypt # link the certificate ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem privkey.pem ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem fullchain.pem # change into the single-node/config folder cd single-node/config # create letsencrypt/ folder mkdir letsencrypt # change into the letsencrypt cd letsencrypt # link the certificate ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem privkey.pem ln -s /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem fullchain.pem Stop the docker containers from running: docker compose down Stop the docker containers from running: docker compose down Stop the docker containers from running: docker compose down docker compose down Add the fullchain.pem and privkey.pem files in the volumes of the Wazuh dashboard container: # create a backup for your docker compose file (wazuh/single-node) cp docker-compose.yml docker-compose-bk.yml # edit dicker-compose file - ./config/letsencrypt/privkey.pem:/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem # New certificate added - ./config/letsencrypt/fullchain.pem:/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem # New certificate added - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom Add the fullchain.pem and privkey.pem files in the volumes of the Wazuh dashboard container: # create a backup for your docker compose file (wazuh/single-node) cp docker-compose.yml docker-compose-bk.yml # edit dicker-compose file - ./config/letsencrypt/privkey.pem:/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem # New certificate added - ./config/letsencrypt/fullchain.pem:/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem # New certificate added - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom Add the fullchain.pem and privkey.pem files in the volumes of the Wazuh dashboard container: fullchain.pem privkey.pem # create a backup for your docker compose file (wazuh/single-node) cp docker-compose.yml docker-compose-bk.yml # edit dicker-compose file - ./config/letsencrypt/privkey.pem:/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem # New certificate added - ./config/letsencrypt/fullchain.pem:/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem # New certificate added - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom # create a backup for your docker compose file (wazuh/single-node) cp docker-compose.yml docker-compose-bk.yml # edit dicker-compose file - ./config/letsencrypt/privkey.pem:/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem # New certificate added - ./config/letsencrypt/fullchain.pem:/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem # New certificate added - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem - ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem - ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml - ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml - wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config - wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom Edit the opensearch_dashboards.yml file to reference the created certificates: server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: https://wazuh.indexer:9200 opensearch.ssl.verificationMode: certificate opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"] opensearch_security.multitenancy.enabled: false opensearch_security.readonly_mode.roles: ["kibana_read_only"] server.ssl.enabled: true server.ssl.key: "/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem" # Newly referenced certificate server.ssl.certificate: "/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem" # Newly referenced certificate opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"] uiSettings.overrides.defaultRoute: /app/wz-home Edit the opensearch_dashboards.yml file to reference the created certificates: server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: https://wazuh.indexer:9200 opensearch.ssl.verificationMode: certificate opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"] opensearch_security.multitenancy.enabled: false opensearch_security.readonly_mode.roles: ["kibana_read_only"] server.ssl.enabled: true server.ssl.key: "/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem" # Newly referenced certificate server.ssl.certificate: "/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem" # Newly referenced certificate opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"] uiSettings.overrides.defaultRoute: /app/wz-home Edit the opensearch_dashboards.yml file to reference the created certificates: opensearch_dashboards.yml server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: https://wazuh.indexer:9200 opensearch.ssl.verificationMode: certificate opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"] opensearch_security.multitenancy.enabled: false opensearch_security.readonly_mode.roles: ["kibana_read_only"] server.ssl.enabled: true server.ssl.key: "/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem" # Newly referenced certificate server.ssl.certificate: "/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem" # Newly referenced certificate opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"] uiSettings.overrides.defaultRoute: /app/wz-home server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: https://wazuh.indexer:9200 opensearch.ssl.verificationMode: certificate opensearch.requestHeadersWhitelist: ["securitytenant","Authorization"] opensearch_security.multitenancy.enabled: false opensearch_security.readonly_mode.roles: ["kibana_read_only"] server.ssl.enabled: true server.ssl.key: "/usr/share/wazuh-dashboard/lets-encrypt/privkey.pem" # Newly referenced certificate server.ssl.certificate: "/usr/share/wazuh-dashboard/lets-encrypt/fullchain.pem" # Newly referenced certificate opensearch.ssl.certificateAuthorities: ["/usr/share/wazuh-dashboard/certs/root-ca.pem"] uiSettings.overrides.defaultRoute: /app/wz-home Setup Certificate Auto-renewal: # Edit the /etc/letsencrypt/renewal/<YOUR_DOMAIN_NAME>.conf file # renew_before_expiry = 30 days version = 2.11.0 archive_dir = /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME> cert = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/cert.pem privkey = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem chain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>chain.pem fullchain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem # Options used in the renewal process [renewalparams] account = 4a622a9****************c authenticator = standalone server = https://acme-v02.api.letsencrypt.org/directory key_type = ecdsa renew_hook = docker restart wazuh_dashboard Setup Certificate Auto-renewal: # Edit the /etc/letsencrypt/renewal/<YOUR_DOMAIN_NAME>.conf file # renew_before_expiry = 30 days version = 2.11.0 archive_dir = /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME> cert = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/cert.pem privkey = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem chain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>chain.pem fullchain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem # Options used in the renewal process [renewalparams] account = 4a622a9****************c authenticator = standalone server = https://acme-v02.api.letsencrypt.org/directory key_type = ecdsa renew_hook = docker restart wazuh_dashboard Setup Certificate Auto-renewal: # Edit the /etc/letsencrypt/renewal/<YOUR_DOMAIN_NAME>.conf file # renew_before_expiry = 30 days version = 2.11.0 archive_dir = /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME> cert = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/cert.pem privkey = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem chain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>chain.pem fullchain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem # Options used in the renewal process [renewalparams] account = 4a622a9****************c authenticator = standalone server = https://acme-v02.api.letsencrypt.org/directory key_type = ecdsa renew_hook = docker restart wazuh_dashboard # Edit the /etc/letsencrypt/renewal/<YOUR_DOMAIN_NAME>.conf file # renew_before_expiry = 30 days version = 2.11.0 archive_dir = /etc/letsencrypt/archive/<YOUR_DOMAIN_NAME> cert = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/cert.pem privkey = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/privkey.pem chain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>chain.pem fullchain = /etc/letsencrypt/live/<YOUR_DOMAIN_NAME>/fullchain.pem # Options used in the renewal process [renewalparams] account = 4a622a9****************c authenticator = standalone server = https://acme-v02.api.letsencrypt.org/directory key_type = ecdsa renew_hook = docker restart wazuh_dashboard Test the renewal hook by running the command below: certbot renew --dry-run Test the renewal hook by running the command below: certbot renew --dry-run Test the renewal hook by running the command below: certbot renew --dry-run certbot renew --dry-run Restart the Wazuh deployment: # wazuh/single-node/ docker-compose up Restart the Wazuh deployment: # wazuh/single-node/ docker-compose up Restart the Wazuh deployment: # wazuh/single-node/ docker-compose up # wazuh/single-node/ docker-compose up The dashboard should be secured after the restart of the deployment. The default username and password for the dashboard are admin and SecretPassword respectively. admin SecretPassword Deploying Wazuh Agent Deploying the Wazuh Manager, Indexer, and Dashboard, along with securing its domain, is just one aspect of the setup. To effectively monitor virtual machines, a Wazuh agent must be installed on each machine. For more detailed information on Wazuh agents, you can read this article . article To deploy this agent in a Kubernetes cluster, a daemonset is utilized, ensuring an agent runs in all the cluster’s nodes. To kick start the deployment process, a daemonset.yml is created whose values can be gotten from this gist . Before creating the daemonset, a couple of environment variables have to be assigned values: daemonset.yml gist JOIN_MANAGER_MASTER_HOST: This is the domain/IP where the Wazuh deployment is running. JOIN_MANAGER_WORKER_HOST: This has same value as the JOIN_MANAGER_MASTER_HOST variable. JOIN_MANAGER_PASSWORD: This is the API password. The default value is MyS3cr37P450r.*- if wish to change this password, you can check out this article. JOIN_MANAGER_USER: This the API Username. The default value is wazuh-wui JOIN_MANAGER_MASTER_HOST: This is the domain/IP where the Wazuh deployment is running. JOIN_MANAGER_MASTER_HOST : This is the domain/IP where the Wazuh deployment is running. JOIN_MANAGER_MASTER_HOST JOIN_MANAGER_WORKER_HOST: This has same value as the JOIN_MANAGER_MASTER_HOST variable. JOIN_MANAGER_WORKER_HOST : This has same value as the JOIN_MANAGER_MASTER_HOST variable. JOIN_MANAGER_WORKER_HOST JOIN_MANAGER_MASTER_HOST JOIN_MANAGER_PASSWORD: This is the API password. The default value is MyS3cr37P450r.*- if wish to change this password, you can check out this article. JOIN_MANAGER_PASSWORD : This is the API password. The default value is MyS3cr37P450r.*- JOIN_MANAGER_PASSWORD MyS3cr37P450r.*- if wish to change this password, you can check out this article . article JOIN_MANAGER_USER: This the API Username. The default value is wazuh-wui JOIN_MANAGER_USER : This the API Username. The default value is wazuh-wui JOIN_MANAGER_USER wazuh-wui Once the above variables have been assigned their values, you can run this command in your Kubernetes cluster: kubectl apply -f daemonset.yml kubectl apply -f daemonset.yml From your Wazuh dashboard, you should have something similar to the image below. If you follow the above steps, you should be able to successfully deploy a Wazuh application using docker, securing its domain, and also deploy agents on VMs to be monitored on Kubernetes. Thanks for reading! References https://documentation.wazuh.com/current/user-manual/wazuh-dashboard/configuring-third-party-certs/ssl.html#configuring-lets-encrypt-ssl-certificates-in-the-wazuh-dashboard https://documentation.wazuh.com/current/deployment-options/docker/wazuh-container.html https://documentation.wazuh.com/current/user-manual/api/securing-api.html https://github.com/pyToshka/docker-wazuh-agent/blob/main/wazuh-daemonset.yaml https://documentation.wazuh.com/current/user-manual/wazuh-dashboard/configuring-third-party-certs/ssl.html#configuring-lets-encrypt-ssl-certificates-in-the-wazuh-dashboard https://documentation.wazuh.com/current/user-manual/wazuh-dashboard/configuring-third-party-certs/ssl.html#configuring-lets-encrypt-ssl-certificates-in-the-wazuh-dashboard https://documentation.wazuh.com/current/deployment-options/docker/wazuh-container.html https://documentation.wazuh.com/current/deployment-options/docker/wazuh-container.html https://documentation.wazuh.com/current/user-manual/api/securing-api.html https://documentation.wazuh.com/current/user-manual/api/securing-api.html https://github.com/pyToshka/docker-wazuh-agent/blob/main/wazuh-daemonset.yaml https://github.com/pyToshka/docker-wazuh-agent/blob/main/wazuh-daemonset.yaml