diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e398916..95d42c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). This project does not follow semantic versioning. -The **major** part of the version is aligned with the stable version of Debian. -The **minor** part changes with big changes (probably incompatible). -The **patch** part changes incrementally at each release. +The **major** part of the version is the year +The **minor** part changes is the month +The **patch** part changes is incremented if multiple releases happen the same month ## [Unreleased] @@ -20,6 +20,91 @@ The **patch** part changes incrementally at each release. ### Security +## [22.01] 2022-01-25 + +### Added + +* Support for Debian 11 « Bullseye » (with possible remaining blind spots) +* apache: new variable for MPM mode (+ updated default config accordingly) +* apache: prevent accessing Git or "env" related files +* certbot: add script for manual deploy hooks execution +* docker-host: install additional dependencies +* dovecot: switch to TLS 1.2+ and external DH params +* etc-git: centralize cron jobs in dedicated crontab +* etc-git: manage commits with an optimized shell script instead of many slow Ansible tasks +* evolinux-base: add script backup-server-state +* evolinux-base: configure top and htop to display the swap column +* evolinux-base: install molly-guard by default +* generate-ldif: detect RAID controller +* generate-ldif: detect mdadm +* listupgrade: crontab is configurable +* logstash: logging to syslog is configurable (default: True) +* mongodb: create munin plugins directory if missing +* munin: systemd override to unprotect home directory +* mysql: add evomariabackup 21.11 +* mysql: improve Bullseye compatibility +* mysql: script "mysql_connections" to display a compact list of connections +* mysql: script "mysql-queries-killer.sh" to kill MySQL queries +* nagios-nrpe + evolinux-users: new check for ipmi +* nagios-nrpe + evolinux-users: new check for RAID (soft + hard) +* nagios-nrpe + evolinux-users: new checks for bkctld +* nagios-nrpe: new check influxdb +* openvpn: new role (beta) +* redis: instance service for Debian 11 +* squid: add *.o.lencr.org to default whitelist + +### Changed + +* Change version pattern +* Install python 2 or 3 libraries according to running python version +* Remove embedded GPG keys only if legacy keyring is present +* apt: remove workaround for Evolix public repositories with Debian 11 +* apt: upgrade packages after all the configuration is done +* apt: use the new security repository for Bullseye +* certbot: silence letsencrypt deprecation warnings +* elasticsearch: elastic_stack_version = 7.x +* evoacme: exclude renewal-hooks directory from cron +* evoadmin-web: simpler PHP packages lists +* evocheck: upstream release 21.10.4 +* evolinux-base: alert5 comes after the network +* evolinux-base: force Debian version to buster for Evolix repository (temporary) +* evolinux-base: install freeipmi by default on dedicated hw +* evolinux-base: logs are rotated with dateext by default +* evolinux-base: split dpkg logrotate configuration +* evolinux-users + nagios-nrpe: Add support for php-fpm80 in lxc +* evomaintenance: extract a config.yml tasks file +* evomaintenance: upstream release 22.01 +* filebeat/metricbeat: elastic_stack_version = 7.x +* kibana: elastic_stack_version = 7.x +* listupgrade: old-kernel-removal version 21.10 +* listupgrade: upstream release 21.06.3 +* logstash: elastic_stack_version = 7.x +* mongodb: Allow to specify a mongodb version for buster & bullseye +* mongodb: Deny the install on Debian 11 « Bullseye » when the version is unsupported +* mongodb: Support version 5.0 (for buster) +* mysql: use python3 and mariadb-client-10.5 with Debian 11 and later +* nodejs: default to version 16 LTS +* php: enforce Debian version with assert instead of fail +* squid: improve default whitelist (more specific patterns) +* squid: must be started in foreground mode for systemd +* squid: remove obsolete variable on Squid 4 + +### Fixed + +* evolinux-base: fix alert5.service dependency syntax +* certbot: sync_remote excludes itself +* lxc-php: fix config for opensmtpd on bullseye containers +* mysql : Create a default ~root/.my.cnf for compatibility reasons +* nginx : fix variable name and debug to actually use nginx-light +* packweb-apache : Support php 8.0 +* nagios-nrpe: Fix check_nfsserver for buster and bullseye + +### Removed + +* evocheck: package install is not supported anymore +* logstash: no more dependency on Java +* php: remove php-gettext for 7.4 + ## [10.6.0] 2021-06-28 ### Added diff --git a/apache/files/evolinux-defaults.conf b/apache/files/evolinux-defaults.conf index 06e28d9e..65c8c921 100644 --- a/apache/files/evolinux-defaults.conf +++ b/apache/files/evolinux-defaults.conf @@ -48,12 +48,23 @@ MaxKeepAliveRequests 10 Deny from env=GoAway + + # We don't want to let the client know a file exist on the server, + # so we return 404 "Not found" instead of 403 "Forbidden". + Redirect 404 + - - Require all denied - +# File names starting with + + Redirect 404 + +# File names ending with + + Redirect 404 + Require all denied + diff --git a/apache/tasks/server_status.yml b/apache/tasks/server_status.yml index 2ca77951..efd2b00e 100644 --- a/apache/tasks/server_status.yml +++ b/apache/tasks/server_status.yml @@ -33,6 +33,7 @@ - debug: var: apache_serverstatus_suffix + verbosity: 1 - name: replace server-status suffix in default site index replace: diff --git a/apt/files/bullseye_backports_preferences b/apt/files/bullseye_backports_preferences new file mode 100644 index 00000000..3a667c93 --- /dev/null +++ b/apt/files/bullseye_backports_preferences @@ -0,0 +1,3 @@ +Package: * +Pin: release a=bullseye-backports +Pin-Priority: 50 diff --git a/apt/tasks/basics.yml b/apt/tasks/basics.yml index fee1430a..33c79129 100644 --- a/apt/tasks/basics.yml +++ b/apt/tasks/basics.yml @@ -19,6 +19,7 @@ - /etc/apt/sources.list.d/debian-jessie.list - /etc/apt/sources.list.d/debian-stretch.list - /etc/apt/sources.list.d/debian-buster.list + - /etc/apt/sources.list.d/debian-bullseye.list - /etc/apt/sources.list.d/debian-update.list when: apt_clean_gandi_sourceslist | bool tags: diff --git a/apt/tasks/config.yml b/apt/tasks/config.yml index 4d7372fc..7befa375 100644 --- a/apt/tasks/config.yml +++ b/apt/tasks/config.yml @@ -39,17 +39,3 @@ when: apt_remove_aptitude | bool tags: - apt - -- name: Updating APT cache - apt: - update_cache: yes - changed_when: False - tags: - - apt - -- name: Upgrading system - apt: - upgrade: dist - when: apt_upgrade | bool - tags: - - apt diff --git a/apt/tasks/evolix_public.yml b/apt/tasks/evolix_public.yml index 00067f46..8352e666 100644 --- a/apt/tasks/evolix_public.yml +++ b/apt/tasks/evolix_public.yml @@ -1,10 +1,18 @@ --- +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - apt + - name: Evolix embedded GPG key is absent apt_key: id: "B8612B5D" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - apt diff --git a/apt/tasks/main.yml b/apt/tasks/main.yml index 118f8ef9..353dca36 100644 --- a/apt/tasks/main.yml +++ b/apt/tasks/main.yml @@ -37,3 +37,17 @@ when: apt_install_hold_packages | bool tags: - apt + +- name: Updating APT cache + apt: + update_cache: yes + changed_when: False + tags: + - apt + +- name: Upgrading system + apt: + upgrade: dist + when: apt_upgrade | bool + tags: + - apt \ No newline at end of file diff --git a/apt/templates/bullseye_backports.list.j2 b/apt/templates/bullseye_backports.list.j2 new file mode 100644 index 00000000..ab989dec --- /dev/null +++ b/apt/templates/bullseye_backports.list.j2 @@ -0,0 +1,3 @@ +# {{ ansible_managed }} + +deb http://mirror.evolix.org/debian bullseye-backports {{ apt_backports_components | mandatory }} diff --git a/apt/templates/bullseye_basics.list.j2 b/apt/templates/bullseye_basics.list.j2 new file mode 100644 index 00000000..94b0995d --- /dev/null +++ b/apt/templates/bullseye_basics.list.j2 @@ -0,0 +1,5 @@ +# {{ ansible_managed }} + +deb http://mirror.evolix.org/debian bullseye {{ apt_basics_components | mandatory }} +deb http://mirror.evolix.org/debian/ bullseye-updates {{ apt_basics_components | mandatory }} +deb https://deb.debian.org/debian-security bullseye-security {{ apt_basics_components | mandatory }} \ No newline at end of file diff --git a/bullseye-detect/tasks/main.yml b/bullseye-detect/tasks/main.yml new file mode 100644 index 00000000..6f97db0a --- /dev/null +++ b/bullseye-detect/tasks/main.yml @@ -0,0 +1,8 @@ +--- + +# Force facts until Debian 11 is released because Ansible is dumb +- set_fact: + ansible_distribution_major_version: 11 + ansible_distribution: "Debian" + ansible_distribution_release: "bullseye" + when: "ansible_lsb.codename == 'bullseye' or ansible_lsb.release == 'testing/unstable'" \ No newline at end of file diff --git a/certbot/files/hooks/deploy/sync_remote.sh b/certbot/files/hooks/deploy/sync_remote.sh index 08006b38..7fc3ecf4 100644 --- a/certbot/files/hooks/deploy/sync_remote.sh +++ b/certbot/files/hooks/deploy/sync_remote.sh @@ -14,8 +14,15 @@ debug() { found_renewed_lineage() { test -f "${RENEWED_LINEAGE}/fullchain.pem" && test -f "${RENEWED_LINEAGE}/privkey.pem" } +cert_content() { + openssl x509 -text -in "${RENEWED_LINEAGE}/fullchain.pem" +} domain_from_cert() { - openssl x509 -noout -subject -in "${RENEWED_LINEAGE}/fullchain.pem" | sed 's/^.*CN\ *=\ *//' + if cert_content | grep -q "X509v3 Subject Alternative Name:" && cert_content | grep -q "DNS:"; then + cert_content | grep "DNS:" | sed -e 's/\s\+//g' -e 's/DNS://g' + else + cert_content | sed 's/^.*CN\ *=\ *//' + fi } main() { if [ -z "${RENEWED_LINEAGE}" ]; then @@ -40,11 +47,11 @@ main() { rsync --archive --copy-links --delete "${RENEWED_LINEAGE}/" "${remote_host}:${remote_lineage}/" \ || error "Couldn't sync certificate on ${server}" - rsync --archive --copy-links --delete --exclude $0 --delete-excluded "${hooks_dir}/" "${remote_host}:${remote_dir}/hooks/" \ + rsync --archive --copy-links --delete --exclude "$(basename "$0")" --delete-excluded "${hooks_dir}/" "${remote_host}:${remote_dir}/hooks/" \ || error "Couldn't sync hooks on ${server}" # shellcheck disable=SC2029 - ssh "${remote_host}" "export RENEWED_LINEAGE=\"${remote_lineage}/\" RENEWED_DOMAINS=${RENEWED_DOMAINS}; find ${remote_dir}/hooks/ -mindepth 1 -maxdepth 1 -type f -executable -exec {} \;" \ + ssh "${remote_host}" "export RENEWED_LINEAGE=\"${remote_lineage}/\" RENEWED_DOMAINS=\"${RENEWED_DOMAINS}\"; find ${remote_dir}/hooks/ -mindepth 1 -maxdepth 1 -type f -executable -exec {} \;" \ || error "Something went wrong on ${server} for deploy hooks" done else diff --git a/certbot/files/hooks/manual-deploy.sh b/certbot/files/hooks/manual-deploy.sh new file mode 100755 index 00000000..70307070 --- /dev/null +++ b/certbot/files/hooks/manual-deploy.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +set -u + +error() { + >&2 echo "${PROGNAME}: $1" + exit 1 +} +debug() { + if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then + >&2 echo "${PROGNAME}: $1" + fi +} +found_renewed_lineage() { + test -f "${RENEWED_LINEAGE}/fullchain.pem" && test -f "${RENEWED_LINEAGE}/privkey.pem" +} +main() { + if [ -z "${RENEWED_LINEAGE:-}" ]; then + error "Missing RENEWED_LINEAGE environment variable (usually provided by certbot)." + fi + if [ "${VERBOSE}" = "1" ]; then + xargs_verbose="--verbose" + else + xargs_verbose="" + fi + if found_renewed_lineage; then + find "${hooks_dir}" -mindepth 1 -maxdepth 1 -type f -executable -print0 | sort --zero-terminated --dictionary-order | xargs ${xargs_verbose} --no-run-if-empty --null --max-args=1 sh -c + else + error "Couldn't find required files in \`${RENEWED_LINEAGE}'" + fi + +} + +PROGNAME=$(basename "$0") +VERBOSE=${VERBOSE:-"0"} +QUIET=${QUIET:-"0"} + +hooks_dir="/etc/letsencrypt/renewal-hooks/deploy" + +main \ No newline at end of file diff --git a/certbot/files/letsencrypt-auto b/certbot/files/letsencrypt-auto index 0e26e29a..5f6ace3d 100644 --- a/certbot/files/letsencrypt-auto +++ b/certbot/files/letsencrypt-auto @@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then fi VENV_BIN="$VENV_PATH/bin" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" -LE_AUTO_VERSION="1.9.0" +LE_AUTO_VERSION="1.14.0" BASENAME=$(basename $0) USAGE="Usage: $BASENAME [OPTIONS] A self-updating wrapper script for the Certbot ACME client. When run, updates @@ -497,7 +497,7 @@ Python36SclIsAvailable() { # Try to enable rh-python36 from SCL if it is necessary and possible. EnablePython36SCL() { - if "$EXISTS" python3.6 > /dev/null 2>/dev/null; then + if "$EXISTS" python3.6 > /dev/null 2> /dev/null; then return 0 fi if [ ! -f /opt/rh/rh-python36/enable ]; then @@ -799,15 +799,15 @@ BootstrapMageiaCommon() { # that function. If Bootstrap is set to a function that doesn't install any # packages BOOTSTRAP_VERSION is not set. if [ -f /etc/debian_version ]; then - Bootstrap() { - BootstrapMessage "Debian-based OSes" - BootstrapDebCommon - } - BOOTSTRAP_VERSION="BootstrapDebCommon $BOOTSTRAP_DEB_COMMON_VERSION" + DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/mageia-release ]; then # Mageia has both /etc/mageia-release and /etc/redhat-release DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/redhat-release ]; then + DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 # Run DeterminePythonVersion to decide on the basis of available Python versions # whether to use 2.x or 3.x on RedHat-like systems. # Then, revert LE_PYTHON to its previous state. @@ -815,7 +815,7 @@ elif [ -f /etc/redhat-release ]; then unset LE_PYTHON DeterminePythonVersion "NOCRASH" - RPM_DIST_NAME=`(. /etc/os-release 2>/dev/null && echo $ID) || echo "unknown"` + RPM_DIST_NAME=`(. /etc/os-release 2> /dev/null && echo $ID) || echo "unknown"` if [ "$PYVER" -eq 26 -a $(uname -m) != 'x86_64' ]; then # 32 bits CentOS 6 and affiliates are not supported anymore by certbot-auto. @@ -825,7 +825,7 @@ elif [ -f /etc/redhat-release ]; then # Set RPM_DIST_VERSION to VERSION_ID from /etc/os-release after splitting on # '.' characters (e.g. "8.0" becomes "8"). If the command exits with an # error, RPM_DIST_VERSION is set to "unknown". - RPM_DIST_VERSION=$( (. /etc/os-release 2>/dev/null && echo "$VERSION_ID") | cut -d '.' -f1 || echo "unknown") + RPM_DIST_VERSION=$( (. /etc/os-release 2> /dev/null && echo "$VERSION_ID") | cut -d '.' -f1 || echo "unknown") # If RPM_DIST_VERSION is an empty string or it contains any nonnumeric # characters, the value is unexpected so we set RPM_DIST_VERSION to 0. @@ -840,12 +840,7 @@ elif [ -f /etc/redhat-release ]; then INTERACTIVE_BOOTSTRAP=1 fi - Bootstrap() { - BootstrapMessage "Legacy RedHat-based OSes that will use Python3" - BootstrapRpmPython3Legacy - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3Legacy $BOOTSTRAP_RPM_PYTHON3_LEGACY_VERSION" # Try now to enable SCL rh-python36 for systems already bootstrapped # NB: EnablePython36SCL has been defined along with BootstrapRpmPython3Legacy in certbot-auto @@ -864,43 +859,38 @@ elif [ -f /etc/redhat-release ]; then fi if [ "$RPM_USE_PYTHON_3" = 1 ]; then - Bootstrap() { - BootstrapMessage "RedHat-based OSes that will use Python3" - BootstrapRpmPython3 - } USE_PYTHON_3=1 - BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION" - else - Bootstrap() { - BootstrapMessage "RedHat-based OSes" - BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" fi fi LE_PYTHON="$prev_le_python" elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/arch-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/manjaro-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/gentoo-release ]; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq FreeBSD ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif uname | grep -iq Darwin ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then - Bootstrap() { - ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon - } - BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" + DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 else DEPRECATED_OS=1 + NO_SELF_UPGRADE=1 fi # We handle this case after determining the normal bootstrap version to allow @@ -1122,15 +1112,17 @@ if [ "$1" = "--le-auto-phase2" ]; then if [ "$DEPRECATED_OS" = 1 ]; then # Phase 2 damage control mode for deprecated OSes. # In this situation, we bypass any bootstrap or certbot venv setup. - error "Your system is not supported by certbot-auto anymore." + # error "Your system is not supported by certbot-auto anymore." if [ ! -d "$VENV_PATH" ] && OldVenvExists; then VENV_BIN="$OLD_VENV_PATH/bin" fi if [ -f "$VENV_BIN/letsencrypt" -a "$INSTALL_ONLY" != 1 ]; then - error "Certbot will no longer receive updates." - error "Please visit https://certbot.eff.org/ to check for other alternatives." + # error "certbot-auto and its Certbot installation will no longer receive updates." + # error "You will not receive any bug fixes including those fixing server compatibility" + # error "or security problems." + # error "Please visit https://certbot.eff.org/ to check for other alternatives." "$VENV_BIN/letsencrypt" "$@" exit 0 else @@ -1497,18 +1489,18 @@ letsencrypt==0.7.0 \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 -certbot==1.9.0 \ - --hash=sha256:d5a804d32e471050921f7b39ed9859e2e9de02824176ed78f57266222036b53a \ - --hash=sha256:2ff9bf7d9af381c7efee22dec2dd6938d9d8fddcc9e11682b86e734164a30b57 -acme==1.9.0 \ - --hash=sha256:d8061b396a22b21782c9b23ff9a945b23e50fca2573909a42f845e11d5658ac5 \ - --hash=sha256:38a1630c98e144136c62eec4d2c545a1bdb1a3cd4eca82214be6b83a1f5a161f -certbot-apache==1.9.0 \ - --hash=sha256:09528a820d57e54984d490100644cd8a6603db97bf5776f86e95795ecfacf23d \ - --hash=sha256:f47fb3f4a9bd927f4812121a0beefe56b163475a28f4db34c64dc838688d9e9e -certbot-nginx==1.9.0 \ - --hash=sha256:bb2e3f7fe17f071f350a3efa48571b8ef40a8e4b6db9c6da72539206a20b70be \ - --hash=sha256:ab26a4f49d53b0e8bf0f903e58e2a840cda233fe1cbbc54c36ff17f973e57d65 +certbot==1.14.0 \ + --hash=sha256:67b4d26ceaea6c7f8325d0d45169e7a165a2cabc7122c84bc971ba068ca19cca \ + --hash=sha256:959ea90c6bb8dca38eab9772722cb940972ef6afcd5f15deef08b3c3636841eb +acme==1.14.0 \ + --hash=sha256:4f48c41261202f1a389ec2986b2580b58f53e0d5a1ae2463b34318d78b87fc66 \ + --hash=sha256:61daccfb0343628cbbca551a7fc4c82482113952c21db3fe0c585b7c98fa1c35 +certbot-apache==1.14.0 \ + --hash=sha256:b757038db23db707c44630fecb46e99172bd791f0db5a8e623c0842613c4d3d9 \ + --hash=sha256:887fe4a21af2de1e5c2c9428bacba6eb7c1219257bc70f1a1d8447c8a321adb0 +certbot-nginx==1.14.0 \ + --hash=sha256:8916a815437988d6c192df9f035bb7a176eab20eee0956677b335d0698d243fb \ + --hash=sha256:cc2a8a0de56d9bb6b2efbda6c80c647dad8db2bb90675cac03ade94bd5fc8597 UNLIKELY_EOF # ------------------------------------------------------------------------- diff --git a/certbot/tasks/install-legacy.yml b/certbot/tasks/install-legacy.yml index e186c80d..446e557a 100644 --- a/certbot/tasks/install-legacy.yml +++ b/certbot/tasks/install-legacy.yml @@ -8,6 +8,7 @@ - include_role: name: evolix/remount-usr +# copied and customized from https://raw.githubusercontent.com/certbot/certbot/v1.14.0/letsencrypt-auto - name: Let's Encrypt script is present copy: src: letsencrypt-auto @@ -55,5 +56,5 @@ dest: "/etc/letsencrypt/cli.ini" section: null option: "no-self-upgrade" - value: 0 + value: "no" state: present diff --git a/certbot/tasks/main.yml b/certbot/tasks/main.yml index e280875c..cede35a6 100644 --- a/certbot/tasks/main.yml +++ b/certbot/tasks/main.yml @@ -7,17 +7,17 @@ - ansible_distribution_major_version is version('8', '>=') msg: only compatible with Debian 9+ -- name: Install legacy script on Debian 8 and 9 +- name: Install legacy script on Debian 8 include: install-legacy.yml when: - ansible_distribution == "Debian" - - ansible_distribution_major_version is version('10', '<') + - ansible_distribution_major_version is version('9', '<') -- name: Install package on Debian 10+ +- name: Install package on Debian 9+ include: install-package.yml when: - ansible_distribution == "Debian" - - ansible_distribution_major_version is version('10', '>=') + - ansible_distribution_major_version is version('9', '>=') - include: acme-challenge.yml @@ -29,6 +29,14 @@ owner: root group: root +- name: Manual deploy hook is present + copy: + src: hooks/manual-deploy.sh + dest: /etc/letsencrypt/renewal-hooks/manual-deploy.sh + mode: "0700" + owner: root + group: root + - name: "sync_remote is configured with servers" lineinfile: dest: /etc/letsencrypt/renewal-hooks/deploy/sync_remote.cf diff --git a/clamav/tasks/main.yml b/clamav/tasks/main.yml index be9e5b00..6d1da3eb 100644 --- a/clamav/tasks/main.yml +++ b/clamav/tasks/main.yml @@ -6,48 +6,48 @@ value: "{{ item.value }}" vtype: "{{ item.type }}" loop: - - { key: 'clamav-daemon/debconf', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/MaxHTMLNormalize', type: 'string', value: '10M' } - - { key: 'clamav-daemon/StatsPEDisabled', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/FollowDirectorySymlinks', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/StreamMaxLength', type: 'string', value: '25' } - - { key: 'clamav-daemon/ReadTimeout', type: 'string', value: '180' } - - { key: 'clamav-daemon/StatsEnabled', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/MaxConnectionQueueLength', type: 'string', value: '15' } - - { key: 'clamav-daemon/LogRotate', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/AllowAllMatchScan', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/ScanOnAccess', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/LogFile', type: 'string', value: '/var/log/clamav/clamav.log' } - - { key: 'clamav-daemon/ScanMail', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/BytecodeTimeout', type: 'string', value: '60000' } - - { key: 'clamav-daemon/LogTime', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/OnAccessMaxFileSize', type: 'string', value: '5M' } - - { key: 'clamav-daemon/TcpOrLocal', type: 'select', value: 'UNIX' } - - { key: 'clamav-daemon/MaxEmbeddedPE', type: 'string', value: '10M' } - - { key: 'clamav-daemon/FixStaleSocket', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/User', type: 'string', value: 'clamav' } - - { key: 'clamav-daemon/BytecodeSecurity', type: 'select', value: 'TrustSigned' } - - { key: 'clamav-daemon/ScanSWF', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/MaxDirectoryRecursion', type: 'string', value: '0' } - - { key: 'clamav-daemon/MaxThreads', type: 'string', value: '12' } - - { key: 'clamav-daemon/LocalSocketGroup', type: 'string', value: 'clamav' } - - { key: 'clamav-daemon/MaxScriptNormalize', type: 'string', value: '5M' } - - { key: 'clamav-daemon/ForceToDisk', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/StatsHostID', type: 'string', value: 'auto' } - - { key: 'clamav-daemon/FollowFileSymlinks', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/TCPSocket', type: 'string', value: '3310' } - - { key: 'clamav-daemon/TCPAddr', type: 'string', value: 'any' } - - { key: 'clamav-daemon/DisableCertCheck', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/SelfCheck', type: 'string', value: '3600' } - - { key: 'clamav-daemon/LocalSocket', type: 'string', value: '/var/run/clamav/clamd.ctl' } - - { key: 'clamav-daemon/LocalSocketMode', type: 'string', value: '666' } - - { key: 'clamav-daemon/StatsTimeout', type: 'string', value: '10' } - - { key: 'clamav-daemon/MaxZipTypeRcg', type: 'string', value: '1M' } - - { key: 'clamav-daemon/MaxHTMLNoTags', type: 'string', value: '2M' } - - { key: 'clamav-daemon/LogSyslog', type: 'boolean', value: 'false' } - - { key: 'clamav-daemon/AddGroups', type: 'string', value: '' } - - { key: 'clamav-daemon/Bytecode', type: 'boolean', value: 'true' } - - { key: 'clamav-daemon/ScanArchive', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/debconf', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/MaxHTMLNormalize', type: 'string', value: '10M' } + - { key: 'clamav-daemon/StatsPEDisabled', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/FollowDirectorySymlinks', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/StreamMaxLength', type: 'string', value: '25' } + - { key: 'clamav-daemon/ReadTimeout', type: 'string', value: '180' } + - { key: 'clamav-daemon/StatsEnabled', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/MaxConnectionQueueLength', type: 'string', value: '15' } + - { key: 'clamav-daemon/LogRotate', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/AllowAllMatchScan', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/ScanOnAccess', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/LogFile', type: 'string', value: '/var/log/clamav/clamav.log' } + - { key: 'clamav-daemon/ScanMail', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/BytecodeTimeout', type: 'string', value: '60000' } + - { key: 'clamav-daemon/LogTime', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/OnAccessMaxFileSize', type: 'string', value: '5M' } + - { key: 'clamav-daemon/TcpOrLocal', type: 'select', value: 'UNIX' } + - { key: 'clamav-daemon/MaxEmbeddedPE', type: 'string', value: '10M' } + - { key: 'clamav-daemon/FixStaleSocket', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/User', type: 'string', value: 'clamav' } + - { key: 'clamav-daemon/BytecodeSecurity', type: 'select', value: 'TrustSigned' } + - { key: 'clamav-daemon/ScanSWF', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/MaxDirectoryRecursion', type: 'string', value: '0' } + - { key: 'clamav-daemon/MaxThreads', type: 'string', value: '12' } + - { key: 'clamav-daemon/LocalSocketGroup', type: 'string', value: 'clamav' } + - { key: 'clamav-daemon/MaxScriptNormalize', type: 'string', value: '5M' } + - { key: 'clamav-daemon/ForceToDisk', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/StatsHostID', type: 'string', value: 'auto' } + - { key: 'clamav-daemon/FollowFileSymlinks', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/TCPSocket', type: 'string', value: '3310' } + - { key: 'clamav-daemon/TCPAddr', type: 'string', value: 'any' } + - { key: 'clamav-daemon/DisableCertCheck', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/SelfCheck', type: 'string', value: '3600' } + - { key: 'clamav-daemon/LocalSocket', type: 'string', value: '/var/run/clamav/clamd.ctl' } + - { key: 'clamav-daemon/LocalSocketMode', type: 'string', value: '666' } + - { key: 'clamav-daemon/StatsTimeout', type: 'string', value: '10' } + - { key: 'clamav-daemon/MaxZipTypeRcg', type: 'string', value: '1M' } + - { key: 'clamav-daemon/MaxHTMLNoTags', type: 'string', value: '2M' } + - { key: 'clamav-daemon/LogSyslog', type: 'boolean', value: 'false' } + - { key: 'clamav-daemon/AddGroups', type: 'string', value: '' } + - { key: 'clamav-daemon/Bytecode', type: 'boolean', value: 'true' } + - { key: 'clamav-daemon/ScanArchive', type: 'boolean', value: 'true' } tags: - clamav @@ -58,17 +58,17 @@ value: "{{ item.value }}" vtype: "{{ item.type }}" loop: - - { key: 'clamav-freshclam/autoupdate_freshclam', type: 'select', value: 'daemon' } - - { key: 'clamav-freshclam/proxy_user', type: 'string', value: '' } - - { key: 'clamav-freshclam/NotifyClamd', type: 'boolean', value: 'true' } - - { key: 'clamav-freshclam/local_mirror', type: 'select', value: 'db.fr.clamav.net' } - - { key: 'clamav-freshclam/http_proxy', type: 'string', value: '' } - - { key: 'clamav-freshclam/LogRotate', type: 'boolean', value: 'true' } - - { key: 'clamav-freshclam/Bytecode', type: 'boolean', value: 'true' } - - { key: 'clamav-freshclam/update_interval', type: 'string', value: '24' } - - { key: 'clamav-freshclam/SafeBrowsing', type: 'boolean', value: 'false' } - - { key: 'clamav-freshclam/PrivateMirror', type: 'string', value: '' } - - { key: 'clamav-freshclam/internet_interface', type: 'string', value: '' } + - { key: 'clamav-freshclam/autoupdate_freshclam', type: 'select', value: 'daemon' } + - { key: 'clamav-freshclam/proxy_user', type: 'string', value: '' } + - { key: 'clamav-freshclam/NotifyClamd', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/local_mirror', type: 'select', value: 'db.fr.clamav.net' } + - { key: 'clamav-freshclam/http_proxy', type: 'string', value: '' } + - { key: 'clamav-freshclam/LogRotate', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/Bytecode', type: 'boolean', value: 'true' } + - { key: 'clamav-freshclam/update_interval', type: 'string', value: '24' } + - { key: 'clamav-freshclam/SafeBrowsing', type: 'boolean', value: 'false' } + - { key: 'clamav-freshclam/PrivateMirror', type: 'string', value: '' } + - { key: 'clamav-freshclam/internet_interface', type: 'string', value: '' } tags: - clamav diff --git a/docker-host/tasks/main.yml b/docker-host/tasks/main.yml index d3a41a28..026181f6 100644 --- a/docker-host/tasks/main.yml +++ b/docker-host/tasks/main.yml @@ -36,13 +36,26 @@ owner: root group: root -- name: Install docker and python-docker +- name: Install Docker apt: name: - docker-ce - - python-docker + - docker-ce-cli + - containerd.io update_cache: yes +- name: python-docker is installed + apt: + name: python-docker + state: present + when: ansible_python_version is version('3', '<') + +- name: python3-docker is installed + apt: + name: python3-docker + state: present + when: ansible_python_version is version('3', '>=') + - name: Copy Docker daemon configuration file template: src: daemon.json.j2 diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml index aa817086..1bebbafc 100644 --- a/dovecot/tasks/main.yml +++ b/dovecot/tasks/main.yml @@ -10,6 +10,11 @@ tags: - dovecot +- name: Generate 4096 bits Diffie-Hellman parameters (may take several minutes) + openssl_dhparam: + path: /etc/ssl/dhparams.pem + size: 4096 + - name: disable pam auth replace: dest: /etc/dovecot/conf.d/10-auth.conf diff --git a/dovecot/templates/z-evolinux-defaults.conf.j2 b/dovecot/templates/z-evolinux-defaults.conf.j2 index 2c067b99..f913ff38 100644 --- a/dovecot/templates/z-evolinux-defaults.conf.j2 +++ b/dovecot/templates/z-evolinux-defaults.conf.j2 @@ -35,12 +35,27 @@ service login { } mail_max_userip_connections = 42 +# Configuration pour stats dovecot +service stats { + unix_listener stats-reader { + user = vmail + group = vmail + mode = 0660 + } + + unix_listener stats-writer { + user = vmail + group = vmail + mode = 0660 + } +} + # SSL/TLS ssl = yes ssl_prefer_server_ciphers = yes -ssl_dh_parameters_length = 2048 +ssl_dh=, + Jérémy Lecour + and others. + +evocommit comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. +END +} + +show_help() { + cat </dev/null; then + mountpoint=$(stat -c '%m' $1) + findmnt "${mountpoint}" --noheadings --output OPTIONS -O ro + else + grep /usr /proc/mounts | grep -E '\bro\b' + fi +} +remount_repository_readwrite() { + if [ "$(get_system)" = "OpenBSD" ]; then + partition=$(stat -f '%Sd' $1) + mount -u -w /dev/${partition} 2>/dev/null + else + mountpoint=$(stat -c '%m' $1) + mount -o remount,rw ${mountpoint} + syslog "Re-mount ${mountpoint} as read-write to commit in repository $1" + fi +} +remount_repository_readonly() { + if [ "$(get_system)" = "OpenBSD" ]; then + partition=$(stat -f '%Sd' $1) + mount -u -r /dev/${partition} 2>/dev/null + else + mountpoint=$(stat -c '%m' $1) + mount -o remount,ro ${mountpoint} 2>/dev/null + syslog "Re-mount ${mountpoint} as read-only after commit to repository $1" + fi +} +is_dry_run() { + test "${DRY_RUN}" = "1" +} +is_verbose() { + test "${VERBOSE}" = "1" +} +is_ansible() { + test "${ANSIBLE}" = "1" +} +main() { + rc=0 + lock="${GIT_DIR}/index.lock" + if [ -f "${lock}" ]; then + limit=$(date +"%s" -d "now - 1 hour") + updated_at=$(stat -c "%Y" "${lock}") + if [ "$updated_at" -lt "$limit" ]; then + rm -f "${lock}" + fi + fi + + git_status=$(${GIT_BIN} status --porcelain) + + if [ -n "${git_status}" ]; then + if is_dry_run; then + ${GIT_BIN} status + else + readonly_orig=0 + # remount mount point read-write if currently readonly + if is_repository_readonly "${REPOSITORY}"; then + readonly_orig=1; + remount_repository_readwrite "${REPOSITORY}"; + fi + author=$(logname) + email=$(git config --get user.email) + email=${email:-"${author}@evolix.net"} + + # commit changes + git_add_result=$(${GIT_BIN} add --all) + git_add_rc=$? + + if is_ansible; then + if [ ${git_add_rc} -ne 0 ]; then + printf "FAILED: %s\n%s" "can't add changes in ${REPOSITORY}" "${git_add_result}" + rc=1 + fi + fi + + git_commit_result=$(${GIT_BIN} commit --message "${MESSAGE}" --author "${author} <${email}>") + git_commit_rc=$? + + if is_ansible; then + if [ ${git_commit_rc} -eq 0 ]; then + printf "CHANGED: %s\n" "commit done in ${REPOSITORY} with \`${MESSAGE}'" + else + printf "FAILED: %s\n%s" "can't commit in ${REPOSITORY} \`${MESSAGE}'" "${git_commit_result}" + rc=1 + fi + fi + + # remount mount point read-only if it was before + if [ ${readonly_orig} -eq 1 ]; then + remount_repository_readonly "${REPOSITORY}" + fi + fi + else + if is_ansible; then + printf "INFO: %s\n" "no commit in ${REPOSITORY}'" + fi + fi + + unset GIT_DIR + unset GIT_WORK_TREE + + exit ${rc} +} +# Parse options +# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a +while :; do + case ${1:-''} in + -h|-\?|--help) + show_help + exit 0 + ;; + -V|--version) + show_version + exit 0 + ;; + --message) + # message options, with value speparated by space + if [ -n "$2" ]; then + MESSAGE=$2 + shift + else + printf 'ERROR: "--message" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --message=?*) + # message options, with value speparated by = + MESSAGE=${1#*=} + ;; + --message=) + # message options, without value + printf 'ERROR: "--message" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + --repository) + # repository options, with value speparated by space + if [ -n "$2" ]; then + REPOSITORY=$2 + shift + else + printf 'ERROR: "--repository" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --repository=?*) + # repository options, with value speparated by = + REPOSITORY=${1#*=} + ;; + --repository=) + # repository options, without value + printf 'ERROR: "--repository" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + -n|--dry-run) + # disable actual commands + DRY_RUN=1 + ;; + -v|--verbose) + # print verbose information + VERBOSE=1 + ;; + --ansible) + # print information for Ansible + ANSIBLE=1 + ;; + --) + # End of all options. + shift + break + ;; + -?*|[[:alnum:]]*) + # ignore unknown options + printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +if [ -z "${MESSAGE}" ]; then + echo "Error: missing message parameter" >&2 + show_usage + exit 1 +fi +if [ -z "${REPOSITORY}" ]; then + echo "Error: missing repository parameter" >&2 + show_usage + exit 1 +fi +DRY_RUN=${DRY_RUN:-0} +VERBOSE=${VERBOSE:-0} +ANSIBLE=${ANSIBLE:-0} + +GIT_BIN=$(command -v git) +readonly GIT_BIN + +LOGGER_BIN=$(command -v logger) +readonly LOGGER_BIN + +export GIT_DIR="${REPOSITORY}/.git" +export GIT_WORK_TREE="${REPOSITORY}" + +if [ -d "${GIT_DIR}" ]; then + main +else + echo "There is no Git repository in '${REPOSITORY}'" >&2 + exit 1 +fi \ No newline at end of file diff --git a/etc-git/files/optimize-etc-git b/etc-git/files/optimize-etc-git deleted file mode 100644 index a7b7510f..00000000 --- a/etc-git/files/optimize-etc-git +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -git --git-dir /etc/.git gc --quiet diff --git a/etc-git/tasks/commit.yml b/etc-git/tasks/commit.yml index 4bcf8e5c..3f993771 100644 --- a/etc-git/tasks/commit.yml +++ b/etc-git/tasks/commit.yml @@ -1,25 +1,52 @@ --- +# /etc - name: Is /etc a git repository stat: path: /etc/.git register: _etc_git -- include: do_commit.yml - vars: - git_folder: "/etc" +- name: "evocommit /etc" + command: "/usr/local/bin/evocommit --ansible --repository /etc --message \"{{ commit_message | mandatory }}\"" + changed_when: + - _etc_git_commit.stdout + - "'CHANGED:' in _etc_git_commit.stdout" + ignore_errors: yes + register: _etc_git_commit when: - _etc_git.stat.exists - _etc_git.stat.isdir +# /etc/bind +- name: Is /etc/bind a git repository + stat: + path: /etc/bind/.git + register: _etc_bind_git + +- name: "evocommit /etc/bind" + command: "/usr/local/bin/evocommit --ansible --repository /etc/bind --message \"{{ commit_message | mandatory }}\"" + changed_when: + - _etc_bind_git_commit.stdout + - "'CHANGED:' in _etc_bind_git_commit.stdout" + ignore_errors: yes + register: _etc_bind_git_commit + when: + - _etc_bind_git.stat.exists + - _etc_bind_git.stat.isdir + +# /usr/share/scripts - name: Is /usr/share/scripts a git repository stat: path: /usr/share/scripts/.git register: _usr_share_scripts_git -- include: do_commit.yml - vars: - git_folder: "/usr/share/scripts" +- name: "evocommit /usr/share/scripts" + command: "/usr/local/bin/evocommit --ansible --repository /usr/share/scripts --message \"{{ commit_message | mandatory }}\"" + changed_when: + - _usr_share_scripts_git_commit.stdout + - "'CHANGED:' in _usr_share_scripts_git_commit.stdout" + ignore_errors: yes + register: _usr_share_scripts_git_commit when: - _usr_share_scripts_git.stat.exists - _usr_share_scripts_git.stat.isdir diff --git a/etc-git/tasks/do_commit.yml b/etc-git/tasks/do_commit.yml deleted file mode 100644 index 6b09eaaf..00000000 --- a/etc-git/tasks/do_commit.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- - -- name: "Remount /usr if needed" - include_role: - name: remount-usr - when: git_folder is match('/usr/.*') - -- name: "is {{ git_folder }} clean?" - command: git status --porcelain - args: - chdir: "{{ git_folder }}" - changed_when: False - register: git_status - when: not ansible_check_mode - ignore_errors: yes - tags: - - etc-git - - commit - -- debug: - var: git_status - verbosity: 3 - tags: - - etc-git - - commit - -- name: fetch current Git user.email - git_config: - name: user.email - repo: "{{ git_folder }}" - register: git_config_user_email - ignore_errors: yes - tags: - - etc-git - - commit - -- name: "set commit author" - set_fact: - commit_author: '{% if ansible_env.SUDO_USER is not defined %}root{% else %}{{ ansible_env.SUDO_USER }}{% endif %}' - commit_email: '{% if git_config_user_email.config_value is not defined or not git_config_user_email.config_value %}root@localhost{% else %}{{ git_config_user_email.config_value }}{% endif %}' # noqa 204 - tags: - - etc-git - - commit - -- name: "{{ git_folder }} modifications are committed" - shell: "git add -A . && git commit -m \"{{ commit_message | mandatory }}\" --author \"{{ commit_author | mandatory }} <{{ commit_email | mandatory }}>\"" - args: - chdir: "{{ git_folder }}" - register: commit_end_run - when: - - not ansible_check_mode - - git_status.stdout | length > 0 - ignore_errors: yes - tags: - - etc-git - - commit - -- debug: - var: commit_end_run - verbosity: 4 - tags: - - etc-git - - commit diff --git a/etc-git/tasks/main.yml b/etc-git/tasks/main.yml index 37d1c692..11be1899 100644 --- a/etc-git/tasks/main.yml +++ b/etc-git/tasks/main.yml @@ -7,6 +7,18 @@ tags: - etc-git +- include_role: + name: evolix/remount-usr + +- name: "evocommit script is installed" + copy: + src: evocommit + dest: /usr/local/bin/evocommit + mode: "0755" + force: yes + tags: + - etc-git + - include: repository.yml vars: repository_path: "/etc" @@ -32,6 +44,24 @@ - _usr_share_scripts.stat.isdir - ansible_distribution_major_version is version('10', '>=') +- name: "etc-git-optimize script is installed" + copy: + src: etc-git-optimize + dest: /usr/share/scripts/etc-git-optimize + mode: "0755" + force: yes + tags: + - etc-git + +- name: "etc-git-status script is installed" + copy: + src: etc-git-status + dest: /usr/share/scripts/etc-git-status + mode: "0755" + force: yes + tags: + - etc-git + - name: Check if cron is installed shell: "set -o pipefail && dpkg -l cron 2>/dev/null | grep -q -E '^(i|h)i'" args: @@ -41,29 +71,44 @@ check_mode: no register: is_cron_installed -- name: Optimize script is installed in monthly crontab - copy: - src: optimize-etc-git - dest: /etc/cron.monthly/optimize-etc-git - mode: "0750" - force: no +- block: + - name: Legacy cron jobs for /etc/.git status are absent + file: + dest: "{{ item }}" + state: absent + loop: + - /etc/cron.monthly/optimize-etc-git + - /etc/cron.d/etc-git-status + + - name: Cron job for monthly git optimization + cron: + name: "Monthly optimization" + cron_file: etc-git + special_time: "monthly" + user: root + job: "/usr/share/scripts/etc-git-optimize" + + - name: Cron job for hourly git status + cron: + name: "Hourly warning for unclean Git repository if nobody is connected" + cron_file: etc-git + special_time: "hourly" + user: root + job: "who > /dev/null || /usr/share/scripts/etc-git-status" + state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}" + + - name: Cron job for daily git status + cron: + name: "Daily warning for unclean Git repository" + cron_file: etc-git + user: root + job: "/usr/share/scripts/etc-git-status" + minute: "21" + hour: "21" + weekday: "*" + day: "*" + month: "*" + state: "{{ etc_git_monitor_status | bool | ternary('present','absent') }}" when: is_cron_installed.rc == 0 tags: - - etc-git - -- name: Cron job for /etc/.git status is installed - template: - src: etc-git-status.j2 - dest: /etc/cron.d/etc-git-status - mode: "0644" - when: is_cron_installed.rc == 0 and etc_git_monitor_status - tags: - - etc-git - -- name: Cron job for /etc/.git status is removed - file: - dest: /etc/cron.d/etc-git-status - state: absent - when: is_cron_installed.rc == 0 and not etc_git_monitor_status - tags: - - etc-git + - etc-git \ No newline at end of file diff --git a/etc-git/tasks/repository.yml b/etc-git/tasks/repository.yml index e8599c1e..80987da2 100644 --- a/etc-git/tasks/repository.yml +++ b/etc-git/tasks/repository.yml @@ -70,4 +70,4 @@ register: git_commit when: git_log.rc != 0 or (git_init is defined and git_init is changed) tags: - - etc-git + - etc-git \ No newline at end of file diff --git a/etc-git/templates/etc-git-status.j2 b/etc-git/templates/etc-git-status.j2 deleted file mode 100644 index e1696c54..00000000 --- a/etc-git/templates/etc-git-status.j2 +++ /dev/null @@ -1,4 +0,0 @@ -# {{ ansible_managed }} - -@hourly root who > /dev/null || git --git-dir=/etc/.git --work-tree=/etc status --short -21 21 * * * root git --git-dir=/etc/.git --work-tree=/etc status --short diff --git a/evoacme/files/evoacme.cron b/evoacme/files/evoacme.cron index 4d849673..7d4b598c 100755 --- a/evoacme/files/evoacme.cron +++ b/evoacme/files/evoacme.cron @@ -15,12 +15,13 @@ find "${CRT_DIR}" \ -maxdepth 1 \ -mindepth 1 \ -type d \ - ! -path "*accounts" \ - ! -path "*archive" \ - ! -path "*csr" \ - ! -path "*hooks" \ - ! -path "*keys" \ - ! -path "*live" \ - ! -path "*renewal" \ + ! -path "${CRT_DIR}/accounts" \ + ! -path "${CRT_DIR}/archive" \ + ! -path "${CRT_DIR}/csr" \ + ! -path "${CRT_DIR}/hooks" \ + ! -path "${CRT_DIR}/keys" \ + ! -path "${CRT_DIR}/live" \ + ! -path "${CRT_DIR}/renewal" \ + ! -path "${CRT_DIR}/renewal-hooks" \ -printf "%f\n" \ | xargs --max-args=1 --no-run-if-empty evoacme diff --git a/evocheck/README.md b/evocheck/README.md index ce9999c0..6739bef8 100644 --- a/evocheck/README.md +++ b/evocheck/README.md @@ -16,6 +16,4 @@ A separate `exec.yml` file can be imported manually in playbooks or roles to exe ## Variables We can force install via : -* `evocheck_force_install: local` : will copy the script provided by the role -* `evocheck_force_install: package` : will install the package via repositories * `evocheck_update_crontab` : will update the crontab (default: `True`) diff --git a/evocheck/defaults/main.yml b/evocheck/defaults/main.yml index e2d80c2a..6dc43677 100644 --- a/evocheck/defaults/main.yml +++ b/evocheck/defaults/main.yml @@ -1,4 +1,4 @@ --- -evocheck_force_install: False + evocheck_update_crontab: True evocheck_bin_dir: /usr/share/scripts diff --git a/evocheck/files/evocheck.sh b/evocheck/files/evocheck.sh index 7adf5757..fb8a6eeb 100644 --- a/evocheck/files/evocheck.sh +++ b/evocheck/files/evocheck.sh @@ -4,7 +4,8 @@ # Script to verify compliance of a Debian/OpenBSD server # powered by Evolix -readonly VERSION="20.12" +VERSION="21.10.4" +readonly VERSION # base functions @@ -12,7 +13,7 @@ show_version() { cat <, +Copyright 2009-2021 Evolix , Romain Dessort , Benoit Série , Gregory Colpart , @@ -62,6 +63,8 @@ detect_os() { 8) DEBIAN_RELEASE="jessie";; 9) DEBIAN_RELEASE="stretch";; 10) DEBIAN_RELEASE="buster";; + 11) DEBIAN_RELEASE="bullseye";; + 12) DEBIAN_RELEASE="bookworm";; esac fi elif [ "$(uname -s)" = "OpenBSD" ]; then @@ -71,7 +74,7 @@ detect_os() { } is_debian() { - test -n "${DEBIAN_RELEASE}" + test -n "${DEBIAN_RELEASE}" } is_debian_lenny() { test "${DEBIAN_RELEASE}" = "lenny" @@ -91,6 +94,12 @@ is_debian_stretch() { is_debian_buster() { test "${DEBIAN_RELEASE}" = "buster" } +is_debian_bullseye() { + test "${DEBIAN_RELEASE}" = "bullseye" +} +is_debian_bookworm() { + test "${DEBIAN_RELEASE}" = "bookworm" +} debian_release() { printf "%s" "${DEBIAN_RELEASE}" } @@ -109,7 +118,7 @@ is_pack_samba(){ } is_installed(){ for pkg in "$@"; do - dpkg -l "$pkg" 2>/dev/null | grep -q -E '^(i|h)i' || return 1 + dpkg -l "$pkg" 2> /dev/null | grep -q -E '^(i|h)i' || return 1 done } minifirewall_file() { @@ -147,7 +156,7 @@ check_lsbrelease(){ ## only the major version matters lhs=$(${LSB_RELEASE_BIN} --release --short | cut -d "." -f 1) rhs=$(cut -d "." -f 1 < /etc/debian_version) - test "$lhs" = "$rhs" || failed "IS_LSBRELEASE" "release is not consistent between lsb_release and /etc/debian_version" + test "$lhs" = "$rhs" || failed "IS_LSBRELEASE" "release is not consistent between lsb_release (${lhs}) and /etc/debian_version (${rhs})" else failed "IS_LSBRELEASE" "lsb_release is missing or not executable" fi @@ -165,7 +174,7 @@ check_dpkgwarning() { test -e /etc/apt/apt.conf \ && failed "IS_DPKGWARNING" "/etc/apt/apt.conf is missing" fi - elif is_debian_stretch || is_debian_buster; then + elif is_debian_stretch || is_debian_buster || is_debian_bullseye; then test -e /etc/apt/apt.conf.d/z-evolinux.conf \ || failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/z-evolinux.conf is missing" fi @@ -211,7 +220,6 @@ check_vartmpfs() { else df /var/tmp | grep -q tmpfs || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs" fi - } check_serveurbase() { is_installed serveur-base || failed "IS_SERVEURBASE" "serveur-base package is not installed" @@ -224,8 +232,19 @@ check_syslogconf() { || failed "IS_SYSLOGCONF" "syslog evolix config file missing" } check_debiansecurity() { - grep -q "^deb.*security" /etc/apt/sources.list \ - || failed "IS_DEBIANSECURITY" "missing debian security repository" + if is_debian_bullseye; then + # https://www.debian.org/releases/bullseye/amd64/release-notes/ch-information.html#security-archive + pattern="^deb https://deb\.debian\.org/debian-security/? bullseye-security main" + elif is_debian_buster; then + pattern="^deb http://security\.debian\.org/debian-security/? buster/updates main" + elif is_debian_stretch; then + pattern="^deb http://security\.debian\.org/debian-security/? stretch/updates main" + else + pattern="^deb.*security" + fi + + source_file="/etc/apt/sources.list" + grep -qE "${pattern}" "${source_file}" || failed "IS_DEBIANSECURITY" "missing debian security repository" } check_aptitudeonly() { if is_debian_squeeze || is_debian_wheezy; then @@ -234,13 +253,13 @@ check_aptitudeonly() { fi } check_aptitude() { - if is_debian_jessie || is_debian_stretch || is_debian_buster; then + if is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then test -e /usr/bin/aptitude && failed "IS_APTITUDE" "aptitude may not be installed on Debian >=8" fi } check_aptgetbak() { - if is_debian_jessie || is_debian_stretch || is_debian_buster; then - test -e /usr/bin/apt-get.bak && failed "IS_APTGETBAK" "missing dpkg-divert apt-get.bak" + if is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then + test -e /usr/bin/apt-get.bak && failed "IS_APTGETBAK" "prohibit the installation of apt-get.bak with dpkg-divert(1)" fi } check_apticron() { @@ -276,7 +295,7 @@ check_mountfstab() { fi } check_listchangesconf() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed apt-listchanges; then failed "IS_LISTCHANGESCONF" "apt-listchanges must not be installed on Debian >=9" fi @@ -296,7 +315,7 @@ check_customcrontab() { test "$found_lines" = 4 && failed "IS_CUSTOMCRONTAB" "missing custom field in crontab" } check_sshallowusers() { - grep -E -qi "(AllowUsers|AllowGroups)" /etc/ssh/sshd_config \ + grep -E -qir "(AllowUsers|AllowGroups)" /etc/ssh/sshd_config /etc/ssh/sshd_config.d \ || failed "IS_SSHALLOWUSERS" "missing AllowUsers or AllowGroups directive in sshd_config" } check_diskperf() { @@ -307,7 +326,7 @@ check_tmoutprofile() { grep -sq "TMOUT=" /etc/profile /etc/profile.d/evolinux.sh || failed "IS_TMOUTPROFILE" "TMOUT is not set" } check_alert5boot() { - if is_debian_buster; then + if is_debian_buster || is_debian_bullseye; then grep -qs "^date" /usr/share/scripts/alert5.sh || failed "IS_ALERT5BOOT" "boot mail is not sent by alert5 init script" test -f /etc/systemd/system/alert5.service || failed "IS_ALERT5BOOT" "alert5 unit file is missing" systemctl is-enabled alert5 -q || failed "IS_ALERT5BOOT" "alert5 unit is not enabled" @@ -320,7 +339,7 @@ check_alert5boot() { fi } check_alert5minifw() { - if is_debian_buster; then + if is_debian_buster || is_debian_bullseye; then grep -qs "^/etc/init.d/minifirewall" /usr/share/scripts/alert5.sh \ || failed "IS_ALERT5MINIFW" "Minifirewall is not started by alert5 script or script is missing" else @@ -336,6 +355,13 @@ check_minifw() { /sbin/iptables -L -n | grep -q -E "^ACCEPT\s*all\s*--\s*31\.170\.8\.4\s*0\.0\.0\.0/0\s*$" \ || failed "IS_MINIFW" "minifirewall seems not starded" } +check_minifw_includes() { + if is_debian_bullseye; then + if grep -q -e '/sbin/iptables' -e '/sbin/ip6tables' "${MINIFW_FILE}"; then + failed "IS_MINIFWINCLUDES" "minifirewall has direct iptables invocations in ${MINIFW_FILE} that should go in /etc/minifirewall.d/" + fi + fi +} check_nrpeperms() { if [ -d /etc/nagios ]; then nagiosDir="/etc/nagios" @@ -357,7 +383,11 @@ check_nrpedisks() { test "$NRPEDISKS" = "$DFDISKS" || failed "IS_NRPEDISKS" "there must be $DFDISKS check_disk in nrpe.cfg" } check_nrpepid() { - if ! is_debian_squeeze; then + if is_debian_bullseye; then + { test -e /etc/nagios/nrpe.cfg \ + && grep -q "^pid_file=/run/nagios/nrpe.pid" /etc/nagios/nrpe.cfg; + } || failed "IS_NRPEPID" "missing or wrong pid_file directive in nrpe.cfg" + elif ! is_debian_squeeze; then { test -e /etc/nagios/nrpe.cfg \ && grep -q "^pid_file=/var/run/nagios/nrpe.pid" /etc/nagios/nrpe.cfg; } || failed "IS_NRPEPID" "missing or wrong pid_file directive in nrpe.cfg" @@ -372,7 +402,7 @@ check_grsecprocs() { } check_apachemunin() { if test -e /etc/apache2/apache2.conf; then - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then { test -h /etc/apache2/mods-enabled/status.load \ && test -h /etc/munin/plugins/apache_accesses \ && test -h /etc/munin/plugins/apache_processes \ @@ -392,17 +422,20 @@ check_apachemunin() { check_mysqlutils() { MYSQL_ADMIN=${MYSQL_ADMIN:-mysqladmin} if is_installed mysql-server; then - # You can configure MYSQL_ADMIN in evocheck.cf - if ! grep -qs "$MYSQL_ADMIN" /root/.my.cnf; then - failed "IS_MYSQLUTILS" "mysqladmin missing in /root/.my.cnf" + # With Debian 11 and later, root can connect to MariaDB with the socket + if is_debian_wheezy || is_debian_jessie || is_debian_stretch || is_debian_buster; then + # You can configure MYSQL_ADMIN in evocheck.cf + if ! grep -qs "^user *= *${MYSQL_ADMIN}" /root/.my.cnf; then + failed "IS_MYSQLUTILS" "${MYSQL_ADMIN} missing in /root/.my.cnf" + fi fi if ! test -x /usr/bin/mytop; then if ! test -x /usr/local/bin/mytop; then failed "IS_MYSQLUTILS" "mytop binary missing" fi fi - if ! grep -qs debian-sys-maint /root/.mytop; then - failed "IS_MYSQLUTILS" "debian-sys-maint missing in /root/.mytop" + if ! grep -qs '^user *=' /root/.mytop; then + failed "IS_MYSQLUTILS" "credentials missing in /root/.mytop" fi fi } @@ -431,7 +464,7 @@ check_muninlogrotate() { } # Verification de l'activation de Squid dans le cas d'un pack mail check_squid() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then squidconffile="/etc/squid/evolinux-custom.conf" else squidconffile="/etc/squid*/squid.conf" @@ -444,7 +477,8 @@ check_squid() { && grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d $host -j ACCEPT" "$MINIFW_FILE" \ && grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -d 127.0.0.(1|0/8) -j ACCEPT" "$MINIFW_FILE" \ && grep -qE "^[^#]*iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port.* $http_port" "$MINIFW_FILE"; - } || failed "IS_SQUID" "missing squid rules in minifirewall" + } || grep -qE "^PROXY='?on'?" "$MINIFW_FILE" \ + || failed "IS_SQUID" "missing squid rules in minifirewall" fi } check_evomaintenance_fw() { @@ -473,7 +507,7 @@ check_log2mailrunning() { fi } check_log2mailapache() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then conf=/etc/log2mail/config/apache else conf=/etc/log2mail/config/default @@ -532,10 +566,10 @@ check_network_interfaces() { } # Verify if all if are in auto check_autoif() { - if is_debian_stretch || is_debian_buster; then - interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | tr "\n" " ") + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then + interfaces=$(/sbin/ip address show up | grep "^[0-9]*:" | grep -E -v "(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 2 | tr -d : | cut -d@ -f1 | tr "\n" " ") else - interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap)" | cut -d " " -f 1 |tr "\n" " ") + interfaces=$(/sbin/ifconfig -s | tail -n +2 | grep -E -v "^(lo|vnet|docker|veth|tun|tap|macvtap|vrrp)" | cut -d " " -f 1 |tr "\n" " ") fi for interface in $interfaces; do if ! grep -q "^auto $interface" /etc/network/interfaces; then @@ -569,6 +603,7 @@ check_evobackup_exclude_mount() { failed "IS_EVOBACKUP_EXCLUDE_MOUNT" "${mount} is not excluded from ${evobackup_file} backup script" done done + rm -rf "${excludes_file}" } # Verification de la presence du userlogrotate check_userlogrotate() { @@ -681,6 +716,7 @@ check_backupuptodate() { backup_dir="/home/backup" if [ -d "${backup_dir}" ]; then if [ -n "$(ls -A ${backup_dir})" ]; then + # shellcheck disable=SC2231 for file in ${backup_dir}/*; do limit=$(date +"%s" -d "now - 2 day") updated_at=$(stat -c "%Y" "$file") @@ -771,7 +807,7 @@ check_tune2fs_m5() { done } check_evolinuxsudogroup() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if grep -q "^evolinux-sudo:" /etc/group; then grep -qE '^%evolinux-sudo +ALL ?= ?\(ALL:ALL\) ALL' /etc/sudoers.d/evolinux \ || failed "IS_EVOLINUXSUDOGROUP" "missing evolinux-sudo directive in sudoers file" @@ -779,7 +815,7 @@ check_evolinuxsudogroup() { fi } check_userinadmgroup() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then users=$(grep "^evolinux-sudo:" /etc/group | awk -F: '{print $4}' | tr ',' ' ') for user in $users; do if ! groups "$user" | grep -q adm; then @@ -790,7 +826,7 @@ check_userinadmgroup() { fi } check_apache2evolinuxconf() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if test -d /etc/apache2; then { test -L /etc/apache2/conf-enabled/z-evolinux-defaults.conf \ && test -L /etc/apache2/conf-enabled/zzz-evolinux-custom.conf \ @@ -800,7 +836,7 @@ check_apache2evolinuxconf() { fi } check_backportsconf() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then grep -qsE "^[^#].*backports" /etc/apt/sources.list \ && failed "IS_BACKPORTSCONF" "backports can't be in main sources list" if grep -qsE "^[^#].*backports" /etc/apt/sources.list.d/*.list; then @@ -810,7 +846,7 @@ check_backportsconf() { fi } check_bind9munin() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed bind9; then { test -L /etc/munin/plugins/bind9 \ && test -e /etc/munin/plugin-conf.d/bind9; @@ -819,7 +855,7 @@ check_bind9munin() { fi } check_bind9logrotate() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed bind9; then test -e /etc/logrotate.d/bind9 || failed "IS_BIND9LOGROTATE" "missing bind logrotate file" fi @@ -840,7 +876,7 @@ check_broadcomfirmware() { check_hardwareraidtool() { LSPCI_BIN=$(command -v lspci) if [ -x "${LSPCI_BIN}" ]; then - if ${LSPCI_BIN} | grep -q 'MegaRAID SAS'; then + if ${LSPCI_BIN} | grep -q 'MegaRAID'; then # shellcheck disable=SC2015 is_installed megacli && { is_installed megaclisas-status || is_installed megaraidsas-status; } \ || failed "IS_HARDWARERAIDTOOL" "Mega tools not found" @@ -853,7 +889,7 @@ check_hardwareraidtool() { fi } check_log2mailsystemdunit() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then systemctl -q is-active log2mail.service \ || failed "IS_LOG2MAILSYSTEMDUNIT" "log2mail unit not running" test -f /etc/systemd/system/log2mail.service \ @@ -869,7 +905,7 @@ check_listupgrade() { || failed "IS_LISTUPGRADE" "missing listupgrade script or not executable" } check_mariadbevolinuxconf() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed mariadb-server; then { test -f /etc/mysql/mariadb.conf.d/z-evolinux-defaults.cnf \ && test -f /etc/mysql/mariadb.conf.d/zzz-evolinux-custom.cnf; @@ -945,6 +981,7 @@ check_elastic_backup() { fi } check_mariadbsystemdunit() { + # TODO: check if it is still needed for bullseye if is_debian_stretch || is_debian_buster; then if is_installed mariadb-server; then if systemctl -q is-active mariadb.service; then @@ -955,7 +992,7 @@ check_mariadbsystemdunit() { fi } check_mysqlmunin() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed mariadb-server; then for file in mysql_bytes mysql_queries mysql_slowqueries \ mysql_threads mysql_connections mysql_files_tables \ @@ -973,7 +1010,7 @@ check_mysqlmunin() { fi } check_mysqlnrpe() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed mariadb-server; then nagios_file=~nagios/.my.cnf if ! test -f ${nagios_file}; then @@ -989,9 +1026,10 @@ check_mysqlnrpe() { fi } check_phpevolinuxconf() { - if is_debian_stretch || is_debian_buster; then - is_debian_stretch && phpVersion="7.0" - is_debian_buster && phpVersion="7.3" + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then + is_debian_stretch && phpVersion="7.0" + is_debian_buster && phpVersion="7.3" + is_debian_bullseye && phpVersion="7.4" if is_installed php; then { test -f /etc/php/${phpVersion}/cli/conf.d/z-evolinux-defaults.ini \ && test -f /etc/php/${phpVersion}/cli/conf.d/zzz-evolinux-custom.ini @@ -1000,15 +1038,15 @@ check_phpevolinuxconf() { fi } check_squidlogrotate() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed squid; then - grep -q monthly /etc/logrotate.d/squid \ + grep -q -e monthly -e daily /etc/logrotate.d/squid \ || failed "IS_SQUIDLOGROTATE" "missing squid logrotate file" fi fi } check_squidevolinuxconf() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if is_installed squid; then { grep -qs "^CONFIG=/etc/squid/evolinux-defaults.conf$" /etc/default/squid \ && test -f /etc/squid/evolinux-defaults.conf \ @@ -1044,7 +1082,7 @@ check_duplicate_fs_label() { fi } check_evolix_user() { - grep -q "evolix:" /etc/passwd \ + grep -q -E "^evolix:" /etc/passwd \ && failed "IS_EVOLIX_USER" "evolix user should be deleted, used only for install" } check_evoacme_cron() { @@ -1083,7 +1121,7 @@ check_apache_confenabled() { # Starting from Jessie and Apache 2.4, /etc/apache2/conf.d/ # must be replaced by conf-available/ and config files symlinked # to conf-enabled/ - if is_debian_jessie || is_debian_stretch || is_debian_buster; then + if is_debian_jessie || is_debian_stretch || is_debian_buster || is_debian_bullseye; then if [ -f /etc/apache2/apache2.conf ]; then test -d /etc/apache2/conf.d/ \ && failed "IS_APACHE_CONFENABLED" "apache's conf.d directory must not exists" @@ -1095,7 +1133,7 @@ check_apache_confenabled() { check_meltdown_spectre() { # For Stretch, detection is easy as the kernel use # /sys/devices/system/cpu/vulnerabilities/ - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then for vuln in meltdown spectre_v1 spectre_v2; do test -f "/sys/devices/system/cpu/vulnerabilities/$vuln" \ || failed "IS_MELTDOWN_SPECTRE" "vulnerable to $vuln" @@ -1148,7 +1186,7 @@ check_usrsharescripts() { test "$expected" = "$actual" || failed "IS_USRSHARESCRIPTS" "/usr/share/scripts must be $expected" } check_sshpermitrootno() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then if grep -q "^PermitRoot" /etc/ssh/sshd_config; then grep -E -qi "PermitRoot.*no" /etc/ssh/sshd_config \ || failed "IS_SSHPERMITROOTNO" "PermitRoot should be set at no" @@ -1159,7 +1197,7 @@ check_sshpermitrootno() { fi } check_evomaintenanceusers() { - if is_debian_stretch || is_debian_buster; then + if is_debian_stretch || is_debian_buster || is_debian_bullseye; then users=$(getent group evolinux-sudo | cut -d':' -f4 | tr ',' ' ') else if [ -f /etc/sudoers.d/evolinux ]; then @@ -1295,6 +1333,154 @@ check_nginx_letsencrypt_uptodate() { fi } +check_lxc_container_resolv_conf() { + if is_installed lxc; then + container_list=$(lxc-ls) + current_resolvers=$(grep nameserver /etc/resolv.conf | sed 's/nameserver//g' ) + + for container in $container_list; do + if [ -f "/var/lib/lxc/${container}/rootfs/etc/resolv.conf" ]; then + + while read -r resolver; do + if ! grep -qE "^nameserver\s+${resolver}" "/var/lib/lxc/${container}/rootfs/etc/resolv.conf"; then + failed "IS_LXC_CONTAINER_RESOLV_CONF" "resolv.conf miss-match beween host and container : missing nameserver ${resolver} in container ${container} resolv.conf" + fi + done <<< "${current_resolvers}" + + else + failed "IS_LXC_CONTAINER_RESOLV_CONF" "resolv.conf missing in container ${container}" + fi + done + fi +} +download_versions() { + local file + file=${1:-} + + ## The file is supposed to list programs : each on a line, then its latest version number + ## Examples: + # evoacme 21.06 + # evomaintenance 0.6.4 + + if is_debian; then + versions_url="https://upgrades.evolix.org/versions-${DEBIAN_RELEASE}" + elif is_openbsd; then + versions_url="https://upgrades.evolix.org/versions-${OPENBSD_RELEASE}" + else + failed "IS_VERSIONS_CHECK" "error determining os release" + fi + + # fetch timeout, in seconds + timeout=10 + + if command -v curl > /dev/null; then + curl --max-time ${timeout} --fail --silent --output "${versions_file}" "${versions_url}" + elif command -v wget > /dev/null; then + wget --timeout=${timeout} --quiet "${versions_url}" -O "${versions_file}" + elif command -v GET; then + GET -t ${timeout}s "${versions_url}" > "${versions_file}" + else + failed "IS_VERSIONS_CHECK" "failed to find curl, wget or GET" + fi + test "$?" -eq 0 || failed "IS_VERSIONS_CHECK" "failed to download ${versions_url} to ${versions_file}" +} +get_command() { + local program + program=${1:-} + + case "${program}" in + ## Special cases where the program name is different than the command name + evocheck) echo "${0}" ;; + evomaintenance) command -v "evomaintenance.sh" ;; + listupgrade) command -v "evolistupgrade.sh" ;; + old-kernel-autoremoval) command -v "old-kernel-autoremoval.sh" ;; + mysql-queries-killer) command -v "mysql-queries-killer.sh" ;; + + ## General case, where the program name is the same as the command name + *) command -v "${program}" ;; + esac +} +get_version() { + local program + local command + program=${1:-} + command=${2:-} + + case "${program}" in + ## Special case if `command --version => 'command` is not the standard way to get the version + # my_command) + # /path/to/my_command --get-version + # ;; + + add-vm) + grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2 + ;; + ## Let's try the --version flag before falling back to grep for the constant + kvmstats) + if ${command} --version > /dev/null 2> /dev/null; then + ${command} --version 2> /dev/null | head -1 | cut -d ' ' -f 3 + else + grep '^VERSION=' "${command}" | head -1 | cut -d '=' -f 2 + fi + ;; + + ## General case to get the version + *) ${command} --version 2> /dev/null | head -1 | cut -d ' ' -f 3 ;; + esac +} +check_version() { + local program + local expected_version + program=${1:-} + expected_version=${2:-} + + command=$(get_command "${program}") + if [ -n "${command}" ]; then + # shellcheck disable=SC2086 + actual_version=$(get_version "${program}" "${command}") + # printf "program:%s expected:%s actual:%s\n" "${program}" "${expected_version}" "${actual_version}" + if [ -z "${actual_version}" ]; then + failed "IS_VERSIONS_CHECK" "failed to lookup actual version of ${program}" + elif dpkg --compare-versions "${actual_version}" lt "${expected_version}"; then + failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is older than expected version ${expected_version}" + elif dpkg --compare-versions "${actual_version}" gt "${expected_version}"; then + failed "IS_VERSIONS_CHECK" "${program} version ${actual_version} is newer than expected version ${expected_version}, you should update tour index." + else + : # Version check OK + fi + fi +} +add_to_path() { + local new_path + new_path=${1:-} + + echo "$PATH" | grep -qF "${new_path}" || export PATH="${PATH}:${new_path}" +} +check_versions() { + versions_file=$(mktemp --tmpdir=/tmp "evocheck-versions.XXXXX") + # shellcheck disable=SC2064 + trap "rm -f ${versions_file}" 0 + download_versions "${versions_file}" + add_to_path "/usr/share/scripts" + + grep -v '^ *#' < "${versions_file}" | while IFS= read -r line; do + local program + local version + program=$(echo "${line}" | cut -d ' ' -f 1) + version=$(echo "${line}" | cut -d ' ' -f 2) + + if [ -n "${program}" ]; then + if [ -n "${version}" ]; then + check_version "${program}" "${version}" + else + failed "IS_VERSIONS_CHECK" "failed to lookup expected version for ${program}" + fi + fi + done + + rm -f "${versions_file}" +} + main() { # Default return code : 0 = no error RC=0 @@ -1349,6 +1535,8 @@ main() { test "${IS_ALERT5MINIFW:=1}" = 1 && test "${IS_MINIFW:=1}" = 1 && check_minifw test "${IS_NRPEPERMS:=1}" = 1 && check_nrpeperms test "${IS_MINIFWPERMS:=1}" = 1 && check_minifwperms + # Enable when minifirewall is released + test "${IS_MINIFWINCLUDES:=0}" = 1 && check_minifw_includes test "${IS_NRPEDISKS:=0}" = 1 && check_nrpedisks test "${IS_NRPEPID:=1}" = 1 && check_nrpepid test "${IS_GRSECPROCS:=1}" = 1 && check_grsecprocs @@ -1421,6 +1609,8 @@ main() { test "${IS_APT_VALID_UNTIL:=1}" = 1 && check_apt_valid_until test "${IS_CHROOTED_BINARY_UPTODATE:=1}" = 1 && check_chrooted_binary_uptodate test "${IS_NGINX_LETSENCRYPT_UPTODATE:=1}" = 1 && check_nginx_letsencrypt_uptodate + test "${IS_LXC_CONTAINER_RESOLV_CONF:=1}" = 1 && check_lxc_container_resolv_conf + test "${IS_CHECK_VERSIONS:=1}" = 1 && check_versions fi #----------------------------------------------------------- @@ -1528,10 +1718,13 @@ main() { exit ${RC} } +PROGNAME=$(basename "$0") # shellcheck disable=SC2034 -readonly PROGNAME=$(basename "$0") -# shellcheck disable=2124 -readonly ARGS=$@ +readonly PROGNAME + +# shellcheck disable=SC2124 +ARGS=$@ +readonly ARGS # Disable LANG* export LANG=C @@ -1557,6 +1750,7 @@ while :; do IS_KERNELUPTODATE=0 IS_UPTIME=0 IS_MELTDOWN_SPECTRE=0 + IS_CHECK_VERSIONS=0 ;; -v|--verbose) VERBOSE=1 diff --git a/evocheck/tasks/install_local.yml b/evocheck/tasks/install.yml similarity index 100% rename from evocheck/tasks/install_local.yml rename to evocheck/tasks/install.yml diff --git a/evocheck/tasks/install_package.yml b/evocheck/tasks/install_package.yml deleted file mode 100644 index 34e672e5..00000000 --- a/evocheck/tasks/install_package.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: install evocheck from package - apt: - name: evocheck - state: present diff --git a/evocheck/tasks/main.yml b/evocheck/tasks/main.yml index 87e2d636..2032740b 100644 --- a/evocheck/tasks/main.yml +++ b/evocheck/tasks/main.yml @@ -1,10 +1,13 @@ --- -- include: install_local.yml - when: evocheck_force_install == "local" +- name: Package install is not supported anymore + fail: + msg: Package install is not supported anymore + when: + - evocheck_force_install is defined + - evocheck_force_install == "package" -- include: install_package.yml - when: evocheck_force_install == "package" +- include: install.yml - include: cron.yml when: evocheck_update_crontab | bool diff --git a/evolinux-base/defaults/main.yml b/evolinux-base/defaults/main.yml index 26f6e4c8..591bc62b 100644 --- a/evolinux-base/defaults/main.yml +++ b/evolinux-base/defaults/main.yml @@ -89,6 +89,7 @@ evolinux_packages_invalid_mta: True evolinux_packages_delete_nfs: True evolinux_packages_listchanges: True evolinux_packages_logcheck_recipient: False +evolinux_packages_delete_aptlistchanges: True # system @@ -164,8 +165,10 @@ evolinux_logs_include: True evolinux_logs_logrotate_confs: True evolinux_logs_default_rotate: True +evolinux_logs_default_dateext : True evolinux_logs_disable_logrotate_rsyslog: True evolinux_logs_rsyslog_conf: True +evolinux_logrotate_dateformat: "-%Y%m%d%H" # default www @@ -206,7 +209,6 @@ evolinux_fail2ban_include: False # Evocheck evolinux_evocheck_include: True -evolinux_evocheck_force_install: "local" # Listupgrade @@ -218,3 +220,6 @@ evolinux_generateldif_include: True # Cron check_hpraid evolinux_cron_checkhpraid_frequency: daily + +# Motd +evolinux_motd_include: True \ No newline at end of file diff --git a/evolinux-base/files/alert5.service b/evolinux-base/files/alert5.service index ea560a51..ea966b37 100644 --- a/evolinux-base/files/alert5.service +++ b/evolinux-base/files/alert5.service @@ -1,9 +1,10 @@ [Unit] Description=Evolix alert5 script +After=network.target [Service] Type=oneshot ExecStart=/usr/share/scripts/alert5.sh [Install] -WantedBy=multi-user.target +WantedBy=multi-user.target \ No newline at end of file diff --git a/evolinux-base/files/backup-server-state.sh b/evolinux-base/files/backup-server-state.sh new file mode 100644 index 00000000..0c503c37 --- /dev/null +++ b/evolinux-base/files/backup-server-state.sh @@ -0,0 +1,635 @@ +#!/bin/sh + +PROGNAME="backup-server-state" + +VERSION="22.01" +readonly VERSION + +backup_dir= +rc=0 + +# base functions + +show_version() { + cat <, + Jérémy Lecour + and others. + +${PROGNAME} comes with ABSOLUTELY NO WARRANTY.This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public License v3.0 for details. +END +} +show_help() { + cat < "${backup_dir}/current_packages.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* dpkg OK" + else + debug "* dpkg ERROR :" + debug "${last_result}" + rc=10 + fi +} + +backup_uptime() { + debug "Backup uptime" + + last_result=$(uptime > "${backup_dir}/uptime.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* uptime OK" + else + debug "* uptime ERROR" + debug "${last_result}" + rc=10 + fi +} + +backup_processes() { + debug "Backup process list" + + last_result=$(ps fauxw > "${backup_dir}/ps.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* ps OK" + else + debug "* ps ERROR" + debug "${last_result}" + rc=10 + fi + + pstree_bin=$(command -v pstree) + + if [ -z "${pstree_bin}" ]; then + last_result=$(pstree -pan > "${backup_dir}/pstree.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* pstree OK" + else + debug "* pstree ERROR" + debug "${last_result}" + rc=10 + fi + fi +} + +backup_netstat() { + debug "Backup network status" + + ss_bin=$(command -v ss) + if [ -z "${ss_bin}" ]; then + last_result=$(${ss_bin} -tanpul > "${backup_dir}/netstat-ss.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* ss OK" + else + debug "* ss ERROR" + debug "${last_result}" + rc=10 + fi + fi + + netstat_bin=$(command -v netstat) + if [ -z "${netstat_bin}" ]; then + last_result=$(netstat -laputen > "${backup_dir}/netstat-legacy.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* netstat OK" + else + debug "* netstat ERROR" + debug "${last_result}" + rc=10 + fi + fi +} + +backup_netcfg() { + debug "Backup network configuration" + + last_result=$(ip address show > "${backup_dir}/ip-address.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* ip address OK" + else + debug "* ip address ERROR" + debug "${last_result}" + rc=10 + fi + + last_result=$(ip route show > "${backup_dir}/ip-route.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* ip route OK" + else + debug "* ip route ERROR" + debug "${last_result}" + rc=10 + fi +} + +backup_iptables() { + debug "Backup iptables" + + last_result=$({ /sbin/iptables -L -n -v; /sbin/iptables -t filter -L -n -v; } > "${backup_dir}/iptables.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* iptables OK" + else + debug "* iptables ERROR" + debug "${last_result}" + rc=10 + fi +} + +backup_sysctl() { + debug "Backup sysctl values" + + last_result=$(sysctl -a | sort -h > "${backup_dir}/sysctl.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* sysctl OK" + else + debug "* sysctl ERROR" + debug "${last_result}" + rc=10 + fi +} + +backup_virsh() { + debug "Backup virsh list" + + virsh_bin=$(command -v virsh) + + if [ -n "${virsh_bin}" ]; then + last_result=$(${virsh_bin} list --all > "${backup_dir}/virsh-list.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* virsh list OK" + else + debug "* virsh list ERROR" + debug "${last_result}" + rc=10 + fi + else + debug "* virsh not installed" + fi +} + +backup_lxc() { + debug "Backup lxc list" + + lxc_ls_bin=$(command -v lxc-ls) + + if [ -n "${lxc_ls_bin}" ]; then + last_result=$(${lxc_ls_bin} --fancy > "${backup_dir}/lxc-list.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* lxc list OK" + else + debug "* lxc list ERROR" + debug "${last_result}" + rc=10 + fi + else + debug "* lxc-ls not installed" + fi +} + +backup_mount() { + debug "Backup mount points" + + findmnt_bin=$(command -v findmnt) + mount_bin=$(command -v mount) + + if [ -n "${findmnt_bin}" ]; then + last_result=$(${findmnt_bin} > "${backup_dir}/mount.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* mount points OK" + else + debug "* mount points ERROR" + debug "${last_result}" + rc=10 + fi + elif [ -n "${mount_bin}" ]; then + last_result=$(${mount_bin} > "${backup_dir}/mount.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* mount points OK" + else + debug "* mount points ERROR" + debug "${last_result}" + rc=10 + fi + else + debug "* findmnt and mount not installed" + fi +} + +backup_df() { + debug "Backup df" + + df_bin=$(command -v df) + + if [ -n "${df_bin}" ]; then + last_result=$(${df_bin} --portability > "${backup_dir}/df.txt") + last_rc=$? + + if [ ${last_rc} -eq 0 ]; then + debug "* df OK" + else + debug "* df ERROR" + debug "${last_result}" + rc=10 + fi + else + debug "* df not installed" + fi +} + +main() { + if [ -z "${backup_dir}" ]; then + echo "ERROR: You must provide the --backup-dir argument" >&2 + exit 1 + fi + + if [ -d "${backup_dir}" ]; then + echo "ERROR: The backup directory ${backup_dir} already exists. Delete it first." >&2 + exit 2 + else + create_backup_dir + fi + + if [ "${DO_ETC}" -eq 1 ]; then + backup_etc + fi + if [ "${DO_DPKG}" -eq 1 ]; then + backup_dpkg + fi + if [ "${DO_APT}" -eq 1 ]; then + backup_apt + fi + if [ "${DO_PACKAGES}" -eq 1 ]; then + backup_packages + fi + if [ "${DO_PROCESSES}" -eq 1 ]; then + backup_processes + fi + if [ "${DO_UPTIME}" -eq 1 ]; then + backup_uptime + fi + if [ "${DO_NETSTAT}" -eq 1 ]; then + backup_netstat + fi + if [ "${DO_NETCFG}" -eq 1 ]; then + backup_netcfg + fi + if [ "${DO_IPTABLES}" -eq 1 ]; then + backup_iptables + fi + if [ "${DO_SYSCTL}" -eq 1 ]; then + backup_sysctl + fi + if [ "${DO_VIRSH}" -eq 1 ]; then + backup_virsh + fi + if [ "${DO_LXC}" -eq 1 ]; then + backup_lxc + fi + if [ "${DO_MOUNT}" -eq 1 ]; then + backup_mount + fi + if [ "${DO_DF}" -eq 1 ]; then + backup_df + fi + + debug "=> Your backup is available at ${backup_dir}" + exit ${rc} +} + +# parse options +# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a +while :; do + case $1 in + -h|-\?|--help) + show_help + exit 0 + ;; + -V|--version) + show_version + exit 0 + ;; + -v|--verbose) + VERBOSE=1 + ;; + + -d|--backup-dir) + # with value separated by space + if [ -n "$2" ]; then + backup_dir=$2 + shift + else + printf 'ERROR: "-d|--backup-dir" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --backup-dir=?*) + # with value speparated by = + backup_dir=${1#*=} + ;; + --backup-dir=) + # without value + printf 'ERROR: "--backup-dir" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + + --etc) + DO_ETC=1 + ;; + --no-etc) + DO_ETC=0 + ;; + + --dpkg) + DO_DPKG=1 + ;; + --no-dpkg) + DO_DPKG=0 + ;; + + --apt) + DO_APT=1 + ;; + --no-apt) + DO_APT=0 + ;; + + --packages) + DO_PACKAGES=1 + ;; + --no-packages) + DO_PACKAGES=0 + ;; + + --processes) + DO_PROCESSES=1 + ;; + --no-processes) + DO_PROCESSES=0 + ;; + + --uptime) + DO_UPTIME=1 + ;; + --no-uptime) + DO_UPTIME=0 + ;; + + --netstat) + DO_NETSTAT=1 + ;; + --no-netstat) + DO_NETSTAT=0 + ;; + + --netcfg) + DO_NETCFG=1 + ;; + --no-netcfg) + DO_NETCFG=0 + ;; + + --iptables) + DO_IPTABLES=1 + ;; + --no-iptables) + DO_IPTABLES=0 + ;; + + --sysctl) + DO_SYSCTL=1 + ;; + --no-sysctl) + DO_SYSCTL=0 + ;; + + --virsh) + DO_VIRSH=1 + ;; + --no-virsh) + DO_VIRSH=0 + ;; + + --lxc) + DO_LXC=1 + ;; + --no-lxc) + DO_LXC=0 + ;; + + --mount) + DO_MOUNT=1 + ;; + --no-mount) + DO_MOUNT=0 + ;; + + --df) + DO_DF=1 + ;; + --no-df) + DO_DF=0 + ;; + + --) + # End of all options. + shift + break + ;; + -?*) + # ignore unknown options + printf 'WARN: Unknown option : %s\n' "$1" >&2 + exit 1 + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +# Default values +: "${VERBOSE:=0}" +: "${DO_ETC:=0}" +: "${DO_DPKG:=0}" +: "${DO_APT:=1}" +: "${DO_PACKAGES:=1}" +: "${DO_PROCESSES:=1}" +: "${DO_UPTIME:=1}" +: "${DO_NETSTAT:=1}" +: "${DO_NETCFG:=1}" +: "${DO_IPTABLES:=1}" +: "${DO_SYSCTL:=1}" +: "${DO_VIRSH:=1}" +: "${DO_LXC:=1}" +: "${DO_MOUNT:=1}" +: "${DO_DF:=1}" + +export LC_ALL=C + +set -u + +main diff --git a/evolinux-base/files/htoprc b/evolinux-base/files/htoprc new file mode 100644 index 00000000..c3380903 --- /dev/null +++ b/evolinux-base/files/htoprc @@ -0,0 +1,2 @@ +# Force the SWAP column to the right of the CPU one +fields=0 48 17 18 38 39 40 119 2 46 47 49 1 diff --git a/evolinux-base/files/logs/logrotate.d/alternatives b/evolinux-base/files/logs/logrotate.d/alternatives new file mode 100644 index 00000000..5fa5b7a1 --- /dev/null +++ b/evolinux-base/files/logs/logrotate.d/alternatives @@ -0,0 +1,9 @@ +/var/log/alternatives.log { + monthly + rotate 120 + compress + delaycompress + missingok + notifempty + create 644 root root +} diff --git a/evolinux-base/files/logs/logrotate.d/dpkg b/evolinux-base/files/logs/logrotate.d/dpkg index 16ac22fe..81f71969 100644 --- a/evolinux-base/files/logs/logrotate.d/dpkg +++ b/evolinux-base/files/logs/logrotate.d/dpkg @@ -6,14 +6,4 @@ missingok notifempty create 644 root root -} -/var/log/alternatives.log { - monthly - rotate 120 - compress - delaycompress - missingok - notifempty - create 644 root root -} - +} \ No newline at end of file diff --git a/evolinux-base/files/logs/logrotate.disabled/ldap b/evolinux-base/files/logs/logrotate.disabled/ldap index 59372a33..4be35fa8 100644 --- a/evolinux-base/files/logs/logrotate.disabled/ldap +++ b/evolinux-base/files/logs/logrotate.disabled/ldap @@ -2,8 +2,8 @@ weekly missingok rotate 3 - compress - notifempty + compress + notifempty create 640 root adm } diff --git a/evolinux-base/files/logs/logrotate.disabled/procmail b/evolinux-base/files/logs/logrotate.disabled/procmail index d42323f1..29dd2d7a 100644 --- a/evolinux-base/files/logs/logrotate.disabled/procmail +++ b/evolinux-base/files/logs/logrotate.disabled/procmail @@ -1,11 +1,7 @@ /var/log/procmail.log { daily rotate 365 - dateext - dateyesterday - dateformat .%Y%m%d missingok - rotate 365 create 640 root adm } diff --git a/evolinux-base/files/topdefaultrc b/evolinux-base/files/topdefaultrc new file mode 100644 index 00000000..b49be289 --- /dev/null +++ b/evolinux-base/files/topdefaultrc @@ -0,0 +1,15 @@ +top's Config File (Linux processes with windows) +Id:j, Mode_altscr=0, Mode_irixps=1, Delay_time=3.0, Curwin=0 +Def fieldscur=ķ&')*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz + winflags=193844, sortindx=18, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0 + summclr=1, msgsclr=1, headclr=3, taskclr=1 +Job fieldscur=(Ļ@<)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz + winflags=193844, sortindx=0, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0 + summclr=6, msgsclr=6, headclr=7, taskclr=6 +Mem fieldscur=?@ABCFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz + winflags=193844, sortindx=3, maxtasks=0, graph_cpus=0, graph_mems=0, double_up=0, combine_cpus=0 + summclr=3, msgsclr=3, headclr=2, taskclr=3 +Fixed_widest=0, Summ_mscale=1, Task_mscale=0, Zero_suppress=0 diff --git a/evolinux-base/meta/main.yml b/evolinux-base/meta/main.yml index 84c001c1..83ed8538 100644 --- a/evolinux-base/meta/main.yml +++ b/evolinux-base/meta/main.yml @@ -14,6 +14,7 @@ galaxy_info: - jessie - stretch - buster + - bullseye galaxy_tags: [] # List tags for your role here, one per line. A tag is diff --git a/evolinux-base/tasks/fstab.yml b/evolinux-base/tasks/fstab.yml index e10f483e..a3933844 100644 --- a/evolinux-base/tasks/fstab.yml +++ b/evolinux-base/tasks/fstab.yml @@ -1,5 +1,6 @@ --- # TODO: trouver comment faire une copie initiale de /etc/fstab +# - piste : paramètre "backup" du module mount https://docs.ansible.com/ansible/latest/collections/ansible/posix/mount_module.html # TODO: try to use the custom mount_uuid module for a different approach - name: Fetch fstab content diff --git a/evolinux-base/tasks/hardware.yml b/evolinux-base/tasks/hardware.yml index 7f4ebf36..e072f95c 100644 --- a/evolinux-base/tasks/hardware.yml +++ b/evolinux-base/tasks/hardware.yml @@ -3,6 +3,8 @@ apt: name: pciutils state: present + tags: + - packages ## Broadcom NetXtreme II @@ -12,6 +14,8 @@ register: broadcom_netextreme_search failed_when: False changed_when: False + tags: + - packages # TODO: add the "non-free" part to the existing sources # instead of adding a new source @@ -22,18 +26,43 @@ tasks_from: basics.yml vars: apt_basics_components: "main contrib non-free" + tags: + - packages when: broadcom_netextreme_search.rc == 0 + +## Dedicated hardware +- name: Install freepmi when it's dedicated hardware + apt: + name: + - libipc-run-perl + - freeipmi + state: present + tags: + - packages + when: ansible_virtualization_role == "host" + ## RAID # Dell and others: MegaRAID SAS # HP gen <10: Hewlett-Packard Company Smart Array # HP gen >=10: Adaptec Smart Storage PQI - name: Detect if RAID is installed - shell: "set -o pipefail && lspci -q | grep -e 'RAID bus controller' -e 'Serial Attached SCSI controller'" + shell: + cmd: "lspci -q | grep -e 'RAID bus controller' -e 'Serial Attached SCSI controller'" + executable: /bin/bash check_mode: no register: raidmodel changed_when: "'FAILED' in raidmodel.stdout" failed_when: "'FAILED' in raidmodel.stdout" + tags: + - packages + +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - packages - name: HPE Smart Storage Administrator (ssacli) is present block: @@ -42,6 +71,9 @@ id: "26C2B797" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists + tags: + - packages - name: HPE GPG key is installed copy: @@ -51,14 +83,21 @@ mode: "0644" owner: root group: root + tags: + - packages - name: Add HPE repository apt_repository: repo: 'deb https://downloads.linux.hpe.com/SDR/repo/mcp {{ ansible_distribution_release }}/current non-free' state: present + tags: + - packages + - name: Install HPE Smart Storage Administrator (ssacli) apt: name: ssacli + tags: + - packages when: - "'Hewlett-Packard Company Smart Array' in raidmodel.stdout" - "'Adaptec Smart Storage PQI' in raidmodel.stdout" @@ -72,6 +111,8 @@ src: check_hpraid.cron.sh dest: /etc/cron.{{ evolinux_cron_checkhpraid_frequency | mandatory }}/check_hpraid mode: "0755" + tags: + - config when: "'Adaptec Smart Storage PQI' in raidmodel.stdout" - name: Install and configure cciss-vol-status (HP gen <10) @@ -80,12 +121,16 @@ apt: name: cciss-vol-status state: present + tags: + - packages - name: cciss-vol-statusd init script is present (HP gen <10) template: src: hardware/cciss-vol-statusd.j2 dest: /etc/init.d/cciss-vol-statusd mode: "0755" + tags: + - packages - name: Configure cciss-vol-statusd (HP gen <10) lineinfile: @@ -93,12 +138,17 @@ line: 'MAILTO="{{ raid_alert_email or general_alert_email | mandatory }}"' regexp: 'MAILTO=' create: yes + tags: + - config - name: Enable cciss-vol-status in systemd (HP gen <10) service: name: cciss-vol-statusd enabled: true state: restarted + tags: + - packages + - config when: "'Hewlett-Packard Company Smart Array' in raidmodel.stdout" - name: MegaRAID SAS package is present @@ -108,7 +158,9 @@ id: "23B3D3B4" keyring: /etc/apt/trusted.gpg state: absent - when: ansible_distribution_major_version is version('9', '>=') + tags: + - packages + when: _trusted_gpg_keyring.stat.exists - name: HWRaid GPG key is installed copy: @@ -118,12 +170,16 @@ mode: "0644" owner: root group: root + tags: + - packages when: ansible_distribution_major_version is version('9', '>=') - name: Add HW tool repository apt_repository: repo: 'deb http://hwraid.le-vert.net/debian {{ ansible_distribution_release }} main' state: present + tags: + - packages - name: Install packages for DELL/LSI hardware apt: @@ -131,18 +187,25 @@ - megacli - megaclisas-status allow_unauthenticated: yes + tags: + - packages - name: Configure packages for DELL/LSI hardware template: src: hardware/megaclisas-statusd.j2 dest: /etc/default/megaclisas-statusd mode: "0755" + tags: + - config - name: Enable DELL/LSI hardware in systemd service: name: megaclisas-statusd enabled: true - state: started - when: "'MegaRAID SAS' in raidmodel.stdout" + state: restarted + tags: + - packages + - config + when: "'MegaRAID' in raidmodel.stdout" - meta: flush_handlers diff --git a/evolinux-base/tasks/htop.yml b/evolinux-base/tasks/htop.yml new file mode 100644 index 00000000..eeb59beb --- /dev/null +++ b/evolinux-base/tasks/htop.yml @@ -0,0 +1,6 @@ +--- +- name: Deploy htop configuration + copy: + src: htoprc + dest: /etc/htoprc + mode: "0644" diff --git a/evolinux-base/tasks/kernel.yml b/evolinux-base/tasks/kernel.yml index 76965f47..6ddeb57f 100644 --- a/evolinux-base/tasks/kernel.yml +++ b/evolinux-base/tasks/kernel.yml @@ -8,8 +8,8 @@ state: present reload: yes loop: - - { name: kernel.panic_on_oops, value: 1 } - - { name: kernel.panic, value: 60 } + - { name: kernel.panic_on_oops, value: 1 } + - { name: kernel.panic, value: 60 } when: evolinux_kernel_reboot_after_panic | bool - name: Don't reboot after panic @@ -19,14 +19,14 @@ state: absent reload: yes loop: - - kernel.panic_on_oops - - kernel.panic + - kernel.panic_on_oops + - kernel.panic when: not evolinux_kernel_reboot_after_panic | bool - name: Disable net.ipv4.tcp_timestamps sysctl: name: net.ipv4.tcp_timestamps - value: 0 + value: '0' sysctl_file: "{{ evolinux_kernel_sysctl_path }}" state: present reload: yes diff --git a/evolinux-base/tasks/logs.yml b/evolinux-base/tasks/logs.yml index 2bf28b98..8298486e 100644 --- a/evolinux-base/tasks/logs.yml +++ b/evolinux-base/tasks/logs.yml @@ -30,11 +30,34 @@ dest: /etc/logrotate.d/zsyslog when: evolinux_logs_logrotate_confs | bool -- name: Configure logrotate.conf +- name: Configure logrotate.conf default rotate value replace: dest: /etc/logrotate.conf regexp: "rotate [0-9]+" replace: "rotate 12" when: evolinux_logs_default_rotate | bool +- name: Enable logrotate.conf dateext option + lineinfile: + dest: /etc/logrotate.conf + line: "dateext" + regexp: "^#?\\s*dateext" + when: evolinux_logs_default_dateext | bool + +- name: Enable logrotate.conf dateformat option + lineinfile: + dest: /etc/logrotate.conf + line: "dateformat {{ evolinux_logrotate_dateformat | mandatory }}" + regexp: "^#?\\s*dateformat.*" + insertafter: 'dateext' + when: evolinux_logs_default_dateext | bool + +- name: Disable logrotate.conf dateyesterday option + lineinfile: + dest: /etc/logrotate.conf + line: "# dateyesterday" + regexp: "^\\s*dateyesterday" + insertafter: 'dateext' + when: evolinux_logs_default_dateext | bool + - meta: flush_handlers diff --git a/evolinux-base/tasks/main.yml b/evolinux-base/tasks/main.yml index 2da87162..5a0532a3 100644 --- a/evolinux-base/tasks/main.yml +++ b/evolinux-base/tasks/main.yml @@ -13,6 +13,7 @@ vars: apt_install_basics: "{{ evolinux_apt_replace_default_sources }}" apt_install_evolix_public: "{{ evolinux_apt_public_sources }}" + apt_upgrade: "{{ evolinux_apt_upgrade }}" when: evolinux_apt_include | bool - name: /etc versioning with Git @@ -97,6 +98,9 @@ when: evolinux_log2mail_include | bool - include: motd.yml + when: evolinux_motd_include | bool + +- include: utils.yml - name: Munin include_role: @@ -116,8 +120,6 @@ - name: Evocheck include_role: name: evolix/evocheck - vars: - evocheck_force_install: "{{ evolinux_evocheck_force_install }}" when: evolinux_evocheck_include | bool - name: Listupgrade @@ -129,3 +131,7 @@ include_role: name: evolix/generate-ldif when: evolinux_generateldif_include | bool + +- include: top.yml + +- include: htop.yml diff --git a/evolinux-base/tasks/packages.yml b/evolinux-base/tasks/packages.yml index 8df64abd..f4eafc6c 100644 --- a/evolinux-base/tasks/packages.yml +++ b/evolinux-base/tasks/packages.yml @@ -16,6 +16,7 @@ - ssl-cert - ca-certificates - rename + - dmidecode when: evolinux_packages_system | bool - name: Install/Update diagnostic tools @@ -34,6 +35,7 @@ - telnet - traceroute - man + - molly-guard when: evolinux_packages_diagnostic | bool - name: Install/Update hardware tools @@ -143,5 +145,6 @@ when: - ansible_distribution == "Debian" - ansible_distribution_major_version is version('9', '>=') + - evolinux_packages_delete_aptlistchanges - meta: flush_handlers diff --git a/evolinux-base/tasks/system.yml b/evolinux-base/tasks/system.yml index 53fa243c..e5363fed 100644 --- a/evolinux-base/tasks/system.yml +++ b/evolinux-base/tasks/system.yml @@ -119,10 +119,10 @@ regexp: "{{ item.regexp }}" replace: "{{ item.replace }}" loop: - - { regexp: '^17((\s*\*){4})', replace: '{{ 59|random(start=1) }}\1' } - - { regexp: '^25\s*6((\s*\*){3})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } - - { regexp: '^47\s*6((\s*\*){2}\s*7)', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } - - { regexp: '^52\s*6(\s*1(\s*\*){2})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } + - { regexp: '^17((\s*\*){4})', replace: '{{ 59|random(start=1) }}\1' } + - { regexp: '^25\s*6((\s*\*){3})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } + - { regexp: '^47\s*6((\s*\*){2}\s*7)', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } + - { regexp: '^52\s*6(\s*1(\s*\*){2})', replace: '{{ 59|random(start=1) }} {{ [0,1,3,4,5,6,7]|random }}\1' } when: - is_cron_installed.rc == 0 - evolinux_system_cron_random | bool @@ -153,7 +153,7 @@ -- name: Install alert5 init script (buster) +- name: Install alert5 init script (buster and later) template: src: system/alert5.sh.j2 dest: /usr/share/scripts/alert5.sh @@ -163,7 +163,7 @@ - evolinux_system_alert5_init | bool - ansible_distribution_major_version is version('10', '>=') -- name: Install alert5 service (buster) +- name: Install alert5 service (buster and later) copy: src: alert5.service dest: /etc/systemd/system/alert5.service @@ -173,7 +173,7 @@ - evolinux_system_alert5_init | bool - ansible_distribution_major_version is version('10', '>=') -- name: Enable alert5 init script (buster) +- name: Enable alert5 init script (buster and later) systemd: name: alert5 daemon_reload: yes @@ -182,6 +182,7 @@ - evolinux_system_alert5_init | bool - evolinux_system_alert5_enable | bool - ansible_distribution_major_version is version('10', '>=') + - not ansible_check_mode ## network interfaces @@ -203,13 +204,4 @@ ## /sbin/deny -- name: "/sbin/deny script is present" - copy: - src: deny.sh - dest: /sbin/deny - mode: "0700" - owner: root - group: root - force: no - - meta: flush_handlers diff --git a/evolinux-base/tasks/top.yml b/evolinux-base/tasks/top.yml new file mode 100644 index 00000000..12eff20c --- /dev/null +++ b/evolinux-base/tasks/top.yml @@ -0,0 +1,7 @@ +--- +- name: Deploy top configuration file + copy: + # The config format is unredable; ATM it only add the SWAP column + src: htoprc + dest: /etc/topdefaultrc + mode: "0644" diff --git a/evolinux-base/tasks/utils.yml b/evolinux-base/tasks/utils.yml new file mode 100644 index 00000000..a5ff56fa --- /dev/null +++ b/evolinux-base/tasks/utils.yml @@ -0,0 +1,22 @@ +--- + +- include_role: + name: evolix/remount-usr + +- name: backup-server-state script is present + copy: + src: "backup-server-state.sh" + dest: /usr/local/sbin/backup-server-state + force: True + owner: root + group: root + mode: "0750" + +- name: "/sbin/deny script is present" + copy: + src: deny.sh + dest: /sbin/deny + mode: "0700" + owner: root + group: root + force: no \ No newline at end of file diff --git a/evolinux-base/templates/logs/zsyslog.j2 b/evolinux-base/templates/logs/zsyslog.j2 index 2fc2bd1a..cb6d931e 100644 --- a/evolinux-base/templates/logs/zsyslog.j2 +++ b/evolinux-base/templates/logs/zsyslog.j2 @@ -1,8 +1,13 @@ # Custom EvoLinux create 640 root adm +{% if not evolinux_logs_default_dateext %} +# BEGIN legacy setting +# … when global dateext and dateformat are not enabled dateext dateyesterday dateformat .%Y%m%d +# END legacy setting +{% endif %} missingok notifempty delaycompress diff --git a/evolinux-users/templates/sudoers_jessie.j2 b/evolinux-users/templates/sudoers_jessie.j2 index b82c67ac..c0703c49 100644 --- a/evolinux-users/templates/sudoers_jessie.j2 +++ b/evolinux-users/templates/sudoers_jessie.j2 @@ -7,6 +7,8 @@ nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_procs nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_minifirewall nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_haproxy_stats nagios ALL = NOPASSWD: /usr/sbin/bkctld check +nagios ALL = NOPASSWD: /usr/sbin/bkctld check-jails +nagios ALL = NOPASSWD: /usr/sbin/bkctld check-setup nagios ALL = (clamav) NOPASSWD: /usr/bin/clamscan /tmp/safe.txt ADMINS ALL = (ALL:ALL) ALL diff --git a/evolinux-users/templates/sudoers_stretch.j2 b/evolinux-users/templates/sudoers_stretch.j2 index 539f871e..4a522e1b 100644 --- a/evolinux-users/templates/sudoers_stretch.j2 +++ b/evolinux-users/templates/sudoers_stretch.j2 @@ -6,10 +6,22 @@ nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_procs nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_minifirewall nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_haproxy_stats nagios ALL = NOPASSWD: /usr/sbin/bkctld check +nagios ALL = NOPASSWD: /usr/sbin/bkctld check-jails +nagios ALL = NOPASSWD: /usr/sbin/bkctld check-setup nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php56/rootfs/etc/php5/fpm/pool.d/ nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php70/rootfs/etc/php/7.0/fpm/pool.d/ nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php73/rootfs/etc/php/7.3/fpm/pool.d/ nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php74/rootfs/etc/php/7.4/fpm/pool.d/ +nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_phpfpm_multi /var/lib/lxc/php74/rootfs/etc/php/8.0/fpm/pool.d/ +nagios ALL = NOPASSWD: /usr/sbin/megaclisas-status --nagios +nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_ipmi_sensor +nagios ALL = NOPASSWD: /sbin/dmsetup status --noflush +nagios ALL = NOPASSWD: /sbin/megacli -PDList -aALL -NoLog +nagios ALL = NOPASSWD: /sbin/megacli -LdInfo -Lall -aALL -NoLog +nagios ALL = NOPASSWD: /sbin/megacli -AdpBbuCmd -GetBbuStatus -aALL -NoLog +nagios ALL = NOPASSWD: /sbin/ssacli controller all show status +nagios ALL = NOPASSWD: /sbin/ssacli controller slot=0 logicaldrive all show + nagios ALL = (clamav) NOPASSWD: /usr/bin/clamscan /tmp/safe.txt %{{ evolinux_sudo_group }} ALL=(ALL:ALL) ALL diff --git a/evomaintenance/files/evomaintenance.sh b/evomaintenance/files/evomaintenance.sh index 1961ebf2..3903f2ef 100644 --- a/evomaintenance/files/evomaintenance.sh +++ b/evomaintenance/files/evomaintenance.sh @@ -4,16 +4,16 @@ # Dependencies (all OS): git postgresql-client # Dependencies (Debian): sudo -# Copyright 2007-2021 Evolix , Gregory Colpart , +# Copyright 2007-2022 Evolix , Gregory Colpart , # Jérémy Lecour and others. -VERSION="0.6.4" +VERSION="22.01" show_version() { cat <, +Copyright 2007-2022 Evolix , Gregory Colpart , Jérémy Lecour and others. @@ -303,6 +303,9 @@ From: ${FULLFROM} Content-Type: text/plain; charset=UTF-8 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit +X-Evomaintenance-Version: ${VERSION} +X-Evomaintenance-Host: ${HOSTNAME_TEXT} +X-Evomaintenance-User: ${USER} To: ${EVOMAINTMAIL} Subject: [evomaintenance] Intervention sur ${HOSTNAME_TEXT} (${USER}) diff --git a/evomaintenance/tasks/config.yml b/evomaintenance/tasks/config.yml new file mode 100644 index 00000000..097e9770 --- /dev/null +++ b/evomaintenance/tasks/config.yml @@ -0,0 +1,18 @@ +--- + +- assert: + that: + - evomaintenance_api_endpoint is not none + - evomaintenance_api_key is not none + msg: evomaintenance api variables must be set + +- name: Configuration is installed + template: + src: evomaintenance.j2 + dest: /etc/evomaintenance.cf + owner: root + group: root + mode: "0600" + force: "{{ evomaintenance_force_config | bool }}" + tags: + - evomaintenance diff --git a/evomaintenance/tasks/install_package_debian.yml b/evomaintenance/tasks/install_package_debian.yml index a5da77ea..ce9d90e7 100644 --- a/evomaintenance/tasks/install_package_debian.yml +++ b/evomaintenance/tasks/install_package_debian.yml @@ -12,15 +12,4 @@ name: evomaintenance allow_unauthenticated: yes tags: - - evomaintenance - -- name: Configuration is installed - template: - src: evomaintenance.j2 - dest: /etc/evomaintenance.cf - owner: root - group: root - mode: "0600" - force: "{{ evomaintenance_force_config | bool }}" - tags: - - evomaintenance + - evomaintenance \ No newline at end of file diff --git a/evomaintenance/tasks/install_vendor_debian.yml b/evomaintenance/tasks/install_vendor_debian.yml index 2faaac79..99448e3c 100644 --- a/evomaintenance/tasks/install_vendor_debian.yml +++ b/evomaintenance/tasks/install_vendor_debian.yml @@ -46,15 +46,4 @@ - { src: 'evomaintenance.sh', dest: '/usr/share/scripts/', mode: '0700' } - { src: 'evomaintenance.tpl', dest: '/usr/share/scripts/', mode: '0600' } tags: - - evomaintenance - -- name: Configuration is installed - template: - src: evomaintenance.j2 - dest: /etc/evomaintenance.cf - owner: root - group: root - mode: "0600" - force: "{{ evomaintenance_force_config | bool }}" - tags: - - evomaintenance + - evomaintenance \ No newline at end of file diff --git a/evomaintenance/tasks/main.yml b/evomaintenance/tasks/main.yml index 9826089b..0a4e5010 100644 --- a/evomaintenance/tasks/main.yml +++ b/evomaintenance/tasks/main.yml @@ -1,14 +1,5 @@ --- -- set_fact: - minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" - -- assert: - that: - - evomaintenance_api_endpoint is not none - - evomaintenance_api_key is not none - msg: evomaintenance api variables must be set - - include: install_package_debian.yml when: - not (evomaintenance_install_vendor | bool) @@ -19,6 +10,8 @@ - evomaintenance_install_vendor | bool - ansible_distribution == "Debian" +- include: config.yml + - include: minifirewall.yml when: - evomaintenance_hook_db | bool diff --git a/evomaintenance/tasks/minifirewall.yml b/evomaintenance/tasks/minifirewall.yml index ad48e856..98dad15b 100644 --- a/evomaintenance/tasks/minifirewall.yml +++ b/evomaintenance/tasks/minifirewall.yml @@ -1,5 +1,8 @@ --- +- set_fact: + minifirewall_restart_handler_name: "{{ minifirewall_restart_if_needed | bool | ternary('restart minifirewall', 'restart minifirewall (noop)') }}" + - name: Is minifirewall installed? stat: path: /etc/default/minifirewall diff --git a/filebeat/defaults/main.yml b/filebeat/defaults/main.yml index 598a08ed..deed1508 100644 --- a/filebeat/defaults/main.yml +++ b/filebeat/defaults/main.yml @@ -1,5 +1,5 @@ --- -elastic_stack_version: "6.x" +elastic_stack_version: "7.x" filebeat_logstash_plugin: False diff --git a/filebeat/handlers/main.yml b/filebeat/handlers/main.yml index 0a6d83f9..3ad08a63 100644 --- a/filebeat/handlers/main.yml +++ b/filebeat/handlers/main.yml @@ -4,3 +4,4 @@ systemd: name: filebeat state: restarted + when: not ansible_check_mode diff --git a/filebeat/tasks/main.yml b/filebeat/tasks/main.yml index 034808d3..dd326cc8 100644 --- a/filebeat/tasks/main.yml +++ b/filebeat/tasks/main.yml @@ -8,11 +8,20 @@ - filebeat - packages +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - filebeat + - packages + - name: Elastic embedded GPG key is absent apt_key: id: "D88E42B4" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - filebeat - packages @@ -53,6 +62,7 @@ name: filebeat enabled: yes notify: restart filebeat + when: not ansible_check_mode - name: is logstash-plugin available? stat: @@ -131,7 +141,9 @@ when: - filebeat_elasticsearch_auth_username | length > 0 - filebeat_elasticsearch_auth_password | length > 0 - when: not (filebeat_use_config_template | bool) + when: + - not (filebeat_use_config_template | bool) + - not ansible_check_mode - name: Filebeat api_key for Elasticsearch are configured lineinfile: diff --git a/fluentd/tasks/main.yml b/fluentd/tasks/main.yml index 159748e6..282accf2 100644 --- a/fluentd/tasks/main.yml +++ b/fluentd/tasks/main.yml @@ -1,10 +1,19 @@ --- +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - packages + - fluentd + - name: Fluentd embedded GPG key is absent apt_key: id: "AB97ACBE" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - packages - fluentd diff --git a/generate-ldif/templates/generateldif.sh.j2 b/generate-ldif/templates/generateldif.sh.j2 index d5c19411..aa3ec7dd 100755 --- a/generate-ldif/templates/generateldif.sh.j2 +++ b/generate-ldif/templates/generateldif.sh.j2 @@ -31,17 +31,30 @@ computerKernel=$(uname -r) HardwareSerial=$(dmidecode -s system-serial-number | grep -v '^#') type="baremetal" -lscpu | grep -q KVM && type="kvm" +lscpu | grep "Hypervisor vendor:" | grep -q KVM && type="kvm" +lscpu | grep "Hypervisor vendor:" | grep -q VMware && type="vmware" lscpu | grep -q Oracle && type="virtualbox" if [ "$type" = "kvm" ]; then + ComputerType="VM" HardwareMark="KVM" HardwareModel="Virtual Machine" cpuMark=$(lscpu | grep Vendor | tr -s '\t' ' ' | cut -d' ' -f3) cpuModel="Virtual $(lscpu | grep "Model name" | tr -s '\t' ' ' | cut -d' ' -f3-), $(nproc) vCPU" cpuFreq="$(lscpu | grep "CPU MHz" | tr -s '\t' ' ' | cut -d' ' -f3-)MHz" + +elif [ "$type" = "vmware" ]; then + ComputerType="VM" + HardwareMark="VMWare" + HardwareModel="Virtual Machine" + + cpuMark=$(lscpu | grep Vendor | tr -s '\t' ' ' | cut -d' ' -f3) + cpuModel="Virtual $(lscpu | grep "Model name" | tr -s '\t' ' ' | cut -d' ' -f3-), $(nproc) vCPU" + cpuFreq="$(lscpu | grep "CPU MHz" | tr -s '\t' ' ' | cut -d' ' -f3-)MHz" + elif [ "$type" = "virtualbox" ]; then + ComputerType="VM" HardwareMark="VirtualBox" HardwareModel="Virtual Machine" @@ -49,6 +62,7 @@ elif [ "$type" = "virtualbox" ]; then cpuModel="Virtual $(lscpu | grep "Model name" | tr -s '\t' ' ' | cut -d' ' -f3-), $(nproc) vCPU" cpuFreq="$(lscpu | grep "CPU MHz" | tr -s '\t' ' ' | cut -d' ' -f3-)MHz" else + ComputerType="Baremetal" HardwareModel=$(dmidecode -s system-product-name | grep -v '^#') cpuMark=$(dmidecode -s processor-manufacturer | grep -v '^#' | head -1) @@ -115,6 +129,7 @@ NagiosEnabled: ${NagiosEnabled} NagiosComments: ${monitoringType},${monitoringMode},${monitoringTimeout} HardwareSerial: ${HardwareSerial} clientNumber: ${clientNumber} +ComputerType: ${ComputerType} EOT # CPU @@ -174,6 +189,19 @@ NagiosEnabled: TRUE EOT fi +# raid hardware +if [ -n "${raidModel}" ]; then + cat <> "${ldif_file}" + +dn: HardwareName=raid_card,${computer_dn} +objectClass: EvoHardware +HardwareName: raid_card +HardwareType: disk +HardwareModel: ${raidModel} +NagiosEnabled: TRUE +EOT +fi + # Swap swap=$(free -h | grep Swap: | tr -s ' ' | cut -d ' ' -f2) if [ -n "${swap}" ]; then @@ -570,10 +598,27 @@ objectClass: EvoService ServiceName: postgresql ipServicePort: 5432 ServiceType: database -ServiceVersion: PostgreSQL ${elasticsearch_version} +ServiceVersion: PostgreSQL ${postgresql_version} EOT fi +# mdadm +if is_pkg_installed mdadm; then + mdadm_version=$(get_pkg_version mdadm) +fi +if [ -n "${mdadm_version}" ]; then + cat <> "${ldif_file}" + +dn: ServiceName=mdadm,${computer_dn} +NagiosEnabled: TRUE +objectClass: EvoService +ServiceName: mdadm +ServiceType: raid +ServiceVersion: mdadm ${mdadm_version} +EOT +fi + + # test if we have a stdout if [ -t 1 ]; then echo "Output is in ${ldif_file}" diff --git a/haproxy/defaults/main.yml b/haproxy/defaults/main.yml index b94d2872..0745f1a9 100644 --- a/haproxy/defaults/main.yml +++ b/haproxy/defaults/main.yml @@ -34,3 +34,4 @@ haproxy_deny_ips: [] haproxy_backports_packages_stretch: haproxy libssl1.0.0 haproxy_backports_packages_buster: haproxy +haproxy_backports_packages_bullseye: haproxy diff --git a/haproxy/tasks/packages_backports.yml b/haproxy/tasks/packages_backports.yml index 9a682120..eab4fbca 100644 --- a/haproxy/tasks/packages_backports.yml +++ b/haproxy/tasks/packages_backports.yml @@ -15,6 +15,10 @@ haproxy_backports_packages: "{{ haproxy_backports_packages_buster }}" when: ansible_distribution_release == 'buster' +- set_fact: + haproxy_backports_packages: "{{ haproxy_backports_packages_bullseye }}" + when: ansible_distribution_release == 'bullseye' + - name: Prefer HAProxy package from backports template: src: haproxy_apt_preferences.j2 diff --git a/java/tasks/oracle.yml b/java/tasks/oracle.yml index c2ab5ebf..0b057695 100644 --- a/java/tasks/oracle.yml +++ b/java/tasks/oracle.yml @@ -14,9 +14,9 @@ state: directory mode: "0777" loop: - - /srv/java-package - - /srv/java-package/src - - /srv/java-package/tmp + - /srv/java-package + - /srv/java-package/src + - /srv/java-package/tmp tags: - java diff --git a/jenkins/tasks/main.yml b/jenkins/tasks/main.yml index da23e5f5..8ed3d38c 100644 --- a/jenkins/tasks/main.yml +++ b/jenkins/tasks/main.yml @@ -5,11 +5,17 @@ # http://mirrors.jenkins.io/.* # http://jenkins.mirror.isppower.de/.* +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + - name: Jenkins embedded GPG key is absent apt_key: id: "D50582E6" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists - name: Add Jenkins GPG key copy: diff --git a/kibana/defaults/main.yml b/kibana/defaults/main.yml index e167c21f..7107398c 100644 --- a/kibana/defaults/main.yml +++ b/kibana/defaults/main.yml @@ -1,5 +1,5 @@ --- -elastic_stack_version: "5.x" +elastic_stack_version: "7.x" kibana_server_host: "127.0.0.1" kibana_server_basepath: "" diff --git a/kibana/files/elastic.gpg b/kibana/files/elastic.gpg new file mode 100644 index 00000000..2508ddc9 Binary files /dev/null and b/kibana/files/elastic.gpg differ diff --git a/kibana/files/elasticsearch.key b/kibana/files/elasticsearch.key deleted file mode 100644 index 1b50dcca..00000000 --- a/kibana/files/elasticsearch.key +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v2.0.14 (GNU/Linux) - -mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD -A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 -CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ -j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd -1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD -2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg -KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy -Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC -F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 -nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ -7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm -TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe -8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ -eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl -zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT -RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ -1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ -Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt -KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww -EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 -c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J -TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j -6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 -vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM -cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ -qPDlGRlOgVTd9xUfHFkzB52c70E= -=92oX ------END PGP PUBLIC KEY BLOCK----- diff --git a/kibana/tasks/main.yml b/kibana/tasks/main.yml index 1ed342e0..d0694094 100644 --- a/kibana/tasks/main.yml +++ b/kibana/tasks/main.yml @@ -8,11 +8,20 @@ - kibana - packages +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - kibana + - packages + - name: Elastic embedded GPG key is absent apt_key: id: "D88E42B4" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - kibana - packages @@ -129,3 +138,5 @@ - include: proxy_nginx.yml when: kibana_proxy_nginx | bool + tags: + - kibana diff --git a/kvm-host/files/add-vm.sh b/kvm-host/files/add-vm.sh index ec50763d..51b5c737 100755 --- a/kvm-host/files/add-vm.sh +++ b/kvm-host/files/add-vm.sh @@ -10,6 +10,8 @@ # Bash strict mode set -euo pipefail +VERSION="21.10" + isDryRun() { test "${doDryRun}" = "true" } diff --git a/kvm-host/files/kvmstats.sh b/kvm-host/files/kvmstats.sh index 5fa20ccb..0dcfb4e8 100755 --- a/kvm-host/files/kvmstats.sh +++ b/kvm-host/files/kvmstats.sh @@ -1,96 +1,202 @@ #!/bin/sh +VERSION="21.10" + +PROGNAME=$(basename "$0") + +show_version() { + cat <, + Alexis Ben Miloud--Josselin , + Jérémy Lecour + and others. + +${PROGNAME} comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. +END +} + +show_help() { + cat < + or ${PROGNAME} --units +END +} + error () { echo "$0": "$@" >&2 exit 1 } -usage () { - echo 'usage:' "$0" '[-a] [-u k|m|g] [-o human|html|csv]' >&2 - exit 1 +main() { + for VM in $(virsh list --name --all | sed '/^$/d' | sort) + do + echo "$VM" + + # cpu + virsh vcpucount --current "$VM" + + # mem + # libvirt stores memory in KiB, POW must be lowered by 1 + virsh dommemstat "$VM" 2>/dev/null | awk 'BEGIN{ret=1}$1~/^actual$/{print $2 / '$((POW / 1024))';ret=0}END{exit ret}' || + virsh dumpxml "$VM" | awk -F'[<>]' '$2~/^memory unit/{print $3/'$((POW / 1024))'}' + + # disk + for BLK in $(virsh domblklist "$VM" | sed '1,2d;/-$/d;/^$/d' | awk '{print $1}') + do + virsh domblkinfo "$VM" "$BLK" 2>/dev/null + done | awk '/Physical:/ { size += $2 } END { print int(size / '${POW}') }' + + # state + virsh domstate "$VM" | grep -q '^running$' && echo yes || echo no + done | xargs -n5 | { + echo vm vcpu ram disk running + awk '{ print } /yes$/ { vcpu += $2; ram += $3; disk += $4; running++ } END { print "TOTAL(running)", vcpu, ram, disk, running }' + test "$SHOW_AVAIL" && { + nproc + awk '/^MemTotal:/ { print int($2 / '$((POW / 1024))' ) }' /proc/meminfo + } | xargs -r printf 'AVAILABLE %s %s %s %s\n' + } | case "$FMT" in + 'human') + column -t + ;; + 'html') + awk 'BEGIN{print "\n"}{printf "";for(i=1;i<=NF;i++)printf "", $i;print ""}END{print "
%s
\n"}' + ;; + 'csv') + tr ' ' ',' + ;; + esac } +parse_units() { + case "$1" in + 'k') + POW="$(echo '1024 ^ 1' | bc)" + ;; + 'm') + POW="$(echo '1024 ^ 2' | bc)" + ;; + 'g') + POW="$(echo '1024 ^ 3' | bc)" + ;; + *) + printf 'ERROR: Unknown unit value: %s. Possible values: %s\n' "$1" "k, m, g" >&2 + echo "" >&2 + show_usage >&2 + exit 1 + ;; + esac +} +parse_output() { + case "$1" in + 'csv'|'html'|'human') + FMT="$1" + ;; + *) + printf 'ERROR: Unknown output value : %s. Possible values: %s\n' "$1" "csv, html, human" >&2 + echo "" >&2 + show_usage >&2 + exit 1 + ;; + esac +} + +# Check dependencies for DEP in bc virsh do command -v "$DEP" > /dev/null || error "$DEP" 'command not found' done +# default values POW="$(echo '1024 ^ 3' | bc)" FMT='human' -while [ "$#" -ne 0 ] -do - case "$1" in - '-a') - SHOW_AVAIL='y' - ;; - '-o') - case "$2" in - 'csv'|'html'|'human') - FMT="$2" + +# Parse options +# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a +while :; do + case $1 in + -h|-\?|--help) + show_help + exit 0 + ;; + -V|--version) + show_version + exit 0 + ;; + -a|--all) + SHOW_AVAIL='y' + ;; + -u|--units) + # with value separated by space + if [ -n "$2" ]; then + parse_units "$2" + shift + else + printf 'ERROR: "-u|--units" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --units=?*) + # with value speparated by = + parse_units ${1#*=} + ;; + --units=) + # without value + printf 'ERROR: "--units" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + + -o|--output) + # with value separated by space + if [ -n "$2" ]; then + parse_output "$2" + shift + else + printf 'ERROR: "-o|--output" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --output=?*) + # with value speparated by = + parse_output ${1#*=} + ;; + --output=) + # without value + printf 'ERROR: "--output" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + + --) + # End of all options. + shift + break + ;; + -?*|[[:alnum:]]*) + # ignore unknown options + printf 'ERROR: Unknown option : %s\n' "$1" >&2 + echo "" >&2 + show_usage >&2 + exit 1 ;; *) - usage + # Default case: If no more options then break out of the loop. + break ;; - esac - shift - ;; - '-u') - case "$2" in - 'k') - POW="$(echo '1024 ^ 1' | bc)" - ;; - 'm') - POW="$(echo '1024 ^ 2' | bc)" - ;; - 'g') - POW="$(echo '1024 ^ 3' | bc)" - ;; - *) - usage - esac - shift - ;; - *) - usage esac + shift done -for VM in $(virsh list --name --all) -do - echo "$VM" - - # cpu - virsh vcpucount --current "$VM" - - # mem - # libvirt stores memory in KiB, POW must be lowered by 1 - virsh dommemstat "$VM" 2>/dev/null | awk 'BEGIN{ret=1}$1~/^actual$/{print $2 / '$((POW / 1024))';ret=0}END{exit ret}' || - virsh dumpxml "$VM" | awk -F'[<>]' '$2~/^memory unit/{print $3/'$((POW / 1024))'}' - - # disk - for BLK in $(virsh domblklist "$VM" | sed '1,2d;/-$/d;/^$/d' | awk '{print $1}') - do - virsh domblkinfo "$VM" "$BLK" 2>/dev/null - done | awk '/Physical:/ { size += $2 } END { print int(size / '${POW}') }' - - # state - virsh domstate "$VM" | grep -q '^running$' && echo yes || echo no -done | xargs -n5 | { - echo vm vcpu ram disk running - awk '{ print } /yes$/ { vcpu += $2; ram += $3; disk += $4; running++ } END { print "TOTAL(running)", vcpu, ram, disk, running }' - test "$SHOW_AVAIL" && { - nproc - awk '/^MemTotal:/ { print int($2 / '$((POW / 1024))' ) }' /proc/meminfo - } | xargs -r printf 'AVAILABLE %s %s %s %s\n' -} | case "$FMT" in -'human') - column -t - ;; -'html') - awk 'BEGIN{print "\n"}{printf "";for(i=1;i<=NF;i++)printf "", $i;print ""}END{print "
%s
\n"}' - ;; -'csv') - tr ' ' ',' - ;; -esac +main diff --git a/kvm-host/tasks/main.yml b/kvm-host/tasks/main.yml index 95cb7090..a2f6953c 100644 --- a/kvm-host/tasks/main.yml +++ b/kvm-host/tasks/main.yml @@ -5,7 +5,7 @@ when: kvm_install_drbd ## TODO: check why it's disabled -#- include: ssh.yml +- include: ssh.yml - include: packages.yml diff --git a/kvm-host/tasks/ssh.yml b/kvm-host/tasks/ssh.yml index fe71c287..a36f7549 100644 --- a/kvm-host/tasks/ssh.yml +++ b/kvm-host/tasks/ssh.yml @@ -15,36 +15,34 @@ debug: msg: "{{ ssh_keys.stdout }}" -- name: Autorize other kvm ssh key - authorized_key: - user: root - state: present - key: "{{ item[0] }}" - delegate_to: "{{ item[1] }}" - loop: "{{ _keys | product(_servers) | list }}" - vars: - _keys: ssh_keys.stdout - _servers: groups['hypervisors'] - when: item[1] != inventory_hostname +#- name: Autorize other kvm ssh key +# authorized_key: +# user: root +# state: present +# key: "{{ item[0] }}" +# delegate_to: "{{ item[1] }}" +# loop: "{{ _keys | product(_servers) | list }}" +# vars: +# _keys: ssh_keys.stdout +# _servers: groups['hypervisors'] +# when: item[1] != inventory_hostname - name: Crontab for sync libvirt xml file cron: - name: "sync libvirt xml on {{ item }}" + name: "sync libvirt xml on {{ kvm_pair }}" state: present special_time: "hourly" user: root - job: "rsync -a --delete /etc/libvirt/qemu/ {{ hostvars[item]['ansible_hostname'] }}:/root/libvirt-{{ inventory_hostname }}/" - loop: - - "{{ groups['hypervisors'] }}" - when: item != inventory_hostname + job: "rsync -a --delete /etc/libvirt/qemu/*xml {{ hostvars[kvm_pair]['lan.ip'] }}:/root/libvirt-{{ inventory_hostname }}/" + when: kvm_pair != inventory_hostname + tags: crontab - name: Crontab for sync list of running vm cron: - name: "sync list of libvirt running vm on {{ item }}" + name: "sync list of libvirt running vm on {{ kvm_pair }}" state: present special_time: "daily" user: root - job: "virsh list --all | ssh {{ hostvars[item]['ansible_hostname'] }} 'cat >/root/libvirt-{{ inventory_hostname }}/virsh-list.txt'" - loop: - - "{{ groups['hypervisors'] }}" - when: item != inventory_hostname + job: "virsh list --all | tee /root/virsh-list.txt | ssh {{ hostvars[kvm_pair]['lan.ip'] }} 'cat >/root/libvirt-{{ inventory_hostname }}/virsh-list.txt'" + when: kvm_pair != inventory_hostname + tags: crontab diff --git a/ldap/defaults/main.yml b/ldap/defaults/main.yml index 29c51244..83760815 100644 --- a/ldap/defaults/main.yml +++ b/ldap/defaults/main.yml @@ -1,10 +1,10 @@ --- -ldap_listen: "ldap://127.0.0.1:389/" +ldap_listen: "ldap://127.0.0.1:389/ ldapi:///" ldap_hostname: "{{ ansible_hostname }}" ldap_domain: "{{ ansible_domain }}" ldap_suffix: "dc={{ ldap_hostname }},dc={{ ldap_domain.split('.')[-2] }},dc={{ ldap_domain.split('.')[-1] }}" ldap_admin_password: "" -ldap_nagios_password: "" \ No newline at end of file +ldap_nagios_password: "" diff --git a/listupgrade/defaults/main.yml b/listupgrade/defaults/main.yml index d3bdff78..a83dc54a 100644 --- a/listupgrade/defaults/main.yml +++ b/listupgrade/defaults/main.yml @@ -2,4 +2,10 @@ general_alert_email: "root@localhost" listupgrade_alert_email: Null -listupgrade_cron_enabled: true \ No newline at end of file +listupgrade_cron_enabled: true +listupgrade_cron_minute: "42" +listupgrade_cron_hour: "9" +listupgrade_cron_day: "*" +listupgrade_cron_month: "*" +listupgrade_cron_weekday: "2" +listupgrade_cron_force: false \ No newline at end of file diff --git a/listupgrade/files/listupgrade.sh b/listupgrade/files/listupgrade.sh index 3c64f37e..74a673aa 100644 --- a/listupgrade/files/listupgrade.sh +++ b/listupgrade/files/listupgrade.sh @@ -1,5 +1,7 @@ #!/bin/bash +# Repository: https://gitea.evolix.org/evolix/maj.sh/ + # Exit codes : # - 30 : $skip_releases or $skip_packages is set to "all" # - 40 : current release is in $skip_releases list @@ -7,7 +9,7 @@ # - 60 : current release is not in the $r_releases list # - 70 : at least an upgradable package is not in the $r_packages list -VERSION="21.06.2" +VERSION="21.06.3" show_version() { cat <"${packagesHold}" fi + local_release=$(cut -f 1 -d . , + Gregory Colpart , + Romain Dessort , + Ludovic Poujol , + Jérémy Lecour + and others. + +${PROGNAME} comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. +END +} +show_help() { + cat <&1 |grep -q "javac"; then + if [ -x "${root}/usr/bin/apt" ] && ! ${root}/usr/bin/apt --version 2>&1 | grep -q "javac"; then echo "apt" - elif [ -x $root/usr/bin/aptitude ]; then + elif [ -x "${root}/usr/bin/aptitude" ]; then echo "aptitude" # Usually in containers else echo "apt-get" fi } -APT=$(get_apt_binary) -list="$("${DPKG}" -l | awk '/^[ih][^nc][ ]+(linux|kfreebsd|gnumach)-image-[0-9]+\./ && $2 !~ /-dbg(:.*)?$/ && $2 !~ /-dbgsym(:.*)?$/ { print $2,$3; }' \ - | sed -e 's#^\(linux\|kfreebsd\|gnumach\)-image-##' -e 's#:[^:]\+ # #')" -debverlist="$(echo "$list" | cut -d' ' -f 2 | sort --unique --reverse --version-sort)" +main() { + specifc_kernel="$1" -if [ -n "$1" ]; then - installed_version="$(echo "$list" | awk "\$1 == \"$1\" { print \$2;exit; }")" -fi -unamer="$(uname -r | tr '[A-Z]' '[a-z]')" -if [ -n "$unamer" ]; then - running_version="$(echo "$list" | awk "\$1 == \"$unamer\" { print \$2;exit; }")" -fi -# ignore the currently running version if attempting a reproducible build -if [ -n "${SOURCE_DATE_EPOCH}" ]; then - unamer="" - running_version="" -fi -latest_version="$(echo "$debverlist" | sed -n 1p)" -previous_version="$(echo "$debverlist" | sed -n 2p)" + # shellcheck disable=SC2046 + eval $(apt-config shell DPKG Dir::bin::dpkg/f) + DPKG="${DPKG:-/usr/bin/dpkg}" -debkernels="$(echo "$latest_version -$installed_version -$running_version" | sort -u | sed -e '/^$/ d')" -kernels="$( (echo "$1 -$unamer"; for deb in $debkernels; do echo "$list" | awk "\$2 == \"$deb\" { print \$1; }"; done; ) \ - | sed -e 's#\([\.\+]\)#\\\1#g' -e '/^$/ d' | sort -u|tr '\n' '|' | sed -e 's/|$//')" + listupgrade_state_dir="${listupgrade_state_dir:-/var/lib/listupgrade}" + + APT=$(get_apt_binary) + + list="$("${DPKG}" -l | awk '/^[ih][^nc][ ]+(linux|kfreebsd|gnumach)-image-[0-9]+\./ && $2 !~ /-dbg(:.*)?$/ && $2 !~ /-dbgsym(:.*)?$/ { print $2,$3; }' \ + | sed -e 's#^\(linux\|kfreebsd\|gnumach\)-image-##' -e 's#:[^:]\+ # #')" + debverlist="$(echo "${list}" | cut -d' ' -f 2 | sort --unique --reverse --version-sort)" + + if [ -n "${specifc_kernel}" ]; then + installed_version="$(echo "$list" | awk "\$1 == \"${specifc_kernel}\" { print \$2;exit; }")" + fi + unamer="$(uname -r | tr '[:upper:]' '[:lower:]')" + if [ -n "${unamer}" ]; then + running_version="$(echo "${list}" | awk "\$1 == \"${unamer}\" { print \$2;exit; }")" + fi + # ignore the currently running version if attempting a reproducible build + if [ -n "${SOURCE_DATE_EPOCH}" ]; then + unamer="" + running_version="" + fi + latest_version="$(echo "${debverlist}" | sed -n 1p)" + previous_version="$(echo "${debverlist}" | sed -n 2p)" + + debkernels="$(echo "${latest_version} + ${installed_version} + ${running_version}" | sort -u | sed -e '/^$/ d')" + kernels="$( (echo "${specifc_kernel} + ${unamer}"; for deb in ${debkernels}; do echo "${list}" | awk "\$2 == \"${deb}\" { print \$1; }"; done; ) \ + | sed -e 's#\([\.\+]\)#\\\1#g' -e '/^$/ d' | sort -u|tr '\n' '|' | sed -e 's/|$//')" -echo " -List of installed kernel packages: -$list + echo " + List of installed kernel packages: + $list -# Running kernel: ${running_version:-ignored} (${unamer:-ignored}) -# Last kernel: $latest_version -# Previous kernel: $previous_version -# Kernel versions list to keep: -$debkernels + # Running kernel: ${running_version:-ignored} (${unamer:-ignored}) + # Last kernel: ${latest_version} + # Previous kernel: ${previous_version} + # Kernel versions list to keep: + ${debkernels} -# Kernel packages (version part) to protect: -$kernels -" + # Kernel packages (version part) to protect: + ${kernels} + " -echo "BEFORE" -dpkg -l | grep linux-image + echo "BEFORE" + dpkg -l | grep linux-image -dpkg --get-selections | tr '\t' ' ' | cut -d" " -f1 | grep ^linux-image-[234] | egrep -v "($kernels)" | xargs --no-run-if-empty $APT -y purge + dpkg --get-selections | tr '\t' ' ' | cut -d" " -f1 | grep '^linux-image-[234]' | grep -v -E "(${kernels})" | xargs --no-run-if-empty ${APT} -o Dir::State::Lists="${listupgrade_state_dir}" -y purge -echo " -AFTER" -dpkg -l | grep linux-image -echo "" + echo " + AFTER" + dpkg -l | grep linux-image + echo "" + +} + +# Parse options +# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a +while :; do + case $1 in + -h|-\?|--help) + show_help + exit 0 + ;; + -V|--version) + show_version + exit 0 + ;; + --) + # End of all options. + shift + break + ;; + -?*|[[:alnum:]]*) + # ignore unknown options + if [ "${QUIET}" != 1 ]; then + printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 + fi + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +set -e + + +main "${@}" diff --git a/listupgrade/tasks/main.yml b/listupgrade/tasks/main.yml index 3ed23da3..fc02dfeb 100644 --- a/listupgrade/tasks/main.yml +++ b/listupgrade/tasks/main.yml @@ -46,14 +46,17 @@ group: root - name: Enable listupgrade cron - copy: - src: listupgrade_cron - dest: /etc/cron.d/listupgrade - mode: "0600" - owner: root - group: root - force: no - when: listupgrade_cron_enabled | bool + cron: + name: "lisupgrade.sh" + cron_file: "listupgrade" + user: root + job: "/usr/share/scripts/listupgrade.sh --cron {{ listupgrade_cron_force | bool | ternary('--force','') }}" + minute: "{{ listupgrade_cron_minute }}" + hour: "{{ listupgrade_cron_hour }}" + weekday: "{{ listupgrade_cron_weekday }}" + day: "{{ listupgrade_cron_day }}" + month: "{{ listupgrade_cron_month }}" + state: "{{ listupgrade_cron_enabled | bool | ternary('present','absent') }}" - name: old-kernel-autoremoval script is present copy: diff --git a/logstash/defaults/main.yml b/logstash/defaults/main.yml index 456769cd..7cc40e49 100644 --- a/logstash/defaults/main.yml +++ b/logstash/defaults/main.yml @@ -1,8 +1,10 @@ --- -elastic_stack_version: "6.x" +elastic_stack_version: "7.x" logstash_jvm_xms: 256m logstash_jvm_xmx: 512g logstash_log_rotate_days: 365 logstash_custom_tmpdir: Null logstash_default_tmpdir: /var/lib/logstash/tmp +logstash_log_syslog_enabled: True +logstash_config_force: True \ No newline at end of file diff --git a/logstash/handlers/main.yml b/logstash/handlers/main.yml new file mode 100644 index 00000000..d21d4de3 --- /dev/null +++ b/logstash/handlers/main.yml @@ -0,0 +1,10 @@ +--- + +- name: restart logstash + systemd: + name: logstash + state: restarted + daemon_reload: yes + +- name: reload systemd + command: systemctl daemon-reload \ No newline at end of file diff --git a/logstash/meta/main.yml b/logstash/meta/main.yml index b2ef1210..bad2b6a5 100644 --- a/logstash/meta/main.yml +++ b/logstash/meta/main.yml @@ -24,5 +24,4 @@ galaxy_info: # NOTE: A tag is limited to a single word comprised of # alphanumeric characters. Maximum 20 tags per role. -dependencies: - - { role: evolix/java, java_alternative: 'openjdk', java_version: 8 } +dependencies: [] diff --git a/logstash/tasks/logs.yml b/logstash/tasks/logs.yml index 975cd8bc..b09ebaf2 100644 --- a/logstash/tasks/logs.yml +++ b/logstash/tasks/logs.yml @@ -16,3 +16,26 @@ group: root mode: "0750" when: is_cron_installed.rc == 0 + +- name: "Create a system config directory for systemd overrides" + file: + path: /etc/systemd/system/logstash.service.d + state: directory + +- name: "disable syslog" + ini_file: + path: /etc/systemd/system/logstash.service.d/override.conf + section: Service + option: "{{ item.option }}" + value: "{{ item.value }}" + owner: root + group: root + mode: "0644" + create: yes + no_extra_spaces: yes + state: "{{ logstash_log_syslog_enabled | bool | ternary('absent','present') }}" + loop: + - { option: "StandardOutput", value: "null" } + - { option: "StandardError", value: "null" } + notify: + - restart logstash \ No newline at end of file diff --git a/logstash/tasks/main.yml b/logstash/tasks/main.yml index 4ae70623..856ceba1 100644 --- a/logstash/tasks/main.yml +++ b/logstash/tasks/main.yml @@ -8,11 +8,20 @@ - logstash - packages +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - logstash + - packages + - name: Elastic embedded GPG key is absent apt_key: id: "D88E42B4" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - logstash - packages @@ -79,7 +88,7 @@ owner: logstash group: logstash mode: "0640" - force: yes + force: "{{ logstash_config_force | bool }}" loop: "{{ query('first_found', templates) }}" vars: templates: diff --git a/lxc-php/defaults/main.yml b/lxc-php/defaults/main.yml index 1cceab35..9eb226f1 100644 --- a/lxc-php/defaults/main.yml +++ b/lxc-php/defaults/main.yml @@ -18,4 +18,5 @@ lxc_php_container_releases: php56: "jessie" php70: "stretch" php73: "buster" - php74: "buster" + php74: "bullseye" + php80: "bullseye" diff --git a/lxc-php/handlers/main.yml b/lxc-php/handlers/main.yml index 95882838..27ba8157 100644 --- a/lxc-php/handlers/main.yml +++ b/lxc-php/handlers/main.yml @@ -1,4 +1,9 @@ --- +- name: Reload php80-fpm + lxc_container: + name: "{{ lxc_php_version }}" + container_command: "systemctl reload php8.0-fpm" + - name: Reload php74-fpm lxc_container: name: "{{ lxc_php_version }}" diff --git a/lxc-php/tasks/mail_opensmtpd.yml b/lxc-php/tasks/mail_opensmtpd.yml index 1b4dbea0..25dec9ea 100644 --- a/lxc-php/tasks/mail_opensmtpd.yml +++ b/lxc-php/tasks/mail_opensmtpd.yml @@ -11,3 +11,13 @@ dest: "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/smtpd.conf" mode: "0644" notify: "Restart opensmtpd" + when: lxc_php_container_releases[lxc_php_version] in ["jessie", "stretch", "buster"] + + +- name: "{{ lxc_php_version }} - Configure opensmtpd (in the container)" + template: + src: smtpd.conf.bullseye.j2 + dest: "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/smtpd.conf" + mode: "0644" + notify: "Restart opensmtpd" + when: not lxc_php_container_releases[lxc_php_version] in ["jessie", "stretch", "buster"] diff --git a/lxc-php/tasks/main.yml b/lxc-php/tasks/main.yml index 25c0a978..0de38336 100644 --- a/lxc-php/tasks/main.yml +++ b/lxc-php/tasks/main.yml @@ -21,4 +21,7 @@ - include: "php74.yml" when: lxc_php_version == "php74" +- include: "php80.yml" + when: lxc_php_version == "php80" + - include: "misc.yml" diff --git a/lxc-php/tasks/php74.yml b/lxc-php/tasks/php74.yml index 2c4538e8..a3a7eb44 100644 --- a/lxc-php/tasks/php74.yml +++ b/lxc-php/tasks/php74.yml @@ -1,46 +1,9 @@ --- -- name: "{{ lxc_php_version }} - Install dependency packages" - lxc_container: - name: "{{ lxc_php_version }}" - container_command: "DEBIAN_FRONTEND=noninteractive apt install -y wget apt-transport-https gnupg" - -- name: "{{ lxc_php_version }} - Add sury repo" - lineinfile: - dest: "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/sources.list.d/sury.list" - line: "{{ item }}" - state: present - create: yes - mode: "0644" - loop: - - "deb https://packages.sury.org/php/ buster main" - - "deb http://pub.evolix.net/ buster-php74/" - -- name: copy pub.evolix.net GPG key - copy: - src: reg.asc - dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/reg.asc - mode: "0644" - owner: root - group: root - -- name: copy packages.sury.org GPG Key - copy: - src: sury.gpg - dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/sury.gpg - mode: "0644" - owner: root - group: root - -- name: "{{ lxc_php_version }} - Update APT cache" - lxc_container: - name: "{{ lxc_php_version }}" - container_command: "DEBIAN_FRONTEND=noninteractive apt update" - - name: "{{ lxc_php_version }} - Install PHP packages" lxc_container: name: "{{ lxc_php_version }}" - container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-gettext php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" + container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" - name: "{{ lxc_php_version }} - Copy evolinux PHP configuration" template: diff --git a/lxc-php/tasks/php80.yml b/lxc-php/tasks/php80.yml new file mode 100644 index 00000000..33f6d409 --- /dev/null +++ b/lxc-php/tasks/php80.yml @@ -0,0 +1,57 @@ +--- + +- name: "{{ lxc_php_version }} - Install dependency packages" + lxc_container: + name: "{{ lxc_php_version }}" + container_command: "DEBIAN_FRONTEND=noninteractive apt install -y wget apt-transport-https gnupg" + +- name: "{{ lxc_php_version }} - Add sury repo" + lineinfile: + dest: "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/sources.list.d/sury.list" + line: "{{ item }}" + state: present + create: yes + mode: "0644" + loop: + - "deb https://packages.sury.org/php/ bullseye main" + - "deb http://pub.evolix.net/ bullseye-php80/" + +- name: copy pub.evolix.net GPG key + copy: + src: reg.asc + dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/reg.asc + mode: "0644" + owner: root + group: root + +- name: copy packages.sury.org GPG Key + copy: + src: sury.gpg + dest: /var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/apt/trusted.gpg.d/sury.gpg + mode: "0644" + owner: root + group: root + +- name: "{{ lxc_php_version }} - Update APT cache" + lxc_container: + name: "{{ lxc_php_version }}" + container_command: "DEBIAN_FRONTEND=noninteractive apt update" + +- name: "{{ lxc_php_version }} - Install PHP packages" + lxc_container: + name: "{{ lxc_php_version }}" + container_command: "DEBIAN_FRONTEND=noninteractive apt install -y php-fpm php-cli php-gd php-intl php-imap php-ldap php-mysql php-pgsql php-sqlite3 php-curl php-zip php-mbstring php-zip composer libphp-phpmailer" + +- name: "{{ lxc_php_version }} - Copy evolinux PHP configuration" + template: + src: z-evolinux-defaults.ini.j2 + dest: "{{ line_item }}" + mode: "0644" + notify: "Reload {{ lxc_php_version }}-fpm" + loop: + - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/8.0/fpm/conf.d/z-evolinux-defaults.ini" + - "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/php/8.0/cli/conf.d/z-evolinux-defaults.ini" + loop_control: + loop_var: line_item + +- include: "mail_opensmtpd.yml" diff --git a/lxc-php/templates/mailname.j2 b/lxc-php/templates/mailname.j2 new file mode 100644 index 00000000..e374dd45 --- /dev/null +++ b/lxc-php/templates/mailname.j2 @@ -0,0 +1 @@ +{{ansible_fqdn}} diff --git a/lxc-php/templates/smtpd.conf.bullseye.j2 b/lxc-php/templates/smtpd.conf.bullseye.j2 new file mode 100644 index 00000000..0a6d658f --- /dev/null +++ b/lxc-php/templates/smtpd.conf.bullseye.j2 @@ -0,0 +1,17 @@ +# This is the smtpd server system-wide configuration file. +# See smtpd.conf(5) for more information. + +# To accept external mail, replace with: listen on all +#listen on localhost + +# If you edit the file, you have to run "smtpctl update table aliases" +table aliases file:/etc/aliases + +action "mbox" mbox alias +action "relay" relay host "smtp://127.0.0.1" + +# Uncomment the following to accept external mail for domain "example.org" +#match from any for domain "example.org" action "mbox" + +match for local action "mbox" +match for any action "relay" diff --git a/lxc-solr/tasks/main.yml b/lxc-solr/tasks/main.yml index 3fad863f..d629bbf6 100644 --- a/lxc-solr/tasks/main.yml +++ b/lxc-solr/tasks/main.yml @@ -8,9 +8,7 @@ path: "/var/lib/lxc/{{ item.name }}/rootfs" state: directory mode: '0755' - loop: - - "{{ lxc_containers }}" + loop: "{{ lxc_containers }}" - include: "solr.yml name={{item.name}} solr_version={{item.solr_version}} solr_port={{item.solr_port}}" - loop: - - "{{ lxc_containers }}" + loop: "{{ lxc_containers }}" diff --git a/lxc/tasks/main.yml b/lxc/tasks/main.yml index a3a31cf5..daf2885a 100644 --- a/lxc/tasks/main.yml +++ b/lxc/tasks/main.yml @@ -5,9 +5,20 @@ - lxc - debootstrap - xz-utils - - python-lxc -- name: Install additional packages on Buster +- name: python-lxc is installed (Debian <= 10) + apt: + name: python-lxc + state: present + when: ansible_python_version is version('3', '<') + +- name: python3-lxc is installed (Debian >= 10) + apt: + name: python3-lxc + state: present + when: ansible_python_version is version('3', '>=') + +- name: Install additional packages (Debian >= 10) apt: name: - apparmor @@ -32,6 +43,12 @@ - lxc_unprivilegied_containers | bool - root_subuids.rc != 0 +- name: Check if /var has not mount options nodev or noexec + shell: findmnt | grep -E "/var[^/]" | grep -e nodev -e noexec + register: check_var + changed_when: false + failed_when: "check_var.rc == 0" + - name: Create containers include: create-container.yml vars: diff --git a/metricbeat/defaults/main.yml b/metricbeat/defaults/main.yml index 9529bef3..780a4ffd 100644 --- a/metricbeat/defaults/main.yml +++ b/metricbeat/defaults/main.yml @@ -1,5 +1,5 @@ --- -elastic_stack_version: "6.x" +elastic_stack_version: "7.x" metricbeat_elasticsearch_hosts: - "localhost:9200" diff --git a/metricbeat/tasks/main.yml b/metricbeat/tasks/main.yml index 640a8902..8a009f7f 100644 --- a/metricbeat/tasks/main.yml +++ b/metricbeat/tasks/main.yml @@ -8,11 +8,20 @@ - metricbeat - packages +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + tags: + - metricbeat + - packages + - name: Elastic embedded GPG key is absent apt_key: id: "D88E42B4" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists tags: - metricbeat - packages @@ -121,13 +130,13 @@ src: "{{ item }}" dest: /etc/metricbeat/metricbeat.yml force: "{{ metricbeat_force_config }}" - loop: "{{ query('first_found', templates) }}" - vars: - templates: - - "templates/metricbeat/metricbeat.{{ inventory_hostname }}.yml.j2" - - "templates/metricbeat/metricbeat.{{ host_group | default('all') }}.yml.j2" - - "templates/metricbeat/metricbeat.default.yml.j2" - - "templates/metricbeat.default.yml.j2" - notify: restart metricbeat + loop: "{{ query('first_found', templates) }}" + vars: + templates: + - "templates/metricbeat/metricbeat.{{ inventory_hostname }}.yml.j2" + - "templates/metricbeat/metricbeat.{{ host_group | default('all') }}.yml.j2" + - "templates/metricbeat/metricbeat.default.yml.j2" + - "templates/metricbeat.default.yml.j2" + notify: restart metricbeat when: metricbeat_update_config | bool when: metricbeat_use_config_template | bool diff --git a/mongodb/defaults/main.yml b/mongodb/defaults/main.yml index ec255349..c118f588 100644 --- a/mongodb/defaults/main.yml +++ b/mongodb/defaults/main.yml @@ -6,3 +6,5 @@ mongodb_bind: 127.0.0.1 # Warning: config must not be overwritten by default # otherwise it can disable important settings, like authorization :/ mongodb_force_config: False + +mongodb_version: 4.4 \ No newline at end of file diff --git a/mongodb/files/server-4.4.asc b/mongodb/files/server-4.4.asc new file mode 100644 index 00000000..9f4d9161 --- /dev/null +++ b/mongodb/files/server-4.4.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFzteqwBEADSirbLWsjgkQmdWr06jXPN8049MCqXQIZ2ovy9uJPyLkHgOCta +8dmX+8Fkk5yNOLScjB1HUGJxAWJG+AhldW1xQGeo6loDfTW1mlfetq/zpW7CKbUp +qve9eYYulneAy/81M/UoUZSzHqj6XY39wzJCH20H+Qx3WwcqXgSU7fSFXyJ4EBYs +kWybbrAra5v29LUTBd7OvvS+Swovdh4T31YijUOUUL/gJkBI9UneVyV7/8DdUoVJ +a8ym2pZ6ALy+GZrWBHcCKD/rQjEkXJnDglu+FSUI50SzaC9YX31TTzEMJijiPi6I +MIZJMXLH7GpCIDcvyrLWIRYVJAQRoYJB4rmp42HTyed4eg4RnSiFrxVV5xQaDnSl +/8zSOdVMBVewp8ipv34VeRXgNTgRkhA2JmL+KlALMkPo7MbRkJF01DiOOsIdz3Iu +43oYg3QYmqxZI6kZNtXpUMnJeuRmMQJJN8yc9ZdOA9Ll2TTcIql8XEsjGcM7IWM9 +CP6zGwCcbrv72Ka+h/bGaLpwLbpkr5I8PjjSECn9fBcgnVX6HfKH7u3y11+Va1nh +a8ZEE1TuOqRxnVDQ+K4iwaZFgFYsBMKo2ghoU2ZbZxu14vs6Eksn6UFsm8DpPwfy +jtLtdje8jrbYAqAy5zIMLoW+I6Rb5sU3Olh9nI7NW4T5qQeemBcuRAwB4QARAQAB +tDdNb25nb0RCIDQuNCBSZWxlYXNlIFNpZ25pbmcgS2V5IDxwYWNrYWdpbmdAbW9u +Z29kYi5jb20+iQI+BBMBAgAoBQJc7XqsAhsDBQkJZgGABgsJCAcDAgYVCAIJCgsE +FgIDAQIeAQIXgAAKCRBlZAjjkM+x9SKmD/9BzdjFAgBPPkUnD5pJQgsBQKUEkDsu +cht6Q0Y4M635K7okpqJvXtZV5Mo+ajWZjUeHn4wPdVgzF2ItwVLRjjak3tIZfe3+ +ME5Y27Aej3LeqQC3Q5g6SnpeZwVEhWzU35CnyhQecP4AhDG3FO0gKUn3GkEgmsd6 +rnXAQLEw3VUYO8boxqBF3zjmFLIIaODYNmO1bLddJgvZlefUC62lWBBUs6Z7PBnl +q7qBQFhz9qV9zXZwCT2/vgGLg5JcwVdcJXwAsQSr1WCVd7Y79+JcA7BZiSg9FAQd +4t2dCkkctoUKgXsAH5fPwErGNj5L6iUnhFODPvdDJ7l35UcIZ2h74lqfEh+jh8eo +UgxkcI2y2FY/lPapcPPKe0FHzCxG2U/NRdM+sqrIfp9+s88Bj+Eub7OhW4dF3AlL +bh/BGHL9R8xAJRDLv8v7nsKkZWUnJaskeDFCKX3rjcTyTRWTG7EuMCmCn0Ou1hKc +R3ECvIq0pVfVh+qk0hu+A5Dvj6k3QDcTfse+KfSAJkYvRKiuRuq5KgYcX3YSzL6K +aZitMyu18XsQxKavpIGzaDhWyrVAig3XXF//zxowYVwuOikr5czgqizu87cqjpyn +S0vVG4Q3+LswH4xVTn3UWadY/9FkM167ecouu4g3op29VDi7hCKsMeFvFP6OOIls +G4vQ/QbzucK77Q== +=eD3N +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/mongodb/files/server-4.4.gpg b/mongodb/files/server-4.4.gpg new file mode 100644 index 00000000..f1b1730e Binary files /dev/null and b/mongodb/files/server-4.4.gpg differ diff --git a/mongodb/files/server-5.0.asc b/mongodb/files/server-5.0.asc new file mode 100644 index 00000000..44ea4919 --- /dev/null +++ b/mongodb/files/server-5.0.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGAsKNUBEAClMqPCvvqm6gFmbiorEN9qp00GI8oaECkwbxtGGbqX9sqMSrKe +AB3sGI7kqG2Fl0K+xmmiq1QDjhNgFDA1jjXq+Bd66RNPtvu747IRxVs+9fX7bk67 +8Bruha7U3M5l4193x5oYLlbcZL9aC7RSJE2mggTyS6LarmF6vKQN9LMXDicnageV +KCPpF2i3jkZaGnLPzAisW/pOjPQpWCbatTVqKOKvtOyP3Fz1spYd4obu6ELu1PXa +gmhSfvWJYt1irpchOl29LWZfcmXuJszmb00bqm4gLcK12VrnK191iXv46A8h2hSO +f3eQqrkc+pF/kw4RyG54EV7QtHXyTe9TVCbJUfgtliWIQt/bCoJYfPLHJaWIMs83 +bzA6ZvOjCKIfMS0CY5ZJyVaBfiI3wURSjgZIYFZAXVwbreQIfOKKuik7UVVn3xUO +nWpmQ2zyI0W7cJMquxwLNjkI+RckPhIqxWFo5iNSV4v6pzrlHD1WmIfFGBKEn7m+ +edwVyHG53fNIFZjxyShO6Pf1vgb9Js/XmXB4lxYnNyx1tB+hQhXTjLlY6N5gPpw5 +Z/PWQc7vfYekUZGQMXhTyRxU0QTwmdEeKcb+fb9r23OH59bbAfzE10xTMzhqCd2L +lgSozMBvMmkHb1xs1x6FFuv/U/X7LjHTrHIf4M//DNwdP4l4I1jhPlTAxwARAQAB +tDdNb25nb0RCIDUuMCBSZWxlYXNlIFNpZ25pbmcgS2V5IDxwYWNrYWdpbmdAbW9u +Z29kYi5jb20+iQI+BBMBAgAoBQJgLCjVAhsDBQkJZgGABgsJCAcDAgYVCAIJCgsE +FgIDAQIeAQIXgAAKCRCwCgvR4sY8EawdD/0ewkyx3yE99K9n3y7gdvh5+2U8BsqU +7SWEfup7kPpf+4pF5xWqMaciEV/wRAGt7TiKlfVyAv3Q9iNsaLFN+s3kMaIcKhwD +8+q/iGfziIuOSTeo20dAxn9vF6YqrKGc7TbHdXf9AtYuJCfIU5j02uVZiupx+P9+ +rG39dEnjOXm3uY0Fv3pRGCpuGubDlWB1DYh0R5O481kDVGoMqBxmc3iTALu14L/u +g+AKxFYfT4DmgdzPVMDhppgywfyd/IOWxoOCl4laEhVjUt5CygBa7w07qdKwWx2w +gTd9U0KGHxnnSmvQYxrRrS5RX3ILPJShivTSZG+rMqnUe6RgCwBrKHCRU1L728Yv +1B3ZFJLxB1TlVT2Hjr+oigp0RY9W1FCIdO2uhb9GImpaJ1Y0ZZqUkt/d9D8U2wcw +SW6/6WYeO7wAi/zlJ25hrBwhxS2+88gM6wJ1yL9yrM9v8JUb7Kq0rCGsEO5kqscV +AmX90wsF2cZ6gHR53eGIDbAJK0MO5RHR73aQ4bpTivPnoTx4HTj5fyhW9z8yCSOe +BlQABoFFqFvOS7KBxoyIS3pxlDetWOSc6yQrvA1CwxnkB81OHNmJfWAbNbEtZkLm +xs2c8CIh2R81yi6HUzAaxyDH7mrThbwX3hUe/wsaD1koV91G6bDD4Xx3zpa9DG/O +HyB98+e983gslg== +=IQQF +-----END PGP PUBLIC KEY BLOCK----- diff --git a/mongodb/tasks/main.yml b/mongodb/tasks/main.yml index a054a5fd..3054ccfe 100644 --- a/mongodb/tasks/main.yml +++ b/mongodb/tasks/main.yml @@ -1,10 +1,5 @@ --- -# - fail: -# msg: only compatible with Debian 8 -# when: -# - ansible_distribution != "Debian" or ansible_distribution_release != "jessie" - - include: main_jessie.yml when: ansible_distribution_release == "jessie" @@ -12,4 +7,7 @@ when: ansible_distribution_release == "stretch" - include: main_buster.yml - when: ansible_distribution_major_version is version('10', '>=') + when: ansible_distribution_release == "buster" + +- include: main_bullseye.yml + when: ansible_distribution_major_version is version('11', '>=') diff --git a/mongodb/tasks/main_bullseye.yml b/mongodb/tasks/main_bullseye.yml new file mode 100644 index 00000000..e31ffed3 --- /dev/null +++ b/mongodb/tasks/main_bullseye.yml @@ -0,0 +1,111 @@ +--- + +- fail: + msg: Not compatible with Debian 11 (Bullseye) + when: + - ansible_distribution_release == "bullseye" + - mongodb_version is version_compare('5.0', '<=') + + +- name: MongoDB embedded GPG key is absent + apt_key: + id: "B8612B5D" + keyring: /etc/apt/trusted.gpg + state: absent + when: _trusted_gpg_keyring.stat.exists + +- name: Add MongoDB GPG key + copy: + src: "server-{{mongodb_version}}.asc" + dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc" + force: yes + mode: "0644" + owner: root + group: root + +- name: enable APT sources list + apt_repository: + repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{mongodb_version}} main" + state: present + filename: "mongodb-org-{{mongodb_version}}" + update_cache: yes + +- name: Install packages + apt: + name: mongodb-org + update_cache: yes + state: present + register: _mongodb_install_package + +- name: MongoDB service in enabled and started + systemd: + name: mongod + enabled: yes + state: started + when: _mongodb_install_package is changed + +- name: install dependency for monitoring + apt: + name: python-pymongo + state: present + +- name: Custom configuration + template: + src: mongodb_buster.conf.j2 + dest: "/etc/mongod.conf" + force: "{{ mongodb_force_config | bool | ternary('yes', 'no') }}" + notify: restart mongod + +- name: Configure logrotate + template: + src: logrotate_buster.j2 + dest: /etc/logrotate.d/mongodb + force: yes + backup: no + +- include_role: + name: evolix/remount-usr + +- name: Create plugin directory + file: + name: /usr/local/share/munin/ + state: directory + mode: "0755" + +- name: Create plugin directory + file: + name: /usr/local/share/munin/plugins/ + state: directory + mode: "0755" + +- name: Munin plugins are present + copy: + src: "munin/{{ item }}" + dest: '/usr/local/share/munin/plugins/{{ item }}' + force: yes + loop: + - mongo_btree + - mongo_collections + - mongo_conn + - mongo_docs + - mongo_lock + - mongo_mem + - mongo_ops + - mongo_page_faults + notify: restart munin-node + +- name: Enable core Munin plugins + file: + src: '/usr/local/share/munin/plugins/{{ item }}' + dest: /etc/munin/plugins/{{ item }} + state: link + loop: + - mongo_btree + - mongo_collections + - mongo_conn + - mongo_docs + - mongo_lock + - mongo_mem + - mongo_ops + - mongo_page_faults + notify: restart munin-node diff --git a/mongodb/tasks/main_buster.yml b/mongodb/tasks/main_buster.yml index 2e62255a..cf5ce2ae 100644 --- a/mongodb/tasks/main_buster.yml +++ b/mongodb/tasks/main_buster.yml @@ -1,15 +1,21 @@ --- +- name: Look for legacy apt keyring + stat: + path: /etc/apt/trusted.gpg + register: _trusted_gpg_keyring + - name: MongoDB embedded GPG key is absent apt_key: id: "B8612B5D" keyring: /etc/apt/trusted.gpg state: absent + when: _trusted_gpg_keyring.stat.exists - name: Add MongoDB GPG key copy: - src: server-4.2.asc - dest: /etc/apt/trusted.gpg.d/mongodb-server-4.2.asc + src: "server-{{mongodb_version}}.asc" + dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc" force: yes mode: "0644" owner: root @@ -17,9 +23,9 @@ - name: enable APT sources list apt_repository: - repo: deb http://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main + repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{mongodb_version}} main" state: present - filename: mongodb-org-4.2 + filename: "mongodb-org-{{mongodb_version}}" update_cache: yes - name: Install packages @@ -55,6 +61,9 @@ force: yes backup: no +- include_role: + name: evolix/remount-usr + - name: Create plugin directory file: name: /usr/local/share/munin/ diff --git a/mongodb/templates/logrotate_bullseye.j2 b/mongodb/templates/logrotate_bullseye.j2 new file mode 100644 index 00000000..8239e880 --- /dev/null +++ b/mongodb/templates/logrotate_bullseye.j2 @@ -0,0 +1,15 @@ +# {{ ansible_managed }} + +/var/log/mongodb/mongod.log { + daily + missingok + rotate 365 + dateext + compress + delaycompress + notifempty + sharedscripts + postrotate + pidof mongod | xargs kill -USR1 + endscript +} diff --git a/mongodb/templates/mongodb_bullseye.conf.j2 b/mongodb/templates/mongodb_bullseye.conf.j2 new file mode 100644 index 00000000..b61479bd --- /dev/null +++ b/mongodb/templates/mongodb_bullseye.conf.j2 @@ -0,0 +1,39 @@ +# mongodb.conf - {{ ansible_managed }} + +# for documentation of all options, see: +# http://docs.mongodb.org/manual/reference/configuration-options/ + +# Where and how to store data. +storage: + dbPath: /var/lib/mongodb + journal: + enabled: true +# engine: +# mmapv1: +# wiredTiger: + +# where to write logging data. +systemLog: + destination: file + logRotate: reopen + logAppend: true + path: /var/log/mongodb/mongodb.log + +# network interfaces +net: + port: {{ mongodb_port }} + bindIp: {{ mongodb_bind }} + +#security: + +#operationProfiling: + +#replication: + +#sharding: + +## Enterprise-Only Options: + +#auditLog: + +#snmp: diff --git a/munin/handlers/main.yml b/munin/handlers/main.yml index a0d465a2..8654181d 100644 --- a/munin/handlers/main.yml +++ b/munin/handlers/main.yml @@ -1,4 +1,5 @@ --- + - name: restart munin-node service: name: munin-node @@ -8,3 +9,7 @@ service: name: munin_node state: restarted + +- name: systemd daemon-reload + systemd: + daemon_reload: yes \ No newline at end of file diff --git a/munin/tasks/main.yml b/munin/tasks/main.yml index aab79f62..81769488 100644 --- a/munin/tasks/main.yml +++ b/munin/tasks/main.yml @@ -88,3 +88,20 @@ [swap] user root when: ansible_kernel is search("-grs-") + +- name: Create override directory for munin-node unit + file: + name: /etc/systemd/system/munin-node.service.d/ + state: directory + mode: "0755" + +- name: Override is present for protected home + ini_file: + dest: "/etc/systemd/system/munin-node.service.d/override.conf" + section: "Service" + option: "ProtectHome" + value: "false" + state: present + notify: + - systemd daemon-reload + - restart munin-node diff --git a/mysql-oracle/tasks/users.yml b/mysql-oracle/tasks/users.yml index da1ca05f..d0c444e5 100644 --- a/mysql-oracle/tasks/users.yml +++ b/mysql-oracle/tasks/users.yml @@ -1,12 +1,24 @@ --- -# dependency for mysql_user and mysql_db -- name: python-mysqldb is installed (Ansible dependency) +- name: Python2 dependencies for Ansible are installed apt: - name: python-mysqldb + name: + - python-mysqldb + - python-pymysql state: present tags: - mysql + when: ansible_python_version is version('3', '<') + +- name: Python3 dependencies for Ansible are installed + apt: + name: + - python3-mysqldb + - python3-pymysql + state: present + tags: + - mysql + when: ansible_python_version is version('3', '>=') - name: create a password for mysqladmin command: "apg -n 1 -m 16 -M lcN" diff --git a/mysql-oracle/tasks/utils.yml b/mysql-oracle/tasks/utils.yml index e7573afe..e0520cee 100644 --- a/mysql-oracle/tasks/utils.yml +++ b/mysql-oracle/tasks/utils.yml @@ -17,7 +17,7 @@ # mytop -- name: "mytop is installed (jessie)" +- name: "mytop is installed (Debian 9)" apt: name: mytop state: present @@ -32,7 +32,7 @@ # name: mysql-utilities # when: ansible_distribution_major_version is version('9', '>=') -- name: "mytop dependencies are installed (stretch)" +- name: "mytop dependencies are installed (Buster)" apt: name: - libconfig-inifiles-perl @@ -46,13 +46,21 @@ - mysql when: ansible_distribution_release == "stretch" -- name: "Install dependencies for mytop (Debian 10 or later)" +- name: "Install dependencies for mytop (Debian 10)" apt: name: - mariadb-client-10.3 - libconfig-inifiles-perl - libterm-readkey-perl - when: ansible_distribution_major_version is version('10', '>=') + when: ansible_distribution_release == "buster" + +- name: "Install dependencies for mytop (Debian 11 or later)" + apt: + name: + - mariadb-client-10.5 + - libconfig-inifiles-perl + - libterm-readkey-perl + when: ansible_distribution_major_version is version('11', '>=') - include_role: name: evolix/remount-usr diff --git a/mysql/defaults/main.yml b/mysql/defaults/main.yml index 2986a869..80f526c6 100644 --- a/mysql/defaults/main.yml +++ b/mysql/defaults/main.yml @@ -48,6 +48,8 @@ mysql_evolinux_custom_file: zzz-evolinux-custom.cnf mysql_restart_if_needed: True +mysql_performance_schema: True + # replication variables: mysql_replication: false mysql_log_bin: null diff --git a/mysql/files/evomariabackup.sh b/mysql/files/evomariabackup.sh new file mode 100644 index 00000000..0e3de84b --- /dev/null +++ b/mysql/files/evomariabackup.sh @@ -0,0 +1,554 @@ +#!/bin/sh + +VERSION="21.11" + +show_version() { + cat <, + Éric Morino , + Jérémy Lecour + and others. + +evomariabackup comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU Affero General Public License v3.0 for details. +END +} +show_help() { + cat <> "${log_file}" + else + log_line "${level}" "${msg}" >&2 + fi + fi +} +log_info() { + level="INFO" + msg=$1 + if ! is_quiet; then + if is_log_file; then + log_line "${level}" "${msg}" >> "${log_file}" + else + log_line "${level}" "${msg}" >&2 + fi + fi +} +log_warning() { + level="WARNING" + msg=$1 + if ! is_quiet; then + if is_log_file; then + log_line "${level}" "${msg}" >> "${log_file}" + else + log_line "${level}" "${msg}" >&2 + fi + fi +} +log_error() { + level="ERROR" + msg=$1 + if ! is_quiet; then + if is_log_file; then + log_line "${level}" "${msg}" >> "${log_file}" + if tty -s; then + printf "%s\n" "${msg}" >&2 + fi + else + log_line "${level}" "${msg}" >&2 + fi + fi +} +log_fatal() { + level="FATAL" + msg=$1 + if is_log_file; then + log_line "${level}" "${msg}" >> "${log_file}" + if tty -s; then + printf "%s\n" "${msg}" >&2 + fi + else + log_line "${level}" "${msg}" >&2 + fi +} +duration_in_seconds() { + if echo "${1}" | grep -E -q '^([0-9]+[wdhms])+$'; then + duration=$(echo "${1}" | sed 's/w/ * 604800 + /g; s/d/ * 86400 + /g; s/h/ * 3600 + /g; s/m/ * 60 + /g; s/s/ + /g; s/+ $//' | xargs expr) + elif echo "${1}" | grep -E -q '^[0-9]+$'; then + duration=$(echo "${1} * 3600" | xargs expr) + else + return 1 + fi + log_debug "Duration \`${1}' translated to ${duration} seconds" + + echo "${duration}" +} +lock_file_created_at() { + created_at=$(stat -c %Z "${lock_file}") + log_debug "Lock file ${lock_file} created at ${created_at}" + + echo "${created_at}" +} +lock_file_age() { + last_change=$(lock_file_created_at) + now=$(date +"%s") + + age=$(( now - last_change )) + log_debug "Lock file ${lock_file} is ${age} seconds old" + + echo "${created_at}" +} +is_lock_file_too_old() { + test "$(lock_file_age)" -ge "${max_age}" +} +kill_or_clean_lockfile() { + lock_file=${1:-} + + if [ -f "${lock_file}" ]; then + # Get Process ID from the lock file + pid=$(cat "${lock_file}") + if [ -n "${pid}" ]; then + log_debug "Found pid ${pid} in ${lock_file}" + + if kill -0 "${pid}" 2> /dev/null; then + log_debug "Found process with pid ${pid}" + + lock_file_created_at_human=$(date --date "@$(lock_file_created_at)" +"%Y-%m-%d %H:%M:%S") + if is_lock_file_too_old ; then + # Kill the children + pkill -9 --parent "${pid}" + # Kill the parent + kill -9 "${pid}" + # Only one process can run in parallel + log_warning "Process \`${pid}' (started at ${lock_file_created_at_human}) has been killed by \`$$'" + else + log_info "Process \`${pid}' (started at ${lock_file_created_at_human}) has precedence. Let's leave it work." + # make sure that this exit doesn't remove the existing lockfile !! + exit 0 + fi + else + log_warning "Process not found at PID \`${pid}'. Ignoring lock file \`${lock_file}'." + fi + else + log_warning "Empty lockfile \`${lock_file}'. It should contain a PID." + fi + # Remove the lock file + rm -f "${lock_file}" + log_debug "Lock file ${lock_file} has been removed" + fi +} +new_lock_file() { + lock_file=${1:-} + lock_dir=$(dirname "${lock_file}") + + if mkdir --parents "${lock_dir}"; then + echo $$ > "${lock_file}" + log_debug "Lock file '${lock_file}' has been created" + else + log_fatal "Failed to acquire lock file '${lock_file}'. Abort." + exit 1 + fi +} +is_mariabackup_directory() { + directory=${1:-} + find "${directory}" -name 'ibdata*' -o -name 'ib_logfile*' -o -name 'xtrabackup_*' > /dev/null +} +check_backup_dir() { + if [ -d "${backup_dir:?}" ]; then + if [ "$(ls -A "${backup_dir:?}")" ]; then + if is_mariabackup_directory "${backup_dir:?}"; then + log_debug "The backup directory ${backup_dir:?} is not empty but looks like a mariabackup target. Let's clear it." + rm -rf "${backup_dir:?}" + else + log_fatal "The backup directory ${backup_dir:?} is not empty and doesn't look like a mariabackup target. Please verify and clear the directory if you are sure." + exit 1 + fi + else + log_debug "The backup directory ${backup_dir:?} exists but is empty. Let's proceed." + fi + else + log_debug "The backup directory ${backup_dir:?} doesn't exist. Let's proceed." + fi + mkdir -p "${backup_dir:?}" +} +check_compress_dir() { + if [ -d "${compress_dir:?}" ]; then + log_debug "The compress_dir directory ${compress_dir:?} exists. Let's proceed." + else + log_debug "The compress_dir directory ${compress_dir:?} doesn't exist. Let's proceed." + fi + mkdir -p "${compress_dir:?}" +} + +backup() { + if [ -z "${backup_dir}" ]; then + log_fatal "backup-dir option is empty" + else + check_backup_dir + fi + + mariabackup_bin=$(command -v mariabackup) + if [ -z "${mariabackup_bin}" ]; then + log_fatal "Couldn't find mariabackup.\nUse 'apt install mariadb-backup'." + exit 1 + fi + + backup_command="${mariabackup_bin} --backup --slave-info --target-dir=${backup_dir:?}" + + + if ! is_quiet; then + log_debug "${backup_command}" + log_info "BEGIN mariabackup backup phase" + fi + + if is_quiet || ! is_verbose ; then + ${backup_command} >/dev/null 2>&1 + backup_rc=$? + elif ! is_quiet; then + if is_log_file; then + ${backup_command} >>"${log_file}" 2>&1 + backup_rc=$? + else + ${backup_command} + backup_rc=$? + fi + fi + + if [ ${backup_rc} -ne 0 ]; then + log_fatal "Error executing mariabackup --backup" + exit 1 + elif ! is_quiet; then + log_info "END mariabackup backup phase" + fi + + prepare_command="${mariabackup_bin} --prepare --target-dir=${backup_dir:?}" + + if ! is_quiet; then + log_debug "${prepare_command}" + log_info "BEGIN mariabackup prepare phase" + fi + + if is_quiet || ! is_verbose ; then + ${prepare_command} >/dev/null 2>&1 + prepare_rc=$? + elif ! is_quiet; then + if is_log_file; then + ${prepare_command} >>"${log_file}" 2>&1 + prepare_rc=$? + else + ${prepare_command} + prepare_rc=$? + fi + fi + + if [ ${prepare_rc} -ne 0 ]; then + log_fatal "Error executing mariabackup --prepare" + exit 1 + elif ! is_quiet; then + log_info "END mariabackup prepare phase" + fi +} +compress() { + compress_dir=$(dirname "${compress_file}") + + if [ -z "${backup_dir}" ]; then + log_fatal "backup-dir option is empty" + exit 1 + elif [ -e "${backup_dir}" ] && [ ! -d "${backup_dir}" ]; then + log_fatal "backup directory '${backup_dir}' exists but is not a directory" + exit 1 + fi + if [ -z "${compress_file}" ]; then + log_fatal "compress-file option is empty" + exit 1 + fi + if [ -n "${compress_dir}" ]; then + check_compress_dir + fi + + pigz_bin=$(command -v pigz) + gzip_bin=$(command -v gzip) + + if [ -n "${pigz_bin}" ]; then + compress_program="${pigz_bin} --keep -6" + elif [ -n "${gzip_bin}" ]; then + compress_program="${gzip_bin} -6" + else + log_fatal "Couldn't find pigz nor gzip.\nUse 'apt install pigz' or 'apt install gzip'." + exit 1 + fi + + if ! is_quiet; then + log_debug "Compression of ${backup_dir} to ${compress_file} using \`${compress_program}'" + log_info "BEGIN compression phase" + fi + if is_quiet || ! is_verbose ; then + tar --use-compress-program="${compress_program}" -cf "${compress_file}" "${backup_dir}" >/dev/null 2>&1 + tar_rc=$? + elif ! is_quiet; then + if is_log_file; then + tar --use-compress-program="${compress_program}" -cf "${compress_file}" "${backup_dir}" >>"${log_file}" 2>&1 + tar_rc=$? + else + tar --use-compress-program="${compress_program}" -cf "${compress_file}" "${backup_dir}" + tar_rc=$? + fi + fi + + if [ ${tar_rc} -ne 0 ]; then + log_fatal "An error occured while compressing ${backup_dir} to ${compress_file}" + exit 1 + elif ! is_quiet; then + log_info "END compression phase" + fi +} +main() { + kill_or_clean_lockfile "${lock_file}" + # shellcheck disable=SC2064 + trap "rm -f ${lock_file};" 0 + new_lock_file "${lock_file}" + + if [ "${do_backup}" = "1" ] && [ -n "${backup_dir}" ]; then + backup "${backup_dir}" + fi + + if [ "${do_compress}" = "1" ] && [ -n "${compress_file}" ]; then + compress "${backup_dir}" "${compress_file}" + fi +} + +# Declare variables + +lock_file="" +log_file="" +verbose="" +quiet="" +max_age="" +max_age="" +do_backup="" +backup_dir="" +do_compress="" +compress_file="" + +# Parse options +# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a +while :; do + case $1 in + -h|-\?|--help) + show_help + exit 0 + ;; + -V|--version) + show_version + exit 0 + ;; + + -m|--max-age) + # with value separated by space + if [ -n "$2" ]; then + max_age=$(duration_in_seconds "$2") + shift + else + log_fatal 'ERROR: "-m|--max-age" requires a non-empty option argument.' + fi + ;; + --max-age=?*) + # with value speparated by = + max_age=$(duration_in_seconds "${1#*=}") + ;; + --max-age=) + # without value + log_fatal 'ERROR: "--max-age" requires a non-empty option argument.' + ;; + + --backup) + do_backup=1 + ;; + + --no-backup) + do_backup=0 + ;; + + --backup-dir) + # with value separated by space + if [ -n "$2" ]; then + backup_dir="$2" + shift + else + log_fatal 'ERROR: "--backup-dir" requires a non-empty option argument.' + fi + ;; + --backup-dir=?*) + # with value speparated by = + backup_dir=${1#*=} + ;; + --backup-dir=) + # without value + log_fatal '"--backup-dir" requires a non-empty option argument.' + ;; + + --compress) + do_compress=1 + ;; + + --no-compress) + do_compress=0 + ;; + + --compress-file) + # with value separated by space + if [ -n "$2" ]; then + compress_file="$2" + if [ -z "${do_compress}" ]; then + do_compress=1 + fi + shift + else + log_fatal '"--compress-file" requires a non-empty option argument.' + fi + ;; + --compress-file=?*) + # with value speparated by = + compress_file=${1#*=} + if [ -z "${do_compress}" ]; then + do_compress=1 + fi + ;; + --compress-file=) + # without value + log_fatal '"--compress-file" requires a non-empty option argument.' + ;; + + --lock-file) + # with value separated by space + if [ -n "$2" ]; then + lock_file="$2" + shift + else + log_fatal '"--lock-file" requires a non-empty option argument.' + fi + ;; + --lock-file=?*) + # with value speparated by = + lock_file=${1#*=} + ;; + --lock-file=) + # without value + log_fatal '"--lock-file" requires a non-empty option argument.' + ;; + + --log-file) + # with value separated by space + if [ -n "$2" ]; then + log_file="$2" + shift + else + log_fatal '"--log-file" requires a non-empty option argument.' + fi + ;; + --log-file=?*) + # with value speparated by = + log_file=${1#*=} + ;; + --log-file=) + # without value + log_fatal '"--log-file" requires a non-empty option argument.' + ;; + + -v|--verbose) + verbose=1 + ;; + + --quiet) + quiet=1 + verbose=0 + ;; + + --) + # End of all options. + shift + break + ;; + -?*|[[:alnum:]]*) + # ignore unknown options + if tty -s; then + printf 'Unknown option : %s\n' "$1" >&2 + echo "" >&2 + show_usage >&2 + exit 1 + else + log_fatal 'Unknown option : %s\n' "$1" >&2 + fi + ;; + *) + # Default case: If no more options then break out of the loop. + break + ;; + esac + + shift +done + +# Default values + +lock_file="${lock_file:-/run/lock/evomariabackup.lock}" +verbose=${verbose:-0} +quiet=${quiet:-0} +max_age="${max_age:-86400}" +do_backup="${do_backup:-1}" +do_compress="${do_compress:-0}" + +main \ No newline at end of file diff --git a/mysql/files/mysql-queries-killer.sh b/mysql/files/mysql-queries-killer.sh new file mode 100644 index 00000000..3ea6e00b --- /dev/null +++ b/mysql/files/mysql-queries-killer.sh @@ -0,0 +1,197 @@ +#!/bin/sh + +VERSION="21.08" + +show_version() { + cat <, + Jérémy Lecour + and others. + +mysql-queries-killer comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. +END +} + +show_help() { + cat <] --list [--time