diff --git a/Readme.md b/Readme.md index 80d76be..a7bdf90 100644 --- a/Readme.md +++ b/Readme.md @@ -261,6 +261,14 @@ You can also mount your own bash aliases by mounting a .bash_aliases file in /ho Solr admin interface can be accessed either through port 8983, i.e http://localhost:8983, or with the /solr/ url, i.e http://www.mysite.ezdev/solr/ . +### Check containers logs + +You can various logs for debugging through Graylog stacks. + +Just go to http://127.0.0.1:9000/ and fill the form with admin/admin. + +For further explanations see [this documentation](./docs/graylog.md) + ## Stopping the Environment ./stack.sh down diff --git a/config/graylog/filebeat/conf.d/filebeat_apache.conf.yml b/config/graylog/filebeat/conf.d/filebeat_apache.conf.yml new file mode 100644 index 0000000..297fd31 --- /dev/null +++ b/config/graylog/filebeat/conf.d/filebeat_apache.conf.yml @@ -0,0 +1,21 @@ +###################### Filebeat Configuration for Apache2 ######################### + +# Retrieve logs from services +# @author Andréas 'Screamz' HANSS + +#=========================== Filebeat prospectors ============================= + +filebeat.prospectors: +- input_type: log + paths: + - /app-logs/apache/access.log + document_type: apache_access + +- input_type: log + paths: + - /app-logs/apache/error.log + document_type: apache_error + +#----------------------------- Graylog2 output -------------------------------- +output.logstash: + hosts: ["graylog-server:5044"] diff --git a/config/graylog/filebeat/conf.d/filebeat_solr.conf.yml b/config/graylog/filebeat/conf.d/filebeat_solr.conf.yml new file mode 100644 index 0000000..8910b1e --- /dev/null +++ b/config/graylog/filebeat/conf.d/filebeat_solr.conf.yml @@ -0,0 +1,16 @@ +###################### Filebeat Configuration for Apache SOLR ######################### + +# Retrieve logs from services +# @author Andréas 'Screamz' HANSS + +#=========================== Filebeat prospectors ============================= + +filebeat.prospectors: +- input_type: log + paths: + - /app-logs/solr/solr.log + document_type: solr + +#----------------------------- Graylog2 output -------------------------------- +output.logstash: + hosts: ["graylog-server:5047"] diff --git a/config/graylog/filebeat/conf.d/filebeat_varnish.conf.yml b/config/graylog/filebeat/conf.d/filebeat_varnish.conf.yml new file mode 100644 index 0000000..0f4c55d --- /dev/null +++ b/config/graylog/filebeat/conf.d/filebeat_varnish.conf.yml @@ -0,0 +1,17 @@ +###################### Filebeat Configuration for Varnish NCSA ######################### + +# Retrieve logs from services +# @author Andréas 'Screamz' HANSS + +#=========================== Filebeat prospectors ============================= + +filebeat.prospectors: +- input_type: log + paths: + - /app-logs/varnish/varnishncsa.log + document_type: varnish + include_lines: ['BAN', 'PURGE'] + +#----------------------------- Graylog2 output -------------------------------- +output.logstash: + hosts: ["graylog-server:5046"] diff --git a/config/graylog/inject-graylog-config.sh b/config/graylog/inject-graylog-config.sh new file mode 100644 index 0000000..e9b56dd --- /dev/null +++ b/config/graylog/inject-graylog-config.sh @@ -0,0 +1 @@ +mongorestore --gzip --archive=/docker-entrypoint-initdb.d/dump.graylog.gz --db graylog \ No newline at end of file diff --git a/docker-compose-dev-graylog-template.yml b/docker-compose-dev-graylog-template.yml new file mode 100644 index 0000000..725928d --- /dev/null +++ b/docker-compose-dev-graylog-template.yml @@ -0,0 +1,173 @@ + +version: '2' +services: + web: + image: klabs/apache_${DOCKER_PHP_VERSION} + hostname: ${DOCKER_PROJECT_NAME}_web + container_name: web + ports: + - "82:82" + - "88:88" + volumes: + - ./config/apache/sites-available/001-dynamic-vhost-ez5.conf:/etc/apache2/sites-available/001-dynamic-vhost-ez5.conf + - ./config/apache/sites-available/002-dynamic-vhost-ezplatform.conf:/etc/apache2/sites-available/002-dynamic-vhost-ezplatform.conf + - ./config/apache/sites-available/003-dynamic-vhost-ez4.conf:/etc/apache2/sites-available/003-dynamic-vhost-ez4.conf + - ./config/apache/sites-available/ez5-common.conf:/etc/apache2/sites-available/ez5-common.conf + - ./config/apache/sites-available/ezplatform-common.conf:/etc/apache2/sites-available/ezplatform-common.conf + - ./logs/apache/:/var/log/apache2 + - "./config/apache/php5/custom_vars.ini:$DOCKER_PHP_CONF_PATH/apache2/conf.d/custom_vars.ini" + - "./config/apache/php5/timezone.ini:$DOCKER_PHP_CONF_PATH/apache2/conf.d/timezone.ini" + - "$DOCKER_WWW_ROOT:$DOCKER_WWW_DEST" + - "$DOCKER_STORAGE_LOCAL_PATH:$DOCKER_STORAGE_MOUNT_POINT" + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + cli: + image: klabs/cli_${DOCKER_PHP_VERSION} + hostname: ${DOCKER_PROJECT_NAME}_cli + container_name: cli + privileged: true + volumes: + - ./logs/cli:/var/log/php + # files in /tmp/cron.d get managed by bootstrap.sh + - ./config/cli/cron.d:/tmp/cron.d + - ~/.gitconfig:/home/site/.gitconfig + - ~/.ssh/config:/home/site/.ssh/config + - "$SSH_AUTH_SOCK:/ssh-agent" + - "./config/cli/php5/custom_vars.ini:$DOCKER_PHP_CONF_PATH/cli/conf.d/custom_vars.ini" + - "./config/cli/php5/timezone.ini:$DOCKER_PHP_CONF_PATH/cli/conf.d/timezone.ini" + - "$DOCKER_WWW_ROOT:$DOCKER_WWW_DEST" + - "$DOCKER_STORAGE_LOCAL_PATH:$DOCKER_STORAGE_MOUNT_POINT" + environment: + - SSH_AUTH_SOCK=/ssh-agent + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + memcached: + image: klabs/memcached + hostname: ${DOCKER_PROJECT_NAME}_memcached + container_name: memcached + ports: + - "11211:11211" + volumes: + - ./logs/memcache/:/var/log/memcache + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + solr: + image: klabs/solr4 + hostname: ${DOCKER_PROJECT_NAME}_solr + container_name: solr + ports: + - "8983:8983" + volumes: + - "${DOCKER_SOLR_CONF_PATH}:/opt/solr/solr/" + - ./data/solr/:/opt/solr/data/ + - ./logs/solr/:/opt/solr/logs + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + varnish: + image: klabs/varnish + hostname: ${DOCKER_PROJECT_NAME}_varnish + container_name: varnish + ports: + - "81:81" + volumes: + - "${DOCKER_VARNISH_VCL_FILE}:/etc/varnish/default.vcl" + - ./logs/varnish/:/var/log/varnish + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + # varnish init daemon wants to set ulimits + - SYS_RESOURCE + security_opt: + - apparmor:unconfined + depends_on: + - web + - cli + haproxy: + image: klabs/haproxy + hostname: ${DOCKER_PROJECT_NAME}_haproxy + container_name: haproxy + ports: + - "80:80" + volumes: + - ./config/haproxy/haproxy.cfg:/etc/haproxy/haproxy.cfg + env_file: + - docker-compose.env + - docker-compose.env.local + depends_on: + - web + - varnish + - solr + mysql: + image: klabs/mysql + hostname: ${DOCKER_PROJECT_NAME}_mysql + container_name: mysql + # nb: this prevents the image to start on some ubuntu installs because of apparmor config... + #privileged: true + ports: + - "3307:3306" + volumes: + - ./config/mysql/:/etc/mysql/conf.d/ + - ./data/mysql/:/var/lib/mysql + - ./logs/mysql/:/var/log/mysql + env_file: + - docker-compose.env + - docker-compose.env.local + cap_add: + - SYS_PTRACE + command: ["/root/bootstrap.sh", "mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci"] + + # official phpmyadmin image + phpmyadmin: + image: phpmyadmin/phpmyadmin + hostname: ${DOCKER_PROJECT_NAME}_phpmyadmin + container_name: phpmyadmin + env_file: + - docker-compose.env + - docker-compose.env.local + depends_on: + - mysql + # Graylog stack + mongo: + container_name: graylog-mongo + image: "mongo:3" + volumes: + - ./config/graylog:/docker-entrypoint-initdb.d + elasticsearch: + container_name: graylog-elastic + image: "elasticsearch:2" + command: "elasticsearch -Des.cluster.name='graylog'" + graylog: + container_name: graylog-server + image: 'graylog2/server:latest' + environment: + GRAYLOG_PASSWORD_SECRET: somepasswordpepper + GRAYLOG_ROOT_PASSWORD_SHA2: 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 + GRAYLOG_WEB_ENDPOINT_URI: http://127.0.0.1:9000/api + depends_on: + - mongo + - elasticsearch + ports: + - "9000:9000" + filebeats: + container_name: graylog-filebeat + #image: TODO_ON_DOCKERHUB_UPLOAD + build: ./images/filebeat + depends_on: + - graylog + volumes: + - ./config/graylog/filebeat:/mnt + - ./logs:/app-logs diff --git a/docs/graylog.md b/docs/graylog.md new file mode 100644 index 0000000..d0de894 --- /dev/null +++ b/docs/graylog.md @@ -0,0 +1,88 @@ +

