diff --git a/CHANGELOG.md b/CHANGELOG.md index 33998f64..c391df9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,39 @@ The **patch** part changes incrementally at each release. ### Security +## [10.3.0] 2020-12-21 + +### Added + +* dovecot: Update munin plugin & configure it +* dovecot: vmail uid/gid are configurable +* evoacme: variable to disable Debian version check (default: False) +* kvm-host: Add drbd role dependency (toggleable with kvm_install_drbd) +* minifirewall: upstream release 20.12 +* minifirewall: add variables to force upgrade the script and the config (default: False) +* mysql: install save_mysql_processlist script +* nextcloud: New role to setup a nextcloud instance +* redis: variable to force use of port 6379 in instances mode +* redis: check maxmemory in NRPE check +* lxc-php: Allow php containers to contact local MySQL with localhost +* varnish: config file name is configurable + +### Changed + +* Create system users for vmail (dovecot) and evoadmin +* apt: disable APT Periodic +* evoacme: upstream release 20.12 +* evocheck: upstream release 20.12 +* evolinux-users: improve uid/login checks +* tomcat-instance: fail if uid already exists +* varnish: change template name for better readability +* varnish: no threadpool delay by default +* varnish: no custom reload script for Debian 10 and later + +### Fixed + +* cerbot: parse HAProxy config file only if HAProxy is found + ## [10.2.0] 2020-09-17 ### Added diff --git a/apt/tasks/config.yml b/apt/tasks/config.yml index 988aac7a..48892b9e 100644 --- a/apt/tasks/config.yml +++ b/apt/tasks/config.yml @@ -11,6 +11,7 @@ with_items: - { line: "APT::Install-Recommends \"false\";", regexp: 'APT::Install-Recommends' } - { line: "APT::Install-Suggests \"false\";", regexp: 'APT::Install-Suggests' } + - { line: "APT::Periodic::Enable \"0\";", regexp: 'APT::Periodic::Enable' } when: apt_evolinux_config tags: - apt diff --git a/certbot/files/hooks/haproxy.sh b/certbot/files/hooks/haproxy.sh index 1a7f5d4e..932a3e90 100644 --- a/certbot/files/hooks/haproxy.sh +++ b/certbot/files/hooks/haproxy.sh @@ -56,6 +56,9 @@ main() { fi if daemon_found_and_running; then + readonly haproxy_config_file="/etc/haproxy/haproxy.cfg" + readonly haproxy_cert_dir=$(detect_haproxy_cert_dir) + if found_renewed_lineage; then haproxy_cert_file="${haproxy_cert_dir}/$(basename "${RENEWED_LINEAGE}").pem" failed_cert_file="/root/$(basename "${RENEWED_LINEAGE}").failed.pem" @@ -86,7 +89,5 @@ readonly VERBOSE=${VERBOSE:-"0"} readonly QUIET=${QUIET:-"0"} readonly haproxy_bin=$(command -v haproxy) -readonly haproxy_config_file="/etc/haproxy/haproxy.cfg" -readonly haproxy_cert_dir=$(detect_haproxy_cert_dir) main diff --git a/dovecot/defaults/main.yml b/dovecot/defaults/main.yml index 884bc1ca..52e06bda 100644 --- a/dovecot/defaults/main.yml +++ b/dovecot/defaults/main.yml @@ -1,2 +1,4 @@ --- -dovecot_foo: bar + +dovecot_vmail_uid: 5000 +dovecot_vmail_gid: 5000 diff --git a/dovecot/files/munin_config b/dovecot/files/munin_config new file mode 100644 index 00000000..1a0553d8 --- /dev/null +++ b/dovecot/files/munin_config @@ -0,0 +1,2 @@ +[dovecot] +group adm diff --git a/dovecot/files/munin_plugin b/dovecot/files/munin_plugin index e5a6d1d1..f12c2b04 100755 --- a/dovecot/files/munin_plugin +++ b/dovecot/files/munin_plugin @@ -2,21 +2,22 @@ # # Munin Plugin # to count logins to your dovecot mailserver -# +# # Created by Dominik Schulz # http://developer.gauner.org/munin/ # Contributions by: # - Stephane Enten # - Steve Schnepp -# +# - pcy (make 'Connected Users' DERIVE, check existence of logfile in autoconf) +# # Parameters understood: # # config (required) # autoconf (optional - used by munin-config) -# +# # Config variables: # -# logfile - Where to find the syslog file +# logfile - Where to find the syslog file # # Add the following line to a file in /etc/munin/plugin-conf.d: # env.logfile /var/log/your/logfile.log @@ -34,13 +35,13 @@ LOGFILE=${logfile:-/var/log/mail.log} ###################### if [ "$1" = "autoconf" ]; then - echo yes + [ -f "$LOGFILE" ] && echo yes || echo "no (logfile $LOGFILE not found)" exit 0 fi if [ "$1" = "config" ]; then echo 'graph_title Dovecot Logins' - echo 'graph_category Mail' + echo 'graph_category mail' echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel Login Counters' @@ -53,6 +54,7 @@ if [ "$1" = "config" ]; then done echo 'connected.label Connected Users' + echo "connected.type DERIVE" exit 0 fi @@ -86,7 +88,7 @@ echo -n echo -en "login_tls.value " VALUE=$(egrep -c '[dovecot]?.*Login.*TLS' $LOGFILE) if [ ! -z "$VALUE" ]; then - echo "$VALUE" + echo "$VALUE" else echo "0" fi @@ -97,7 +99,7 @@ echo -n echo -en "login_ssl.value " VALUE=$(egrep -c '[dovecot]?.*Login.*SSL' $LOGFILE) if [ ! -z "$VALUE" ]; then - echo "$VALUE" + echo "$VALUE" else echo "0" fi @@ -108,7 +110,7 @@ echo -n echo -en "login_imap.value " VALUE=$(egrep -c '[dovecot]?.*imap.*Login' $LOGFILE) if [ ! -z "$VALUE" ]; then - echo "$VALUE" + echo "$VALUE" else echo "0" fi @@ -119,7 +121,7 @@ echo -n echo -en "login_pop3.value " VALUE=$(egrep -c '[dovecot]?.*pop3.*Login' $LOGFILE) if [ ! -z "$VALUE" ]; then - echo "$VALUE" + echo "$VALUE" else echo "0" fi diff --git a/dovecot/tasks/main.yml b/dovecot/tasks/main.yml index 8492e00a..1a7e4280 100644 --- a/dovecot/tasks/main.yml +++ b/dovecot/tasks/main.yml @@ -40,7 +40,8 @@ - name: create vmail group group: name: vmail - gid: 5000 + gid: "{{ dovecot_vmail_gid }}" + system: True tags: - dovecot @@ -48,8 +49,9 @@ user: name: vmail group: vmail - uid: 5000 + uid: "{{ dovecot_vmail_uid }}" shell: /bin/false + system: True tags: - dovecot diff --git a/dovecot/tasks/munin.yml b/dovecot/tasks/munin.yml index 21d17519..c6b58d28 100644 --- a/dovecot/tasks/munin.yml +++ b/dovecot/tasks/munin.yml @@ -14,8 +14,10 @@ dest: /etc/munin/plugins/dovecot mode: "0755" -# TODO : add in /etc/munin/plugin-conf.d/munin-node -# [dovecot] -# group adm + - name: Install munin config + copy: + src: munin_config + dest: /etc/munin/plugin-conf.d/dovecot + mode: "0644" when: munin_node_plugins_config.stat.exists diff --git a/evoacme/defaults/main.yml b/evoacme/defaults/main.yml index e54ef2fc..ef16ee78 100644 --- a/evoacme/defaults/main.yml +++ b/evoacme/defaults/main.yml @@ -14,3 +14,5 @@ evoacme_ssl_loc: 'Marseille' evoacme_ssl_org: 'Evolix' evoacme_ssl_ou: 'Security' evoacme_ssl_email: 'security@evolix.net' + +evoacme_disable_debian_check: False diff --git a/evoacme/files/evoacme.sh b/evoacme/files/evoacme.sh index e8330748..2ea2d273 100755 --- a/evoacme/files/evoacme.sh +++ b/evoacme/files/evoacme.sh @@ -14,7 +14,7 @@ show_version() { cat <, +Copyright 2009-2020 Evolix , Victor Laborie , Jérémy Lecour , Benoit Série @@ -284,13 +284,19 @@ main() { export EVOACME_CHAIN="${LIVE_CHAIN}" export EVOACME_FULLCHAIN="${LIVE_FULLCHAIN}" + # emulate certbot hooks environment variables + export RENEWED_LINEAGE="${LIVE_DIR}" + export RENEWED_DOMAINS="${VHOST}" + # search for files in hooks directory for hook in $(find ${HOOKS_DIR} -type f -executable | sort); do + set +e # keep only executables files, not containing a "." - if [ -x "${hook}" ] && (basename "${hook}" | grep -vqF "."); then + if [ -x "${hook}" ] && (basename "${hook}" | grep -vqF ".disable"); then debug "Executing ${hook}" ${hook} fi + set -e done } @@ -303,7 +309,7 @@ readonly QUIET=${QUIET:-"0"} readonly TEST=${TEST:-"0"} readonly DRY_RUN=${DRY_RUN:-"0"} -readonly VERSION="20.08" +readonly VERSION="20.12" # Read configuration file, if it exists [ -r /etc/default/evoacme ] && . /etc/default/evoacme diff --git a/evoacme/files/make-csr.sh b/evoacme/files/make-csr.sh index 372c58fc..f82ad65b 100755 --- a/evoacme/files/make-csr.sh +++ b/evoacme/files/make-csr.sh @@ -13,7 +13,7 @@ show_version() { cat <, +Copyright 2009-2020 Evolix , Victor Laborie , Jérémy Lecour , Benoit Série @@ -265,7 +265,7 @@ readonly ARGS=$@ readonly VERBOSE=${VERBOSE:-"0"} readonly QUIET=${QUIET:-"0"} -readonly VERSION="20.08" +readonly VERSION="20.12" # Read configuration file, if it exists [ -r /etc/default/evoacme ] && . /etc/default/evoacme diff --git a/evoacme/files/vhost-domains.sh b/evoacme/files/vhost-domains.sh index 41b065b6..5a60c23c 100755 --- a/evoacme/files/vhost-domains.sh +++ b/evoacme/files/vhost-domains.sh @@ -13,7 +13,7 @@ show_version() { cat <, +Copyright 2009-2020 Evolix , Victor Laborie , Jérémy Lecour , Benoit Série @@ -170,7 +170,7 @@ readonly ARGS=$@ readonly VERBOSE=${VERBOSE:-"0"} readonly QUIET=${QUIET:-"0"} -readonly VERSION="20.08" +readonly VERSION="20.12" readonly SRV_IP=${SRV_IP:-""} diff --git a/evoacme/tasks/main.yml b/evoacme/tasks/main.yml index bd8cc055..4c71d90e 100644 --- a/evoacme/tasks/main.yml +++ b/evoacme/tasks/main.yml @@ -6,6 +6,7 @@ - ansible_distribution == "Debian" - ansible_distribution_major_version is version('9', '>=') msg: only compatible with Debian >= 9 + when: not evoacme_disable_debian_check - include: certbot.yml diff --git a/evocheck/files/evocheck.sh b/evocheck/files/evocheck.sh index 5c3f1365..287982e2 100644 --- a/evocheck/files/evocheck.sh +++ b/evocheck/files/evocheck.sh @@ -4,7 +4,7 @@ # Script to verify compliance of a Debian/OpenBSD server # powered by Evolix -readonly VERSION="20.04.3" +readonly VERSION="20.12" # base functions @@ -205,10 +205,13 @@ check_customsudoers() { grep -E -qr "umask=0077" /etc/sudoers* || failed "IS_CUSTOMSUDOERS" "missing umask=0077 in sudoers file" } check_vartmpfs() { - df /var/tmp | grep -q tmpfs || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs" -} -check_vartmpfs() { - df /var/tmp | grep -q tmpfs || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs" + FINDMNT_BIN=$(command -v findmnt) + if [ -x "${FINDMNT_BIN}" ]; then + ${FINDMNT_BIN} /var/tmp --type tmpfs --noheadings > /dev/null || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs" + else + df /var/tmp | grep -q tmpfs || failed "IS_VARTMPFS" "/var/tmp is not a tmpfs" + fi + } check_serveurbase() { is_installed serveur-base || failed "IS_SERVEURBASE" "serveur-base package is not installed" @@ -559,7 +562,7 @@ check_evobackup_exclude_mount() { # shellcheck disable=SC2064 trap "rm -f ${excludes_file}" 0 # shellcheck disable=SC2044 - for evobackup_file in $(find /etc/cron* -name '*evobackup*'); do + for evobackup_file in $(find /etc/cron* -name '*evobackup*' | grep -v -E ".disabled$"); do grep -- "--exclude " "${evobackup_file}" | grep -E -o "\"[^\"]+\"" | tr -d '"' > "${excludes_file}" not_excluded=$(findmnt --type nfs,nfs4,fuse.sshfs, -o target --noheadings | grep -v -f "${excludes_file}") for mount in ${not_excluded}; do @@ -878,15 +881,25 @@ check_sql_backup() { if (is_installed "mysql-server" || is_installed "mariadb-server"); then # You could change the default path in /etc/evocheck.cf SQL_BACKUP_PATH=${SQL_BACKUP_PATH:-"/home/backup/mysql.bak.gz"} - test -f "$SQL_BACKUP_PATH" || failed "IS_SQL_BACKUP" "MySQL dump is missing (${SQL_BACKUP_PATH})" + for backup_path in ${SQL_BACKUP_PATH}; do + if [ ! -f "${backup_path}" ]; then + failed "IS_SQL_BACKUP" "MySQL dump is missing (${backup_path})" + test "${VERBOSE}" = 1 || break + fi + done fi } check_postgres_backup() { - if is_installed "postgresql-9*"; then + if is_installed "postgresql-9*" || is_installed "postgresql-1*"; then # If you use something like barman, you should disable this check # You could change the default path in /etc/evocheck.cf - POSTGRES_BACKUP_PATH=${POSTGRES_BACKUP_PATH:-"/home/backup/pg.dump.bak"} - test -f "$POSTGRES_BACKUP_PATH" || failed "IS_POSTGRES_BACKUP" "PostgreSQL dump is missing (${POSTGRES_BACKUP_PATH})" + POSTGRES_BACKUP_PATH=${POSTGRES_BACKUP_PATH:-"/home/backup/pg.dump.bak*"} + for backup_path in ${POSTGRES_BACKUP_PATH}; do + if [ ! -f "${backup_path}" ]; then + failed "IS_POSTGRES_BACKUP" "PostgreSQL dump is missing (${backup_path})" + test "${VERBOSE}" = 1 || break + fi + done fi } check_mongo_backup() { @@ -1013,7 +1026,7 @@ check_duplicate_fs_label() { BLKID_BIN=$(command -v blkid) if [ -x "$BLKID_BIN" ]; then tmpFile=$(mktemp -p /tmp) - parts=$($BLKID_BIN | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2) + parts=$($BLKID_BIN -c /dev/null | grep -ve raid_member -e EFI_SYSPART | grep -Eo ' LABEL=".*"' | cut -d'"' -f2) for part in $parts; do echo "$part" >> "$tmpFile" done @@ -1517,8 +1530,6 @@ main() { # shellcheck disable=SC2034 readonly PROGNAME=$(basename "$0") -# shellcheck disable=SC2034 -readonly PROGDIR=$(realpath -m "$(dirname "$0")") # shellcheck disable=2124 readonly ARGS=$@ diff --git a/evolinux-users/tasks/sudo.yml b/evolinux-users/tasks/sudo.yml index 2f2ee07c..6f127da8 100644 --- a/evolinux-users/tasks/sudo.yml +++ b/evolinux-users/tasks/sudo.yml @@ -4,6 +4,6 @@ when: ansible_distribution_release == "jessie" - include: sudo_stretch.yml - when: ansible_distribution_major_version is version('9', '>=') + when: ansible_distribution_major_version is defined and ansible_distribution_major_version is version('9', '>=') - meta: flush_handlers diff --git a/evolinux-users/tasks/user.yml b/evolinux-users/tasks/user.yml index 2f5e4e43..b8dda1d2 100644 --- a/evolinux-users/tasks/user.yml +++ b/evolinux-users/tasks/user.yml @@ -2,20 +2,41 @@ # Unix account +- fail: + msg: "You must provide a value for the 'user.name ' variable." + when: user.name is not defined or user.name == '' + +- fail: + msg: "You must provide a value for the 'user.uid ' variable." + when: user.uid is not defined or user.uid == '' + - name: "Test if '{{ user.name }}' exists" - command: 'getent passwd {{ user.name }}' - register: loginisbusy + command: 'id -u "{{ user.name }}"' + register: get_id_from_login failed_when: False changed_when: False check_mode: no -- name: "Test if uid exists for '{{ user.name }}'" - command: 'getent passwd {{ user.uid }}' - register: uidisbusy +- name: "Test if uid '{{ user.uid }}' exists" + command: 'id -un -- "{{ user.uid }}"' + register: get_login_from_id failed_when: False changed_when: False check_mode: no +# Error if +# the uid already exists +# and the user associated with this uid is not the desired user +- name: "Fail if uid already exists for another user" + fail: + msg: "Uid '{{ user.uid }}' is already used by '{{ get_login_from_id.stdout }}'. You must change uid for '{{ user.name }}'" + when: + - get_login_from_id.rc == 0 + - get_login_from_id.stdout != user.name + +# Create/Update the user account with defined uid if +# the user doesn't already exist and the uid isn't already used +# or the user exists with the defined uid - name: "Unix account for '{{ user.name }}' is present (with uid '{{ user.uid }}')" user: state: present @@ -24,11 +45,13 @@ comment: '{{ user.fullname }}' shell: /bin/bash password: '{{ user.password_hash }}' - update_password: on_create + update_password: "on_create" when: - - loginisbusy.rc != 0 - - uidisbusy.rc != 0 + - (get_id_from_login.rc != 0 and get_login_from_id.rc != 0) or (get_id_from_login.rc == 0 and get_login_from_id.stdout == user.name) +# Create/Update the user account without defined uid if +# the user doesn't already exist but the defined uid is already used +# or another user already exists with a the same uid - name: "Unix account for '{{ user.name }}' is present (with random uid)" user: state: present @@ -36,10 +59,9 @@ comment: '{{ user.fullname }}' shell: /bin/bash password: '{{ user.password_hash }}' - update_password: on_create + update_password: "on_create" when: - - loginisbusy.rc != 0 - - uidisbusy.rc == 0 + - (get_id_from_login.rc != 0 and get_login_from_id.rc == 0) or (get_id_from_login.rc == 0 and get_login_from_id.stdout != user.name) - name: Is /etc/aliases present? stat: diff --git a/filebeat/defaults/main.yml b/filebeat/defaults/main.yml index cd92eb3c..322aba46 100644 --- a/filebeat/defaults/main.yml +++ b/filebeat/defaults/main.yml @@ -12,6 +12,12 @@ filebeat_elasticsearch_auth_api_key: "" filebeat_elasticsearch_auth_username: "" filebeat_elasticsearch_auth_password: "" +filebeat_logstash_hosts: [] +filebeat_logstash_protocol: "http" +filebeat_logstash_auth_api_key: "" +filebeat_logstash_auth_username: "" +filebeat_logstash_auth_password: "" + filebeat_use_config_template: False filebeat_update_config: True filebeat_force_config: True diff --git a/filebeat/templates/filebeat.default.yml.j2 b/filebeat/templates/filebeat.default.yml.j2 index 65a15fd1..a0a0c0d4 100644 --- a/filebeat/templates/filebeat.default.yml.j2 +++ b/filebeat/templates/filebeat.default.yml.j2 @@ -143,15 +143,11 @@ setup.kibana: # Configure what output to use when sending the data collected by the beat. +{% if filebeat_elasticsearch_hosts %} # ---------------------------- Elasticsearch Output ---------------------------- output.elasticsearch: - # Array of hosts to connect to. hosts: ["{{ filebeat_elasticsearch_hosts | join('", "') }}"] - - # Protocol - either `http` (default) or `https`. protocol: "{{ filebeat_elasticsearch_protocol | default('http') }}" - - # Authentication credentials - either API key or username/password. {% if filebeat_elasticsearch_auth_api_key %} api_key: "{{ filebeat_elasticsearch_auth_api_key }}" {% endif %} @@ -161,11 +157,22 @@ output.elasticsearch: {% if filebeat_elasticsearch_auth_password %} password: "{{ filebeat_elasticsearch_auth_password }}" {% endif %} - -# ------------------------------ Logstash Output ------------------------------- -#output.logstash: - # The Logstash hosts - #hosts: ["localhost:5044"] +{% endif %} +{% if filebeat_logstash_hosts %} +# ---------------------------- Logstash Output --------------------------------- +output.logstash: + hosts: ["{{ filebeat_logstash_hosts | join('", "') }}"] + protocol: "{{ filebeat_logstash_protocol | default('http') }}" +{% if filebeat_logstash_auth_api_key %} + api_key: "{{ filebeat_logstash_auth_api_key }}" +{% endif %} +{% if filebeat_logstash_auth_username %} + username: "{{ filebeat_logstash_auth_username }}" +{% endif %} +{% if filebeat_logstash_auth_password %} + password: "{{ filebeat_logstash_auth_password }}" +{% endif %} +{% endif %} # Optional SSL. By default is off. # List of root certificates for HTTPS server verifications diff --git a/kvm-host/defaults/main.yml b/kvm-host/defaults/main.yml index 4c77a2ff..bb97c0f9 100644 --- a/kvm-host/defaults/main.yml +++ b/kvm-host/defaults/main.yml @@ -1,2 +1,3 @@ --- kvm_custom_libvirt_images_path: '' +kvm_install_drbd: True diff --git a/kvm-host/meta/main.yml b/kvm-host/meta/main.yml index 1d6d1c36..0976cf88 100644 --- a/kvm-host/meta/main.yml +++ b/kvm-host/meta/main.yml @@ -12,8 +12,8 @@ galaxy_info: - name: Debian versions: - jessie + - stretch + - buster -dependencies: [] - # List your role dependencies here, one per line. - # Be sure to remove the '[]' above if you add dependencies - # to this list. +dependencies: + - { role: evolix/drbd, when: kvm_install_drbd } diff --git a/lxc-php/defaults/main.yml b/lxc-php/defaults/main.yml index 8cb62665..69ef9380 100644 --- a/lxc-php/defaults/main.yml +++ b/lxc-php/defaults/main.yml @@ -7,6 +7,10 @@ php_conf_html_errors: "Off" php_conf_allow_url_fopen: "Off" php_conf_disable_functions: "exec,shell-exec,system,passthru,popen" +# Allows accessing a local mysql database using localhost +php_conf_mysql_socket_dir: /mysqld +php_conf_mysql_default_socket: "{{ php_conf_mysql_socket_dir }}/mysqld.sock" + lxc_php_version: Null lxc_php_container_releases: diff --git a/lxc-php/handlers/main.yml b/lxc-php/handlers/main.yml index 06953b4f..b8322e94 100644 --- a/lxc-php/handlers/main.yml +++ b/lxc-php/handlers/main.yml @@ -18,3 +18,9 @@ lxc_container: name: "{{ lxc_php_version }}" container_command: "systemctl restart opensmtpd" + +- name: Restart container + lxc_container: + name: "{{ lxc_php_version }}" + state: restarted + diff --git a/lxc-php/tasks/misc.yml b/lxc-php/tasks/misc.yml index af848213..3b6164d0 100644 --- a/lxc-php/tasks/misc.yml +++ b/lxc-php/tasks/misc.yml @@ -18,8 +18,16 @@ dest: "/var/lib/lxc/{{ lxc_php_version }}/rootfs/etc/mailname" notify: "Restart opensmtpd" - - name: "{{ lxc_php_version }} - Install misc packages" lxc_container: name: "{{ lxc_php_version }}" container_command: "DEBIAN_FRONTEND=noninteractive apt install -y cron logrotate git zip unzip" + +- name: "{{ lxc_php_version }} - Add MySQL socket to container default mounts" + lxc_container: + name: "{{ lxc_php_version }}" + container_config: + - "lxc.mount.entry = /run/mysqld {{ php_conf_mysql_socket_dir | replace('/', '', 1) }} none bind,create=dir 0 0" + when: php_conf_mysql_socket_dir is string + notify: "Restart container" + diff --git a/lxc-php/templates/z-evolinux-defaults.ini.j2 b/lxc-php/templates/z-evolinux-defaults.ini.j2 index 7e3e116b..3bc6e4ee 100644 --- a/lxc-php/templates/z-evolinux-defaults.ini.j2 +++ b/lxc-php/templates/z-evolinux-defaults.ini.j2 @@ -6,3 +6,11 @@ log_errors = {{ php_conf_log_errors }} html_errors = {{ php_conf_html_errors }} allow_url_fopen = {{ php_conf_allow_url_fopen }} disable_functions = {{ php_conf_disable_functions }} + +{% if php_conf_mysql_socket_dir %} +[Pdo_mysql] +pdo_mysql.default_socket = {{ php_conf_mysql_default_socket }} + +[MySQLi] +mysqli.default_socket = {{ php_conf_mysql_default_socket }} +{% endif %} diff --git a/minifirewall/defaults/main.yml b/minifirewall/defaults/main.yml index 5489b06a..fd4e726b 100644 --- a/minifirewall/defaults/main.yml +++ b/minifirewall/defaults/main.yml @@ -5,11 +5,15 @@ minifirewall_tail_file: /etc/default/minifirewall.tail minifirewall_tail_included: False minifirewall_tail_force: True +minifirewall_force_upgrade_script: False +minifirewall_force_upgrade_config: False + minifirewall_git_url: "https://forge.evolix.org/minifirewall.git" minifirewall_checkout_path: "/tmp/minifirewall" minifirewall_int: "{{ ansible_default_ipv4.interface }}" minifirewall_ipv6: "on" minifirewall_intlan: "{{ ansible_default_ipv4.address }}/32" +minifirewall_docker: "off" minifirewall_default_trusted_ips: [] minifirewall_additional_trusted_ips: [] diff --git a/minifirewall/files/minifirewall.conf b/minifirewall/files/minifirewall.conf index 7285822a..1c637483 100644 --- a/minifirewall/files/minifirewall.conf +++ b/minifirewall/files/minifirewall.conf @@ -1,6 +1,5 @@ # Configuration for minifirewall : https://gitea.evolix.org/evolix/minifirewall -# For fun, we keep last change from first CVS repository: -# version 0.1 - 12 juillet 2007 $Id: firewall.rc,v 1.2 2007/07/12 19:08:59 reg Exp $ +# Version 20.12 — 2020-12-01 22:55:35 # Main interface INT='eth0' @@ -8,6 +7,12 @@ INT='eth0' # IPv6 IPV6=on +# Docker Mode +# Changes the behaviour of minifirewall to not break the containers' network +# For instance, turning it on will disable nat table purge +# Also, we'll add the DOCKER-USER chain, in iptable +DOCKER='off' + # Trusted IPv4 local network # ...will be often IP/32 if you don't trust anything INTLAN='192.168.0.2/32' diff --git a/minifirewall/tasks/config.yml b/minifirewall/tasks/config.yml index 82be385c..4c852d6b 100644 --- a/minifirewall/tasks/config.yml +++ b/minifirewall/tasks/config.yml @@ -51,13 +51,19 @@ blockinfile: dest: "{{ minifirewall_main_file }}" marker: "# {mark} ANSIBLE MANAGED BLOCK FOR IPS" - content: | + block: | # Main interface INT='{{ minifirewall_int }}' # IPv6 IPV6='{{ minifirewall_ipv6 }}' + # Docker Mode + # Changes the behaviour of minifirewall to not break the containers' network + # For instance, turning it on will disable nat table purge + # Also, we'll add the DOCKER-USER chain, in iptable + DOCKER='{{ minifirewall_docker }}' + # Trusted IPv4 local network # ...will be often IP/32 if you don't trust anything INTLAN='{{ minifirewall_intlan }}' @@ -89,7 +95,7 @@ blockinfile: dest: "{{ minifirewall_main_file }}" marker: "# {mark} ANSIBLE MANAGED BLOCK FOR PORTS" - content: | + block: | # Protected services # (add also in Public services if needed) SERVICESTCP1p='{{ minifirewall_protected_ports_tcp | join(' ') }}' diff --git a/minifirewall/tasks/install.yml b/minifirewall/tasks/install.yml index a4bcf734..5d6438ed 100644 --- a/minifirewall/tasks/install.yml +++ b/minifirewall/tasks/install.yml @@ -9,7 +9,7 @@ template: src: minifirewall.j2 dest: /etc/init.d/minifirewall - force: no + force: "{{ minifirewall_force_upgrade_script | default('no') }}" mode: "0700" owner: root group: root @@ -18,7 +18,7 @@ copy: src: minifirewall.conf dest: "{{ minifirewall_main_file }}" - force: no + force: "{{ minifirewall_force_upgrade_config | default('no') }}" mode: "0600" owner: root group: root diff --git a/minifirewall/templates/minifirewall.j2 b/minifirewall/templates/minifirewall.j2 index 8045ce60..13b5130d 100755 --- a/minifirewall/templates/minifirewall.j2 +++ b/minifirewall/templates/minifirewall.j2 @@ -4,7 +4,7 @@ # we used netfilter/iptables http://netfilter.org/ designed for recent Linux kernel # See https://gitea.evolix.org/evolix/minifirewall -# Copyright (c) 2007-2015 Evolix +# Copyright (c) 2007-2020 Evolix # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 3 @@ -51,6 +51,20 @@ BROAD='255.255.255.255' PORTSROOT='0:1023' PORTSUSER='1024:65535' +chain_exists() +{ + local chain_name="$1" ; shift + [ $# -eq 1 ] && local intable="--table $1" + iptables $intable -nL "$chain_name" >/dev/null 2>&1 +} + +# Configuration +oldconfigfile="/etc/firewall.rc" +configfile="{{ minifirewall_main_file }}" + +IPV6=$(grep "IPV6=" {{ minifirewall_main_file }} | awk -F '=' -F "'" '{print $2}') +DOCKER=$(grep "DOCKER=" {{ minifirewall_main_file }} | awk -F '=' -F "'" '{print $2}') +INT=$(grep "INT=" {{ minifirewall_main_file }} | awk -F '=' -F "'" '{print $2}') case "$1" in start) @@ -109,10 +123,6 @@ $IPT -N LOG_ACCEPT $IPT -A LOG_ACCEPT -j LOG --log-prefix '[IPTABLES ACCEPT] : ' $IPT -A LOG_ACCEPT -j ACCEPT -# Configuration -oldconfigfile="/etc/firewall.rc" -configfile="{{ minifirewall_main_file }}" - if test -f $oldconfigfile; then echo "$oldconfigfile is deprecated, rename to $configfile" >&2 exit 1 @@ -165,6 +175,33 @@ $IPT -A OUTPUT -o lo -j ACCEPT $IPT -A INPUT -s $LOOPBACK ! -i lo -j DROP +if [ "$DOCKER" = "on" ]; then + + $IPT -N MINIFW-DOCKER-TRUSTED + $IPT -A MINIFW-DOCKER-TRUSTED -j DROP + + $IPT -N MINIFW-DOCKER-PRIVILEGED + $IPT -A MINIFW-DOCKER-PRIVILEGED -j MINIFW-DOCKER-TRUSTED + $IPT -A MINIFW-DOCKER-PRIVILEGED -j RETURN + + $IPT -N MINIFW-DOCKER-PUB + $IPT -A MINIFW-DOCKER-PUB -j MINIFW-DOCKER-PRIVILEGED + $IPT -A MINIFW-DOCKER-PUB -j RETURN + + # Flush DOCKER-USER if exist, create it if absent + if chain_exists 'DOCKER-USER'; then + $IPT -F DOCKER-USER + else + $IPT -N DOCKER-USER + fi; + + # Pipe new connection through MINIFW-DOCKER-PUB + $IPT -A DOCKER-USER -i $INT -m state --state NEW -j MINIFW-DOCKER-PUB + $IPT -A DOCKER-USER -j RETURN + +fi + + # Local services restrictions ############################# @@ -218,6 +255,64 @@ for x in $SERVICESUDP3 done +if [ "$DOCKER" = "on" ]; then + + # Public services defined in SERVICESTCP1 & SERVICESUDP1 + for dstport in $SERVICESTCP1 + do + $IPT -I MINIFW-DOCKER-PUB -p tcp --dport "$dstport" -j RETURN + done + + for dstport in $SERVICESUDP1 + do + $IPT -I MINIFW-DOCKER-PUB -p udp --dport "$dstport" -j RETURN + done + + # Privileged services (accessible from privileged & trusted IPs) + for dstport in $SERVICESTCP2 + do + for srcip in $PRIVILEGIEDIPS + do + $IPT -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "$srcip" --dport "$dstport" -j RETURN + done + + for srcip in $TRUSTEDIPS + do + $IPT -I MINIFW-DOCKER-PRIVILEGED -p tcp -s "$srcip" --dport "$dstport" -j RETURN + done + done + + for dstport in $SERVICESUDP2 + do + for srcip in $PRIVILEGIEDIPS + do + $IPT -I MINIFW-DOCKER-PRIVILEGED -p udp -s "$srcip" --dport "$dstport" -j RETURN + done + + for srcip in $TRUSTEDIPS + do + $IPT -I MINIFW-DOCKER-PRIVILEGED -p udp -s "$srcip" --dport "$dstport" -j RETURN + done + done + + # Trusted services (accessible from trusted IPs) + for dstport in $SERVICESTCP3 + do + for srcip in $TRUSTEDIPS + do + $IPT -I MINIFW-DOCKER-TRUSTED -p tcp -s "$srcip" --dport "$dstport" -j RETURN + done + done + + for dstport in $SERVICESUDP3 + do + for srcip in $TRUSTEDIPS + do + $IPT -I MINIFW-DOCKER-TRUSTED -p udp -s "$srcip" --dport "$dstport" -j RETURN + done + done +fi + # External services ################### @@ -323,11 +418,24 @@ trap - INT TERM EXIT $IPT -F ONLYTRUSTED $IPT -F ONLYPRIVILEGIED $IPT -F NEEDRESTRICT - $IPT -t nat -F + [ "$DOCKER" = "off" ] && $IPT -t nat -F $IPT -t mangle -F [ "$IPV6" != "off" ] && $IPT6 -F INPUT [ "$IPV6" != "off" ] && $IPT6 -F OUTPUT + if [ "$DOCKER" = "on" ]; then + $IPT -F DOCKER-USER + $IPT -A DOCKER-USER -j RETURN + + $IPT -F MINIFW-DOCKER-PUB + $IPT -X MINIFW-DOCKER-PUB + $IPT -F MINIFW-DOCKER-PRIVILEGED + $IPT -X MINIFW-DOCKER-PRIVILEGED + $IPT -F MINIFW-DOCKER-TRUSTED + $IPT -X MINIFW-DOCKER-TRUSTED + + fi + # Accept all $IPT -P INPUT ACCEPT $IPT -P OUTPUT ACCEPT diff --git a/mysql-oracle/files/evolinux-defaults.cnf b/mysql-oracle/files/evolinux-defaults.cnf index 395ccac4..c42ed727 100644 --- a/mysql-oracle/files/evolinux-defaults.cnf +++ b/mysql-oracle/files/evolinux-defaults.cnf @@ -1,6 +1,8 @@ [mysqld] ###### Connexions +# Path to socket +socket = /run/mysqld/mysqld.sock # Maximum de connexions concurrentes (defaut = 100)... provoque un "Too many connections" max_connections = 250 # Maximum de connexions en attente en cas de max_connections atteint (defaut = 50) @@ -60,3 +62,6 @@ character-set-server=utf8 collation-server=utf8_general_ci # Patch MySQL 5.5.53 secure-file-priv = "" + +[client] +socket = /run/mysqld/mysqld.sock diff --git a/mysql/files/save_mysql_processlist.sh b/mysql/files/save_mysql_processlist.sh new file mode 100644 index 00000000..95abc57d --- /dev/null +++ b/mysql/files/save_mysql_processlist.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +set -e + +processlist() { + mysqladmin --verbose --vertical processlist +} + +DIR="/var/log/mysql-processlist" +TS=`date +%Y%m%d%H%M%S` +FILE="${DIR}/${TS}" + +if [ ! -d "${DIR}" ]; then + mkdir -p "${DIR}" + chown root:adm "${DIR}" + chmod 750 "${DIR}" +fi + +processlist > "${FILE}" +chmod 640 "${FILE}" +chown root:adm "${FILE}" + +find "${DIR}" -type f -mtime +1 -delete + +exit 0 diff --git a/mysql/handlers/main.yml b/mysql/handlers/main.yml index 87a7613a..80afafe5 100644 --- a/mysql/handlers/main.yml +++ b/mysql/handlers/main.yml @@ -22,4 +22,4 @@ - name: 'restart xinetd' service: name: 'xinetd' - state: 'restart' + state: 'restarted' diff --git a/mysql/tasks/utils.yml b/mysql/tasks/utils.yml index 7609a81e..164507aa 100644 --- a/mysql/tasks/utils.yml +++ b/mysql/tasks/utils.yml @@ -178,3 +178,12 @@ tags: - mysql - packages + +- name: "Install save_mysql_processlist.sh" + copy: + src: save_mysql_processlist.sh + dest: "{{ mysql_scripts_dir or general_scripts_dir | mandatory }}/save_mysql_processlist.sh" + mode: "0755" + force: no + tags: + - mysql diff --git a/packweb-apache/meta/main.yml b/packweb-apache/meta/main.yml index c8981b6e..f98442a6 100644 --- a/packweb-apache/meta/main.yml +++ b/packweb-apache/meta/main.yml @@ -21,11 +21,11 @@ dependencies: - { role: evolix/apache } - { role: evolix/php, php_apache_enable: True, when: packweb_apache_modphp } - { role: evolix/php, php_fpm_enable: True, when: packweb_apache_fpm } - - { role: evolix/lxc-php, lxc_php_version: php56, when: "'php56' in packweb_multiphp_versions" } - - { role: evolix/lxc-php, lxc_php_version: php70, when: "'php70' in packweb_multiphp_versions" } - - { role: evolix/lxc-php, lxc_php_version: php73, when: "'php73' in packweb_multiphp_versions" } - { role: evolix/squid, squid_localproxy_enable: True } - { role: evolix/mysql, when: packweb_mysql_variant == "debian" } - { role: evolix/mysql-oracle, when: packweb_mysql_variant == "oracle" } + - { role: evolix/lxc-php, lxc_php_version: php56, when: "'php56' in packweb_multiphp_versions" } + - { role: evolix/lxc-php, lxc_php_version: php70, when: "'php70' in packweb_multiphp_versions" } + - { role: evolix/lxc-php, lxc_php_version: php73, when: "'php73' in packweb_multiphp_versions" } - { role: evolix/webapps/evoadmin-web, evoadmin_enable_vhost: "{{ packweb_enable_evoadmin_vhost }}", evoadmin_multiphp_versions: "{{ packweb_multiphp_versions }}" } - { role: evolix/evoacme } diff --git a/postgresql/defaults/main.yml b/postgresql/defaults/main.yml index c81ff575..7b2b3734 100644 --- a/postgresql/defaults/main.yml +++ b/postgresql/defaults/main.yml @@ -9,7 +9,7 @@ postgresql_random_page_cost: 1.5 postgresql_effective_cache_size: "{{ (ansible_memtotal_mb * 0.5) | int }}MB" # PostgreSQL version -postgresql_version: '9.6' +postgresql_version: '' # Set locales locales_default: fr_FR.UTF-8 diff --git a/postgresql/tasks/packages_buster.yml b/postgresql/tasks/packages_buster.yml index 3f45e84c..3a1a440e 100644 --- a/postgresql/tasks/packages_buster.yml +++ b/postgresql/tasks/packages_buster.yml @@ -1,5 +1,10 @@ --- +- name: "Set variables (Debian 10)" + set_fact: + postgresql_version: '11' + when: postgresql_version == "" + - include: pgdg-repo.yml when: postgresql_version != '11' diff --git a/postgresql/tasks/packages_jessie.yml b/postgresql/tasks/packages_jessie.yml index abf0ad08..3e21bc0e 100644 --- a/postgresql/tasks/packages_jessie.yml +++ b/postgresql/tasks/packages_jessie.yml @@ -1,5 +1,10 @@ --- +- name: "Set variables (Debian 8)" + set_fact: + postgresql_version: '9.4' + when: postgresql_version == "" + - include: pgdg-repo.yml when: postgresql_version != '9.4' diff --git a/postgresql/tasks/packages_stretch.yml b/postgresql/tasks/packages_stretch.yml index d6a3aa5e..eff513f9 100644 --- a/postgresql/tasks/packages_stretch.yml +++ b/postgresql/tasks/packages_stretch.yml @@ -1,5 +1,10 @@ --- +- name: "Set variables (Debian 9)" + set_fact: + postgresql_version: '9.6' + when: postgresql_version == "" + - include: pgdg-repo.yml when: postgresql_version != '9.6' diff --git a/postgresql/tasks/pgdg-repo.yml b/postgresql/tasks/pgdg-repo.yml index dcc63d6f..8d937b82 100644 --- a/postgresql/tasks/pgdg-repo.yml +++ b/postgresql/tasks/pgdg-repo.yml @@ -18,8 +18,13 @@ #url: http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc data: "{{ lookup('file', 'ACCC4CF8.asc') }}" +- name: Update and upgrade apt packages for PGDG repository + apt: + upgrade: yes + update_cache: yes + - name: Add APT preference file template: src: postgresql.pref.j2 - dest: /etc/apt/preferences.d/ + dest: /etc/apt/preferences.d/postgresql.pref mode: "0644" diff --git a/proftpd/templates/ftps.conf.j2 b/proftpd/templates/ftps.conf.j2 index ceec0631..33a2cff3 100644 --- a/proftpd/templates/ftps.conf.j2 +++ b/proftpd/templates/ftps.conf.j2 @@ -25,6 +25,7 @@ DefaultRoot ~ PassivePorts 60000 61000 + TransferLog /var/log/proftpd/xferlog AllowGroup ftpusers diff --git a/proftpd/templates/sftp.conf.j2 b/proftpd/templates/sftp.conf.j2 index 5f12ca9c..9a96e5ef 100644 --- a/proftpd/templates/sftp.conf.j2 +++ b/proftpd/templates/sftp.conf.j2 @@ -12,6 +12,7 @@ DefaultRoot ~ SFTPLog /var/log/proftpd/sftp.log + TransferLog /var/log/proftpd/xferlog SFTPAuthMethods password SFTPHostKey /etc/ssh/ssh_host_ecdsa_key diff --git a/redis/defaults/main.yml b/redis/defaults/main.yml index 6fc0b4c3..5cd311ce 100644 --- a/redis/defaults/main.yml +++ b/redis/defaults/main.yml @@ -3,6 +3,8 @@ redis_systemd_name: redis-server redis_conf_dir_prefix: /etc/redis +redis_force_instance_port: False + redis_port: 6379 redis_bind_interface: 127.0.0.1 diff --git a/redis/files/check_redis_instances.sh b/redis/files/check_redis_instances.sh index 7821aeb0..a7dead82 100644 --- a/redis/files/check_redis_instances.sh +++ b/redis/files/check_redis_instances.sh @@ -30,11 +30,21 @@ check_server() { host=$(config_var "bind" "${conf_file}") port=$(config_var "port" "${conf_file}") pass=$(config_var "requirepass" "${conf_file}") + maxmemory=$(config_var "maxmemory" "${conf_file}") + maxmemory_policy=$(config_var "maxmemory-policy" "${conf_file}") cmd="${check_bin} -H ${host} -p ${port}" + # If "requirepass" is set we add the password to the check if [ -n "${pass}" ]; then cmd="${cmd} -x ${pass}" fi + # If "maxmemory" is set and "maxmemory-policy" is missing or set to "noeviction" + # then we enforce the "maxmemory" limit + if [ -n "${maxmemory}" ]; then + if [ -z "${maxmemory_policy}" ] || [ "${maxmemory_policy}" = "noeviction" ]; then + cmd="${cmd} --total_memory ${maxmemory} --memory_utilization 80,90" + fi + fi result=$($cmd) ret="${?}" if [ "${ret}" -ge 2 ]; then diff --git a/redis/tasks/default-log2mail.yml b/redis/tasks/default-log2mail.yml index 8614a11d..21628b0c 100644 --- a/redis/tasks/default-log2mail.yml +++ b/redis/tasks/default-log2mail.yml @@ -8,7 +8,7 @@ mode: "0640" create: yes marker: "# {mark} ANSIBLE MANAGED RULES FOR DEFAULT INSTANCE" - content: | + block: | file = {{ redis_log_dir }}/redis-server.log pattern = "Cannot allocate memory" mailto = {{ log2mail_alert_email or general_alert_email | mandatory }} diff --git a/redis/tasks/instance-server.yml b/redis/tasks/instance-server.yml index 6437567c..5f4b2601 100644 --- a/redis/tasks/instance-server.yml +++ b/redis/tasks/instance-server.yml @@ -5,6 +5,7 @@ that: - redis_port != 6379 msg: "If you want to use port 6379, use the default instance, not a named instance." + when: not redis_force_instance_port - name: "Instance '{{ redis_instance_name }}' group is present" group: diff --git a/tomcat-instance/tasks/user.yml b/tomcat-instance/tasks/user.yml index a4a7bcb2..64244799 100644 --- a/tomcat-instance/tasks/user.yml +++ b/tomcat-instance/tasks/user.yml @@ -1,4 +1,24 @@ --- + +- fail: + msg: "You must provide a value for the 'tomcat_instance_port' variable." + when: tomcat_instance_port is not defined or tomcat_instance_port == '' + + +- name: "Test if uid '{{ tomcat_instance_port }}' exists" + command: 'id -un -- "{{ tomcat_instance_port }}"' + register: get_login_from_id + failed_when: False + changed_when: False + check_mode: no + +- name: "Fail if uid already exists for another user" + fail: + msg: "Uid '{{ tomcat_instance_port }}' is already used by '{{ get_login_from_id.stdout }}'. You must change uid for '{{ tomcat_instance_name }}'" + when: + - get_login_from_id.rc == 0 + - get_login_from_id.stdout != tomcat_instance_name + - name: Create group instance group: name: "{{ tomcat_instance_name }}" diff --git a/varnish/defaults/main.yml b/varnish/defaults/main.yml index 544d0cf7..7a7d8c2f 100644 --- a/varnish/defaults/main.yml +++ b/varnish/defaults/main.yml @@ -10,7 +10,7 @@ varnish_malloc_size: "2G" varnish_storage: malloc,{{ varnish_malloc_size }} varnish_thread_pools: "{{ ansible_processor_cores * ansible_processor_count }}" -varnish_thread_pool_add_delay: 2 +varnish_thread_pool_add_delay: 0 varnish_thread_pool_min: 500 varnish_thread_pool_max: 5000 diff --git a/varnish/files/reload-vcl.sh b/varnish/files/reload-vcl.sh deleted file mode 100644 index 537dcddf..00000000 --- a/varnish/files/reload-vcl.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -UUID=`cat /proc/sys/kernel/random/uuid` -/usr/sbin/varnishd -C -f /etc/varnish/default.vcl >/dev/null \ - &&/usr/bin/varnishadm -T localhost:6082 -S /etc/varnish/secret "vcl.load vcl_$UUID /etc/varnish/default.vcl" \ - && /usr/bin/varnishadm -T localhost:6082 -S /etc/varnish/secret "vcl.use vcl_$UUID" diff --git a/varnish/tasks/main.yml b/varnish/tasks/main.yml index c55218ef..7274cba8 100644 --- a/varnish/tasks/main.yml +++ b/varnish/tasks/main.yml @@ -4,49 +4,62 @@ name: varnish state: present tags: - - varnish + - varnish - name: Remove default varnish configuration files file: path: "{{ item }}" state: absent with_items: - - /etc/default/varnish - - /etc/default/varnishncsa - - /etc/default/varnishlog + - /etc/default/varnish + - /etc/default/varnishncsa + - /etc/default/varnishlog notify: reload varnish tags: - - varnish + - varnish -- name: Copy Custom Varnish ExecReload script (Debian <=9) - copy: - src: "reload-vcl.sh" +- name: Copy Custom Varnish ExecReload script (Debian <10) + template: + src: "reload-vcl.sh.j2" dest: "/etc/varnish/reload-vcl.sh" mode: "0700" owner: root group: root - when: ansible_distribution_major_version is version('9', '<=') + when: ansible_distribution_major_version is version('10', '<') notify: reload varnish tags: - - varnish + - varnish - name: Create a system config directory for systemd overrides file: path: /etc/systemd/system/varnish.service.d state: directory tags: - - varnish + - varnish -- name: Override Varnish systemd unit +- name: Override Varnish systemd unit (Stretch and before) template: - src: varnish.conf.j2 + src: varnish.conf.jessie.j2 dest: /etc/systemd/system/varnish.service.d/evolinux.conf force: yes + when: ansible_distribution_major_version is version('10', '<') notify: - reload systemd - restart varnish tags: - - varnish + - varnish + +- name: Override Varnish systemd unit (Buster and later) + template: + src: varnish.conf.buster.j2 + dest: /etc/systemd/system/varnish.service.d/evolinux.conf + force: yes + when: ansible_distribution_major_version is version('10', '>=') + notify: + - reload systemd + - restart varnish + tags: + - varnish - name: Patch logrotate conf replace: @@ -57,22 +70,26 @@ - varnishlog - varnishncsa tags: - - varnish + - varnish - name: Copy Varnish configuration template: src: "{{ item }}" - dest: /etc/varnish/default.vcl + dest: "{{ varnish_config_file }}" mode: "0644" force: yes with_first_found: - - "templates/varnish/default.{{ inventory_hostname }}.vcl.j2" - - "templates/varnish/default.{{ host_group }}.vcl.j2" - - "templates/varnish/default.default.vcl.j2" - - "default.vcl.j2" + - "templates/varnish/varnish.{{ inventory_hostname }}.vcl.j2" + - "templates/varnish/default.{{ inventory_hostname }}.vcl.j2" + - "templates/varnish/varnish.{{ host_group }}.vcl.j2" + - "templates/varnish/default.{{ host_group }}.vcl.j2" + - "templates/varnish/varnish.default.vcl.j2" + - "templates/varnish/default.default.vcl.j2" + - "varnish.vcl.j2" + - "default.vcl.j2" notify: reload varnish tags: - - varnish + - varnish - name: Create Varnish config dir file: @@ -80,7 +97,7 @@ state: directory mode: "0755" tags: - - varnish + - varnish - name: Copy included Varnish config template: @@ -92,6 +109,6 @@ - "templates/varnish/conf.d/*.vcl" notify: reload varnish tags: - - varnish + - varnish - include: munin.yml diff --git a/varnish/templates/reload-vcl.sh.j2 b/varnish/templates/reload-vcl.sh.j2 new file mode 100644 index 00000000..e60d8257 --- /dev/null +++ b/varnish/templates/reload-vcl.sh.j2 @@ -0,0 +1,5 @@ +#!/bin/sh +UUID=`cat /proc/sys/kernel/random/uuid` +/usr/sbin/varnishd -C -f {{ varnish_config_file }} >/dev/null \ + && /usr/bin/varnishadm -T {{ varnish_management_address }} -S {{ varnish_secret_file }} "vcl.load vcl_$UUID {{ varnish_config_file }}" \ + && /usr/bin/varnishadm -T {{ varnish_management_address }} -S {{ varnish_secret_file }} "vcl.use vcl_$UUID" diff --git a/varnish/templates/varnish.conf.buster.j2 b/varnish/templates/varnish.conf.buster.j2 new file mode 100644 index 00000000..09dcf7c4 --- /dev/null +++ b/varnish/templates/varnish.conf.buster.j2 @@ -0,0 +1,5 @@ +# {{ ansible_managed }} + +[Service] +ExecStart= +ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F {{ varnish_addresses | map('regex_replace', '^(.*)$', '-a \\1') | list | join(' ') }} -T {{ varnish_management_address }} -f {{ varnish_config_file }} -S {{ varnish_secret_file }} -s {{ varnish_storage }} -p thread_pools={{ varnish_thread_pools }} -p thread_pool_add_delay={{ varnish_thread_pool_add_delay }} -p thread_pool_min={{ varnish_thread_pool_min }} -p thread_pool_max={{ varnish_thread_pool_max }} diff --git a/varnish/templates/varnish.conf.j2 b/varnish/templates/varnish.conf.j2 deleted file mode 100644 index 3020d556..00000000 --- a/varnish/templates/varnish.conf.j2 +++ /dev/null @@ -1,7 +0,0 @@ -# {{ ansible_managed }} - -[Service] -ExecStart= -ExecStart=/usr/sbin/varnishd -F {{ varnish_addresses | map('regex_replace', '^(.*)$', '-a \\1') | list | join(' ') }} -T {{ varnish_management_address }} -f {{ varnish_config_file }} -S {{ varnish_secret_file }} -s {{ varnish_storage }} -p thread_pools={{ varnish_thread_pools }} -p thread_pool_add_delay={{ varnish_thread_pool_add_delay }} -p thread_pool_min={{ varnish_thread_pool_min }} -p thread_pool_max={{ varnish_thread_pool_max }} -ExecReload= -ExecReload=/etc/varnish/reload-vcl.sh diff --git a/varnish/templates/varnish.conf.jessie.j2 b/varnish/templates/varnish.conf.jessie.j2 new file mode 100644 index 00000000..59651b36 --- /dev/null +++ b/varnish/templates/varnish.conf.jessie.j2 @@ -0,0 +1,7 @@ +# {{ ansible_managed }} + +[Service] +ExecStart= +ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F {{ varnish_addresses | map('regex_replace', '^(.*)$', '-a \\1') | list | join(' ') }} -T {{ varnish_management_address }} -f {{ varnish_config_file }} -S {{ varnish_secret_file }} -s {{ varnish_storage }} -p thread_pools={{ varnish_thread_pools }} -p thread_pool_add_delay={{ varnish_thread_pool_add_delay }} -p thread_pool_min={{ varnish_thread_pool_min }} -p thread_pool_max={{ varnish_thread_pool_max }} +ExecReload= +ExecReload=/etc/varnish/reload-vcl.sh diff --git a/varnish/templates/default.vcl.j2 b/varnish/templates/varnish.vcl.j2 similarity index 100% rename from varnish/templates/default.vcl.j2 rename to varnish/templates/varnish.vcl.j2 diff --git a/webapps/evoadmin-web/tasks/user.yml b/webapps/evoadmin-web/tasks/user.yml index 5aa6c29c..7b58270c 100644 --- a/webapps/evoadmin-web/tasks/user.yml +++ b/webapps/evoadmin-web/tasks/user.yml @@ -6,6 +6,7 @@ comment: "Evoadmin Web Account" home: "{{ evoadmin_home_dir }}" password: "!" + system: yes - name: Create www-evoadmin group group: @@ -22,6 +23,7 @@ - name: "Create www-evoadmin (Debian 9 or later)" user: name: www-evoadmin + system: yes when: ansible_distribution_major_version is version('9', '>=') - name: Is /etc/aliases present? diff --git a/webapps/nextcloud/defaults/main.yml b/webapps/nextcloud/defaults/main.yml new file mode 100644 index 00000000..cb8b70a0 --- /dev/null +++ b/webapps/nextcloud/defaults/main.yml @@ -0,0 +1,19 @@ +--- +nextcloud_webserver: 'nginx' +nextcloud_version: "20.0.0" +nextcloud_archive_name: "nextcloud-{{ nextcloud_version }}.tar.bz2" +nextcloud_releases_baseurl: "https://download.nextcloud.com/server/releases/" + +nextcloud_instance_name: "nextcloud" +nextcloud_user: "{{ nextcloud_instance_name }}" +nextcloud_domains: [] + +nextcloud_home: "/home/{{ nextcloud_user }}" +nextcloud_webroot: "{{ nextcloud_home }}/nextcloud" +nextcloud_data: "{{ nextcloud_webroot }}/data" + +nextcloud_db_user: "{{ nextcloud_user }}" +nextcloud_db_name: "{{ nextcloud_instance_name }}" + +nextcloud_admin_login: "admin" +nextcloud_admin_password: "" diff --git a/webapps/nextcloud/handlers/main.yml b/webapps/nextcloud/handlers/main.yml new file mode 100644 index 00000000..2db4770d --- /dev/null +++ b/webapps/nextcloud/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: reload php-fpm + service: + name: php7.3-fpm + state: reloaded + +- name: reload nginx + service: + name: nginx + state: reloaded diff --git a/webapps/nextcloud/meta/main.yml b/webapps/nextcloud/meta/main.yml new file mode 100644 index 00000000..d5852e32 --- /dev/null +++ b/webapps/nextcloud/meta/main.yml @@ -0,0 +1,4 @@ +--- +# dependencies: + # - { role: nginx, when: nextcloud_webserver == 'nginx' } + # - { role: php, php_fpm_enable: True } diff --git a/webapps/nextcloud/tasks/archive.yml b/webapps/nextcloud/tasks/archive.yml new file mode 100644 index 00000000..d59bd582 --- /dev/null +++ b/webapps/nextcloud/tasks/archive.yml @@ -0,0 +1,37 @@ +--- + +- name: Retrieve Nextcloud archive + get_url: + url: "{{ nextcloud_releases_baseurl }}{{ nextcloud_archive_name }}" + dest: "{{ nextcloud_home }}/{{ nextcloud_archive_name }}" + force: no + tags: + - nextcloud + +- name: Retrieve Nextcloud sha256 checksum + get_url: + url: "{{ nextcloud_releases_baseurl }}{{ nextcloud_archive_name }}.sha256" + dest: "{{ nextcloud_home }}/{{ nextcloud_archive_name }}.sha256" + force: no + tags: + - nextcloud + +- name: Verify Nextcloud sha256 checksum + command: "sha256sum -c {{ nextcloud_archive_name }}.sha256" + changed_when: "False" + args: + chdir: "{{ nextcloud_home }}" + tags: + - nextcloud + +- name: Extract Nextcloud archive + unarchive: + src: "{{ nextcloud_home }}/{{ nextcloud_archive_name }}" + dest: "{{ nextcloud_home }}" + creates: "{{ nextcloud_home }}/nextcloud" + remote_src: True + mode: "0750" + owner: "{{ nextcloud_user }}" + group: "{{ nextcloud_user }}" + tags: + - nextcloud diff --git a/webapps/nextcloud/tasks/config.yml b/webapps/nextcloud/tasks/config.yml new file mode 100644 index 00000000..a4e3a3e7 --- /dev/null +++ b/webapps/nextcloud/tasks/config.yml @@ -0,0 +1,81 @@ +--- + +- block: + - name: Generate admin password + command: 'apg -n 1 -m 16 -M lcN' + register: nextcloud_admin_password_apg + check_mode: no + changed_when: False + + - debug: + var: nextcloud_admin_password_apg + + - set_fact: + nextcloud_admin_password: "{{ nextcloud_admin_password_apg.stdout }}" + + tags: + - nextcloud + when: nextcloud_admin_password == "" + +- name: Get Nextcloud Status + shell: "php ./occ status --output json | grep -v 'Nextcloud is not installed'" + args: + chdir: "{{ nextcloud_webroot }}" + become_user: "{{ nextcloud_user }}" + register: nc_status + check_mode: no + tags: + - nextcloud + +- name: Install Nextcloud + command: "php ./occ maintenance:install --database mysql --database-name {{ nextcloud_db_name | mandatory }} --database-user {{ nextcloud_db_user | mandatory }} --database-pass {{ nextcloud_db_pass | mandatory }} --admin-user {{ nextcloud_admin_login | mandatory }} --admin-pass {{ nextcloud_admin_password | mandatory }} --data-dir {{ nextcloud_data | mandatory }}" + args: + chdir: "{{ nextcloud_webroot }}" + creates: "{{ nextcloud_home }}/config/config.php" + become_user: "{{ nextcloud_user }}" + when: (nc_status.stdout | from_json).installed == false + tags: + - nextcloud + +- name: Configure Nextcloud Mysql password + replace: + dest: "{{ nextcloud_home }}/nextcloud/config/config.php" + regexp: "'dbpassword' => '([^']*)'," + replace: "'dbpassword' => '{{ nextcloud_db_pass }}'," + tags: + - nextcloud + +- name: Configure Nextcloud cron + cron: + name: 'Nextcloud' + minute: "*/5" + job: "php -f {{ nextcloud_webroot }}/cron.php" + user: "{{ nextcloud_user }}" + tags: + - nextcloud + +- name: Erase previously trusted domains config + command: "php ./occ config:system:set trusted_domains" + args: + chdir: "{{ nextcloud_webroot }}" + become_user: "{{ nextcloud_user }}" + tags: + - nextcloud + +- name: Configure trusted domains + command: "php ./occ config:system:set trusted_domains {{ item.0 }} --value {{ item.1 }}" + args: + chdir: "{{ nextcloud_webroot }}" + with_indexed_items: + - "{{ nextcloud_domains }}" + become_user: "{{ nextcloud_user }}" + tags: + - nextcloud + +#- name: Configure memcache local to APCu +# command: "php ./occ config:system:set memcache.local --value '\\OC\\Memcache\\APCu'" +# args: +# chdir: "{{ nextcloud_webroot }}" +# become_user: "{{ nextcloud_user }}" +# tags: +# - nextcloud diff --git a/webapps/nextcloud/tasks/main.yml b/webapps/nextcloud/tasks/main.yml new file mode 100644 index 00000000..2c525114 --- /dev/null +++ b/webapps/nextcloud/tasks/main.yml @@ -0,0 +1,31 @@ +--- +- name: Install dependencies + apt: + state: present + name: + - bzip2 + - php-gd + - php-json + - php-xml + - php-mbstring + - php-zip + - php-curl + - php-bz2 + - php-intl + - php-gmp + - php-apcu + - php-redis + - php-bcmath + - python-mysqldb + tags: + - nextcloud + +- include: user.yml + +- include: archive.yml + +- include: vhost.yml + +- include: mysql.yml + +- include: config.yml diff --git a/webapps/nextcloud/tasks/mysql.yml b/webapps/nextcloud/tasks/mysql.yml new file mode 100644 index 00000000..f2fcee32 --- /dev/null +++ b/webapps/nextcloud/tasks/mysql.yml @@ -0,0 +1,62 @@ +--- +- name: Get actual Mysql password + shell: "grep password {{ nextcloud_home }}/.my.cnf | awk '{ print $3 }'" + register: nextcloud_db_pass_grep + check_mode: no + changed_when: False + failed_when: False + tags: + - nextcloud + +- name: Generate Mysql password + command: 'apg -n 1 -m 16 -M lcN' + register: nextcloud_db_pass_apg + check_mode: no + changed_when: False + tags: + - nextcloud + +- name: Set Mysql password + set_fact: + nextcloud_db_pass: "{{ nextcloud_db_pass_grep.stdout | default(nextcloud_db_pass_apg.stdout, True) }}" + tags: + - nextcloud + +- debug: + var: nextcloud_db_pass + verbosity: 1 + +- name: Create Mysql database + mysql_db: + name: "{{ nextcloud_db_name }}" + config_file: "/root/.my.cnf" + state: present + tags: + - nextcloud + +- name: Create Mysql user + mysql_user: + name: "{{ nextcloud_db_user }}" + password: '{{ nextcloud_db_pass }}' + priv: "{{ nextcloud_db_name }}.*:ALL" + config_file: "/root/.my.cnf" + update_password: always + state: present + tags: + - nextcloud + +- name: Store credentials in my.cnf + ini_file: + dest: "{{ nextcloud_home }}/.my.cnf" + owner: "{{ nextcloud_user }}" + group: "{{ nextcloud_user }}" + mode: "0600" + section: client + option: "{{ item.option }}" + value: "{{ item.value }}" + with_items: + - { option: "user", value: "{{ nextcloud_db_user }}" } + - { option: "database", value: "{{ nextcloud_db_name }}" } + - { option: "password", value: "{{ nextcloud_db_pass }}" } + tags: + - nextcloud diff --git a/webapps/nextcloud/tasks/user.yml b/webapps/nextcloud/tasks/user.yml new file mode 100644 index 00000000..07d5a31a --- /dev/null +++ b/webapps/nextcloud/tasks/user.yml @@ -0,0 +1,38 @@ +--- +- name: Create Nextcloud group + group: + name: "{{ nextcloud_instance_name | mandatory }}" + state: present + tags: + - nextcloud + +- name: Create Nextcloud user + user: + name: "{{ nextcloud_user | mandatory }}" + group: "{{ nextcloud_user }}" + home: "{{ nextcloud_home | mandatory }}" + shell: '/bin/bash' + createhome: True + state: present + tags: + - nextcloud + +- name: Add the user 'www-data' to Nextcloud group + user: + name: www-data + groups: "{{ nextcloud_user | mandatory }}" + append: yes + +- name: Create top-level directories + file: + dest: "{{ item }}" + state: directory + mode: "0770" + owner: "{{ nextcloud_user }}" + group: "{{ nextcloud_user }}" + with_items: + - "{{ nextcloud_home }}/log" + - "{{ nextcloud_home }}/tmp" + - "{{ nextcloud_home }}/data" + tags: + - nextcloud diff --git a/webapps/nextcloud/tasks/vhost.yml b/webapps/nextcloud/tasks/vhost.yml new file mode 100644 index 00000000..1f1592cc --- /dev/null +++ b/webapps/nextcloud/tasks/vhost.yml @@ -0,0 +1,34 @@ +--- +- block: + - name: Copy Nginx vhost + template: + src: nginx.conf.j2 + dest: "/etc/nginx/sites-available/{{ nextcloud_instance_name }}.conf" + mode: "0640" + notify: reload nginx + tags: + - nextcloud + + - name: Enable Nginx vhost + file: + src: "/etc/nginx/sites-available/{{ nextcloud_instance_name }}.conf" + dest: "/etc/nginx/sites-enabled/{{ nextcloud_instance_name }}.conf" + state: link + notify: reload nginx + tags: + - nextcloud + + - name: Generate ssl config + shell: + cmd: "/usr/local/sbin/vhost-domains {{ nextcloud_instance_name }} | /usr/local/sbin/make-csr {{ nextcloud_instance_name }}" + creates: "/etc/nginx/ssl/{{ nextcloud_instance_name }}.conf" + + - name: Copy PHP-FPM pool + template: + src: php-fpm.conf.j2 + dest: "/etc/php/7.3/fpm/pool.d/{{ nextcloud_instance_name }}.conf" + mode: "0640" + notify: reload php-fpm + tags: + - nextcloud + when: nextcloud_webserver == 'nginx' diff --git a/webapps/nextcloud/templates/nginx.conf.j2 b/webapps/nextcloud/templates/nginx.conf.j2 new file mode 100644 index 00000000..ffb72f01 --- /dev/null +++ b/webapps/nextcloud/templates/nginx.conf.j2 @@ -0,0 +1,134 @@ +upstream php-handler-{{ nextcloud_instance_name }} { + server unix:/var/run/php/php-fpm-{{ nextcloud_instance_name }}.sock; +} + +server { + listen 80; + listen [::]:80; + listen 443 ssl http2; + listen [::]:443 ssl http2; + + server_name {{ nextcloud_domains | join(' ') }}; + + access_log {{ nextcloud_home }}/log/access.log; + error_log {{ nextcloud_home }}/log/error.log; + + include /etc/nginx/snippets/letsencrypt.conf; + include /etc/nginx/ssl/{{ nextcloud_instance_name }}.conf; + + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Download-Options "noopen" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "none" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Remove X-Powered-By, which is an information leak + fastcgi_hide_header X-Powered-By; + + root {{ nextcloud_webroot }}; + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # The following 2 rules are only needed for the user_webfinger app. + # Uncomment it if you're planning to use this app. + rewrite ^/.well-known/host-meta /public.php?service=host-meta last; + rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; + + # The following rule is only needed for the Social app. + # Uncomment it if you're planning to use this app. + rewrite ^/.well-known/webfinger /public.php?service=webfinger last; + + location = /.well-known/carddav { + return 301 $scheme://$host:$server_port/remote.php/dav; + } + location = /.well-known/caldav { + return 301 $scheme://$host:$server_port/remote.php/dav; + } + + # set max upload size + client_max_body_size 512M; + fastcgi_buffers 64 4K; + + # Enable gzip but do not remove ETag headers + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + + location / { + rewrite ^ /index.php; + } + + location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { + deny all; + } + location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { + deny all; + } + + + location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy)\.php(?:$|\/) { + fastcgi_split_path_info ^(.+?\.php)(\/.*|)$; + set $path_info $fastcgi_path_info; + try_files $fastcgi_script_name =404; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $path_info; + fastcgi_param HTTPS on; + # Avoid sending the security headers twice + fastcgi_param modHeadersAvailable true; + # Enable pretty urls + fastcgi_param front_controller_active true; + fastcgi_pass php-handler-{{ nextcloud_instance_name }}; + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + } + + location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { + try_files $uri/ =404; + index index.php; + } + + # Adding the cache control header for js, css and map files + # Make sure it is BELOW the PHP block + location ~ \.(?:css|js|woff2?|svg|gif|map)$ { + try_files $uri /index.php$request_uri; + add_header Cache-Control "public, max-age=15778463"; + # Add headers to serve security related headers (It is intended to + # have those duplicated to the ones above) + # Before enabling Strict-Transport-Security headers please read into + # this topic first. + #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; + # + # WARNING: Only add the preload option once you read about + # the consequences in https://hstspreload.org/. This option + # will add the domain to a hardcoded list that is shipped + # in all major browsers and getting removed from this list + # could take several months. + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Download-Options "noopen" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "none" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Optional: Don't log access to assets + access_log off; + } + + location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ { + try_files $uri /index.php$request_uri; + # Optional: Don't log access to other assets + access_log off; + } +} diff --git a/webapps/nextcloud/templates/php-fpm.conf.j2 b/webapps/nextcloud/templates/php-fpm.conf.j2 new file mode 100644 index 00000000..1b4c7861 --- /dev/null +++ b/webapps/nextcloud/templates/php-fpm.conf.j2 @@ -0,0 +1,17 @@ +[{{ nextcloud_instance_name }}] +user = {{ nextcloud_user }} +group = {{ nextcloud_user }} +listen = /run/php/php-fpm-{{ nextcloud_instance_name }}.sock +listen.owner = {{ nextcloud_user }} +listen.group = {{ nextcloud_user }} + +pm = ondemand +pm.max_children = 50 +pm.process_idle_timeout = 120s +pm.status_path = /fpm_status + +env[HOSTNAME] = $HOSTNAME +env[PATH] = /usr/local/bin:/usr/bin:/bin +env[TMP] = {{ nextcloud_home }}/tmp +env[TMPDIR] = {{ nextcloud_home }}/tmp +env[TEMP] = {{ nextcloud_home }}/tmp