diff --git a/docker-compose/munin/docker-compose.yml.j2 b/docker-compose/munin/docker-compose.yml.j2
deleted file mode 100644
index 2f2b5d90..00000000
--- a/docker-compose/munin/docker-compose.yml.j2
+++ /dev/null
@@ -1,45 +0,0 @@
-version: '3'
-services:
- munin:
- container_name: "munin-master"
- image: registry.mgrote.net/munin-server:latest
- restart: always
- environment:
- MAILCONTACT: michael.grote@posteo.de
- MAILSERVER: postfix
- MAILPORT: 25
- MAILFROM: munin@mgrote.net
- MAILUSER: munin@mgrote.net
- MAILNAME: Munin
- MAILDOMAIN: mgrote.net
- MAILPASSWORD: ""
- TZ: Europe/Berlin
- CRONDELAY: 5
- NODES: |
- fileserver3.mgrote.net:fileserver3.mgrote.net
- ansible2.mgrote.net:ansible2.mgrote.net
- pve5.mgrote.net:pve5.mgrote.net
- forgejo.mgrote.net:forgejo.mgrote.net
- docker10.mgrote.net:docker10.mgrote.net
- pbs.mgrote.net:pbs.mgrote.net
- blocky.mgrote.net:blocky.mgrote.net
- ldap.mgrote.net:ldap.mgrote.net
- munin-container:localhost
- # z.B.
- # computer-test.mgrote.net:192.68.2.4
- # computer.mgrote.net:computer.mgrote.net
- volumes:
- - db:/var/lib/munin
- - logs:/var/log/munin
- - cache:/var/cache/munin
- ports:
- - 1234:80
-
-volumes:
- db:
- logs:
- cache:
-
-networks:
- postfix:
- external: true
diff --git a/group_vars/all.yml b/group_vars/all.yml
index aebbb7ec..9c733b30 100644
--- a/group_vars/all.yml
+++ b/group_vars/all.yml
@@ -213,8 +213,8 @@ munin_node_disabled_plugins:
- squid_traffic # proxmox
- timesync
- docker_volumesize2
-
- docker_multi
+
munin_node_plugins:
- name: chrony
src: https://git.mgrote.net/mirrors/munin-contrib/raw/branch/master/plugins/chrony/chrony
diff --git a/group_vars/blocky.yml b/group_vars/blocky.yml
index 5cce7dbb..fec986e0 100644
--- a/group_vars/blocky.yml
+++ b/group_vars/blocky.yml
@@ -91,6 +91,8 @@ blocky_custom_lookups: # optional
ip: 192.168.5.1
- name: ldap.mgrote.net
ip: 192.168.2.47
+ - name: munin.mgrote.net
+ ip: 192.168.2.41
### mgrote_munin_node
# kann git.mgrote.net nicht auflösen, deshalb hiermit IP
diff --git a/group_vars/munin.yml b/group_vars/munin.yml
new file mode 100644
index 00000000..25b109ae
--- /dev/null
+++ b/group_vars/munin.yml
@@ -0,0 +1,76 @@
+---
+### oefenweb.ufw
+ufw_rules:
+ - rule: allow
+ to_port: 22
+ protocol: tcp
+ comment: 'ssh'
+ from_ip: 0.0.0.0/0
+ - rule: allow
+ to_port: 80 #TODO passt?
+ protocol: tcp
+ comment: 'munin'
+
+### mgrote_restic
+restic_folders_to_backup: "/usr/local /etc /root /home /var/lib/munin"
+
+### geerlingguy.apache
+apache_vhosts:
+ # Additional optional properties: 'serveradmin, serveralias, extra_parameters'.
+ - servername: "munin.mgrote.net"
+ documentroot: "/var/cache/munin/www"
+
+### mrlesmithjr.ansible-manage-lvm
+lvm_groups:
+ - vgname: vg_munin
+ disks:
+ - /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi1
+ create: true
+ lvnames:
+ - lvname: lv_munin
+ size: +100%FREE
+ create: true
+ filesystem: xfs
+ mount: true
+ mntp: /var/lib/munin
+manage_lvm: true
+pvresize_to_max: true
+
+### mgrote_munin_node
+munin_node_bind_host: "127.0.0.1"
+munin_node_bind_port: "4949"
+munin_node_allowed_cidrs: [127.0.0.1]
+
+### mgrote_munin_master
+munin_mail_user: munin@mgrote.net
+munin_mail_server: "{{ postfix_smtp_server }}"
+munin_mail_port: "{{ 1025 }}"
+munin_mail_tls: false
+munin_enable_alerts: false
+munin_alerts_to: info@mgrote.net
+
+munin_hosts:
+ - name: "{{ ansible_fqdn }}.mgrote.net"
+ address: "127.0.0.1"
+ extra: ["use_node_name yes"]
+ - name: fileserver3.mgrote.net
+ address: fileserver3.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: pve5.mgrote.net
+ address: pve5.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: forgejo.mgrote.net
+ address: forgejo.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: docker10.mgrote.net
+ address: docker10.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: pbs.mgrote.net
+ address: pbs.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: blocky.mgrote.net
+ address: blocky.mgrote.net
+ extra: ["use_node_name yes"]
+ - name: ldap.mgrote.net
+ address: ldap.mgrote.net
+ extra: ["use_node_name yes"]
diff --git a/inventory b/inventory
index 11e7a7d7..b181c708 100644
--- a/inventory
+++ b/inventory
@@ -15,6 +15,9 @@ all:
ansible:
hosts:
ansible2.mgrote.net:
+ munin:
+ hosts:
+ munin.mgrote.net:
docker:
hosts:
docker10.mgrote.net:
@@ -49,6 +52,7 @@ all:
pbs.mgrote.net:
blocky.mgrote.net:
ldap.mgrote.net:
+ munin.mgrote.net:
test:
hosts:
vm-test-2204.mgrote.net:
diff --git a/keepass_db.kdbx b/keepass_db.kdbx
index 6952d493..ce6855d3 100644
Binary files a/keepass_db.kdbx and b/keepass_db.kdbx differ
diff --git a/playbooks/3_service/munin.yml b/playbooks/3_service/munin.yml
new file mode 100644
index 00000000..ace977a9
--- /dev/null
+++ b/playbooks/3_service/munin.yml
@@ -0,0 +1,6 @@
+---
+- hosts: munin
+ roles:
+ - role: mgrote_munin_server
+ tags: "munin"
+ become: true
diff --git a/roles/mgrote_munin_server/defaults/main.yml b/roles/mgrote_munin_server/defaults/main.yml
new file mode 100644
index 00000000..13509f1e
--- /dev/null
+++ b/roles/mgrote_munin_server/defaults/main.yml
@@ -0,0 +1,40 @@
+---
+munin_packages:
+ - cron
+ - munin
+ - apache2
+ - wget
+ - libapache2-mod-fcgid
+ - libcgi-fast-perl
+ - ssmtp
+ - perl
+ - mailutils
+ - curl
+ - tzdata
+ - munin-node
+ - libfile-readbackwards-perl
+munin_servername: "{{ ansible_fqdn }}.mgrote.net"
+munin_dirs:
+ - /var/run/munin
+ - /etc/munin/plugins
+ - /var/cache/munin/www
+ - /var/lib/munin
+ - /var/cache/munin
+munin_server_plugins:
+ - munin_stats
+ - munin_update
+munin_cron_job: present
+munin_dbdir: "/var/lib/munin"
+
+munin_enable_alerts: false
+munin_mail_server: mail.server.com
+munin_mail_port: 25
+munin_mail_tls: false
+munin_alerts_to: nobody@nowhere.com
+
+munin_mode: cgi # or cron
+
+munin_hosts:
+ - name: "{{ ansible_fqdn }}"
+ address: "127.0.0.1"
+ extra: ["use_node_name yes"]
diff --git a/roles/mgrote_munin_server/handlers/main.yml b/roles/mgrote_munin_server/handlers/main.yml
new file mode 100644
index 00000000..b45dc6cd
--- /dev/null
+++ b/roles/mgrote_munin_server/handlers/main.yml
@@ -0,0 +1,17 @@
+---
+- name: "restart apache2"
+ become: true
+ ansible.builtin.systemd:
+ name: apache2
+ enabled: true
+ masked: false
+ state: restarted
+
+- name: "restart munin"
+ become: true
+ ansible.builtin.systemd:
+ name: munin
+ enabled: true
+ masked: false
+ state: restarted
+...
diff --git a/roles/mgrote_munin_server/tasks/main.yml b/roles/mgrote_munin_server/tasks/main.yml
new file mode 100644
index 00000000..7f605c54
--- /dev/null
+++ b/roles/mgrote_munin_server/tasks/main.yml
@@ -0,0 +1,86 @@
+---
+- name: ensure packages are installed
+ become: true
+ ansible.builtin.package:
+ name: "{{ munin_packages }}"
+ state: present
+
+- name: Ensure needed dirs exists
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: directory
+ mode: '0755'
+ owner: munin
+ group: munin
+ loop: "{{ munin_dirs }}"
+
+- name: Ensure permissions are set
+ ansible.builtin.file:
+ path: /var/lib/munin/cgi-tmp
+ mode: 'ugo+rw'
+ state: directory
+ owner: munin
+ group: munin
+ recurse: true
+
+- name: Template apache config
+ ansible.builtin.template:
+ src: apache.conf
+ dest: /etc/apache2/sites-available/000-default.conf
+ mode: '0644'
+ owner: root
+ group: root
+ notify: "restart apache2"
+
+- name: Enable fgcid
+ community.general.apache2_module:
+ state: present
+ name: fcgid
+
+- name: Template munin-server plugins
+ ansible.builtin.template:
+ src: "{{ item }}"
+ dest: "/etc/munin/plugins/{{ item }}"
+ mode: '0755'
+ loop: "{{ munin_server_plugins }}"
+
+- name: Template munin config
+ ansible.builtin.template:
+ src: munin.conf
+ dest: /etc/munin/munin.conf
+ mode: '0644'
+ owner: munin
+ group: munin
+ notify: "restart munin"
+
+- name: Enable or disable the munin cron job.
+ ansible.builtin.lineinfile:
+ dest: /etc/cron.d/munin
+ state: "{{ munin_cron_job }}"
+ regexp: "^\\*/5 \\* \\* \\* \\*"
+ line: "*/5 * * * * munin if [ -x /usr/bin/munin-cron ]; then /usr/bin/munin-cron; fi"
+ create: true
+ mode: '0644'
+
+- name: check if munin has been run
+ ansible.builtin.stat:
+ path: /var/cache/munin/www/index.html
+ register: placeholder
+
+- name: Template website placeholder
+ ansible.builtin.template:
+ src: placeholder.html
+ dest: /var/cache/munin/www/index.html
+ mode: '0644'
+ owner: munin
+ group: munin
+ when: not placeholder.stat.exists
+
+- name: Template ssmtp config
+ ansible.builtin.template:
+ src: ssmtp.conf
+ dest: /etc/ssmtp/ssmtp.conf
+ mode: '0644'
+ owner: root
+ group: root
+...
diff --git a/roles/mgrote_munin_server/templates/apache.conf b/roles/mgrote_munin_server/templates/apache.conf
new file mode 100644
index 00000000..4d21bc08
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/apache.conf
@@ -0,0 +1,24 @@
+
+ ServerName {{ munin_servername }}
+
+ # Redirect requests without /munin to /munin
+ RedirectMatch ^/$ /munin/
+
+ # Existing configuration for serving /munin
+ Alias /munin /var/cache/munin/www
+
+ Require all granted
+ Options None
+
+
+ ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
+
+ Require all granted
+
+ SetHandler fcgid-script
+
+
+ SetHandler cgi-script
+
+
+
diff --git a/roles/mgrote_munin_server/templates/munin.conf b/roles/mgrote_munin_server/templates/munin.conf
new file mode 100644
index 00000000..1d8effa0
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/munin.conf
@@ -0,0 +1,115 @@
+includedir /etc/munin/munin-conf.d
+
+# Example configuration file for Munin, generated by 'make build'
+
+# The next three variables specifies where the location of the RRD
+# databases, the HTML output, logs and the lock/pid files. They all
+# must be writable by the user running munin-cron. They are all
+# defaulted to the values you see here.
+#
+dbdir {{ munin_dbdir }}
+#htmldir /var/cache/munin/www
+#logdir /var/log/munin
+#rundir /var/run/munin
+
+# Where to look for the HTML templates
+#
+#tmpldir /etc/munin/templates
+
+# Where to look for the static www files
+#
+#staticdir /etc/munin/static
+
+# temporary cgi files are here. note that it has to be writable by
+# the cgi user (usually nobody or httpd).
+#
+# cgitmpdir /var/lib/munin/cgi-tmp
+
+# (Exactly one) directory to include all files from.
+includedir /etc/munin/munin-conf.d
+
+# You can choose the time reference for "DERIVE" like graphs, and show
+# "per minute", "per hour" values instead of the default "per second"
+#
+#graph_period second
+
+# Graphics files are generated either via cron or by a CGI process.
+# See http://munin-monitoring.org/wiki/CgiHowto2 for more
+# documentation.
+# Since 2.0, munin-graph has been rewritten to use the cgi code.
+# It is single threaded *by design* now.
+#
+graph_strategy {{ munin_mode }}
+
+# munin-cgi-graph is invoked by the web server up to very many times at the
+# same time. This is not optimal since it results in high CPU and memory
+# consumption to the degree that the system can thrash. Again the default is
+# 6. Most likely the optimal number for max_cgi_graph_jobs is the same as
+# max_graph_jobs.
+#
+#munin_cgi_graph_jobs 6
+
+# If the automatic CGI url is wrong for your system override it here:
+#
+#cgiurl_graph /munin-cgi/munin-cgi-graph
+
+# max_size_x and max_size_y are the max size of images in pixel.
+# Default is 4000. Do not make it too large otherwise RRD might use all
+# RAM to generate the images.
+#
+#max_size_x 4000
+#max_size_y 4000
+
+# HTML files are normally generated by munin-html, no matter if the
+# files are used or not. You can change this to on-demand generation
+# by following the instructions in http://munin-monitoring.org/wiki/CgiHowto2
+#
+# Notes:
+# - moving to CGI for HTML means you cannot have graph generated by cron.
+# - cgi html has some bugs, mostly you still have to launch munin-html by hand
+#
+html_strategy {{ munin_mode }}
+
+# munin-update runs in parallel.
+#
+# The default max number of processes is 16, and is probably ok for you.
+#
+# If set too high, it might hit some process/ram/filedesc limits.
+# If set too low, munin-update might take more than 5 min.
+#
+# If you want munin-update to not be parallel set it to 0.
+#
+#max_processes 16
+
+# RRD updates are per default, performed directly on the rrd files.
+# To reduce IO and enable the use of the rrdcached, uncomment it and set it to
+# the location of the socket that rrdcached uses.
+#
+#rrdcached_socket /var/run/rrdcached.sock
+
+# Drop somejuser@fnord.comm and anotheruser@blibb.comm an email everytime
+# something changes (OK -> WARNING, CRITICAL -> OK, etc)
+# test with: sudo -u munin /usr/share/munin/munin-limits --contact someuser --force
+{% if munin_enable_alerts is sameas true %}
+contact.someuser.command mail -aFROM:munin@mgrote.net -s "Munin ${var:worst}: ${var:group}::${var:host}::${var:plugin}" {{ munin_alerts_to }}
+{% endif %}
+#contact.anotheruser.command mail -s "Munin ${var:worst}: ${var:group}::${var:host}::${var:plugin}" anotheruser@blibb.comm
+#
+# For those with Nagios, the following might come in handy. In addition,
+# the services must be defined in the Nagios server as well.
+#contact.nagios.command /usr/bin/send_nsca nagios.host.comm -c /etc/nsca.conf
+
+
+# Munin hosts.
+{% for host in munin_hosts %}
+[{{ host.name }}]
+{% if host.address is defined %}
+ address {{ host.address }}
+{% endif %}
+{% if host.extra is defined %}
+{% for extra in host.extra %}
+ {{ extra }}
+{% endfor %}
+{% endif %}
+
+{% endfor %}
diff --git a/roles/mgrote_munin_server/templates/munin_stats b/roles/mgrote_munin_server/templates/munin_stats
new file mode 100644
index 00000000..c03cab0a
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/munin_stats
@@ -0,0 +1,118 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006-2009 Rodolphe Quiédeville
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2 dated June,
+# 1991.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#
+# Magic markers (used by munin-node-configure and some installation scripts):
+#%# family=auto
+#%# capabilities=autoconf
+
+use strict;
+use warnings;
+
+use Munin::Plugin;
+
+
+my $missing_module = undef;
+$missing_module = "File::ReadBackwards" unless (eval "require File::ReadBackwards");
+
+my @logs = qw/update graph html limits/;
+my $logdir = ($ENV{'logdir'} || $ENV{'MUNIN_LOGDIR'} || '/var/log/munin');
+
+if ($ENV{'fields'}) {
+ @logs = split(/ +/, $ENV{'fields'});
+}
+
+sub uses_graph_cron {
+ my $log_file = $_[0];
+ my $bw = File::ReadBackwards->new($log_file) or
+ die "can't read 'log_file' $!";
+ if (defined(my $log_line = $bw->readline)) {
+ if ($log_line =~ ('.*graphing is cgi, do nothing$')) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 1;
+ }
+}
+
+
+if ($ARGV[0] and $ARGV[0] eq 'autoconf') {
+ my $munin_update_location =
+ "$Munin::Common::Defaults::MUNIN_LIBDIR/munin-update";
+
+ if (! -e $munin_update_location) {
+ print "no (munin-update was not found at $munin_update_location)\n";
+ } elsif (! -x $munin_update_location) {
+ print "no ($munin_update_location was found, but is not executable)\n";
+ } elsif (defined($missing_module)) {
+ print "no (missing Perl module: '$missing_module')\n";
+ } else {
+ print "yes\n";
+ }
+ exit 0;
+}
+
+if ($ARGV[0] and $ARGV[0] eq "config") {
+ print "graph_title Munin processing time\n",
+ "graph_info This graph shows the run time of the four different processes making up a munin-master run. Munin-master is run from cron every 5 minutes and we want each of the programmes in munin-master to complete before the next instance starts. If munin-update uses too long time to run please see the munin-update graph to determine which host is slowing it down.\n",
+ "graph_args --base 1000 -l 0\n",
+ "graph_scale yes\n",
+ "graph_vlabel seconds\n",
+ "graph_category munin\n";
+ foreach my $log (@logs) {
+ print "$log.label munin $log\n";
+ print "$log.draw AREASTACK\n";
+
+ next unless $log eq "update" || $log eq "graph";
+
+ print_thresholds("$log", undef, undef, 240, 285);
+ }
+ exit 0;
+}
+
+
+if (defined($missing_module)) {
+ die "Failed to run due to missing Perl module '$missing_module'";
+}
+
+foreach my $log (@logs) {
+ my $logfile = "$logdir/munin-$log.log";
+ my $time = 'U';
+
+ if (! -r $logfile) {
+ print "$log.extinfo Can't open $logfile for reading\n";
+ print "$log.value $time\n";
+ next;
+ }
+
+ my $bw = File::ReadBackwards->new("$logdir/munin-$log.log") or
+ die "can't read 'log_file' $!";
+ my $found_previous_finished = 0;
+ while(defined(my $log_line = $bw->readline) && $found_previous_finished == 0) {
+ if ($log_line =~ (/(finished|generated) \((\d+\.\d+)\ssec\)$/)) {
+ $time = $2;
+ $found_previous_finished = 1;
+ }
+ }
+
+ if ($log ne "graph" || uses_graph_cron("$logdir/munin-$log.log")) {
+ print "$log.value $time\n";
+ }
+}
diff --git a/roles/mgrote_munin_server/templates/munin_update b/roles/mgrote_munin_server/templates/munin_update
new file mode 100644
index 00000000..174d87db
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/munin_update
@@ -0,0 +1,123 @@
+#!/bin/sh
+
+: <<=cut
+
+=head1 NAME
+
+munin_update - Munin plugin to graph the time to query about each host from the nodes.
+
+=head1 APPLICABLE SYSTEMS
+
+Munin master servers.
+
+=head1 CONFIGURATION
+
+Normally needs no configuration. You may configure it with the
+following parameter:
+
+ [munin*]
+ env.UPDATE_STATSFILE .../munin-update.stats
+ env.MUNIN_UPDATE_LOCACTION .../munin-update
+
+The first is the statistics file for munin update.
+
+The exact location of this file is package/site specific, but
+munin_update will know where it is unless you have made changes.
+
+=head1 INTERPRETATION
+
+The script reads the munin-update "stats" file to determine how long
+it takes to query the nodes about each host configured in Munin.
+
+Munin is run from cron every 5 minutes and before the next run of
+munin-update the previous run needs to be done. Each run of
+munin-update forks one process pr. host that needs to get data
+collected, so all collection runs in parallel.
+
+Any host that is slow, for example slower than 4 miniutes, causes a
+risk that the next run of munin-update must be canceled due to the
+lateness of the previous run. In such cases there will be single line
+gaps in the "by day" graph.
+
+Keep your hosts updating quickly and all will be well.
+
+=head1 MAGIC MARKERS
+
+ #%# family=manual
+ #%# capabilities=autoconf
+
+=head1 BUGS
+
+Munin-update is always run at the same time as this plugin runs -
+therefore the stats file may be incompletely written and the plugin
+will likely show a incomplete list of hosts. It should be using
+munin-update.old-stats, which is not currently even made.
+
+Munin-update removes the "domain" information on all hosts. If there
+are two hosts with the same host name in different domains then one of
+them will be disappeared by the munin-update collection process.
+
+=head1 AUTHOR
+
+The munin_update plugin has been included in munin for many years (at
+least 2004). The most likely author is one of the original munin team.
+
+Documentation and updating to 2009 for Munin 1.4 by Nicolai Langfeldt.
+
+(C) 2004-2009 The Munin Team, Redpill Linpro AS
+
+=head1 LICENSE
+
+GPLv2
+
+=cut
+
+. "$MUNIN_LIBDIR/plugins/plugin.sh"
+
+
+UPDATE_STATSFILE=${UPDATE_STATSFILE:-$MUNIN_DBDIR/munin-update.stats}
+MUNIN_UPDATE_LOCATION=${MUNIN_UPDATE_LOCATION:-$MUNIN_LIBDIR/munin-update}
+
+
+if [ "$1" = "autoconf" ]; then
+ if [ -e "$MUNIN_UPDATE_LOCATION" ] ; then
+ echo "yes"
+ else
+ echo "no ($MUNIN_UPDATE_LOCATION is not present so this is not a munin-master)"
+ fi
+ exit 0
+fi
+
+if [ "$1" = "config" ]; then
+ [ -f "$UPDATE_STATSFILE" ] || {
+ echo 'graph_title Plugin error'
+ echo "graph_info Plugin cannot read stats file $UPDATE_STATSFILE"
+ echo 'error.label Error'
+ echo 'error.critical 1'
+ exit 0
+ }
+
+ echo 'graph_title Munin-update'
+ echo 'graph_vlabel seconds'
+ echo 'graph_category munin'
+ echo 'graph_info This graph shows the time it takes to collect data from each hosts that munin collects data on. Munin-master is run from cron every 5 minutes and we want each of the munin-update runs to complete before the next one starts. If munin-update uses too long time to run on one host run it with --debug to determine which plugin(s) are slow and solve the problem with them if possible.'
+ sed '/^UD|/!d; s/.*;//; s/|/ /;' < "$UPDATE_STATSFILE" | sort |
+ while read -r i j; do
+ name="$(clean_fieldname "$i")"
+ echo "$name.label $i"
+ warning=${warning:-240} critical=${critical:-285} print_thresholds "$name"
+ done
+ exit 0
+fi
+
+[ -f "$UPDATE_STATSFILE" ] || {
+ echo 'error.value 1'
+ echo "error.extinfo Plugin cannot read stats file $UPDATE_STATSFILE"
+ exit 0
+}
+
+sed '/^UD|/!d; s/.*;//; s/|/ /;' < "$UPDATE_STATSFILE" | sort |
+while read -r i j; do
+ name="$(clean_fieldname "$i")"
+ echo "$name.value $j"
+done
diff --git a/roles/mgrote_munin_server/templates/placeholder.html b/roles/mgrote_munin_server/templates/placeholder.html
new file mode 100644
index 00000000..707a402a
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/placeholder.html
@@ -0,0 +1,8 @@
+
+
+ Munin
+
+
+ Munin has not run yet. Please try again in a few moments.
+
+
diff --git a/roles/mgrote_munin_server/templates/run.sh b/roles/mgrote_munin_server/templates/run.sh
new file mode 100644
index 00000000..d0dadfb9
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/run.sh
@@ -0,0 +1,106 @@
+#!/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
+
+# 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
+
+# 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
+chown munin:munin /var/log/munin/munin-graph.log
+chown munin:munin /var/log/munin/munin-limits.log
+chown munin:munin /var/log/munin/munin-html.log
+
+# 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/roles/mgrote_munin_server/templates/ssmtp.conf b/roles/mgrote_munin_server/templates/ssmtp.conf
new file mode 100644
index 00000000..27a5b091
--- /dev/null
+++ b/roles/mgrote_munin_server/templates/ssmtp.conf
@@ -0,0 +1,12 @@
+# The user that gets all the mails (UID < 1000, usually the admin)
+root={{ munin_alerts_to }}
+
+# The mail server (where the mail is sent to), both port 465 or 587 should be acceptable
+# See also https://support.google.com/mail/answer/78799
+mailhub={{ munin_mail_server }}:{{ munin_mail_port }}
+
+# The full hostname. Must be correctly formed, fully qualified domain name or GMail will reject connection.
+hostname={{ munin_servername }}
+
+# Use implicit TLS (port 465). When using port 587, change UseSTARTTLS=Yes
+UseTLS={{ munin_mail_tls }}