+graylog logo +
+ + Graylog - Logs Management Stack +
+

+ +

Various log aggregator in order to enhance debugging and monitoring

+ +

+ Kaliop logo +

+
+ +This stack is a poke in order to demonstrate the power of such tool. Please follow the guide to accomplish the walkthrough. + +This library is mainly maintained by [Andréas HANSS](https://github.com/ScreamZ), feel free to contact if you are having some questions. + +# Requirements + +- **Kaliop eZ Docker stack.** https://github.com/kaliop/ezdocker-stack +- **Docker & Docker-compose.** Recent version + +# Introduction + +**Why GRAYLOG ?** + +- Open source log management. +- Scale well in large architecture. +- Embedded user authentication system. +- Embedded alert system on various metrics. +- Support for various format, especially well with [GELF](http://docs.graylog.org/en/2.2/pages/gelf.html). +- Awesome admin & UI. +- Support for LDAP. + +**Why not ELK (Elastic Logstash Kibana)** +- Require [Shield/security](https://www.elastic.co/products/x-pack/security) for user authentication handling (Not free). +- Require [Watcher](https://www.elastic.co/products/x-pack/alerting) for user authentication handling (Not free). +- Heavy costly resources consumption and poor performances. +- Logstash has no UI out-of-the-box, require manual configuration. + +# Setup + +## What is logged + +At the moment you're able to receive following logs : + +- **Varnish BAN / PURGE -** While you're not banning using the Varnish agent tool, take note that it works with back-office BANs. + +- **Apache2 Access/Errors** + +- **Nginx Access/Errors** + +- **SOLR** + + +# Troubleshooting + +**Check docker network** +Your containers might be on different network, feel free to update the docker-compose.yml file accordingly in order to match. + +# Future improvements + +**Pre-bootstrap Mongo with config** +Instead of doing the restore, bootstrap the database at compilation with given parameters. + +**Use log aggregator system** + +- ElasticBEAT with graylog sidecar mode or without. http://docs.graylog.org/en/2.2/pages/collector.html (Deprecated) see http://docs.graylog.org/en/2.2/pages/collector_sidecar.html +- FluentD +- Rsylog / Syslog-NG + +**Think about using LDAP system** + +**Optimize index and stream internally** + +**Find a way to use GELF everywhere** + +- In symfony use monolog with specific wrapper that ignore exception in case of not responsing server + +**Format Apache/NGINX logs upstream in config** \ No newline at end of file diff --git a/graylog.yml b/graylog.yml new file mode 100644 index 0000000..ce641f8 --- /dev/null +++ b/graylog.yml @@ -0,0 +1,36 @@ +# Graylog stack +version: '2' +services: + mongo: + container_name: graylog-mongo + image: "mongo:3" + volumes: + - ./config/graylog:/docker-entrypoint-initdb.d + + elasticsearch: + container_name: graylog-elastic + image: "elasticsearch:2" + command: "elasticsearch -Des.cluster.name='graylog'" + + graylog: + container_name: graylog-server + image: 'graylog2/server:latest' + environment: + GRAYLOG_PASSWORD_SECRET: somepasswordpepper + GRAYLOG_ROOT_PASSWORD_SHA2: 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 + GRAYLOG_WEB_ENDPOINT_URI: http://127.0.0.1:9000/api + depends_on: + - mongo + - elasticsearch + ports: + - "9000:9000" + + filebeats: + container_name: graylog-filebeat + #image: TODO_ON_DOCKERHUB_UPLOAD + build: ./images/filebeat + depends_on: + - graylog + volumes: + - ./config/graylog/filebeat:/mnt + - ./logs:/app-logs \ No newline at end of file diff --git a/images/apache_php54/bootstrap.sh b/images/apache_php54/bootstrap.sh index 53b4998..b31394a 100644 --- a/images/apache_php54/bootstrap.sh +++ b/images/apache_php54/bootstrap.sh @@ -55,9 +55,8 @@ trap clean_up SIGTERM service apache2 restart - echo [`date`] Bootstrap finished tail -f /dev/null & child=$! -wait "$child" \ No newline at end of file +wait "$child" diff --git a/images/apache_php56/bootstrap.sh b/images/apache_php56/bootstrap.sh index 8307a73..dd5336c 100644 --- a/images/apache_php56/bootstrap.sh +++ b/images/apache_php56/bootstrap.sh @@ -56,9 +56,8 @@ trap clean_up SIGTERM service apache2 restart - echo [`date`] Bootstrap finished tail -f /dev/null & child=$! -wait "$child" \ No newline at end of file +wait "$child" diff --git a/images/apache_php7/bootstrap.sh b/images/apache_php7/bootstrap.sh index 8307a73..dd5336c 100644 --- a/images/apache_php7/bootstrap.sh +++ b/images/apache_php7/bootstrap.sh @@ -56,9 +56,8 @@ trap clean_up SIGTERM service apache2 restart - echo [`date`] Bootstrap finished tail -f /dev/null & child=$! -wait "$child" \ No newline at end of file +wait "$child" diff --git a/images/filebeat/Dockerfile b/images/filebeat/Dockerfile new file mode 100644 index 0000000..5f6db7a --- /dev/null +++ b/images/filebeat/Dockerfile @@ -0,0 +1,6 @@ +FROM docker.elastic.co/beats/filebeat:5.4.2 +USER root +COPY service.sh /root/service.sh +RUN chmod +x /root/service.sh && mkdir /usr/share/filebeat/conf.d/ +WORKDIR /usr/share/filebeat/ +CMD ["/root/service.sh"] diff --git a/images/filebeat/service.sh b/images/filebeat/service.sh new file mode 100644 index 0000000..a4a5a50 --- /dev/null +++ b/images/filebeat/service.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# Copy config to have file with root owner +cp /mnt/conf.d/* /usr/share/filebeat/conf.d/ +cd /usr/share/filebeat/conf.d/ + +configFileAmount=$(ls -l *.conf.yml | egrep -c '^-') +currentFile=0 + +# Avoid troll config +if [ $configFileAmount -gt 25 ];then + echo "Too much config files detected" + exit 1 +fi + +# Create a worker for each defined service, each one need his own registery so we make a folder for each +for f in *.conf.yml;do + (( currentFile++ )) + if [ $currentFile -eq $configFileAmount ];then + mkdir "workdir-$f" && mv $f "workdir-$f" && cd "workdir-$f" + exec filebeat -c $f + cd .. + else + mkdir "workdir-$f" && mv $f "workdir-$f" && cd "workdir-$f" + filebeat -c $f & + cd .. + fi +done diff --git a/images/solr4/Dockerfile b/images/solr4/Dockerfile index 5fc2e17..780ae52 100644 --- a/images/solr4/Dockerfile +++ b/images/solr4/Dockerfile @@ -13,7 +13,7 @@ RUN echo $DOCKER_TIMEZONE > /etc/timezone; dpkg-reconfigure -f noninteractive tz # Base packages # ----------------------------------------------------------------------------- RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqy \ - openjdk-7-jre-headless + openjdk-7-jre-headless; COPY ./solr_4.10 /opt/solr COPY init/solr /etc/init.d/solr @@ -31,4 +31,4 @@ EXPOSE 8983 WORKDIR /opt/solr -CMD ["/root/bootstrap.sh"] \ No newline at end of file +CMD ["/root/bootstrap.sh"] diff --git a/images/solr4/bootstrap.sh b/images/solr4/bootstrap.sh index 85d1a78..97d65ed 100755 --- a/images/solr4/bootstrap.sh +++ b/images/solr4/bootstrap.sh @@ -19,4 +19,4 @@ echo [`date`] Bootstrap finished tail -f /dev/null & child=$! -wait "$child" \ No newline at end of file +wait "$child" diff --git a/images/varnish40/Dockerfile b/images/varnish40/Dockerfile index 5c6050e..9dfa707 100644 --- a/images/varnish40/Dockerfile +++ b/images/varnish40/Dockerfile @@ -46,4 +46,4 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* EXPOSE 81 EXPOSE 6082 -CMD ["/root/bootstrap.sh"] \ No newline at end of file +CMD ["/root/bootstrap.sh"] diff --git a/images/varnish40/bootstrap.sh b/images/varnish40/bootstrap.sh index 9bc388c..a96f0a4 100755 --- a/images/varnish40/bootstrap.sh +++ b/images/varnish40/bootstrap.sh @@ -28,4 +28,4 @@ echo [`date`] Bootstrap finished tail -f /dev/null & child=$! -wait "$child" \ No newline at end of file +wait "$child" diff --git a/images/varnish40/etc/default/varnishncsa b/images/varnish40/etc/default/varnishncsa index 39a5ea3..4ea9c8a 100644 --- a/images/varnish40/etc/default/varnishncsa +++ b/images/varnish40/etc/default/varnishncsa @@ -11,7 +11,7 @@ # NCSA log format, to be used by HTTP log analyzers VARNISHNCSA_ENABLED=1 -LOG_FORMAT="%h|%u|%{%Y-%m-%d}t|%{%H:%M:%S}t|%{%z}t|%m|%{Host}i|%U|%q|%s|%b|%{Referer}i|%{User-agent}i|%{Varnish:time_firstbyte}x|%T|%D|%{Varnish:handling}x|%{X-FE-Varnish-Obj-TTL}o|%{X-FE-Varnish-Obj-Stat}o|%{X-Location-Id}i" +LOG_FORMAT="%h~%u~%{%Y-%m-%d}t~%{%H:%M:%S}t~%{%z}t~%m~%{Host}i~%U~%q~%s~%b~%{Referer}i~%{User-agent}i~%{Varnish:time_firstbyte}x~%T~%D~%{Varnish:handling}x~%{X-FE-Varnish-Obj-TTL}o~%{X-FE-Varnish-Backend}o~%{X-FE-Varnish-Obj-Stat}o~%{X-Location-Id}i~%{X-Match}i" DAEMON_OPTS="-a -w /var/log/varnish/varnishncsa.log -D -P /var/run/varnishncsa/varnishncsa.pid -F ${LOG_FORMAT}" @@ -84,3 +84,12 @@ DAEMON_OPTS="-a -w /var/log/varnish/varnishncsa.log -D -P /var/run/varnishncsa/v # 20 %{X-FE-Varnish-Obj-Stat}o # Custom header showing whether request resulted in cache HIT # or MISS, if HIT, the number of HITs thus far for the object. +# +# 21 %{X-Location-Id}i +# +# Custom header showing locationID of banned eZPublish contents. +# +# 22 %{X-Match}i +# +# Custom header displaying a url path that will be banned. +# diff --git a/stack.sh b/stack.sh index 4a636a6..bd3e25b 100755 --- a/stack.sh +++ b/stack.sh @@ -302,4 +302,4 @@ case "$1" in # any other variation, let it go directly through to docker-compose $DOCKER_COMPOSE -p "$DOCKER_PROJECT_NAME" $@ -esac \ No newline at end of file +esac