├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── build ├── install_modules.sh ├── install_themes.sh ├── modules.json └── themes.json ├── compose ├── config │ └── nginx.conf ├── database.yml ├── grafana.yml ├── graphite.yml ├── head.yml ├── icingaweb2.yml ├── influxdb.yml ├── master.yml ├── nginx.yml ├── satellite.yml └── ssl │ ├── cert.pem │ ├── dh.pem │ └── key.pem ├── docker-compose_example.yml ├── hooks ├── build ├── clean ├── compose-file ├── environment ├── exec ├── github-cache ├── offline_modules ├── offline_themes ├── run ├── shell ├── start └── stop ├── import ├── dashboards │ ├── icinga2-default.json │ ├── icinga2-details.json │ └── itl-icinga_rev1.json └── provisioning │ ├── dashboards │ └── dashboards.yml │ ├── datasources │ └── datasource.yml │ └── notifiers │ └── notifier.yml ├── rootfs ├── etc │ ├── icingaweb2 │ │ ├── authentication.ini │ │ ├── config.ini │ │ ├── modules │ │ │ ├── boxydash │ │ │ │ └── config.ini │ │ │ ├── director │ │ │ │ └── config.ini │ │ │ └── monitoring │ │ │ │ ├── backends.ini │ │ │ │ ├── commandtransports.ini │ │ │ │ └── config.ini │ │ └── preferences │ │ │ └── icinga │ │ │ └── config.ini │ ├── nginx │ │ ├── modules.d │ │ │ ├── 00-health_check.conf │ │ │ ├── 00-restrictions.conf │ │ │ └── 99-icingaweb.conf │ │ ├── nginx.conf │ │ └── sites-enabled │ │ │ └── 01-icingaweb.conf │ ├── php7 │ │ └── php-fpm.conf │ ├── supervisor.d │ │ ├── nginx.ini │ │ └── php-fpm.ini │ └── supervisord.conf └── init │ ├── common.sh │ ├── create_login_users.sh │ ├── custom.d │ ├── .keep │ └── x509 │ │ ├── .keep │ │ └── jobs.ini │ ├── database │ ├── fix_latin1_db_statements.sh │ └── mysql.sh │ ├── ini_parser.sh │ ├── modules.d │ ├── authentication.sh │ ├── commandtransport.sh │ ├── director.sh │ ├── grafana.sh │ ├── graphite.sh │ ├── reporting.sh │ ├── skeleton │ ├── vspheredb.sh │ └── x509.sh │ ├── output.sh │ ├── run.sh │ ├── runtime │ ├── watch_vspheredb.sh │ └── watch_x509.sh │ └── wait_for │ ├── dns.sh │ ├── grafana.sh │ ├── icinga_master.sh │ ├── mysql.sh │ └── port.sh └── tests ├── input-raw-tcp.json ├── input-syslog-tcp.json ├── integration_test.sh └── linter.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .env 3 | docker-compose.yml 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | services: 3 | - docker 4 | env: 5 | global: 6 | - ICINGAWEB_VERSION=${ICINGAWEB_VERSION:-2.7.0} 7 | - BUILD_DATE=$(date +"%Y-%m-%d") 8 | - BUILD_TYPE=${ICINGAWEB_VERSION:-stable} 9 | - ICINGAWEB_DIRECTOR=${ICINGAWEB_DIRECTOR:-false} 10 | - secure: hyPBzfOysnyHSvtZx02W6Bp8AGLBPTH2kabS6AAloXffNz6rT2VexiNuEYO2DYSAIFBRRqLdaHIImKb+jJqJ/G9EPuUKjUzX/V/E6wGhU7hqx4/vUis9rTB3xtJedfT63a7t5T14uVv4rnkMBWANGwXmzDrtPK+Ay2rnENE6MQ2Neg4VmJO69b7IV6I1pqe23wdaNAWR+intSu0C3/n2daygr9N78sGoqZD/Fy3mfc6+ubY6f5A9/EDVZTpaCvAi3iaSEkHu+bRPEmykS/MZQXb7jDlQ4VntlmNvrVyf9srF6Pcd+Hgc/9nixtpF1WnpE4PjXSAqgUdvoYRRW5Ng+zZWGPQ5MY8MUqW6CzTTNhc0iMsR72qb96oGRjDIOleLc7V71EZMXK/puQ/i9+z+2l3GxK0MyYB/9+CPcXLdPq3eOou3ujCj+NBzezQysp909AuGKbBwWxfvLBrATq9hGwJe71zQOPE1pjOkQqTDcY7rQVocem8OeH2iYfKkZZNxEwrx5q52oED7xoHxME+Hwt/z1lUZJC452EUaWjsvUREppryjqJDtn4LrTh7hOq5Cm+NwB5ZugyniIbdhPy9/OJVM5pyGK9SQXxZVd0F+XK1SM1LYKYFvfkMWTh5AnyhLIgwvs3W8vYYkiCj09pv/CRBIkSPnMHrikcxIzkMzDLo= 11 | jobs: 12 | include: 13 | - stage: build 14 | script: 15 | - make 16 | - stage: build and test 17 | script: 18 | - make offline_themes 19 | - make offline_modules 20 | - make compose-file 21 | - docker-compose build 22 | - docker-compose up -d 23 | - sleep 2m 24 | - make test 25 | - docker-compose kill 26 | - docker-compose down 27 | - stage: push latest docker image 28 | if: branch = master 29 | script: 30 | - travis_wait 40 make 31 | - docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}" 32 | - docker tag ${USER}/icingaweb2:latest ${DOCKER_USERNAME}/docker-icingaweb2:latest 33 | - docker push ${DOCKER_USERNAME}/docker-icingaweb2:latest 34 | - docker logout 35 | - stage: push version docker image 36 | if: branch = master 37 | script: 38 | - travis_wait 40 make 39 | - docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}" 40 | - docker tag ${USER}/icingaweb2:latest ${DOCKER_USERNAME}/docker-icingaweb2:${ICINGAWEB_VERSION} 41 | - docker push ${DOCKER_USERNAME}/docker-icingaweb2:${ICINGAWEB_VERSION} 42 | - docker logout 43 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | FROM alpine:3.10 as stage1 3 | 4 | # hadolint ignore=DL3018 5 | RUN \ 6 | apk update --quiet --no-cache 7 | 8 | # hadolint ignore=DL3018 9 | RUN \ 10 | apk add --quiet --no-cache \ 11 | build-base \ 12 | ca-certificates \ 13 | curl \ 14 | php7-dev \ 15 | php7-fpm \ 16 | php7-ctype \ 17 | php7-curl \ 18 | php7-dom \ 19 | php7-fpm \ 20 | php7-gettext \ 21 | php7-gd \ 22 | php7-iconv \ 23 | php7-intl \ 24 | php7-json \ 25 | php7-ldap \ 26 | php7-mbstring \ 27 | php7-openssl \ 28 | php7-pdo_mysql \ 29 | php7-pear \ 30 | php7-phar \ 31 | php7-session \ 32 | php7-simplexml \ 33 | php7-tokenizer \ 34 | php7-xml \ 35 | yaml \ 36 | yaml-dev 37 | 38 | # patch fucking pecl to read php.ini 39 | RUN \ 40 | sed -i "s|$PHP -C -n -q |$PHP -C -q |" /usr/bin/pecl 41 | 42 | RUN \ 43 | pecl channel-update pecl.php.net 44 | 45 | # hadolint ignore=DL4006 46 | RUN \ 47 | (yes '' | pecl install yaml) && \ 48 | (yes '' | pecl install xdebug) 49 | 50 | # --------------------------------------------------------------------------------------- 51 | 52 | FROM alpine:3.10 as stage2 53 | 54 | ARG VCS_REF 55 | ARG BUILD_DATE 56 | ARG BUILD_VERSION 57 | ARG BUILD_TYPE 58 | ARG ICINGAWEB_VERSION 59 | ARG INSTALL_THEMES 60 | ARG INSTALL_MODULES 61 | 62 | # hadolint ignore=DL3018 63 | RUN \ 64 | apk update --quiet --no-cache && \ 65 | apk add --quiet --no-cache \ 66 | bash \ 67 | ca-certificates \ 68 | curl \ 69 | composer \ 70 | jq \ 71 | git 72 | 73 | # hadolint ignore=DL3018 74 | RUN \ 75 | apk add --quiet --no-cache \ 76 | php7 \ 77 | php7-ctype \ 78 | php7-openssl \ 79 | php7-intl \ 80 | php7-gettext 81 | 82 | COPY build /build 83 | 84 | WORKDIR /tmp 85 | 86 | # hadolint ignore=DL3003,DL4006 87 | RUN \ 88 | mkdir /usr/share/webapps && \ 89 | if [ -z "${BUILD_TYPE}" ] || [ "${BUILD_TYPE}" = "stable" ] ; then \ 90 | echo "install icingaweb2 v${ICINGAWEB_VERSION}" && \ 91 | curl \ 92 | --silent \ 93 | --location \ 94 | --retry 3 \ 95 | --cacert /etc/ssl/certs/ca-certificates.crt \ 96 | "https://github.com/Icinga/icingaweb2/archive/v${ICINGAWEB_VERSION}.tar.gz" \ 97 | | gunzip \ 98 | | tar x -C /usr/share/webapps/ && \ 99 | ln -s "/usr/share/webapps/icingaweb2-${ICINGAWEB_VERSION}" /usr/share/webapps/icingaweb2 ; \ 100 | else \ 101 | echo "install icingaweb2 from git " && \ 102 | git clone https://github.com/Icinga/icingaweb2.git && \ 103 | cd icingaweb2 && \ 104 | version=$(git describe --tags --always | sed 's/^v//') && \ 105 | echo " version: ${version}" && \ 106 | rm -rf /tmp/icingaweb2/.git* && \ 107 | rm -rf /tmp/icingaweb2/.puppet && \ 108 | mv /tmp/icingaweb2 /usr/share/webapps/ ; \ 109 | fi 110 | 111 | RUN \ 112 | ln -s /usr/share/webapps/icingaweb2/bin/icingacli /usr/bin/icingacli && \ 113 | mkdir -p /var/log/icingaweb2 && \ 114 | mkdir -p /etc/icingaweb2/modules && \ 115 | mkdir -p /etc/icingaweb2/enabledModules 116 | 117 | #RUN \ 118 | # /build/install_modules.sh 119 | 120 | #RUN \ 121 | # /build/install_themes.sh 122 | 123 | COPY build/icingaweb2-modules /usr/share/webapps/icingaweb2/modules/ 124 | COPY build/icingaweb2-themes /usr/share/webapps/icingaweb2/modules/ 125 | 126 | RUN \ 127 | /build/install_themes.sh 128 | 129 | # --------------------------------------------------------------------------------------- 130 | 131 | FROM alpine:3.10 as final 132 | 133 | ARG VCS_REF 134 | ARG BUILD_DATE 135 | ARG BUILD_VERSION 136 | ARG BUILD_TYPE 137 | ARG ICINGAWEB_VERSION 138 | ARG INSTALL_THEMES 139 | ARG INSTALL_MODULES 140 | 141 | COPY --from=stage1 /usr/lib/php7/modules/yaml.so /usr/lib/php7/modules/ 142 | COPY --from=stage1 /usr/lib/php7/modules/xdebug.so /usr/lib/php7/modules/ 143 | COPY --from=stage2 /usr/share/webapps /usr/share/webapps 144 | COPY --from=stage2 /etc/icingaweb2 /etc/icingaweb2 145 | 146 | # hadolint ignore=DL3017,DL3018 147 | RUN \ 148 | apk update --quiet --no-cache && \ 149 | apk upgrade --quiet --no-cache && \ 150 | apk add --quiet --no-cache \ 151 | bash \ 152 | bind-tools \ 153 | ca-certificates \ 154 | curl \ 155 | inotify-tools \ 156 | jq \ 157 | mysql-client \ 158 | nginx \ 159 | netcat-openbsd \ 160 | openssl \ 161 | php7 \ 162 | php7-ctype \ 163 | php7-fpm \ 164 | php7-pdo_mysql \ 165 | php7-openssl \ 166 | php7-intl \ 167 | php7-ldap \ 168 | php7-gettext \ 169 | php7-json \ 170 | php7-mbstring \ 171 | php7-curl \ 172 | php7-iconv \ 173 | php7-session \ 174 | php7-xml \ 175 | php7-dom \ 176 | php7-soap \ 177 | php7-sockets \ 178 | php7-posix \ 179 | php7-pcntl \ 180 | php7-gmp \ 181 | shadow \ 182 | tzdata \ 183 | pwgen \ 184 | yaml \ 185 | yajl-tools && \ 186 | cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime && \ 187 | echo "extension=yaml.so" > /etc/php7/conf.d/ext-yaml.ini && \ 188 | echo "zend_extension=xdebug.so" > /etc/php7/conf.d/ext-xdebug.ini.disabled && \ 189 | sed -i -e '/^#/ d' -e '/^;/ d' -e '/^ *$/ d' /etc/php7/php.ini && \ 190 | ln -s /usr/share/webapps/icingaweb2/bin/icingacli /usr/bin/icingacli && \ 191 | mkdir -p /var/log/icingaweb2 && \ 192 | /usr/bin/icingacli module disable setup && \ 193 | /usr/bin/icingacli module enable monitoring 2> /dev/null && \ 194 | /usr/bin/icingacli module enable translation 2> /dev/null && \ 195 | /usr/bin/icingacli module enable doc 2> /dev/null && \ 196 | mkdir /run/nginx && \ 197 | mkdir /var/log/php-fpm && \ 198 | apk del --quiet \ 199 | tzdata && \ 200 | rm -rf \ 201 | /build \ 202 | /tmp/* \ 203 | /var/cache/apk/* 204 | 205 | COPY rootfs/ / 206 | 207 | WORKDIR /etc/icingaweb2 208 | 209 | VOLUME ["/etc/icingaweb2", "/usr/share/webapps/icingaweb2", "/init/custom.d"] 210 | 211 | HEALTHCHECK \ 212 | --interval=5s \ 213 | --timeout=2s \ 214 | --retries=12 \ 215 | CMD curl --silent --fail http://localhost/health || exit 1 216 | 217 | CMD ["/init/run.sh"] 218 | 219 | # --------------------------------------------------------------------------------------- 220 | 221 | # Build-time metadata as defined at http://label-schema.org 222 | LABEL \ 223 | version=${BUILD_VERSION} \ 224 | maintainer="Bodo Schulz " \ 225 | org.label-schema.build-date=${BUILD_DATE} \ 226 | org.label-schema.name="IcingaWeb2 Docker Image" \ 227 | org.label-schema.description="Inofficial IcingaWeb2 Docker Image" \ 228 | org.label-schema.url="https://www.icinga.org/" \ 229 | org.label-schema.vcs-ref=${VCS_REF} \ 230 | org.label-schema.vcs-url="https://github.com/bodsch/docker-icingaweb2" \ 231 | org.label-schema.vendor="Bodo Schulz" \ 232 | org.label-schema.version=${ICINGAWEB_VERSION} \ 233 | org.label-schema.schema-version="1.0" \ 234 | com.microscaling.docker.dockerfile="/Dockerfile" \ 235 | com.microscaling.license="GNU General Public License v3.0" 236 | 237 | # --------------------------------------------------------------------------------------- 238 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export GIT_SHA1 := $(shell git rev-parse --short HEAD) 2 | export DOCKER_IMAGE_NAME := icingaweb2 3 | export DOCKER_NAME_SPACE := ${USER} 4 | export DOCKER_VERSION ?= latest 5 | export BUILD_DATE := $(shell date +%Y-%m-%d) 6 | export BUILD_VERSION := $(shell date +%y%m) 7 | export BUILD_TYPE ?= stable 8 | export ICINGAWEB_VERSION ?= 2.7.0 9 | export INSTALL_THEMES ?= true 10 | export INSTALL_MODULES ?= true 11 | 12 | 13 | .PHONY: build shell run exec start stop clean compose-file github-cache 14 | 15 | default: build 16 | 17 | github-cache: 18 | @hooks/github-cache 19 | 20 | offline_themes: 21 | @hooks/offline_themes 22 | 23 | offline_modules: 24 | @hooks/offline_modules 25 | 26 | build: offline_themes offline_modules 27 | @hooks/build 28 | 29 | shell: 30 | @hooks/shell 31 | 32 | run: 33 | @hooks/run 34 | 35 | exec: 36 | @hooks/exec 37 | 38 | start: 39 | @hooks/start 40 | 41 | stop: 42 | @hooks/stop 43 | 44 | clean: 45 | @hooks/clean 46 | 47 | compose-file: 48 | @hooks/compose-file 49 | 50 | linter: 51 | @tests/linter.sh 52 | 53 | integration_test: 54 | @tests/integration_test.sh 55 | 56 | test: linter integration_test 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | docker-icingaweb2 2 | ================= 3 | 4 | Docker Container for icingaweb2 based on alpine-linux. 5 | 6 | Now with PHP7 (7.x) Support and many installed modules and themes (see below). 7 | 8 | # Status 9 | 10 | [![Docker Pulls](https://img.shields.io/docker/pulls/bodsch/docker-icingaweb2.svg)][hub] 11 | [![Image Size](https://images.microbadger.com/badges/image/bodsch/docker-icingaweb2.svg)][microbadger] 12 | [![Build Status](https://travis-ci.org/bodsch/docker-icingaweb2.svg)][travis] 13 | 14 | [hub]: https://hub.docker.com/r/bodsch/docker-icingaweb2/ 15 | [microbadger]: https://microbadger.com/images/bodsch/docker-icingaweb2 16 | [travis]: https://travis-ci.org/bodsch/docker-icingaweb2 17 | 18 | 19 | # Build 20 | 21 | Your can use the included Makefile. 22 | 23 | - To build the Container: `make build` 24 | - To remove the builded Docker Image: `make clean` 25 | - Starts the Container: `make run` 26 | - Starts the Container with Login Shell: `make shell` 27 | - Entering the Container: `make exec` 28 | - Stop (but **not kill**): `make stop` 29 | - History `make history` 30 | 31 | 32 | # director integration in combination with a dockerized icinga2-master 33 | 34 | The Director will be automated configured. 35 | For this we need a stable running Icinga2 master. 36 | 37 | For this we check the availability of the API port (5665) and wait until the Icinga2 master has reached an uptime of 2 minutes. 38 | 39 | 40 | # Modules 41 | 42 | - [director](https://github.com/Icinga/icingaweb2-module-director) 43 | - [graphite](https://github.com/Icinga/icingaweb2-module-graphite) 44 | - [genericTTS](https://github.com/Icinga/icingaweb2-module-generictts) 45 | - [businessprocess](https://github.com/Icinga/icingaweb2-module-businessprocess) 46 | - [elasticsearch](https://github.com/Icinga/icingaweb2-module-elasticsearch) 47 | - [cube](https://github.com/Icinga/icingaweb2-module-cube) 48 | - [aws](https://github.com/Icinga/icingaweb2-module-aws) 49 | - [fileshipper](https://github.com/Icinga/icingaweb2-module-fileshipper) 50 | - [grafana](https://github.com/Mikesch-mp/icingaweb2-module-grafana) 51 | - [globe](https://github.com/Mikesch-mp/icingaweb2-module-globe) 52 | - [map](https://github.com/nbuchwitz/icingaweb2-module-map) 53 | - [boxydash](https://github.com/morgajel/icingaweb2-module-boxydash) 54 | - [toplevelview](https://github.com/Icinga/icingaweb2-module-toplevelview) 55 | - [vspheredb](https://github.com/Thomas-Gelf/icingaweb2-module-vspheredb) 56 | - [x509](https://github.com/Icinga/icingaweb2-module-x509d) 57 | 58 | 59 | 60 | ## vspheredb 61 | 62 | The implementation of the plugin used here does not use the integrated daemon, because it is 63 | currently causing problems.
64 | Instead, the commandline tools are integrated via a separate process. 65 | 66 | ### known bus / problems 67 | 68 | After deleting a vcenter, fragments of VMs, datastores, etc. remain in the database and can still be displayed. 69 | 70 | ## x509 71 | 72 | You can add an customized configuration for the `x509` module by adding an directory `/init/custom.d/x509` and drop a `jobs.ini` file: 73 | 74 | Example file 75 | ```bash 76 | [google] 77 | cidrs = "172.217.21.227/32" 78 | ports = "443" 79 | schedule = "0 0 * * *" 80 | ``` 81 | For more information read the module [documentation](https://github.com/Icinga/icingaweb2-module-x509/blob/master/doc/03-Configuration.md)! 82 | 83 | 84 | # Themes 85 | 86 | - [unicorn](https://github.com/Mikesch-mp/icingaweb2-theme-unicorn) 87 | - [lsd](https://github.com/Mikesch-mp/icingaweb2-theme-lsd) 88 | - [april](https://github.com/Mikesch-mp/icingaweb2-theme-april) 89 | - [company](https://github.com/Icinga/icingaweb2-theme-company) 90 | - [batman](https://github.com/jschanz/icingaweb2-theme-batman) 91 | - [batman-dark](https://github.com/jschanz/icingaweb2-theme-batman-dark) 92 | - [nordlicht](https://github.com/sysadmama/icingaweb2-theme-nordlicht) 93 | - [spring](https://github.com/dnsmichi/icingaweb2-theme-spring) 94 | - [dark](https://github.com/vita2/icingaweb2-module-theme-dark) 95 | - [beyondthepines](https://github.com/Wintermute2k6/icingaweb2-module-beyondthepines) 96 | - [always-green](https://github.com/xam-stephan/icingaweb2-module-theme-always-green) 97 | - [colourblind](https://github.com/sol1/icingaweb2-theme-colourblind) 98 | - [particles](https://github.com/Mikesch-mp/icingaweb2-theme-particles) 99 | 100 | 101 | # Docker Hub 102 | 103 | You can find the Container also at [DockerHub](https://hub.docker.com/r/bodsch/docker-icingaweb2/) 104 | 105 | 106 | # supported Environment Vars 107 | 108 | | Environmental Variable | Default Value | Description | 109 | | :--------------------------------- | :------------- | :----------- | 110 | | `MYSQL_HOST` | - | MySQL Host | 111 | | `MYSQL_PORT` | `3306` | MySQL Port | 112 | | `MYSQL_ROOT_USER` | `root` | MySQL root User | 113 | | `MYSQL_ROOT_PASS` | - | MySQL root password | 114 | | `IDO_DATABASE_NAME` | `icinga2core` | Schema Name for IDO | 115 | | `IDO_PASSWORD` | - | IDO password | 116 | | | | | 117 | | `GRAPHITE_HOST` | - | Hostname for the graphite service
If no hostname is specified, the module is automatically deactivated. | 118 | | `GRAPHITE_HTTP_PORT` | `8080` | graphite port | 119 | | | | | 120 | | `ICINGA2_MASTER` | `icinga2-master` | Icinga2 Host for Command Transport over API | 121 | | `ICINGA2_API_PORT` | `5665` | Icinga2 API Port | 122 | | `ICINGA2_CMD_API_USER` | - | API User for Command Transport | 123 | | `ICINGA2_CMD_API_PASS` | - | API Password for Command Transport | 124 | | | | | 125 | | `ICINGAWEB_ADMIN_USER` | `icinga` | | 126 | | `ICINGAWEB_ADMIN_PASS` | `icinga` | | 127 | | `ICINGAWEB2_USERS` | - | comma separated list to create Icingaweb2 Users. The format are `username:password`
(e.g. `admin:admin,dashing:dashing` and so on) | 128 | | | | | 129 | | `ICINGAWEB_DIRECTOR` | `true` | switch the Director configuration `on` / `off`
Disabling the Director automatically disables the following modules: *x509*, *vspheredb* | 130 | | `ICINGA2_UPTIME` | `125` | Waits (in seconds) for a stable running Icinga2 instance.
Otherwise the Director cannot be configured automatically. | 131 | 132 | ## Grafana Support 133 | 134 | | Environmental Variable | Default Value | Description | 135 | | :--------------------------------- | :------------- | :----------- | 136 | | `GRAFANA_HOST` | `grafana` | | 137 | | `GRAFANA_PORT` | `3000` | | 138 | | `GRAFANA_TIMERANGE` | `12h` | | 139 | | `GRAFANA_TIMERANGE_ALL` | `7d` | | 140 | | `GRAFANA_DASHBOARD` | `icinga2-default` | | 141 | | `GRAFANA_DASHBOARD_UID` | `` | | 142 | | `GRAFANA_PROTOCOL` | `http` | | 143 | | `GRAFANA_ACCESS` | `proxy` | | 144 | | `GRAFANA_AUTHENTICATION` | `token` | | 145 | | `GRAFANA_AUTHENTICATION_TOKEN` | `` | | 146 | | `GRAFANA_AUTHENTICATION_USERNAME` | `admin` | | 147 | | `GRAFANA_AUTHENTICATION_PASSWORD` | `admin` | | 148 | | `GRAFANA_DATASOURCE` | `influxdb` | | 149 | | `GRAFANA_ENABLE_LINK` | `no` | | 150 | | `GRAFANA_SHOW_DEBUG` | `0` | | 151 | | `GRAFANA_PUBLIC` | `no` | | 152 | | `GRAFANA_PUBLIC_HOST` | `localhost/grafana/` | | 153 | | `GRAFANA_PUBLIC_PROTOCOL` | `http` | | 154 | | `GRAFANA_THEME` | `light` | | 155 | | `GRAFANA_PROXY_TIMEOUT` | `5` | | 156 | 157 | 158 | ## LDAP support 159 | 160 | Please read more at the [official Icingaweb2 Doku](https://www.icinga.com/docs/icingaweb2/latest/doc/05-Authentication/#active-directory-or-ldap-authentication). 161 | 162 | The environment variables for LDAP can be configured for 2 different reasons.: 163 | 164 | ### each environment variable is specified individually 165 | 166 | - `LDAP_AD` (default: `false`) is the LDAP server an Active Directory 167 | - `LDAP_SERVER` (default: `-`) the LDAP server 168 | - `LDAP_PORT` (default: `389`) the LDAP Port 169 | - `LDAP_BIND_DN` (default: `-`) LDAP Bind DN 170 | - `LDAP_BIND_PASSWORD` (default: `-`) Bind Password 171 | - `LDAP_BASE_DN` (default: `-`) Base DN 172 | - `LDAP_FILTER` (default: `-`) LDAP filter 173 | - `LDAP_ROLE_GROUPS` (default: `-`) LDAP groups 174 | - `LDAP_ROLE_PERMISSIONS` (default: `*`) LDAP group permissions 175 | 176 | ### an environment variable summarizes everything as json 177 | 178 | - `LDAP`(default: `-`) json formated configuration 179 | 180 | ```json 181 | { 182 | "active_directory": "true", 183 | "server":"${LDAP_SERVER}", 184 | "port":"${LDAP_PORT}", 185 | "bind_dn": "${LDAP_BIND_DN}", 186 | "bind_password": "${LDAP_BIND_PASSWORD}", 187 | "base_dn": "${LDAP_BASE_DN}", 188 | "filter": "${LDAP_FILTER}", 189 | "role": { 190 | "groups": "${LDAP_ROLE_GROUPS}", 191 | "permissions": "${LDAP_ROLE_PERMISSIONS}" 192 | } 193 | } 194 | ``` 195 | 196 | -------------------------------------------------------------------------------- /build/install_modules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # install a set of icingaweb2 modules 4 | 5 | set -e 6 | 7 | [[ "${INSTALL_MODULES}" = "false" ]] && exit 0 8 | 9 | echo "install icingaweb2 modules" 10 | 11 | MODULE_DIRECTORY="/usr/share/webapps/icingaweb2/modules" 12 | 13 | cd /build 14 | 15 | if [[ -f cache.tgz ]] 16 | then 17 | tar -xzf cache.tgz 18 | 19 | cd cache 20 | 21 | for file in $(ls -1 github_*.json) 22 | do 23 | 24 | published_at=$(jq --raw-output ".published_at" ${file}) 25 | project_name=$(jq --raw-output ".project_name" ${file}) 26 | project_maintainer=$(jq --raw-output ".project_maintainer" ${file}) 27 | author=$(jq --raw-output ".author.login" ${file}) 28 | version=$(jq --raw-output ".tag_name" ${file}) 29 | url=$(jq --raw-output ".tarball_url" ${file}) 30 | enable=$(jq --raw-output ".enable" ${file}) 31 | use_git=$(jq --raw-output ".use_git" ${file}) 32 | destination=$(jq --raw-output ".destination" ${file}) 33 | 34 | [[ "${destination}" == null ]] && destination= 35 | 36 | if [[ ${published_at} != null ]] 37 | then 38 | if [[ -e /etc/alpine-release ]] 39 | then 40 | release_date=$(date -d @$(date -u -D %Y-%m-%dT%TZ -d "${published_at}" +%s) +%d.%m.%Y) 41 | else 42 | release_date=$(date -d ${published_at} +%d.%m.%Y) 43 | fi 44 | 45 | release="released at ${release_date}" 46 | 47 | if [[ "${use_git}" == "true" ]] 48 | then 49 | release="${release} but use git" 50 | fi 51 | 52 | else 53 | version="" 54 | release="never released, use git" 55 | fi 56 | 57 | echo " - ${project_name} ${version} (${release}) (${project_maintainer})" 58 | 59 | if [[ ${url} != null ]] && [[ "${use_git}" = "false" ]] 60 | then 61 | if [[ ! -f "${project_name}.tgz" ]] 62 | then 63 | curl \ 64 | --silent \ 65 | --location \ 66 | --retry 3 \ 67 | --output "${project_name}.tgz" \ 68 | ${url} 69 | fi 70 | 71 | if [[ -f "${project_name}.tgz" ]] 72 | then 73 | [[ -d ${MODULE_DIRECTORY} ]] || continue 74 | 75 | tar -xzf ${project_name}.tgz 76 | 77 | if [[ ! -z ${destination} ]] 78 | then 79 | [[ -d ${destination} ]] || mkdir -p ${destination} 80 | 81 | find . -mindepth 1 -maxdepth 1 -type d -name "*${project_name}*" -exec mv {} ${project_name} \; 82 | mv ${project_name}/* ${destination}/ 83 | rm -f ${project_name}.tgz 84 | else 85 | find . -mindepth 1 -maxdepth 1 -type d -name "*${project_name}*" -exec mv {} ${MODULE_DIRECTORY}/${project_name} \; 86 | 87 | rm -f ${project_name}.tgz 88 | mkdir /etc/icingaweb2/modules/${project_name} 89 | fi 90 | fi 91 | 92 | else 93 | 94 | [[ -d icingaweb2-module-${project_name} ]] && rm -rf icingaweb2-module-${project_name} 95 | git clone \ 96 | --quiet \ 97 | https://github.com/${project_maintainer}/icingaweb2-module-${project_name} > /dev/null 98 | 99 | [[ -d ${MODULE_DIRECTORY} ]] || continue 100 | 101 | # install PHP dependency 102 | # 103 | if [[ -e "icingaweb2-module-${project_name}/composer.json" ]] 104 | then 105 | # echo "found composer.json" 106 | pushd icingaweb2-module-${project_name} > /dev/null 107 | 108 | /usr/bin/composer install > /dev/null 2> /dev/null 109 | 110 | popd > /dev/null 111 | fi 112 | 113 | mv icingaweb2-module-${project_name} ${MODULE_DIRECTORY}/${project_name} 114 | fi 115 | 116 | if [[ "${enable}" = "true" ]] && [[ -d ${MODULE_DIRECTORY}/${project_name} ]] 117 | then 118 | /usr/bin/icingacli module enable ${project_name} 2> /dev/null 119 | fi 120 | 121 | done 122 | 123 | find ${MODULE_DIRECTORY} -name ".git*" -exec rm -rf {} 2> /dev/null \; || true 124 | 125 | else 126 | echo "no cached github information found" 127 | fi 128 | -------------------------------------------------------------------------------- /build/install_themes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # install a set of icingaweb2 themes 4 | 5 | [[ "${INSTALL_THEMES}" = "false" ]] && exit 0 6 | 7 | echo "install icingaweb2 themes" 8 | 9 | MODULE_DIRECTORY="/usr/share/webapps/icingaweb2/modules" 10 | 11 | cd /tmp 12 | 13 | if [[ -f /build/themes.json ]] 14 | then 15 | THEMES_JSON=$(cat /build/themes.json) 16 | else 17 | THEMES_JSON='{ 18 | "Mikesch-mp/icingaweb2-theme-unicorn" : { 19 | "image": [{ 20 | "name": "unicorn.png", 21 | "url": "http://i.imgur.com/SCfMd.png" 22 | }] 23 | }, 24 | "Icinga/icingaweb2-theme-company": {}, 25 | "jschanz/icingaweb2-theme-batman": {}, 26 | "sysadmama/icingaweb2-theme-nordlicht": {}, 27 | "dnsmichi/icingaweb2-theme-spring": {}, 28 | "vita2/icingaweb2-module-theme-dark": {} 29 | }' 30 | fi 31 | 32 | #set -e 33 | 34 | for k in $(echo ${THEMES_JSON} | jq -r '. | to_entries | .[] | .key') 35 | do 36 | enable="$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].enable")" 37 | [[ "${enable}" == null ]] && enable=true 38 | 39 | project="$(echo "${k}" | sed -e 's|\.git||g' -e 's/https\?:\/\///' -e 's|github.com/||g')" 40 | project_maintainer="$(echo "${project}" | cut -d "/" -f1)" 41 | project_name="$(echo "${project}" | cut -d "/" -f2 | sed -e 's|icingaweb2-||g' -e 's|module-||g' -e 's|theme-||g' | tr [:upper:] [:lower:])" 42 | outpath=$(echo "${project}" | tr [:upper:] [:lower:] | sed -e 's|/|_|g') 43 | 44 | #echo " - ${project_name} (${project_maintainer})" 45 | 46 | #[[ -d ${outpath} ]] || mkdir ${outpath} 47 | #[[ -d ${MODULE_DIRECTORY}/${project_name} ]] || mkdir ${MODULE_DIRECTORY}/${project_name} 48 | # 49 | #pushd ${outpath} > /dev/null 50 | # 51 | #git clone https://github.com/${k} 2> /dev/null 52 | # 53 | #images=$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].image") 54 | # 55 | #if [[ $images != null ]] 56 | #then 57 | # data=$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].image") 58 | # 59 | # for row in $(echo "${data}" | jq -r '.[] | @base64'); do 60 | # _jq() { 61 | # echo ${row} | base64 -d | jq -r ${1} 62 | # } 63 | # 64 | # name=$(_jq '.name') 65 | # url=$(_jq '.url') 66 | # 67 | # curl \ 68 | # --silent \ 69 | # --location \ 70 | # --retry 3 \ 71 | # --output ${name} \ 72 | # ${url} 73 | # 74 | # mv ${name} */public/img/ 75 | # done 76 | #fi 77 | # 78 | #mv */public ${MODULE_DIRECTORY}/${project_name}/ 79 | 80 | if [[ "${enable}" = "true" ]] 81 | then 82 | echo " enable module" 83 | /usr/bin/icingacli module enable ${project_name} 2> /dev/null 84 | fi 85 | 86 | # popd > /dev/null 87 | done 88 | -------------------------------------------------------------------------------- /build/modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "aws/aws-sdk-php": { 3 | "destination": "/usr/share/webapps/icingaweb2/modules/aws/library/vendor/aws" 4 | }, 5 | "Icinga/icingaweb2-module-aws": {}, 6 | "https://github.com/Icinga/icingaweb2-module-director": {}, 7 | "Icinga/icingaweb2-module-vsphere": { 8 | "ignore": "true" 9 | }, 10 | "Icinga/icingaweb2-module-vspheredb": {}, 11 | "Icinga/icingaweb2-module-graphite": {}, 12 | "Icinga/icingaweb2-module-generictts": {}, 13 | "Icinga/icingaweb2-module-businessprocess": {}, 14 | "Icinga/icingaweb2-module-elasticsearch": {}, 15 | "Icinga/icingaweb2-module-cube": {}, 16 | "Icinga/icingaweb2-module-fileshipper": {}, 17 | "Icinga/icingaweb2-module-toplevelview": {}, 18 | "Icinga/icingaweb2-module-x509": {}, 19 | "Icinga/icingaweb2-module-reporting": { 20 | "ignore": "true", 21 | "use_git": "true" 22 | }, 23 | "Mikesch-mp/icingaweb2-module-grafana": {}, 24 | "Mikesch-mp/icingaweb2-module-globe": {}, 25 | "nbuchwitz/icingaweb2-module-map": {}, 26 | "morgajel/icingaweb2-module-boxydash": {}, 27 | "Thomas-Gelf/icingaweb2-module-reporting": { 28 | "ignore": "true", 29 | "use_git": "true" 30 | }, 31 | "https://github.com/Icinga/icingaweb2-module-reactbundle": {}, 32 | "https://github.com/Icinga/icingaweb2-module-ipl": {}, 33 | "https://github.com/Icinga/icingaweb2-module-incubator": {}, 34 | "https://github.com/Icinga/icingaweb2-module-pdfexport": {} 35 | } 36 | -------------------------------------------------------------------------------- /build/themes.json: -------------------------------------------------------------------------------- 1 | { 2 | "Mikesch-mp/icingaweb2-theme-unicorn" : { 3 | "image": [{ 4 | "name": "unicorn.png", 5 | "url": "http://i.imgur.com/SCfMd.png" 6 | }] 7 | }, 8 | "Mikesch-mp/icingaweb2-theme-lsd": {}, 9 | "Mikesch-mp/icingaweb2-theme-particles": {}, 10 | "Mikesch-mp/icingaweb2-theme-april": {}, 11 | "Icinga/icingaweb2-theme-company": {}, 12 | "jschanz/icingaweb2-theme-batman": {}, 13 | "jschanz/icingaweb2-theme-batman-dark": {}, 14 | "sysadmama/icingaweb2-theme-nordlicht": {}, 15 | "dnsmichi/icingaweb2-theme-spring": {}, 16 | "vita2/icingaweb2-module-theme-dark": {}, 17 | "xam-stephan/icingaweb2-module-theme-always-green": {}, 18 | "sol1/icingaweb2-theme-colourblind": {} 19 | } 20 | -------------------------------------------------------------------------------- /compose/config/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | worker_processes 1; 3 | 4 | error_log /dev/stdout warn; 5 | 6 | daemon off; 7 | pid run/nginx.pid; 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | http { 14 | include mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; 18 | 19 | map $http_user_agent $ignore_ua { 20 | default 1; 21 | "ELB-HealthChecker/1.0" 0; 22 | "ELB-HealthChecker/2.0" 0; 23 | } 24 | 25 | access_log /dev/stdout main; 26 | 27 | sendfile on; 28 | 29 | keepalive_timeout 300; 30 | send_timeout 600; 31 | 32 | gzip on; 33 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 34 | 35 | include /etc/nginx/conf.d/*.conf; 36 | 37 | server { 38 | listen *:80 default_server; 39 | server_name _; 40 | 41 | log_not_found off; 42 | access_log off; 43 | error_log off; 44 | 45 | # we want an permantent redirect to https 46 | # 47 | if ($ssl_protocol = "") { 48 | return 301 https://$host$request_uri; 49 | } 50 | } 51 | 52 | server { 53 | listen *:443 ssl http2; 54 | server_name _; 55 | 56 | resolver 127.0.0.11 valid=2; 57 | 58 | ssl on; 59 | ssl_certificate /etc/nginx/secure/localhost/cert.pem; 60 | ssl_certificate_key /etc/nginx/secure/localhost/key.pem; 61 | ssl_dhparam /etc/nginx/secure/localhost/dh.pem; 62 | 63 | # only this domain 64 | add_header Strict-Transport-Security "max-age=31536000"; 65 | 66 | # apply also on subdomains 67 | add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; 68 | 69 | include conf.d/ssl.conf; 70 | include modules.d/00-health_check.conf; 71 | include modules.d/00-restrictions.conf; 72 | 73 | location = / { 74 | return 301 https://$host/icinga; 75 | } 76 | 77 | location /icinga { 78 | log_not_found off; 79 | access_log /dev/stdout; 80 | error_log off; 81 | 82 | add_header X-Backend "icingaweb2"; 83 | 84 | proxy_pass http://icingaweb2; 85 | 86 | proxy_set_header Host $host; 87 | proxy_set_header X-Real-IP $remote_addr; 88 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 89 | proxy_set_header X-Forwarded-Proto $scheme; 90 | } 91 | 92 | location /cert-service { 93 | log_not_found off; 94 | access_log /dev/stdout; 95 | error_log /dev/stdout; 96 | 97 | add_header X-Backend "icinga-cert-service"; 98 | 99 | proxy_pass http://icinga2-master:8080/; 100 | 101 | proxy_set_header Host $host; 102 | proxy_set_header X-Real-IP $remote_addr; 103 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 104 | proxy_set_header X-Forwarded-Proto $scheme; 105 | } 106 | 107 | location /grafana/ { 108 | 109 | log_not_found off; 110 | access_log off; 111 | error_log off; 112 | 113 | add_header X-Backend "grafana"; 114 | 115 | proxy_pass http://grafana:3000/; 116 | 117 | proxy_set_header Host $host; 118 | proxy_set_header X-Real-IP $remote_addr; 119 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 120 | proxy_set_header X-Forwarded-Proto $scheme; 121 | } 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /compose/database.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | database: 7 | image: bodsch/docker-mariadb 8 | container_name: database 9 | hostname: database 10 | environment: 11 | - MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD} 12 | networks: 13 | - backend 14 | - database 15 | -------------------------------------------------------------------------------- /compose/grafana.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | grafana: 6 | image: bodsch/docker-grafana 7 | restart: always 8 | container_name: grafana 9 | hostname: grafana 10 | ports: 11 | - 3000:3000 12 | environment: 13 | - URL_PATH 14 | - LOG_LEVEL 15 | - ROUTER_LOGGING 16 | volumes: 17 | - ${PWD}/import/provisioning:/etc/grafana/provisioning:ro 18 | - ${PWD}/import/dashboards:/var/lib/grafana/dashboards:ro 19 | links: 20 | - influxdb 21 | depends_on: 22 | - influxdb 23 | networks: 24 | - frontend 25 | - backend 26 | - database 27 | -------------------------------------------------------------------------------- /compose/graphite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | graphite: 7 | restart: always 8 | image: bodsch/docker-graphite:1.1.5 9 | container_name: graphite 10 | hostname: graphite 11 | networks: 12 | - backend 13 | -------------------------------------------------------------------------------- /compose/head.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | networks: 5 | frontend: 6 | backend: 7 | database: 8 | satellite: 9 | -------------------------------------------------------------------------------- /compose/icingaweb2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | # icingaweb2 6 | # 7 | icingaweb2: 8 | build: 9 | context: .. 10 | dockerfile: Dockerfile 11 | args: 12 | - BUILD_TYPE=${BUILD_TYPE} 13 | - ICINGAWEB_VERSION=${ICINGAWEB_VERSION} 14 | - INSTALL_THEMES=${INSTALL_THEMES} 15 | - INSTALL_MODULES=${INSTALL_MODULES} 16 | container_name: icingaweb2 17 | hostname: icingaweb2.matrix.lan 18 | ports: 19 | - 80 20 | environment: 21 | - MYSQL_HOST 22 | - MYSQL_ROOT_USER=root 23 | - MYSQL_ROOT_PASS=${MARIADB_ROOT_PASSWORD} 24 | # 25 | - IDO_DATABASE_NAME=icinga2core 26 | - IDO_PASSWORD=${IDO_PASSWORD} 27 | # 28 | - ICINGA2_MASTER=icinga2-master.matrix.lan 29 | - ICINGA2_CMD_API_USER 30 | - ICINGA2_CMD_API_PASS 31 | # 32 | - ICINGAWEB2_USERS=icinga:icinga,foo:bar 33 | - ICINGAWEB_DIRECTOR 34 | # 35 | - GRAPHITE_HOST=graphite 36 | # 37 | - GRAFANA_HOST # This is for swarm, url is: stackname_servicename 38 | - GRAFANA_PORT 39 | - GRAFANA_AUTHENTICATION 40 | - GRAFANA_TOKEN 41 | - GRAFANA_ENABLE_LINK 42 | - GRAFANA_SHOW_DEBUG 43 | - GRAFANA_PUBLIC 44 | - GRAFANA_PUBLIC_HOST 45 | - GRAFANA_PUBLIC_PROTOCOL 46 | - GRAFANA_THEME 47 | env_file: 48 | - ${PWD}/.env 49 | links: 50 | - icinga2-master:icinga2-master.matrix.lan 51 | - database 52 | - grafana 53 | networks: 54 | - database 55 | - frontend 56 | - backend 57 | -------------------------------------------------------------------------------- /compose/influxdb.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | influxdb: 6 | restart: always 7 | image: influxdb:1.7-alpine 8 | container_name: influxdb 9 | hostname: influxdb 10 | ports: 11 | - 8086 12 | environment: 13 | - INFLUXDB_DB 14 | - INFLUXDB_HTTP_AUTH_ENABLED 15 | - INFLUXDB_ADMIN_USER 16 | - INFLUXDB_ADMIN_PASSWORD 17 | - INFLUXDB_USER 18 | - INFLUXDB_USER_PASSWORD 19 | networks: 20 | - backend 21 | -------------------------------------------------------------------------------- /compose/master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | # the Icinga2 Master 6 | # includes a certificate service to create and provide a icinga certificate 7 | icinga2-master: 8 | image: bodsch/docker-icinga2:2.10.5-master 9 | container_name: icinga2-master 10 | hostname: icinga2-master.matrix.lan 11 | restart: always 12 | privileged: false 13 | ports: 14 | - 5665:5665 15 | - 8080:8080 16 | env_file: 17 | - ${PWD}/.env 18 | volumes: 19 | - /etc/localtime:/etc/localtime:ro 20 | depends_on: 21 | - database 22 | - influxdb 23 | links: 24 | - database 25 | - influxdb 26 | networks: 27 | - database 28 | - backend 29 | 30 | -------------------------------------------------------------------------------- /compose/nginx.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | nginx: 6 | restart: always 7 | image: bodsch/docker-nginx 8 | container_name: nginx 9 | hostname: nginx 10 | ports: 11 | - 80:80 12 | - 443:443 13 | depends_on: 14 | - icinga2-master 15 | - icingaweb2 16 | links: 17 | - icinga2-master 18 | - icingaweb2:icingaweb2.matrix.lan 19 | volumes: 20 | - ./ssl/cert.pem:/etc/nginx/secure/localhost/cert.pem:ro 21 | - ./ssl/key.pem:/etc/nginx/secure/localhost/key.pem:ro 22 | - ./ssl/dh.pem:/etc/nginx/secure/localhost/dh.pem:ro 23 | - ./config/nginx.conf:/etc/nginx/nginx.conf:ro 24 | networks: 25 | - frontend 26 | - backend 27 | -------------------------------------------------------------------------------- /compose/satellite.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | icinga2-satellite-1: 7 | image: bodsch/docker-icinga2:2.10.5-satellite 8 | container_name: icinga2-satellite-1 9 | hostname: icinga2-satellite-1.matrix.lan 10 | restart: always 11 | privileged: true 12 | environment: 13 | - DEBUG=0 14 | - ICINGA2_MASTER 15 | - ICINGA2_PARENT 16 | - CERT_SERVICE_BA_USER 17 | - CERT_SERVICE_BA_PASSWORD 18 | - CERT_SERVICE_API_USER 19 | - CERT_SERVICE_API_PASSWORD 20 | - CERT_SERVICE_SERVER 21 | - CERT_SERVICE_PORT 22 | - CERT_SERVICE_PATH 23 | volumes: 24 | - /proc:/host/proc:ro 25 | - /sys:/host/sys:ro 26 | - /sys:/sys:ro 27 | - /dev:/dev:ro 28 | links: 29 | - icinga2-master:icinga2-master.matrix.lan 30 | networks: 31 | - backend 32 | - satellite 33 | 34 | # icinga2-satellite-2: 35 | # image: bodsch/docker-icinga2:2.10.4-satellite 36 | # container_name: icinga2-satellite-2 37 | # hostname: icinga2-satellite-2.matrix.lan 38 | # restart: always 39 | # privileged: true 40 | # environment: 41 | # - DEBUG=0 42 | # - ICINGA2_MASTER=icinga2-master.matrix.lan 43 | # - ICINGA2_PARENT=icinga2-master.matrix.lan 44 | # - CERT_SERVICE_BA_USER=admin 45 | # - CERT_SERVICE_BA_PASSWORD=admin 46 | # - CERT_SERVICE_API_USER=root 47 | # - CERT_SERVICE_API_PASSWORD=icinga 48 | # - CERT_SERVICE_SERVER=nginx 49 | # - CERT_SERVICE_PORT=443 50 | # - CERT_SERVICE_PATH=/cert-service/ 51 | # volumes: 52 | # - ../import:/import:ro 53 | # - /proc:/host/proc:ro 54 | # - /sys:/host/sys:ro 55 | # - /sys:/sys:ro 56 | # - /dev:/dev:ro 57 | # links: 58 | # - icinga2-master:icinga2-master.matrix.lan 59 | # networks: 60 | # - backend 61 | # - satellite 62 | # 63 | -------------------------------------------------------------------------------- /compose/ssl/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDozCCAougAwIBAgIJALtPIdJ3TvOIMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV 3 | BAYTAkRFMRAwDgYDVQQIDAdIYW1idXJnMRAwDgYDVQQHDAdIYW1idXJnMSEwHwYD 4 | VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9z 5 | dDAeFw0xODA4MjAwODM2MjhaFw0xOTA4MjAwODM2MjhaMGgxCzAJBgNVBAYTAkRF 6 | MRAwDgYDVQQIDAdIYW1idXJnMRAwDgYDVQQHDAdIYW1idXJnMSEwHwYDVQQKDBhJ 7 | bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIw 8 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBQyX42gJDn3HK0grRW10fYhbKb 9 | y5rJRVizrXGQXDU+oQEKBH1tMnQdyYbHD0PKzdzTU4SUnlGXRfr7MOWISZ1H8tjQ 10 | EYg/JI/MWBPUnI4kFtHAdjSi91MnrEjmS4I4eBJnJYqN/07oiwmpzmqrBTDQ1ZbF 11 | 17+jSFfK7ZHLbHs9HuPFA2Ws3atxH9OMjH6gK0ORbnO7dbyXfHWWTmrHg21pgLTH 12 | 4jlBlzJSwXQ8+6oPwD3Bl9uDPTvpTKrJ0jEC+8GMosU7uCVO88lK61zVWWdYSWDi 13 | /GAhqbJBsHbejiS0g2KWKSf6Ed/c3bIHVcTB3q9kDR3y3/hS8NBh22PDEF8CAwEA 14 | AaNQME4wHQYDVR0OBBYEFPS5vhkV8xAmlwYIiw7i8ebwHOjgMB8GA1UdIwQYMBaA 15 | FPS5vhkV8xAmlwYIiw7i8ebwHOjgMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL 16 | BQADggEBAGsyObFBllTtdHqOf9Y4XiZr4E/dh39ET8Kdb4LSdPiOdtG3Y4gFhsD2 17 | 1c/cjYoc8jQhI7W5ukqRVlIlsVPimvqo0WJK2MJrooyI4kj2Y0AueA2ArGVaoSOr 18 | RUMUwNH99P5kGuJjyMHpbh1LYCMdFzREW1rFOU0ieAW8ujv35wZxLMuigrljvgND 19 | 9z35D0OTWUeO42kD7FovJqa8zRhh4OHsJNs327WGbrDHvkIaj4vvQiT7ijOeHg9o 20 | HlX8kXhBwNoGlhPTxZOFzLS7Q5TFuaSpNDyTkJf67+r9QodC7kR+Q6CqXFUhGqRx 21 | vPFpVE0qj5p6P2xYqjw6jmXPF1/JWMQ= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /compose/ssl/dh.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEAzEY5vhK7YfazPE8PFvmfSJeee0Ea0VWHXQVUFlB356nS+k6j7C9h 3 | AfTpdkStz7BvRbYmAuCboDehmITmwyRL88Cady1BSi3U0Ki/OT5AgCc7lVuHcjHr 4 | fEesLNmGzcVDj0a82yXHL+iIjG4JiCMOKaHD0cuTX3wiONi7yJCc/b5ANGzT9pYV 5 | 5XWa1WwU4qDwBhoZOeJB2CEjWtV4n2F0AyP+pqNxCLOHoiZ7DIcjaQ6QymT8TX/q 6 | lsbLcjHYRfme1gjCZ8/Fnsn8F9ha7pd1JwKKb6Jsp1IjARz3eQgS6rrMQgMAXsv4 7 | qNOZQ07lINe1vyZ3yo3vsjcYX4NAXGy7ewIBAg== 8 | -----END DH PARAMETERS----- 9 | -------------------------------------------------------------------------------- /compose/ssl/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAUMl+NoCQ59xy 3 | tIK0VtdH2IWym8uayUVYs61xkFw1PqEBCgR9bTJ0HcmGxw9Dys3c01OElJ5Rl0X6 4 | +zDliEmdR/LY0BGIPySPzFgT1JyOJBbRwHY0ovdTJ6xI5kuCOHgSZyWKjf9O6IsJ 5 | qc5qqwUw0NWWxde/o0hXyu2Ry2x7PR7jxQNlrN2rcR/TjIx+oCtDkW5zu3W8l3x1 6 | lk5qx4NtaYC0x+I5QZcyUsF0PPuqD8A9wZfbgz076UyqydIxAvvBjKLFO7glTvPJ 7 | Sutc1VlnWElg4vxgIamyQbB23o4ktINilikn+hHf3N2yB1XEwd6vZA0d8t/4UvDQ 8 | YdtjwxBfAgMBAAECggEALoIbCFvT4bdA17iRt10c+PIC+zu0FH3COH5TXphjxDie 9 | JSswBMkon24os2Bmb6WW/WVZ2EE8vEySDu06WPgJnXCt6QMAimuCwwfO8RTEu5c8 10 | sYMS0w3qNADvKD4RWq+fUgwBxy0p5gJUxYR8N82eFr0aOjkkQOMS9rBLnauNU4v8 11 | FhzsmjWXuhwZklxmJS6t6byUVCSthVrWDFx9jndg76P9EtTo+jSMevPyn/v7jQoF 12 | EPFAp0isObLOwUFeHcy4SaYhVh1op7qHymT3k3AlVczuqbJRUhFtjbUWFCQqJJoG 13 | fZRpzAVGKhXjTxlqGDqU6qUzTosVr2pKAoQfe0AA0QKBgQDjyUlHGParP36JJnvr 14 | +M2CiBaPopXa6SdoW5Z4+LtRMk7J3xTlgYfwb/YtFnD2lQTtm4qSgu8aUHeBxJ+e 15 | 8eFBZOTcjwqiZf4H7WiWYp5lN0bdjzhhzCnmc7Xf+4NmUrNWxEBscc0XH7EkbWKv 16 | 4XtlyjuneHBzTPsU+GKhtq3DeQKBgQDYIskYG6MvwuYj461D5TCRXoPE8fwVESqq 17 | PDvbiSFp/SDwAEsdKoMX8omWSiVRaxO8u0dCt3Prk1D2p69rY8jGa/5Ru4ShCzJ/ 18 | dgwBdna2EPyHUQM3QBvBpJ6FuYXbpjJK2Jkq4WHgMLQ4uiw6eta+VLBBiKem9JQq 19 | RFhrSlXklwKBgBkYL855XZN4J0SMzNIuUtWykGm6i6/WR9UjYexp2pkTZcKvpOmz 20 | 33oJm6FT+5XuzOAwZo/FhPntK31MYBlupFZD+0KhL5a8jcPpz7/hlXmpIVF/WcLM 21 | b0FINh065Dr9mWxRqpdH4kRN5YIR2vFtcd7A7NmCV0Eclfy1cIhIS9RhAoGBAMkS 22 | K3RzGbBwJ7wRrnoweKt0ey+4U2Sh8MgoeyM0gtJge8jq7PY4O3cG2rrnRapl7Bmz 23 | PIszsfLhvPuKamaEkR8PDqyov602hocPogGmXK/qQ5P7aPt4d5oBdLxBKOd7yOPa 24 | dzvuKyjvBmqTwFuzNZ4hmUuOPzHR7RkZNgyyPhAHAoGAGj42xQKsXMuaaEkVv/EA 25 | IiiEh83N42iJLzZ+wIzOtFgZdzMiAJbP6gSJ8wiSTHT6UvUb0esR+CVLF+XT4H/i 26 | iHvoy91UeeG1WhrQPK0GdZzl4QQq5g/X7eK4A++S2SuBopcoXBfhr3xeTuuBYIcK 27 | Csk/hQ5ONXfFHh73GMF8Cok= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /docker-compose_example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3.3' 3 | 4 | services: 5 | 6 | database: 7 | image: bodsch/docker-mariadb 8 | container_name: database 9 | hostname: database 10 | environment: 11 | - MARIADB_SYSTEM_USER=root 12 | - MARIADB_ROOT_PASSWORD=vYUQ14SGVrJRi69PsujC 13 | 14 | graphite: 15 | restart: always 16 | image: bodsch/docker-graphite:1.1.5 17 | container_name: graphite 18 | hostname: graphite 19 | 20 | # the Icinga2 Master 21 | # includes a certificate service to create and provide a icinga certificate 22 | # 23 | icinga2-master: 24 | image: bodsch/docker-icinga2:2.10.2-master 25 | container_name: icinga2-master 26 | hostname: icinga2-master 27 | restart: always 28 | ports: 29 | - 5665:5665 30 | - 8080:8080 31 | environment: 32 | ICINGA2_MASTER: icinga2-master 33 | ICINGA2_API_USERS: root:icinga,dashing:dashing,cert:foo-bar 34 | MYSQL_HOST: database 35 | MYSQL_ROOT_USER: root 36 | MYSQL_ROOT_PASS: vYUQ14SGVrJRi69PsujC 37 | IDO_DATABASE_NAME: icinga2core 38 | IDO_PASSWORD: ido.pass 39 | CARBON_HOST: graphite 40 | links: 41 | - database:database 42 | 43 | # icingaweb2 44 | # 45 | icingaweb2: 46 | build: 47 | context: . 48 | dockerfile: Dockerfile 49 | args: 50 | - BUILD_TYPE=${BUILD_TYPE} 51 | - ICINGAWEB_VERSION=${ICINGAWEB_VERSION} 52 | - INSTALL_THEMES=${INSTALL_THEMES} 53 | - INSTALL_MODULES=${INSTALL_MODULES} 54 | container_name: icingaweb2 55 | hostname: icingaweb2 56 | ports: 57 | - 80:80 58 | environment: 59 | ICINGA2_MASTER: icinga2-master 60 | ICINGA2_CMD_API_USER: root 61 | ICINGA2_CMD_API_PASS: icinga 62 | MYSQL_HOST: database 63 | MYSQL_ROOT_USER: root 64 | MYSQL_ROOT_PASS: vYUQ14SGVrJRi69PsujC 65 | GRAPHITE_HOST: graphite 66 | ICINGAWEB2_USERS: 'icinga:icinga,foo:bar' 67 | IDO_DATABASE_NAME: icinga2core 68 | IDO_PASSWORD: ido.pass 69 | ICINGAWEB_DIRECTOR: ${ICINGAWEB_DIRECTOR} 70 | XDEBUG_ENABLED: ${XDEBUG_ENABLED} 71 | # LDAP: '{ 72 | # "active_directory": "true", 73 | # "server":"${LDAP_SERVER}", 74 | # "port":"${LDAP_PORT}", 75 | # "bind_dn": "${LDAP_BIND_DN}", 76 | # "bind_password": "${LDAP_BIND_PASSWORD}", 77 | # "base_dn": "${LDAP_BASE_DN}", 78 | # "filter": "${LDAP_FILTER}", 79 | # "role": { 80 | # "groups": "${LDAP_GROUP_NAMES}", 81 | # "permissions": "${GROUP_PERMISSIONS}" 82 | # } 83 | # }' 84 | links: 85 | - icinga2-master 86 | - database 87 | - graphite 88 | 89 | -------------------------------------------------------------------------------- /hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | docker build \ 7 | --file Dockerfile \ 8 | --rm \ 9 | --compress \ 10 | --build-arg VCS_REF=${GIT_SHA1} \ 11 | --build-arg BUILD_DATE=${BUILD_DATE} \ 12 | --build-arg BUILD_VERSION=${BUILD_VERSION} \ 13 | --build-arg BUILD_TYPE=${BUILD_TYPE} \ 14 | --build-arg ICINGAWEB_VERSION=${ICINGAWEB_VERSION} \ 15 | --build-arg INSTALL_THEMES=${INSTALL_THEMES} \ 16 | --build-arg INSTALL_MODULES=${INSTALL_MODULES} \ 17 | --tag ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} . 18 | -------------------------------------------------------------------------------- /hooks/clean: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | images=$(docker images -q ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME} | uniq) 7 | 8 | # [[ -z "${images}" ]] && exit 0 9 | 10 | if [[ ! -z "${images}" ]] 11 | then 12 | docker rmi \ 13 | --force ${images} 14 | fi 15 | 16 | pushd build > /dev/null 17 | 18 | [[ -d icingaweb2-modules ]] && rm -rf icingaweb2-modules 19 | [[ -d icingaweb2-themes ]] && rm -rf icingaweb2-themes 20 | 21 | popd > /dev/null 22 | -------------------------------------------------------------------------------- /hooks/compose-file: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | cat << EOF > .env 9 | 10 | BUILD_DATE=${BUILD_DATE} 11 | BUILD_VERSION=${BUILD_VERSION} 12 | 13 | ICINGAWEB_VERSION=${ICINGAWEB_VERSION} 14 | # INSTALL_THEMES=${INSTALL_THEMES} 15 | # INSTALL_MODULES=${INSTALL_MODULES} 16 | 17 | MARIADB_SYSTEM_USER=root 18 | MARIADB_ROOT_PASSWORD=vYUQ14SGVrJRi69PsujC 19 | 20 | MYSQL_HOST=database 21 | 22 | MYSQL_ROOT_PASS=vYUQ14SGVrJRi69PsujC 23 | IDO_PASSWORD=qUVuLTk9oEDUV0A 24 | 25 | # enable director 26 | ICINGAWEB_DIRECTOR=${ICINGAWEB_DIRECTOR:-false} 27 | 28 | XDEBUG_ENABLED=true 29 | 30 | ICINGA2_MASTER=icinga2-master.matrix.lan 31 | ICINGA2_PARENT=icinga2-master.matrix.lan 32 | 33 | ICINGA2_CMD_API_USER=root 34 | ICINGA2_CMD_API_PASS=icinga 35 | 36 | BASIC_AUTH_USER=admin 37 | BASIC_AUTH_PASS=admin 38 | 39 | CERT_SERVICE_BA_USER=admin 40 | CERT_SERVICE_BA_PASSWORD=admin 41 | CERT_SERVICE_API_USER=root 42 | CERT_SERVICE_API_PASSWORD=icinga 43 | CERT_SERVICE_SERVER=nginx 44 | CERT_SERVICE_PORT=443 45 | CERT_SERVICE_PATH=/cert-service/ 46 | 47 | CARBON_HOST= 48 | CARBON_PORT=2003 49 | 50 | DEMO_DATA=false 51 | 52 | # influx 53 | INFLUXDB_DB=icinga2 54 | INFLUXDB_HTTP_AUTH_ENABLED=true 55 | INFLUXDB_ADMIN_USER=admin 56 | INFLUXDB_ADMIN_PASSWORD=hqkBGSQW34iDRpbU 57 | INFLUXDB_USER=icinga2 58 | INFLUXDB_USER_PASSWORD=w7uK6nfcxR6ZBtZC 59 | 60 | # influx integration 61 | INFLUXDB_HOST=influxdb 62 | INFLUXDB_PASS=w7uK6nfcxR6ZBtZC 63 | 64 | 65 | # grafana 66 | URL_PATH=/grafana 67 | LOG_LEVEL=info 68 | ROUTER_LOGGING=false 69 | 70 | GRAFANA_HOST=grafana 71 | GRAFANA_PORT=3000 72 | GRAFANA_AUTHENTICATION=token 73 | GRAFANA_TOKEN= 74 | GRAFANA_ENABLE_LINK=yes 75 | GRAFANA_SHOW_DEBUG=0 76 | GRAFANA_PUBLIC=yes 77 | GRAFANA_PUBLIC_HOST=localhost/grafana 78 | GRAFANA_PUBLIC_PROTOCOL=https 79 | GRAFANA_THEME=light 80 | 81 | GRAFANA_DASHBOARD_UID=icinga2-default 82 | 83 | GRAFANA_PUBLIC_HTTP_PATH=/grafana 84 | 85 | EOF 86 | 87 | docker-compose \ 88 | --file compose/head.yml \ 89 | --file compose/nginx.yml \ 90 | --file compose/grafana.yml \ 91 | --file compose/database.yml \ 92 | --file compose/influxdb.yml \ 93 | --file compose/icingaweb2.yml \ 94 | --file compose/master.yml \ 95 | --file compose/satellite.yml \ 96 | config > docker-compose.yml 97 | -------------------------------------------------------------------------------- /hooks/environment: -------------------------------------------------------------------------------- 1 | 2 | PORTS=" 3 | --publish 80:80" 4 | 5 | VOLUMES="" 6 | 7 | ENV=" 8 | --env URL_PATH="/" \ 9 | --env AUTH_LDAP_SERVER="smb.matrix.lan" \ 10 | --env AUTH_LDAP_PORT="389" \ 11 | --env AUTH_LDAP_USER_CLASS="user" \ 12 | --env AUTH_LDAP_BASE_DN="cn=users,dc=matrix,dc=lan" \ 13 | --env AUTH_LDAP_USER_NAME_ATTRIBUTE="sAMAccountName" \ 14 | --env AUTH_LDAP_FILTER="memberOf=CN=Office,CN=Users,DC=matrix,DC=lan" \ 15 | --env AUTH_LDAP_ROOT_DN="cn=users,dc=matrix,dc=lan" \ 16 | --env AUTH_LDAP_BIND_DN="CN=Administrator,CN=Users,DC=matrix,DC=lan" \ 17 | --env AUTH_LDAP_BIND_PASSWORD="foo"" 18 | -------------------------------------------------------------------------------- /hooks/exec: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | # Custom build for Docker Hub 6 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 7 | 8 | [[ -e hooks/environment ]] && . hooks/environment 9 | 10 | docker exec \ 11 | --interactive \ 12 | --tty \ 13 | ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 14 | /bin/bash 15 | -------------------------------------------------------------------------------- /hooks/github-cache: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | GITHUB_USER=${GITHUB_USER:-bodsch} 7 | WORK_DIR=$(dirname $(readlink --canonicalize "${0}")) 8 | JSON_DIR=$(dirname $(readlink --canonicalize "${0%/*}"))/build 9 | TEMP_DIR=$(mktemp --directory) 10 | 11 | pushd ${TEMP_DIR} 12 | 13 | echo "current directory: ${PWD}" 14 | 15 | default_modules() { 16 | 17 | if [[ -f ${JSON_DIR}/modules.json ]] 18 | then 19 | MODULE_JSON=$(cat ${JSON_DIR}/modules.json) 20 | else 21 | MODULE_JSON='{ 22 | "Icinga/icingaweb2-module-director": {}, 23 | "Icinga/icingaweb2-module-vsphere": { 24 | "enable": false 25 | }, 26 | "Icinga/icingaweb2-module-vspheredb": {}, 27 | "Icinga/icingaweb2-module-graphite": {}, 28 | "Icinga/icingaweb2-module-generictts": {}, 29 | "Icinga/icingaweb2-module-businessprocess": {}, 30 | "Icinga/icingaweb2-module-elasticsearch": {}, 31 | "Icinga/icingaweb2-module-cube": {}, 32 | "Icinga/icingaweb2-module-aws": {}, 33 | "Icinga/icingaweb2-module-fileshipper": {}, 34 | "Icinga/icingaweb2-module-toplevelview": {}, 35 | "Mikesch-mp/icingaweb2-module-grafana.git": {}, 36 | "Mikesch-mp/icingaweb2-module-globe": {}, 37 | "Thomas-Gelf/icingaweb2-module-reporting": {}, 38 | "nbuchwitz/icingaweb2-module-map": {}, 39 | "morgajel/icingaweb2-module-boxydash": {} 40 | }' 41 | fi 42 | 43 | } 44 | 45 | # check github rate limits 46 | # we consume for each REST API call a credit 47 | # 48 | github_ratelimit() { 49 | 50 | local -n VAR=$1 51 | 52 | curl_opts= 53 | [[ -z ${GITHUB_OAUTH_TOKEN} ]] || curl_opts="--user ${GITHUB_USER}:${GITHUB_OAUTH_TOKEN}" 54 | 55 | remaining=$(curl \ 56 | --silent \ 57 | --include \ 58 | ${curl_opts} \ 59 | "https://api.github.com/users/${GITHUB_USER}" | grep "X-RateLimit-Remaining: " | awk -F 'X-RateLimit-Remaining: ' '{print $2}') 60 | 61 | echo "RateLimit Remaining: ${remaining}" 62 | 63 | VAR=${remaining} 64 | } 65 | 66 | 67 | check_downloads() { 68 | 69 | cd cache 70 | 71 | for file in $(ls -1 github_*.json) 72 | do 73 | published_at=$(jq --raw-output ".published_at" ${file}) 74 | project_name=$(jq --raw-output ".project_name" ${file}) 75 | project_maintainer=$(jq --raw-output ".project_maintainer" ${file}) 76 | author=$(jq --raw-output ".author.login" ${file}) 77 | version=$(jq --raw-output ".tag_name" ${file}) 78 | url=$(jq --raw-output ".tarball_url" ${file}) 79 | enable=$(jq --raw-output ".enable" ${file}) 80 | use_git=$(jq --raw-output ".use_git" ${file}) 81 | destination=$(jq --raw-output ".destination" ${file}) 82 | 83 | if [[ ${published_at} != null ]] 84 | then 85 | if [[ -e /etc/alpine-release ]] 86 | then 87 | release_date=$(date -d @$(date -u -D %Y-%m-%dT%TZ -d "${published_at}" +%s) +%d.%m.%Y) 88 | else 89 | release_date=$(date -d ${published_at} +%d.%m.%Y) 90 | fi 91 | 92 | release="released at ${release_date}" 93 | 94 | if [[ "${use_git}" == "true" ]] 95 | then 96 | release="${release} but use git" 97 | fi 98 | 99 | else 100 | version="" 101 | release="never released, use git" 102 | fi 103 | 104 | echo " - ${project_maintainer} :: ${project_name} ${version} (${release})" 105 | done 106 | 107 | cd .. 108 | } 109 | 110 | 111 | download_modules() { 112 | 113 | echo " - get latest published versions" 114 | 115 | [[ -d cache ]] || mkdir -p cache 116 | 117 | #current_time=$(date +%s) 118 | 119 | for k in $(echo ${MODULE_JSON} | jq --raw-output '. | to_entries | .[] | .key') 120 | do 121 | enable="$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].enable")" 122 | ignore=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].ignore") 123 | use_git="$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].use_git")" 124 | tarball_url=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].tarball_url") 125 | destination=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].destination") 126 | 127 | [[ "${enable}" == null ]] && enable=true 128 | [[ "${ignore}" == null ]] && ignore=false 129 | [[ "${use_git}" == null ]] && use_git=false 130 | [[ "${tarball_url}" == null ]] && tarball_url='' 131 | [[ "${destination}" == null ]] && destination= 132 | 133 | if [[ ${ignore} == true ]] 134 | then 135 | continue 136 | fi 137 | 138 | project="$(echo "${k}" | sed -e 's|\.git||g' -e 's/https\?:\/\///' -e 's|github.com/||g')" 139 | project_maintainer="$(echo "${project}" | cut -d "/" -f1)" 140 | project_name="$(echo "${project}" | cut -d "/" -f2 | sed -e 's|icingaweb2-module-||g')" 141 | outfile=$(echo "${project}" | tr [:upper:] [:lower:] | sed -e 's|/|_|g') 142 | 143 | #if [[ -f "cache/github_${outfile}.json" ]] 144 | #then 145 | # file_time=$(stat -c '%Y' "/build/cache/github_${outfile}.json") 146 | # 147 | # echo "${file_time}" 148 | # 149 | # if (( file_time < ( current_time - ( 60 * 60 * 24 * 10 ) ) )); then 150 | # echo "cached file for github_${outfile}.json is older than 10 days" 151 | # else 152 | # echo "use cached file" 153 | # cp -v cache/github_${outfile}.json /tmp/ 154 | # fi 155 | #else 156 | # echo "no cache" 157 | #fi 158 | 159 | curl_opts= 160 | [[ -z ${GITHUB_OAUTH_TOKEN} ]] || curl_opts="--user ${GITHUB_USER}:${GITHUB_OAUTH_TOKEN}" 161 | 162 | # download project releated release file from github 163 | # 164 | # when ${http_code} == 404 then this module is not released yet! 165 | # 166 | if [[ ! -f "cache/github_${outfile}.json" ]] 167 | then 168 | echo "https://api.github.com/repos/${project}/releases/latest" 169 | 170 | code=$(curl \ 171 | ${curl_opts} \ 172 | --silent \ 173 | --header 'Accept: application/vnd.github.v3.full+json' \ 174 | --write-out "%{http_code}\n" \ 175 | --out "cache/github_${outfile}.json" \ 176 | https://api.github.com/repos/${project}/releases/latest) 177 | fi 178 | set -x 179 | # remove some unneeded parts 180 | # and add our things 181 | # 182 | if [[ -f "cache/github_${outfile}.json" ]] && [[ $(stat -c %s cache/github_${outfile}.json) -gt 0 ]] 183 | then 184 | cat "cache/github_${outfile}.json" | \ 185 | jq 'del(.author) | del(.body_html) | del(.body_text) | del(.body) | del(.assets)' | \ 186 | jq ". |= .+ {\"enable\": \"${enable}\", \"use_git\": \"${use_git}\", \"project_maintainer\": \"${project_maintainer}\", \"project_name\": \"${project_name}\" }" > cache/github_${outfile}.json_TMP 187 | 188 | if [[ ! -z ${destination} ]] 189 | then 190 | cat "cache/github_${outfile}.json_TMP" | \ 191 | jq ". |= .+ {\"destination\": \"${destination}\" }" > cache/github_${outfile}.json_TMP2 192 | 193 | mv cache/github_${outfile}.json_TMP2 cache/github_${outfile}.json_TMP 194 | fi 195 | set +x 196 | mv cache/github_${outfile}.json_TMP cache/github_${outfile}.json 197 | fi 198 | 199 | cat cache/github_${outfile}.json 200 | done 201 | 202 | check_downloads 203 | 204 | tar -czf cache.tgz cache 205 | } 206 | 207 | 208 | github_ratelimit remaining 209 | 210 | remaining="${remaining/$'\r'/}" 211 | 212 | if [[ "${remaining}" -gt 20 ]] 213 | then 214 | default_modules 215 | download_modules 216 | 217 | if [[ -f cache.tgz ]] 218 | then 219 | cp -v cache.tgz ${JSON_DIR}/ 220 | fi 221 | else 222 | echo "sorry, API rate limit fot github exceeded. (only ${remaining} left)" 223 | fi 224 | 225 | popd 226 | 227 | rm -rfv ${TEMP_DIR} 228 | -------------------------------------------------------------------------------- /hooks/offline_modules: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | GITHUB_USER=${GITHUB_USER:-bodsch} 6 | WORK_DIR=$(dirname $(readlink --canonicalize "${0}")) 7 | JSON_DIR=$(dirname $(readlink --canonicalize "${0%/*}"))/build 8 | TEMP_DIR=$(mktemp --directory) 9 | 10 | pushd ${TEMP_DIR} > /dev/null 11 | 12 | echo "current directory: ${PWD}" 13 | echo "json directory : ${JSON_DIR}" 14 | 15 | # check github rate limits 16 | # we consume for each REST API call a credit 17 | # 18 | github_ratelimit() { 19 | 20 | local -n VAR=$1 21 | 22 | curl_opts= 23 | [[ -z ${GITHUB_OAUTH_TOKEN} ]] || curl_opts="--user ${GITHUB_USER}:${GITHUB_OAUTH_TOKEN}" 24 | 25 | remaining=$(curl \ 26 | --silent \ 27 | --include \ 28 | ${curl_opts} \ 29 | "https://api.github.com/users/${GITHUB_USER}" | grep "X-RateLimit-Remaining: " | awk -F 'X-RateLimit-Remaining: ' '{print $2}') 30 | 31 | echo "RateLimit Remaining: ${remaining}" 32 | 33 | VAR=${remaining} 34 | } 35 | 36 | 37 | default_modules() { 38 | 39 | if [[ -f ${JSON_DIR}/modules.json ]] 40 | then 41 | MODULE_JSON=$(cat ${JSON_DIR}/modules.json) 42 | else 43 | MODULE_JSON='{ 44 | "Icinga/icingaweb2-module-director": {}, 45 | "Icinga/icingaweb2-module-vsphere": { 46 | "enable": false 47 | }, 48 | "Icinga/icingaweb2-module-vspheredb": {}, 49 | "Icinga/icingaweb2-module-graphite": {}, 50 | "Icinga/icingaweb2-module-generictts": {}, 51 | "Icinga/icingaweb2-module-businessprocess": {}, 52 | "Icinga/icingaweb2-module-elasticsearch": {}, 53 | "Icinga/icingaweb2-module-cube": {}, 54 | "Icinga/icingaweb2-module-aws": {}, 55 | "Icinga/icingaweb2-module-fileshipper": {}, 56 | "Icinga/icingaweb2-module-toplevelview": {}, 57 | "Mikesch-mp/icingaweb2-module-grafana.git": {}, 58 | "Mikesch-mp/icingaweb2-module-globe": {}, 59 | "Thomas-Gelf/icingaweb2-module-reporting": {}, 60 | "nbuchwitz/icingaweb2-module-map": {}, 61 | "morgajel/icingaweb2-module-boxydash": {} 62 | }' 63 | fi 64 | 65 | } 66 | 67 | 68 | module_informations() { 69 | 70 | pushd cache > /dev/null 71 | 72 | for file in $(ls -1 github_*.json) 73 | do 74 | published_at=$(jq --raw-output ".published_at" ${file}) 75 | project_name=$(jq --raw-output ".project_name" ${file}) 76 | project_maintainer=$(jq --raw-output ".project_maintainer" ${file}) 77 | author=$(jq --raw-output ".author.login" ${file}) 78 | version=$(jq --raw-output ".tag_name" ${file}) 79 | url=$(jq --raw-output ".tarball_url" ${file}) 80 | enable=$(jq --raw-output ".enable" ${file}) 81 | use_git=$(jq --raw-output ".use_git" ${file}) 82 | destination=$(jq --raw-output ".destination" ${file}) 83 | 84 | if [[ ${published_at} != null ]] 85 | then 86 | if [[ -e /etc/alpine-release ]] 87 | then 88 | release_date=$(date -d @$(date -u -D %Y-%m-%dT%TZ -d "${published_at}" +%s) +%d.%m.%Y) 89 | else 90 | release_date=$(date -d ${published_at} +%d.%m.%Y) 91 | fi 92 | 93 | release="released at ${release_date}" 94 | 95 | if [[ "${use_git}" == "true" ]] 96 | then 97 | release="${release} but use git" 98 | fi 99 | 100 | else 101 | version="" 102 | release="never released, use git" 103 | fi 104 | 105 | echo " - ${project_maintainer} :: ${project_name} ${version} (${release})" 106 | done 107 | 108 | popd > /dev/null 109 | } 110 | 111 | 112 | build_cache() { 113 | 114 | echo " get latest published versions:" 115 | 116 | if [[ -d "${JSON_DIR}/icingaweb2-modules/cache" ]] 117 | then 118 | cp -ar "${JSON_DIR}/icingaweb2-modules/cache" . 119 | fi 120 | 121 | [[ -d cache ]] || mkdir -p cache 122 | 123 | #current_time=$(date +%s) 124 | 125 | for k in $(echo ${MODULE_JSON} | jq --raw-output '. | to_entries | .[] | .key') 126 | do 127 | enable="$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].enable")" 128 | ignore=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].ignore") 129 | use_git="$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].use_git")" 130 | tarball_url=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].tarball_url") 131 | destination=$(echo "${MODULE_JSON}" | jq --raw-output ".[\"$k\"].destination") 132 | 133 | [[ "${enable}" == null ]] && enable=true 134 | [[ "${ignore}" == null ]] && ignore=false 135 | [[ "${use_git}" == null ]] && use_git=false 136 | [[ "${tarball_url}" == null ]] && tarball_url='' 137 | [[ "${destination}" == null ]] && destination= 138 | 139 | if [[ ${ignore} == true ]] 140 | then 141 | continue 142 | fi 143 | 144 | project="$(echo "${k}" | sed -e 's|\.git||g' -e 's/https\?:\/\///' -e 's|github.com/||g')" 145 | project_maintainer="$(echo "${project}" | cut -d "/" -f1)" 146 | project_name="$(echo "${project}" | cut -d "/" -f2 | sed -e 's|icingaweb2-module-||g')" 147 | outfile=$(echo "${project}" | tr [:upper:] [:lower:] | sed -e 's|/|_|g') 148 | 149 | #if [[ -f "cache/github_${outfile}.json" ]] 150 | #then 151 | # file_time=$(stat -c '%Y' "/build/cache/github_${outfile}.json") 152 | # 153 | # echo "${file_time}" 154 | # 155 | # if (( file_time < ( current_time - ( 60 * 60 * 24 * 10 ) ) )); then 156 | # echo "cached file for github_${outfile}.json is older than 10 days" 157 | # else 158 | # echo "use cached file" 159 | # cp -v cache/github_${outfile}.json /tmp/ 160 | # fi 161 | #else 162 | # echo "no cache" 163 | #fi 164 | 165 | curl_opts= 166 | [[ -z ${GITHUB_OAUTH_TOKEN} ]] || curl_opts="--user ${GITHUB_USER}:${GITHUB_OAUTH_TOKEN}" 167 | 168 | # download project releated release file from github 169 | # 170 | # when ${http_code} == 404 then this module is not released yet! 171 | # 172 | if [[ ! -f "cache/github_${outfile}.json" ]] 173 | then 174 | # echo "https://api.github.com/repos/${project}/releases/latest" 175 | 176 | code=$(curl \ 177 | ${curl_opts} \ 178 | --silent \ 179 | --header 'Accept: application/vnd.github.v3.full+json' \ 180 | --write-out "%{http_code}\n" \ 181 | --out "cache/github_${outfile}.json" \ 182 | https://api.github.com/repos/${project}/releases/latest) 183 | fi 184 | 185 | # remove some unneeded parts 186 | # and add our things 187 | # 188 | if [[ -f "cache/github_${outfile}.json" ]] && [[ $(stat -c %s cache/github_${outfile}.json) -gt 0 ]] 189 | then 190 | cat "cache/github_${outfile}.json" | \ 191 | jq 'del(.author) | del(.body_html) | del(.body_text) | del(.body) | del(.assets)' | \ 192 | jq ". |= .+ {\"enable\": \"${enable}\", \"use_git\": \"${use_git}\", \"project_maintainer\": \"${project_maintainer}\", \"project_name\": \"${project_name}\" }" > cache/github_${outfile}.json_TMP 193 | 194 | if [[ ! -z ${destination} ]] 195 | then 196 | cat "cache/github_${outfile}.json_TMP" | \ 197 | jq ". |= .+ {\"destination\": \"${destination}\" }" > cache/github_${outfile}.json_TMP2 198 | 199 | mv cache/github_${outfile}.json_TMP2 cache/github_${outfile}.json_TMP 200 | fi 201 | 202 | mv cache/github_${outfile}.json_TMP cache/github_${outfile}.json 203 | fi 204 | 205 | # cat cache/github_${outfile}.json 206 | done 207 | 208 | # save the cache 209 | # if [[ ! -d "${JSON_DIR}/icingaweb2-modules/cache" ]] 210 | # then 211 | cp -ar cache "${JSON_DIR}/icingaweb2-modules/" 212 | # fi 213 | } 214 | 215 | 216 | download_modules() { 217 | 218 | [[ -d ${TEMP_DIR}/icingaweb2-modules ]] || mkdir -p ${TEMP_DIR}/icingaweb2-modules 219 | 220 | pushd cache > /dev/null 221 | 222 | echo "" 223 | echo " download modules:" 224 | 225 | for file in $(ls -1 github_*.json) 226 | do 227 | published_at=$(jq --raw-output ".published_at" ${file}) 228 | project_name=$(jq --raw-output ".project_name" ${file}) 229 | project_maintainer=$(jq --raw-output ".project_maintainer" ${file}) 230 | author=$(jq --raw-output ".author.login" ${file}) 231 | version=$(jq --raw-output ".tag_name" ${file}) 232 | url=$(jq --raw-output ".tarball_url" ${file}) 233 | enable=$(jq --raw-output ".enable" ${file}) 234 | use_git=$(jq --raw-output ".use_git" ${file}) 235 | destination=$(jq --raw-output ".destination" ${file}) 236 | 237 | [[ $destination =~ /usr/share/webapps/icingaweb2/modules/ ]] && destination=$(echo "${destination}" | sed "s|/usr/share/webapps/icingaweb2/modules/|${TEMP_DIR}/icingaweb2-modules/|") 238 | [[ "${destination}" == null ]] && destination= 239 | 240 | # echo ${destination} 241 | 242 | # continue 243 | 244 | if [[ ${published_at} != null ]] 245 | then 246 | if [[ -e /etc/alpine-release ]] 247 | then 248 | release_date=$(date -d @$(date -u -D %Y-%m-%dT%TZ -d "${published_at}" +%s) +%d.%m.%Y) 249 | else 250 | release_date=$(date -d ${published_at} +%d.%m.%Y) 251 | fi 252 | 253 | release="released at ${release_date}" 254 | 255 | if [[ "${use_git}" == "true" ]] 256 | then 257 | release="${release} but use git" 258 | fi 259 | 260 | else 261 | version="" 262 | release="never released, use git" 263 | fi 264 | 265 | echo " - ${project_name} ${version} (${release}) (${project_maintainer})" 266 | 267 | if [[ ${url} != null ]] && [[ "${use_git}" = "false" ]] 268 | then 269 | if [[ ! -f "${project_name}.tgz" ]] 270 | then 271 | curl \ 272 | --silent \ 273 | --location \ 274 | --retry 3 \ 275 | --output "${project_name}.tgz" \ 276 | ${url} 277 | fi 278 | 279 | if [[ -f "${project_name}.tgz" ]] 280 | then 281 | # [[ -d ${MODULE_DIRECTORY} ]] || continue 282 | 283 | tar -xzf ${project_name}.tgz 284 | 285 | if [[ ! -z ${destination} ]] 286 | then 287 | [[ -d ${destination} ]] || mkdir -p ${destination} 288 | 289 | find . -mindepth 1 -maxdepth 1 -type d -name "*${project_name}*" -exec mv {} ${project_name} 2> /dev/null \; 290 | mv ${project_name}/* ${destination}/ 291 | rm -f ${project_name}.tgz 292 | else 293 | find . -mindepth 1 -maxdepth 1 -type d -name "*${project_name}*" -exec mv {} ${TEMP_DIR}/icingaweb2-modules/${project_name} \; 294 | 295 | #rm -f ${project_name}.tgz 296 | #mkdir /etc/icingaweb2/modules/${project_name} 297 | fi 298 | fi 299 | 300 | else 301 | 302 | [[ -d icingaweb2-module-${project_name} ]] && rm -rf icingaweb2-module-${project_name} 303 | 304 | git clone \ 305 | --quiet \ 306 | https://github.com/${project_maintainer}/icingaweb2-module-${project_name} > /dev/null 307 | 308 | #[[ -d ${MODULE_DIRECTORY} ]] || continue 309 | 310 | # install PHP dependency 311 | # 312 | if [[ -e "icingaweb2-module-${project_name}/composer.json" ]] 313 | then 314 | # echo "found composer.json" 315 | pushd icingaweb2-module-${project_name} > /dev/null 316 | 317 | set +e 318 | composer=$(command -v composer) 319 | 320 | [[ -z "${composer}" ]] || ${composer} install > /dev/null 2> /dev/null 321 | set -e 322 | popd > /dev/null 323 | fi 324 | 325 | mv icingaweb2-module-${project_name} ${TEMP_DIR}/icingaweb2-modules/${project_name} 326 | fi 327 | 328 | #if [[ "${enable}" = "true" ]] && [[ -d ${TEMP_DIR}/icingaweb2-modules/${project_name} ]] 329 | #then 330 | # /usr/bin/icingacli module enable ${project_name} 2> /dev/null 331 | #fi 332 | 333 | done 334 | 335 | find ${TEMP_DIR}/icingaweb2-modules -name ".git*" -exec rm -rf {} 2> /dev/null \; || true 336 | 337 | popd > /dev/null 338 | } 339 | 340 | 341 | github_ratelimit remaining 342 | 343 | remaining="${remaining/$'\r'/}" 344 | 345 | if [[ "${remaining}" -gt 20 ]] 346 | then 347 | default_modules 348 | build_cache 349 | module_informations 350 | 351 | download_modules 352 | 353 | find ${TEMP_DIR}/icingaweb2-modules -type f -name "*.md" -delete 354 | find ${TEMP_DIR}/icingaweb2-modules -type d -name "doc" -exec rm -rf {} 2> /dev/null \; || true 355 | 356 | rsync \ 357 | -ar \ 358 | --exclude ".changes" \ 359 | ${TEMP_DIR}/icingaweb2-modules ${JSON_DIR} 360 | 361 | echo "you can find all offline modules in the directory '${JSON_DIR}/icingaweb2-modules'" 362 | else 363 | echo "sorry, API rate limit for github exceeded. (only ${remaining} left)" 364 | 365 | exit 1 366 | fi 367 | 368 | popd > /dev/null 369 | 370 | rm -rf ${TEMP_DIR} 371 | -------------------------------------------------------------------------------- /hooks/offline_themes: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set -e 4 | 5 | GITHUB_USER=${GITHUB_USER:-bodsch} 6 | WORK_DIR=$(dirname $(readlink --canonicalize "${0}")) 7 | JSON_DIR=$(dirname $(readlink --canonicalize "${0%/*}"))/build 8 | TEMP_DIR=$(mktemp --directory) 9 | 10 | # pushd ${TEMP_DIR} > /dev/null 11 | 12 | echo "current directory: ${PWD}" 13 | echo "json directory : ${JSON_DIR}" 14 | 15 | # check github rate limits 16 | # we consume for each REST API call a credit 17 | # 18 | github_ratelimit() { 19 | 20 | local -n VAR=$1 21 | 22 | curl_opts= 23 | [[ -z ${GITHUB_OAUTH_TOKEN} ]] || curl_opts="--user ${GITHUB_USER}:${GITHUB_OAUTH_TOKEN}" 24 | 25 | remaining=$(curl \ 26 | --silent \ 27 | --include \ 28 | ${curl_opts} \ 29 | "https://api.github.com/users/${GITHUB_USER}" | grep "X-RateLimit-Remaining: " | awk -F 'X-RateLimit-Remaining: ' '{print $2}') 30 | 31 | echo "RateLimit Remaining: ${remaining}" 32 | 33 | VAR=${remaining} 34 | } 35 | 36 | 37 | default_themes() { 38 | 39 | if [[ -f ${JSON_DIR}/themes.json ]] 40 | then 41 | THEMES_JSON=$(cat ${JSON_DIR}/themes.json) 42 | else 43 | THEMES_JSON='{ 44 | "Mikesch-mp/icingaweb2-theme-unicorn" : { 45 | "image": [{ 46 | "name": "unicorn.png", 47 | "url": "http://i.imgur.com/SCfMd.png" 48 | }] 49 | }, 50 | "Icinga/icingaweb2-theme-company": {}, 51 | "sysadmama/icingaweb2-theme-nordlicht": {}, 52 | "vita2/icingaweb2-module-theme-dark": {}, 53 | "xam-stephan/icingaweb2-module-theme-always-green": {} 54 | }' 55 | fi 56 | 57 | } 58 | 59 | 60 | download_themes() { 61 | 62 | echo " download themes ..." 63 | 64 | [[ -d ${TEMP_DIR}/icingaweb2-themes ]] || mkdir -p ${TEMP_DIR}/icingaweb2-themes 65 | [[ -d ${TEMP_DIR}/tmp ]] || mkdir -p ${TEMP_DIR}/tmp 66 | 67 | pushd ${TEMP_DIR}/tmp > /dev/null 68 | 69 | for k in $(echo ${THEMES_JSON} | jq -r '. | to_entries | .[] | .key') 70 | do 71 | enable="$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].enable")" 72 | [[ "${enable}" == null ]] && enable=true 73 | 74 | project="$(echo "${k}" | sed -e 's|\.git||g' -e 's/https\?:\/\///' -e 's|github.com/||g')" 75 | project_maintainer="$(echo "${project}" | cut -d "/" -f1)" 76 | project_name="$(echo "${project}" | cut -d "/" -f2 | sed -e 's|icingaweb2-||g' -e 's|module-||g' -e 's|theme-||g' | tr [:upper:] [:lower:])" 77 | outpath=$(echo "${project}" | tr [:upper:] [:lower:] | sed -e 's|/|_|g') 78 | 79 | echo " - ${project_name} (${project_maintainer})" 80 | 81 | [[ -d ${outpath} ]] || mkdir ${outpath} 82 | [[ -d ${TEMP_DIR}/icingaweb2-themes/${project_name} ]] || mkdir ${TEMP_DIR}/icingaweb2-themes/${project_name} 83 | 84 | pushd ${outpath} > /dev/null 85 | 86 | git clone "https://github.com/${k}" 2> /dev/null 87 | 88 | images=$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].image") 89 | 90 | if [[ $images != null ]] 91 | then 92 | data=$(echo "${THEMES_JSON}" | jq -r ".[\"$k\"].image") 93 | 94 | for row in $(echo "${data}" | jq -r '.[] | @base64'); do 95 | _jq() { 96 | echo ${row} | base64 -d | jq -r ${1} 97 | } 98 | 99 | name=$(_jq '.name') 100 | url=$(_jq '.url') 101 | 102 | echo " download external image: ${name}" 103 | 104 | curl \ 105 | --silent \ 106 | --location \ 107 | --retry 3 \ 108 | --output ${name} \ 109 | ${url} 110 | 111 | cp -a ${name} */public/img/ 112 | done 113 | fi 114 | 115 | cp -ar */public ${TEMP_DIR}/icingaweb2-themes/${project_name}/ 116 | 117 | popd > /dev/null 118 | done 119 | 120 | rm -rf ${TEMP_DIR}/tmp 121 | 122 | popd > /dev/null 123 | } 124 | 125 | 126 | github_ratelimit remaining 127 | 128 | remaining="${remaining/$'\r'/}" 129 | 130 | if [[ "${remaining}" -gt 20 ]] 131 | then 132 | default_themes 133 | download_themes 134 | 135 | rsync -ar ${TEMP_DIR}/icingaweb2-themes ${JSON_DIR} 136 | 137 | echo "you can find all offline themes in the directory '${JSON_DIR}/icingaweb2-themes'" 138 | else 139 | echo "sorry, API rate limit for github exceeded. (only ${remaining} left)" 140 | 141 | exit 1 142 | fi 143 | 144 | # popd > /dev/null 145 | 146 | # rm -rfv ${TEMP_DIR} 147 | -------------------------------------------------------------------------------- /hooks/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 11 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | ${PORTS} \ 13 | ${VOLUMES} \ 14 | ${ENV} \ 15 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} 16 | -------------------------------------------------------------------------------- /hooks/shell: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 11 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | --interactive \ 13 | --tty \ 14 | --cap-add=SYS_ADMIN \ 15 | ${PORTS} \ 16 | ${VOLUMES} \ 17 | ${ENV} \ 18 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} \ 19 | /bin/sh 20 | -------------------------------------------------------------------------------- /hooks/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Custom build for Docker Hub 4 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 5 | 6 | [[ -e hooks/environment ]] && . hooks/environment 7 | 8 | docker run \ 9 | --rm \ 10 | --detach \ 11 | --name ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 12 | --hostname ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} \ 13 | ${PORTS} \ 14 | ${VOLUMES} \ 15 | ${ENV} \ 16 | ${DOCKER_NAME_SPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_VERSION} 17 | -------------------------------------------------------------------------------- /hooks/stop: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | # Custom build for Docker Hub 6 | # see: https://medium.com/microscaling-systems/labelling-automated-builds-on-docker-hub-f3d073fb8e1 7 | 8 | [[ -e hooks/environment ]] && . hooks/environment 9 | 10 | docker stop \ 11 | ${DOCKER_NAME_SPACE}-${DOCKER_IMAGE_NAME} 12 | -------------------------------------------------------------------------------- /import/dashboards/icinga2-default.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "description": "Show all metrics from a Icinga2 service or host", 16 | "editable": true, 17 | "gnetId": null, 18 | "graphTooltip": 0, 19 | "id": 1, 20 | "iteration": 1549642691124, 21 | "links": [], 22 | "panels": [ 23 | { 24 | "aliasColors": {}, 25 | "bars": false, 26 | "dashLength": 10, 27 | "dashes": false, 28 | "datasource": "Icinga2", 29 | "fill": 1, 30 | "gridPos": { 31 | "h": 7, 32 | "w": 24, 33 | "x": 0, 34 | "y": 0 35 | }, 36 | "id": 1, 37 | "legend": { 38 | "alignAsTable": false, 39 | "avg": false, 40 | "current": false, 41 | "max": false, 42 | "min": false, 43 | "rightSide": false, 44 | "show": true, 45 | "total": false, 46 | "values": false 47 | }, 48 | "lines": true, 49 | "linewidth": 1, 50 | "links": [], 51 | "nullPointMode": "null", 52 | "percentage": false, 53 | "pointradius": 1, 54 | "points": false, 55 | "renderer": "flot", 56 | "seriesOverrides": [], 57 | "spaceLength": 10, 58 | "stack": false, 59 | "steppedLine": false, 60 | "targets": [ 61 | { 62 | "alias": "$tag_metric", 63 | "dsType": "influxdb", 64 | "groupBy": [ 65 | { 66 | "params": [ 67 | "$__interval" 68 | ], 69 | "type": "time" 70 | }, 71 | { 72 | "params": [ 73 | "metric" 74 | ], 75 | "type": "tag" 76 | }, 77 | { 78 | "params": [ 79 | "none" 80 | ], 81 | "type": "fill" 82 | } 83 | ], 84 | "measurement": "/^$command$/", 85 | "orderByTime": "ASC", 86 | "policy": "default", 87 | "refId": "A", 88 | "resultFormat": "time_series", 89 | "select": [ 90 | [ 91 | { 92 | "params": [ 93 | "value" 94 | ], 95 | "type": "field" 96 | }, 97 | { 98 | "params": [], 99 | "type": "mean" 100 | } 101 | ] 102 | ], 103 | "tags": [ 104 | { 105 | "key": "hostname", 106 | "operator": "=~", 107 | "value": "/^$hostname$/" 108 | }, 109 | { 110 | "condition": "AND", 111 | "key": "service", 112 | "operator": "=~", 113 | "value": "/^$service$/" 114 | } 115 | ] 116 | } 117 | ], 118 | "thresholds": [], 119 | "timeFrom": null, 120 | "timeRegions": [], 121 | "timeShift": null, 122 | "title": "$service", 123 | "tooltip": { 124 | "shared": true, 125 | "sort": 1, 126 | "value_type": "individual" 127 | }, 128 | "type": "graph", 129 | "xaxis": { 130 | "buckets": null, 131 | "mode": "time", 132 | "name": null, 133 | "show": true, 134 | "values": [] 135 | }, 136 | "yaxes": [ 137 | { 138 | "format": "short", 139 | "label": null, 140 | "logBase": 1, 141 | "max": null, 142 | "min": null, 143 | "show": true 144 | }, 145 | { 146 | "format": "short", 147 | "label": null, 148 | "logBase": 1, 149 | "max": null, 150 | "min": null, 151 | "show": false 152 | } 153 | ], 154 | "yaxis": { 155 | "align": false, 156 | "alignLevel": null 157 | } 158 | } 159 | ], 160 | "schemaVersion": 16, 161 | "style": "dark", 162 | "tags": [ 163 | "Icinga2", 164 | "influxdb" 165 | ], 166 | "templating": { 167 | "list": [ 168 | { 169 | "current": { 170 | "text": "null", 171 | "value": "null" 172 | }, 173 | "hide": 2, 174 | "label": null, 175 | "name": "hostname", 176 | "options": [ 177 | { 178 | "text": "null", 179 | "value": "null" 180 | } 181 | ], 182 | "query": "null", 183 | "skipUrlSync": false, 184 | "type": "constant" 185 | }, 186 | { 187 | "current": { 188 | "text": "null", 189 | "value": "null" 190 | }, 191 | "hide": 2, 192 | "label": null, 193 | "name": "service", 194 | "options": [ 195 | { 196 | "text": "null", 197 | "value": "null" 198 | } 199 | ], 200 | "query": "null", 201 | "skipUrlSync": false, 202 | "type": "constant" 203 | }, 204 | { 205 | "current": { 206 | "text": "null", 207 | "value": "null" 208 | }, 209 | "hide": 2, 210 | "label": null, 211 | "name": "command", 212 | "options": [ 213 | { 214 | "text": "null", 215 | "value": "null" 216 | } 217 | ], 218 | "query": "null", 219 | "skipUrlSync": false, 220 | "type": "constant" 221 | } 222 | ] 223 | }, 224 | "time": { 225 | "from": "now-6h", 226 | "to": "now" 227 | }, 228 | "timepicker": { 229 | "refresh_intervals": [ 230 | "5s", 231 | "10s", 232 | "30s", 233 | "1m", 234 | "5m", 235 | "15m", 236 | "30m", 237 | "1h", 238 | "2h", 239 | "1d" 240 | ], 241 | "time_options": [ 242 | "5m", 243 | "15m", 244 | "1h", 245 | "6h", 246 | "12h", 247 | "24h", 248 | "2d", 249 | "7d", 250 | "30d" 251 | ] 252 | }, 253 | "timezone": "", 254 | "title": "icinga2-default", 255 | "uid": "icinga2-default", 256 | "version": 1 257 | } 258 | -------------------------------------------------------------------------------- /import/provisioning/dashboards/dashboards.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: 'default' 5 | orgId: 1 6 | folder: '' 7 | type: file 8 | disableDeletion: false 9 | updateIntervalSeconds: 10 #how often Grafana will scan for changed dashboards 10 | options: 11 | path: /var/lib/grafana/dashboards 12 | -------------------------------------------------------------------------------- /import/provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # list of datasources that should be deleted from the database 5 | deleteDatasources: 6 | - name: Icinga2 7 | orgId: 1 8 | 9 | # list of datasources to insert/update depending 10 | # whats available in the database 11 | ## This is for swarm, url is: stackname_servicename 12 | datasources: 13 | - name: Icinga2 14 | type: influxdb 15 | access: proxy 16 | database: icinga2 17 | user: icinga2 18 | password: w7uK6nfcxR6ZBtZC 19 | url: http://influxdb:8086 20 | editable: true 21 | jsonData: 22 | timeInterval: "15s" 23 | 24 | - name: graphite 25 | type: graphite 26 | isDefault: true 27 | access: proxy 28 | url: http://graphite:8080 29 | editable: true 30 | jsonData: 31 | graphiteVersion: "1.1" 32 | -------------------------------------------------------------------------------- /import/provisioning/notifiers/notifier.yml: -------------------------------------------------------------------------------- 1 | # config file version 2 | apiVersion: 1 3 | 4 | # http://docs.grafana.org/administration/provisioning/#provisioning-grafana 5 | 6 | #delete_notifiers: 7 | # - name: notification-channel-1 8 | # - name: notification-channel-2 9 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/authentication.ini: -------------------------------------------------------------------------------- 1 | 2 | [icingaweb2] 3 | backend = "db" 4 | resource = "icingaweb_db" 5 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/config.ini: -------------------------------------------------------------------------------- 1 | [global] 2 | module_path = "/etc/icingaweb2/enabledModules" 3 | show_stacktraces = "1" 4 | # config_backend = "ini" 5 | 6 | [logging] 7 | log = "php" 8 | level = "DEBUG" 9 | # file = "/proc/self/fd/2" 10 | 11 | [preferences] 12 | store = "db" 13 | resource = "icingaweb_db" 14 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/modules/boxydash/config.ini: -------------------------------------------------------------------------------- 1 | [settings] 2 | setting_refresh = "10" 3 | setting_boxsize = "10" 4 | include_softstate = "1" 5 | requires_authentication = "1" 6 | show_legend = "1" 7 | path_prefix = "/icinga" 8 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/modules/director/config.ini: -------------------------------------------------------------------------------- 1 | [db] 2 | resource = "director" 3 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/modules/monitoring/backends.ini: -------------------------------------------------------------------------------- 1 | 2 | [icinga] 3 | type = "ido" 4 | resource = "icinga_ido" 5 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/modules/monitoring/commandtransports.ini: -------------------------------------------------------------------------------- 1 | 2 | # 'OLD' Local Command Pipe 3 | #[icinga] 4 | #transport = "local" 5 | #path = "/var/run/icinga2/cmd/icinga2.cmd" 6 | 7 | # NEW via Icinga2 API 8 | [icinga] 9 | transport = "api" 10 | host = "%ICINGA2_MASTER%" # "127.0.0.1" - Icinga 2 host 11 | port = "5665" 12 | username = "%ICINGA2_CMD_API_USER%" 13 | password = "%ICINGA2_CMD_API_PASS%" 14 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/modules/monitoring/config.ini: -------------------------------------------------------------------------------- 1 | 2 | [security] 3 | protected_customvars = "*pw*,*pass*,community" 4 | -------------------------------------------------------------------------------- /rootfs/etc/icingaweb2/preferences/icinga/config.ini: -------------------------------------------------------------------------------- 1 | [icingaweb] 2 | theme = "Icinga" 3 | timezone = "Europe/Berlin" 4 | show_stacktraces = "0" 5 | show_benchmark = "0" 6 | auto_refresh = "1" 7 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/modules.d/00-health_check.conf: -------------------------------------------------------------------------------- 1 | 2 | location /health { 3 | access_log off; 4 | return 200; 5 | } 6 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/modules.d/00-restrictions.conf: -------------------------------------------------------------------------------- 1 | # Global restrictions configuration file. 2 | # Designed to be included in any server {} block.

