From ef6bd5e4dbca239f747bd8eb4bc8b9fea329fdfb Mon Sep 17 00:00:00 2001 From: Michael Grote Date: Sat, 23 Jul 2022 10:46:57 +0200 Subject: [PATCH] first commit; copied from https://github.com/occitech/docker --- 000-default.conf | 54 ++++++++++++++++++++ Dockerfile | 37 ++++++++++++++ README.md | 74 ++++++++++++++++++++++++++++ logrotate-munin | 51 +++++++++++++++++++ munin.conf | 9 ++++ munin_mail.conf | 7 +++ munin_slack.conf | 2 + revaliases | 8 +++ run.sh | 126 +++++++++++++++++++++++++++++++++++++++++++++++ slack_munin.sh | 58 ++++++++++++++++++++++ ssmtp.conf | 25 ++++++++++ 11 files changed, 451 insertions(+) create mode 100644 000-default.conf create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 logrotate-munin create mode 100644 munin.conf create mode 100644 munin_mail.conf create mode 100644 munin_slack.conf create mode 100644 revaliases create mode 100644 run.sh create mode 100644 slack_munin.sh create mode 100644 ssmtp.conf diff --git a/000-default.conf b/000-default.conf new file mode 100644 index 0000000..aea048a --- /dev/null +++ b/000-default.conf @@ -0,0 +1,54 @@ +Documentroot /var/cache/munin/www + +ServerName localhost.localdomain + + + Allow from all + Satisfy Any + Options none + + ExpiresActive On + ExpiresDefault M310 + + + +Alias /munin-cgi/ /usr/lib/munin/cgi/ + + Allow from all + Satisfy Any + Options +ExecCGI + + SetHandler fcgid-script + + + SetHandler cgi-script + + + + + + Allow from all + Satisfy Any + + + + Allow from all + Satisfy Any + + SetHandler fcgid-script + + + SetHandler cgi-script + + + + + Allow from all + Satisfy Any + + SetHandler fcgid-script + + + SetHandler cgi-script + + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b5acb73 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM ubuntu:20.04 + +# install and configure munin +RUN apt-get update -qq && RUNLEVEL=1 DEBIAN_FRONTEND=noninteractive \ + apt-get install -y -qq cron munin nginx apache2 wget libapache2-mod-fcgid libcgi-fast-perl ssmtp mailutils curl tzdata autoconf +RUN (cp /etc/munin/apache24.conf /etc/apache2/sites-available/000-default.conf) +RUN (sed -i 's/^Alias.*/Alias \/ \/var\/cache\/munin\/www\//g' /etc/apache2/sites-available/000-default.conf) +RUN (sed -i 's/Allow from .*/Satisfy Any/g' /etc/apache2/sites-available/000-default.conf) +RUN (sed -i 's/Order allow,deny.*/Allow from all/g' /etc/apache2/sites-available/000-default.conf) +RUN (mkdir -p /var/run/munin && chown -R munin:munin /var/run/munin) + +RUN (chfn -f 'munin' root) +RUN (/usr/sbin/a2enmod fcgid) + +COPY 000-default.conf /etc/apache2/sites-available/000-default.conf +COPY logrotate-munin /etc/logrotate.d/munin +COPY munin.conf /etc/munin/munin.conf +COPY ssmtp.conf /etc/ssmtp/ssmtp.conf +COPY revaliases /etc/ssmtp/revaliases +COPY munin_mail.conf /etc/munin/munin-conf.d/munin_mail.conf +COPY slack_munin.sh /usr/local/bin/notify_slack_munin +RUN chmod +x /usr/local/bin/notify_slack_munin +COPY munin_slack.conf /etc/munin/munin-conf.d/munin_slack.conf + +# copy launcher +ADD run.sh /usr/local/bin/run +RUN chmod +x /usr/local/bin/run + +# persist +VOLUME /var/lib/munin +VOLUME /var/log/munin +VOLUME /var/cache/munin + +EXPOSE 80 + +# launcher +CMD ["/usr/local/bin/run"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..48a9575 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# Munin (master) + +**UNMAINTAINED** This repository is not maintained anymore, please use and report issues on it. + +## Quickstart + +Munin stats aggregator and reporting, based on lrivallain () and Arcus () work. +Update base image (ubuntu 20.04) and munin (2.0.56) and add easily configurable mail and Slack notifications. + +### Build + +```bash +git clone https://github.com/occitech/docker.git +docker build -t munin ./munin +docker run -p 80 munin +``` + +### Or pull + +```bash +docker pull occitech/munin +docker run -p 80 occitech/munin:latest +``` + +## How it works + +### Ports + +* 80 + +### Volumes + +* `/var/lib/munin` : Databases files +* `/var/log/munin` : Logs +* `/var/cache/munin` : Where are generated graphs + +### Environment Variables + +* `NODES`: Space separated list of `:` munin node pairs. (i.e. `foo.local:127.0.0.1 bar.remote:1.2.3.4`) +* `CRONDELAY`: Change the cron settings to update charts every X minutes (default: 5) +* `TZ`: Customize the timezone according to your place: (i.e. `Europe/London`) (default: `Europe/Paris`) +* `THISNODENAME`: Customize the displayed node name for local host (default: `munin`) +* `THISNODEIP`: Customize the node IP for local host (default: `127.0.0.1`) +* `DISABLELOCALNODE`: Disable local munin node (default: `no`) +* `MAILCONTACT`: Recipient of the mail alert (i.e. `alert@example.test`, needed for mail alert) +* `MAILSERVER`: Address of your mail server (i.e. `mail.example.test`, needed for mail alert) +* `MAILPORT`: Port of your SMTP mail server (i.e. `25`, needed for mail alert) +* `MAILUSER`: User to Auth on your mail server (i.e. `user@example.test`, needed for mail alert) +* `MAILPASSWORD`: Password of your mail server (needed for mail alert) +* `MAILFROM`: Where the mail seems to come from (i.e. `munin@example.test`, needed for mail alert) +* `MAILNAME`: Friendly sender name displayed for recipiend +* `MAILDOMAIN`: Domain of your mail server (i.e. `example.test`, needed for mail alert) +* `SLACKCHANNEL`: Name of your Slack channel (i.e. `hosting`, needed for Slack alert) +* `SLACKWEBHOOKURL`: URL of your Slack webhook (i.e. `https://hooks.slack.com/services/XXXXX/YYYYYYY/ZZZZZZZ`, needed for Slack alert) +* `SLACKUSER`: Username of munin bot on your Slack +* `SLACKICON`: Icon of munin bot on your Slack +* `VIRTUAL_HOST`: FQDN of your munin website + +## Persistent example + +```bash +docker run \ + -d \ + --name=munin \ + -p 127.0.0.1:8080:80 \ + -e THISNODENAME="munin.example.com" \ + -e TZ="Europe/London" \ + -e CRONDELAY=2 \ + -e NODES="anothernode.example.com:1.2.3.4 anothernode2.example.com:5.6.7.8" \ + -v /data/munin/db:/var/lib/munin \ + -v /data/munin/logs:/var/log/munin \ + -v /data/munin/cache:/var/cache/munin \ + munin +``` diff --git a/logrotate-munin b/logrotate-munin new file mode 100644 index 0000000..1bd78d6 --- /dev/null +++ b/logrotate-munin @@ -0,0 +1,51 @@ +/var/log/munin/munin-update.log { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + create 640 munin adm +} + +/var/log/munin/munin-graph.log { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + create 660 munin munin +} + +/var/log/munin/munin-html.log { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + create 640 munin adm +} + +/var/log/munin/munin-limits.log { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + create 640 munin adm +} + +/var/log/munin/munin-cgi-graph.log { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + #create 640 www-data adm + # see http://munin-monitoring.org/ticket/1152 + copytruncate +} diff --git a/munin.conf b/munin.conf new file mode 100644 index 0000000..6ad7843 --- /dev/null +++ b/munin.conf @@ -0,0 +1,9 @@ +includedir /etc/munin/munin-conf.d + +# local host +[localhost.localdomain] + address 127.0.0.1 + use_node_name yes + diskstats_latency.contacts no + +# remote host diff --git a/munin_mail.conf b/munin_mail.conf new file mode 100644 index 0000000..834245d --- /dev/null +++ b/munin_mail.conf @@ -0,0 +1,7 @@ +contact.hosting.command mail -s "[MUNIN] Alert ${var:graph_title} for ${var:host}" mailcontact +contact.hosting.max_messages 1 +# if activated mail will be send at each check (every 5mn) +# contact.hosting.always_send critical + +# to prevent flooding log file because missing documented contact parameters "no" +contact.no.command awk '{ print "[MUNIN] Alert ${var:graph_title} for ${var:host}" }' /dev/null diff --git a/munin_slack.conf b/munin_slack.conf new file mode 100644 index 0000000..29009f7 --- /dev/null +++ b/munin_slack.conf @@ -0,0 +1,2 @@ +# notify slack +contact.slack.command MUNIN_SERVICESTATE="${var:worst}" MUNIN_HOST="${var:host}" MUNIN_SERVICE="${var:graph_title}" MUNIN_GROUP=${var:group} MUNIN_IMAGE="https://muninurl/${var:group}/${var:host}/${var:plugin}-day.png" /usr/local/bin/notify_slack_munin diff --git a/revaliases b/revaliases new file mode 100644 index 0000000..1f83411 --- /dev/null +++ b/revaliases @@ -0,0 +1,8 @@ +# sSMTP aliases +# +# Format: local_account:outgoing_address:mailhub +# +# Example: root:your_login@your.domain:mailhub.your.domain[:port] +# where [:port] is an optional port number that defaults to 25. +root:mailfrom:mailserver:mailport +munin:mailfrom:mailserver:mailport diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..6c3642f --- /dev/null +++ b/run.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +# timezone settings +TZ=${TZ:="Europe/Paris"} +echo $TZ > /etc/timezone +# workaround https://bugs.launchpad.net/ubuntu/+source/tzdata/+bug/1554806 +rm /etc/localtime +dpkg-reconfigure -f noninteractive tzdata + +# change cron setting for updates +CRONDELAY=${CRONDELAY:=5} +sed -i "s/\*\/5/\*\/$CRONDELAY/g" /etc/cron.d/munin + +# configure default node name +THISNODENAME=${THISNODENAME:="munin"} +sed -i "s/^\[localhost\.localdomain\]/\[$THISNODENAME\]/g" /etc/munin/munin.conf + +# configure default node IP +THISNODEIP=${THISNODEIP:="127.0.0.1"} +sed -i "s/^\( *address\) 127\.0\.0\.1\$/\1 $THISNODEIP/" /etc/munin/munin.conf + +# configure default servername +THISSERVERNAME=${SERVERNAME:="munin"} +sed -i "s/^\[localhost\.localdomain\]/\[$SERVERNAME\]/g" /etc/apache2/sites-available/000-default.conf + +if [[ $DISABLELOCALNODE == "yes" ]] ; then + echo "includedir /etc/munin/munin-conf.d" > /etc/munin/munin.conf +fi + +# configure mail notification + +if [[ -n "$MAILCONTACT" && -n "$MAILSERVER" && -n "$MAILPORT" && -n "$MAILUSER" && -n "$MAILPASSWORD" && -n "$MAILDOMAIN" ]] ; then + MAILCONTACT=${MAILCONTACT:="contact@domain.test"} + sed -i "s/mailcontact/$MAILCONTACT/g" /etc/ssmtp/ssmtp.conf + sed -i "s/mailcontact/$MAILCONTACT/g" /etc/munin/munin-conf.d/munin_mail.conf + MAILSERVER=${MAILSERVER:="mail.domain.test"} + sed -i "s/mailserver/$MAILSERVER/g" /etc/ssmtp/ssmtp.conf + sed -i "s/mailserver/$MAILSERVER/g" /etc/ssmtp/revaliases + MAILPORT=${MAILPORT:="25"} + sed -i "s/mailport/$MAILPORT/g" /etc/ssmtp/ssmtp.conf + sed -i "s/mailport/$MAILPORT/g" /etc/ssmtp/revaliases + MAILUSER=${MAILUSER:="alert@domain.test"} + sed -i "s/mailuser/$MAILUSER/g" /etc/ssmtp/ssmtp.conf + MAILFROM=${MAILFROM:="munin@domain.test"} + sed -i "s/mailfrom/$MAILFROM/g" /etc/ssmtp/revaliases + MAILPASSWORD=${MAILPASSWORD:="XXXXXXXXX"} + sed -i "s/mailpassword/$MAILPASSWORD/g" /etc/ssmtp/ssmtp.conf + MAILDOMAIN=${MAILDOMAIN:="domain.test"} + sed -i "s/maildomain/$MAILDOMAIN/g" /etc/ssmtp/ssmtp.conf + sed -i "s/mailhost/$MAILDOMAIN/g" /etc/ssmtp/ssmtp.conf + MAILNAME=${MAILNAME:="Munin"} + sed -i "s/munin application user/$MAILNAME/g" /etc/passwd +else + rm /etc/munin/munin-conf.d/munin_mail.conf /etc/ssmtp/ssmtp.conf +fi + +# configure Slack notification + +if [[ -n "$SLACKCHANNEL" && -n "$SLACKWEBHOOKURL" ]] ; then + SLACKCHANNEL=${SLACKCHANNEL:="hosting"} + sed -i "s/slackchannel/$SLACKCHANNEL/g" /usr/local/bin/notify_slack_munin + SLACKWEBHOOKURL=${SLACKWEBHOOKURL:="https://hooks.slack.com/services/XXXXX/YYYYYYY/ZZZZZZZ"} + sed -i "s,slackwebhookurl,$SLACKWEBHOOKURL,g" /usr/local/bin/notify_slack_munin + SLACKUSER=${SLACKUSER:="munin"} + sed -i "s/slackuser/$SLACKUSER/g" /usr/local/bin/notify_slack_munin + SLACKICON=${SLACKICON:=":bomb:"} + sed -i "s/slackicon/$SLACKICON/g" /usr/local/bin/notify_slack_munin + sed -i "s/muninurl/$VIRTUAL_HOST/g" /usr/local/bin/notify_slack_munin + sed -i "s/muninurl/$VIRTUAL_HOST/g" /etc/munin/munin-conf.d/munin_slack.conf +else + rm /etc/munin/munin-conf.d/munin_slack.conf +fi + +# generate node list +NODES=${NODES:-} +for NODE in $NODES +do + NAME=`echo $NODE | cut -d ':' -f1` + HOST=`echo $NODE | cut -d ':' -f2` + grep -q "${HOST}$" /etc/munin/munin.conf || cat << EOF >> /etc/munin/munin.conf +[$NAME] + address $HOST + use_node_name yes + +EOF +done + +# placeholder html to prevent permission error +if [ ! -f /var/cache/munin/www/index.html ]; then + cat << EOF > /var/cache/munin/www/index.html + + + Munin + + + Munin has not run yet. Please try again in a few moments. + + +EOF + chown -R munin: /var/cache/munin/www/index.html +fi + +# ensure munin folder exist and have right permission + +mkdir -p /var/lib/munin/cgi-tmp /var/cache/munin/www +chown -R munin:munin /var/lib/munin /var/cache/munin +chmod -R ugo+rw /var/lib/munin/cgi-tmp + +# start cron +/usr/sbin/cron & + +# start local munin-node +/usr/sbin/munin-node > /dev/null 2>&1 & + +# confirm nodes +echo "Using the following munin nodes:" +echo " $THISNODENAME" +echo " $NODES" + +# start apache +/usr/sbin/apache2ctl start + +# display logs +touch /var/log/munin/munin-update.log +chown munin:munin /var/log/munin/munin-update.log +tail -f /var/log/munin/munin-*.log diff --git a/slack_munin.sh b/slack_munin.sh new file mode 100644 index 0000000..848196f --- /dev/null +++ b/slack_munin.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +# Slack notification script for Munin +# Mark Matienzo (@anarchivist) +# +# To use: +# 1) Create a new incoming webhook for Slack +# 2) Edit the configuration variables that start with "SLACK_" below +# 3) Add the following to your munin configuration: +# +# # -- Slack contact configuration +# contact.slack.command MUNIN_SERVICESTATE="${var:worst}" MUNIN_HOST="${var:host}" MUNIN_SERVICE="${var:graph_title}" MUNIN_GROUP=${var:group} MUNIN_IMAGE="http://munin.example.org/${var:group}/${var:host}/${var:plugin}-day.png" /usr/local/bin/notify_slack_munin +# contact.slack.always_send warning critical +# # note: This has to be on one line for munin to parse properly +# contact.slack.text ${if:cfields \u000A* CRITICALs:${loop<,>:cfields ${var:label} is ${var:value} (outside range [${var:crange}])${if:extinfo : ${var:extinfo}}}.}${if:wfields \u000A* WARNINGs:${loop<,>:wfields ${var:label} is ${var:value} (outside range [${var:wrange}])${if:extinfo : ${var:extinfo}}}.}${if:ufields \u000A* UNKNOWNs:${loop<,>:ufields ${var:label} is ${var:value}${if:extinfo : ${var:extinfo}}}.}${if:fofields \u000A* OKs:${loop<,>:fofields ${var:label} is ${var:value}${if:extinfo : ${var:extinfo}}}.} + + +SLACK_CHANNEL="slackchannel" +SLACK_WEBHOOK_URL="slackwebhookurl" +SLACK_USERNAME="slackuser" +SLACK_ICON_EMOJI="slackicon" + +# Url to link from slack notifications +MUNIN_URL="http://muninurl/problems.html" + +input=`cat` + +#Set the message icon based on service state +if [ "$MUNIN_SERVICESTATE" = "CRITICAL" ] +then + ICON=":exclamation:" + COLOR="danger" +elif [ "$MUNIN_SERVICESTATE" = "WARNING" ] +then + ICON=":warning:" + COLOR="warning" +elif [ "$MUNIN_SERVICESTATE" = "ok" ] +then + ICON=":white_check_mark:" + COLOR="good" +elif [ "$MUNIN_SERVICESTATE" = "OK" ] +then + ICON=":white_check_mark:" + COLOR="good" +elif [ "$MUNIN_SERVICESTATE" = "UNKNOWN" ] +then + ICON=":question:" + COLOR="#00CCCC" +else + ICON=":white_medium_square:" + COLOR="#CCCCCC" +fi + +# Generate the JSON payload +PAYLOAD="{\"channel\": \"${SLACK_CHANNEL}\", \"username\": \"${SLACK_USERNAME}\", \"attachments\": [{\"image_url\": \"${MUNIN_IMAGE}\", \"color\": \"${COLOR}\", \"fallback\": \"Munin alert - ${MUNIN_SERVICESTATE}: ${MUNIN_SERVICE} on ${MUNIN_HOST}\", \"pretext\": \"${ICON} Munin alert - ${MUNIN_SERVICESTATE}: ${MUNIN_SERVICE} on ${MUNIN_HOST} in ${MUNIN_GROUP} - <${MUNIN_URL}|View Munin>\", \"fields\": [{\"title\": \"Severity\", \"value\": \"${MUNIN_SERVICESTATE}\", \"short\": \"true\"}, {\"title\": \"Service\", \"value\": \"${MUNIN_SERVICE}\", \"short\": \"true\"}, {\"title\": \"Host\", \"value\": \"${MUNIN_HOST}\", \"short\": \"true\"}, {\"title\": \"Current Values\", \"value\": \"${input}\", \"short\": \"false\"}]}]}" + +#Send message to Slack +curl -sX POST -o /dev/null --data "payload=${PAYLOAD}" $SLACK_WEBHOOK_URL diff --git a/ssmtp.conf b/ssmtp.conf new file mode 100644 index 0000000..e8ee995 --- /dev/null +++ b/ssmtp.conf @@ -0,0 +1,25 @@ +# +# Config file for sSMTP sendmail +# +# The person who gets all mail for userids < 1000 +# Make this empty to disable rewriting. +root=mailuser + +# The place where the mail goes. The actual machine name is required no +# MX records are consulted. Commonly mailhosts are named mail.domain.com +mailhub=mailserver:mailport +AuthUser=mailuser +AuthPass=mailpassword +UseTLS=YES +UseSTARTTLS=YES + +# Where will the mail seem to come from? +rewriteDomain=maildomain + +# The full hostname +hostname=mailhost + +# Are users allowed to set their own From: address? +# YES - Allow the user to specify their own From: address +# NO - Use the system generated From: address +FromLineOverride=NO