Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker-compose.yml doesn't contain important directives and definitions #1106

Open
kkovaletp opened this issue Nov 13, 2023 · 5 comments
Open

Comments

@kkovaletp
Copy link

kkovaletp commented Nov 13, 2023

Hi Team,

I've recently deployed the product (4.6.0) using the docker-compose approach and had to make noticeable changes in the compose file, as it doesn't provide the best possible setup out of the box. Of course, we could negotiate in the comments about my next proposals, but I think that they are valuable enough to be mentioned here:

  • Before proposing changes to the compose file, I'd like to propose a change to your docker image release strategy: now users have to subscribe to the repo releases notification and manually upgrade to the new product version. Is there some real technical reason for that? It would be much more convenient to have a stable tag for the latest LTS version, a release tag for the latest released one, and a latest for the latest published one in your docker hub repo - this will allow those users, who want to always stay on some of the mentioned branches, follow corresponding tag in their setup configs and reduce the amount of human factor and manual work.
  • restart: unless-stopped would be much better than always, as it works the same, except for the case when the service was stopped intentionally and shouldn't be restarted again.
  • stop_grace_period: 30s or some better value lets application components gracefully finish the execution before the container is stopped
  • the next section ensures better compatibility on the system with AppArmor or SELinux enabled, which should be the main scenario, I guess.
security_opt:
       - seccomp:unconfined
       - apparmor:unconfined
  • The devices: section might be useful to map some physical resources of the host (CPU, GPU, etc) and speed up the service. Of course, the application components need to utilize such hardware and work with the /dev/ directly - only in this case it would be useful
  • there is no healthcheck defined in the compose file, not in the Dockerfile for images, so users couldn't use built-in functionality to monitor the health of the containers, and, more importantly, the dependency from the dashboard to indexer unable to ensure the application is ready, so, instead it checks only that the container is up and running.
  • to continue the healthcheck topic, the condition: service_healthy under the wazuh.indexer in the depends_on: section of the dashboard service ensures the app is ready by parsing the healthcheck results of the dependency container
  • the next section of the compose file allows the solution to utilize the IPv6 capabilities in case it is working on the host:
networks:
   wazuh_net:
     enable_ipv6: true
     ipam:
       config:
         - subnet: 172.20.0.0/16
         - subnet: 2001:0DB8::/64

Of course, the docker engine has to be configured to allow IPv6 communication by adding the next lines into the /etc/docker/daemon.json:

{
  "experimental": true,
  "ip6tables": true
}

Also, each service in the compose needs to have the same network connected by adding the next lines to the service definition:

networks:
       - wazuh_net
  • the volumes section could be enhanced by specifying the path on the host, where the data is stored. It is much better than the default docker system location of all volumes because it is not hidden from the user and the user can manage where to store that files and how to backup them. The example:
   wazuh_api_configuration:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_api_configuration'

Of course, all mentioned paths have to exist before the 1st start of the solution.

  • To improve simplicity and reduce the amount of manually executed commands, a Makefile can be created with scripts for all typical use-cases, like volume paths creation, backup, and more
  • The next 2 volume mappings are useful to apply server's time zone and local time to the running containers, so that all logs and other data on server has the same time and users don't need to remember the difference:
   volumes:
       - "/etc/localtime:/etc/localtime:ro" ## use timezone from host
       - "/etc/timezone:/etc/timezone:ro"   ## use timezone from host

I could create a PR with such changes, but I'd like to know your point of view 1st to not do extra work, so, waiting for your replies)

@muhdidhamm
Copy link

do you have any sample of your full compose file with best practice setup? from that we can discuss either it suitable to use in production or not.

@kkovaletp
Copy link
Author

kkovaletp commented Nov 14, 2023

Sure, here is my compose, based on the proposals and assumptions, listed above:

version: '3.9'