3 | location = /favicon.ico { 4 | log_not_found off; 5 | access_log off; 6 | } 7 | 8 | location = /robots.txt { 9 | allow all; 10 | log_not_found off; 11 | access_log off; 12 | } 13 | 14 | # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac). 15 | # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) 16 | location ~ /\. { 17 | deny all; 18 | } 19 | 20 | # Deny access to any files with a .php extension in the uploads directory 21 | # Works in sub-directory installs and also in multisite network 22 | # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) 23 | location ~* /(?:uploads|files)/.*\.php$ { 24 | deny all; 25 | } 26 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/modules.d/99-icingaweb.conf: -------------------------------------------------------------------------------- 1 | 2 | location = / { 3 | return 301 /icinga; 4 | } 5 | 6 | location ^~ /icinga { 7 | 8 | root /usr/share/webapps/icingaweb2/public; 9 | 10 | index index.php; 11 | 12 | location ~ ^/icinga/index\.php(.*)$ { 13 | fastcgi_index index.php; 14 | fastcgi_param ICINGAWEB_CONFIGDIR /etc/icingaweb2; 15 | fastcgi_param SCRIPT_FILENAME /usr/share/webapps/icingaweb2/public/index.php; 16 | fastcgi_read_timeout 600; 17 | fastcgi_pass unix:/run/php-fpm-worker-01.sock; 18 | include fastcgi_params; 19 | } 20 | 21 | location ~ ^/icinga(.+)? { 22 | alias /usr/share/webapps/icingaweb2/public; 23 | index index.php; 24 | try_files $1 $uri $uri/ /icinga/index.php$is_args$args; 25 | } 26 | 27 | location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ { 28 | expires 1d; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | worker_processes 1; 3 | 4 | error_log /proc/self/fd/1 warn; 5 | 6 | daemon off; 7 | pid run/nginx.pid; 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | http { 14 | include mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main 18 | '$remote_addr - $remote_user [$time_local] ' 19 | '"$request" $status $bytes_sent ' 20 | '"$http_referer" "$http_user_agent" ' 21 | '"$http_x_forwarded_for" ' 22 | '"$gzip_ratio"'; 23 | 24 | sendfile on; 25 | server_tokens off; 26 | 27 | keepalive_timeout 65; 28 | 29 | gzip on; 30 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 31 | 32 | #client_body_temp_path /var/nginx/client_body_temp; 33 | client_max_body_size 10m; 34 | client_body_buffer_size 128k; 35 | proxy_redirect off; 36 | #proxy_temp_path /var/nginx/proxy_temp; 37 | proxy_connect_timeout 90; 38 | proxy_send_timeout 90; 39 | proxy_read_timeout 90; 40 | proxy_buffers 32 4k; 41 | proxy_buffer_size 8k; 42 | proxy_set_header Host $host; 43 | proxy_set_header X-Real-IP $remote_addr; 44 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 45 | proxy_headers_hash_bucket_size 64; 46 | 47 | include /etc/nginx/sites-enabled/*; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /rootfs/etc/nginx/sites-enabled/01-icingaweb.conf: -------------------------------------------------------------------------------- 1 | 2 | server { 3 | listen *:80 default_server; 4 | server_name _; 5 | 6 | root /usr/share/webapps/icingaweb2/public; 7 | index index.php; 8 | 9 | access_log /dev/null main; 10 | error_log /proc/self/fd/1; 11 | 12 | include modules.d/00-restrictions.conf; 13 | include modules.d/00-health_check.conf; 14 | include modules.d/99-icingaweb.conf; 15 | } 16 | -------------------------------------------------------------------------------- /rootfs/etc/php7/php-fpm.conf: -------------------------------------------------------------------------------- 1 | 2 | [global] 3 | pid = /run/php-fpm.pid 4 | daemonize = no 5 | error_log = /proc/self/fd/1 6 | log_level = notice 7 | emergency_restart_threshold = 10 8 | emergency_restart_interval = 30 9 | process_control_timeout = 5 10 | process.max = 32 11 | 12 | [worker-01] 13 | user = nginx 14 | group = nginx 15 | 16 | listen = /run/php-fpm-$pool.sock 17 | listen.owner = nginx 18 | listen.group = nginx 19 | 20 | pm = dynamic 21 | pm.max_children = 10 22 | pm.start_servers = 4 23 | pm.min_spare_servers = 2 24 | pm.max_spare_servers = 5 25 | pm.status_path = /status 26 | 27 | ;ping.path = /ping 28 | ;ping.response = pong 29 | 30 | ; access.log = /proc/self/fd/2 31 | ; access.format = "%R - %n - %{HTTP_HOST}e - %u %t \"%m %r [%Q%q]\" %s %f %{mili}d %{kilo}M %C%%" 32 | ; slowlog = /proc/self/fd/1 33 | ; request_slowlog_timeout = 10s 34 | ; request_terminate_timeout = 120s 35 | 36 | chdir = / 37 | clear_env = no 38 | catch_workers_output = yes 39 | 40 | ;env[HOSTNAME] = $HOSTNAME 41 | ;env[PATH] = /usr/local/bin:/usr/bin:/bin 42 | ;env[TMP] = /tmp 43 | ;env[TMPDIR] = /tmp 44 | ;env[TEMP] = /tmp 45 | 46 | php_admin_value[date.timezone] = "Europe/Berlin" 47 | php_admin_value[error_log] = /proc/self/fd/1 48 | php_admin_value[max_execution_time] = 300 49 | php_admin_value[memory_limit] = 512M 50 | php_admin_value[error_reporting] = E_ALL 51 | 52 | php_admin_value[display_errors] = on 53 | php_admin_value[display_startup_errors] = on 54 | php_admin_value[log_errors] = on 55 | 56 | php_admin_value[track_errors] = on 57 | php_admin_value[report_zend_debug] = 1 58 | 59 | php_admin_flag[log_errors] = on 60 | php_admin_flag[expose_php] = off 61 | -------------------------------------------------------------------------------- /rootfs/etc/supervisor.d/nginx.ini: -------------------------------------------------------------------------------- 1 | 2 | [program:nginx] 3 | command = /usr/sbin/nginx 4 | user = root 5 | stdout_logfile = /tmp/%(program_name)s.log 6 | stderr_logfile = /tmp/%(program_name)s.log 7 | autostart = true 8 | -------------------------------------------------------------------------------- /rootfs/etc/supervisor.d/php-fpm.ini: -------------------------------------------------------------------------------- 1 | 2 | [program:phpfpm] 3 | command = /usr/bin/php-fpm --fpm-config /etc/php/php-fpm.conf --pid /run/php-fpm.pid --allow-to-run-as-root --nodaemonize 4 | user = root 5 | stdout_logfile = /tmp/%(program_name)s.log 6 | stderr_logfile = /tmp/%(program_name)s.log 7 | autostart = true 8 | ; autorestart = true 9 | -------------------------------------------------------------------------------- /rootfs/etc/supervisord.conf: -------------------------------------------------------------------------------- 1 | 2 | [unix_http_server] 3 | file = /run/supervisord.sock 4 | 5 | [inet_http_server] 6 | port = *:9001 7 | username = supervisor 8 | password = supervisor 9 | 10 | [supervisord] 11 | logfile = /var/log/supervisord.log 12 | logfile_maxbytes = 5MB 13 | logfile_backups = 2 14 | loglevel = info 15 | pidfile = /run/supervisord.pid 16 | nodaemon = true 17 | 18 | [rpcinterface:supervisor] 19 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 20 | 21 | [supervisorctl] 22 | serverurl = unix:///run/supervisord.sock 23 | port = *:9001 24 | username = supervisor 25 | password = supervisor 26 | history_file = /root/.sc_history 27 | 28 | [include] 29 | files = /etc/supervisor.d/*.ini 30 | -------------------------------------------------------------------------------- /rootfs/init/common.sh: -------------------------------------------------------------------------------- 1 | 2 | enable_module() { 3 | 4 | local module="${1}" 5 | 6 | log_info " enable module" 7 | [[ -d "/etc/icingaweb2/modules/${module}" ]] || mkdir -p "/etc/icingaweb2/modules/${module}" 8 | 9 | [[ -e "/etc/icingaweb2/enabledModules/${module}" ]] || ln -s "${ICINGAWEB_MODULES_DIRECTORY}/${module}" /etc/icingaweb2/enabledModules/ 10 | } 11 | 12 | 13 | disable_module() { 14 | 15 | local module="${1}" 16 | 17 | [[ -e "/etc/icingaweb2/modules/${module}" ]] && rm -rf "/etc/icingaweb2/modules/${module}" 18 | [[ -e "/etc/icingaweb2/enabledModules/${module}" ]] && rm -rf "/etc/icingaweb2/enabledModules/${module}" 19 | } 20 | 21 | list_module() { 22 | 23 | local module="${1}" 24 | 25 | if [[ -e "${ICINGAWEB_MODULES_DIRECTORY}/${module}" ]] 26 | then 27 | echo 1 28 | else 29 | echo 0 30 | fi 31 | } 32 | 33 | -------------------------------------------------------------------------------- /rootfs/init/create_login_users.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Script to create users 3 | 4 | ICINGAWEB_ADMIN_USER=${ICINGAWEB_ADMIN_USER:-"icinga"} 5 | ICINGAWEB_ADMIN_PASS=${ICINGAWEB_ADMIN_PASS:-"icinga"} 6 | 7 | ICINGAWEB2_USERS=${ICINGAWEB2_USERS:-"${ICINGAWEB_ADMIN_USER}:${ICINGAWEB_ADMIN_PASS}"} 8 | 9 | # create the user into the database 10 | # 11 | insert_user_into_database() { 12 | 13 | local user="${1}" 14 | local pass="${2}" 15 | 16 | pass=$(openssl passwd -1 ${pass}) 17 | 18 | # insert default icingauser 19 | ( 20 | echo "USE ${WEB_DATABASE_NAME};" 21 | echo "INSERT IGNORE INTO icingaweb_user (name, active, password_hash) VALUES ('${user}', 1, '${pass}');" 22 | echo "quit" 23 | ) | mysql ${MYSQL_OPTS} 24 | 25 | if [[ $? -gt 0 ]] 26 | then 27 | log_error "can't create the icingaweb user" 28 | exit 1 29 | fi 30 | } 31 | 32 | # create (or add) the user(s) to the admin role 33 | # 34 | insert_users_into_role() { 35 | 36 | local user_list="${1}" 37 | 38 | if [[ $(grep -c "\[local admins\]" /etc/icingaweb2/roles.ini) -eq 0 ]] 39 | then 40 | cat << EOF > /etc/icingaweb2/roles.ini 41 | [local admins] 42 | users = "${user_list}" 43 | permissions = "*" 44 | 45 | EOF 46 | else 47 | 48 | sed -i \ 49 | -e "/^users.*=/s/=.*/= ${user_list}/" \ 50 | /etc/icingaweb2/roles.ini 51 | fi 52 | } 53 | 54 | 55 | create_login_user() { 56 | 57 | local users= 58 | local users_list=() 59 | 60 | [[ -n "${ICINGAWEB2_USERS}" ]] && users=$(echo ${ICINGAWEB2_USERS} | sed -e 's/,/ /g' -e 's/\s+/\n/g' | uniq) 61 | 62 | if [[ -z "${users}" ]] 63 | then 64 | log_info "no user found, create default 'admin' user" 65 | 66 | insert_user_into_database ${ICINGAWEB_ADMIN_USER} ${ICINGAWEB_ADMIN_PASSWORD} 67 | else 68 | log_info "create local icingaweb users ..." 69 | 70 | for u in ${users} 71 | do 72 | user=$(echo "${u}" | cut -d: -f1) 73 | pass=$(echo "${u}" | cut -d: -f2) 74 | 75 | [[ -z ${pass} ]] && pass=${user} 76 | 77 | log_info " ${user}" 78 | 79 | insert_user_into_database ${user} ${pass} 80 | 81 | users_list=("${users_list[@]}" "${user}") 82 | done 83 | fi 84 | 85 | lst=$( IFS=','; echo "${users_list[*]}" ); 86 | 87 | insert_users_into_role ${lst} 88 | } 89 | 90 | 91 | create_login_user 92 | 93 | # EOF 94 | 95 | -------------------------------------------------------------------------------- /rootfs/init/custom.d/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodsch/docker-icingaweb2/b268af3d35b7d39bb7b16f197ba800610923ae62/rootfs/init/custom.d/.keep -------------------------------------------------------------------------------- /rootfs/init/custom.d/x509/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bodsch/docker-icingaweb2/b268af3d35b7d39bb7b16f197ba800610923ae62/rootfs/init/custom.d/x509/.keep -------------------------------------------------------------------------------- /rootfs/init/custom.d/x509/jobs.ini: -------------------------------------------------------------------------------- 1 | [www.zweit-hirn.de] 2 | cidrs = "185.244.193.186/32" 3 | ports = "443" 4 | schedule = "0 0 * * *" 5 | -------------------------------------------------------------------------------- /rootfs/init/database/fix_latin1_db_statements.sh: -------------------------------------------------------------------------------- 1 | 2 | # this part is hard and need discussion! 3 | # when we remove all 'latin1_general_ci' parts has this possible bad side effects 4 | # 5 | # i hope, this works well, when the charset of database utf8 is 6 | 7 | # grep only the 'icingaweb_db' section of our configuration 8 | charset=$(grep -A10 '\[icingaweb_db\]' /etc/icingaweb2/resources.ini | \ 9 | grep '^charset' | \ 10 | tr -d ' ' | \ 11 | uniq | \ 12 | awk -F '=' '{printf $2}' | \ 13 | sed -e 's|"||g') 14 | 15 | if [[ "${charset}" = "utf8" ]] 16 | then 17 | # charset = "utf8" 18 | cd /usr/share/webapps/icingaweb2/modules/monitoring/library/Monitoring/Backend/Ido/Query 19 | sed -i 's| COLLATE latin1_general_ci||g' *.php 20 | fi 21 | -------------------------------------------------------------------------------- /rootfs/init/database/mysql.sh: -------------------------------------------------------------------------------- 1 | 2 | MYSQL_HOST=${MYSQL_HOST:-""} 3 | MYSQL_PORT=${MYSQL_PORT:-"3306"} 4 | MYSQL_ROOT_USER=${MYSQL_ROOT_USER:-"root"} 5 | MYSQL_ROOT_PASS=${MYSQL_ROOT_PASS:-""} 6 | 7 | IDO_DATABASE_NAME=${IDO_DATABASE_NAME:-"icinga2core"} 8 | WEB_DATABASE_NAME=${WEB_DATABASE_NAME:-"icingaweb2"} 9 | 10 | # ------------------------------------------------------------------------------------------------- 11 | 12 | [[ -z "${MYSQL_OPTS}" ]] && return 13 | [[ -z "${MYSQL_HOST}" ]] && return 14 | 15 | 16 | create_database() { 17 | 18 | # create user - when they NOT exists 19 | query="select host, user, password from mysql.user where user = '${WEB_DATABASE_NAME}';" 20 | status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w) 21 | 22 | if [[ ${status} -eq 0 ]] 23 | then 24 | log_info "create database '${WEB_DATABASE_NAME}' with user and grants for 'icingaweb2'" 25 | ( 26 | echo "--- create user 'icingaweb2'@'%' IDENTIFIED BY '${IDO_PASSWORD}';" 27 | echo "--- CREATE DATABASE IF NOT EXISTS ${WEB_DATABASE_NAME} DEFAULT CHARACTER SET 'utf8' DEFAULT COLLATE utf8_general_ci;" 28 | echo "CREATE DATABASE IF NOT EXISTS ${WEB_DATABASE_NAME};" 29 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${WEB_DATABASE_NAME}.* TO 'icingaweb2'@'%' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 30 | echo "FLUSH PRIVILEGES;" 31 | ) | mysql ${MYSQL_OPTS} 32 | 33 | if [ $? -eq 1 ] 34 | then 35 | log_error "can't create database '${WEB_DATABASE_NAME}'" 36 | exit 1 37 | fi 38 | fi 39 | 40 | # check user 41 | # 42 | # query="select host, user, password from mysql.user where user = '${WEB_DATABASE_NAME}';" 43 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = \"${WEB_DATABASE_NAME}\";" 44 | status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | grep -v host | wc -l) 45 | 46 | return ${status} 47 | } 48 | 49 | 50 | create_database_schema() { 51 | 52 | log_info "create database schema" 53 | 54 | mysql ${MYSQL_OPTS} --force ${WEB_DATABASE_NAME} < /usr/share/webapps/icingaweb2/etc/schema/mysql.schema.sql 55 | 56 | if [ $? -gt 0 ] 57 | then 58 | log_error "can't insert the icingaweb2 database schema" 59 | exit 1 60 | fi 61 | } 62 | 63 | 64 | drop_database_schema() { 65 | 66 | query="drop database ${WEB_DATABASE_NAME};" 67 | status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w) 68 | } 69 | 70 | 71 | configure_database() { 72 | 73 | create_database 74 | status=$? 75 | 76 | # if ${status} == 0, 77 | # 78 | if [[ ${status} -eq 0 ]] 79 | then 80 | # the database is fresh created 81 | create_database_schema 82 | elif ( [[ ${status} -gt 0 ]] && [[ ${status} -lt 5 ]] ) 83 | then 84 | # between 1 and 5, the creation of database was wrong 85 | drop_database_schema 86 | sleep 2s 87 | create_database_schema 88 | fi 89 | } 90 | 91 | 92 | create_resource_file() { 93 | 94 | if [[ $(grep -c "icingaweb_db]" /etc/icingaweb2/resources.ini) -eq 0 ]] 95 | then 96 | cat << EOF >> /etc/icingaweb2/resources.ini 97 | 98 | [icingaweb_db] 99 | type = "db" 100 | db = "mysql" 101 | host = "${MYSQL_HOST}" 102 | port = "3306" 103 | dbname = "icingaweb2" 104 | username = "icingaweb2" 105 | password = "${MYSQL_ICINGAWEB2_PASSWORD}" 106 | prefix = "icingaweb_" 107 | charset = "utf8" 108 | 109 | EOF 110 | fi 111 | 112 | if [[ $(grep -c "icinga_ido]" /etc/icingaweb2/resources.ini) -eq 0 ]] 113 | then 114 | if ( [[ ! -z ${IDO_PASSWORD} ]] || [[ ! -z ${IDO_DATABASE_NAME} ]] ) 115 | then 116 | cat << EOF >> /etc/icingaweb2/resources.ini 117 | 118 | [icinga_ido] 119 | type = "db" 120 | db = "mysql" 121 | host = "${MYSQL_HOST}" 122 | port = "3306" 123 | dbname = "${IDO_DATABASE_NAME}" 124 | username = "icinga2" 125 | password = "${IDO_PASSWORD}" 126 | charset = "utf8" 127 | EOF 128 | else 129 | log_warn "IDO_PASSWORD isn't set." 130 | log_warn "disable IDO Access for Icingaweb" 131 | fi 132 | fi 133 | } 134 | 135 | . /init/wait_for/mysql.sh 136 | 137 | configure_database 138 | 139 | create_resource_file 140 | 141 | # EOF 142 | 143 | -------------------------------------------------------------------------------- /rootfs/init/ini_parser.sh: -------------------------------------------------------------------------------- 1 | # 2 | # based on http://theoldschooldevops.com/2008/02/09/bash-ini-parser/ 3 | # 4 | 5 | PREFIX="cfg_section_" 6 | 7 | function debug { 8 | if ! [ "x$BASH_INI_PARSER_DEBUG" == "x" ] 9 | then 10 | echo $* 11 | echo --start-- 12 | echo "${ini[*]}" 13 | echo --end-- 14 | echo 15 | fi 16 | } 17 | 18 | function cfg_parser { 19 | shopt -p extglob &> /dev/null 20 | CHANGE_EXTGLOB=$? 21 | if [ $CHANGE_EXTGLOB = 1 ] 22 | then 23 | shopt -s extglob 24 | fi 25 | ini="$(<$1)" # read the file 26 | ini=${ini//$'\r'/} # remove linefeed i.e dos2unix 27 | 28 | ini="${ini//[/\\[}" 29 | debug "escaped [" 30 | ini="${ini//]/\\]}" 31 | debug "escaped ]" 32 | IFS=$'\n' && ini=( ${ini} ) # convert to line-array 33 | debug 34 | ini=( ${ini[*]/#*([[:space:]]);*/} ) 35 | debug "remove ; comments" 36 | ini=( ${ini[*]/#*([[:space:]])\#*/} ) 37 | debug "remove # comments" 38 | ini=( ${ini[*]/#+([[:space:]])/} ) # remove init whitespace 39 | debug 40 | ini=( ${ini[*]/%+([[:space:]])/} ) # remove ending whitespace 41 | debug "whitespace around =" 42 | ini=( ${ini[*]/*([[:space:]])=*([[:space:]])/=} ) # remove whitespace around = 43 | debug 44 | ini=( ${ini[*]/#\\[/\}$'\n'"$PREFIX"} ) # set section prefix 45 | debug 46 | ini=( ${ini[*]/%\\]/ \(} ) # convert text2function (1) 47 | debug 48 | ini=( ${ini[*]/=/=\( } ) # convert item to array 49 | debug 50 | ini=( ${ini[*]/%/ \)} ) # close array parenthesis 51 | debug 52 | ini=( ${ini[*]/%\\ \)/ \\} ) # the multiline trick 53 | debug 54 | ini=( ${ini[*]/%\( \)/\(\) \{} ) # convert text2function (2) 55 | debug 56 | ini=( ${ini[*]/%\} \)/\}} ) # remove extra parenthesis 57 | ini=( ${ini[*]/%\{/\{$'\n''cfg_unset ${FUNCNAME/#'$PREFIX'}'$'\n'} ) # clean previous definition of section 58 | debug 59 | ini[0]="" # remove first element 60 | debug 61 | ini[${#ini[*]} + 1]='}' # add the last brace 62 | debug 63 | eval "$(echo "${ini[*]}")" # eval the result 64 | EVAL_STATUS=$? 65 | if [ $CHANGE_EXTGLOB = 1 ] 66 | then 67 | shopt -u extglob 68 | fi 69 | return $EVAL_STATUS 70 | } 71 | 72 | function cfg_writer { 73 | SECTION=$1 74 | OLDIFS="$IFS" 75 | IFS=' '$'\n' 76 | if [ -z "$SECTION" ] 77 | then 78 | fun="$(declare -F)" 79 | else 80 | fun="$(declare -F $PREFIX$SECTION)" 81 | if [ -z "$fun" ] 82 | then 83 | echo "section $SECTION not found" 1>&2 84 | exit 1 85 | fi 86 | fi 87 | fun="${fun//declare -f/}" 88 | for f in $fun; do 89 | [ "${f#$PREFIX}" == "${f}" ] && continue 90 | item="$(declare -f ${f})" 91 | item="${item##*\{}" # remove function definition 92 | item="${item##*FUNCNAME*$PREFIX\};}" # remove clear section 93 | item="${item/FUNCNAME\/#$PREFIX;}" # remove line 94 | item="${item/\}}" # remove function close 95 | item="${item%)*}" # remove everything after parenthesis 96 | item="${item});" # add close parenthesis 97 | vars="" 98 | while [ "$item" != "" ] 99 | do 100 | newvar="${item%%=*}" # get item name 101 | vars="$vars$newvar" # add name to collection 102 | item="${item#*;}" # remove readed line 103 | done 104 | vars=$(echo "$vars" | sort -u) # remove duplication 105 | eval $f 106 | echo "[${f#$PREFIX}]" # output section 107 | for var in $vars; do 108 | eval 'local length=${#'$var'[*]}' # test if var is an array 109 | if [ $length == 1 ] 110 | then 111 | echo $var=\"${!var}\" #output var 112 | else 113 | echo ";$var is an array" # add comment denoting var is an array 114 | eval 'echo $var=\"${'$var'[*]}\"' # output array var 115 | fi 116 | done 117 | done 118 | IFS="$OLDIFS" 119 | } 120 | 121 | function cfg_unset { 122 | SECTION=$1 123 | OLDIFS="$IFS" 124 | IFS=' '$'\n' 125 | if [ -z "$SECTION" ] 126 | then 127 | fun="$(declare -F)" 128 | else 129 | fun="$(declare -F $PREFIX$SECTION)" 130 | if [ -z "$fun" ] 131 | then 132 | echo "section $SECTION not found" 1>&2 133 | return 134 | fi 135 | fi 136 | fun="${fun//declare -f/}" 137 | for f in $fun; do 138 | [ "${f#$PREFIX}" == "${f}" ] && continue 139 | item="$(declare -f ${f})" 140 | item="${item##*\{}" # remove function definition 141 | item="${item##*FUNCNAME*$PREFIX\};}" # remove clear section 142 | item="${item/\}}" # remove function close 143 | item="${item%)*}" # remove everything after parenthesis 144 | item="${item});" # add close parenthesis 145 | vars="" 146 | while [ "$item" != "" ] 147 | do 148 | newvar="${item%%=*}" # get item name 149 | vars="$vars $newvar" # add name to collection 150 | item="${item#*;}" # remove readed line 151 | done 152 | for var in $vars; do 153 | unset $var 154 | done 155 | done 156 | IFS="$OLDIFS" 157 | } 158 | 159 | function cfg_clear { 160 | SECTION=$1 161 | OLDIFS="$IFS" 162 | IFS=' '$'\n' 163 | if [ -z "$SECTION" ] 164 | then 165 | fun="$(declare -F)" 166 | else 167 | fun="$(declare -F $PREFIX$SECTION)" 168 | if [ -z "$fun" ] 169 | then 170 | echo "section $SECTION not found" 1>&2 171 | exit 1 172 | fi 173 | fi 174 | fun="${fun//declare -f/}" 175 | for f in $fun; do 176 | [ "${f#$PREFIX}" == "${f}" ] && continue 177 | unset -f ${f} 178 | done 179 | IFS="$OLDIFS" 180 | } 181 | 182 | function cfg_update { 183 | SECTION=$1 184 | VAR=$2 185 | OLDIFS="$IFS" 186 | IFS=' '$'\n' 187 | fun="$(declare -F $PREFIX$SECTION)" 188 | if [ -z "$fun" ] 189 | then 190 | echo "section $SECTION not found" 1>&2 191 | exit 1 192 | fi 193 | fun="${fun//declare -f/}" 194 | item="$(declare -f ${fun})" 195 | #item="${item##* $VAR=*}" # remove var declaration 196 | item="${item/\}}" # remove function close 197 | item="${item} 198 | $VAR=(${!VAR}) 199 | " 200 | item="${item} 201 | }" # close function again 202 | 203 | eval "function $item" 204 | } 205 | 206 | #Test harness 207 | if [ $# != 0 ] 208 | then 209 | $@ 210 | fi 211 | # vim: filetype=sh 212 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/authentication.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | 7 | log_info " authentication" 8 | 9 | # configure the LDAP resources 10 | # 11 | configure() { 12 | 13 | [[ "${USE_LDAP}" = "false" ]] && return 14 | 15 | backend="ldap" 16 | user_name_attribute="uid" 17 | user_class="inetOrgPerson" 18 | 19 | [[ "${LDAP_AD}" = "true" ]] && backend="msldap" 20 | [[ "${LDAP_AD}" = "true" ]] && user_name_attribute="sAMAccountName" 21 | [[ "${LDAP_AD}" = "true" ]] && user_class="user" 22 | 23 | 24 | # create a LDAP resource 25 | # 26 | if [[ $(grep -c "\[ldap\]" /etc/icingaweb2/resources.ini) -eq 0 ]] 27 | then 28 | log_info " - LDAP resource" 29 | 30 | cat << EOF >> /etc/icingaweb2/resources.ini 31 | 32 | [ldap] 33 | type = "ldap" 34 | hostname = "${LDAP_SERVER}" 35 | port = "${LDAP_PORT}" 36 | encryption = "none" 37 | root_dn = "${LDAP_BASE_DN}" 38 | bind_dn = "${LDAP_BIND_DN}" 39 | bind_pw = "${LDAP_BIND_PASSWORD}" 40 | 41 | EOF 42 | fi 43 | 44 | 45 | # add user authentication 46 | # 47 | if [[ $(grep -c "\[ldap users\]" /etc/icingaweb2/authentication.ini) -eq 0 ]] 48 | then 49 | log_info " - LDAP authentication" 50 | 51 | cat << EOF >> /etc/icingaweb2/authentication.ini 52 | 53 | [ldap users] 54 | backend = "${backend}" 55 | resource = "ldap" 56 | user_class = "${user_class}" 57 | base_dn = "${LDAP_BASE_DN}" 58 | # the login AND displayed name 59 | user_name_attribute = "${user_name_attribute}" 60 | 61 | EOF 62 | if [[ ! -z "${LDAP_FILTER}" ]] 63 | then 64 | echo "filter = \"${LDAP_FILTER}\"" >> /etc/icingaweb2/authentication.ini 65 | fi 66 | fi 67 | 68 | # add group filter 69 | # 70 | if ( [[ ! -f /etc/icingaweb2/groups.ini ]] || [[ $(grep -c "\[ldap groups\]" /etc/icingaweb2/groups.ini) -eq 0 ]] ) 71 | then 72 | log_info " - LDAP groups" 73 | 74 | cat << EOF >> /etc/icingaweb2/groups.ini 75 | 76 | [ldap groups] 77 | backend = "${backend}" 78 | resource = "ldap" 79 | user_backend = "ldap users" 80 | # the displayed name 81 | group_name_attribute = "cn" 82 | 83 | EOF 84 | fi 85 | 86 | 87 | # add LDAP role 88 | # 89 | if [[ $(grep -c "\[ldap roles\]" /etc/icingaweb2/roles.ini) -eq 0 ]] 90 | then 91 | log_info " - LDAP roles" 92 | 93 | if [[ ! -z "${LDAP_ROLE_GROUPS}" ]] 94 | then 95 | cat << EOF >> /etc/icingaweb2/roles.ini 96 | 97 | [ldap roles] 98 | groups = "${LDAP_ROLE_GROUPS}" 99 | permissions = "${LDAP_ROLE_PERMISSIONS}" 100 | 101 | EOF 102 | 103 | fi 104 | fi 105 | 106 | } 107 | 108 | 109 | # extract Environment variables 110 | # 111 | extract_vars() { 112 | 113 | # default values for our Environment 114 | # 115 | USE_LDAP=false 116 | LDAP_AD=${LDAP_AD:-false} 117 | LDAP_SERVER=${LDAP_SERVER:-} 118 | LDAP_PORT=${LDAP_PORT:-389} 119 | LDAP_USER_CLASS=${LDAP_USER_CLASS:-user} 120 | LDAP_BASE_DN=${LDAP_BASE_DN:-} 121 | LDAP_FILTER=${LDAP_FILTER:-} 122 | LDAP_BIND_DN=${LDAP_BIND_DN:-} 123 | LDAP_BIND_PASSWORD=${LDAP_BIND_PASSWORD:-} 124 | LDAP_ROLE_GROUPS=${LDAP_ROLE_GROUPS:-} 125 | LDAP_ROLE_PERMISSIONS=${LDAP_ROLE_PERMISSIONS:-'*'} 126 | 127 | USE_JSON="true" 128 | 129 | # detect if 'LDAP' an json 130 | # 131 | if ( [[ ! -z "${LDAP}" ]] && [[ "${LDAP}" != "true" ]] && [[ "${LDAP}" != "false" ]] ) 132 | then 133 | echo "${LDAP}" | json_verify -q 2> /dev/null 134 | 135 | if [[ $? -gt 0 ]] 136 | then 137 | # log_debug " the LDAP Environment is not an json" 138 | # log_info "use fallback strategy." 139 | USE_JSON="false" 140 | fi 141 | else 142 | # log_debug " the LDAP Environment is not an json" 143 | # log_info "use fallback strategy." 144 | USE_JSON="false" 145 | fi 146 | 147 | # we can use json as configure 148 | # 149 | if [[ "${USE_JSON}" == "true" ]] 150 | then 151 | #log_info "the LDAP Environment is an json" 152 | 153 | if ( [[ "${LDAP}" == "true" ]] || [[ "${LDAP}" == "false" ]] ) 154 | then 155 | log_error " the LDAP Environment must be an json, not true or false!" 156 | else 157 | LDAP_AD=$(echo "${LDAP}" | jq --raw-output .active_directory) 158 | LDAP_SERVER=$(echo "${LDAP}" | jq --raw-output .server) 159 | LDAP_PORT=$(echo "${LDAP}" | jq --raw-output .port) 160 | LDAP_BIND_DN=$(echo "${LDAP}" | jq --raw-output .bind_dn) 161 | LDAP_BIND_PASSWORD=$(echo "${LDAP}" | jq --raw-output .bind_password) 162 | LDAP_BASE_DN=$(echo "${LDAP}" | jq --raw-output .base_dn) 163 | LDAP_FILTER=$(echo "${LDAP}" | jq --raw-output .filter) 164 | LDAP_ROLE_GROUPS=$(echo "${LDAP}" | jq --raw-output .role.groups) 165 | LDAP_ROLE_PERMISSIONS=$(echo "${LDAP}" | jq --raw-output .role.permissions) 166 | 167 | [[ "${LDAP_AD}" == null ]] && LDAP_AD= 168 | [[ "${LDAP_SERVER}" == null ]] && LDAP_SERVER= 169 | [[ "${LDAP_PORT}" == null ]] && LDAP_PORT=389 170 | [[ "${LDAP_BIND_DN}" == null ]] && LDAP_BIND_DN= 171 | [[ "${LDAP_BIND_PASSWORD}" == null ]] && LDAP_BIND_PASSWORD= 172 | [[ "${LDAP_BASE_DN}" == null ]] && LDAP_BASE_DN= 173 | [[ "${LDAP_FILTER}" == null ]] && LDAP_FILTER= 174 | [[ "${LDAP_ROLE_GROUPS}" == null ]] && LDAP_ROLE_GROUPS= 175 | [[ "${LDAP_ROLE_PERMISSIONS}" == null ]] && LDAP_ROLE_PERMISSIONS='*' 176 | fi 177 | else 178 | LDAP_AD=${LDAP_AD:-false} 179 | LDAP_SERVER=${LDAP_SERVER:-} 180 | LDAP_PORT=${LDAP_PORT:-389} 181 | LDAP_USER_CLASS=${LDAP_USER_CLASS:-user} 182 | LDAP_BASE_DN=${LDAP_BASE_DN:-} 183 | LDAP_FILTER=${LDAP_FILTER:-} 184 | LDAP_BIND_DN=${LDAP_BIND_DN:-} 185 | LDAP_BIND_PASSWORD=${LDAP_BIND_PASSWORD:-} 186 | LDAP_ROLE_GROUPS=${LDAP_ROLE_GROUPS:-} 187 | LDAP_ROLE_PERMISSIONS=${LDAP_ROLE_PERMISSIONS:-'*'} 188 | fi 189 | 190 | validate_ldap_environment 191 | } 192 | 193 | # validate extracted Environment variables 194 | # 195 | validate_ldap_environment() { 196 | 197 | LDAP_AD=${LDAP_AD:-false} 198 | LDAP_SERVER=${LDAP_SERVER:-} 199 | LDAP_PORT=${LDAP_PORT:-389} 200 | LDAP_USER_CLASS=${LDAP_USER_CLASS:-user} 201 | LDAP_BASE_DN=${LDAP_BASE_DN:-} 202 | LDAP_FILTER=${LDAP_FILTER:-} 203 | LDAP_BIND_DN=${LDAP_BIND_DN:-} 204 | LDAP_BIND_PASSWORD=${LDAP_BIND_PASSWORD:-} 205 | LDAP_ROLE_GROUPS=${LDAP_ROLE_GROUPS:-} 206 | LDAP_ROLE_PERMISSIONS=${LDAP_ROLE_PERMISSIONS:-'*'} 207 | 208 | # use the new Cert Service to create and get a valide certificat for distributed icinga services 209 | # 210 | if ( 211 | [[ ! -z ${LDAP_AD} ]] && 212 | [[ ! -z ${LDAP_SERVER} ]] && 213 | [[ ! -z ${LDAP_PORT} ]] && 214 | [[ ! -z ${LDAP_BIND_DN} ]] && 215 | [[ ! -z ${LDAP_BIND_PASSWORD} ]] && 216 | [[ ! -z ${LDAP_BASE_DN} ]] && 217 | [[ ! -z ${LDAP_FILTER} ]] && 218 | [[ ! -z ${LDAP_ROLE_GROUPS} ]] && 219 | [[ ! -z ${LDAP_ROLE_PERMISSIONS} ]] 220 | ) 221 | then 222 | USE_LDAP=true 223 | 224 | export LDAP_AD 225 | export LDAP_FILTER 226 | export LDAP_SERVER 227 | export LDAP_PORT 228 | export LDAP_USER_CLASS 229 | export LDAP_BASE_DN 230 | export LDAP_FILTER 231 | export LDAP_BIND_DN 232 | export LDAP_ROLE_GROUPS 233 | export LDAP_ROLE_PERMISSIONS 234 | 235 | export USE_LDAP 236 | fi 237 | } 238 | 239 | extract_vars 240 | 241 | configure 242 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/commandtransport.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | 7 | log_info " command transport" 8 | 9 | ICINGA2_MASTER=${ICINGA2_MASTER:-"icinga2-master"} 10 | ICINGA2_PORT=${ICINGA2_PORT:-5665} 11 | 12 | ICINGA2_CMD_API_USER=${ICINGA2_CMD_API_USER:-""} 13 | ICINGA2_CMD_API_PASS=${ICINGA2_CMD_API_PASS:-""} 14 | 15 | # ------------------------------------------------------------------------------------------------- 16 | 17 | check() { 18 | if ( [[ -z ${ICINGA2_MASTER} ]] || [[ -z ${ICINGA2_CMD_API_USER} ]] || [[ -z ${ICINGA2_CMD_API_PASS} ]] ) 19 | then 20 | log_warn " no valid information for command transport over API" 21 | exit 0 22 | fi 23 | } 24 | 25 | configure() { 26 | 27 | log_info " configure command transport over API" 28 | 29 | cat << EOF > /etc/icingaweb2/modules/monitoring/commandtransports.ini 30 | 31 | [icinga] 32 | transport = "api" 33 | host = "${ICINGA2_MASTER}" 34 | port = "${ICINGA2_PORT}" 35 | username = "${ICINGA2_CMD_API_USER}" 36 | password = "${ICINGA2_CMD_API_PASS}" 37 | 38 | EOF 39 | 40 | } 41 | 42 | check 43 | configure 44 | 45 | # EOF 46 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/director.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | . /init/common.sh 7 | 8 | log_info " director" 9 | 10 | MYSQL_ICINGAWEB2_PASSWORD="director" 11 | 12 | check() { 13 | 14 | [[ -z "${MYSQL_OPTS}" ]] && exit 1 15 | 16 | if [[ "${ICINGAWEB_DIRECTOR}" = "false" ]] 17 | then 18 | log_info " director support is disabled" 19 | 20 | disable_module director 21 | exit 0 22 | fi 23 | } 24 | 25 | create_database() { 26 | 27 | local database_name='director' 28 | local director="${ICINGAWEB_MODULES_DIRECTORY}/director" 29 | 30 | # check if database already created ... 31 | # 32 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = '${database_name}' limit 1;" 33 | 34 | director_status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w ) 35 | 36 | if [[ ${director_status} -eq 0 ]] 37 | then 38 | # Database isn't created 39 | # well, i do my job ... 40 | # 41 | log_info " initializing databases" 42 | ( 43 | echo "--- create user 'director'@'%' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 44 | echo "CREATE DATABASE IF NOT EXISTS ${database_name} DEFAULT CHARACTER SET 'utf8';" 45 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'director'@'%' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 46 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'director'@'$(hostname -i)' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 47 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'director'@'$(hostname -s)' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 48 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'director'@'$(hostname -f)' IDENTIFIED BY '${MYSQL_ICINGAWEB2_PASSWORD}';" 49 | echo "quit" 50 | ) | mysql ${MYSQL_OPTS} 51 | 52 | SCHEMA_FILE="${director}/schema/mysql.sql" 53 | 54 | if [[ -f ${SCHEMA_FILE} ]] 55 | then 56 | log_info " import database schema" 57 | 58 | mysql ${MYSQL_OPTS} --force ${database_name} < ${SCHEMA_FILE} 59 | 60 | if [[ $? -gt 0 ]] 61 | then 62 | log_error "can't insert the director Database Schema" 63 | exit 1 64 | fi 65 | else 66 | log_warn "missing schema file" 67 | fi 68 | fi 69 | } 70 | 71 | 72 | configure() { 73 | 74 | check 75 | 76 | local director="${ICINGAWEB_MODULES_DIRECTORY}/director" 77 | 78 | # icingaweb director 79 | # 80 | if [[ -d ${director} ]] 81 | then 82 | 83 | log_info " configure director" 84 | 85 | create_database 86 | 87 | enable_module director 88 | 89 | log_info " create config files for icingaweb" 90 | 91 | if [[ $(grep -c "director]" /etc/icingaweb2/resources.ini) -eq 0 ]] 92 | then 93 | cat << EOF >> /etc/icingaweb2/resources.ini 94 | 95 | [director] 96 | type = "db" 97 | db = "mysql" 98 | charset = "utf8" 99 | host = "${MYSQL_HOST}" 100 | port = "3306" 101 | dbname = "director" 102 | username = "director" 103 | password = "${MYSQL_ICINGAWEB2_PASSWORD}" 104 | 105 | EOF 106 | fi 107 | 108 | # we must wait for icinha2-master 109 | # 110 | if [[ ! -f /etc/icingaweb2/modules/director/kickstart.ini ]] 111 | then 112 | cat << EOF > /etc/icingaweb2/modules/director/kickstart.ini 113 | [config] 114 | endpoint = ${ICINGA2_MASTER} 115 | host = ${ICINGA2_MASTER} 116 | port = ${ICINGA2_API_PORT} 117 | username = ${ICINGA2_CMD_API_USER} 118 | password = ${ICINGA2_CMD_API_PASS} 119 | EOF 120 | fi 121 | 122 | set +e 123 | set +u 124 | 125 | log_info " start director migration and kickstart" 126 | 127 | retry=4 128 | migration_status= 129 | kickstart_status= 130 | 131 | until [[ ${retry} -le 0 ]] 132 | do 133 | migration_status= 134 | kickstart_status= 135 | 136 | status=$(icingacli director endpoint exists ${ICINGA2_MASTER}) 137 | #log_info " ${status}" 138 | 139 | code=$(icingacli director migration pending --verbose) 140 | migration_status="${?}" 141 | #log_info " migration pending" # '${code}' (${migration_status})" 142 | 143 | if [[ ${migration_status} -eq 0 ]] 144 | then 145 | #log_info " icingacli director migration run" 146 | status=$(icingacli director migration run --verbose) 147 | #log_info " ${status}" 148 | fi 149 | 150 | code=$(icingacli director kickstart required --verbose) 151 | kickstart_status="${?}" 152 | 153 | #log_info " kickstart required" # '${code}' (${kickstart_status})" 154 | 155 | if [[ ${kickstart_status} -eq 1 ]] 156 | then 157 | break 158 | fi 159 | 160 | if [[ ${kickstart_status} -eq 0 ]] 161 | then 162 | #log_info " icingacli director kickstart run" 163 | status=$(icingacli director kickstart run --verbose) 164 | #log_info " ${status}" 165 | fi 166 | 167 | retry=$(expr ${retry} - 1) 168 | done 169 | 170 | status=$(icingacli director config render) 171 | #log_info " ${status}" 172 | status=$(icingacli director config deploy) 173 | #log_info " ${status}" 174 | fi 175 | 176 | } 177 | 178 | configure 179 | 180 | # EOF 181 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/grafana.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | GRAFANA_HOST=${GRAFANA_HOST:-grafana} 5 | GRAFANA_PORT=${GRAFANA_PORT:-3000} 6 | 7 | GRAFANA_TIMERANGE=${GRAFANA_TIMERANGE:-12h} 8 | GRAFANA_TIMERANGE_ALL=${GRAFANA_TIMERANGE_ALL:-7d} 9 | 10 | GRAFANA_DASHBOARD=${GRAFANA_DASHBOARD:-icinga2-default} 11 | GRAFANA_DASHBOARD_UID=${GRAFANA_DASHBOARD_UID:-} 12 | GRAFANA_PROTOCOL=${GRAFANA_PROTOCOL:-http} 13 | GRAFANA_ACCESS=${GRAFANA_ACCESS:-proxy} 14 | 15 | GRAFANA_AUTHENTICATION=${GRAFANA_AUTHENTICATION:-token} 16 | GRAFANA_AUTHENTICATION_TOKEN=${GRAFANA_AUTHENTICATION_TOKEN:-} 17 | GRAFANA_AUTHENTICATION_USERNAME=${GRAFANA_AUTHENTICATION_USERNAME:-admin} 18 | GRAFANA_AUTHENTICATION_PASSWORD=${GRAFANA_AUTHENTICATION_PASSWORD:-admin} 19 | 20 | GRAFANA_DATASOURCE=${GRAFANA_DATASOURCE:-influxdb} 21 | 22 | GRAFANA_ENABLE_LINK=${GRAFANA_ENABLE_LINK:-no} 23 | GRAFANA_SHOW_DEBUG=${GRAFANA_SHOW_DEBUG:-0} 24 | GRAFANA_PUBLIC=${GRAFANA_PUBLIC:-no} 25 | GRAFANA_PUBLIC_HOST=${GRAFANA_PUBLIC_HOST:-localhost/grafana/} 26 | GRAFANA_PUBLIC_PROTOCOL=${GRAFANA_PUBLIC_PROTOCOL:-http} 27 | GRAFANA_THEME=${GRAFANA_THEME:-light} 28 | 29 | GRAFANA_PROXY_TIMEOUT=${GRAFANA_PROXY_TIMEOUT:-5} 30 | 31 | . /init/output.sh 32 | . /init/common.sh 33 | 34 | log_info " grafana" 35 | 36 | check() { 37 | 38 | if ( [[ -z ${GRAFANA_HOST} ]] || [[ -z ${GRAFANA_PORT} ]] ) 39 | then 40 | log_info " disable grafana support while missing GRAFANA_HOST or GRAFANA_PORT" 41 | 42 | disable_module grafana 43 | exit 0 44 | fi 45 | } 46 | 47 | 48 | create_token() { 49 | 50 | log_info " create API token" 51 | 52 | API_TOKEN_FILE="/tmp/grafana.test" 53 | api_key="icingaweb2" 54 | 55 | curl_opts="--silent --insecure --user ${GRAFANA_AUTHENTICATION_USERNAME}:${GRAFANA_AUTHENTICATION_PASSWORD}" 56 | 57 | data=$(curl \ 58 | ${curl_opts} \ 59 | --header "Content-Type: application/json" \ 60 | http://${GRAFANA_HOST}:${GRAFANA_PORT}/api/auth/keys) 61 | 62 | result=${?} 63 | 64 | existing_api_key=$(echo "${data}" | jq --raw-output .[].name) 65 | 66 | if [[ -n ${existing_api_key} ]] && [[ -f ${API_TOKEN_FILE} ]] 67 | then 68 | #log_debug "reuse token" 69 | 70 | GRAFANA_AUTHENTICATION_TOKEN=$(jq --raw-output .key ${API_TOKEN_FILE}) 71 | API_NAME=$(jq --raw-output .name ${API_TOKEN_FILE}) 72 | else 73 | 74 | code=$(curl \ 75 | ${curl_opts} \ 76 | --request POST \ 77 | --header "Content-Type: application/json" \ 78 | --write-out '%{http_code}\n' \ 79 | --output ${API_TOKEN_FILE} \ 80 | --data "{\"name\":\"${api_key}\", \"role\": \"Admin\"}" \ 81 | http://${GRAFANA_HOST}:${GRAFANA_PORT}/api/auth/keys) 82 | 83 | result=${?} 84 | 85 | if [[ ${result} -eq 0 ]] && [[ ${code} = 200 ]] 86 | then 87 | #log_debug "token request are successfull" 88 | 89 | GRAFANA_AUTHENTICATION_TOKEN=$(jq --raw-output .key ${API_TOKEN_FILE}) 90 | 91 | export GRAFANA_AUTHENTICATION_TOKEN 92 | else 93 | log_error "token request failed" 94 | fi 95 | fi 96 | } 97 | 98 | 99 | configure() { 100 | 101 | if [[ $(list_module grafana) -eq 0 ]] 102 | then 103 | log_warn "grafana module is not installed" 104 | exit 0 105 | fi 106 | 107 | # if [[ $(/usr/bin/icingacli module list | grep -c grafana) -eq 0 ]] 108 | # then 109 | # log_warn "grafana module is not installed" 110 | # exit 0 111 | # fi 112 | 113 | log_info " create config files for icingaweb" 114 | 115 | [[ -d /etc/icingaweb2/modules/grafana ]] || mkdir -p /etc/icingaweb2/modules/grafana 116 | 117 | cat << EOF > /etc/icingaweb2/modules/grafana/config.ini 118 | 119 | [grafana] 120 | version = 1 121 | host = "${GRAFANA_HOST}:${GRAFANA_PORT}" 122 | protocol = "${GRAFANA_PROTOCOL}" 123 | timerangeAll = "${GRAFANA_TIMERANGE_ALL}" 124 | timerange = "${GRAFANA_TIMERANGE}" 125 | # timerangeAll = "1w/w" 126 | defaultdashboard = "${GRAFANA_DASHBOARD}" 127 | defaultdashboarduid = "${GRAFANA_DASHBOARD_UID}" 128 | defaultdashboardpanelid = 1 129 | defaultorgid = 1 130 | shadows = 0 131 | theme = "${GRAFANA_THEME}" 132 | datasource = "${GRAFANA_DATASOURCE}" 133 | accessmode = "${GRAFANA_ACCESS}" 134 | height = 280 135 | width = 640 136 | enableLink = ${GRAFANA_ENABLE_LINK} 137 | debug = ${GRAFANA_SHOW_DEBUG} 138 | usepublic = ${GRAFANA_PUBLIC} 139 | publichost = ${GRAFANA_PUBLIC_HOST} 140 | publicprotocol = ${GRAFANA_PUBLIC_PROTOCOL} 141 | proxytimeout = ${GRAFANA_PROXY_TIMEOUT} 142 | EOF 143 | 144 | if [[ "${GRAFANA_AUTHENTICATION}" = "token" ]] && [[ -z "${GRAFANA_AUTHENTICATION_TOKEN}" ]] 145 | then 146 | . /init/wait_for/grafana.sh 147 | 148 | create_token 149 | 150 | if [[ -z "${GRAFANA_AUTHENTICATION_TOKEN}" ]] 151 | then 152 | log_error "token creation failed" 153 | log_error "use fallback" 154 | 155 | GRAFANA_AUTHENTICATION="basic" 156 | fi 157 | fi 158 | 159 | 160 | # authentications ... 161 | if [[ "${GRAFANA_AUTHENTICATION}" = "token" ]] 162 | then 163 | 164 | cat << EOF >> /etc/icingaweb2/modules/grafana/config.ini 165 | 166 | authentication = "token" 167 | apitoken = "${GRAFANA_AUTHENTICATION_TOKEN}" 168 | 169 | EOF 170 | 171 | elif [[ "${GRAFANA_AUTHENTICATION}" = "basic" ]] 172 | then 173 | cat << EOF >> /etc/icingaweb2/modules/grafana/config.ini 174 | 175 | authentication = "basic" 176 | username = "${GRAFANA_AUTHENTICATION_USERNAME}" 177 | password = "${GRAFANA_AUTHENTICATION_PASSWORD}" 178 | 179 | EOF 180 | elif [[ "${GRAFANA_AUTHENTICATION}" = "anon" ]] 181 | then 182 | cat << EOF >> /etc/icingaweb2/modules/grafana/config.ini 183 | 184 | # anonymous 185 | authentication = "anon" 186 | 187 | EOF 188 | else 189 | 190 | log_warn "wrong authentication configured" 191 | log_warn "use 'anonymous' as default" 192 | 193 | cat << EOF >> /etc/icingaweb2/modules/grafana/config.ini 194 | 195 | # anonymous 196 | authentication = "anon" 197 | 198 | EOF 199 | 200 | fi 201 | 202 | enable_module grafana 203 | } 204 | 205 | check 206 | configure 207 | 208 | # EOF 209 | 210 | # [grafana] 211 | # version = "1" 212 | # host = "grafana:3000" 213 | # protocol = "http" 214 | # timerangeAll = "1w/w" 215 | # defaultdashboard = "icinga2-default" 216 | # defaultdashboarduid = "icinga2-default" 217 | # defaultdashboardpanelid = "1" 218 | # defaultorgid = "1" 219 | # shadows = "0" 220 | # theme = "light" 221 | # datasource = "influxdb" 222 | # accessmode = "proxy" 223 | # height = "280" 224 | # width = "640" 225 | # enableLink = "yes" 226 | # debug = "0" 227 | # authentication = "token" 228 | # apitoken = "==" 229 | # proxytimeout = "5" 230 | # usepublic = "yes" 231 | # publichost = "localhost/grafana/" 232 | # publicprotocol = "http" 233 | 234 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/graphite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | GRAPHITE_HOST=${GRAPHITE_HOST:-""} 6 | GRAPHITE_HTTP_PORT=${GRAPHITE_HTTP_PORT:-8080} 7 | 8 | . /init/output.sh 9 | . /init/common.sh 10 | 11 | log_info " graphite" 12 | 13 | check() { 14 | 15 | if ( [[ -z ${GRAPHITE_HOST} ]] || [[ -z ${GRAPHITE_HTTP_PORT} ]] ) 16 | then 17 | log_info " disable graphite support while missing GRAPHITE_HOST or GRAPHITE_HTTP_PORT" 18 | 19 | disable_module graphite 20 | exit 0 21 | fi 22 | 23 | } 24 | 25 | configure() { 26 | 27 | if [[ $(list_module graphite) -eq 0 ]] 28 | then 29 | log_warn "graphite module is not installed" 30 | exit 0 31 | fi 32 | 33 | log_info " create config files for icingaweb" 34 | 35 | [[ -d /etc/icingaweb2/modules/graphite ]] || mkdir -p /etc/icingaweb2/modules/graphite 36 | 37 | cat << EOF > /etc/icingaweb2/modules/graphite/config.ini 38 | 39 | [graphite] 40 | url = "http://${GRAPHITE_HOST}:${GRAPHITE_HTTP_PORT}" 41 | ; user = "user" 42 | ; password = "pass" 43 | 44 | [ui] 45 | default_time_range = "12" 46 | default_time_range_unit = "hours" 47 | disable_no_graphs_found = "0" 48 | 49 | ;[icinga] 50 | ; graphite_writer_host_name_template = "host tpl" 51 | ; graphite_writer_service_name_template = "service tpl" 52 | 53 | EOF 54 | 55 | enable_module graphite 56 | } 57 | 58 | check 59 | configure 60 | 61 | # EOF 62 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/reporting.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | . /init/common.sh 7 | 8 | log_info " reporting" 9 | 10 | DATABASE_REPORTING_PASSWORD="reporting" 11 | 12 | check() { 13 | 14 | [[ -z "${MYSQL_OPTS}" ]] && exit 1 15 | } 16 | 17 | configure() { 18 | 19 | local module_directory="${ICINGAWEB_MODULES_DIRECTORY}/reporting" 20 | 21 | # icingaweb module_directory 22 | # 23 | if [[ -d ${module_directory} ]] 24 | then 25 | create_database 26 | 27 | [[ -d /etc/icingaweb2/modules/reporting ]] || mkdir -p /etc/icingaweb2/modules/reporting 28 | 29 | log_info " create config files for icingaweb" 30 | 31 | if [[ $(grep -c "reporting" /etc/icingaweb2/resources.ini) -eq 0 ]] 32 | then 33 | cat << EOF >> /etc/icingaweb2/resources.ini 34 | 35 | [reporting] 36 | type = "db" 37 | db = "mysql" 38 | host = "${MYSQL_HOST}" 39 | port = 3306 40 | dbname = "reporting" 41 | username = "reporting" 42 | password = "${DATABASE_REPORTING_PASSWORD}" 43 | charset = "utf8mb4" 44 | 45 | EOF 46 | fi 47 | 48 | if [[ ! -f /etc/icingaweb2/modules/reporting/config.ini ]] 49 | then 50 | cat << EOF > /etc/icingaweb2/modules/reporting/config.ini 51 | 52 | [backend] 53 | resource = "reporting" 54 | EOF 55 | fi 56 | 57 | enable_module reporting 58 | 59 | log_info " run background deamon" 60 | /usr/bin/icingacli \ 61 | reporting \ 62 | schedule \ 63 | run & 64 | 65 | fi 66 | } 67 | 68 | create_database() { 69 | 70 | local database_name='reporting' 71 | local modules_directory="${ICINGAWEB_MODULES_DIRECTORY}/reporting" 72 | 73 | # check if database already created ... 74 | # 75 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = '${database_name}' limit 1;" 76 | 77 | database_status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w ) 78 | 79 | if [[ ${database_status} -eq 0 ]] 80 | then 81 | # Database isn't created 82 | # well, i do my job ... 83 | # 84 | log_info " - initializing databases" 85 | ( 86 | echo "--- create user 'reporting'@'%' IDENTIFIED BY '${DATABASE_REPORTING_PASSWORD}';" 87 | echo "CREATE DATABASE IF NOT EXISTS ${database_name} DEFAULT CHARACTER SET 'utf8mb4' COLLATE utf8mb4_bin;" 88 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'reporting'@'%' IDENTIFIED BY '${DATABASE_REPORTING_PASSWORD}';" 89 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'reporting'@'$(hostname -i)' IDENTIFIED BY '${DATABASE_REPORTING_PASSWORD}';" 90 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'reporting'@'$(hostname -s)' IDENTIFIED BY '${DATABASE_REPORTING_PASSWORD}';" 91 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'reporting'@'$(hostname -f)' IDENTIFIED BY '${DATABASE_REPORTING_PASSWORD}';" 92 | echo "quit" 93 | ) | mysql ${MYSQL_OPTS} 94 | 95 | SCHEMA_FILE="${modules_directory}/schema/mysql.sql" 96 | 97 | if [[ -f ${SCHEMA_FILE} ]] 98 | then 99 | log_info " - import database schema" 100 | 101 | mysql ${MYSQL_OPTS} --force ${database_name} < ${SCHEMA_FILE} 102 | 103 | if [[ $? -gt 0 ]] 104 | then 105 | log_error "can't insert the Database Schema" 106 | exit 1 107 | fi 108 | else 109 | log_warn "missing schema file" 110 | fi 111 | 112 | fi 113 | } 114 | 115 | check 116 | configure 117 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/skeleton: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | 7 | 8 | check() { 9 | log_info "check" 10 | } 11 | 12 | configure() { 13 | log_info "check" 14 | } 15 | 16 | create_database() { 17 | log_info "create_database" 18 | } 19 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/vspheredb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | . /init/output.sh 6 | . /init/common.sh 7 | 8 | log_info " vspheredb" 9 | 10 | DATABASE_VSPHEREDB_PASSWORD="vspheredb" 11 | 12 | check() { 13 | 14 | [[ -z "${MYSQL_OPTS}" ]] && exit 1 15 | 16 | if [[ "${ICINGAWEB_DIRECTOR}" = "false" ]] 17 | then 18 | log_info " director support is disabled" 19 | 20 | disable_module vspheredb 21 | exit 0 22 | fi 23 | } 24 | 25 | create_database() { 26 | 27 | local database_name='vspheredb' 28 | local modules_directory="${ICINGAWEB_MODULES_DIRECTORY}/vspheredb" 29 | 30 | # check if database already created ... 31 | # 32 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = '${database_name}' limit 1;" 33 | 34 | database_status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w ) 35 | 36 | if [[ ${database_status} -eq 0 ]] 37 | then 38 | # Database isn't created 39 | # well, i do my job ... 40 | # 41 | log_info " initializing databases" 42 | ( 43 | echo "--- create user 'vspheredb'@'%' IDENTIFIED BY '${DATABASE_VSPHEREDB_PASSWORD}';" 44 | echo "CREATE DATABASE IF NOT EXISTS ${database_name} DEFAULT CHARACTER SET 'utf8mb4' COLLATE utf8mb4_bin;" 45 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'vspheredb'@'%' IDENTIFIED BY '${DATABASE_VSPHEREDB_PASSWORD}';" 46 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'vspheredb'@'$(hostname -i)' IDENTIFIED BY '${DATABASE_VSPHEREDB_PASSWORD}';" 47 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'vspheredb'@'$(hostname -s)' IDENTIFIED BY '${DATABASE_VSPHEREDB_PASSWORD}';" 48 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'vspheredb'@'$(hostname -f)' IDENTIFIED BY '${DATABASE_VSPHEREDB_PASSWORD}';" 49 | echo "quit" 50 | ) | mysql ${MYSQL_OPTS} 51 | 52 | SCHEMA_FILE="${modules_directory}/schema/mysql.sql" 53 | 54 | if [[ -f ${SCHEMA_FILE} ]] 55 | then 56 | log_info " import database schema" 57 | 58 | mysql ${MYSQL_OPTS} --force ${database_name} < ${SCHEMA_FILE} 59 | 60 | if [[ $? -eq 0 ]] 61 | then 62 | 63 | log_info " import database migrations" 64 | for f in $(ls -1 ${modules_directory}/schema/mysql-migrations/*.sql) 65 | do 66 | log_info " apply database migration from '$(basename ${f})'" 67 | 68 | mysql ${MYSQL_OPTS} --force ${database_name} < ${f} 2> /dev/null 69 | 70 | if [[ $? -gt 0 ]] 71 | then 72 | log_error " database migration failed" 73 | exit 1 74 | fi 75 | done 76 | 77 | else 78 | log_error "can't insert the Database Schema" 79 | exit 1 80 | fi 81 | else 82 | log_warn "missing schema file" 83 | fi 84 | fi 85 | } 86 | 87 | configure() { 88 | 89 | #check 90 | 91 | #react="/usr/share/webapps/icingaweb2/modules/reactbundle" 92 | # 93 | #if [[ ! -e /usr/bin/composer ]] 94 | #then 95 | # log_error "missing composer!" 96 | # log_debug "read: https://gist.github.com/bodsch/4ea55240d7c4b0706d8504eba6b975fc" 97 | # 98 | # exit 1 99 | #else 100 | # cd ${react} 101 | # 102 | # /usr/bin/composer install 103 | #fi 104 | 105 | local vspheredb="${ICINGAWEB_MODULES_DIRECTORY}/vspheredb" 106 | 107 | # icingaweb vspheredb 108 | # 109 | if [[ -d ${vspheredb} ]] 110 | then 111 | #log_info "configure vspheredb" 112 | 113 | create_database 114 | 115 | log_info " create config files for icingaweb" 116 | 117 | if [[ $(grep -c "vspheredb]" /etc/icingaweb2/resources.ini) -eq 0 ]] 118 | then 119 | cat << EOF >> /etc/icingaweb2/resources.ini 120 | 121 | [vspheredb] 122 | type = "db" 123 | db = "mysql" 124 | host = "${MYSQL_HOST}" 125 | port = 3306 126 | dbname = "vspheredb" 127 | username = "vspheredb" 128 | password = "${DATABASE_VSPHEREDB_PASSWORD}" 129 | charset = "utf8mb4" 130 | 131 | EOF 132 | fi 133 | 134 | [[ -d /etc/icingaweb2/modules/vspheredb ]] || mkdir -p /etc/icingaweb2/modules/vspheredb 135 | 136 | # 137 | # 138 | if [[ ! -f /etc/icingaweb2/modules/vspheredb/config.ini ]] 139 | then 140 | cat << EOF > /etc/icingaweb2/modules/vspheredb/config.ini 141 | [db] 142 | resource = "vspheredb" 143 | EOF 144 | fi 145 | fi 146 | 147 | # enable module 148 | # 149 | enable_module vspheredb 150 | 151 | # icingacli vspheredb task initialize --serverId 1 152 | # icingacli vspheredb daemon run --trace --debug 153 | # icingacli vspheredb task sync --trace --debug --vCenterId 1 154 | 155 | nohup /init/runtime/watch_vspheredb.sh > /dev/stdout 2>&1 & 156 | 157 | 158 | # TODO check running process and restart them if needed 159 | # 160 | # 161 | 162 | # this produce the following 'error' 163 | # S erver for vCenterID=1 failed, will try again in 30 seconds 164 | # Server for vCenterID=2 failed, will try again in 30 seconds 165 | # and ist so not usable 166 | # see issue https://github.com/Icinga/icingaweb2-module-vspheredb/issues/80 167 | # 168 | #log_info " - run background deamon" 169 | #nohup /usr/bin/icingacli \ 170 | # vspheredb \ 171 | # daemon \ 172 | # run > /proc/self/fd/2 2>&1 & 173 | 174 | } 175 | 176 | check 177 | configure 178 | -------------------------------------------------------------------------------- /rootfs/init/modules.d/x509.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | CERTS_FILE=${CERTS_FILE:-"/etc/ssl/certs/ca-certificates.crt"} 6 | 7 | . /init/output.sh 8 | . /init/common.sh 9 | 10 | log_info " x509" 11 | 12 | DATABASE_X509_PASSWORD="x509" 13 | 14 | check() { 15 | 16 | [[ -z "${MYSQL_OPTS}" ]] && exit 1 17 | } 18 | 19 | configure() { 20 | 21 | local module_directory="${ICINGAWEB_MODULES_DIRECTORY}/x509" 22 | 23 | # icingaweb module_directory 24 | # 25 | if [[ -d ${module_directory} ]] 26 | then 27 | create_database 28 | 29 | [[ -d /etc/icingaweb2/modules/x509 ]] || mkdir -p /etc/icingaweb2/modules/x509 30 | 31 | log_info " create config files for icingaweb" 32 | 33 | if [[ $(grep -c "x509" /etc/icingaweb2/resources.ini) -eq 0 ]] 34 | then 35 | cat << EOF >> /etc/icingaweb2/resources.ini 36 | 37 | [x509] 38 | type = "db" 39 | db = "mysql" 40 | host = "${MYSQL_HOST}" 41 | port = 3306 42 | dbname = "x509" 43 | username = "x509" 44 | password = "${DATABASE_X509_PASSWORD}" 45 | charset = "utf8mb4" 46 | 47 | EOF 48 | fi 49 | 50 | if [[ ! -f /etc/icingaweb2/modules/x509/config.ini ]] 51 | then 52 | cat << EOF > /etc/icingaweb2/modules/x509/config.ini 53 | 54 | [backend] 55 | resource = "x509" 56 | EOF 57 | fi 58 | 59 | enable_module x509 60 | 61 | if [[ -f ${CERTS_FILE} ]] 62 | then 63 | log_info " import ca-certificates.crt" 64 | /usr/bin/icingacli x509 import --verbose --file ${CERTS_FILE} 65 | else 66 | log_error " no certificate file found" 67 | fi 68 | 69 | #log_info " enable module" 70 | #/usr/bin/icingacli module enable x509 71 | 72 | touch /etc/icingaweb2/modules/x509/jobs.ini 73 | 74 | if [[ -d /init/custom.d/x509 ]] && [[ -f /init/custom.d/x509/jobs.ini ]] 75 | then 76 | cat /init/custom.d/x509/jobs.ini >> /etc/icingaweb2/modules/x509/jobs.ini 77 | fi 78 | 79 | #log_info " run background deamon" 80 | /init/runtime/watch_x509.sh > /dev/stdout 2>&1 & 81 | 82 | sleep 2s 83 | 84 | log_info " run background deamon" 85 | /usr/bin/icingacli \ 86 | x509 \ 87 | jobs \ 88 | run & 89 | 90 | fi 91 | } 92 | 93 | create_database() { 94 | 95 | local database_name='x509' 96 | local modules_directory="/usr/share/webapps/icingaweb2/modules/x509" 97 | 98 | # check if database already created ... 99 | # 100 | query="SELECT TABLE_SCHEMA FROM information_schema.tables WHERE table_schema = '${database_name}' limit 1;" 101 | 102 | database_status=$(mysql ${MYSQL_OPTS} --batch --execute="${query}" | wc -w ) 103 | 104 | if [[ ${database_status} -eq 0 ]] 105 | then 106 | # Database isn't created 107 | # well, i do my job ... 108 | # 109 | log_info " initializing databases" 110 | ( 111 | echo "--- create user 'x509'@'%' IDENTIFIED BY '${DATABASE_X509_PASSWORD}';" 112 | echo "CREATE DATABASE IF NOT EXISTS ${database_name} DEFAULT CHARACTER SET 'utf8mb4' COLLATE utf8mb4_bin;" 113 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'x509'@'%' IDENTIFIED BY '${DATABASE_X509_PASSWORD}';" 114 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'x509'@'$(hostname -i)' IDENTIFIED BY '${DATABASE_X509_PASSWORD}';" 115 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'x509'@'$(hostname -s)' IDENTIFIED BY '${DATABASE_X509_PASSWORD}';" 116 | echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE VIEW, INDEX, EXECUTE ON ${database_name}.* TO 'x509'@'$(hostname -f)' IDENTIFIED BY '${DATABASE_X509_PASSWORD}';" 117 | echo "quit" 118 | ) | mysql ${MYSQL_OPTS} 119 | 120 | SCHEMA_FILE="${modules_directory}/etc/schema/mysql.schema.sql" 121 | 122 | if [[ -f ${SCHEMA_FILE} ]] 123 | then 124 | log_info " import database schema" 125 | 126 | mysql ${MYSQL_OPTS} --force ${database_name} < ${SCHEMA_FILE} 127 | 128 | if [[ $? -gt 0 ]] 129 | then 130 | log_error "can't insert the Database Schema" 131 | exit 1 132 | fi 133 | else 134 | log_warn "missing schema file" 135 | fi 136 | 137 | fi 138 | } 139 | 140 | check 141 | configure 142 | -------------------------------------------------------------------------------- /rootfs/init/output.sh: -------------------------------------------------------------------------------- 1 | 2 | RED='\033[38;5;202m' 3 | # GREEN='\033[38;5;70m' 4 | BLUE='\033[38;5;141m' 5 | # WHITE='\033[0;37m' 6 | NC='\033[0m' # No Color 7 | BOLD='\033[1m' 8 | 9 | log_output() { 10 | 11 | level="${1}" 12 | message="${2}" 13 | 14 | if [ -z "${level}" ] 15 | then 16 | printf "$(date +"[%Y-%m-%d %H:%M:%S]") %b\\n" "${message}" 17 | else 18 | printf "$(date +"[%Y-%m-%d %H:%M:%S]") %b %b\\n" "${level}" "${message}" 19 | fi 20 | } 21 | 22 | log_info() { 23 | message="${1}" 24 | log_output "" "${message}" 25 | } 26 | 27 | log_INFO() { 28 | message="${1}" 29 | log_output "" "${BOLD}${message}${NC}" 30 | } 31 | 32 | log_warn() { 33 | message="${1}" 34 | log_output "${BLUE}${BOLD}WARNING${NC}" "${message}" 35 | } 36 | 37 | log_WARN() { 38 | message="${1}" 39 | log_output "${RED}${BOLD}WARNING${NC}" "${RED}${BOLD}${message}${NC}" 40 | } 41 | 42 | log_error() { 43 | message="${1}" 44 | log_output "${RED}${BOLD}ERROR${NC}" "${message}" 45 | } 46 | 47 | log_debug() { 48 | message="${1}" 49 | log_output "${BOLD}DEBUG${NC}" "${message}" 50 | } 51 | -------------------------------------------------------------------------------- /rootfs/init/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | MYSQL_HOST=${MYSQL_HOST:-"database"} 6 | MYSQL_PORT=${MYSQL_PORT:-"3306"} 7 | MYSQL_ROOT_USER=${MYSQL_ROOT_USER:-"root"} 8 | MYSQL_ROOT_PASS=${MYSQL_ROOT_PASS:-""} 9 | MYSQL_OPTS= 10 | 11 | XDEBUG_ENABLED=${XDEBUG_ENABLED:-""} 12 | 13 | ICINGA2_API_PORT=${ICINGA2_API_PORT:-5665} 14 | ICINGA2_UPTIME=${ICINGA2_UPTIME:-125} 15 | 16 | ICINGAWEB_ADMIN_USER=${ICINGAWEB_ADMIN_USER:-"icinga"} 17 | ICINGAWEB_ADMIN_PASS=${ICINGAWEB_ADMIN_PASS:-"icinga"} 18 | 19 | export ICINGAWEB_DIRECTOR=${ICINGAWEB_DIRECTOR:-"true"} 20 | 21 | export ICINGAWEB_MODULES_DIRECTORY=/usr/share/webapps/icingaweb2/modules 22 | 23 | . /init/output.sh 24 | 25 | # ------------------------------------------------------------------------------------------------- 26 | 27 | if [[ -z ${MYSQL_HOST} ]] 28 | then 29 | log_error "no MYSQL_HOST set ..." 30 | exit 1 31 | else 32 | MYSQL_OPTS= 33 | MYSQL_OPTS="${MYSQL_OPTS} --host=${MYSQL_HOST}" 34 | MYSQL_OPTS="${MYSQL_OPTS} --port=${MYSQL_PORT}" 35 | MYSQL_OPTS="${MYSQL_OPTS} --user=${MYSQL_ROOT_USER}" 36 | MYSQL_OPTS="${MYSQL_OPTS} --password=${MYSQL_ROOT_PASS}" 37 | export MYSQL_OPTS 38 | fi 39 | 40 | # ------------------------------------------------------------------------------------------------- 41 | 42 | prepare() { 43 | 44 | for p in HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy 45 | do 46 | unset "${p}" 47 | done 48 | 49 | MYSQL_ICINGAWEB2_PASSWORD=icingaweb2 50 | 51 | touch /etc/icingaweb2/resources.ini 52 | touch /etc/icingaweb2/roles.ini 53 | 54 | if [[ -n "$XDEBUG_ENABLED" ]] && [[ -f /usr/lib/php7/modules/xdebug.so ]] 55 | then 56 | log_info "Enabling xdebug" 57 | cp /etc/php7/conf.d/ext-xdebug.ini.disabled /etc/php7/conf.d/xdebug.ini 58 | 59 | cat << EOF >> /etc/php7/conf.d/xdebug.ini 60 | 61 | [Xdebug] 62 | xdebug.remote_enable=true 63 | xdebug.remote_connect_back=true 64 | xdebug.profiler_enable=0 65 | xdebug.profiler_output_dir=/tmp/profile 66 | xdebug.profiler_enable_trigger=1 67 | EOF 68 | fi 69 | } 70 | 71 | 72 | correct_rights() { 73 | 74 | chmod 1777 /tmp 75 | chmod 2770 /etc/icingaweb2 76 | 77 | chown root:nginx /etc/icingaweb2 78 | chown -R nginx:nginx /etc/icingaweb2/* 79 | 80 | find /etc/icingaweb2 -type f -name "*.ini" -exec chmod 0660 {} \; 81 | find /etc/icingaweb2 -type d -exec chmod 2770 {} \; 82 | 83 | chown nginx:nginx /var/log/icingaweb2 84 | } 85 | 86 | # side channel to inject some wild-style customized scripts 87 | # 88 | custom_scripts() { 89 | 90 | if [[ -d /init/custom.d ]] 91 | then 92 | for f in /init/custom.d/* 93 | do 94 | case "$f" in 95 | *.sh) 96 | log_WARN "------------------------------------------------------" 97 | log_WARN "RUN SCRIPT: ${f}" 98 | log_WARN "YOU SHOULD KNOW WHAT YOU'RE DOING." 99 | log_WARN "THIS CAN BREAK THE COMPLETE ICINGA2 CONFIGURATION!" 100 | nohup "${f}" > /proc/self/fd/2 2>&1 & 101 | log_WARN "------------------------------------------------------" 102 | ;; 103 | *) 104 | log_warn "ignoring file ${f}" 105 | ;; 106 | esac 107 | echo 108 | done 109 | fi 110 | } 111 | 112 | 113 | configure_modules() { 114 | 115 | log_info "configure modules" 116 | 117 | [[ -e /etc/icingaweb2/enabledModules/reactbundle ]] || ln -s /usr/share/webapps/icingaweb2/modules/reactbundle /etc/icingaweb2/enabledModules/ 118 | [[ -e /etc/icingaweb2/enabledModules/incubator ]] || ln -s /usr/share/webapps/icingaweb2/modules/incubator /etc/icingaweb2/enabledModules/ 119 | [[ -e /etc/icingaweb2/enabledModules/ipl ]] || ln -s /usr/share/webapps/icingaweb2/modules/ipl /etc/icingaweb2/enabledModules/ 120 | 121 | if [[ -d /init/modules.d ]] 122 | then 123 | for f in /init/modules.d/* 124 | do 125 | case "$f" in 126 | *.sh) 127 | if [[ -x ${f} ]] 128 | then 129 | # log_debug "execute file: $(basename ${f})" 130 | ${f} # > /proc/self/fd/2 2>&1 131 | sleep 1s 132 | else 133 | log_warn "file '${f}' is not executable" 134 | fi 135 | ;; 136 | *) 137 | # log_warn "ignoring file ${f}" 138 | ;; 139 | esac 140 | done 141 | fi 142 | } 143 | 144 | run() { 145 | 146 | prepare 147 | 148 | . /init/database/mysql.sh 149 | 150 | . /init/wait_for/icinga_master.sh 151 | . /init/create_login_users.sh 152 | 153 | configure_modules 154 | correct_rights 155 | 156 | /usr/sbin/php-fpm7 \ 157 | --fpm-config /etc/php7/php-fpm.conf \ 158 | --pid /run/php-fpm.pid \ 159 | --allow-to-run-as-root \ 160 | --force-stderr \ 161 | --nodaemonize > /proc/self/fd/1 2>&1 & 162 | 163 | /usr/sbin/nginx > /proc/self/fd/1 2>&1 164 | } 165 | 166 | run 167 | 168 | # EOF 169 | -------------------------------------------------------------------------------- /rootfs/init/runtime/watch_vspheredb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # watch database to detect configured vcenter instances 4 | # run 'icingacli vspheredb task initialize ...' and 5 | # 'icingacli vspheredb task sync' manually 6 | # 7 | 8 | . /init/output.sh 9 | . /init/ini_parser.sh 10 | 11 | monitored_directory="/etc/icingaweb2/modules/vspheredb" 12 | hostname_f=$(hostname -f) 13 | 14 | database_cnf="${monitored_directory}/.my.cnf" 15 | 16 | finish() { 17 | 18 | rv=$? 19 | echo -e "\033[38;5;202m\033[1mexit with signal '${rv}'\033[0m" 20 | 21 | pids=$(ps aux | grep -v grep | grep "Icinga::vSphereDB::sync" | awk '{print $1}') 22 | 23 | for p in ${pids} 24 | do 25 | kill -15 ${p} 26 | rm -f "/tmp/vspheredb_*_sync.lock" 27 | done 28 | 29 | exit $rv 30 | } 31 | 32 | trap finish KILL # SIGINT SIGTERM INT TERM EXIT 33 | 34 | clean_sync_tasks() { 35 | 36 | local pids=${1} 37 | local db_data=${2} 38 | 39 | arr_pids=($pids) 40 | arr_dba=($db_data) 41 | 42 | for i in ${arr_dba[@]} 43 | do 44 | # log_debug "search ${i}" 45 | 46 | pid=$(ps aux | grep -v grep | grep $i | awk '{print $1}') 47 | 48 | if [[ " ${arr_pids[@]} " =~ " ${pid} " ]] 49 | then 50 | for x in ${!arr_pids[@]} 51 | do 52 | if [ "${arr_pids[$x]}" == "${pid}" ] 53 | then 54 | unset arr_pids[$x] 55 | fi 56 | done 57 | fi 58 | done 59 | 60 | for i in ${arr_pids[@]} 61 | do 62 | missing=$(ps ax -o pid,args | grep -v grep | grep ${i} | cut -d "(" -f2 | cut -d ")" -f1) 63 | log_info "remove sync task for ${missing} (pid: ${i})" 64 | kill -15 ${i} 65 | done 66 | 67 | #set +x 68 | } 69 | 70 | 71 | create_secrets_file() { 72 | 73 | if [[ ! -f "${database_cnf}" ]] 74 | then 75 | # log_info " read database resource ..." 76 | cfg_parser '/etc/icingaweb2/resources.ini' 77 | cfg_section_vspheredb 78 | 79 | dba_name="${dbname}" 80 | dba_host="${host}" 81 | dba_username="${username}" 82 | dba_password="${password}" 83 | 84 | cat << EOF >> ${database_cnf} 85 | [client] 86 | host=${dba_host} 87 | database=${dba_name} 88 | user=${dba_username} 89 | password=${dba_password} 90 | EOF 91 | 92 | fi 93 | } 94 | 95 | 96 | vspheredb_handler() { 97 | 98 | while true 99 | do 100 | # clean up old sync tasks 101 | # 102 | pids=$(ps aux | grep -v grep | grep "Icinga::vSphereDB::sync" | awk '{print $1}') 103 | 104 | data=$(mysql \ 105 | --defaults-file=${database_cnf} \ 106 | --skip-column-names \ 107 | --silent \ 108 | "--execute=SELECT JSON_OBJECT( 'host', host ) from vcenter_server;") 109 | 110 | if ( [[ ! -z "${pids}" ]] || [[ ! -z "${data}" ]] ) && ( [[ $(echo "${pids}" | wc -l) -gt $(echo "${data}" | jq '.host' | wc -l) ]] ) 111 | then 112 | # log_debug "data: '${data}' $(echo "${data}" | jq '.host' | wc -l) " 113 | 114 | clean_sync_tasks "${pids}" "${data}" 115 | fi 116 | 117 | # get data from database 118 | # 119 | while read -r line 120 | do 121 | id=$(echo "${line}" | awk '{print $1}') 122 | vcenter_id=$(echo "${line}" | awk '{print $2}') 123 | host=$(echo "${line}" | awk '{print $3}') 124 | 125 | if [[ -z ${id} ]] || [[ -z ${vcenter_id} ]] 126 | then 127 | continue 128 | fi 129 | 130 | # log_debug " vspheredb: host: '${host}' / id: '${id}' / vcenter_id: '${vcenter_id}'" 131 | 132 | if [[ "${vcenter_id}" = "NULL" ]] 133 | then 134 | log_info " - run initialize task for ${host}" 135 | /usr/bin/icingacli vspheredb task initialize --serverId ${id} 136 | else 137 | 138 | lockfile="/tmp/vspheredb_${host}_sync.lock" 139 | pid=$(ps aux | grep -v grep | grep "Icinga::vSphereDB::sync" | grep ${host} | awk '{print $1}') 140 | 141 | if [[ ! -e "${lockfile}" ]] && [[ -z ${pid} ]] 142 | then 143 | ( 144 | log_info " - run sync task for ${host}" 145 | touch ${lockfile} 146 | /usr/bin/icingacli vspheredb task sync --vCenterId ${vcenter_id} 147 | 148 | # log_debug " - remove lockfile ${lockfile}" 149 | rm -f ${lockfile} 150 | ) & 151 | fi 152 | fi 153 | 154 | done< <(mysql \ 155 | --defaults-file=${database_cnf} \ 156 | --skip-column-names \ 157 | --silent \ 158 | --execute="select id, vcenter_id, host from vcenter_server order by id;") 159 | 160 | sleep 1m 161 | done 162 | } 163 | 164 | 165 | run() { 166 | 167 | log_info " start the vspheredb monitor" 168 | 169 | create_secrets_file 170 | 171 | vspheredb_handler 172 | } 173 | 174 | run 175 | -------------------------------------------------------------------------------- /rootfs/init/runtime/watch_x509.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # use inotify to detect changes in the ${monitored_directory} and sync 4 | # changes to ${backup_directory} 5 | # when a 'delete' event is triggerd, the file/directory will also removed 6 | # from ${backup_directory} 7 | # 8 | # 9 | 10 | . /init/output.sh 11 | 12 | monitored_directory="/etc/icingaweb2/modules/x509" 13 | hostname_f=$(hostname -f) 14 | 15 | log_info " start the x509 monitor" 16 | 17 | CNT=0 18 | 19 | while read path action file 20 | do 21 | [[ -z "${file}" ]] && continue 22 | [[ ${path} =~ backup ]] && continue 23 | 24 | # log_debug "x509 monitor - The file '$file' appeared in directory '$path' via '$action' (${CNT})" 25 | 26 | if [[ "${action}" = "CLOSE_WRITE,CLOSE" ]] && [[ "${file}" = "jobs.ini" ]] 27 | then 28 | ((CNT++)) 29 | for i in $(grep "\[" ${monitored_directory}/jobs.ini) 30 | do 31 | job=$(echo $i | sed -e 's|\[||' -e 's|\]||') 32 | log_info " scan x509 job ${job}" 33 | /usr/bin/icingacli x509 scan --job ${job} 34 | 35 | if [[ $(ps -ef | grep -v grep | grep -c "icingacli x509 jobs run") -eq 0 ]] 36 | then 37 | /usr/bin/icingacli \ 38 | x509 \ 39 | jobs \ 40 | run & 41 | fi 42 | 43 | done 44 | fi 45 | 46 | done < <(inotifywait \ 47 | --monitor \ 48 | --event close_write \ 49 | --event modify \ 50 | ${monitored_directory}) 51 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/dns.sh: -------------------------------------------------------------------------------- 1 | 2 | wait_for_dns() { 3 | 4 | local server=${1} 5 | local max_retry=${2:-9} 6 | local retry=0 7 | local host= 8 | 9 | log_info "check if a DNS record for '${server}' is available" 10 | 11 | until ( [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] ) 12 | do 13 | # icinga2-master.matrix.lan has address 172.23.0.3 14 | # Host icinga2-master-fail not found: 3(NXDOMAIN) 15 | host=$(host ${server} 2> /dev/null) 16 | 17 | if [[ -z "${host}" ]] || [[ $(echo -e "${host}" | grep -c "has address") -eq 0 ]] 18 | then 19 | retry=$(expr ${retry} + 1) 20 | log_info " wait for a valid dns record (${retry}/${max_retry})" 21 | sleep 10s 22 | else 23 | break 24 | fi 25 | done 26 | 27 | if [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] 28 | then 29 | log_error "a DNS record for '${server}' could not be determined." 30 | log_error "$(host ${server})" 31 | exit 1 32 | fi 33 | } 34 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/grafana.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for grafana 3 | # 4 | wait_for_grafana() { 5 | 6 | . /init/wait_for/dns.sh 7 | . /init/wait_for/port.sh 8 | 9 | wait_for_dns ${GRAFANA_HOST} 10 | wait_for_port ${GRAFANA_HOST} ${GRAFANA_PORT} 15 11 | 12 | sleep 2s 13 | } 14 | 15 | wait_for_grafana 16 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/icinga_master.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for the Icinga2 Master 3 | # 4 | wait_for_icinga_master() { 5 | 6 | if [[ -z "${ICINGA2_MASTER}" ]] 7 | then 8 | log_error "ICINGA2_MASTER isn't set" 9 | exit 1 10 | fi 11 | 12 | log_info "wait for icinga2 master '${ICINGA2_MASTER}'" 13 | 14 | . /init/wait_for/dns.sh 15 | . /init/wait_for/port.sh 16 | 17 | wait_for_dns ${ICINGA2_MASTER} 18 | wait_for_port ${ICINGA2_MASTER} 5665 50 19 | 20 | if [[ "${ICINGAWEB_DIRECTOR}" == "true" ]] 21 | then 22 | 23 | log_info "For a clean director configuration, the Icinga2 Master must run for at least ${ICINGA2_UPTIME} seconds without interruption." 24 | 25 | RETRY=50 26 | 27 | until [[ ${RETRY} -le 0 ]] 28 | do 29 | code=$(curl \ 30 | --silent \ 31 | --user ${ICINGA2_CMD_API_USER}:${ICINGA2_CMD_API_PASS} \ 32 | --header 'Accept: application/json' \ 33 | --insecure \ 34 | https://${ICINGA2_MASTER}:5665/v1/status/CIB) 35 | 36 | if [[ $? -eq 0 ]] 37 | then 38 | uptime=$(echo "${code}" | jq --raw-output ".results[].status.uptime") 39 | 40 | utime=${uptime%.*} 41 | 42 | if [[ ${utime} -gt ${ICINGA2_UPTIME} ]] 43 | then 44 | break 45 | else 46 | sleep 20s 47 | RETRY=$(expr ${RETRY} - 1) 48 | fi 49 | else 50 | sleep 10s 51 | RETRY=$(expr ${RETRY} - 1) 52 | fi 53 | done 54 | 55 | sleep 5s 56 | 57 | log_info "The icinga2 master '${ICINGA2_MASTER}' seems to be available stable" 58 | fi 59 | } 60 | 61 | wait_for_icinga_master 62 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/mysql.sh: -------------------------------------------------------------------------------- 1 | 2 | # wait for mariadb / mysql 3 | # 4 | wait_for_database() { 5 | 6 | . /init/wait_for/dns.sh 7 | . /init/wait_for/port.sh 8 | 9 | wait_for_dns ${MYSQL_HOST} 10 | wait_for_port ${MYSQL_HOST} ${MYSQL_PORT} 15 11 | 12 | sleep 2s 13 | 14 | RETRY=10 15 | 16 | # must start initdb and do other jobs well 17 | # 18 | until [[ ${RETRY} -le 0 ]] 19 | do 20 | mysql ${MYSQL_OPTS} --execute="select 1 from mysql.user limit 1" > /dev/null 21 | 22 | [[ $? -eq 0 ]] && break 23 | 24 | log_info "wait for the database for her initdb and all other jobs" 25 | sleep 13s 26 | RETRY=$(expr ${RETRY} - 1) 27 | done 28 | 29 | sleep 2s 30 | } 31 | 32 | wait_for_database 33 | -------------------------------------------------------------------------------- /rootfs/init/wait_for/port.sh: -------------------------------------------------------------------------------- 1 | 2 | wait_for_port() { 3 | 4 | local server=${1} 5 | local port=${2} 6 | local max_retry=${3:-30} 7 | local retry=0 8 | 9 | log_info "check if the port ${port} for '${server}' is available" 10 | 11 | until [[ ${max_retry} -lt ${retry} ]] 12 | do 13 | # -v Verbose 14 | # -w secs Timeout for connects and final net reads 15 | # -X proto Proxy protocol: "4", "5" (SOCKS) or "connect" 16 | # 17 | status=$(nc -v -w1 -X connect ${server} ${port} 2>&1 > /dev/null) 18 | 19 | #log_debug "'${status}'" 20 | 21 | if [[ $(echo "${status}" | grep -c succeeded) -eq 1 ]] 22 | then 23 | break 24 | else 25 | retry=$(expr ${retry} + 1) 26 | log_info " wait for an open port (${retry}/${max_retry})" 27 | sleep 10s 28 | fi 29 | done 30 | 31 | if [[ ${retry} -eq ${max_retry} ]] || [[ ${retry} -gt ${max_retry} ]] 32 | then 33 | log_error "could not connect to '${server}'" 34 | exit 1 35 | fi 36 | } 37 | -------------------------------------------------------------------------------- /tests/input-raw-tcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "configuration" : { 3 | "bind_address" : "0.0.0.0", 4 | "port" : 5555 5 | }, 6 | "title" : "Raw/Plaintext TCP", 7 | "type" : "org.graylog2.inputs.raw.tcp.RawTCPInput", 8 | "global" : true 9 | } 10 | -------------------------------------------------------------------------------- /tests/input-syslog-tcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "type" : "org.graylog2.inputs.syslog.tcp.SyslogTCPInput", 3 | "global" : true, 4 | "configuration" : { 5 | "port" : 514, 6 | "bind_address" : "0.0.0.0" 7 | }, 8 | "title" : "Syslog TCP" 9 | } 10 | -------------------------------------------------------------------------------- /tests/integration_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | 6 | CURL=$(which curl 2> /dev/null) 7 | NC=$(which nc 2> /dev/null) 8 | NC_OPTS="-z" 9 | 10 | inspect() { 11 | 12 | echo "" 13 | echo "inspect needed containers" 14 | for d in $(docker ps | tail -n +2 | awk '{print($1)}') 15 | do 16 | # docker inspect --format "{{lower .Name}}" ${d} 17 | c=$(docker inspect --format '{{with .State}} {{$.Name}} has pid {{.Pid}} {{end}}' ${d}) 18 | s=$(docker inspect --format '{{json .State.Health }}' ${d} | jq --raw-output .Status) 19 | 20 | printf "%-40s - %s\n" "${c}" "${s}" 21 | done 22 | } 23 | 24 | 25 | wait_for_icingaweb() { 26 | 27 | echo -e "\nwait for icingaweb" 28 | RETRY=35 29 | 30 | until [[ ${RETRY} -le 0 ]] 31 | do 32 | timeout 1 bash -c "cat < /dev/null > /dev/tcp/localhost/443" 2> /dev/null 33 | if [ $? -eq 0 ] 34 | then 35 | break 36 | else 37 | sleep 10s 38 | RETRY=$(expr ${RETRY} - 1) 39 | fi 40 | done 41 | 42 | # until [[ ${RETRY} -le 0 ]] 43 | # do 44 | # ${NC} ${NC_OPTS} localhost 80 < /dev/null > /dev/null 45 | # 46 | # [[ $? -eq 0 ]] && break 47 | # 48 | # sleep 10s 49 | # RETRY=$((expr RETRY - 1)) 50 | # done 51 | 52 | if [[ $RETRY -le 0 ]] 53 | then 54 | echo "could not connect to icingaweb" 55 | exit 1 56 | fi 57 | echo "" 58 | # sleep 2s 59 | } 60 | 61 | 62 | head() { 63 | 64 | curl \ 65 | --insecure \ 66 | --location \ 67 | https://localhost/icinga/authentication/login?_checkCookie=1 68 | } 69 | 70 | 71 | 72 | running_containers=$(docker ps | tail -n +2 | wc -l) 73 | 74 | if [[ ${running_containers} -eq 5 ]] || [[ ${running_containers} -gt 4 ]] 75 | then 76 | inspect 77 | 78 | wait_for_icingaweb 79 | 80 | head 81 | 82 | exit 0 83 | else 84 | echo "the test setup needs 4 containers" 85 | echo "only ${running_containers} running" 86 | echo "please run " 87 | echo " make compose-file" 88 | echo " docker-compose up -d" 89 | echo "before" 90 | echo "or check your system" 91 | 92 | exit 1 93 | fi 94 | 95 | 96 | -------------------------------------------------------------------------------- /tests/linter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HADOLINT_VERSION='1.16.3' 4 | HADOLINT_PATH='/usr/local/bin/hadolint' 5 | 6 | if ! [[ -e "${HADOLINT_PATH}_${HADOLINT_VERSION}" ]] 7 | then 8 | sudo curl \ 9 | --silent \ 10 | --location \ 11 | --output "${HADOLINT_PATH}_${HADOLINT_VERSION}" \ 12 | "https://github.com/hadolint/hadolint/releases/download/v${HADOLINT_VERSION}/hadolint-Linux-x86_64" 13 | sudo chmod +x "${HADOLINT_PATH}_${HADOLINT_VERSION}" 14 | sudo ln -sf ${HADOLINT_PATH}_${HADOLINT_VERSION} ${HADOLINT_PATH} 15 | fi 16 | 17 | hadolint Dockerfile 18 | 19 | shellcheck \ 20 | --external-sources \ 21 | --shell=bash \ 22 | --exclude=SC1091,SC2034 \ 23 | rootfs/init/run.sh 24 | --------------------------------------------------------------------------------