diff --git a/.Jenkinsfile b/.Jenkinsfile index 3f591b98..d10526b2 100644 --- a/.Jenkinsfile +++ b/.Jenkinsfile @@ -6,6 +6,20 @@ pipeline { } stages { + stage('Anible Lint') { + agent { + docker { + image 'evolix/ansible-lint:latest' + } + } + steps { + script { + sh 'for role_dir in ./*/; do HOME=$WORKSPACE_TMP ansible-lint -p $role_dir || : ; done' + recordIssues(tools: [ansibleLint()]) + } + } + } + stage('Build tagged docker image') { when { buildingTag() diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..ce271884 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "*.yml": "ansible", + "*.yaml": "ansible" + }, + "yaml.format.enable": false +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f5e0e0c..dc0b7cc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ 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] ### Added @@ -20,6 +21,63 @@ The **patch** part changes is incremented if multiple releases happen the same m ### Security +## [23.03] 2023-03-16 + +### Added + +* apache: add task to enable mailgraph on default vhost and index.html +* apt: add move-apt-keyrings script/tasks +* apt: add tools to migrate sources to deb822 format +* fail2ban: add "Internal login failure" to Dovecot filter +* lxc: copy `/etc/profile.d/evolinux.sh` from host into container +* nagios-nrpe: add tasks/files for a wrapper +* nagios-nrpe: Print pool config path in check_phpfpm_multi output +* php: add `php_version` variable when sury is activated for each Debian version +* php: add a way to choose which version to install using sury repository +* postfix: Add task to enable mailgraph on packmail +* postgresql: configure max_connections +* userlogrotate: create dedicated role, separated from packweb-apache +* varnish: add `varnish_update_config` variable to disable configuration update + +### Changed + +* Use systemd module instead of command +* Removed all `warn: False` args in command, shell and other modules as it's been deprecated and will give a hard fail in ansible-core 2.14.0. +* apt: Use pub.evolix.org instead of pub.evolix.net +* bind: refactor role +* elasticsearch: Disable garabge collector logging (JDK >= 9) +* evolinux-users: Update sudoers template to remove commands allowed without password +* listupgrade: upstream release 23.03.3 +* kvmstats: use virsh domstats | awk to get guests informations +* nagios-nrpe : Rewrite `check_vrrpd` for a better check (check `rp_filter`, `vrrpd` and `uvrrpd` compatible, use arguments, …) +* openvpn: Change `check_openvpn` destination file to comply with recent EvoBSD change +* postfix: come back to default value of `notify_classes` for pack mails. +* userlogrotate: set rotate date format in right order (YYYY-MM-DD)! +* webapps/nextcloud : Change default data directory to be outside web root +* webapps/nextcloud : Small enhancement on the vhost template to lock out data dir +* yarn: update apt key + +### Fixed + +* Proper jinja spacing +* clamav: set `MaxConnectionQueueLength` to its default value (200), custom (15) was way too small and caused recurring failures in Postfix. +* docker-host: fix type in `daemon.json` and remove host configuration that is already in the systemd service by default +* evolinux-base: ensure dbus is started and enabled (not by default in the case of an offline netinst) +* haproxy: fix missing admin ACL in stats module access permissions +* openvpn: fix the client cipher configuration to match the server cipher configuration +* php: fix error introduced in #33503e4538 (`False` evaluated as a String instead of Boolean) +* php: install using Sury repositories on Bullseye +* postfix (packmail only): disable `concurrency_failed_cohort_limit` for destination smtp-amavis to prevent the suspension of this destination when Amavis fails to answer. Indeed, we configure the suspension delay quite long in `minimal_backoff_time` (2h) and `maximal_backoff_time` (6h) to reduce the risk of ban from external SMTPs. +* postfix: avoid Amavis transport to be considered dead when restarted. +* postfix: remove unused `aliases_scope=sub` from virtual_aliases.cf (it generated warnings) +* userlogrotate: fix bug introduced in commit 2e54944a246 (rotated files were not zipped) +* userlogrotate: skip zipping if .gz log already exists (prevents interactive question) + +### Removed + +* evolinux-base: subversion is not installed anymore + + ## [22.12] 2022-12-14 ### Added @@ -34,6 +92,7 @@ The **patch** part changes is incremented if multiple releases happen the same m * packweb-apache: enable `log_forensic` module * rabbitmq: add link in default page * varnish: create special tmp directory for syntax validation +* postfix: add localhost.$mydomain to mydestination ### Changed diff --git a/amazon-ec2/tasks/create-instance.yml b/amazon-ec2/tasks/create-instance.yml index a3f84b1a..86e8f803 100644 --- a/amazon-ec2/tasks/create-instance.yml +++ b/amazon-ec2/tasks/create-instance.yml @@ -3,34 +3,34 @@ - name: Launch new instance(s) ec2: state: present - aws_access_key: "{{aws_access_key}}" - aws_secret_key: "{{aws_secret_key}}" - region: "{{aws_region}}" - image: "{{ec2_base_ami}}" - instance_type: "{{ec2_instance_type}}" - count: "{{ec2_instance_count}}" - assign_public_ip: "{{ec2_public_ip}}" - group: "{{ec2_security_group.name}}" - key_name: "{{ec2_keyname}}" + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + region: "{{ aws_region }}" + image: "{{ ec2_base_ami }}" + instance_type: "{{ ec2_instance_type }}" + count: "{{ ec2_instance_count }}" + assign_public_ip: "{{ ec2_public_ip }}" + group: "{{ ec2_security_group.name }}" + key_name: "{{ ec2_keyname }}" wait: yes register: ec2 - name: Add newly created instance(s) to inventory add_host: - hostname: "{{item.public_dns_name}}" + hostname: "{{ item.public_dns_name }}" groupname: launched-instances ansible_user: admin ansible_ssh_common_args: "-o StrictHostKeyChecking=no" - loop: "{{ec2.instances}}" + loop: "{{ ec2.instances }}" - debug: - msg: "Your newly created instance is reachable at: {{item.public_dns_name}}" - loop: "{{ec2.instances}}" + msg: "Your newly created instance is reachable at: {{ item.public_dns_name }}" + loop: "{{ ec2.instances }}" - name: Wait for SSH to come up on all instances (give up after 2m) wait_for: state: started - host: "{{item.public_dns_name}}" + host: "{{ item.public_dns_name }}" port: 22 timeout: 120 - loop: "{{ec2.instances}}" + loop: "{{ ec2.instances }}" diff --git a/apache/tasks/server_status.yml b/apache/tasks/server_status.yml index efd2b00e..38daf285 100644 --- a/apache/tasks/server_status.yml +++ b/apache/tasks/server_status.yml @@ -68,3 +68,10 @@ insertafter: "[apache_*]" create: no notify: restart munin-node + +- name: add mailgraph URL in index.html + lineinfile: + dest: /var/www/index.html + state: present + line: '
  • Stats Mail
  • ' + insertbefore: "" diff --git a/apache/templates/evolinux-default.conf.j2 b/apache/templates/evolinux-default.conf.j2 index 68cdcf84..effa55c6 100644 --- a/apache/templates/evolinux-default.conf.j2 +++ b/apache/templates/evolinux-default.conf.j2 @@ -35,6 +35,15 @@ Include /etc/apache2/ipaddr_whitelist.conf + # Mailgraph configuration + Alias /mailgraph /usr/share/mailgraph + + DirectoryIndex mailgraph.cgi + Require all granted + Options +FollowSymLinks +ExecCGI + AddHandler cgi-script .cgi + + CustomLog /var/log/apache2/access.log vhost_combined ErrorLog /var/log/apache2/error.log LogLevel warn @@ -118,6 +127,15 @@ Include /etc/apache2/ipaddr_whitelist.conf + # Mailgraph configuration + Alias /mailgraph /usr/share/mailgraph + + DirectoryIndex mailgraph.cgi + Require all granted + Options +FollowSymLinks +ExecCGI + AddHandler cgi-script .cgi + + # BEGIN phpMyAdmin section # END phpMyAdmin section diff --git a/apt/files/deb822-migration.py b/apt/files/deb822-migration.py new file mode 100644 index 00000000..10ee47ae --- /dev/null +++ b/apt/files/deb822-migration.py @@ -0,0 +1,96 @@ +#!/bin/env python3 + +import re +import sys +import os + +if len(sys.argv) > 1: + src_file = sys.argv[1] +else: + print("You must provide a source file as first argument", file=sys.stderr) + sys.exit(1) + +if not os.access(src_file, os.R_OK): + print(src_file, "is not readable", file=sys.stderr) + sys.exit(2) + +pattern = re.compile('^(?Pdeb|deb-src) +(?P\[.+\] ?)*(?P\w+:\/\/\S+) +(?P\S+)(?: +(?P.*))?$') + +sources = {} + +def split_options(raw): + table = str.maketrans({ + "[": None, + "]": None + }) + options = raw.translate(table).split(' ') + + return options + +with open(src_file,'r') as file: + for line in file: + matches = re.match(pattern, line) + if matches is not None: + # print(matches.groupdict()) + uri = matches['uri'] + + options = {} + if matches.group('options'): + for option in split_options(matches['options']): + if "=" in option: + key, value = option.split("=") + options[key] = value + + if uri in sources: + sources[uri]["Types"].add(matches["type"]) + sources[uri]["URIs"] = matches["uri"] + sources[uri]["Suites"].add(matches["suite"]) + sources[uri]["Components"].update(matches["components"].split(' ')) + else: + source = { + "Types": {matches['type']}, + "URIs": matches['uri'], + "Enabled": "yes", + } + + if matches.group('suite'): + source["Suites"] = set(matches['suite'].split(' ')) + + if matches.group('components'): + source["Components"] = set(matches['components'].split(' ')) + + if "arch" in options: + if "Architectures" in source: + source["Architectures"].append(options["arch"]) + else: + source["Architectures"] = {options["arch"]} + + if "signed-by" in options: + if "Signed-by" in source: + source["Signed-by"].append(options["signed-by"]) + else: + source["Signed-by"] = {options["signed-by"]} + + if "lang" in options: + if "Languages" in source: + source["Languages"].append(options["lang"]) + else: + source["Languages"] = {options["lang"]} + + if "target" in options: + if "Targets" in source: + source["Targets"].append(options["target"]) + else: + source["Targets"] = {options["target"]} + + sources[uri] = source + +for i, (uri, source) in enumerate(sources.items()): + if i > 0: + print("") + for key, value in source.items(): + if isinstance(value, str): + print("{}: {}".format(key, value) ) + else: + print("{}: {}".format(key, ' '.join(value)) ) + i += 1 \ No newline at end of file diff --git a/apt/files/deb822-migration.sh b/apt/files/deb822-migration.sh new file mode 100644 index 00000000..cffa2f95 --- /dev/null +++ b/apt/files/deb822-migration.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +deb822_migrate_script=$(command -v deb822-migration.py) + +if [ -z "${deb822_migrate_script}" ]; then + deb822_migrate_script="./deb822-migration.py" +fi +if [ ! -x "${deb822_migrate_script}" ]; then + >&2 echo "ERROR: '${deb822_migrate_script}' not found or not executable" + exit 1 +fi + +dest_dir="/etc/apt/sources.list.d" +rc=0 + +migrate_file() { + legacy_file=$1 + deb822_file=$2 + + if [ -f "${legacy_file}" ]; then + if [ -f "${deb822_file}" ]; then + >&2 echo "ERROR: '${deb822_file}' already exists" + rc=2 + else + ${deb822_migrate_script} "${legacy_file}" > "${deb822_file}" + if [ $? -eq 0 ] && [ -f "${deb822_file}" ]; then + mv "${legacy_file}" "${legacy_file}.bak" + echo "Migrated ${legacy_file} to ${deb822_file} and renamed to ${legacy_file}.bak" + else + >&2 echo "ERROR: failed to convert '${legacy_file}' to '${deb822_file}'" + rc=2 + fi + fi + else + >&2 echo "ERROR: '${legacy_file}' not found" + rc=2 + fi +} + +migrate_file "/etc/apt/sources.list" "${dest_dir}/system.sources" + +# shellcheck disable=SC2044 +for legacy_file in $(find /etc/apt/sources.list.d -mindepth 1 -maxdepth 1 -type f -name '*.list'); do + deb822_file=$(basename "${legacy_file}" .list) + migrate_file "${legacy_file}" "${dest_dir}/${deb822_file}.sources" +done + +exit ${rc} \ No newline at end of file diff --git a/apt/files/move-apt-keyrings.sh b/apt/files/move-apt-keyrings.sh new file mode 100644 index 00000000..2d266412 --- /dev/null +++ b/apt/files/move-apt-keyrings.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# Move apt repository key from /etc/apt/trusted.gpg.d/ to /etc/apt/keyrings/ and add "signed-by" tag in source list +# +# Example: move-apt-keyrings.sh http://repo.mongodb.org/apt/debian mongodb-server-[0-9\\.]+.asc + +repository_pattern=$1 +key=$2 + +found_files=$(grep --files-with-matches --recursive --extended-regexp "${repository_pattern}" "/etc/apt/sources.list.d/*.list") + +old_key_file="/etc/apt/trusted.gpg.d/${key}" +new_key_file="/etc/apt/keyrings/${key}" + +for file in ${found_files}; do + if ! grep --quiet "signed-by" "${file}"; then + signed_by="signed-by=${new_key_file}" + if grep --quiet "deb(-src)? \[" "${file}"; then + sed -i "s@deb\(-src\)\? \[\([^]]\+\)\]@deb\1 [\2 ${signed_by}]@" "${file}" + else + sed -i "s@deb\(-src\)\? @deb\1 [${signed_by}] @" "${file}" + fi + fi +done + +if [ -f "${old_key_file}" ] && [ ! -f "${new_key_file}" ]; then + mv "${old_key_file}" "${new_key_file}" +fi +if [ -f "${new_key_file}" ]; then + chmod 644 "${new_key_file}" + chown root: "${new_key_file}" +fi diff --git a/apt/files/pub_evolix.asc b/apt/files/pub_evolix.asc new file mode 100644 index 00000000..4a21bdfe --- /dev/null +++ b/apt/files/pub_evolix.asc @@ -0,0 +1,87 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +oA9QflpnDubMnCve +=ZCml +-----END PGP PUBLIC KEY BLOCK----- diff --git a/apt/tasks/evolix_public.yml b/apt/tasks/evolix_public.yml index 21062a32..8c4d5216 100644 --- a/apt/tasks/evolix_public.yml +++ b/apt/tasks/evolix_public.yml @@ -18,8 +18,8 @@ - name: Add Evolix GPG key copy: - src: reg.asc - dest: "{{ apt_keyring_dir }}/reg.asc" + src: pub_evolix.asc + dest: "{{ apt_keyring_dir }}/pub_evolix.asc" force: yes mode: "0644" owner: root diff --git a/apt/tasks/hold_packages.yml b/apt/tasks/hold_packages.yml index 691f3763..10f5b358 100644 --- a/apt/tasks/hold_packages.yml +++ b/apt/tasks/hold_packages.yml @@ -1,5 +1,8 @@ --- +- include_role: + name: evolix/remount-usr + - name: "hold packages (apt)" shell: "set -o pipefail && (dpkg -l {{ item }} 2>/dev/null | grep -q -E '^(i|h)i') && ((apt-mark showhold | grep --quiet {{ item }}) || apt-mark hold {{ item }})" args: @@ -76,8 +79,8 @@ - name: Check if Cron is installed shell: "dpkg --list 'cron' 2>/dev/null | grep -q -E '^(i|h)i'" register: is_cron - changed_when: false - failed_when: false + changed_when: False + failed_when: False check_mode: no tags: - apt diff --git a/apt/tasks/migrate-to-deb822.yml b/apt/tasks/migrate-to-deb822.yml new file mode 100644 index 00000000..642bcb4f --- /dev/null +++ b/apt/tasks/migrate-to-deb822.yml @@ -0,0 +1,31 @@ +--- +- include_role: + name: evolix/remount-usr + +- name: /usr/share/scripts exists + file: + dest: /usr/share/scripts + mode: "0700" + owner: root + group: root + state: directory + tags: + - apt + +- name: Migration scripts are installed + copy: + src: "{{ item }}" + dest: "/usr/share/scripts/{{ item }}" + force: yes + mode: "0755" + loop: + - deb822-migration.py + - deb822-migration.sh + tags: + - apt + +- name: Exec migration script + command: /usr/share/scripts/deb822-migration.sh + ignore_errors: yes + tags: + - apt \ No newline at end of file diff --git a/apt/tasks/move-apt-keyring.yml b/apt/tasks/move-apt-keyring.yml new file mode 100644 index 00000000..4214d2d6 --- /dev/null +++ b/apt/tasks/move-apt-keyring.yml @@ -0,0 +1,52 @@ +--- + +- name: New APT keyrings directory is present + file: + path: /etc/apt/keyrings + state: directory + mode: "0755" + owner: root + group: root + +- include_role: + name: evolix/remount-usr + +- name: /usr/share/scripts exists + file: + dest: /usr/share/scripts + mode: "0700" + owner: root + group: root + state: directory + tags: + - apt + +- name: migration script is present + copy: + src: move-apt-keyrings.sh + dest: /usr/share/scripts/move-apt-keyrings.sh + mode: "0755" + owner: root + group: root + +- name: Move repository signing key + command: "/usr/share/scripts/move-apt-keyrings.sh \"{{ item.repository_pattern }}\" \"{{ item.key }}\"" + loop: + - { repository_pattern: "http://pub.evolix.net/", key: "reg.asc" } + - { repository_pattern: "http://pub.evolix.org/evolix", key: "pub_evolix.asc" } + - { repository_pattern: "https://pub.evolix.org/evolix", key: "pub_evolix.asc" } + - { repository_pattern: "https://artifacts.elastic.co/packages/[^/]+/apt", key: "elastics.asc" } + - { repository_pattern: "https://download.docker.com/linux/debian", key: "docker-debian.asc" } + - { repository_pattern: "https://downloads.linux.hpe.com/SDR/repo/mcp", key: "hpePublicKey2048_key1.asc" } + - { repository_pattern: "http://pkg.jenkins-ci.org/debian-stable", key: "jenkins.asc" } + - { repository_pattern: "https://packages.sury.org/php/", key: "sury.gpg" } + - { repository_pattern: "http://repo.mongodb.org/apt/debian", key: "mongodb-server-[0-9\\.]+.asc" } + - { repository_pattern: "http://apt.newrelic.com/debian/", key: "newrelic.asc" } + - { repository_pattern: "https://deb.nodesource.com/", key: "nodesource.asc" } + - { repository_pattern: "https://dl.yarnpkg.com/debian/", key: "yarn.asc" } + - { repository_pattern: "http://apt.postgresql.org/pub/repos/apt/", key: "postgresql.asc" } + register: _cmd + +- name: Debug command + debug: + var: _cmd diff --git a/apt/templates/evolix_public.list.j2 b/apt/templates/evolix_public.list.j2 index e0bc0de7..e00899e7 100644 --- a/apt/templates/evolix_public.list.j2 +++ b/apt/templates/evolix_public.list.j2 @@ -1,7 +1,3 @@ # {{ ansible_managed }} -{% if ansible_distribution_release == "bookworm" %} -deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ bullseye/ -{% else %} -deb [signed-by={{ apt_keyring_dir }}/reg.asc] http://pub.evolix.net/ {{ ansible_distribution_release }}/ -{% endif %} \ No newline at end of file +deb [signed-by={{ apt_keyring_dir }}/pub_evolix.asc] http://pub.evolix.org/evolix {{ ansible_distribution_release }} main diff --git a/bind/defaults/main.yml b/bind/defaults/main.yml index 99b33e13..c34490f8 100644 --- a/bind/defaults/main.yml +++ b/bind/defaults/main.yml @@ -8,4 +8,5 @@ bind_systemd_service_path: /etc/systemd/system/bind9.service bind_statistics_file: /var/run/named.stats bind_log_file: /var/log/bind.log bind_query_file: /var/log/bind_queries.log +bind_query_file_enabled: False bind_cache_dir: /var/cache/bind diff --git a/bind/handlers/main.yml b/bind/handlers/main.yml index 8bb61a21..b426fcd1 100644 --- a/bind/handlers/main.yml +++ b/bind/handlers/main.yml @@ -1,19 +1,21 @@ --- - name: reload systemd - command: systemctl daemon-reload + systemd: + daemon-reload: yes + - name: restart apparmor - service: + systemd: name: apparmor state: restarted - name: restart bind - service: + systemd: name: bind9 state: restarted - name: restart munin-node - service: + systemd: name: munin-node state: restarted diff --git a/bind/tasks/authoritative.yml b/bind/tasks/authoritative.yml new file mode 100644 index 00000000..52992fa1 --- /dev/null +++ b/bind/tasks/authoritative.yml @@ -0,0 +1,11 @@ +--- + +- name: Set bind configuration for authoritative server + template: + src: named.conf.options_authoritative.j2 + dest: /etc/bind/named.conf.options + owner: bind + group: bind + mode: "0644" + force: yes + notify: restart bind \ No newline at end of file diff --git a/bind/tasks/main.yml b/bind/tasks/main.yml index d1348cd2..9b053b6c 100644 --- a/bind/tasks/main.yml +++ b/bind/tasks/main.yml @@ -1,22 +1,30 @@ # Until chroot-bind.sh is migrated to ansible, we hardcode the chroot paths. - name: set chroot variables set_fact: - bind_log_file: /var/log/bind.log - bind_query_file: /var/log/bind_queries.log - bind_cache_dir: /var/cache/bind - bind_statistics_file: /var/run/named.stats - bind_chroot_path: /var/chroot-bind + bind_log_file: /var/log/bind.log + bind_query_file: /var/log/bind_queries.log + bind_cache_dir: /var/cache/bind + bind_statistics_file: /var/run/named.stats + bind_chroot_path: /var/chroot-bind when: bind_chroot_set | bool +- name: Check AppArmor + shell: systemctl is-active apparmor || systemctl is-enabled apparmor + failed_when: False + changed_when: False + check_mode: no + register: check_apparmor + - name: configure apparmor template: src: apparmor.usr.sbin.named.j2 dest: /etc/apparmor.d/usr.sbin.named owner: root group: root - mode: '0644' + mode: "0644" force: yes notify: restart apparmor + when: check_apparmor.rc == 0 - name: package are installed apt: @@ -25,47 +33,23 @@ - dnstop state: present -- name: Set bind configuration for recursive server - template: - src: named.conf.options_recursive.j2 - dest: /etc/bind/named.conf.options - owner: bind - group: bind - mode: "0644" - force: yes - notify: restart bind - when: bind_recursive_server | bool - -- name: enable zones.rfc1918 for recursive server - lineinfile: - dest: /etc/bind/named.conf.local - line: 'include "/etc/bind/zones.rfc1918";' - regexp: "zones.rfc1918" - notify: restart bind - when: bind_recursive_server | bool - -- name: Set bind configuration for authoritative server - template: - src: named.conf.options_authoritative.j2 - dest: /etc/bind/named.conf.options - owner: bind - group: bind - mode: "0644" - force: yes - notify: restart bind +- include: authoritative.yml when: bind_authoritative_server | bool -- name: Create systemd service +- include: recursive.yml + when: bind_recursive_server | bool + +- name: Create systemd service for Debian 8 (Jessie) template: - src: bind9.service.j2 + src: bind9.service.jessie.j2 dest: "{{ bind_systemd_service_path }}" owner: root group: root mode: "0644" force: yes notify: - - reload systemd - - restart bind + - reload systemd + - restart bind when: ansible_distribution_release == "jessie" - name: "touch {{ bind_log_file }} if non chroot" diff --git a/bind/tasks/munin.yml b/bind/tasks/munin.yml index f97ddf85..7bedfd2c 100644 --- a/bind/tasks/munin.yml +++ b/bind/tasks/munin.yml @@ -19,7 +19,7 @@ - bind9_rndc notify: restart munin-node when: - - bind_authoritative_server + - bind_authoritative_server | bool - munin_node_plugins_config.stat.exists tags: - bind @@ -32,10 +32,10 @@ state: link loop: - bind9 - - bind9_rndc notify: restart munin-node when: - - bind_recursive_server + - bind_recursive_server | bool + - bind_query_file_enabled | bool - munin_node_plugins_config.stat.exists tags: - bind diff --git a/bind/tasks/recursive.yml b/bind/tasks/recursive.yml new file mode 100644 index 00000000..ddbeafbf --- /dev/null +++ b/bind/tasks/recursive.yml @@ -0,0 +1,19 @@ +--- + + +- name: Set bind configuration for recursive server + template: + src: named.conf.options_recursive.j2 + dest: /etc/bind/named.conf.options + owner: bind + group: bind + mode: "0644" + force: yes + notify: restart bind + +- name: enable zones.rfc1918 for recursive server + lineinfile: + dest: /etc/bind/named.conf.local + line: 'include "/etc/bind/zones.rfc1918";' + regexp: "zones.rfc1918" + notify: restart bind diff --git a/bind/templates/apparmor.usr.sbin.named.j2 b/bind/templates/apparmor.usr.sbin.named.j2 index 9a554437..d9f0be04 100644 --- a/bind/templates/apparmor.usr.sbin.named.j2 +++ b/bind/templates/apparmor.usr.sbin.named.j2 @@ -56,7 +56,9 @@ # some people like to put logs in /var/log/named/ instead of having # syslog do the heavy lifting. {{ bind_log_file }} rw, +{% if bind_query_file_enabled | bool %} {{ bind_query_file }} rw, +{% endif %} # gssapi /var/lib/sss/pubconf/krb5.include.d/** r, diff --git a/bind/templates/bind9.service.j2 b/bind/templates/bind9.service.jessie.j2 similarity index 100% rename from bind/templates/bind9.service.j2 rename to bind/templates/bind9.service.jessie.j2 diff --git a/bind/templates/logrotate_bind.j2 b/bind/templates/logrotate_bind.j2 index 3fe1589e..c7ec3c30 100644 --- a/bind/templates/logrotate_bind.j2 +++ b/bind/templates/logrotate_bind.j2 @@ -1,7 +1,7 @@ -{% if bind_chroot_set %} -{{ bind_chroot_path }}{{bind_log_file}} { +{% if bind_chroot_set | bool %} +{{ bind_chroot_path }}{{ bind_log_file }} { {% else %} -{{bind_log_file}} { +{{ bind_log_file }} { {% endif %} weekly missingok diff --git a/bind/templates/munin-env_bind9.j2 b/bind/templates/munin-env_bind9.j2 index de88b27a..2af70548 100644 --- a/bind/templates/munin-env_bind9.j2 +++ b/bind/templates/munin-env_bind9.j2 @@ -1,9 +1,17 @@ [bind*] user root -env.logfile {% if bind_chroot_set %}{{ bind_chroot_path }}{% endif %}{{ bind_query_file }} +{% if bind_query_file_enabled | bool %} +{% if bind_chroot_set | bool %} +env.logfile {{ bind_chroot_path }}{{ bind_query_file }} +{% else %} +env.logfile {{ bind_query_file }} +{% endif %} +{% endif %} + {% if bind_authoritative_server %} env.querystats {% if bind_chroot_set %}{{ bind_chroot_path }}{% endif %}{{ bind_statistics_file }} {% endif %} + env.MUNIN_PLUGSTATE /var/lib/munin timeout 120 diff --git a/bind/templates/named.conf.options_authoritative.j2 b/bind/templates/named.conf.options_authoritative.j2 index 8f48cbb5..4b6065b6 100644 --- a/bind/templates/named.conf.options_authoritative.j2 +++ b/bind/templates/named.conf.options_authoritative.j2 @@ -1,7 +1,7 @@ -acl "foo" { - ::ffff:192.0.2.21; 192.0.2.21; - 2001:db8::21; -}; +// acl "foo" { +// ::ffff:192.0.2.21; 192.0.2.21; +// 2001:db8::21; +// }; options { directory "{{ bind_cache_dir }}"; @@ -20,16 +20,20 @@ options { logging { category default { default_file; }; +{% if bind_query_file_enabled | bool %} category queries { query_logging; }; +{% endif %} channel default_file { file "{{ bind_log_file }}"; severity info; }; +{% if bind_query_file_enabled | bool %} channel query_logging { file "{{ bind_query_file }}" versions 2 size 128M; print-category yes; print-severity yes; print-time yes; }; +{% endif %} }; diff --git a/bind/templates/named.conf.options_recursive.j2 b/bind/templates/named.conf.options_recursive.j2 index 27246d13..931ac71d 100644 --- a/bind/templates/named.conf.options_recursive.j2 +++ b/bind/templates/named.conf.options_recursive.j2 @@ -9,16 +9,20 @@ options { logging { category default { default_file; }; +{% if bind_query_file_enabled | bool %} category queries { query_logging; }; +{% endif %} channel default_file { file "{{ bind_log_file }}"; severity info; }; +{% if bind_query_file_enabled | bool %} channel query_logging { file "{{ bind_query_file }}" versions 2 size 128M; print-category yes; print-severity yes; print-time yes; }; +{% endif %} }; diff --git a/clamav/tasks/main.yml b/clamav/tasks/main.yml index 6d1da3eb..f74efae5 100644 --- a/clamav/tasks/main.yml +++ b/clamav/tasks/main.yml @@ -13,7 +13,7 @@ - { 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/MaxConnectionQueueLength', type: 'string', value: '200' } - { key: 'clamav-daemon/LogRotate', type: 'boolean', value: 'true' } - { key: 'clamav-daemon/AllowAllMatchScan', type: 'boolean', value: 'true' } - { key: 'clamav-daemon/ScanOnAccess', type: 'boolean', value: 'false' } diff --git a/docker-host/defaults/main.yml b/docker-host/defaults/main.yml index 44496203..42c9cecc 100644 --- a/docker-host/defaults/main.yml +++ b/docker-host/defaults/main.yml @@ -1,7 +1,7 @@ --- # If docher_home sets to /home/, the partition should be mounted with exec option. docker_home: /var/lib/docker -docker_tmpdir: "{{docker_home}}/tmp" +docker_tmpdir: "{{ docker_home }}/tmp" # Chose to use iptables instead of docker-proxy userland process docker_conf_use_iptables: False @@ -20,9 +20,9 @@ docker_remote_access_enabled: False docker_daemon_port: 2376 docker_daemon_listening_ip: 0.0.0.0 -# TLS +# TLS docker_tls_enabled: False -docker_tls_path: "{{docker_home}}/tls" +docker_tls_path: "{{ docker_home }}/tls" docker_tls_ca: ca/ca.pem docker_tls_ca_key: ca/ca-key.pem docker_tls_cert: server/cert.pem diff --git a/docker-host/handlers/main.yml b/docker-host/handlers/main.yml index 8b484b49..c21a84ef 100644 --- a/docker-host/handlers/main.yml +++ b/docker-host/handlers/main.yml @@ -1,6 +1,7 @@ --- - name: reload systemd - command: systemctl daemon-reload + systemd: + daemon-reload: yes - name: restart docker service: diff --git a/docker-host/templates/daemon.json.j2 b/docker-host/templates/daemon.json.j2 index 08dcb1b2..a044234b 100644 --- a/docker-host/templates/daemon.json.j2 +++ b/docker-host/templates/daemon.json.j2 @@ -1,40 +1,30 @@ { - "debug": false, - + "debug": false {# Docker data-dir (default to /var/lib/docker) #} - "data-root": "{{ docker_home }}", - + ,"data-root": "{{ docker_home }}" {# Keep containers running while docker daemon downtime #} - "live-restore": {{ docker_conf_live_restore | to_json }},, - + ,"live-restore": {{ docker_conf_live_restore | to_json }} {# Turn on user namespace remaping #} - "userns-remap": "default", - - {% if docker_conf_use_iptables %} + ,"userns-remap": "default" +{% if docker_conf_use_iptables %} {# Use iptables instead of docker-proxy #} - "userland-proxy": false, - "iptables": true, - {% endif %} - + ,"userland-proxy": false + ,"iptables": true +{% endif %} {# Disable the possibility for containers processes to gain new privileges #} - "no-new-privileges": {{ docker_conf_no_newprivileges | to_json }}, - - {% if docker_conf_disable_default_networking %} + ,"no-new-privileges": {{ docker_conf_no_newprivileges | to_json }} +{% if docker_conf_disable_default_networking %} {# Disable all default network connectivity #} - "bridge": "none", - "icc": false, - {% endif %} - - {% if docker_tls_enabled %} - "tls": true, - "tlscert": "{{ docker_tls_path }}/{{ docker_tls_cert }}", - "tlscacert": "{{ docker_tls_path }}/{{ docker_tls_ca }}", - "tlskey": "{{ docker_tls_path }}/{{ docker_tls_key }}", - {% endif %} - - {% if docker_remote_access_enabled %} - "hosts": ["tcp://{{ docker_daemon_listening_ip }}:{{ docker_daemon_port }}", "fd://"] - {% else %} - "hosts": ["fd://"] - {% endif %} + ,"bridge": "none" + ,"icc": false +{% endif %} +{% if docker_tls_enabled %} + ,"tls": true + ,"tlscert": "{{ docker_tls_path }}/{{ docker_tls_cert }}" + ,"tlscacert": "{{ docker_tls_path }}/{{ docker_tls_ca }}" + ,"tlskey": "{{ docker_tls_path }}/{{ docker_tls_key }}" +{% endif %} +{% if docker_remote_access_enabled %} + ,"hosts": ["tcp://{{ docker_daemon_listening_ip }}:{{ docker_daemon_port }}", "fd://"] +{% endif %} } diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml index c9de6045..dddd951c 100644 --- a/dovecot/tasks/main.yml +++ b/dovecot/tasks/main.yml @@ -87,7 +87,7 @@ name: log2mail state: present tags: dovecot - + - name: dovecot is configured in log2mail blockinfile: path: /etc/log2mail/config/mail.conf diff --git a/elasticsearch/tasks/additional_scripts.yml b/elasticsearch/tasks/additional_scripts.yml index 19e43535..e8373ef8 100644 --- a/elasticsearch/tasks/additional_scripts.yml +++ b/elasticsearch/tasks/additional_scripts.yml @@ -2,7 +2,7 @@ - include_role: name: evolix/remount-usr - when: elasticsearch_additional_scripts_dir is search ("/usr") + when: elasticsearch_additional_scripts_dir is search("/usr") - name: "{{ elasticsearch_additional_scripts_dir }} exists" file: diff --git a/elasticsearch/tasks/configuration.yml b/elasticsearch/tasks/configuration.yml index 99c311c2..7324f610 100644 --- a/elasticsearch/tasks/configuration.yml +++ b/elasticsearch/tasks/configuration.yml @@ -118,6 +118,17 @@ tags: - config +- name: Disable garbage collector logs (JDK >= 9) + lineinfile: + dest: /etc/elasticsearch/jvm.options + regexp: "Xlog:gc" + line: "#9-:-Xlog:gc*,gc+age=trace,safepoint:file=/opt/my-app/gc.log:utctime,pid,tags:filecount=32,filesize=64m" + owner: root + group: elasticsearch + mode: "0640" + tags: + - config + - name: Configure cluster members lineinfile: dest: /etc/elasticsearch/elasticsearch.yml diff --git a/elasticsearch/tasks/datadir.yml b/elasticsearch/tasks/datadir.yml index c0c20f05..ef91cf1d 100644 --- a/elasticsearch/tasks/datadir.yml +++ b/elasticsearch/tasks/datadir.yml @@ -10,7 +10,7 @@ - name: "read the real datadir" command: readlink -f /var/lib/elasticsearch - changed_when: false + changed_when: False register: elasticsearch_current_real_datadir_test check_mode: no tags: diff --git a/elasticsearch/tasks/logs.yml b/elasticsearch/tasks/logs.yml index 01829dc9..8c5977a4 100644 --- a/elasticsearch/tasks/logs.yml +++ b/elasticsearch/tasks/logs.yml @@ -17,3 +17,4 @@ group: root mode: "0750" when: is_cron_installed.rc == 0 + diff --git a/elasticsearch/templates/rotate_elasticsearch_logs.j2 b/elasticsearch/templates/rotate_elasticsearch_logs.j2 index 849a9ca1..981ca433 100644 --- a/elasticsearch/templates/rotate_elasticsearch_logs.j2 +++ b/elasticsearch/templates/rotate_elasticsearch_logs.j2 @@ -8,7 +8,6 @@ MAX_AGE={{ elasticsearch_log_rotate_days | mandatory }} # Compress logs find ${LOG_DIR} -type f -user ${USER} -name "*.log.????-??-??" -exec gzip --best {} \; find ${LOG_DIR} -type f -user ${USER} -name "*-????-??-??.log" -exec gzip --best {} \; -find ${LOG_DIR} -type f -user ${USER} -name "*.log.??" -not -name "*.gz" -exec gzip --best {} \; # Delete old logs -find ${LOG_DIR} -type f -user ${USER} -name "*gz" -ctime +${MAX_AGE} -delete \ No newline at end of file +find ${LOG_DIR} -type f -user ${USER} -name "*gz" -ctime +${MAX_AGE} -delete diff --git a/etc-git/tasks/main.yml b/etc-git/tasks/main.yml index f71ba552..ac28e1e7 100644 --- a/etc-git/tasks/main.yml +++ b/etc-git/tasks/main.yml @@ -6,7 +6,7 @@ state: present tags: - etc-git - when: + when: - ansible_distribution == "Debian" - name: Install and configure utilities diff --git a/etc-git/tasks/repository.yml b/etc-git/tasks/repository.yml index 80987da2..7ebfc773 100644 --- a/etc-git/tasks/repository.yml +++ b/etc-git/tasks/repository.yml @@ -2,14 +2,13 @@ - include_role: name: evolix/remount-usr - when: repository_path is search ("/usr") + when: repository_path is search("/usr") - name: "{{ repository_path }} is versioned with git" command: "git init ." args: chdir: "{{ repository_path }}" creates: "{{ repository_path }}/.git/" - warn: no register: git_init tags: - etc-git @@ -54,7 +53,6 @@ command: "git log" args: chdir: "{{ repository_path }}" - warn: no changed_when: False failed_when: False register: git_log @@ -66,7 +64,6 @@ shell: "git add -A . && git commit -m \"Initial commit via Ansible\"" args: chdir: "{{ repository_path }}" - warn: no register: git_commit when: git_log.rc != 0 or (git_init is defined and git_init is changed) tags: diff --git a/etc-git/tasks/utils.yml b/etc-git/tasks/utils.yml index cd060de1..831f62a6 100644 --- a/etc-git/tasks/utils.yml +++ b/etc-git/tasks/utils.yml @@ -51,7 +51,7 @@ register: is_cron_installed - block: - - name: Legacy cron jobs for /etc/.git status are absent + - name: Legacy cron jobs for /etc/.git status are absent file: dest: "{{ item }}" state: absent diff --git a/evoacme/templates/evoacme.conf.j2 b/evoacme/templates/evoacme.conf.j2 index 27405f56..eae3ff45 100644 --- a/evoacme/templates/evoacme.conf.j2 +++ b/evoacme/templates/evoacme.conf.j2 @@ -1,9 +1,9 @@ ### File generated by Ansible ### -SSL_KEY_DIR=${SSL_KEY_DIR:-{{ evoacme_ssl_key_dir }}} -ACME_DIR=${ACME_DIR:-{{ evoacme_acme_dir }}} -CSR_DIR=${CSR_DIR:-{{ evoacme_csr_dir }}} -CRT_DIR=${CRT_DIR:-{{ evoacme_crt_dir }}} +SSL_KEY_DIR=${SSL_KEY_DIR:-{{ evoacme_ssl_key_dir }} } +ACME_DIR=${ACME_DIR:-{{ evoacme_acme_dir }} } +CSR_DIR=${CSR_DIR:-{{ evoacme_csr_dir }} } +CRT_DIR=${CRT_DIR:-{{ evoacme_crt_dir }} } HOOKS_DIR=${HOOKS_DIR:-"{{ evoacme_hooks_dir }}"} -LOG_DIR=${LOG_DIR:-{{ evoacme_log_dir }}} -SSL_MINDAY=${SSL_MINDAY:-{{ evoacme_ssl_minday }}} +LOG_DIR=${LOG_DIR:-{{ evoacme_log_dir }} } +SSL_MINDAY=${SSL_MINDAY:-{{ evoacme_ssl_minday }} } diff --git a/evocheck/files/evocheck.cf b/evocheck/files/evocheck.cf index 9eca204e..983363f9 100644 --- a/evocheck/files/evocheck.cf +++ b/evocheck/files/evocheck.cf @@ -1,5 +1,3 @@ -# Managed by Ansible -# # Configuration for evocheck # Use this file to change configuration values defined in evocheck.sh # Ex : IS_TMP_1777=0 diff --git a/evocheck/files/evocheck.jessie.sh b/evocheck/files/evocheck.jessie.sh index a5a32a5a..5d1a186e 100755 --- a/evocheck/files/evocheck.jessie.sh +++ b/evocheck/files/evocheck.jessie.sh @@ -4,7 +4,7 @@ # Script to verify compliance of a Linux (Debian) server # powered by Evolix -VERSION="22.11" +VERSION="23.03.01" readonly VERSION # base functions diff --git a/evocheck/files/evocheck.sh b/evocheck/files/evocheck.sh old mode 100644 new mode 100755 index c5cd8fbd..647192cc --- a/evocheck/files/evocheck.sh +++ b/evocheck/files/evocheck.sh @@ -4,7 +4,7 @@ # Script to verify compliance of a Linux (Debian) server # powered by Evolix -VERSION="22.11" +VERSION="23.03.01" readonly VERSION # base functions @@ -100,6 +100,17 @@ is_installed(){ # logging +log() { + date=$(/bin/date +"${DATE_FORMAT}") + if [ "${1}" != '' ]; then + printf "[%s] %s: %s\\n" "$date" "${PROGNAME}" "${1}" >> "${LOGFILE}" + else + while read line; do + printf "[%s] %s: %s\\n" "$date" "${PROGNAME}" "${line}" >> "${LOGFILE}" + done < /dev/stdin + fi +} + failed() { check_name=$1 shift @@ -113,6 +124,9 @@ failed() { printf "%s FAILED!\n" "${check_name}" >> "${main_output_file}" fi fi + + # Always log verbose + log "${check_name} FAILED! ${check_comments}" } # check functions @@ -131,6 +145,13 @@ check_dpkgwarning() { test -e /etc/apt/apt.conf.d/z-evolinux.conf \ || failed "IS_DPKGWARNING" "/etc/apt/apt.conf.d/z-evolinux.conf is missing" } +# Check if localhost, localhost.localdomain and localhost.$mydomain are set in Postfix mydestination option. +check_localhost_in_postfix_mydestination() { + # shellcheck disable=SC2016 + if ! grep mydestination /etc/postfix/main.cf | grep --quiet --extended-regexp '(localhost[^\\.]|localhost.localdomain|localhost.$mydomain)'; then + failed "IS_LOCALHOST_IN_POSTFIX_MYDESTINATION" "'localhost' and/or 'localhost.localdomain' and/or 'localhost.\$mydomain' are missing in Postfix mydestination option. Consider adding then." + fi +} # Verifying check_mailq in Nagios NRPE config file. (Option "-M postfix" need to be set if the MTA is Postfix) check_nrpepostfix() { if is_installed postfix; then @@ -391,7 +412,7 @@ check_log2mailrunning() { fi } check_log2mailapache() { - conf=/etc/log2mail/config/Apache + conf=/etc/log2mail/config/apache if is_pack_web && is_installed log2mail; then grep -s -q "^file = /var/log/apache2/error.log" $conf \ || failed "IS_LOG2MAILAPACHE" "missing log2mail directive for apache" @@ -463,18 +484,26 @@ check_evobackup() { evobackup_found=$(find /etc/cron* -name '*evobackup*' | wc -l) test "$evobackup_found" -gt 0 || failed "IS_EVOBACKUP" "missing evobackup cron" } -# Vérification de la mise en place de la purge pour fail2ban -check_purge_fail2ban() { +# Vérification de la mise en place d'un cron de purge de la base SQLite de Fail2ban +check_fail2ban_purge() { if is_debian_stretch || is_debian_buster; then if is_installed fail2ban; then test -f /etc/cron.daily/fail2ban_dbpurge || failed "IS_FAIL2BAN_PURGE" "missing script fail2ban_dbpurge cron" fi fi } +# Vérification qu'il ne reste pas des jails nommées ssh non renommées en sshd +check_ssh_fail2ban_jail_renamed() { + if is_installed fail2ban && [ -f /etc/fail2ban/jail.local ]; then + if grep --quiet --fixed-strings "[ssh]" /etc/fail2ban/jail.local; then + failed "IS_SSH_FAIL2BAN_JAIL_RENAMED" "Jail ssh must be renamed sshd in fail2ban >= 0.9." + fi + fi +} # Vérification de l'exclusion des montages (NFS) dans les sauvegardes check_evobackup_exclude_mount() { - excludes_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.evobackup_exclude_mount.XXXXX") - files_to_cleanup="${files_to_cleanup} ${excludes_file}" + excludes_file=$(mktemp --tmpdir "evocheck.evobackup_exclude_mount.XXXXX") + files_to_cleanup+=("${excludes_file}") # shellcheck disable=SC2044 for evobackup_file in $(find /etc/cron* -name '*evobackup*' | grep -v -E ".disabled$"); do @@ -643,7 +672,7 @@ check_notupgraded() { fi done if $upgraded; then - last_upgrade=$(date +%s -d "$(zgrep -h upgrade /var/log/dpkg.log* | sort -n | tail -1 | cut -f1 -d ' ')") + last_upgrade=$(date +%s -d "$(zgrep --no-filename --no-messages upgrade /var/log/dpkg.log* | sort -n | tail -1 | cut -f1 -d ' ')") fi if grep -qs '^mailto="listupgrade-todo@' /etc/evolinux/listupgrade.cnf \ || grep -qs -E '^[[:digit:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[^\*]' /etc/cron.d/listupgrade; then @@ -841,10 +870,17 @@ check_redis_backup() { # You could change the default path in /etc/evocheck.cf # REDIS_BACKUP_PATH may contain space-separated paths, example: # REDIS_BACKUP_PATH='/home/backup/redis-instance1/dump.rdb /home/backup/redis-instance2/dump.rdb' - REDIS_BACKUP_PATH=${REDIS_BACKUP_PATH:-"/home/backup/redis/dump.rdb"} - for file in ${REDIS_BACKUP_PATH}; do - test -f "${file}" || failed "IS_REDIS_BACKUP" "Redis dump is missing (${file})" - done + # Old default path: /home/backup/dump.rdb + # New default path: /home/backup/redis/dump.rdb + if [ -z "${REDIS_BACKUP_PATH}" ]; then + if ! [ -f "/home/backup/dump.rdb" ] && ! [ -f "/home/backup/redis/dump.rdb" ]; then + failed "IS_REDIS_BACKUP" "Redis dump is missing (/home/backup/dump.rdb or /home/backup/redis/dump.rdb)." + fi + else + for file in ${REDIS_BACKUP_PATH}; do + test -f "${file}" || failed "IS_REDIS_BACKUP" "Redis dump ${file} is missing." + done + fi fi } check_elastic_backup() { @@ -895,15 +931,15 @@ check_mysqlnrpe() { grep -q -F "command[check_mysql]=/usr/lib/nagios/plugins/check_mysql" /etc/nagios/nrpe.d/evolix.cfg \ || failed "IS_MYSQLNRPE" "check_mysql is missing" fi - fi + fi } check_phpevolinuxconf() { 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 + { test -f "/etc/php/${phpVersion}/cli/conf.d/z-evolinux-defaults.ini" \ + && test -f "/etc/php/${phpVersion}/cli/conf.d/zzz-evolinux-custom.ini" } || failed "IS_PHPEVOLINUXCONF" "missing php evolinux config" fi } @@ -929,8 +965,8 @@ check_duplicate_fs_label() { # Do it only if thereis blkid binary BLKID_BIN=$(command -v blkid) if [ -n "$BLKID_BIN" ]; then - tmpFile=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.duplicate_fs_label.XXXXX") - files_to_cleanup="${files_to_cleanup} ${tmpFile}" + tmpFile=$(mktemp --tmpdir "evocheck.duplicate_fs_label.XXXXX") + files_to_cleanup+=("${tmpFile}") parts=$($BLKID_BIN -c /dev/null | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2) for part in $parts; do @@ -1097,8 +1133,8 @@ check_evobackup_incs() { bkctld_cron_file=${bkctld_cron_file:-/etc/cron.d/bkctld} if [ -f "${bkctld_cron_file}" ]; then root_crontab=$(grep -v "^#" "${bkctld_cron_file}") - echo "${root_crontab}" | grep -q "bkctld inc" || failed "IS_EVOBACKUP_INCS" "\`bkctld inc' is missing in ${bkctld_cron_file}" - echo "${root_crontab}" | grep -qE "(check-incs.sh|bkctld check-incs)" || failed "IS_EVOBACKUP_INCS" "\`check-incs.sh' is missing in ${bkctld_cron_file}" + echo "${root_crontab}" | grep -q "bkctld inc" || failed "IS_EVOBACKUP_INCS" "'bkctld inc' is missing in ${bkctld_cron_file}" + echo "${root_crontab}" | grep -qE "(check-incs.sh|bkctld check-incs)" || failed "IS_EVOBACKUP_INCS" "'check-incs.sh' is missing in ${bkctld_cron_file}" else failed "IS_EVOBACKUP_INCS" "Crontab \`${bkctld_cron_file}' is missing" fi @@ -1129,7 +1165,7 @@ check_chrooted_binary_uptodate() { for process_name in ${process_list}; do # what is the binary path? original_bin=$(command -v "${process_name}") - for pid in $(pgrep ${process_name}); do + for pid in $(pgrep "${process_name}"); do process_bin=$(realpath "/proc/${pid}/exe") # Is the process chrooted? real_root=$(realpath "/proc/${pid}/root") @@ -1157,7 +1193,6 @@ check_nginx_letsencrypt_uptodate() { fi fi } - check_lxc_container_resolv_conf() { if is_installed lxc; then container_list=$(lxc-ls) @@ -1178,6 +1213,38 @@ check_lxc_container_resolv_conf() { done fi } +# Check that there are containers if lxc is installed. +check_no_lxc_container() { + if is_installed lxc; then + containers_count=$(lxc-ls | wc -l) + if [ "$containers_count" -eq 0 ]; then + failed "IS_NO_LXC_CONTAINER" "LXC is installed but have no container. Consider removing it." + fi + fi +} +# Check that in LXC containers, phpXX-fpm services have UMask set to 0007. +check_lxc_php_fpm_service_umask_set() { + if is_installed lxc; then + php_containers_list=$(lxc-ls --filter php) + missing_umask="" + for container in $php_containers_list; do + # Translate container name in service name + if [ "$container" = "php56" ]; then + service="php5-fpm" + else + service="${container:0:4}.${container:4}-fpm" + fi + umask=$(lxc-attach --name "${container}" -- systemctl show -p UMask "$service" | cut -d "=" -f2) + if [ "$umask" != "0007" ]; then + missing_umask="${missing_umask} ${container}" + fi + done + if [ -n "${missing_umask}" ]; then + failed "IS_LXC_PHP_FPM_SERVICE_UMASK_SET" "UMask is not set to 0007 in PHP-FPM services of theses containers : ${missing_umask}." + fi + fi +} + download_versions() { local file file=${1:-} @@ -1280,8 +1347,8 @@ add_to_path() { echo "$PATH" | grep -qF "${new_path}" || export PATH="${PATH}:${new_path}" } check_versions() { - versions_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.versions.XXXXX") - files_to_cleanup="${files_to_cleanup} ${versions_file}" + versions_file=$(mktemp --tmpdir "evocheck.versions.XXXXX") + files_to_cleanup+=("${versions_file}") download_versions "${versions_file}" add_to_path "/usr/share/scripts" @@ -1308,8 +1375,8 @@ main() { # Detect operating system name, version and release detect_os - main_output_file=$(mktemp --tmpdir="${TMPDIR:-/tmp}" "evocheck.main.XXXXX") - files_to_cleanup="${files_to_cleanup} ${main_output_file}" + main_output_file=$(mktemp --tmpdir "evocheck.main.XXXXX") + files_to_cleanup+=("${main_output_file}") test "${IS_TMP_1777:=1}" = 1 && check_tmp_1777 test "${IS_ROOT_0700:=1}" = 1 && check_root_0700 @@ -1322,6 +1389,7 @@ main() { test "${IS_LSBRELEASE:=1}" = 1 && check_lsbrelease test "${IS_DPKGWARNING:=1}" = 1 && check_dpkgwarning + test "${IS_LOCALHOST_IN_POSTFIX_MYDESTINATION:=1}" = 1 && check_localhost_in_postfix_mydestination test "${IS_NRPEPOSTFIX:=1}" = 1 && check_nrpepostfix test "${IS_CUSTOMSUDOERS:=1}" = 1 && check_customsudoers test "${IS_VARTMPFS:=1}" = 1 && check_vartmpfs @@ -1367,6 +1435,8 @@ main() { test "${IS_INTERFACESGW:=1}" = 1 && check_interfacesgw test "${IS_NETWORKING_SERVICE:=1}" = 1 && check_networking_service test "${IS_EVOBACKUP:=1}" = 1 && check_evobackup + test "${IS_PURGE_FAIL2BAN:=1}" = 1 && check_fail2ban_purge + test "${IS_SSH_FAIL2BAN_JAIL_RENAMED:=1}" = 1 && check_ssh_fail2ban_jail_renamed test "${IS_EVOBACKUP_EXCLUDE_MOUNT:=1}" = 1 && check_evobackup_exclude_mount test "${IS_USERLOGROTATE:=1}" = 1 && check_userlogrotate test "${IS_APACHECTL:=1}" = 1 && check_apachectl @@ -1418,6 +1488,8 @@ main() { 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_NO_LXC_CONTAINER:=1}" = 1 && check_no_lxc_container + test "${IS_LXC_PHP_FPM_SERVICE_UMASK_SET:=1}" = 1 && check_lxc_php_fpm_service_umask_set test "${IS_CHECK_VERSIONS:=1}" = 1 && check_versions if [ -f "${main_output_file}" ]; then @@ -1431,9 +1503,12 @@ main() { exit ${RC} } -cleanup_temp_files() { - # shellcheck disable=SC2086 - rm -f ${files_to_cleanup} +cleanup() { + # Cleanup tmp files + # shellcheck disable=SC2086,SC2317 + rm -f ${files_to_cleanup[@]} + + log "$PROGNAME exit." } PROGNAME=$(basename "$0") @@ -1444,17 +1519,23 @@ readonly PROGNAME ARGS=$@ readonly ARGS +LOGFILE="/var/log/evocheck.log" +readonly LOGFILE + +CONFIGFILE="/etc/evocheck.cf" +readonly CONFIGFILE + +DATE_FORMAT="%Y-%m-%d %H:%M:%S" +# shellcheck disable=SC2034 +readonly DATEFORMAT + # Disable LANG* export LANG=C export LANGUAGE=C -files_to_cleanup="" -# shellcheck disable=SC2064 -trap cleanup_temp_files 0 - # Source configuration file # shellcheck disable=SC1091 -test -f /etc/evocheck.cf && . /etc/evocheck.cf +test -f "${CONFIGFILE}" && . "${CONFIGFILE}" # Parse options # based on https://gist.github.com/deshion/10d3cb5f88a21671e17a @@ -1502,5 +1583,24 @@ while :; do shift done +# Keep this after "show_version(); exit 0" which is called by check_versions +# to avoid logging exit twice. +declare -a files_to_cleanup +files_to_cleanup="" +# shellcheck disable=SC2064 +trap cleanup EXIT INT TERM + +log '-----------------------------------------------' +log "Running $PROGNAME $VERSION..." + +# Log config file content +if [ -f "${CONFIGFILE}" ]; then + log "Runtime configuration (${CONFIGFILE}):" + sed -e '/^[[:blank:]]*#/d; s/#.*//; /^[[:blank:]]*$/d' "${CONFIGFILE}" | log +fi + # shellcheck disable=SC2086 main ${ARGS} + +log "End of $PROGNAME execution." + diff --git a/evocheck/files/evocheck.wheezy.sh b/evocheck/files/evocheck.wheezy.sh index cd41cb50..cd038268 100755 --- a/evocheck/files/evocheck.wheezy.sh +++ b/evocheck/files/evocheck.wheezy.sh @@ -4,7 +4,7 @@ # Script to verify compliance of a Linux (Debian) server # powered by Evolix -VERSION="22.11" +VERSION="23.03.01" readonly VERSION # base functions diff --git a/evocheck/tasks/install.yml b/evocheck/tasks/install.yml index c996542e..8abd7d57 100644 --- a/evocheck/tasks/install.yml +++ b/evocheck/tasks/install.yml @@ -1,7 +1,7 @@ --- - include_role: name: evolix/remount-usr - when: evocheck_bin_dir is search ("/usr") + when: evocheck_bin_dir is search("/usr") tags: - evocheck diff --git a/evolinux-base/handlers/main.yml b/evolinux-base/handlers/main.yml index 7331a245..388bf051 100644 --- a/evolinux-base/handlers/main.yml +++ b/evolinux-base/handlers/main.yml @@ -23,13 +23,9 @@ - name: remount /home command: mount -o remount /home - args: - warn: no - name: remount /var command: mount -o remount /var - args: - warn: no - name: restart nginx diff --git a/evolinux-base/tasks/hostname.yml b/evolinux-base/tasks/hostname.yml index 2b9cfa93..ec3f99d1 100644 --- a/evolinux-base/tasks/hostname.yml +++ b/evolinux-base/tasks/hostname.yml @@ -4,6 +4,12 @@ name: dbus state: present +- name: dbus is enabled and started + service: + name: dbus + state: started + enabled: true + - name: Set hostname "{{ evolinux_hostname }}" hostname: name: "{{ evolinux_hostname }}" diff --git a/evolinux-base/tasks/packages.yml b/evolinux-base/tasks/packages.yml index b4a1d666..4c2249e3 100644 --- a/evolinux-base/tasks/packages.yml +++ b/evolinux-base/tasks/packages.yml @@ -55,7 +55,6 @@ - mutt - tree - git - - subversion - rsync - bc - pinentry-curses diff --git a/evolinux-users/tasks/main.yml b/evolinux-users/tasks/main.yml index d105aefe..1e9cc5a3 100644 --- a/evolinux-users/tasks/main.yml +++ b/evolinux-users/tasks/main.yml @@ -16,7 +16,7 @@ vars: user: "{{ item.value }}" loop: "{{ evolinux_users | dict2items }}" - when: + when: - user.create == evolinux_users_create - evolinux_users | length > 0 diff --git a/evolinux-users/templates/sudoers_jessie.j2 b/evolinux-users/templates/sudoers_jessie.j2 index c0703c49..6bc3e57b 100644 --- a/evolinux-users/templates/sudoers_jessie.j2 +++ b/evolinux-users/templates/sudoers_jessie.j2 @@ -1,6 +1,6 @@ Defaults umask=0077 -Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh, /usr/share/scripts/listupgrade.sh, /usr/bin/apt, /bin/mount +Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh, /usr/share/scripts/listupgrade.sh User_Alias ADMINS = {{ user.name }} nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_procs diff --git a/evolinux-users/templates/sudoers_stretch.j2 b/evolinux-users/templates/sudoers_stretch.j2 index 8211f121..287483d9 100644 --- a/evolinux-users/templates/sudoers_stretch.j2 +++ b/evolinux-users/templates/sudoers_stretch.j2 @@ -1,6 +1,6 @@ Defaults umask=0077 -Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh, /usr/share/scripts/listupgrade.sh, /usr/bin/apt, /bin/mount +Cmnd_Alias MAINT = /usr/share/scripts/evomaintenance.sh, /usr/share/scripts/listupgrade.sh nagios ALL = NOPASSWD: /usr/lib/nagios/plugins/check_procs nagios ALL = NOPASSWD: /usr/local/lib/nagios/plugins/check_minifirewall diff --git a/fail2ban/files/dovecot-evolix.conf b/fail2ban/files/dovecot-evolix.conf index e1ef1a3f..5c18fb9f 100644 --- a/fail2ban/files/dovecot-evolix.conf +++ b/fail2ban/files/dovecot-evolix.conf @@ -1,3 +1,3 @@ [Definition] -failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=,.* +failregex = (?: pop3-login|imap-login): .*(?:Authentication failure|Internal login failure|Aborted login \(auth failed|Aborted login \(tried to use disabled|Disconnected \(auth failed|Aborted login \(\d+ authentication attempts).*rip=,.* ignoreregex = diff --git a/fail2ban/tasks/fix-dbpurgeage.yml b/fail2ban/tasks/fix-dbpurgeage.yml index 67819a3f..dbf9c0d9 100644 --- a/fail2ban/tasks/fix-dbpurgeage.yml +++ b/fail2ban/tasks/fix-dbpurgeage.yml @@ -1,3 +1,4 @@ +--- - name: Sqlite needed ansible.builtin.apt: name: @@ -6,10 +7,20 @@ - name: Register bantime from default config from package shell: "grep -R -E 'dbpurgeage[[:blank:]]*=[[:blank:]]*[0-9]+' /etc/fail2ban/fail2ban.conf |awk '{print $3}'|head -n1" - register: default_dbpurgeage - changed_when: false + register: dbpurgeage + changed_when: False check_mode: false +- name: + set_fact: + dbpurgeage_default : "{{ dbpurgeage.stdout }}" + when: dbpurgeage.stdout | regex_search("^\\d+\w+$") + +- name: + set_fact: + dbpurgeage_default : "{{ dbpurgeage.stdout }} second" + when: dbpurgeage.stdout | regex_search("^\\d+$") + - name: Add crontab template: src: fail2ban_dbpurge.j2 diff --git a/fail2ban/tasks/main.yml b/fail2ban/tasks/main.yml index 08478112..b9c2d109 100644 --- a/fail2ban/tasks/main.yml +++ b/fail2ban/tasks/main.yml @@ -97,7 +97,7 @@ marker: "# ANSIBLE MANAGED" block: | [DEFAULT] - dbpurgeage = {{ fail2ban_recidive_bantime}} + dbpurgeage = {{ fail2ban_recidive_bantime }} insertafter: EOF create: yes mode: "0644" diff --git a/fail2ban/templates/fail2ban_dbpurge.j2 b/fail2ban/templates/fail2ban_dbpurge.j2 index ee984438..8b6d9612 100644 --- a/fail2ban/templates/fail2ban_dbpurge.j2 +++ b/fail2ban/templates/fail2ban_dbpurge.j2 @@ -2,7 +2,7 @@ # Juin - Decembre 2022 : #64088 # Purge pour Stretch et Buster -/usr/bin/ionice -c3 /usr/bin/sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "DELETE FROM bans WHERE datetime('now', '-{{ bantime.stdout }} second') > datetime(timeofban, 'unixepoch');" +/usr/bin/ionice -c3 /usr/bin/sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "DELETE FROM bans WHERE datetime('now', '-{{ dbpurgeage_default }}') > datetime(timeofban, 'unixepoch');" place_dispo=$( df -h /var/lib/fail2ban/fail2ban.sqlite3 --output="avail" -h --block-size=1 |tail -n1 ) place_pris=$( echo $(("$(stat --format %s /var/lib/fail2ban/fail2ban.sqlite3 ) * 2" )) ) diff --git a/fail2ban/templates/jail.local.j2 b/fail2ban/templates/jail.local.j2 index 3738ee33..6713c92e 100644 --- a/fail2ban/templates/jail.local.j2 +++ b/fail2ban/templates/jail.local.j2 @@ -16,7 +16,7 @@ destemail = {{ fail2ban_alert_email or general_alert_email | mandatory }} # ACTIONS banaction = iptables-multiport -action = %({{fail2ban_default_action}})s +action = %({{ fail2ban_default_action }})s [sshd] diff --git a/filebeat/tasks/main.yml b/filebeat/tasks/main.yml index fa24a893..20858669 100644 --- a/filebeat/tasks/main.yml +++ b/filebeat/tasks/main.yml @@ -84,8 +84,8 @@ command: grep logstash-input-beats /usr/share/logstash/Gemfile check_mode: no register: logstash_plugin_installed - failed_when: false - changed_when: false + failed_when: False + changed_when: False when: - filebeat_logstash_plugin | bool - logstash_plugin.stat.exists diff --git a/haproxy/templates/haproxy.default.cfg.j2 b/haproxy/templates/haproxy.default.cfg.j2 index e33d111a..0f13e54d 100644 --- a/haproxy/templates/haproxy.default.cfg.j2 +++ b/haproxy/templates/haproxy.default.cfg.j2 @@ -63,7 +63,7 @@ listen stats acl stats_users http_auth(stats_users) stats http-request auth realm "HAProxy admin" if !stats_access_ips !stats_users {% else %} - stats http-request deny if !stats_access_ips + stats http-request deny if !stats_access_ips !stats_admin_ips {% endif %} http-request set-log-level silent diff --git a/java/tasks/openjdk.yml b/java/tasks/openjdk.yml index 4af3cec1..13135d9c 100644 --- a/java/tasks/openjdk.yml +++ b/java/tasks/openjdk.yml @@ -25,7 +25,7 @@ - name: Install specific openjdk package apt: - name: "openjdk-{{ java_version}}-jre-headless" + name: "openjdk-{{ java_version }}-jre-headless" default_release: "{{ java_apt_release }}" state: present tags: diff --git a/keepalived/files/notify.sh b/keepalived/files/notify.sh index b99c0489..7844a341 100644 --- a/keepalived/files/notify.sh +++ b/keepalived/files/notify.sh @@ -1,2 +1,3 @@ #!/bin/bash echo $1 $2 is in $3 state > /var/run/keepalive.state +chmod og+r /var/run/keepalive.state diff --git a/kibana/tasks/main.yml b/kibana/tasks/main.yml index e6377dde..341bfd13 100644 --- a/kibana/tasks/main.yml +++ b/kibana/tasks/main.yml @@ -126,8 +126,6 @@ # - name: Get mount options for /usr partition # shell: "mount | grep 'on /usr type'" -# args: -# warn: no # register: mount # changed_when: False # failed_when: False diff --git a/kvm-host/files/kvmstats.sh b/kvm-host/files/kvmstats.sh index 0dcfb4e8..0258b322 100755 --- a/kvm-host/files/kvmstats.sh +++ b/kvm-host/files/kvmstats.sh @@ -42,25 +42,34 @@ error () { 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 | { + printf '%s ' "${VM}" + virsh domstats "${VM}" | awk ' +BEGIN { + FS = "=" +} +/vcpu\.current/ { + vcpu = $2 +} +/balloon\.current/ { + mem = $2 +} +/balloon\.maximum/ { + if (!mem) + mem = $2 +} +/block\.[0-9]+\.physical/ { + disksize += $2 +} +/state\.state/ { + if ($2 == 1) + running = "yes" + else + running = "no" +} +END { + print vcpu, mem / 1024 ^ 2, disksize / 1024 ^ 3, running +}' + done | { 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" && { @@ -72,7 +81,19 @@ main() { column -t ;; 'html') - awk 'BEGIN{print "\n"}{printf "";for(i=1;i<=NF;i++)printf "", $i;print ""}END{print "
    %s
    \n"}' + awk ' +BEGIN { + print "\n" +} +{ + printf "" + for(i = 1; i <= NF; i++) + printf "", $i + print "" +} +END { + print "
    %s
    \n" +}' ;; 'csv') tr ' ' ',' diff --git a/kvm-host/tasks/ssh.yml b/kvm-host/tasks/ssh.yml index 3c097abc..d954bc06 100644 --- a/kvm-host/tasks/ssh.yml +++ b/kvm-host/tasks/ssh.yml @@ -9,7 +9,7 @@ command: cat /root/.ssh/id_rsa.pub register: ssh_keys check_mode: no - changed_when: false + changed_when: False - name: Print ssh public keys debug: diff --git a/kvm-host/tasks/tools.yml b/kvm-host/tasks/tools.yml index 83845a31..1e114bb7 100644 --- a/kvm-host/tasks/tools.yml +++ b/kvm-host/tasks/tools.yml @@ -8,7 +8,7 @@ - include_role: name: remount-usr - when: kvm_scripts_dir is search ("/usr") + when: kvm_scripts_dir is search("/usr") - name: add-vm script is present copy: diff --git a/listupgrade/files/listupgrade.sh b/listupgrade/files/listupgrade.sh index 3e1baa39..e6518f43 100644 --- a/listupgrade/files/listupgrade.sh +++ b/listupgrade/files/listupgrade.sh @@ -9,13 +9,13 @@ # - 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.3" +VERSION="23.03.3" show_version() { cat <, +Copyright 2018-2023 Evolix , Gregory Colpart , Romain Dessort , Ludovic Poujol , @@ -84,6 +84,7 @@ Subject: Prochain creneau pour mise a jour de votre serveur ${hostname} X-Debian-Release: ${local_release} X-Packages: ${packagesParsable} X-Date: ${date} +X-Listupgrade-Version: ${VERSION} Bonjour, @@ -100,15 +101,15 @@ semaine prochaine. Voici la listes de packages qui seront mis à jour : -$(cat "${packages}" | sort | uniq) +$(sort -h "${packages}" | uniq) Liste des packages dont la mise-à-jour a été manuellement suspendue : -$(cat "${packagesHold}" | sort | uniq) +$(sort -h "${packagesHold}" | uniq) Liste des services qui seront redémarrés : -$(cat "${servicesToRestart}" | sort | uniq) +$(sort -h "${servicesToRestart}" | uniq) N'hésitez pas à nous faire toute remarque sur ce créneau d'intervention le plus tôt possible. @@ -181,6 +182,28 @@ main() { fi local_release=$(cut -f 1 -d . &2 else - # store current state + # store current state (without colors) mkdir -p "$(dirname "${STATE_FILE_CURRENT}")" - status_without_numbers > "${STATE_FILE_CURRENT}" + status_without_numbers | remove_colors > "${STATE_FILE_CURRENT}" # clean previous diff file rm -f "${STATE_FILE_DIFF}" @@ -310,9 +313,9 @@ report_state_changes() { check_unpersisted_state fi - # Then reset the known state + # Then reset the known state (without colors) mkdir -p "$(dirname "${STATE_FILE_LATEST}")" - status_without_numbers > "${STATE_FILE_LATEST}" + status_without_numbers | remove_colors > "${STATE_FILE_LATEST}" # But if there is a previous known state # let's compare with the new known state @@ -920,8 +923,9 @@ stop() { printf "${BLUE}flushing all rules and accepting everything${RESET}\n" + # Save previous state (without colors) mkdir -p "$(dirname "${STATE_FILE_PREVIOUS}")" - status_without_numbers > "${STATE_FILE_PREVIOUS}" + status_without_numbers | remove_colors > "${STATE_FILE_PREVIOUS}" # Delete all rules ${IPT} -F INPUT diff --git a/minifirewall/tasks/main.yml b/minifirewall/tasks/main.yml index bc56b7dc..e0dbcaf0 100644 --- a/minifirewall/tasks/main.yml +++ b/minifirewall/tasks/main.yml @@ -6,6 +6,8 @@ stat: path: /etc/init.d/minifirewall register: _minifirewall_check + tags: + - always # Legacy versions of minifirewall don't define the VERSION variable - name: Look for minifirewall version @@ -14,6 +16,8 @@ changed_when: False check_mode: False register: _minifirewall_version_check + tags: + - always - name: Set install mode to legacy if needed set_fact: @@ -24,21 +28,30 @@ - minifirewall_install_mode != 'modern' - not (minifirewall_force_upgrade_script | bool) - _minifirewall_version_check.rc == 1 # grep didn't find but the file exists + tags: + - always - name: Set install mode to modern if not legacy set_fact: minifirewall_install_mode: modern when: minifirewall_install_mode != 'legacy' + tags: + - always - name: Debug install mode debug: var: minifirewall_install_mode verbosity: 1 + tags: + - always - name: 'Set minifirewall_restart_handler_name to "noop"' set_fact: minifirewall_restart_handler_name: "restart minifirewall (noop)" - when: not (minifirewall_restart_if_needed | bool) + when: + - not (minifirewall_restart_if_needed | bool) + tags: + - always - name: 'Set minifirewall_restart_handler_name to "legacy"' set_fact: @@ -46,6 +59,8 @@ when: - minifirewall_restart_if_needed | bool - minifirewall_install_mode == 'legacy' + tags: + - always - name: 'Set minifirewall_restart_handler_name to "modern"' set_fact: @@ -53,6 +68,8 @@ when: - minifirewall_restart_if_needed | bool - minifirewall_install_mode != 'legacy' + tags: + - always ####################################################################### @@ -62,54 +79,74 @@ when: - minifirewall_install_mode != 'legacy' - minifirewall_main_file is defined + tags: + - always - name: Install tasks (modern mode) - include: install.yml + import_tasks: install.yml when: minifirewall_install_mode != 'legacy' - name: Install tasks (legacy mode) - include: install.legacy.yml + import_tasks: install.legacy.yml when: minifirewall_install_mode == 'legacy' - name: Debug minifirewall_update_config debug: var: minifirewall_update_config | bool verbosity: 1 + tags: + - always - name: Config tasks (modern mode) - include: config.yml + include_tasks: config.yml when: - minifirewall_install_mode != 'legacy' - minifirewall_update_config | bool + tags: + - manage - name: Config tasks (legacy mode) - include: config.legacy.yml + include_tasks: config.legacy.yml + args: + apply: + tags: + - manage when: - minifirewall_install_mode == 'legacy' - minifirewall_update_config | bool - name: Utils tasks - include: utils.yml + include_tasks: utils.yml - name: NRPE tasks - include: nrpe.yml + include_tasks: nrpe.yml - name: Activation tasks - include: activate.yml + include_tasks: activate.yml - name: Debug minifirewall_tail_included debug: var: minifirewall_tail_included | bool verbosity: 1 + tags: + - always - name: Tail tasks (modern mode) - include: tail.yml + include_tasks: tail.yml + args: + apply: + tags: + - manage when: - minifirewall_install_mode != 'legacy' - minifirewall_tail_included | bool - name: Tail tasks (legacy mode) - include: tail.legacy.yml + include_tasks: tail.legacy.yml + args: + apply: + tags: + - manage when: - minifirewall_install_mode == 'legacy' - minifirewall_tail_included | bool @@ -120,10 +157,14 @@ debug: var: minifirewall_restart_force | bool verbosity: 1 + tags: + - always - name: Force restart minifirewall (legacy) command: /bin/true notify: "restart minifirewall (legacy)" + tags: + - always when: - minifirewall_install_mode == 'legacy' - minifirewall_restart_force | bool @@ -131,6 +172,8 @@ - name: Force restart minifirewall (modern) command: /bin/true notify: "restart minifirewall (modern)" + tags: + - always when: - minifirewall_install_mode != 'legacy' - minifirewall_restart_force | bool \ No newline at end of file diff --git a/mongodb/tasks/main_bullseye.yml b/mongodb/tasks/main_bullseye.yml index cd8bb15f..c17642ea 100644 --- a/mongodb/tasks/main_bullseye.yml +++ b/mongodb/tasks/main_bullseye.yml @@ -3,7 +3,7 @@ - fail: msg: Not compatible with Debian 11 (Bullseye) when: - - ansible_distribution_release == "bullseye" + - ansible_distribution_release == "bullseye" - mongodb_version is version('5.0', '<') - name: Look for legacy apt keyring @@ -20,8 +20,8 @@ - name: Add MongoDB GPG key copy: - src: "server-{{mongodb_version}}.asc" - dest: "{{ apt_keyring_dir }}/mongodb-server-{{mongodb_version}}.asc" + src: "server-{{ mongodb_version }}.asc" + dest: "{{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc" force: yes mode: "0644" owner: root @@ -29,16 +29,16 @@ - name: Enable APT sources list apt_repository: - repo: "deb [signed-by={{ apt_keyring_dir }}/mongodb-server-{{mongodb_version}}.asc] http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{mongodb_version}} main" + repo: "deb [signed-by={{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc] http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{ mongodb_version }} main" state: present - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Disable unsigned APT sources list apt_repository: - repo: "deb http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{mongodb_version}} main" + repo: "deb http://repo.mongodb.org/apt/debian bullseye/mongodb-org/{{ mongodb_version }} main" state: absent - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Install packages diff --git a/mongodb/tasks/main_buster.yml b/mongodb/tasks/main_buster.yml index 5d2024c8..44baabc9 100644 --- a/mongodb/tasks/main_buster.yml +++ b/mongodb/tasks/main_buster.yml @@ -14,7 +14,7 @@ - name: Add MongoDB GPG key copy: - src: "server-{{mongodb_version}}.asc" + src: "server-{{ mongodb_version }}.asc" dest: "{{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc" force: yes mode: "0644" @@ -25,14 +25,14 @@ apt_repository: repo: "deb [signed-by={{ apt_keyring_dir }}/mongodb-server-{{ mongodb_version }}.asc] http://repo.mongodb.org/apt/debian buster/mongodb-org/{{ mongodb_version }} main" state: present - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Disable unsigned APT sources list apt_repository: repo: "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/{{ mongodb_version }} main" state: absent - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Install packages diff --git a/mongodb/tasks/main_jessie.yml b/mongodb/tasks/main_jessie.yml index 7fdb3df5..bc239393 100644 --- a/mongodb/tasks/main_jessie.yml +++ b/mongodb/tasks/main_jessie.yml @@ -14,8 +14,8 @@ - name: Add MongoDB GPG key copy: - src: "server-{{mongodb_version}}.asc" - dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{mongodb_version}}.asc" + src: "server-{{ mongodb_version }}.asc" + dest: "/etc/apt/trusted.gpg.d/mongodb-server-{{ mongodb_version }}.asc" force: yes mode: "0644" owner: root @@ -23,16 +23,16 @@ - name: Enable APT sources list apt_repository: - repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{mongodb_version}} main" + repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{ mongodb_version }} main" state: present - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Disable APT sources list apt_repository: - repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{mongodb_version}} main" + repo: "deb http://repo.mongodb.org/apt/debian jessie/mongodb-org/{{ mongodb_version }} main" state: absent - filename: "mongodb-org-{{mongodb_version}}" + filename: "mongodb-org-{{ mongodb_version }}" update_cache: yes - name: Install packages diff --git a/munin/tasks/main.yml b/munin/tasks/main.yml index a4ea9a49..6d3098dd 100644 --- a/munin/tasks/main.yml +++ b/munin/tasks/main.yml @@ -85,7 +85,7 @@ src: /usr/share/munin/plugins/sensors_ dest: "/etc/munin/plugins/sensors_{{ item }}" state: link - with_items: + with_items: - fan - temp when: ansible_virtualization_role == "host" diff --git a/mysql-oracle/tasks/utils.yml b/mysql-oracle/tasks/utils.yml index e0520cee..82b0ddbe 100644 --- a/mysql-oracle/tasks/utils.yml +++ b/mysql-oracle/tasks/utils.yml @@ -5,7 +5,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Scripts directory exists file: @@ -106,7 +106,7 @@ name: evolix/remount-usr tags: - mysql - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: mysqltuner is installed # copy: @@ -132,7 +132,7 @@ name: evolix/remount-usr tags: - mysql - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: mysql-optimize.sh is installed copy: @@ -203,7 +203,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Install my-add.sh copy: diff --git a/mysql/defaults/main.yml b/mysql/defaults/main.yml index 80f526c6..af43f495 100644 --- a/mysql/defaults/main.yml +++ b/mysql/defaults/main.yml @@ -50,8 +50,10 @@ mysql_restart_if_needed: True mysql_performance_schema: True +mysql_skip_enabled: False + # replication variables: -mysql_replication: false +mysql_replication: False mysql_log_bin: null mysql_binlog_format: mixed mysql_server_id: null diff --git a/mysql/files/mysql_skip.sh b/mysql/files/mysql_skip.sh new file mode 100644 index 00000000..95bc28f7 --- /dev/null +++ b/mysql/files/mysql_skip.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# File containing error messages to skip (one per line). +error_messages="/etc/mysql_skip.conf" + +# Sleep interval between 2 check. +sleep_interval="1" + +# Exit when Seconds_Behind_Master reached 0. +exit_when_uptodate="false" + +# Options to pass to mysql. +#mysql_opt="-P 3307" + +# File to log skipped queries to (leave empty for no logs). +log_file="/var/log/mysql_skip.log" + +mysql_skip_error() { + error="$1" + + error="$(date --iso-8601=seconds) Skiping: $error" + printf "Skipping: $error\n" + mysql $mysql_opt -e 'SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;' + + [ -n "$log_file" ] && echo "$error" >>"$log_file" +} + +while true; do + slave_status="$(mysql $mysql_opt -e 'SHOW SLAVE STATUS\G')" + seconds_behind_master=$(echo "$slave_status" |grep 'Seconds_Behind_Master: ' |awk -F ' ' '{print $2}') + last_SQL_error="$(echo "$slave_status" |grep 'Last_SQL_Error: ' |sed 's/^.\+Last_SQL_Error: //')" + + if [ "$seconds_behind_master" = "0" ]; then + #printf 'Replication is up to date!\n' + if [ "$exit_when_uptodate" = "true" ]; then + exit 0 + fi + + elif [ -z "$last_SQL_error" ]; then + sleep $sleep_interval + + elif echo "$last_SQL_error" |grep -q -f $error_messages; then + mysql_skip_error "$last_SQL_error" + + fi + sleep 1 +done diff --git a/mysql/tasks/main.yml b/mysql/tasks/main.yml index 70a972f3..95cde4a1 100644 --- a/mysql/tasks/main.yml +++ b/mysql/tasks/main.yml @@ -45,3 +45,5 @@ - include_tasks: log2mail.yml - include_tasks: utils.yml + +- include_tasks: mysql_skip.yml diff --git a/mysql/tasks/mysql_skip.yml b/mysql/tasks/mysql_skip.yml new file mode 100644 index 00000000..65d1c13f --- /dev/null +++ b/mysql/tasks/mysql_skip.yml @@ -0,0 +1,54 @@ +--- + +- name: "Copy script mysql_skip.sh into /usr/local/bin/" + copy: + src: mysql_skip.sh + dest: "/usr/local/bin/mysql_skip.sh" + owner: root + group: root + mode: "0700" + force: yes + tags: + - mysql_skip + +- name: "Copy config file for mysql_skip.sh" + template: + src: mysql_skip.conf.j2 + dest: "/etc/mysql_skip.conf" + owner: root + group: root + mode: "0600" + tags: + - mysql_skip + +- name: "Create log file for mysql_skip.sh" + file: + path: "/var/log/mysql_skip.log" + state: touch + owner: root + group: adm + mode: "0640" + tags: + - mysql_skip + +- name: "Copy logrotate file for mysql_skip.sh" + template: + src: mysql_skip.logrotate.j2 + dest: "/etc/logrotate.d/mysql_skip" + owner: root + group: root + mode: "0600" + tags: + - mysql_skip + +- name: "Copy mysql_skip.sh systemd unit" + template: + src: mysql_skip.systemd.j2 + dest: /etc/systemd/system/mysql_skip.service + force: yes + +- name: "Start or stop systemd unit" + systemd: + name: mysql_skip + daemon_reload: yes + state: "{{ mysql_skip_enabled | bool | ternary('started', 'stopped') }}" \ No newline at end of file diff --git a/mysql/tasks/utils.yml b/mysql/tasks/utils.yml index 1ac8f2df..8adbb1be 100644 --- a/mysql/tasks/utils.yml +++ b/mysql/tasks/utils.yml @@ -5,7 +5,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Ensure scripts directory exists file: @@ -96,7 +96,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Install mysqltuner # copy: @@ -132,7 +132,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Optimize script for MySQL copy: @@ -196,7 +196,7 @@ - include_role: name: evolix/remount-usr - when: _mysql_scripts_dir is search ("/usr") + when: _mysql_scripts_dir is search("/usr") - name: Install my-add.sh copy: diff --git a/mysql/templates/mysql_skip.conf.j2 b/mysql/templates/mysql_skip.conf.j2 new file mode 100644 index 00000000..3c8ef5fc --- /dev/null +++ b/mysql/templates/mysql_skip.conf.j2 @@ -0,0 +1 @@ +## Put your matched patern here ## diff --git a/mysql/templates/mysql_skip.logrotate.j2 b/mysql/templates/mysql_skip.logrotate.j2 new file mode 100644 index 00000000..4a75b3ea --- /dev/null +++ b/mysql/templates/mysql_skip.logrotate.j2 @@ -0,0 +1,10 @@ +/var/log/mysql_skip.log { + missingok + notifempty + monthly + rotate 12 + compress + create 640 root adm + dateext + dateformat -%Y%m%d%H +} \ No newline at end of file diff --git a/mysql/templates/mysql_skip.systemd.j2 b/mysql/templates/mysql_skip.systemd.j2 new file mode 100644 index 00000000..afe44700 --- /dev/null +++ b/mysql/templates/mysql_skip.systemd.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=Script for skip define mysql replication errors + +[Service] +ExecStart=/usr/local/bin/mysql_skip.sh +Type=simple +User=root +Group=root +PIDFile=/run/mysql_skip.pid +ExecStop=/bin/kill -- $MAINPID +KillMode=process +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=multi-user.target diff --git a/mysql/templates/replication.cnf.j2 b/mysql/templates/replication.cnf.j2 index 030f2470..460f0833 100644 --- a/mysql/templates/replication.cnf.j2 +++ b/mysql/templates/replication.cnf.j2 @@ -1,4 +1,4 @@ -# {{ansible_managed}} +# {{ ansible_managed }} [mysqld] {% if mysql_log_bin %} diff --git a/nagios-nrpe/files/alerts_switch b/nagios-nrpe/files/alerts_switch new file mode 100644 index 00000000..3c5a1417 --- /dev/null +++ b/nagios-nrpe/files/alerts_switch @@ -0,0 +1,83 @@ +#!/bin/bash + +# https://forge.evolix.org/projects/evolix-private/repository +# +# You should not alter this file. +# If you need to, create and customize a copy. + +set -e + +readonly PROGNAME=$(basename $0) +readonly PROGDIR=$(readlink -m $(dirname $0)) +readonly ARGS="$@" + +usage() { + echo "$PROGNAME action prefix" +} + +disable_alerts () { + disabled_file="$1_disabled" + enabled_file="$1_enabled" + + if [ -e "${enabled_file}" ]; then + mv "${enabled_file}" "${disabled_file}" + else + touch "${disabled_file}" + chmod 0644 "${disabled_file}" + fi +} + +enable_alerts () { + disabled_file="$1_disabled" + enabled_file="$1_enabled" + + if [ -e "${disabled_file}" ]; then + mv "${disabled_file}" "${enabled_file}" + else + touch "${enabled_file}" + chmod 0644 "${enabled_file}" + fi +} + +now () { + date --iso-8601=seconds +} + +log_disable () { + echo "$(now) - alerts disabled by $(logname || echo unknown)" >> $1 +} + +log_enable () { + echo "$(now) - alerts enabled by $(logname || echo unknown)" >> $1 +} + +main () { + local action=$1 + local prefix=$2 + + local base_dir="/var/lib/misc" + mkdir -p "${base_dir}" + + local file_path="${base_dir}/${prefix}_alerts" + local log_file="/var/log/${prefix}_alerts.log" + + case "$action" in + enable) + enable_alerts ${file_path} + log_enable ${log_file} + ;; + disable) + disable_alerts ${file_path} + log_disable ${log_file} + ;; + help) + usage + ;; + *) + >&2 echo "Unknown action '$action'" + exit 1 + ;; + esac +} + +main $ARGS diff --git a/nagios-nrpe/files/alerts_wrapper b/nagios-nrpe/files/alerts_wrapper new file mode 100644 index 00000000..d4524fdd --- /dev/null +++ b/nagios-nrpe/files/alerts_wrapper @@ -0,0 +1,217 @@ +#!/bin/bash + +# https://forge.evolix.org/projects/evolix-private/repository +# +# You should not alter this file. +# If you need to, create and customize a copy. + +VERSION="21.04" +readonly VERSION + +# base functions + +show_version() { + cat <, + Jérémy Lecour + and others. + +alerts_wrapper 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 < "${check_stdout}" + check_rc=$? + readonly check_rc + + delay=0 + + if [ -e "${alerts_disabled_file}" ]; then + delay=$(delay_from_alerts_disabled_file) + + if [ "${delay}" -le "0" ]; then + enable_check + fi + fi + + if [ -e "${alerts_disabled_file}" ]; then + formatted_last_change=$(date --date "@$(stat -c %Z "${alerts_disabled_file}")" +'%c') + readonly formatted_last_change + + echo "ALERTS DISABLED for ${check_name} (since ${formatted_last_change}, delay: ${delay} sec) - $(cat "${check_stdout}")" + if [ ${check_rc} = 0 ]; then + # Nagios OK + exit 0 + else + # Nagios WARNING + exit 1 + fi + else + cat "${check_stdout}" + exit ${check_rc} + fi +} + +# Default: 1 day before re-enabling the check +wrapper_limit_default="1d" +readonly wrapper_limit_default + +if [[ "${1}" =~ -.* ]]; then + # 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 + ;; + + --limit) + # with value separated by space + if [ -n "$2" ]; then + wrapper_limit=$2 + shift + else + printf 'ERROR: "--limit" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --limit=?*) + # with value speparated by = + wrapper_limit=${1#*=} + ;; + --limit=) + # without value + printf 'ERROR: "--limit" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + + --name) + # with value separated by space + if [ -n "$2" ]; then + check_name=$2 + shift + else + printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2 + exit 1 + fi + ;; + --name=?*) + # with value speparated by = + check_name=${1#*=} + ;; + --name=) + # without value + printf 'ERROR: "--name" requires a non-empty option argument.\n' >&2 + exit 1 + ;; + + --) + # 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 + # The rest is the command + check_command="$*" +else + # no option is passed (backward compatibility with previous version) + # treat the first argument as check_name and the rest as the command + check_name="${1}" + shift + check_command="$*" +fi + +# Default values or errors +if [ -z "${wrapper_limit}" ]; then + wrapper_limit="${wrapper_limit_default}" +fi +if [ -z "${check_name}" ]; then + printf 'ERROR: You must specify a check name, with --name.\n' >&2 + exit 1 +fi +if [ -z "${check_command}" ]; then + printf 'ERROR: You must specify a command to execute.\n' >&2 + exit 1 +fi + +readonly check_name +readonly check_command +readonly wrapper_limit +alerts_disabled_file="/var/lib/misc/${check_name}_alerts_disabled" +readonly alerts_disabled_file + +check_file="/var/lib/misc/${check_name}_alerts_disabled" +readonly check_file + +check_stdout=$(mktemp --tmpdir=/tmp "${check_name}_stdout.XXXX") +readonly check_stdout + +# shellcheck disable=SC2064 +trap "rm ${check_stdout}" EXIT + +main diff --git a/nagios-nrpe/files/check_async b/nagios-nrpe/files/check_async index 5ff8ad24..2a54f920 100644 --- a/nagios-nrpe/files/check_async +++ b/nagios-nrpe/files/check_async @@ -59,9 +59,9 @@ delay_from_check_file() { enable_check() { if [ "$(id -u)" -eq "0" ] ; then - /usr/share/scripts/alerts_switch enable "${check_name}" + /usr/local/bin/alerts_switch enable "${check_name}" else - sudo /usr/share/scripts/alerts_switch enable "${check_name}" + sudo /usr/local/bin/alerts_switch enable "${check_name}" fi } diff --git a/nagios-nrpe/files/plugins/check_phpfpm_multi b/nagios-nrpe/files/plugins/check_phpfpm_multi index 865c31d3..b02fc7e2 100644 --- a/nagios-nrpe/files/plugins/check_phpfpm_multi +++ b/nagios-nrpe/files/plugins/check_phpfpm_multi @@ -56,20 +56,20 @@ for pool_file in $POOL_FILES; do if [ "${ret}" -ge 2 ]; then nb_crit=$((nb_crit + 1)) - output="${output}${result}\n" [ "${return}" -le 2 ] && return=2 elif [ "${ret}" -ge 1 ]; then nb_warn=$((nb_warn + 1)) - output="${output}${result}\n" [ "${return}" -le 1 ] && return=1 else nb_ok=$((nb_ok + 1)) - output="${output}$(echo "$result" | cut -d '|' -f1)\n" [ "${return}" -le 0 ] && return=0 fi + result_status=$(echo ${result} | awk -F' - ' '{ print $1}') + result_content=$(echo ${result} | awk -F' - ' '{ print $2}') + output="${output}${result_status} - ${pool_file} - ${result_content}\n" -done; +done [ "${return}" -ge 0 ] && header="OK" diff --git a/nagios-nrpe/files/plugins/check_vrrpd b/nagios-nrpe/files/plugins/check_vrrpd index 9390aa6e..a82c379b 100755 --- a/nagios-nrpe/files/plugins/check_vrrpd +++ b/nagios-nrpe/files/plugins/check_vrrpd @@ -1,94 +1,190 @@ #!/bin/bash +# shellcheck disable=SC2207,SC2009,SC2076 -# README -# -# Variable to adjust : is_master and vrrpd_processes. -# vrrpd_processes is the number of vrrpd processes that should run on the server. -# is_master defines whether the vrrpd group should be master (1) or backup (0). -# -# If some instances have to be master and some other have to be backup, -# then the value of is_master is 2 and the states has to be precised in arguments. -# e.g. : ./check_vrrpd master backup master -# The order is defined by the output order of `ps auwx | grep vrrp` +usage() { +cat << EOL + Usage : -RC=0 -IFS=' -' + $0 --master X,Y --backup Z -is_master=2 # 1 if master ; 0 if backup ; 2 if mixed master and backup, in this case, it has to be precised in arguments -vrrpd_processes=3 # number of vrrpd processes that should be running -is_vrrpd_running=$(sudo /usr/lib/nagios//plugins/check_procs -C vrrpd -c $vrrpd_processes:$vrrpd_processes) -rc_is_vrrpd_running=$? -IP_vrrpd=($(for i in $(ps auwx | grep vrrpd | grep -v grep | grep -v check); do echo $i | awk '{print $--NF}'; done)) -INT_vrrpd=($(for i in $(ps auwx | grep vrrpd | grep -v grep | grep -v check); do echo $i | awk '{print $13}'; done)) -ID_vrrpd=($(for i in $(ps auwx | grep vrrpd | grep -v grep | grep -v check); do echo $i | awk '{print $19}'; done)) + -m|--master ID_MASTER # VRRP ID that should be master, separated by a comma "," + -b|--backup ID_BACKUP # VRRP ID that should be backup, separated by a comma "," + [--vrrpd] # Check for vrrpd daemon (default) + [--uvrrpd] # Check for uvrrpd daemon +EOL +} -if [[ $rc_is_vrrpd_running -ne 0 ]]; then - echo $is_vrrpd_running instead of $vrrpd_processes +unset ID_master +unset ID_backup +vrrpd_option="unset" +uvrrpd_option="unset" +unset critical_output +critical_state="unset" +unset warning_output +warning_state="unset" +unset ok_output +ok_state="unset" +exit_code=0 +used_daemon="vrrpd" +IFS=" +" + +# If no argument then show usage +if [ "$#" -eq 0 ]; then + usage exit 2 fi -for i in $(seq 0 $((${#ID_vrrpd[*]}-1))); do - ifconfig vrrp_${ID_vrrpd[$i]}_${INT_vrrpd[$i]} >/dev/null 2>&1 - # If has interface - if [[ $? -eq 0 ]]; then - # If has to be master : OK - if [[ $is_master -eq 1 ]]; then - echo OK - ${IP_vrrpd[$i]} exists and is master - # If has to be backup : KO - elif [[ $is_master -eq 0 ]]; then - echo CRITICAL - ${IP_vrrpd[$i]} exists whereas it should be backup - RC=2 - # We retrieve the state it should be from args - elif [[ $is_master -eq 2 ]]; then - arg=$(($i+1)) - state=${!arg} - # If has to be master : OK - if [[ $state = master ]]; then - echo OK - ${IP_vrrpd[$i]} exists and is master - # If has to be backup : KO - elif [[ $state = backup ]]; then - echo CRITICAL - ${IP_vrrpd[$i]} exists whereas it should be backup - RC=2 +while :; do + case $1 in + -h|-\?|--help) # Call a "usage" function to display a synopsis, then exit. + usage + exit + ;; + -m|--master) # Takes an option argument, ensuring it has been specified. + if [ -n "$2" ]; then + ID_master=($(echo "$2" | tr "," "\n")) # Make an array with values separated by "," + shift else - echo "CRITICAL - The arguments have to be master or backup. Exiting" + printf 'ERROR: "--master" requires a non-empty option argument.\n' >&2 exit 2 fi - # Unknown - else - RC=3 - fi - # If hasn't interface - elif [[ $? -ne 0 ]]; then - # If has to be master : KO - if [[ $is_master -eq 1 ]]; then - echo CRITICAL - ${IP_vrrpd[$i]} does not exist whereas it should be master - RC=2 - # If has to be backup : OK - elif [[ $is_master -eq 0 ]]; then - echo OK - ${IP_vrrpd[$i]} is backup - # We retrieve the state it should be from args - elif [[ $is_master -eq 2 ]]; then - arg=$(($i+1)) - state=${!arg} - # If has to be master : KO - if [[ $state = master ]]; then - echo CRITICAL - ${IP_vrrpd[$i]} does not exist whereas it should be master - RC=2 - # If has to be backup : OK - elif [[ $state = backup ]]; then - echo OK - ${IP_vrrpd[$i]} is backup + ;; + -b|--backup) # Takes an option argument, ensuring it has been specified. + if [ -n "$2" ]; then + ID_backup=($(echo "$2" | tr "," "\n")) # Make an array with values separated by "," + shift else - echo "CRITICAL - The arguments have to be master or backup. Exiting" + printf 'ERROR: "--backup" requires a non-empty option argument.\n' >&2 exit 2 fi - # Unknown - else - RC=3 - fi - # Unknown - else - RC=3 - fi + ;; + --vrrpd) + used_daemon="vrrpd" + vrrpd_option="set" + ;; + --uvrrpd) + used_daemon="uvrrpd" + uvrrpd_option="set" + ;; + -?*) + printf 'WARNING: Unknown option (ignored): %s\n' "$1" >&2 + ;; + *) # Default case: If no more options then break out of the loop. + break + esac + shift done -exit $RC + +# Make sure that each given ID is given once only +all_ID=("${ID_master[@]}" "${ID_backup[@]}") +uniqueNum=$(printf '%s\n' "${all_ID[@]}"|awk '!($0 in seen){seen[$0];c++} END {print c}') +if [ "$uniqueNum" != ${#all_ID[@]} ]; then + echo "ERROR : At least one VRRP ID is given multiple times" + exit 2 +fi + +# Make sure --vrrpd and --uvrrpd are not both set +if [ $vrrpd_option = "set" ] && [ $uvrrpd_option = "set" ]; then + echo "ERROR : You cannot set both parameters --vrrpd and --uvrrpd" + exit 2 +fi + +# Make sure no sysclt parameter "rp_filter" is set to 1 +if grep -q 1 /proc/sys/net/ipv4/conf/*/rp_filter; then + critical_output="${critical_output}CRITICAL - rp_filter is set to 1 at least for one interface\n" + critical_state="set" +fi + +vrrpd_processes_number=$((${#ID_master[@]}+${#ID_backup[@]})) # Number of vrrpd processes that should be running = length of arrays ID_master + ID_backup +regex_ipv4="((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])" +regex_ipv6="(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))" +vrrpd_processes=$(ps auwx | grep "$used_daemon" | grep -v -e grep -e check) +ID_running_vrrpd=($(for i in ${vrrpd_processes}; do echo "$i" | grep -Eo -- "-v [0-9]+" | awk '{print $2}'; done)) + +# Check the number of running vrrpd processes in comparison to the number of ID given +if ! sudo /usr/lib/nagios/plugins/check_procs -C "$used_daemon" -c $vrrpd_processes_number:$vrrpd_processes_number >/dev/null; then + critical_output="${critical_output}CRITICAL : $vrrpd_processes_number VRRP ID are given but $(ps auwx | grep "$used_daemon" | grep -v -e grep -e check -c) $used_daemon processes are running\n" + if pgrep uvrrp >/dev/null && [ $uvrrpd_option = "unset" ]; then + critical_output="${critical_output}It seems that uvrrpd is running. Use parameter --uvrrpd\n" + fi + critical_state="set" +fi + +IFS=" " + +# For each ID_master, make sure a process exist +if [ ${#ID_master[@]} -ne 0 ]; then + for i in "${ID_master[@]}"; do + # If array contains the current ID, then a process exist, and we have to make sure the corresponding interface exists + if [[ " ${ID_running_vrrpd[*]} " =~ " $i " ]]; then + vrrpd_current_proccess=$(echo "$vrrpd_processes" | grep -E -- "-v $i ") + INT_current_vrrpd=$(echo "$vrrpd_current_proccess" | grep -Eo -- "-i \S+" | awk '{print $2}') + IP_current_vrrpd=$(echo "$vrrpd_current_proccess" | grep -Eo "${regex_ipv4}|${regex_ipv6}") + if [ "$used_daemon" = "vrrpd" ]; then + int_name="vrrp_${i}_${INT_current_vrrpd}" + elif [ "$used_daemon" = "uvrrpd" ]; then + int_name="${INT_current_vrrpd}_${i}" + fi + if /sbin/ifconfig "$int_name" 2> /dev/null | grep -q "$IP_current_vrrpd"; then + ok_output="${ok_output}OK - ID $i has a process and $IP_current_vrrpd is master\n" + ok_state="set" + else + warning_output="${warning_output}WARNING - The IP $IP_current_vrrpd for ID $i is backup while it should be master\n" + warning_state="set" + fi + else + critical_output="${critical_output}CRITICAL - No process is running for VRRP ID $i\n" + critical_state="set" + fi + done +fi + +# For each ID_backup, make sure a process exist +if [ ${#ID_backup[@]} -ne 0 ]; then + for i in "${ID_backup[@]}"; do + # If array contains the current ID, then a process exist, and we have to make sure the corresponding interface does not exist + if [[ " ${ID_running_vrrpd[*]} " =~ " $i " ]]; then + vrrpd_current_proccess=$(echo "$vrrpd_processes" | grep -E -- "-v $i ") + INT_current_vrrpd=$(echo "$vrrpd_current_proccess" | grep -Eo -- "-i \S+" | awk '{print $2}') + IP_current_vrrpd=$(echo "$vrrpd_current_proccess" | grep -Eo "${regex_ipv4}|${regex_ipv6}") + if [ "$used_daemon" = "vrrpd" ]; then + int_name="vrrp_${i}_${INT_current_vrrpd}" + elif [ "$used_daemon" = "uvrrpd" ]; then + int_name="${INT_current_vrrpd}_${i}" + fi + if ! /sbin/ifconfig "$int_name" 2> /dev/null | grep -q "$IP_current_vrrpd"; then + ok_output="${ok_output}OK - ID $i has a process and $IP_current_vrrpd is backup\n" + ok_state="set" + else + warning_output="${warning_output}WARNING - The IP $IP_current_vrrpd for ID $i is master while it should be backup\n" + warning_state="set" + fi + else + critical_output="${critical_output}CRITICAL - No process is running for VRRP ID $i\n" + critical_state="set" + fi + done +fi + +# Make $exit_code the highest set +if [ "$critical_state" = "set" ]; then + exit_code=2 +elif [ "$warning_state" = "set" ]; then + exit_code=1 +elif [ "$ok_state" = "set" ]; then + exit_code=0 +fi + +# Echo most critical output first, least last +if [ -n "$critical_output" ]; then + echo -e "$critical_output" | grep -v "^$" +fi +if [ -n "$warning_output" ]; then + echo -e "$warning_output" | grep -v "^$" +fi +if [ -n "$ok_output" ]; then + echo -e "$ok_output" | grep -v "^$" +fi + +exit $exit_code diff --git a/nagios-nrpe/tasks/main.yml b/nagios-nrpe/tasks/main.yml index 77770020..5a77c4ee 100644 --- a/nagios-nrpe/tasks/main.yml +++ b/nagios-nrpe/tasks/main.yml @@ -58,7 +58,7 @@ - include_role: name: evolix/remount-usr - when: nagios_plugins_directory is search ("/usr") + when: nagios_plugins_directory is search("/usr") tags: - nagios-nrpe - nagios-plugins @@ -83,3 +83,5 @@ notify: restart nagios-nrpe-server tags: - nagios-nrpe + +- include_tasks: wrapper.yml \ No newline at end of file diff --git a/nagios-nrpe/tasks/wrapper.yml b/nagios-nrpe/tasks/wrapper.yml new file mode 100644 index 00000000..f49c7509 --- /dev/null +++ b/nagios-nrpe/tasks/wrapper.yml @@ -0,0 +1,42 @@ +--- + + +- name: "Remount /usr if needed" + include_role: + name: remount-usr + +- name: check if old script is present + stat: + path: /usr/share/scripts/alerts_switch + register: old_alerts_switch + +- name: alerts_switch is at the right place + command: "mv /usr/share/scripts/alerts_switch /usr/local/bin/alerts_switch" + args: + creates: /usr/local/bin/alerts_switch + when: old_alerts_switch.stat.exists + +- name: "copy alerts_switch" + copy: + src: alerts_switch + dest: /usr/local/bin/alerts_switch + owner: root + group: root + mode: "0750" + force: yes + +- name: "symlink for backward compatibility" + file: + src: /usr/local/bin/alerts_switch + dest: /usr/share/scripts/alerts_switch + state: link + when: old_alerts_switch.stat.exists + +- name: "copy alerts_wrapper" + copy: + src: alerts_wrapper + dest: "{{ nagios_plugins_directory }}/alerts_wrapper" + owner: root + group: staff + mode: "0755" + force: yes \ No newline at end of file diff --git a/nameserver/tasks/main.yml b/nameserver/tasks/main.yml index 420e65af..83ba2a34 100644 --- a/nameserver/tasks/main.yml +++ b/nameserver/tasks/main.yml @@ -3,7 +3,7 @@ shell: grep nameserver /etc/resolv.conf | awk '{ print $2 }' register: grep_nameserver check_mode: no - changed_when: false + changed_when: False tags: - nameserver diff --git a/newrelic/tasks/php.yml b/newrelic/tasks/php.yml index c41dbac9..3bd4d809 100644 --- a/newrelic/tasks/php.yml +++ b/newrelic/tasks/php.yml @@ -18,7 +18,7 @@ - name: list newrelic config files shell: "find /etc/php* -type f -name newrelic.ini" - changed_when: false + changed_when: False check_mode: no register: find_newrelic_ini diff --git a/nginx/tasks/main.yml b/nginx/tasks/main.yml index b3f1c313..e7abc1b5 100644 --- a/nginx/tasks/main.yml +++ b/nginx/tasks/main.yml @@ -66,7 +66,7 @@ - name: Include IP address whitelist task include: ip_whitelist.yml -- name: Copy evolinux_server_custom +- name: Copy evolinux_server_custom copy: src: nginx/snippets/evolinux_server_custom dest: /etc/nginx/snippets/evolinux_server_custom diff --git a/nginx/tasks/munin_vhost.yml b/nginx/tasks/munin_vhost.yml index ff9f8423..5aa137c9 100644 --- a/nginx/tasks/munin_vhost.yml +++ b/nginx/tasks/munin_vhost.yml @@ -18,15 +18,11 @@ shell: "chown --verbose www-data:munin /var/log/munin/munin-cgi-*" register: command_result changed_when: "'changed' in command_result.stdout" - args: - warn: no - name: Mode for munin-cgi is set to 660 shell: "chmod --verbose 660 /var/log/munin/munin-cgi-*" register: command_result changed_when: "'changed' in command_result.stdout" - args: - warn: no - name: Systemd unit for Munin-fcgi is installed copy: diff --git a/nodejs/files/yarn.asc b/nodejs/files/yarn.asc index e8d9cabb..03d9338a 100644 --- a/nodejs/files/yarn.asc +++ b/nodejs/files/yarn.asc @@ -158,86 +158,63 @@ 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 -=IgpF ------END PGP PUBLIC KEY BLOCK----- +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 +=e4wy +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/openvpn/tasks/debian.yml b/openvpn/tasks/debian.yml index b0201f0c..bee05d9e 100644 --- a/openvpn/tasks/debian.yml +++ b/openvpn/tasks/debian.yml @@ -89,13 +89,13 @@ stat: path: "/etc/default/minifirewall" check_mode: no - changed_when: false + changed_when: False register: minifirewall_config - name: Retrieve the default interface shell: "grep '^INT=' /etc/default/minifirewall | cut -d\\' -f 2" check_mode: no - changed_when: false + changed_when: False register: minifirewall_int when: minifirewall_config.stat.exists @@ -176,7 +176,7 @@ stat: path: "/etc/nagios/nrpe.d/evolix.cfg" check_mode: no - changed_when: false + changed_when: False register: nrpe_evolix_config - name: Install NRPE check dependencies @@ -290,6 +290,6 @@ The "push" parameter may be needed to push a route to the client, so that the client can access that route through OpenVPN. Take note of the generated CA password and store it in your password manager : {{ ca_pwd }} - + Press enter to exit when it's done. diff --git a/openvpn/tasks/openbsd.yml b/openvpn/tasks/openbsd.yml index b0e629be..e33923e1 100644 --- a/openvpn/tasks/openbsd.yml +++ b/openvpn/tasks/openbsd.yml @@ -132,7 +132,7 @@ - name: Configure NRPE OpenVPN check lineinfile: - dest: "/etc/nrpe.d/zzz_evolix.cfg" + dest: "/etc/nrpe.d/evolix.cfg" regexp: '^command\[check_openvpn\]=' line: "command[check_openvpn]=/usr/local/libexec/nagios/plugins/check_openvpn.pl -H 127.0.0.1 -p 1195 -P {{ management_pwd }}" create: yes @@ -218,6 +218,6 @@ The "push" parameter may be needed to push a route to the client, so that the client can access that route through OpenVPN. Take note of the generated CA password and store it in your password manager : {{ ca_pwd }} - + Press enter to exit when it's done. diff --git a/openvpn/templates/ovpn.conf.j2 b/openvpn/templates/ovpn.conf.j2 index d1b3c214..f65d43fd 100644 --- a/openvpn/templates/ovpn.conf.j2 +++ b/openvpn/templates/ovpn.conf.j2 @@ -9,5 +9,5 @@ nobind persist-key persist-tun -cipher AES-256-CBC +cipher AES-256-GCM diff --git a/packweb-apache/files/userlogrotate_jessie b/packweb-apache/files/userlogrotate_jessie deleted file mode 100644 index 339101a9..00000000 --- a/packweb-apache/files/userlogrotate_jessie +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -DATE=`/bin/date +"%d-%m-%Y"` -HOMEPREFIX="/home" - -rotate () { - mv $1 $1.$DATE - gzip $1.$DATE - touch $1 - chown $2 $1 - chmod g+r $1 -} - -user_for() { - homedir=`echo $1 | sed "s#\($HOMEPREFIX/\([^/]\+\)\).*#\1#"` - stat -L -c '%G' $homedir -} - -for log in access.log access-*.log error.log; do - for i in `ls -1 -d $HOMEPREFIX/*/log/$log 2>/dev/null | grep -v \.bak\.`; do - USER=`user_for $i` - rotate $i root:$USER - done -done - -for i in `ls -1 -d $HOMEPREFIX/*/log/php.log 2>/dev/null | grep -v \.bak\.`; do - USER=`user_for $i` - rotate $i www-$USER:$USER -done - -for log in production.log delayed_job.log development.log test.log; do - for i in `ls -1 -d $HOMEPREFIX/*/www/{,current/}log/$log 2>/dev/null | grep -v \.bak\.`; do - USER=`user_for $i` - rotate $i $USER:$USER - done -done - -apache2ctl restart > /dev/null diff --git a/packweb-apache/tasks/main.yml b/packweb-apache/tasks/main.yml index ff3cd9a7..c0a44935 100644 --- a/packweb-apache/tasks/main.yml +++ b/packweb-apache/tasks/main.yml @@ -65,19 +65,8 @@ - access.log - error.log -- name: "Install userlogrotate (jessie)" - copy: - src: userlogrotate_jessie - dest: /etc/cron.weekly/userlogrotate - mode: "0755" - when: ansible_distribution_release == "jessie" - -- name: "Install userlogrotate (Debian 9 or later)" - copy: - src: userlogrotate - dest: /etc/cron.weekly/userlogrotate - mode: "0755" - when: ansible_distribution_major_version is version('9', '>=') +- include_role: + name: userlogrotate - name: Force DIR_MODE to 0750 in /etc/adduser.conf lineinfile: @@ -102,3 +91,4 @@ - include: multiphp.yml when: packweb_multiphp_versions | length > 0 + diff --git a/packweb-apache/tasks/update_userlogrotate.yml b/packweb-apache/tasks/update_userlogrotate.yml deleted file mode 100644 index 1e8a6d85..00000000 --- a/packweb-apache/tasks/update_userlogrotate.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- - -- name: "Cherche l'emplacement de userlogrotate" - ansible.builtin.find: - path: /etc - patterns: userlogrotate - register: find_logrotate - -- name: "Met-à-jour userlogrotate" - ansible.builtin.copy: - src: userlogrotate - dest: "{{ item }}" - mode: "0755" - loop: "{{ find_logrotate.files }}" - when: find_logrotate.files | length>0 - diff --git a/php/README.md b/php/README.md index e0a194ac..e2190a3c 100644 --- a/php/README.md +++ b/php/README.md @@ -6,6 +6,8 @@ Installation and basic configuration of PHP Minimal configuration is in `tasks/main.yml` +Set variable `php_version` in your playbook. + ## Available variables The full list of variables (with default values) can be found in `defaults/main.yml`. diff --git a/php/files/reg.asc b/php/files/reg.asc new file mode 100644 index 00000000..3fadeb07 --- /dev/null +++ b/php/files/reg.asc @@ -0,0 +1,920 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.6 +Comment: Hostname: keyserver.ubuntu.com + +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 +BWcdiQ== +=iUyJ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/php/files/sury.preferences b/php/files/sury.preferences index 15aa9c16..adcc5918 100644 --- a/php/files/sury.preferences +++ b/php/files/sury.preferences @@ -1,4 +1,4 @@ -Package: php* libapache2-mod-php* libpcre2* libzip4* libgd* +Package: php* libapache2-mod-php* libpcre2* libzip4* libgd* libpcre3* Pin: origin packages.sury.org Pin-Priority: 999 diff --git a/php/handlers/main.yml b/php/handlers/main.yml index 079a14d5..206eab3a 100644 --- a/php/handlers/main.yml +++ b/php/handlers/main.yml @@ -5,6 +5,11 @@ name: php5-fpm state: restarted +- name: restart php5.6-fpm + service: + name: php5.6-fpm + state: restarted + - name: restart php7.0-fpm service: name: php7.0-fpm @@ -24,3 +29,8 @@ service: name: php8.1-fpm state: restarted + +- name: restart php8.2-fpm + service: + name: php8.2-fpm + state: restarted diff --git a/php/tasks/main_bookworm.yml b/php/tasks/main_bookworm.yml index 4dcde767..6ad64399 100644 --- a/php/tasks/main_bookworm.yml +++ b/php/tasks/main_bookworm.yml @@ -1,8 +1,11 @@ --- -- name: "Set php version to 8.1 (Debian 12)" +- name: "Set php version to 8.2 (Debian 12)" set_fact: - php_version: "8.1" + php_version: "8.2" + when: + - php_sury_enable == false + check_mode: no - name: "Set php config directories (Debian 12)" set_fact: @@ -19,9 +22,9 @@ php_apache_custom_ini_file: "{{ php_apache_conf_dir }}/zzz-evolinux-custom.ini" php_fpm_defaults_ini_file: "{{ php_fpm_conf_dir }}/z-evolinux-defaults.ini" php_fpm_custom_ini_file: "{{ php_fpm_conf_dir }}/zzz-evolinux-custom.ini" - php_fpm_debian_default_pool_file: "{{ php_fpm_pool_dir}}/www.conf" - php_fpm_default_pool_file: "{{ php_fpm_pool_dir}}/www-evolinux-defaults.conf" - php_fpm_default_pool_custom_file: "{{ php_fpm_pool_dir}}/www-evolinux-zcustom.conf" + php_fpm_debian_default_pool_file: "{{ php_fpm_pool_dir }}/www.conf" + php_fpm_default_pool_file: "{{ php_fpm_pool_dir }}/www-evolinux-defaults.conf" + php_fpm_default_pool_custom_file: "{{ php_fpm_pool_dir }}/www-evolinux-zcustom.conf" php_fpm_default_pool_socket: "/var/run/php/php{{ php_version }}-fpm.sock" php_fpm_service_name: "php{{ php_version }}-fpm" diff --git a/php/tasks/main_bullseye.yml b/php/tasks/main_bullseye.yml index 403a7b76..4cb185b7 100644 --- a/php/tasks/main_bullseye.yml +++ b/php/tasks/main_bullseye.yml @@ -1,18 +1,25 @@ --- +- name: "Set php version to 7.4 if Sury repo is not enabled" + set_fact: + php_version: "7.4" + when: + - php_sury_enable == False + check_mode: no + - name: "Set variables (Debian 11)" set_fact: - php_cli_defaults_ini_file: /etc/php/7.4/cli/conf.d/z-evolinux-defaults.ini - php_cli_custom_ini_file: /etc/php/7.4/cli/conf.d/zzz-evolinux-custom.ini - php_apache_defaults_ini_file: /etc/php/7.4/apache2/conf.d/z-evolinux-defaults.ini - php_apache_custom_ini_file: /etc/php/7.4/apache2/conf.d/zzz-evolinux-custom.ini - php_fpm_defaults_ini_file: /etc/php/7.4/fpm/conf.d/z-evolinux-defaults.ini - php_fpm_custom_ini_file: /etc/php/7.4/fpm/conf.d/zzz-evolinux-custom.ini - php_fpm_debian_default_pool_file: /etc/php/7.4/fpm/pool.d/www.conf - php_fpm_default_pool_file: /etc/php/7.4/fpm/pool.d/www-evolinux-defaults.conf - php_fpm_default_pool_custom_file: /etc/php/7.4/fpm/pool.d/www-evolinux-zcustom.conf - php_fpm_default_pool_socket: /var/run/php/php7.4-fpm.sock - php_fpm_service_name: php7.4-fpm + php_cli_defaults_ini_file: /etc/php/{{ php_version }}/cli/conf.d/z-evolinux-defaults.ini + php_cli_custom_ini_file: /etc/php/{{ php_version }}/cli/conf.d/zzz-evolinux-custom.ini + php_apache_defaults_ini_file: /etc/php/{{ php_version }}/apache2/conf.d/z-evolinux-defaults.ini + php_apache_custom_ini_file: /etc/php/{{ php_version }}/apache2/conf.d/zzz-evolinux-custom.ini + php_fpm_defaults_ini_file: /etc/php/{{ php_version }}/fpm/conf.d/z-evolinux-defaults.ini + php_fpm_custom_ini_file: /etc/php/{{ php_version }}/fpm/conf.d/zzz-evolinux-custom.ini + php_fpm_debian_default_pool_file: /etc/php/{{ php_version }}/fpm/pool.d/www.conf + php_fpm_default_pool_file: /etc/php/{{ php_version }}/fpm/pool.d/www-evolinux-defaults.conf + php_fpm_default_pool_custom_file: /etc/php/{{ php_version }}/fpm/pool.d/www-evolinux-zcustom.conf + php_fpm_default_pool_socket: /var/run/php/php{{ php_version }}-fpm.sock + php_fpm_service_name: php{{ php_version }}-fpm # Packages @@ -25,7 +32,6 @@ - php-imap - php-ldap - php-mysql - # php-mcrypt is no longer packaged for PHP 7.2 - php-pgsql - php-sqlite3 - php-curl @@ -54,8 +60,8 @@ - name: "Install PHP FPM packages (Debian 11)" apt: name: - - php-fpm - - php + - php{{ php_version }}-fpm + - php{{ php_version }} state: present when: php_fpm_enable @@ -67,12 +73,12 @@ mode: "0755" with_items: - /etc/php - - /etc/php/7.4 + - /etc/php/{{ php_version }} - include: config_cli.yml - name: "Enforce permissions on PHP cli directory (Debian 11)" file: - dest: /etc/php/7.4/cli + dest: /etc/php/{{ php_version }}/cli mode: "0755" - include: config_fpm.yml @@ -80,7 +86,7 @@ - name: "Enforce permissions on PHP fpm directory (Debian 11)" file: - dest: /etc/php/7.4/fpm + dest: /etc/php/{{ php_version }}/fpm mode: "0755" when: php_fpm_enable @@ -89,9 +95,9 @@ - name: "Enforce permissions on PHP apache2 directory (Debian 11)" file: - dest: /etc/php/7.4/apache2 + dest: /etc/php/{{ php_version }}/apache2 mode: "0755" when: php_apache_enable -- include: sury_post.yml - when: php_sury_enable +#- include: sury_post.yml +# when: php_sury_enable diff --git a/php/tasks/main_buster.yml b/php/tasks/main_buster.yml index 2fc4293e..24673378 100644 --- a/php/tasks/main_buster.yml +++ b/php/tasks/main_buster.yml @@ -1,18 +1,28 @@ --- +- debug: + msg: "{{ php_sury_enable }}" + +- name: "Set php version to 7.3 if Sury repo is not enabled" + set_fact: + php_version: "7.3" + when: + - php_sury_enable == false + check_mode: no + - name: "Set variables (Debian 10)" set_fact: - php_cli_defaults_ini_file: /etc/php/7.3/cli/conf.d/z-evolinux-defaults.ini - php_cli_custom_ini_file: /etc/php/7.3/cli/conf.d/zzz-evolinux-custom.ini - php_apache_defaults_ini_file: /etc/php/7.3/apache2/conf.d/z-evolinux-defaults.ini - php_apache_custom_ini_file: /etc/php/7.3/apache2/conf.d/zzz-evolinux-custom.ini - php_fpm_defaults_ini_file: /etc/php/7.3/fpm/conf.d/z-evolinux-defaults.ini - php_fpm_custom_ini_file: /etc/php/7.3/fpm/conf.d/zzz-evolinux-custom.ini - php_fpm_debian_default_pool_file: /etc/php/7.3/fpm/pool.d/www.conf - php_fpm_default_pool_file: /etc/php/7.3/fpm/pool.d/www-evolinux-defaults.conf - php_fpm_default_pool_custom_file: /etc/php/7.3/fpm/pool.d/www-evolinux-zcustom.conf - php_fpm_default_pool_socket: /var/run/php/php7.3-fpm.sock - php_fpm_service_name: php7.3-fpm + php_cli_defaults_ini_file: /etc/php/{{ php_version }}/cli/conf.d/zvolinux-defaults.ini + php_cli_custom_ini_file: /etc/php/{{ php_version }}/cli/conf.d/zzz-evolinux-custom.ini + php_apache_defaults_ini_file: /etc/php/{{ php_version }}/apache2/conf.d/z-evolinux-defaults.ini + php_apache_custom_ini_file: /etc/php/{{ php_version }}/apache2/conf.d/zzz-evolinux-custom.ini + php_fpm_defaults_ini_file: /etc/php/{{ php_version }}/fpm/conf.d/z-evolinux-defaults.ini + php_fpm_custom_ini_file: /etc/php/{{ php_version }}/fpm/conf.d/zzz-evolinux-custom.ini + php_fpm_debian_default_pool_file: /etc/php/{{ php_version }}/fpm/pool.d/www.conf + php_fpm_default_pool_file: /etc/php/{{ php_version }}/fpm/pool.d/www-evolinux-defaults.conf + php_fpm_default_pool_custom_file: /etc/php/{{ php_version }}/fpm/pool.d/www-evolinux-zcustom.conf + php_fpm_default_pool_socket: /var/run/php/php{{ php_version }}-fpm.sock + php_fpm_service_name: php{{ php_version }}-fpm # Packages @@ -54,8 +64,8 @@ - name: "Install PHP FPM packages (Debian 10)" apt: name: - - php-fpm - - php + - php{{ php_version }}-fpm + - php{{ php_version }} state: present when: php_fpm_enable | bool @@ -67,12 +77,12 @@ mode: "0755" loop: - /etc/php - - /etc/php/7.3 + - /etc/php/{{ php_version }} - include: config_cli.yml - name: "Enforce permissions on PHP cli directory (Debian 10)" file: - dest: /etc/php/7.3/cli + dest: /etc/php/{{ php_version }}/cli mode: "0755" - include: config_fpm.yml @@ -80,7 +90,7 @@ - name: "Enforce permissions on PHP fpm directory (Debian 10)" file: - dest: /etc/php/7.3/fpm + dest: /etc/php/{{ php_version }}/fpm mode: "0755" when: php_fpm_enable | bool @@ -89,9 +99,9 @@ - name: "Enforce permissions on PHP apache2 directory (Debian 10)" file: - dest: /etc/php/7.3/apache2 + dest: /etc/php/{{ php_version }}/apache2 mode: "0755" when: php_apache_enable | bool -- include: sury_post.yml - when: php_sury_enable | bool +#- include: sury_post.yml +# when: php_sury_enable | bool diff --git a/php/tasks/sury_pre.yml b/php/tasks/sury_pre.yml index a1dcbb0e..0d146555 100644 --- a/php/tasks/sury_pre.yml +++ b/php/tasks/sury_pre.yml @@ -8,6 +8,14 @@ owner: root group: root +- name: copy pub.evolix.org GPG key + copy: + src: pub_evolix.asc + dest: "{{ apt_keyring_dir }}/pub_evolix.asc" + mode: "0644" + owner: root + group: root + - name: Setup deb.sury.org repository - Install apt-transport-https apt: state: present @@ -17,6 +25,16 @@ copy: src: sury.preferences dest: /etc/apt/preferences.d/z-sury + when: + - ansible_distribution_release != "bullseye" + +- name: Setup pub.evolix.org repository - Add source list + apt_repository: + repo: "deb [signed-by={{ apt_keyring_dir }}/pub_evolix.asc] http://pub.evolix.org/evolix {{ ansible_distribution_release }}-php81 main" + filename: evolix-php + state: present + when: + - ansible_distribution_release == "bullseye" - name: Setup deb.sury.org repository - Add source list apt_repository: @@ -33,17 +51,16 @@ - name: "Override package list for Sury (Debian 9 or later)" set_fact: php_stretch_packages: - - php-cli - - php-gd - - php-intl - - php-imap - - php-ldap - - php-mysql + - php{{ php_version }}-cli + - php{{ php_version }}-gd + - php{{ php_version }}-intl + - php{{ php_version }}-imap + - php{{ php_version }}-ldap + - php{{ php_version }}-mysql # php-mcrypt is no longer packaged for PHP 7.2 - - php-pgsql - - php-gettext - - php-curl - - php-ssh2 - - composer - - libphp-phpmailer - when: ansible_distribution_release != "bullseye" + - php{{ php_version }}-pgsql + - php{{ php_version }}-gettext + - php{{ php_version }}-curl + - php{{ php_version }}-ssh2 +# - composer +# - libphp-phpmailer diff --git a/postfix/tasks/packmail.yml b/postfix/tasks/packmail.yml index 90d424b2..0407a72b 100644 --- a/postfix/tasks/packmail.yml +++ b/postfix/tasks/packmail.yml @@ -10,6 +10,20 @@ tags: - postfix +- name: make /var/lib/mailgraph accessible by www-data + file: + path: "/var/lib/mailgraph" + state: directory + owner: www-data + group: www-data + mode: '0755' + +- name: make sure a service Mailgraph is running + systemd: + name: mailgraph.service + state: started + enabled: true + - name: create packmail main.cf template: src: packmail_main.cf.j2 @@ -119,6 +133,6 @@ - name: update antispam list command: /usr/share/scripts/spam.sh - changed_when: false + changed_when: False tags: - postfix diff --git a/postfix/templates/evolinux_main.cf.j2 b/postfix/templates/evolinux_main.cf.j2 index 0c871546..5d298f1d 100644 --- a/postfix/templates/evolinux_main.cf.j2 +++ b/postfix/templates/evolinux_main.cf.j2 @@ -5,7 +5,7 @@ myhostname = {{ postfix_hostname }} alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases myorigin = $myhostname -mydestination = $myhostname localhost.localdomain localhost +mydestination = $myhostname localhost localhost.localdomain localhost.$mydomain relayhost = mynetworks = 127.0.0.0/8 mailbox_size_limit = 0 diff --git a/postfix/templates/packmail_main.cf.j2 b/postfix/templates/packmail_main.cf.j2 index 82b94afa..b803389e 100644 --- a/postfix/templates/packmail_main.cf.j2 +++ b/postfix/templates/packmail_main.cf.j2 @@ -74,7 +74,7 @@ myhostname = {{ ansible_fqdn }} # Liste des noms de domaine (ou IP) consideres comme local #par defaut, = $myhostname, localhost.$mydomain, localhost -mydestination = $myhostname localhost.localdomain localhost +mydestination = $myhostname localhost localhost.localdomain localhost.$mydomain # Indique le domaine apparaissant dans le courrier envoye #par defaut, = $myhostname @@ -294,7 +294,7 @@ slow_destination_concurrency_failed_cohort_limit = 100 # bounce : envoie les entetes de tous les message renvoyes # 2bounce : envoie les entetes de tous les messages renvoyes non delivres #par defaut, = resource, software -notify_classes = resource, software, bounce, 2bounce, delay, policy, protocol +#notify_classes = resource, software # A qui les reporter ? #Pour delay @@ -412,8 +412,10 @@ smtpd_sasl_path = private/auth-client # Amavis and OpenDKIM content_filter = smtp-amavis:[127.0.0.1]:10024 +smtp-amavis_destination_concurrency_failed_cohort_limit = 0 smtpd_milters = inet:[127.0.0.1]:8891 non_smtpd_milters = inet:[127.0.0.1]:8891 +smtp-amavis_destination_concurrency_failed_cohort_limit = 0 {% if postfix_slow_transport_include == True %} # Slow transports configuration @@ -430,3 +432,4 @@ slow_destination_concurrency_failed_cohort_limit = 100 slow_destination_recipient_limit = 25 transport_maps = hash:$config_directory/transport {% endif %} + diff --git a/postfix/templates/virtual_aliases.cf.j2 b/postfix/templates/virtual_aliases.cf.j2 index 1a6e5f9c..97f4baf3 100644 --- a/postfix/templates/virtual_aliases.cf.j2 +++ b/postfix/templates/virtual_aliases.cf.j2 @@ -2,4 +2,3 @@ search_base = {{ ldap_suffix }} query_filter = (&(mailacceptinggeneralid=%u@%d)(isActive=TRUE)) result_attribute = maildrop version = 3 -aliases_scope = sub diff --git a/postgresql/defaults/main.yml b/postgresql/defaults/main.yml index ffc3007c..634ea4f1 100644 --- a/postgresql/defaults/main.yml +++ b/postgresql/defaults/main.yml @@ -7,6 +7,7 @@ postgresql_shared_buffers: "{{ (ansible_memtotal_mb * 0.25) | int }}MB" postgresql_work_mem: 8MB postgresql_random_page_cost: 1.5 postgresql_effective_cache_size: "{{ (ansible_memtotal_mb * 0.5) | int }}MB" +postgresql_max_connections: None # Binding postgresql_listen_addresses: diff --git a/postgresql/files/logrotate_postgresql b/postgresql/files/logrotate_postgresql index a9306aa3..656e2991 100644 --- a/postgresql/files/logrotate_postgresql +++ b/postgresql/files/logrotate_postgresql @@ -1,11 +1,10 @@ /var/log/postgresql/*.log { + su postgres postgres daily rotate 10 copytruncate nodelaycompress compress - notifempty missingok - su root root + dateext } - diff --git a/postgresql/handlers/main.yml b/postgresql/handlers/main.yml index 5275b6a1..15a773dd 100644 --- a/postgresql/handlers/main.yml +++ b/postgresql/handlers/main.yml @@ -16,7 +16,8 @@ daemon_reload: yes - name: reload systemd - command: systemctl daemon-reload + systemd: + daemon-reload: yes - name: Restart minifirewall command: /etc/init.d/minifirewall restart diff --git a/postgresql/tasks/config.yml b/postgresql/tasks/config.yml index f29026df..966f0930 100644 --- a/postgresql/tasks/config.yml +++ b/postgresql/tasks/config.yml @@ -17,13 +17,13 @@ - name: Allow conf.d/*.conf files to be included in PostgreSQL configuration lineinfile: - name: "/etc/postgresql/{{postgresql_version}}/main/postgresql.conf" + name: "/etc/postgresql/{{ postgresql_version }}/main/postgresql.conf" line: include_dir = 'conf.d' notify: restart postgresql - name: Create conf.d directory file: - name: "/etc/postgresql/{{postgresql_version}}/main/conf.d/" + name: "/etc/postgresql/{{ postgresql_version }}/main/conf.d/" state: directory owner: postgres group: postgres @@ -32,7 +32,7 @@ - name: Copy PostgreSQL config file template: src: postgresql.conf.j2 - dest: "/etc/postgresql/{{postgresql_version}}/main/conf.d/zz-evolinux.conf" + dest: "/etc/postgresql/{{ postgresql_version }}/main/conf.d/zz-evolinux.conf" owner: postgres group: postgres mode: "0644" diff --git a/postgresql/tasks/munin.yml b/postgresql/tasks/munin.yml index 227304c8..feb0b678 100644 --- a/postgresql/tasks/munin.yml +++ b/postgresql/tasks/munin.yml @@ -12,8 +12,8 @@ - name: Add Munin plugins for PostgreSQL file: state: link - src: '/usr/share/munin/plugins/{{item}}' - dest: '/etc/munin/plugins/{{item}}' + src: '/usr/share/munin/plugins/{{ item }}' + dest: '/etc/munin/plugins/{{ item }}' loop: - postgres_bgwriter - postgres_checkpoints @@ -26,8 +26,8 @@ - name: Add Munin plugins for PostgreSQL (for specific databases) file: state: link - src: '/usr/share/munin/plugins/{{item[0]}}' - dest: '/etc/munin/plugins/{{item[0]}}{{item[1]}}' + src: '/usr/share/munin/plugins/{{ item[0] }}' + dest: '/etc/munin/plugins/{{ item[0] }}{{ item[1] }}' loop: "{{ _plugins | product(_databases) | list }}" vars: _plugins: diff --git a/postgresql/tasks/nrpe.yml b/postgresql/tasks/nrpe.yml index 4aea2d81..833ab1ea 100644 --- a/postgresql/tasks/nrpe.yml +++ b/postgresql/tasks/nrpe.yml @@ -42,7 +42,7 @@ lineinfile: name: /etc/nagios/nrpe.d/evolix.cfg regexp: '^command\[check_pgsql\]=' - line: 'command[check_pgsql]=/usr/lib/nagios/plugins/check_pgsql -H localhost -l nrpe -p "{{postgresql_nrpe_password.stdout}}"' + line: 'command[check_pgsql]=/usr/lib/nagios/plugins/check_pgsql -H localhost -l nrpe -p "{{ postgresql_nrpe_password.stdout }}"' notify: restart nagios-nrpe-server when: postgresql_create_nrpe_user is changed when: nrpe_evolix_config.stat.exists diff --git a/postgresql/tasks/packages_bookworm.yml b/postgresql/tasks/packages_bookworm.yml index 2a78b967..8db31b9b 100644 --- a/postgresql/tasks/packages_bookworm.yml +++ b/postgresql/tasks/packages_bookworm.yml @@ -1,5 +1,5 @@ --- - + - name: "Set variables (Debian 12)" set_fact: postgresql_version: '15' @@ -11,6 +11,6 @@ - name: Install postgresql package apt: name: - - "postgresql-{{postgresql_version}}" + - "postgresql-{{ postgresql_version }}" - pgtop - libdbd-pg-perl diff --git a/postgresql/tasks/packages_bullseye.yml b/postgresql/tasks/packages_bullseye.yml index 1b4cb0ac..e825b799 100644 --- a/postgresql/tasks/packages_bullseye.yml +++ b/postgresql/tasks/packages_bullseye.yml @@ -1,5 +1,5 @@ --- - + - name: "Set variables (Debian 11)" set_fact: postgresql_version: '13' @@ -11,6 +11,6 @@ - name: Install postgresql package apt: name: - - "postgresql-{{postgresql_version}}" + - "postgresql-{{ postgresql_version }}" - pgtop - libdbd-pg-perl diff --git a/postgresql/tasks/packages_buster.yml b/postgresql/tasks/packages_buster.yml index 815e741d..7ecf11be 100644 --- a/postgresql/tasks/packages_buster.yml +++ b/postgresql/tasks/packages_buster.yml @@ -11,6 +11,6 @@ - name: Install postgresql package apt: name: - - "postgresql-{{postgresql_version}}" + - "postgresql-{{ postgresql_version }}" - pgtop - libdbd-pg-perl diff --git a/postgresql/tasks/packages_jessie.yml b/postgresql/tasks/packages_jessie.yml index b9f9b31b..60bb2247 100644 --- a/postgresql/tasks/packages_jessie.yml +++ b/postgresql/tasks/packages_jessie.yml @@ -10,8 +10,8 @@ - name: Install postgresql package apt: - name: '{{item}}' + name: '{{ item }}' loop: - - "postgresql-{{postgresql_version}}" + - "postgresql-{{ postgresql_version }}" - ptop - libdbd-pg-perl diff --git a/postgresql/tasks/packages_stretch.yml b/postgresql/tasks/packages_stretch.yml index a43c313b..45b8840c 100644 --- a/postgresql/tasks/packages_stretch.yml +++ b/postgresql/tasks/packages_stretch.yml @@ -11,6 +11,6 @@ - name: Install postgresql package apt: name: - - "postgresql-{{postgresql_version}}" + - "postgresql-{{ postgresql_version }}" - ptop - libdbd-pg-perl diff --git a/postgresql/tasks/pgdg-repo.yml b/postgresql/tasks/pgdg-repo.yml index f03ae52f..ef467f97 100644 --- a/postgresql/tasks/pgdg-repo.yml +++ b/postgresql/tasks/pgdg-repo.yml @@ -31,12 +31,12 @@ - name: Add PGDG repository apt_repository: - repo: "deb [signed-by={{ apt_keyring_dir }}/postgresql.asc] http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main" + repo: "deb [signed-by={{ apt_keyring_dir }}/postgresql.asc] http://apt.postgresql.org/pub/repos/apt/ {{ ansible_distribution_release }}-pgdg main" update_cache: yes - name: Remove unsigned PGDG repository apt_repository: - repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main" + repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ ansible_distribution_release }}-pgdg main" update_cache: yes state: absent diff --git a/postgresql/templates/postgresql.conf.j2 b/postgresql/templates/postgresql.conf.j2 index 9adce0b4..2f39937f 100644 --- a/postgresql/templates/postgresql.conf.j2 +++ b/postgresql/templates/postgresql.conf.j2 @@ -9,6 +9,9 @@ checkpoint_segments = 30 {% else %} max_wal_size = 15GB {% endif %} +{% if postgresql_max_connections and postgresql_max_connections | int > 0 %} +max_connections = {{ postgresql_max_connections }} +{% endif %} checkpoint_completion_target = 0.9 random_page_cost = {{ postgresql_random_page_cost }} @@ -20,6 +23,8 @@ log_checkpoints = on log_lock_waits = on log_temp_files = 5MB log_autovacuum_min_duration = 1s +log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h ' +lc_messages = 'C' # Locales lc_monetary = 'fr_FR.UTF-8' diff --git a/postgresql/templates/postgresql.pref.j2 b/postgresql/templates/postgresql.pref.j2 index 74196cf6..5d252e05 100644 --- a/postgresql/templates/postgresql.pref.j2 +++ b/postgresql/templates/postgresql.pref.j2 @@ -1,3 +1,3 @@ -Package: postgresql-{{postgresql_version}} postgresql-client-common postgresql-common libpq5 ptop -Pin: release a={{ansible_distribution_release}}-pgdg +Package: postgresql-{{ postgresql_version }} postgresql-client-common postgresql-common libpq5 ptop +Pin: release a={{ ansible_distribution_release }}-pgdg Pin-Priority: 999 diff --git a/postgresql/tests/test.yml b/postgresql/tests/test.yml index 438eddee..88714dd1 100644 --- a/postgresql/tests/test.yml +++ b/postgresql/tests/test.yml @@ -6,7 +6,7 @@ apt: name: locales state: present - changed_when: false + changed_when: False - name: Setting default locales lineinfile: @@ -14,7 +14,7 @@ line: "{{ item }}" create: yes state: present - changed_when: false + changed_when: False loop: - "en_US.UTF-8 UTF-8" - "fr_FR ISO-8859-1" @@ -23,7 +23,7 @@ - name: Reconfigure locales command: /usr/sbin/locale-gen - changed_when: false + changed_when: False when: test_locales is changed roles: diff --git a/proftpd/tasks/account.yml b/proftpd/tasks/account.yml index a03fd1f1..cfe82156 100644 --- a/proftpd/tasks/account.yml +++ b/proftpd/tasks/account.yml @@ -1,7 +1,7 @@ --- - name: Check if FTP account exist command: grep "^{{ proftpd_name }}:" /etc/proftpd/vpasswd - failed_when: false + failed_when: False check_mode: no changed_when: check_ftp_account.rc != 0 register: check_ftp_account @@ -36,7 +36,7 @@ register: hashed_ftp_password check_mode: no when: check_ftp_account.rc == 0 - changed_when: false + changed_when: False tags: - proftpd @@ -45,7 +45,7 @@ proftpd_password: "{{ hashed_ftp_password.stdout }}" check_mode: no when: check_ftp_account.rc == 0 - changed_when: false + changed_when: False tags: - proftpd diff --git a/proftpd/tasks/accounts.yml b/proftpd/tasks/accounts.yml index 4db814ef..b5cc5e85 100644 --- a/proftpd/tasks/accounts.yml +++ b/proftpd/tasks/accounts.yml @@ -70,7 +70,7 @@ loop_control: loop_var: _proftpd_account notify: restart proftpd - when: + when: - proftpd_sftp_enable | bool - proftpd_sftp_use_publickeys | bool tags: diff --git a/proftpd/tasks/accounts_password.yml b/proftpd/tasks/accounts_password.yml index 01517083..3ae37c88 100644 --- a/proftpd/tasks/accounts_password.yml +++ b/proftpd/tasks/accounts_password.yml @@ -1,7 +1,7 @@ --- - name: Check if FTP account exist command: grep "^{{ item.name }}:" /etc/proftpd/vpasswd - failed_when: false + failed_when: False check_mode: no changed_when: check_ftp_account.rc != 0 register: check_ftp_account @@ -12,7 +12,7 @@ shell: grep "^{{ item.name }}:" /etc/proftpd/vpasswd | cut -d':' -f2 register: protftpd_cur_password check_mode: no - changed_when: false + changed_when: False - name: Set password for this account set_fact: diff --git a/proftpd/tasks/main.yml b/proftpd/tasks/main.yml index f45958a9..3afc69cb 100644 --- a/proftpd/tasks/main.yml +++ b/proftpd/tasks/main.yml @@ -56,7 +56,7 @@ owner: root group: root notify: restart proftpd - when: + when: - proftpd_sftp_enable | bool - proftpd_sftp_use_publickeys | bool tags: diff --git a/rbenv/tasks/main.yml b/rbenv/tasks/main.yml index de366e78..8294cfdc 100644 --- a/rbenv/tasks/main.yml +++ b/rbenv/tasks/main.yml @@ -88,8 +88,6 @@ - name: "is Ruby {{ rbenv_ruby_version }} available for {{ username }} ?" shell: /bin/bash -lc "rbenv versions | grep {{ rbenv_ruby_version }}" - args: - warn: no failed_when: False changed_when: False check_mode: False @@ -101,8 +99,6 @@ - name: "Ruby {{ rbenv_ruby_version }} is available for {{ username }} (be patient... could be long)" shell: /bin/bash -lc "TMPDIR=~/tmp rbenv install {{ rbenv_ruby_version }}" - args: - warn: no when: ruby_installed.rc != 0 become_user: "{{ username }}" become: yes @@ -111,8 +107,6 @@ - name: "is Ruby {{ rbenv_ruby_version }} selected for {{ username }} ?" shell: /bin/bash -lc "rbenv version | cut -d ' ' -f 1 | grep -Fx '{{ rbenv_ruby_version }}'" - args: - warn: no register: ruby_selected changed_when: False failed_when: False @@ -124,8 +118,6 @@ - name: "select Ruby {{ rbenv_ruby_version }} for {{ username }}" shell: /bin/bash -lc "rbenv global {{ rbenv_ruby_version }} && rbenv rehash" - args: - warn: no when: ruby_selected.rc != 0 become_user: "{{ username }}" become: yes diff --git a/redis/tasks/main.yml b/redis/tasks/main.yml index d9a57bb2..24315b42 100644 --- a/redis/tasks/main.yml +++ b/redis/tasks/main.yml @@ -36,7 +36,7 @@ - name: Get Redis version shell: "redis-server -v | grep -Eo '(v=\\S+)' | cut -d'=' -f 2 | grep -E '^([0-9]|\\.)+$'" - changed_when: false + changed_when: False check_mode: no register: _redis_installed_version tags: diff --git a/redmine/tasks/mysql.yml b/redmine/tasks/mysql.yml index 6c40a338..5f1f6631 100644 --- a/redmine/tasks/mysql.yml +++ b/redmine/tasks/mysql.yml @@ -4,7 +4,7 @@ register: redmine_get_mysql_password check_mode: no changed_when: False - failed_when: false + failed_when: False tags: - redmine diff --git a/redmine/tasks/user.yml b/redmine/tasks/user.yml index 932e049c..dc959db1 100644 --- a/redmine/tasks/user.yml +++ b/redmine/tasks/user.yml @@ -41,4 +41,4 @@ - name: Enable systemd user mode command: "loginctl enable-linger {{ redmine_user }}" - changed_when: false + changed_when: False diff --git a/remount-usr/handlers/main.yml b/remount-usr/handlers/main.yml index 5f197e78..854a8883 100644 --- a/remount-usr/handlers/main.yml +++ b/remount-usr/handlers/main.yml @@ -1,6 +1,4 @@ --- - name: remount usr command: "mount -o remount /usr" - failed_when: false - args: - warn: no + failed_when: False \ No newline at end of file diff --git a/remount-usr/tasks/main.yml b/remount-usr/tasks/main.yml index 1bfedc64..e4cf9d36 100644 --- a/remount-usr/tasks/main.yml +++ b/remount-usr/tasks/main.yml @@ -10,8 +10,6 @@ - name: "mount /usr in rw" command: 'mount -o remount,rw /usr' - args: - warn: no changed_when: False when: usr_partition.rc == 0 notify: remount usr diff --git a/spamassasin/tasks/main.yml b/spamassasin/tasks/main.yml index a7568391..a2cbaf9a 100644 --- a/spamassasin/tasks/main.yml +++ b/spamassasin/tasks/main.yml @@ -87,7 +87,7 @@ - name: update SpamAssasin's rules command: "/usr/share/scripts/sa-update.sh" - changed_when: false + changed_when: False tags: - spamassassin diff --git a/squid/tasks/main.yml b/squid/tasks/main.yml index 4a3cab4d..5cb60ea9 100644 --- a/squid/tasks/main.yml +++ b/squid/tasks/main.yml @@ -24,7 +24,7 @@ - name: Fetch packages package_facts: - manager: auto + manager: auto - debug: var: ansible_facts.packages[squid_daemon_name] diff --git a/tomcat-instance/tasks/check.yml b/tomcat-instance/tasks/check.yml index eff9d236..b9426a33 100644 --- a/tomcat-instance/tasks/check.yml +++ b/tomcat-instance/tasks/check.yml @@ -6,7 +6,7 @@ - name: Check use of gid command: id -ng "{{ tomcat_instance_port }}" register: check_port_gid - changed_when: false + changed_when: False failed_when: - check_port_gid | success - check_port_gid.stdout != "{{ tomcat_instance_name }}" @@ -14,7 +14,7 @@ - name: Check use of uid command: id -nu "{{ tomcat_instance_port }}" register: check_port_uid - changed_when: false + changed_when: False failed_when: - check_port_uid | success - check_port_uid.stdout != "{{ tomcat_instance_name }}" diff --git a/tomcat-instance/tasks/systemd.yml b/tomcat-instance/tasks/systemd.yml index 7558bbaa..c3a6a877 100644 --- a/tomcat-instance/tasks/systemd.yml +++ b/tomcat-instance/tasks/systemd.yml @@ -1,7 +1,7 @@ --- - name: Enable systemd user mode command: "loginctl enable-linger {{ tomcat_instance_name }}" - changed_when: false + changed_when: False - name: Set systemd conf var lineinfile: diff --git a/userlogrotate/files/userlogrotate b/userlogrotate/files/userlogrotate new file mode 100644 index 00000000..dfa51738 --- /dev/null +++ b/userlogrotate/files/userlogrotate @@ -0,0 +1,58 @@ +#!/bin/bash + +DATE="$(/bin/date +"%Y-%m-%d")" +HOMEPREFIX="/home" + +rotate () { + mv $1 $1.$DATE + touch $1 + chown $2 $1 + chmod g+r $1 +} + +user_for() { + homedir="$(echo $1 | sed "s#\($HOMEPREFIX/\([^/]\+\)\).*#\1#")" + stat -L -c '%G' $homedir +} + +for log in access.log access-*.log error.log; do + for i in $(ls -1 -d $HOMEPREFIX/*/log/$log 2>/dev/null | grep -v \.bak\.); do + USER="$(user_for $i)" + rotate $i root:$USER + done +done + +for log in production.log delayed_job.log development.log test.log; do + for i in $(ls -1 -d $HOMEPREFIX/*/www/{,current/}log/$log 2>/dev/null | grep -v \.bak\.); do + USER="$(user_for $i)" + rotate $i $USER:$USER + done +done + +test -x /usr/sbin/apache2ctl && if /etc/init.d/apache2 status > /dev/null ; then \ + /etc/init.d/apache2 reload > /dev/null; \ +fi; + +test -x /usr/sbin/nginx && invoke-rc.d nginx rotate >/dev/null 2>&1 + +# Zipping is done after web server reload, so that the file descriptor is released. +# Else, an error is raised (gzip file size changed while zipping) +# and logs written during the zipping process might be lost. + +for log in access.log*[!\.gz] access-*.log*[!\.gz] error.log*[!\.gz]; do + for i in $(ls -1 -d $HOMEPREFIX/*/log/$log 2>/dev/null | grep -v \.bak\.); do + if test -f "$i"; then + gzip "$i" + fi + done +done + +for log in production.log*[!\.gz] delayed_job.log*[!\.gz] development.log*[!\.gz] test.log*[!\.gz]; do + for i in $(ls -1 -d $HOMEPREFIX/*/www/{,current/}log/$log 2>/dev/null | grep -v \.bak\.); do + if test -f "$i"; then + gzip "$i" + fi + done +done + +exit 0 \ No newline at end of file diff --git a/packweb-apache/files/userlogrotate b/userlogrotate/files/userlogrotate_jessie similarity index 70% rename from packweb-apache/files/userlogrotate rename to userlogrotate/files/userlogrotate_jessie index 7ed42668..347736fc 100644 --- a/packweb-apache/files/userlogrotate +++ b/userlogrotate/files/userlogrotate_jessie @@ -22,6 +22,11 @@ for log in access.log access-*.log error.log; do done done +for i in `ls -1 -d $HOMEPREFIX/*/log/php.log 2>/dev/null | grep -v \.bak\.`; do + USER=`user_for $i` + rotate $i www-$USER:$USER +done + for log in production.log delayed_job.log development.log test.log; do for i in `ls -1 -d $HOMEPREFIX/*/www/{,current/}log/$log 2>/dev/null | grep -v \.bak\.`; do USER=`user_for $i` @@ -29,27 +34,26 @@ for log in production.log delayed_job.log development.log test.log; do done done -test -x /usr/sbin/apache2ctl && if /etc/init.d/apache2 status > /dev/null ; then \ - /etc/init.d/apache2 reload > /dev/null; \ -fi; - -test -x /usr/sbin/nginx && invoke-rc.d nginx rotate >/dev/null 2>&1 +apache2ctl restart > /dev/null # Zipping is done after web server reload, so that the file descriptor is released. # Else, an error is raised (gzip file size changed while zipping) # and logs written during the zipping process might be lost. -for log in access.log access-*.log error.log; do +for log in access.log*[!\.gz] access-*.log*[!\.gz] error.log*[!\.gz]; do for i in `ls -1 -d $HOMEPREFIX/*/log/$log 2>/dev/null | grep -v \.bak\.`; do - gzip $i + if test -f "$i"; then + gzip "$i" + fi done done -for log in production.log delayed_job.log development.log test.log; do +for log in production.log*[!\.gz] delayed_job.log*[!\.gz] development.log*[!\.gz] test.log*[!\.gz]; do for i in `ls -1 -d $HOMEPREFIX/*/www/{,current/}log/$log 2>/dev/null | grep -v \.bak\.`; do - gzip $i + if test -f "$i"; then + gzip "$i" + fi done done -# we want exit 0 -true + diff --git a/userlogrotate/tasks/main.yml b/userlogrotate/tasks/main.yml new file mode 100644 index 00000000..2642186c --- /dev/null +++ b/userlogrotate/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: "Is userlogrotate present ?" + ansible.builtin.find: + paths: ["/etc/cron.weekly", "/etc/cron.daily"] + patterns: ["userlogrotate"] + register: find_logrotate + check_mode: no + +- name: "Update userlogrotate" + ansible.builtin.copy: + src: userlogrotate + dest: "{{ item.path }}" + mode: "0755" + loop: "{{ find_logrotate.files }}" + when: find_logrotate.files | length>0 + +- name: "Install userlogrotate (jessie)" + copy: + src: userlogrotate_jessie + dest: /etc/cron.weekly/userlogrotate + mode: "0755" + when: + - ansible_distribution_release == "jessie" + - find_logrotate.files | length==0 + +- name: "Install userlogrotate (Debian 9 or later)" + copy: + src: userlogrotate + dest: /etc/cron.weekly/userlogrotate + mode: "0755" + when: + - ansible_distribution_major_version is version('9', '>=') + - find_logrotate.files | length==0 + diff --git a/varnish/defaults/main.yml b/varnish/defaults/main.yml index acc9b114..ec8a251e 100644 --- a/varnish/defaults/main.yml +++ b/varnish/defaults/main.yml @@ -17,6 +17,7 @@ varnish_jail: "unix,user=vcache" varnish_additional_options: "" varnish_config_file: /etc/varnish/default.vcl +varnish_update_config: True varnish_secret_file: /etc/varnish/secret varnish_tmp_dir: /var/tmp-vcache \ No newline at end of file diff --git a/varnish/handlers/main.yml b/varnish/handlers/main.yml index 7f9fd3ff..6e47bc10 100644 --- a/varnish/handlers/main.yml +++ b/varnish/handlers/main.yml @@ -12,7 +12,8 @@ daemon_reload: yes - name: reload systemd - command: systemctl daemon-reload + systemd: + daemon-reload: yes - name: restart munin-node service: diff --git a/varnish/tasks/main.yml b/varnish/tasks/main.yml index 43399f0d..cca302bb 100644 --- a/varnish/tasks/main.yml +++ b/varnish/tasks/main.yml @@ -122,8 +122,8 @@ - name: Patch logrotate conf replace: name: /etc/logrotate.d/varnish - regexp: '^(\s+)(/usr/sbin/invoke-rc.d {{item}}.*)' - replace: '\1systemctl -q is-active {{item}} && \2' + regexp: '^(\s+)(/usr/sbin/invoke-rc.d {{ item }}.*)' + replace: '\1systemctl -q is-active {{ item }} && \2' loop: - varnishlog - varnishncsa @@ -137,6 +137,7 @@ dest: "{{ varnish_config_file }}" mode: "0644" force: yes + when: "{{ varnish_update_config }}" loop: "{{ query('first_found', templates) }}" vars: templates: diff --git a/varnish/tasks/munin.yml b/varnish/tasks/munin.yml index 1ccf5f88..77637a98 100644 --- a/varnish/tasks/munin.yml +++ b/varnish/tasks/munin.yml @@ -33,7 +33,7 @@ - name: Enable varnish5 munin plugin file: src: /usr/local/share/munin/plugins/varnish5_ - dest: "/etc/munin/plugins/varnish5_{{item}}" + dest: "/etc/munin/plugins/varnish5_{{ item }}" state: link loop: - memory_usage diff --git a/vrrpd/tasks/ip.yml b/vrrpd/tasks/ip.yml index 273c882e..e58595a2 100644 --- a/vrrpd/tasks/ip.yml +++ b/vrrpd/tasks/ip.yml @@ -17,6 +17,6 @@ daemon_reload: yes enabled: yes state: "{{ vrrp_address.state }}" - when: + when: - vrrp_systemd_unit is changed - not ansible_check_mode \ No newline at end of file diff --git a/webapps/evoadmin-web/tasks/user.yml b/webapps/evoadmin-web/tasks/user.yml index bbad1b8f..0d453e9a 100644 --- a/webapps/evoadmin-web/tasks/user.yml +++ b/webapps/evoadmin-web/tasks/user.yml @@ -80,7 +80,7 @@ - include_role: name: evolix/remount-usr - when: evoadmin_scripts_dir is search ("/usr") + when: evoadmin_scripts_dir is search("/usr") - name: "Create {{ evoadmin_scripts_dir }}" file: @@ -100,8 +100,6 @@ register: command_result changed_when: "'changed' in command_result.stdout" # failed_when: False - args: - warn: False - name: Add evoadmin sudoers file template: diff --git a/webapps/nextcloud/defaults/main.yml b/webapps/nextcloud/defaults/main.yml index 5c586620..c6e0a316 100644 --- a/webapps/nextcloud/defaults/main.yml +++ b/webapps/nextcloud/defaults/main.yml @@ -9,7 +9,7 @@ nextcloud_domains: [] nextcloud_home: "/home/{{ nextcloud_user }}" nextcloud_webroot: "{{ nextcloud_home }}/nextcloud" -nextcloud_data: "{{ nextcloud_webroot }}/data" +nextcloud_data: "{{ nextcloud_home }}/data" nextcloud_db_user: "{{ nextcloud_user }}" nextcloud_db_name: "{{ nextcloud_instance_name }}" diff --git a/webapps/nextcloud/templates/apache-vhost.conf.j2 b/webapps/nextcloud/templates/apache-vhost.conf.j2 index ff9f621c..556fa4cb 100644 --- a/webapps/nextcloud/templates/apache-vhost.conf.j2 +++ b/webapps/nextcloud/templates/apache-vhost.conf.j2 @@ -5,9 +5,11 @@ ServerAlias {{ domain_alias }} {% endfor %} + # SSL # SSLEngine on # SSLCertificateFile /etc/letsencrypt/live/{{ nextcloud_instance_name }}/fullchain.pem # SSLCertificateKeyFile /etc/letsencrypt/live/{{ nextcloud_instance_name }}/privkey.pem + # Header always set Strict-Transport-Security "max-age=15552000" DocumentRoot {{ nextcloud_webroot }}/ @@ -21,6 +23,15 @@ + + Require all denied + AllowOverride None + + + Dav off + + + # SSL Redirect # RewriteEngine On # RewriteCond %{HTTPS} !=on diff --git a/webapps/wordpress/tasks/main.yml b/webapps/wordpress/tasks/main.yml index e1f442c0..32eda170 100644 --- a/webapps/wordpress/tasks/main.yml +++ b/webapps/wordpress/tasks/main.yml @@ -25,7 +25,7 @@ - name: Generate random password command: apg -n1 -m 12 -M LCN register: shell_password - changed_when: false + changed_when: False - name: Read mysql config from .my.cnf set_fact: @@ -48,13 +48,13 @@ - name: Configure site shell: '{{ wordpress_wpcli }} core install --url={{ wordpress_host | quote }} --title={{ wordpress_title | quote }} --admin_user=admin --admin_password="{{ admin_pwd | quote }}" --admin_email={{ wordpress_email }} --skip-email' - changed_when: false + changed_when: False - name: Check if Wordpress is up to date shell: '{{ wordpress_wpcli }} core check-update | grep -q Success' register: check_version check_mode: no - failed_when: false + failed_when: False changed_when: check_version.rc == 1 - name: Update Wordpress @@ -65,17 +65,17 @@ - name: Install default plugin shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} || {{ wordpress_wpcli }} plugin install {{ item }}' - changed_when: false + changed_when: False loop: "{{ wordpress_plugins }}" - name: Update default plugins shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin update {{ item }}' - changed_when: false + changed_when: False loop: "{{ wordpress_plugins }}" - name: Activate default plugins shell: '{{ wordpress_wpcli }} plugin is-installed {{ item }} && {{ wordpress_wpcli }} plugin activate {{ item }}' - changed_when: false + changed_when: False loop: "{{ wordpress_plugins }}" - name: Send a summary mail