From 6f459df0f21a9550170c3dccebe8afba023d23a9 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sat, 7 Jul 2018 13:38:51 +0200 Subject: [PATCH] Initial version based on LibreNMS 1.41 --- .dockerignore | 13 ++ .editorconfig | 19 ++ .gitignore | 6 + .res/docker-librenms.jpg | Bin 0 -> 58044 bytes .res/paypal.png | Bin 0 -> 7643 bytes .travis.yml | 59 +++++++ CHANGELOG.md | 5 + Dockerfile | 62 +++++++ LICENSE | 21 +++ README.md | 183 +++++++++++++++++++ assets/etc/php7/conf.d/sendmail-ssmtp.ini | 1 + assets/etc/supervisord.conf | 21 +++ assets/etc/supervisord/nginx.conf | 8 + assets/etc/supervisord/php.conf | 8 + assets/etc/supervisord/snmpd.conf | 7 + assets/tpls/etc/nginx/nginx.conf | 88 ++++++++++ assets/tpls/etc/php7/conf.d/opcache.ini | 7 + assets/tpls/etc/php7/php-fpm.d/www.conf | 28 +++ assets/usr/local/bin/cron | 5 + entrypoint.sh | 205 ++++++++++++++++++++++ examples/compose/docker-compose.yml | 97 ++++++++++ examples/compose/librenms.env | 23 +++ 22 files changed, 866 insertions(+) create mode 100644 .dockerignore create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .res/docker-librenms.jpg create mode 100644 .res/paypal.png create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 assets/etc/php7/conf.d/sendmail-ssmtp.ini create mode 100644 assets/etc/supervisord.conf create mode 100644 assets/etc/supervisord/nginx.conf create mode 100644 assets/etc/supervisord/php.conf create mode 100644 assets/etc/supervisord/snmpd.conf create mode 100644 assets/tpls/etc/nginx/nginx.conf create mode 100644 assets/tpls/etc/php7/conf.d/opcache.ini create mode 100644 assets/tpls/etc/php7/php-fpm.d/www.conf create mode 100644 assets/usr/local/bin/cron create mode 100644 entrypoint.sh create mode 100644 examples/compose/docker-compose.yml create mode 100644 examples/compose/librenms.env diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..617e694 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +/.dev +/.idea +/*.iml + +/.git +/.res +/examples +/.editorconfig +/.gitignore +/.travis.yml +/CHANGELOG.md +/LICENSE +/README.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..acb43f7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{Dockerfile,*.sh,*.yml}] +indent_size = 2 + +[assets/**] +insert_final_newline = false + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98df5db --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Jetbrains +/.idea +/*.iml + +# App +/.dev diff --git a/.res/docker-librenms.jpg b/.res/docker-librenms.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a2bed3a317369015474b1caa00d2b56e37848abc GIT binary patch literal 58044 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 literal 0 HcmV?d00001 diff --git a/.res/paypal.png b/.res/paypal.png new file mode 100644 index 0000000000000000000000000000000000000000..76842ea133ed15c15ee904594e6b50500def29a8 GIT binary patch literal 7643 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 JPDHLkV1mzqba4Ox literal 0 HcmV?d00001 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..27b4cb7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,59 @@ +sudo: required + +services: + - docker + +env: + global: + - VERSION=1.41 + - GITHUB_REPO=crazy-max/docker-librenms + - DOCKER_USERNAME=crazymax + - DOCKER_REPONAME=librenms + - QUAY_USERNAME=crazymax + - QUAY_REPONAME=librenms + - secure: GMYFptO3rWVVITjC0Wz8g9uccBjSMBvVt3aFC3Y08/3Hw9CoA/SS51X/2lh0bRn+y49X0742QC7b2LtSWa3eERM1HbzlS1ODK75+P0lGYdtW2Ng5JutI+GRt8xTouY7+iP4qSAbOYMUdM5e61PkRepJvZWVeBkPtAtcGpxZO75h+snFxuzFVZXWLoSKjByKIqy9VXzT2P0Wx+zuUWpeo2qA62ONRJf5RjIKCDxHmWEwhXKmmDjeqo+Db/zsUwGYSwKpKRGBhyPVP0MnKFA2HQ/+dG1NyikXhae5dhjaZvgG9tSpbYdOWCHCunbxm6VWozt/kvkqkbizn+S3aoeeZyco40ZFIUinpypxw/nZpVvfDkwBIhw3nOS4giMKHLLBtnkSZw2szP6zfdLX6MLKWSjcDsBbtqj8aNe8Z1ViEKc2uW+yqJvd6GNnDL+AINe5rJ/cjeseh1ancOaGG8tlGsg/80dhOV3l+E4nINn+1uj354ncH/lv14e4giDNMGRw8gq7HFWxIE1X8SLetK9Hz5kLyMIPlSCO2fL73adrqfJFFluTQ0CbzsOEHSuScHT8i9UJWrqcu25BQ4pKidmDAt0gT7x6cz7zziuTY0hTO05txIP0FCop0qCFoLuAGM/bQg8r6FnfIZu4NbUxutjLiAN5aMB1D3znnymxKdeX/HOc= # DOCKER_PASSWORD + - secure: XMkF9Nz6FjKVB52vv7rZ+fa7vDDRXG7/nDm5Wio4eljYU/+cIZwdbBv2hU2IEmherZBn2jO9V64LYR9yTLALOGMEjqE/0E8KNiibj7VRjeRmtQrTHbUj7XpBmqAVyNek2GxkmtS4meOIcUUxBOfCAiIu2b++iuR70rAHvr+dL8skX7FNG77ZgTRsP9VkCylyfw0qb+50pD+2ukOFHxZ4tSi89F8ZU4UQOiNTBre4NUPCN5DZmglSt4nUYt3iofKs9p4ZjPP0cTBpHhArn37VZJyo1tOcl1jP8x18PVvgxrHO8Z0FQCasnZ6O269FR8lF28yM4CwHxk6ufCuieCCj5f0ez6S8IEv82a8ljmw+a75Gb6+pAmYB8nY49VkrWmA6KoDY+F+Ob30QOOtLCGumGBLZ1++6MOtwFjN5BzAyVl3Qhl+9heUMM3ULkbEV0IGJHL1M3zEBqxkQO6urdgf6cPEf3uldd+T6Ochn2DZ42Ge+yiZiIrgF/p0R3l1vDbyBG6OcnmaEoQWdIgqa6DUV48MBkYHF9Sp0idUbsrOaoVNsZZ4h0P72fRci/rElvoDGJIAdFEEE1ZW/y3a6hJihxvYQM9+S+HvzluI+5SKzdFUJ4hRpaGfIvclKdyaCNSE1B0VrwGXn7pBt5tem0IZnE5BQ9d/6TgVFc+L2Eyf7Mck= # QUAY_PASSWORD + - secure: mLY2C4Ggmg/VUdWoYc8vqYQb7lLSSB/YMvKUzY+z8VGAi5A8J1A6oTgeeThiKPWaNp9GgU1hdHA5WqoSCuOk2SzJoIEhnPU0j3GkDknuXmbhU1UXsuefMF++v2J9RarmC2CkyGiBDzJCrcs9srcS6RjmbK7hQv5EsbkjjyQHQwZlMG+q2aUwNcNxhAeD0+gn8j6eZ6myxt/SJ3LZRLCb+ZpP1NITc6aHjC9glc6ZO7bTy6WG6SVg0SREdxbht+cUrTNQvAcIkoEZQ4vOJBi3kAo6aZz6QYglofaYpTCdmiSSFGHseJ7k1Dl+khCL8OqeOnVCOkcu8SgPV7tI6WId8Dky/YPUsFtjivJqekjs/ctAekOHTzJW9UeOLkCOiqeLmQTDQ01JDLno1znzMOTC3T96I5d2LUnob3QOu32chdzqw0LfcawcuNnLwLdbK4AwPcDuIUl6b1FjU6I8DckHjtvL9Mr9xLhIkNrhdPW0vAj8yZkvGCxvGXh+qK6ejNDt/RdH6wWojh1yTbJSCAQLo1WnJ5YpqLxtu5++/4PfiTLkt7u8QMnau5m+8wZ4ju2RfFrwmEaKkrZSkq7ViQ+RsI/y0bNxUzk3Bb02Wgh9MfpPUXLA+4llYWIPnbgL17N5zhsROp9u0YSbzc3cWJm+0TQZZ0hAjyXBDoT2UCsDNqE= # GITHUB_TOKEN + +before_install: + - sudo apt-get update + - docker --version + - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + - export DOCKER_TAG=$(if [ "$BRANCH" == "master" ]; then echo "latest"; else echo $BRANCH; fi) + - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH, DOCKER_TAG=$DOCKER_TAG" + +install: + - | + docker build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ + --build-arg VCS_REF=${TRAVIS_COMMIT::8} \ + --build-arg VERSION=${VERSION} \ + -t $DOCKER_USERNAME/$DOCKER_REPONAME . + +before_script: + - docker network create -d bridge $DOCKER_REPONAME + - docker run -d --network=$DOCKER_REPONAME --name db mariadb:10.2 + - docker run -d --network=$DOCKER_REPONAME --link db -p 8000:80 -e "DB_HOST=db" --name $DOCKER_REPONAME $DOCKER_USERNAME/$DOCKER_REPONAME + - sleep 20 + - docker logs $DOCKER_REPONAME + +script: + - docker ps | grep $DOCKER_REPONAME + +after_success: + - test $TRAVIS_PULL_REQUEST = false + && echo "$DOCKER_PASSWORD" | docker login --username "$DOCKER_USERNAME" --password-stdin + && docker tag $DOCKER_USERNAME/$DOCKER_REPONAME $DOCKER_USERNAME/$DOCKER_REPONAME:$DOCKER_TAG + && docker tag $DOCKER_USERNAME/$DOCKER_REPONAME $DOCKER_USERNAME/$DOCKER_REPONAME:$VERSION + && docker push $DOCKER_USERNAME/$DOCKER_REPONAME + && echo "$QUAY_PASSWORD" | docker login quay.io --username "$QUAY_USERNAME" --password-stdin + && docker tag $DOCKER_USERNAME/$DOCKER_REPONAME quay.io/$DOCKER_USERNAME/$DOCKER_REPONAME:$DOCKER_TAG + && docker tag $DOCKER_USERNAME/$DOCKER_REPONAME quay.io/$DOCKER_USERNAME/$DOCKER_REPONAME:$VERSION + && docker push quay.io/$QUAY_USERNAME/$QUAY_REPONAME + +branches: + except: + - /^[0-9]/ + +notifications: + webhooks: + secure: qy/lFOFGeP0IMvDTJZmPemOtHjkpnYq4sm734rTjBsKFNA8MU4TyWCnx24hljRd4YazAkH6j2Uav3XfmnR+UGfutXRsmktzZoDTlygiJLP/026gvD+VuT8GZIFXRpYhNlfPemFoN2/wO5sf91JGQL4cxVcF9r1A0aUQUtAzvl9UKwk+DRc9Y78oCKRmIaeoFrvKE1SCGPf/drNYeLKJiRiq7VV5jL+1tmZUjYKWVYnWU3yYSyg3OdAvXAVEDagzvAQ0ors9UJeXxAsAls0kTQc8c2+uWfEH411sRrPuqTYYkXIPQpJszLeDhG0ISU5xs5UCJSi7QzTRxD5lWgn8C2QfGS8x3eQK8fHEfN1Q0frqGdCYJcEC2izs91bwZDmFmDj9B0mkuOyHDjWmTIo+HPkb/ryATFD3Bk2pekHWBkuq+KKTQzvgtgokp4V7xRumDh7htyYzr88uk1EQFR7VY05aWFGFsoZ13oKa4UQ4uglH2xmWVW3X9cyf5NCj/t4mUt5223ZM7Q+LKDONSPz/VEDlSOkPapjC4rpn6mn/k6FNN3UyC4hL9+HXSFyCOJZDy3P6lagCWWlzLxt0R4DnptZG+cShW0+bzcecEaGPjyEidACctKl3hfDCiblg05Js0lvW454C4TPnzZ/tDAE6VE8mCFtU/K1ur+wneZuOv2pA= diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cc352ba --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 1.41-RC1 (2018/07/07) + +* Initial version based on LibreNMS 1.41 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eb8387b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +FROM alpine:3.8 +MAINTAINER CrazyMax + +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION + +LABEL org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.name="librenms" \ + org.label-schema.description="LibreNMS based on Alpine Linux and Nginx" \ + org.label-schema.version=$VERSION \ + org.label-schema.url="https://github.com/crazy-max/docker-librenms" \ + org.label-schema.vcs-ref=$VCS_REF \ + org.label-schema.vcs-url="https://github.com/crazy-max/docker-librenms" \ + org.label-schema.vendor="CrazyMax" \ + org.label-schema.schema-version="1.0" + +RUN apk --update --no-cache add \ + binutils ca-certificates coreutils curl fping git graphviz imagemagick mtr mysql-client net-snmp net-snmp-tools \ + nginx nmap openssl python2 rrdtool runit shadow ssmtp supervisor tzdata util-linux whois \ + php7 php7-cli php7-ctype php7-curl php7-fpm php7-gd php7-json php7-mcrypt php7-memcached php7-mbstring php7-mysqli \ + php7-opcache php7-openssl php7-pdo php7-pdo_mysql php7-phar php7-posix php7-session php7-simplexml php7-snmp \ + php7-tokenizer php7-xml php7-zip \ + && sed -i -e "s/;date\.timezone.*/date\.timezone = UTC/" /etc/php7/php.ini \ + && cp -f /etc/ssmtp/ssmtp.conf /etc/ssmtp/ssmtp.conf.or \ + && rm -rf /var/cache/apk/* /var/www/* /tmp/* + +ENV LIBRENMS_VERSION="1.41" \ + LIBRENMS_PATH="/opt/librenms" \ + DATA_PATH="/data" \ + CRONTAB_PATH="/var/spool/cron/crontabs" + +RUN mkdir -p /opt \ + && addgroup -g 1000 librenms \ + && adduser -u 1000 -G librenms -h ${LIBRENMS_PATH} -s /sbin/nologin -D librenms \ + && usermod -a -G librenms nginx \ + && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer \ + && git clone --branch ${LIBRENMS_VERSION} https://github.com/librenms/librenms.git ${LIBRENMS_PATH} \ + && chown -R librenms. ${LIBRENMS_PATH} \ + && su - librenms -s /bin/sh -c "composer install --no-dev --no-interaction --no-ansi --working-dir=${LIBRENMS_PATH}" \ + && wget -q https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/distro -O /usr/bin/distro \ + && chmod +x /usr/bin/distro \ + && rm -rf /tmp/* + +ADD entrypoint.sh /entrypoint.sh +ADD assets / + +RUN mkdir -p /data ${LIBRENMS_PATH}/config.d /var/log/supervisord \ + && chmod a+x /entrypoint.sh \ + && cp ${LIBRENMS_PATH}/snmpd.conf.example /etc/snmp/snmpd.conf \ + && cp ${LIBRENMS_PATH}/config.php.default ${LIBRENMS_PATH}/config.php \ + && echo "foreach (glob(\"${DATA_PATH}/config/*.php\") as \$filename) include \$filename;" >> ${LIBRENMS_PATH}/config.php \ + && echo "foreach (glob(\"${LIBRENMS_PATH}/config.d/*.php\") as \$filename) include \$filename;" >> ${LIBRENMS_PATH}/config.php \ + && chown -R librenms. ${DATA_PATH} ${LIBRENMS_PATH} \ + && chown -R nginx. /var/lib/nginx /var/log/nginx /var/log/php7 /var/tmp/nginx + +EXPOSE 80 +WORKDIR ${LIBRENMS_PATH} +VOLUME [ "${DATA_PATH}" ] + +ENTRYPOINT [ "/entrypoint.sh" ] +CMD [ "/usr/bin/supervisord", "-c", "/etc/supervisord.conf" ] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..29b1e96 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 CrazyMax + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a636ff --- /dev/null +++ b/README.md @@ -0,0 +1,183 @@ +

+ +

+ Version + Build Status + Docker Stars + Docker Pulls + Docker Repository on Quay + Donate Paypal +

+ +## About + +🐳 [LibreNMS](https://www.librenms.org/) Docker image based on Alpine Linux and Nginx.
+If you are interested, [check out](https://hub.docker.com/r/crazymax/) my other 🐳 Docker images! + +## Features + +### Included + +* Alpine Linux 3.8, Nginx, PHP 7.2 +* Cron tasks as a ["sidecar" container](#cron) +* [SSMTP](https://linux.die.net/man/8/ssmtp) for SMTP relay to send emails +* OPCache enabled to store precompiled script bytecode in shared memory + +### From docker-compose + +* [Traefik](https://github.com/containous/traefik-library-image) as reverse proxy and creation/renewal of Let's Encrypt certificates +* [Memcached](https://github.com/docker-library/memcached) image ready to use for better scalability +* [RRDcached](https://github.com/crazy-max/rrdcached) image ready to use for better scalability +* [MariaDB](https://github.com/docker-library/mariadb) image as database instance +* Cron jobs as a ["sidecar" container](#cron) + +## Docker + +### Environment variables + +| Key | Default | Description +|-----------------------------|-------------------|------------------------------------------- +| `TZ` | `UTC` | Timezone (e.g. `Europe/Paris`) +| `PUID` | `1000` | LibreNMS user id +| `PGID` | `1000` | LibreNMS group id +| `MEMORY_LIMIT` | `256M` | PHP memory limit +| `UPLOAD_MAX_SIZE` | `16M` | Upload max size +| `OPCACHE_MEM_SIZE` | `128` | PHP OpCache memory consumption +| `LIBRENMS_POLLER_THREADS` | `16` | Threads that `poller-wrapper.py` runs +| `LIBRENMS_SNMP_COMMUNITY` | `librenmsdocker` | Your community string +| `DB_HOST` | | MySQL database hostname / IP address +| `DB_PORT` | `3306` | MySQL database port +| `DB_NAME` | `librenms` | MySQL database name +| `DB_USER` | `librenms` | MySQL user +| `DB_PASSWORD` | `librenms` | MySQL password +| `SSMTP_HOST` | | SMTP server host +| `SSMTP_PORT` | `25` | SMTP server port +| `SSMTP_HOSTNAME` | `$(hostname -f)` | Full hostname +| `SSMTP_USER` | | SMTP username +| `SSMTP_PASSWORD` | | SMTP password +| `SSMTP_TLS` | `NO` | SSL/TLS +| `MEMCACHED_HOST` | | Hostname / IP address of a Memcached server +| `RRDCACHED_HOST` | | Hostname / IP address of a RRDcached server + +### Volumes + +* `/data` : Contains configuration, rrd database, logs + +### Ports + +* `80` : HTTP port + +## Use this image + +### Docker Compose + +Docker compose is the recommended way to run this image. Copy the content of folder [examples/compose](examples/compose) in `/var/librenms/` on your host for example. Edit the compose and env files with your preferences and run the following commands : + +```bash +touch acme.json +chmod 600 acme.json +docker-compose up -d +docker-compose logs -f +``` + +### Command line + +You can also use the following minimal command : + +```bash +docker run -d -p 80:80 --name librenms \ + -v $(pwd)/data:/data \ + -e "DB_HOST=db" \ + crazymax/librenms:latest +``` + +> `-e "DB_HOST=db"` +> :warning: `db` must be a running MySQL instance + +## Notes + +### Edit configuration + +You can edit configuration of LibreNMS by placing `*.php` files inside `/data/config` folder. Let's say you want to edit the [WebUI config](https://docs.librenms.org/#Support/Configuration/#webui-settings). Create a file called for example `/data/config/webui.php` with this content : + +```php + `-v librenms:/data` +> :warning: `librenms` must be a valid volume already attached to a LibreNMS container + +## Upgrade + +To upgrade to the latest version of LibreNMS, pull the newer image and launch the container. LibreNMS will upgrade automatically : + +```bash +docker-compose pull +docker-compose up -d +``` + +## How can i help ? + +All kinds of contributions are welcomed :raised_hands:!
+The most basic way to show your support is to star :star2: the project, or to raise issues :speech_balloon:
+But we're not gonna lie to each other, I'd rather you buy me a beer or two :beers:! + +[![Paypal](.res/paypal.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=962TPYQKMQ2UE) + +## License + +MIT. See `LICENSE` for more details. diff --git a/assets/etc/php7/conf.d/sendmail-ssmtp.ini b/assets/etc/php7/conf.d/sendmail-ssmtp.ini new file mode 100644 index 0000000..6f1b45e --- /dev/null +++ b/assets/etc/php7/conf.d/sendmail-ssmtp.ini @@ -0,0 +1 @@ +sendmail_path=/usr/sbin/ssmtp -t diff --git a/assets/etc/supervisord.conf b/assets/etc/supervisord.conf new file mode 100644 index 0000000..90df761 --- /dev/null +++ b/assets/etc/supervisord.conf @@ -0,0 +1,21 @@ +[supervisord] +nodaemon = true +user = root +logfile = /var/log/supervisord/supervisord.log +pidfile = /var/run/supervisord.pid +childlogdir = /var/log/supervisord/ +logfile_maxbytes = 50MB +logfile_backups = 10 +loglevel = info + +[supervisorctl] +serverurl = unix:///var/run/supervisor.sock + +[unix_http_server] +file = /var/run/supervisor.sock + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[include] +files = /etc/supervisord/*.conf diff --git a/assets/etc/supervisord/nginx.conf b/assets/etc/supervisord/nginx.conf new file mode 100644 index 0000000..70a8762 --- /dev/null +++ b/assets/etc/supervisord/nginx.conf @@ -0,0 +1,8 @@ +[program:nginx] +command = /usr/sbin/nginx +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +autorestart = false +startentries = 0 diff --git a/assets/etc/supervisord/php.conf b/assets/etc/supervisord/php.conf new file mode 100644 index 0000000..8ef3a3b --- /dev/null +++ b/assets/etc/supervisord/php.conf @@ -0,0 +1,8 @@ +[program:php] +command = /usr/sbin/php-fpm7 +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +autorestart = false +startentries = 0 diff --git a/assets/etc/supervisord/snmpd.conf b/assets/etc/supervisord/snmpd.conf new file mode 100644 index 0000000..d3a1ef4 --- /dev/null +++ b/assets/etc/supervisord/snmpd.conf @@ -0,0 +1,7 @@ +[program:snmpd] +command = /usr/sbin/snmpd -f -c /etc/snmpd.conf +startentries = 0 +stdout_logfile = /proc/1/fd/1 +stdout_logfile_maxbytes = 0 +stderr_logfile = /proc/1/fd/2 +stderr_logfile_maxbytes = 0 \ No newline at end of file diff --git a/assets/tpls/etc/nginx/nginx.conf b/assets/tpls/etc/nginx/nginx.conf new file mode 100644 index 0000000..d3f22d8 --- /dev/null +++ b/assets/tpls/etc/nginx/nginx.conf @@ -0,0 +1,88 @@ +daemon off; +user nginx; +pid /run/nginx.pid; +worker_processes auto; +error_log /proc/1/fd/2 info; +worker_rlimit_nofile 8192; + +events { + worker_connections 2048; + use epoll; + multi_accept on; +} + +http { + include mime.types; + default_type application/octet-stream; + access_log /proc/1/fd/1; + + aio threads; + sendfile on; + + ## Timeouts + client_body_timeout 60; + client_header_timeout 60; + keepalive_timeout 10 10; + send_timeout 60; + + ## TCP options + tcp_nopush on; + tcp_nodelay on; + + ## Handling of IPs in proxied and load balancing situations + set_real_ip_from 0.0.0.0/32; + real_ip_header X-Forwarded-For; + + ## Hide the Nginx version number + server_tokens off; + + ## Body size + client_max_body_size @UPLOAD_MAX_SIZE@; + client_body_buffer_size 128k; + + ## Compression + gzip on; + gzip_buffers 16 8k; + gzip_comp_level 1; + gzip_http_version 1.1; + gzip_min_length 10; + gzip_types text/css application/javascript text/javascript application/x-javascript image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon; + gzip_vary on; + gzip_proxied any; + gzip_disable "msie6"; + + ## Serve already compressed files directly, bypassing on-the-fly compression + gzip_static on; + + ## FastCGI + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_buffers 256 4k; + fastcgi_intercept_errors on; + fastcgi_read_timeout 14400; + + server { + listen 80; + + root /opt/librenms/html; + index index.php; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location /api/v0 { + try_files $uri $uri/ /api_v0.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/var/run/php-fpm7.sock; + } + + location ~ /\.ht { + deny all; + } + } +} diff --git a/assets/tpls/etc/php7/conf.d/opcache.ini b/assets/tpls/etc/php7/conf.d/opcache.ini new file mode 100644 index 0000000..f6a74ca --- /dev/null +++ b/assets/tpls/etc/php7/conf.d/opcache.ini @@ -0,0 +1,7 @@ +opcache.enable=1 +opcache.enable_cli=1 +opcache.fast_shutdown=1 +opcache.memory_consumption=@OPCACHE_MEM_SIZE@ +opcache.interned_strings_buffer=16 +opcache.max_accelerated_files=10000 +opcache.revalidate_freq=60 diff --git a/assets/tpls/etc/php7/php-fpm.d/www.conf b/assets/tpls/etc/php7/php-fpm.d/www.conf new file mode 100644 index 0000000..ef857fe --- /dev/null +++ b/assets/tpls/etc/php7/php-fpm.d/www.conf @@ -0,0 +1,28 @@ +[global] +daemonize = no +error_log = /proc/self/fd/2 + +[www] +user = librenms +group = librenms + +listen = /run/php-fpm7.sock +listen.owner = librenms +listen.group = librenms + +pm = dynamic +pm.max_children = 15 +pm.start_servers = 2 +pm.min_spare_servers = 1 +pm.max_spare_servers = 6 +request_terminate_timeout = 0 + +; if we send this to /proc/self/fd/1, it never appears +access.log = /proc/self/fd/2 + +php_admin_value[post_max_size] = @UPLOAD_MAX_SIZE@ +php_admin_value[upload_max_filesize] = @UPLOAD_MAX_SIZE@ +php_admin_value[max_execution_time] = 10800 +php_admin_value[max_input_time] = 3600 +php_admin_value[expose_php] = Off +php_admin_value[memory_limit] = @MEMORY_LIMIT@ \ No newline at end of file diff --git a/assets/usr/local/bin/cron b/assets/usr/local/bin/cron new file mode 100644 index 0000000..53d6c2c --- /dev/null +++ b/assets/usr/local/bin/cron @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +exec busybox crond -f -L /dev/stdout diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..70fd7df --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,205 @@ +#!/bin/sh + +function runas_librenms() { + su - librenms -s /bin/sh -c "$1" +} + +TZ=${TZ:-"UTC"} +PUID=${PUID:-1000} +PGID=${PGID:-1000} + +MEMORY_LIMIT=${MEMORY_LIMIT:-"256M"} +UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE:-"16M"} +OPCACHE_MEM_SIZE=${OPCACHE_MEM_SIZE:-"128"} + +LIBRENMS_POLLER_THREADS=${LIBRENMS_POLLER_THREADS:-"16"} +LIBRENMS_SNMP_COMMUNITY=${LIBRENMS_SNMP_COMMUNITY:-"librenmsdocker"} + +DB_PORT=${DB_PORT:-"3306"} +DB_NAME=${DB_NAME:-"librenms"} +DB_USER=${DB_USER:-"librenms"} +DB_PASSWORD=${DB_PASSWORD:-"asupersecretpassword"} + +SSMTP_PORT=${SSMTP_PORT:-"25"} +SSMTP_HOSTNAME=${SSMTP_HOSTNAME:-"$(hostname -f)"} +SSMTP_TLS=${SSMTP_TLS:-"NO"} + +# Timezone +echo "Setting timezone to ${TZ}..." +ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime +echo ${TZ} > /etc/timezone +sed -i -e "s|date\.timezone.*|date\.timezone = ${TZ}|" /etc/php7/php.ini \ + +# Change librenms UID / GID +echo "Checking if librenms UID / GID has changed..." +if [ $(id -u librenms) != ${PUID} ]; then + usermod -u ${PUID} librenms +fi +if [ $(id -g librenms) != ${PGID} ]; then + groupmod -g ${PGID} librenms +fi + +# PHP +echo "Setting PHP-FPM configuration..." +sed -e "s/@MEMORY_LIMIT@/$MEMORY_LIMIT/g" \ + -e "s/@UPLOAD_MAX_SIZE@/$UPLOAD_MAX_SIZE/g" \ + /tpls/etc/php7/php-fpm.d/www.conf > /etc/php7/php-fpm.d/www.conf + +# OpCache +echo "Setting OpCache configuration..." +sed -e "s/@OPCACHE_MEM_SIZE@/$OPCACHE_MEM_SIZE/g" \ + /tpls/etc/php7/conf.d/opcache.ini > /etc/php7/conf.d/opcache.ini + +# Nginx +echo "Setting Nginx configuration..." +sed -e "s/@UPLOAD_MAX_SIZE@/$UPLOAD_MAX_SIZE/g" \ + /tpls/etc/nginx/nginx.conf > /etc/nginx/nginx.conf + +# SSMTP +echo "Setting SSMTP configuration..." +if [ -z "$SSMTP_HOST" ] ; then + echo "WARNING: SSMTP_HOST must be defined if you want to send emails" + cp -f /etc/ssmtp/ssmtp.conf.or /etc/ssmtp/ssmtp.conf +else + cat > /etc/ssmtp/ssmtp.conf <&2 echo "ERROR: DB_HOST must be defined" + exit 1 +fi +cat > ${LIBRENMS_PATH}/config.d/database.php < ${LIBRENMS_PATH}/config.d/fping.php < ${LIBRENMS_PATH}/config.d/autoupdate.php < ${LIBRENMS_PATH}/config.d/email.php < ${LIBRENMS_PATH}/config.d/memcached.php < ${LIBRENMS_PATH}/config.d/rrdcached.php <>" + echo ">> Sidecar cron container detected" + echo ">>" + + # Init + rm -rf ${CRONTAB_PATH} + mkdir -m 0644 -p ${CRONTAB_PATH} + touch ${CRONTAB_PATH}/librenms + + # Add crons + cat ${LIBRENMS_PATH}/librenms.nonroot.cron > ${CRONTAB_PATH}/librenms + sed -i -e "s/ librenms //" ${CRONTAB_PATH}/librenms + sed -i -e "s/poller-wrapper.py 16/poller-wrapper.py ${LIBRENMS_POLLER_THREADS}/g" ${CRONTAB_PATH}/librenms + + # Fix perms + echo "Fixing permissions..." + chmod -R 0644 ${CRONTAB_PATH} +else + # Config : Directories + cat > ${LIBRENMS_PATH}/config.d/directories.php < /dev/null 2>&1; do + sleep 1 + counter=`expr $counter + 1` + if [ ${counter} -gt ${waitdb_timeout} ]; then + >&2 echo "ERROR: Failed to connect to database on $DB_HOST" + exit 1 + fi; + done + echo "Database up!" + + counttables=$(echo 'SHOW TABLES' | ${dbcmd} "$DB_NAME" | wc -l) + + echo "Updating database schema..." + runas_librenms "php build-base.php" + + if [ "${counttables}" -eq "0" ]; then + echo "Creating admin user..." + runas_librenms "php adduser.php librenms librenms 10 librenms@librenms.docker" + fi +fi + +exec "$@" diff --git a/examples/compose/docker-compose.yml b/examples/compose/docker-compose.yml new file mode 100644 index 0000000..0f303a6 --- /dev/null +++ b/examples/compose/docker-compose.yml @@ -0,0 +1,97 @@ +version: '3.2' + +services: + traefik: + image: traefik:1.6-alpine + command: + - --logLevel=INFO + - --defaultentrypoints=http,https + - --entryPoints=Name:http Address::80 Redirect.EntryPoint:https + - --entryPoints=Name:https Address::443 TLS + - --docker + - --docker.exposedbydefault=false + - --docker.domain=example.com + - --acme=true + - --acme.acmelogging=true + - --acme.email=webmaster@example.com + - --acme.storage=acme.json + - --acme.entryPoint=https + - --acme.onhostrule=true + - --acme.httpchallenge=true + - --acme.httpchallenge.entrypoint=http + ports: + - target: 80 + published: 80 + protocol: tcp + mode: host + - target: 443 + published: 443 + protocol: tcp + mode: host + volumes: + - ./acme.json:/acme.json + - /var/run/docker.sock:/var/run/docker.sock + restart: always + + db: + image: mariadb:10.2 + command: + - mysqld + - --sql-mode= + - --innodb-file-per-table=1 + - --lower-case-table-names=0 + volumes: + - db:/var/lib/mysql + environment: + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=librenms + - MYSQL_USER=librenms + - MYSQL_PASSWORD=asupersecretpassword + restart: always + + memcached: + image: memcached:alpine + restart: always + + rrdcached: + image: crazymax/rrdcached + environment: + - TZ=Europe/Paris + - LOG_LEVEL=LOG_INFO + - WRITE_TIMEOUT=1800 + - WRITE_JITTER=1800 + - WRITE_THREADS=4 + - FLUSH_DEAD_DATA_INTERVAL=3600 + restart: always + + app: + image: crazymax/librenms:latest + depends_on: + - db + - memcached + - rrdcached + volumes: + - librenms:/data + labels: + - traefik.enable=true + - traefik.backend=librenms + - traefik.port=80 + - traefik.frontend.rule=Host:librenms.example.com + env_file: + - ./librenms.env + restart: always + + cron: + image: crazymax/librenms:latest + depends_on: + - app + volumes: + - librenms:/data + command: /usr/local/bin/cron + env_file: + - ./librenms.env + restart: always + +volumes: + db: + librenms: diff --git a/examples/compose/librenms.env b/examples/compose/librenms.env new file mode 100644 index 0000000..681515b --- /dev/null +++ b/examples/compose/librenms.env @@ -0,0 +1,23 @@ +TZ=Europe/Paris + +MEMORY_LIMIT=256M +UPLOAD_MAX_SIZE=16M +OPCACHE_MEM_SIZE=128 + +LIBRENMS_POLLER_THREADS=16 +LIBRENMS_SNMP_COMMUNITY=librenmsdocker + +DB_HOST=db +DB_NAME=librenms +DB_USER=librenms +DB_PASSWORD=asupersecretpassword + +SSMTP_HOST=smtp.example.com +SSMTP_PORT=587 +SSMTP_HOSTNAME=librenms.example.com +SSMTP_USER=smtp@example.com +SSMTP_PASSWORD= +SSMTP_TLS=YES + +MEMCACHED_HOST=memcached +RRDCACHED_HOST=rrdcached