services:
   wazuh.manager:
     image: wazuh/wazuh-manager:4.6.0
     hostname: wazuh.manager
     restart: unless-stopped
     stop_grace_period: 30s
     ulimits:
       memlock:
         soft: -1
         hard: -1
       nofile:
         soft: 655360
         hard: 655360
     networks:
       - wazuh_net
     ports:
       - "1514:1514"
       - "1515:1515"
       - "514:514/udp"
       - "55000:55000"
     security_opt:
       - seccomp:unconfined
       - apparmor:unconfined
     environment:
       - INDEXER_URL=https://wazuh.indexer:9200
       - INDEXER_USERNAME=admin
       - INDEXER_PASSWORD=<password>
       - FILEBEAT_SSL_VERIFICATION_MODE=full
       - SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/root-ca.pem
       - SSL_CERTIFICATE=/etc/ssl/filebeat.pem
       - SSL_KEY=/etc/ssl/filebeat.key
       - API_USERNAME=wazuh-wui
       - API_PASSWORD=<password>
     devices:
       - "/dev/dri:/dev/dri"
     volumes:
       - "/etc/localtime:/etc/localtime:ro" ## use timezone from host
       - "/etc/timezone:/etc/timezone:ro"   ## use timezone from host
       - wazuh_api_configuration:/var/ossec/api/configuration
       - wazuh_etc:/var/ossec/etc
       - wazuh_logs:/var/ossec/logs
       - wazuh_queue:/var/ossec/queue
       - wazuh_var_multigroups:/var/ossec/var/multigroups
       - wazuh_integrations:/var/ossec/integrations
       - wazuh_active_response:/var/ossec/active-response/bin
       - wazuh_agentless:/var/ossec/agentless
       - wazuh_wodles:/var/ossec/wodles
       - filebeat_etc:/etc/filebeat
       - filebeat_var:/var/lib/filebeat
       - ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem
       - ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem
       - ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key
       - ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf

   wazuh.indexer:
     image: wazuh/wazuh-indexer:4.6.0
     hostname: wazuh.indexer
     restart: unless-stopped
     stop_grace_period: 30s
     networks:
       - wazuh_net
     ports:
       - "9200:9200"
     security_opt:
       - seccomp:unconfined
       - apparmor:unconfined
     environment:
       - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
     ulimits:
       memlock:
         soft: -1
         hard: -1
       nofile:
         soft: 65536
         hard: 65536
     devices:
       - "/dev/dri:/dev/dri"
     volumes:
       - "/etc/localtime:/etc/localtime:ro" ## use timezone from host
       - "/etc/timezone:/etc/timezone:ro"   ## use timezone from host
       - wazuh-indexer-data:/var/lib/wazuh-indexer
       - ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/certs/root-ca.pem
       - ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.key
       - ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/certs/wazuh.indexer.pem
       - ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/certs/admin.pem
       - ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/certs/admin-key.pem
       - ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/opensearch.yml
       - ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/opensearch-security/internal_users.yml

   wazuh.dashboard:
     image: wazuh/wazuh-dashboard:4.6.0
     hostname: wazuh.dashboard
     restart: unless-stopped
     stop_grace_period: 10s
     networks:
       - wazuh_net
     ports:
       - "8443:5601"
     security_opt:
       - seccomp:unconfined
       - apparmor:unconfined
     environment:
       - INDEXER_USERNAME=admin
       - INDEXER_PASSWORD=<password>
       - WAZUH_API_URL=https://wazuh.manager
       - DASHBOARD_USERNAME=kibanaserver
       - DASHBOARD_PASSWORD=<password>
       - API_USERNAME=wazuh-wui
       - API_PASSWORD=<password>
     devices:
       - "/dev/dri:/dev/dri"
     volumes:
       - "/etc/localtime:/etc/localtime:ro" ## use timezone from host
       - "/etc/timezone:/etc/timezone:ro"   ## use timezone from host
       - ./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
     depends_on:
       - wazuh.indexer
        # condition: service_healthy
     links:
       - wazuh.indexer:wazuh.indexer
       - wazuh.manager:wazuh.manager

networks:
   wazuh_net:
     enable_ipv6: true
     ipam:
       config:
         - subnet: 172.20.0.0/16
         - subnet: 2001:0DB8::/64

volumes:
   wazuh_api_configuration:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_api_configuration'
   wazuh_etc:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_etc'
   wazuh_logs:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_logs'
   wazuh_queue:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_queue'
   wazuh_var_multigroups:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_var_multigroups'
   wazuh_integrations:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_integrations'
   wazuh_active_response:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_active_response'
   wazuh_agentless:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_agentless'
   wazuh_wodles:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh_wodles'
   filebeat_etc:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/filebeat_etc'
   filebeat_var:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/filebeat_var'
   wazuh-indexer-data:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh-indexer-data'
   wazuh-dashboard-config:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh-dashboard-config'
   wazuh-dashboard-custom:
     driver: local
     driver_opts:
       type: 'none'
       o: 'bind'
       device: './volumes/wazuh-dashboard-custom'

@kkovaletp
Copy link
Author

This YAML needs the next improvements (which require contribution of product experts):

  • the stop_grace_period has to be set to some better values according to the app components shutdown time
  • The devices section needs to be enhanced with devices mapping according to device utilization capabilities of app components per service
  • healthcheck has to be defined here per service or in corresponding Dockerfile per image, then the condition line can be uncommented in the dependency section of the dashboard service
  • IP subnets could be modified to better match the solution. Unfortunately, it is impossible to not specify them at all, so users have to review and modify them to match their docker network setup

@kkovaletp
Copy link
Author

I've just added 1 more useful proposal to the original issue and to the compose file:

  • The next 2 volume mappings are useful to apply server's time zone and local time to the running containers, so that all logs and other data on server has the same time and users don't need to remember the difference:
   volumes:
       - "/etc/localtime:/etc/localtime:ro" ## use timezone from host
       - "/etc/timezone:/etc/timezone:ro"   ## use timezone from host

@BAStos525
Copy link

Any updates regarding healthchecks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants