diff --git a/CHANGELOG.md b/CHANGELOG.md index 4826724a..15539488 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,31 @@ The **patch** part changes incrementally at each release. ### Security +## [9.4.0] - 2018-09-20 + +### Added +* etc-git: manage a cron job to monitor uncommited changes in /etc/.git (default: `True`) +* evolinux-base: better shell history +* evolinux-users: add user to /etc/aliases +* generate-ldif: add a section for postgresql +* logstash: tmp directory can be customized +* logstash: max memory is set to 512M by default +* logstash: version 6.x is installed by default +* mysql: add a variable to prevent mysql from restarting +* networkd-to-ifconfig: add a role to switch from networkd to ifconfig +* webapps/evoadmin-web: add users to /etc/aliases +* redis: add support for multi instances +* nagios-nrpe: add check_redis_instances + +### Changed +* dovecot: stronger TLS configuration + +### Fixed +* apache: cleaner way to overwrite the server status suffix +* packweb-apache: don't regenerate phpMyAdmin suffix each time +* nginx: cleaner way to overwrite the server status suffix +* redis: add missing tags + ## [9.3.2] - 2018-09-06 ### Added diff --git a/apache/tasks/server_status.yml b/apache/tasks/server_status.yml index 696f2592..f9e1aed8 100644 --- a/apache/tasks/server_status.yml +++ b/apache/tasks/server_status.yml @@ -9,7 +9,11 @@ state: directory - name: set apache serverstatus suffix if provided - shell: "echo {{ apache_serverstatus_suffix }} > {{ apache_serverstatus_suffix_file }}" + copy: + dest: "{{ apache_serverstatus_suffix_file }}" + # The last character "\u000A" is a line feed (LF), it's better to keep it + content: "{{ apache_serverstatus_suffix }}\u000A" + force: yes when: apache_serverstatus_suffix != "" - name: generate random string for server-status suffix diff --git a/dovecot/templates/z-evolinux-defaults.conf.j2 b/dovecot/templates/z-evolinux-defaults.conf.j2 index 787b9d01..2c067b99 100644 --- a/dovecot/templates/z-evolinux-defaults.conf.j2 +++ b/dovecot/templates/z-evolinux-defaults.conf.j2 @@ -37,5 +37,10 @@ mail_max_userip_connections = 42 # SSL/TLS ssl = yes +ssl_prefer_server_ciphers = yes +ssl_dh_parameters_length = 2048 +ssl_options = no_compression no_ticket +ssl_protocols = !TLSv1 !TLSv1.1 +ssl_cipher_list = ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS ssl_cert = =') - when: (elasticsearch_custom_tmpdir != '' and elasticsearch_custom_tmpdir != None) or fstab_tmp_noexec | success + when: (elasticsearch_custom_tmpdir != '' and elasticsearch_custom_tmpdir != None) or fstab_tmp_noexec.rc == 0 diff --git a/etc-git/README.md b/etc-git/README.md index 9028cc1c..2d3c3840 100644 --- a/etc-git/README.md +++ b/etc-git/README.md @@ -29,3 +29,7 @@ There is also an independant task that can be executed to commit changes made in vars: commit_message: "Ansible post-run my splendid playbook" ``` + +## Available variables + +* `etc_git_monitor_status`: monitor uncommited changes in /etc/.git (default: `True`) ; diff --git a/etc-git/defaults/main.yml b/etc-git/defaults/main.yml index 2743375a..8a822abd 100644 --- a/etc-git/defaults/main.yml +++ b/etc-git/defaults/main.yml @@ -1,2 +1,4 @@ --- commit_message: Ansible run + +etc_git_monitor_status: True diff --git a/etc-git/tasks/main.yml b/etc-git/tasks/main.yml index 452711c9..029d102c 100644 --- a/etc-git/tasks/main.yml +++ b/etc-git/tasks/main.yml @@ -88,3 +88,20 @@ force: no tags: - etc-git + +- name: Cron job for /etc/.git status is installed + template: + src: etc-git-status.j2 + dest: /etc/cron.d/etc-git-status + mode: "0644" + when: etc_git_monitor_status + tags: + - etc-git + +- name: Cron job for /etc/.git status is removed + file: + dest: /etc/cron.d/etc-git-status + state: absent + when: not etc_git_monitor_status + tags: + - etc-git diff --git a/etc-git/templates/etc-git-status.j2 b/etc-git/templates/etc-git-status.j2 new file mode 100644 index 00000000..e1696c54 --- /dev/null +++ b/etc-git/templates/etc-git-status.j2 @@ -0,0 +1,4 @@ +# {{ ansible_managed }} + +@hourly root who > /dev/null || git --git-dir=/etc/.git --work-tree=/etc status --short +21 21 * * * root git --git-dir=/etc/.git --work-tree=/etc status --short diff --git a/evolinux-base/tasks/root.yml b/evolinux-base/tasks/root.yml index 8fb2d113..ae2d8a89 100644 --- a/evolinux-base/tasks/root.yml +++ b/evolinux-base/tasks/root.yml @@ -14,9 +14,11 @@ create: yes state: present with_items: - - "export HISTCONTROL=$HISTCONTROL${HISTCONTROL+,}ignoreboth" + - "export HISTCONTROL=$HISTCONTROL${HISTCONTROL+,}ignoreboth,erasedups" - "export HISTSIZE=65535" - "export HISTTIMEFORMAT=\"%c : \"" + - "shopt -s histappend" + - "PROMPT_COMMAND=\"history -a;${PROMPT_COMMAND}\"" when: evolinux_root_bashrc ## .bash_history should be append-only diff --git a/evolinux-users/tasks/user.yml b/evolinux-users/tasks/user.yml index bd480cfb..9859db2f 100644 --- a/evolinux-users/tasks/user.yml +++ b/evolinux-users/tasks/user.yml @@ -41,6 +41,20 @@ - loginisbusy.rc != 0 - uidisbusy.rc == 0 +- name: Is /etc/aliases present? + stat: + path: /etc/aliases + register: etc_aliases + +- name: Set mail alias + lineinfile: + state: present + dest: /etc/aliases + line: '{{ user.name }}: root' + regexp: '^{{ user.name }}:' + when: etc_aliases.stat.exists + notify: "newaliases" + # Unix groups ## Group for SSH authorizations diff --git a/generate-ldif/templates/generateldif.sh.j2 b/generate-ldif/templates/generateldif.sh.j2 index 73fe88c8..778c4fcf 100755 --- a/generate-ldif/templates/generateldif.sh.j2 +++ b/generate-ldif/templates/generateldif.sh.j2 @@ -547,6 +547,24 @@ ServiceVersion: Elasticsearch ${elasticsearch_version} EOT fi +# PostgreSQL +if is_pkg_installed postgresql; then + postgresql_version=$(get_pkg_version postgresql) +fi +if [ -n "${postgresql_version}" ]; then + cat <> "${ldif_file}" + +dn: ServiceName=postgresql,${computer_dn} +NagiosEnabled: TRUE +ipServiceProtocol: tcp +objectClass: EvoService +ServiceName: postgresql +ipServicePort: 5432 +ServiceType: database +ServiceVersion: PostgreSQL ${elasticsearch_version} +EOT +fi + # test if we have a stdout if [ -t 1 ]; then echo "Output is in ${ldif_file}" diff --git a/logstash/defaults/main.yml b/logstash/defaults/main.yml index 38b7f85f..456769cd 100644 --- a/logstash/defaults/main.yml +++ b/logstash/defaults/main.yml @@ -1,6 +1,8 @@ --- -elastic_stack_version: "5.x" +elastic_stack_version: "6.x" logstash_jvm_xms: 256m -logstash_jvm_xmx: 1g +logstash_jvm_xmx: 512g logstash_log_rotate_days: 365 +logstash_custom_tmpdir: Null +logstash_default_tmpdir: /var/lib/logstash/tmp diff --git a/logstash/tasks/main.yml b/logstash/tasks/main.yml index 8f740424..e6438abe 100644 --- a/logstash/tasks/main.yml +++ b/logstash/tasks/main.yml @@ -75,3 +75,5 @@ verbosity: 1 - include: logs.yml + +- include: tmpdir.yml diff --git a/logstash/tasks/tmpdir.yml b/logstash/tasks/tmpdir.yml new file mode 100644 index 00000000..4149f5af --- /dev/null +++ b/logstash/tasks/tmpdir.yml @@ -0,0 +1,31 @@ +--- + +- name: Check if /tmp is noexec + shell: "cat /etc/fstab | grep -E \" +/tmp\" | grep noexec" + register: fstab_tmp_noexec + failed_when: False + changed_when: False + check_mode: no + +- block: + - name: "Create {{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + file: + path: "{{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + owner: logstash + group: logstash + mode: "0755" + state: directory + tags: + - logstash + + - name: change JVM tmpdir + lineinfile: + dest: /etc/logstash/jvm.options + line: "-Djava.io.tmpdir={{ logstash_custom_tmpdir or logstash_default_tmpdir | mandatory }}" + regexp: "^-Djava.io.tmpdir=" + insertafter: "## JVM configuration" + notify: + - restart logstash + tags: + - logstash + when: (logstash_custom_tmpdir != '' and logstash_custom_tmpdir != None) or fstab_tmp_noexec.rc == 0 diff --git a/mysql-oracle/README.md b/mysql-oracle/README.md index 5d09720e..011e1ac3 100644 --- a/mysql-oracle/README.md +++ b/mysql-oracle/README.md @@ -28,6 +28,7 @@ Tasks are extracted in several files, included in `tasks/main.yml` : * `general_scripts_dir`: general directory for scripts installation (default: `/usr/local/bin`). * `mysql_scripts_dir`: email address to send Log2mail messages to (default: `general_scripts_dir`). * `mysql_force_new_nrpe_password` : change the password for NRPE even if it exists already (default: `False`). +* `mysql_restart_if_needed` : should the restart handler be executed (default: `True`) NB : changing the _datadir_ location can be done multiple times, as long as it is not restored to the default initial location, (because a symlink is created and can't be switched back, yet). diff --git a/mysql-oracle/defaults/main.yml b/mysql-oracle/defaults/main.yml index e37f0680..d9724ca2 100644 --- a/mysql-oracle/defaults/main.yml +++ b/mysql-oracle/defaults/main.yml @@ -22,3 +22,5 @@ mysql_cron_mysqltuner: True mysql_cron_mysqltuner_frequency: monthly mysql_force_new_nrpe_password: False + +mysql_restart_if_needed: True diff --git a/mysql-oracle/handlers/main.yml b/mysql-oracle/handlers/main.yml index 5a82afae..c89d562a 100644 --- a/mysql-oracle/handlers/main.yml +++ b/mysql-oracle/handlers/main.yml @@ -14,6 +14,11 @@ name: mysql state: restarted +- name: restart mysql (noop) + meta: noop + failed_when: False + changed_when: False + - name: reload systemd systemd: name: mysql diff --git a/mysql-oracle/tasks/main.yml b/mysql-oracle/tasks/main.yml index 273960a9..2e2f09bf 100644 --- a/mysql-oracle/tasks/main.yml +++ b/mysql-oracle/tasks/main.yml @@ -1,5 +1,8 @@ --- +- set_fact: + mysql_restart_handler_name: "{{ mysql_restart_if_needed | bool | ternary('restart mysql', 'restart mysql (noop)') }}" + - include: packages.yml - include: users.yml diff --git a/mysql-oracle/tasks/tmpdir.yml b/mysql-oracle/tasks/tmpdir.yml index ca560077..8d518160 100644 --- a/mysql-oracle/tasks/tmpdir.yml +++ b/mysql-oracle/tasks/tmpdir.yml @@ -17,7 +17,7 @@ section: mysqld option: tmpdir value: "{{ mysql_custom_tmpdir }}" - notify: restart mysql + notify: "{{ mysql_restart_handler_name }}" tags: - mysql when: mysql_custom_tmpdir != '' diff --git a/mysql/README.md b/mysql/README.md index 4c813a15..6941df20 100644 --- a/mysql/README.md +++ b/mysql/README.md @@ -38,5 +38,6 @@ Tasks are extracted in several files, included in `tasks/main.yml` : * `mysql_scripts_dir`: email address to send Log2mail messages to (default: `general_scripts_dir`). * `mysql_force_new_nrpe_password` : change the password for NRPE even if it exists already (default: `False`). * `mysql_install_libclient`: install mysql client libraries (default: `False`). +* `mysql_restart_if_needed` : should the restart handler be executed (default: `True`) NB : changing the _datadir_ location can be done multiple times, as long as it is not restored to the default initial location, (because a symlink is created and can't be switched back, yet). diff --git a/mysql/defaults/main.yml b/mysql/defaults/main.yml index d93f7270..52bf8b07 100644 --- a/mysql/defaults/main.yml +++ b/mysql/defaults/main.yml @@ -40,3 +40,5 @@ mysql_force_new_nrpe_password: False mysql_evolinux_defaults_file: z-evolinux-defaults.cnf mysql_evolinux_custom_file: zzz-evolinux-custom.cnf + +mysql_restart_if_needed: True diff --git a/mysql/handlers/main.yml b/mysql/handlers/main.yml index 32c630af..2ea13151 100644 --- a/mysql/handlers/main.yml +++ b/mysql/handlers/main.yml @@ -14,6 +14,11 @@ name: mysql state: restarted +- name: restart mysql (noop) + meta: noop + failed_when: False + changed_when: False + - name: reload systemd systemd: name: mysql diff --git a/mysql/tasks/main.yml b/mysql/tasks/main.yml index dd9c2e99..9f9c07f4 100644 --- a/mysql/tasks/main.yml +++ b/mysql/tasks/main.yml @@ -1,5 +1,8 @@ --- +- set_fact: + mysql_restart_handler_name: "{{ mysql_restart_if_needed | bool | ternary('restart mysql', 'restart mysql (noop)') }}" + - include: packages_stretch.yml when: ansible_distribution_major_version | version_compare('9', '>=') diff --git a/mysql/tasks/tmpdir.yml b/mysql/tasks/tmpdir.yml index 35942612..e2c13dc5 100644 --- a/mysql/tasks/tmpdir.yml +++ b/mysql/tasks/tmpdir.yml @@ -17,7 +17,7 @@ section: mysqld option: tmpdir value: "{{ mysql_custom_tmpdir }}" - notify: restart mysql + notify: "{{ mysql_restart_handler_name }}" tags: - mysql when: mysql_custom_tmpdir != '' diff --git a/nagios-nrpe/files/plugins/check_redis_instances b/nagios-nrpe/files/plugins/check_redis_instances new file mode 100755 index 00000000..829cd81e --- /dev/null +++ b/nagios-nrpe/files/plugins/check_redis_instances @@ -0,0 +1,49 @@ +#!/bin/sh + +set -u + +return=0 +nb_crit=0 +nb_warn=0 +nb_ok=0 +nb_unchk=0 +output="" + +instances=$(ls /etc/redis/redis-*.conf) +for instance in ${instances}; do + name=$(basename "${instance}"| sed '{s/redis-//;s/.conf//}') + port=$(grep "port" "${instance}"|grep -oE "[0-9]*") + if [ -h "/etc/systemd/system/multi-user.target.wants/redis-server@${name}.service" ]; then + /usr/lib/nagios/plugins/check_tcp -p "${port}" >/dev/null 2>&1 + ret="${?}" + if [ "${ret}" -ge 2 ]; then + nb_crit=$((nb_crit + 1)) + output="${output}CRITICAL - ${name} (${port})\n" + [ "${return}" -le 2 ] && return=2 + elif [ "${ret}" -ge 1 ]; then + nb_warn=$((nb_warn + 1)) + output="${output}WARNING - ${name} (${port})\n" + [ "${return}" -le 1 ] && return=1 + else + nb_ok=$((nb_ok + 1)) + output="${output}OK - ${name} (${port})\n" + [ "${return}" -le 0 ] && return=0 + fi + else + nb_unchk=$((nb_unchk + 1)) + output="${output}UNCHK - ${name} (${port})\n" + fi +done + +[ "${return}" -ge 0 ] && header="OK" +[ "${return}" -ge 1 ] && header="WARNING" +[ "${return}" -ge 2 ] && header="CRITICAL" + +printf "%s - %s UNCHK / %s CRIT / %s WARN / %s OK\n\n" "${header}" "${nb_unchk}" "${nb_crit}" "${nb_warn}" "${nb_ok}" + +printf "${output}" | grep -E "^CRITICAL" +printf "${output}" | grep -E "^WARNING" +printf "${output}" | grep -E "^OK" +printf "${output}" | grep -E "^UNCHK" + +exit "${return}" diff --git a/nagios-nrpe/templates/evolix.cfg.j2 b/nagios-nrpe/templates/evolix.cfg.j2 index 845bae33..bab8b681 100644 --- a/nagios-nrpe/templates/evolix.cfg.j2 +++ b/nagios-nrpe/templates/evolix.cfg.j2 @@ -68,6 +68,7 @@ command[check_supervisord_status]={{ nagios_plugins_directory }}/check_superviso command[check_varnish]={{ nagios_plugins_directory }}/check_varnish_health -i 127.0.0.1 -p 6082 -s /etc/varnish/secret -w 2 -c 4 command[check_haproxy]={{ nagios_plugins_directory }}/check_haproxy_stats -s /var/run/haproxy.sock -w 80 -c 90 command[check_minifirewall]=sudo {{ nagios_plugins_directory }}/check_minifirewall +command[check_redis_instances]={{ nagios_plugins_directory }}/check_redis_instances # Check HTTP "many". Use this to check many websites (http, https, ports, sockets and SSL certificates). # Beware! All checks must not take more than 10s! diff --git a/networkd-to-ifconfig/README.md b/networkd-to-ifconfig/README.md new file mode 100644 index 00000000..dfcadf4b --- /dev/null +++ b/networkd-to-ifconfig/README.md @@ -0,0 +1,9 @@ +# networkd-to-ifconfig + +Switch back from systemd "networkd" to plain old /etc/network/interfaces. + +The role does nothing if an /etc/network/interfaces file is present. + +You should always double-check if everything seems OK, then reboot. + +Caveat: a public IPv4 and a public IPv6 are expected. diff --git a/networkd-to-ifconfig/meta/main.yml b/networkd-to-ifconfig/meta/main.yml new file mode 100644 index 00000000..e5cd8119 --- /dev/null +++ b/networkd-to-ifconfig/meta/main.yml @@ -0,0 +1,19 @@ +galaxy_info: + author: Evolix + description: Switch back from systemd "networkd" to plain old /etc/network/interfaces. + + issue_tracker_url: https://forge.evolix.org/projects/ansible-roles/issues + + license: GPLv2 + + min_ansible_version: 2.2 + + platforms: + - name: Debian + versions: + - stretch + +dependencies: [] + # List your role dependencies here, one per line. + # Be sure to remove the '[]' above if you add dependencies + # to this list. diff --git a/networkd-to-ifconfig/tasks/main.yml b/networkd-to-ifconfig/tasks/main.yml new file mode 100644 index 00000000..02ef0c53 --- /dev/null +++ b/networkd-to-ifconfig/tasks/main.yml @@ -0,0 +1,54 @@ +--- + +- name: Check state of /etc/network/interfaces + stat: + path: /etc/network/interfaces + register: interfaces_file + +- debug: + msg: A /etc/network/interfaces file already exists, nothing is done. + when: interfaces_file.stat.exists + +- block: + - name: "Parse addresses" + shell: "grep Address= /etc/systemd/network/50-default.network | cut -d'=' -f2" + register: network_address_grep + check_mode: no + + - name: "Parse gateways" + shell: "grep Gateway= /etc/systemd/network/50-default.network | cut -d'=' -f2" + register: network_gateway_grep + check_mode: no + + - name: Prepare variables + set_fact: + eni_interface_name: "{{ ansible_default_ipv4.interface }}" + eni_ipv4_address: "{{ network_address_grep.stdout_lines | ipv4 | first }}" + eni_ipv4_gateway: "{{ network_gateway_grep.stdout_lines | ipv4 | first }}" + eni_ipv6_address: "{{ network_address_grep.stdout_lines | ipv6 | first }}" + eni_ipv6_gateway: "{{ network_gateway_grep.stdout_lines | ipv6 | first }}" + + - name: "A new /etc/network/interfaces is generated" + template: + src: interfaces.j2 + dest: /etc/network/interfaces + mode: "0644" + owner: root + group: root + + - name: "Systemd 'networkd' unit is stopped and disabled" + systemd: + name: systemd-networkd.service + enabled: False + state: stopped + + - name: "Systemd 'networking' unit is restarted (it often results in error)" + systemd: + name: networking + enabled: True + state: restarted + ignore_errors: True + + - debug: + msg: You should verify your configuration, then reboot the server. + when: not interfaces_file.stat.exists diff --git a/networkd-to-ifconfig/templates/interfaces.j2 b/networkd-to-ifconfig/templates/interfaces.j2 new file mode 100644 index 00000000..f1030430 --- /dev/null +++ b/networkd-to-ifconfig/templates/interfaces.j2 @@ -0,0 +1,17 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +iface lo inet loopback + +# The primary network interface +auto {{ eni_interface_name }} +iface {{ eni_interface_name }} inet static + address {{ eni_ipv4_address }} + gateway {{ eni_ipv4_gateway }} + +iface {{ eni_interface_name }} inet6 static + address {{ eni_ipv6_address }} + gateway {{ eni_ipv6_gateway }} + post-up /sbin/ip -6 route add {{ eni_ipv6_gateway }} dev {{ eni_interface_name }} + post-up /sbin/ip -6 route add default via IPV6 diff --git a/nginx/tasks/server_status.yml b/nginx/tasks/server_status.yml index 4eeed7e7..7e84c1e4 100644 --- a/nginx/tasks/server_status.yml +++ b/nginx/tasks/server_status.yml @@ -9,7 +9,11 @@ state: directory - name: set nginx serverstatus suffix if provided - shell: "echo {{ nginx_serverstatus_suffix }} > {{ nginx_serverstatus_suffix_file }}" + copy: + dest: "{{ nginx_serverstatus_suffix_file }}" + # The last character "\u000A" is a line feed (LF), it's better to keep it + content: "{{ nginx_serverstatus_suffix }}\u000A" + force: yes when: nginx_serverstatus_suffix != "" - name: generate random string for server-status suffix diff --git a/packweb-apache/defaults/main.yml b/packweb-apache/defaults/main.yml index 7f79e90d..fa7a701a 100644 --- a/packweb-apache/defaults/main.yml +++ b/packweb-apache/defaults/main.yml @@ -8,5 +8,6 @@ packweb_apache_modphp: True packweb_apache_fpm: False packweb_phpmyadmin_suffix: "" +packweb_phpmyadmin_suffix_file: "/etc/evolinux/phpmyadmin_suffix" packweb_mysql_variant: "debian" diff --git a/packweb-apache/tasks/phpmyadmin.yml b/packweb-apache/tasks/phpmyadmin.yml index dfa779c1..eac50843 100644 --- a/packweb-apache/tasks/phpmyadmin.yml +++ b/packweb-apache/tasks/phpmyadmin.yml @@ -23,16 +23,40 @@ changed_when: "'Disabling' in command_result.stderr" when: pma_default_config.stat.exists +- name: "phpmyadmin suffix dirname '{{ packweb_phpmyadmin_suffix_file | dirname }}' exists" + file: + dest: "{{ packweb_phpmyadmin_suffix_file | dirname }}" + mode: "0700" + owner: root + group: root + state: directory + +- name: set phpmyadmin suffix if provided + copy: + dest: "{{ packweb_phpmyadmin_suffix_file }}" + # The last character "\u000A" is a line feed (LF), it's better to keep it + content: "{{ packweb_phpmyadmin_suffix }}\u000A" + force: yes + when: packweb_phpmyadmin_suffix != "" + - name: generate random string for phpmyadmin suffix - command: "apg -a 1 -M N -n 1" + shell: "apg -a 1 -M N -n 1 > {{ packweb_phpmyadmin_suffix_file }}" + args: + creates: "{{ packweb_phpmyadmin_suffix_file }}" + +- name: read phpmyadmin suffix + command: "tail -n 1 {{ packweb_phpmyadmin_suffix_file }}" changed_when: False - check_mode: False - register: _random_phpmyadmin_suffix + check_mode: no + register: new_packweb_phpmyadmin_suffix - name: overwrite packweb_phpmyadmin_suffix set_fact: - packweb_phpmyadmin_suffix: "{{ _random_phpmyadmin_suffix.stdout }}" - when: packweb_phpmyadmin_suffix == "" + packweb_phpmyadmin_suffix: "{{ new_packweb_phpmyadmin_suffix.stdout }}" + +- debug: + var: packweb_phpmyadmin_suffix + verbosity: 1 - name: enable phpMyAdmin config blockinfile: diff --git a/redis/defaults/main.yml b/redis/defaults/main.yml index 46aaf555..363fb0de 100644 --- a/redis/defaults/main.yml +++ b/redis/defaults/main.yml @@ -5,6 +5,7 @@ redis_conf_path: /etc/redis/redis.conf redis_port: 6379 redis_bind_interface: 127.0.0.1 redis_unixsocket: '/var/run/redis/redis.sock' +redis_pidfile: "/var/run/redis/{{ redis_daemon }}.pid" redis_timeout: 300 redis_password: NULL diff --git a/redis/files/redis-server@.service b/redis/files/redis-server@.service new file mode 100644 index 00000000..203f4b74 --- /dev/null +++ b/redis/files/redis-server@.service @@ -0,0 +1,18 @@ +[Unit] +Description=Advanced key-value store +After=network.target + +[Service] +ExecStartPre=/bin/mkdir -m 0755 -p /run/redis/%i +ExecStartPre=/bin/chown redis-%i: /run/redis/%i +PermissionsStartOnly=yes + +Type=forking +ExecStart=/usr/bin/redis-server /etc/redis/redis-%i.conf --unixsocket /run/redis/%i/redis.sock --pidfile /run/redis/%i/redis-server.pid +ExecStop=/usr/bin/redis-cli -s /run/redis/%i/redis.sock shutdown +Restart=always +User=redis-%i +Group=redis-%i + +[Install] +WantedBy=multi-user.target diff --git a/redis/handlers/main.yml b/redis/handlers/main.yml index 49b906a1..ed452e65 100644 --- a/redis/handlers/main.yml +++ b/redis/handlers/main.yml @@ -1,6 +1,6 @@ --- - name: restart redis - service: + systemd: name: "{{ redis_daemon }}" state: restarted diff --git a/redis/tasks/instances.yml b/redis/tasks/instances.yml new file mode 100644 index 00000000..151f47b4 --- /dev/null +++ b/redis/tasks/instances.yml @@ -0,0 +1,75 @@ +--- +- name: Systemd template for redis instances is installed + copy: + src: 'redis-server@.service' + dest: '/etc/systemd/system/' + mode: "0644" + tags: + - redis + +- name: Redis SysVinit script is stopped and disabled + service: + name: "redis-server" + enabled: no + state: stopped + tags: + - redis + +- name: Set variables for the instance + set_fact: + redis_daemon: "redis-server@{{ redis_instance_name }}" + redis_conf_path: "/etc/redis/redis-{{ redis_instance_name }}.conf" + redis_unixsocket: "/var/run/redis/{{ redis_instance_name }}/redis.sock" + redis_pidfile: "/var/run/redis/{{ redis_instance_name }}/{{ redis_daemon }}.pid" + redis_logfile: "/var/log/redis/{{ redis_instance_name }}/redis-server.log" + redis_dbdir: "/var/lib/redis/{{ redis_instance_name }}" + tags: + - redis + +- name: Redis instance configuration file is present. + template: + src: redis.conf.j2 + dest: "{{ redis_conf_path }}" + mode: "0644" + tags: + - redis + +- name: Redis instance group is present + group: + name: "redis-{{ redis_instance_name }}" + state: present + system: True + tags: + - redis + +- name: Redis instance user is present + user: + name: "redis-{{ redis_instance_name }}" + group: "redis-{{ redis_instance_name }}" + state: present + system: True + shell: '/bin/falase' + tags: + - redis + +- name: Instances directories are present + file: + dest: "{{ item }}" + state: directory + mode: "0755" + owner: "redis-{{ redis_instance_name }}" + group: "redis-{{ redis_instance_name }}" + with_items: + - "{{ redis_dbdir }}" + - "{{ redis_logfile | dirname }}" + tags: + - redis + +- name: Redis systemd unit is enabled and started + systemd: + name: "{{ redis_daemon }}" + enabled: yes + state: started + daemon_reload: yes + tags: + - redis diff --git a/redis/tasks/main.yml b/redis/tasks/main.yml index d9c997c9..c2d57d62 100644 --- a/redis/tasks/main.yml +++ b/redis/tasks/main.yml @@ -15,10 +15,17 @@ changed_when: false check_mode: no register: _redis_installed_version + tags: + - redis - set_fact: redis_installed_version: "{{ _redis_installed_version.stdout }}" check_mode: no + tags: + - redis + +- include: instances.yml + when: redis_instance_name is defined - name: Redis is configured. template: @@ -26,14 +33,16 @@ dest: "{{ redis_conf_path }}" mode: "0644" notify: restart redis + when: redis_instance_name is not defined tags: - redis - name: Redis is running and enabled on boot. - service: + systemd: name: "{{ redis_daemon }}" enabled: yes state: started + when: redis_instance_name is not defined tags: - redis diff --git a/redis/templates/redis.conf.j2 b/redis/templates/redis.conf.j2 index fc529903..d2e558cc 100644 --- a/redis/templates/redis.conf.j2 +++ b/redis/templates/redis.conf.j2 @@ -1,5 +1,5 @@ daemonize yes -pidfile /var/run/redis/{{ redis_daemon }}.pid +pidfile {{ redis_pidfile }} port {{ redis_port }} bind {{ redis_bind_interface }} diff --git a/webapps/evoadmin-mail/defaults/main.yml b/webapps/evoadmin-mail/defaults/main.yml index 000be699..b0652522 100644 --- a/webapps/evoadmin-mail/defaults/main.yml +++ b/webapps/evoadmin-mail/defaults/main.yml @@ -11,6 +11,7 @@ evoadminmail_scripts_dir: /usr/share/scripts/ evoadminmail_host: "evoadminmail.{{ ansible_fqdn }}" evoadminmail_enable_vhost: True +evoadminmail_webserver: apache evoadminmail_tpl_servername: "{{ ansible_fqdn }}" evoadminmail_tpl_address: "{{ ansible_default_ipv4.address }}" diff --git a/webapps/evoadmin-mail/files/pool.evoadmin-mail.conf b/webapps/evoadmin-mail/files/pool.evoadmin-mail.conf new file mode 100644 index 00000000..096e199f --- /dev/null +++ b/webapps/evoadmin-mail/files/pool.evoadmin-mail.conf @@ -0,0 +1,14 @@ +[evoadmin-mail] + +user = www-evoadmin-mail +group = evoadmin-mail + +listen = /run/php/php7.0-evoadmin-mail-fpm.sock + +listen.owner = www-data +listen.group = www-data +;listen.mode = 0660 + +pm = ondemand +pm.max_children = 25 + diff --git a/webapps/evoadmin-mail/handlers/main.yml b/webapps/evoadmin-mail/handlers/main.yml index 6866dc8b..236d93bf 100644 --- a/webapps/evoadmin-mail/handlers/main.yml +++ b/webapps/evoadmin-mail/handlers/main.yml @@ -3,3 +3,13 @@ service: name: apache2 state: reloaded + +- name: reload nginx + service: + name: nginx + state: reloaded + +- name: reload php-fpm + service: + name: php7.0-fpm + state: reload diff --git a/webapps/evoadmin-mail/tasks/web.yml b/webapps/evoadmin-mail/tasks/apache.yml similarity index 97% rename from webapps/evoadmin-mail/tasks/web.yml rename to webapps/evoadmin-mail/tasks/apache.yml index e7d915a3..b9c33383 100644 --- a/webapps/evoadmin-mail/tasks/web.yml +++ b/webapps/evoadmin-mail/tasks/apache.yml @@ -11,7 +11,7 @@ - name: Install evoadminmail VHost template: - src: evoadminmail.conf.j2 + src: apache_evoadminmail.conf.j2 dest: /etc/apache2/sites-available/evoadminmail.conf notify: reload apache2 diff --git a/webapps/evoadmin-mail/tasks/main.yml b/webapps/evoadmin-mail/tasks/main.yml index 0647bbcb..7d54c322 100644 --- a/webapps/evoadmin-mail/tasks/main.yml +++ b/webapps/evoadmin-mail/tasks/main.yml @@ -8,7 +8,11 @@ - include: ssl.yml -- include: web.yml +- include: apache.yml + when: evoadminmail_webserver == "apache" + +- include: nginx.yml + when: evoadminmail_webserver == "nginx" - name: enable evoadmin-mail link in default site index lineinfile: diff --git a/webapps/evoadmin-mail/tasks/nginx.yml b/webapps/evoadmin-mail/tasks/nginx.yml new file mode 100644 index 00000000..b942c024 --- /dev/null +++ b/webapps/evoadmin-mail/tasks/nginx.yml @@ -0,0 +1,35 @@ +--- + +- name: "Set custom values for PHP config (Debian 9 or later)" + ini_file: + dest: /etc/php/7.0/fpm/conf.d/zzz-evolinux-custom.ini + section: PHP + option: "disable_functions" + value: "shell-exec,system,passthru,putenv,popen,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority" + notify: reload nginx + when: ansible_distribution_major_version | version_compare('9', '>=') + +- name: Copy php-fpm evoadmin-mail pool + copy: + src: pool.evoadmin-mail.conf + dest: /etc/php/7.0/fpm/pool.d/evoadmin-mail.conf + notify: reload php-fpm + +- name: Install evoadminmail VHost + template: + src: nginx_evoadminmail.conf.j2 + dest: /etc/nginx/sites-available/evoadminmail.conf + notify: reload nginx + +- name: Active evoadminmail VHost + file: + src: "/etc/nginx/sites-available/evoadminmail.conf" + dest: "/etc/nginx/sites-enabled/evoadminmail.conf" + state: link + notify: reload nginx + when: evoadminmail_enable_vhost + +- name: Disable evoadminmail vhost + command: "unlink /etc/nginx/sites-enabled/evoadminmail.conf" + notify: reload nginx + when: not evoadminmail_enable_vhost diff --git a/webapps/evoadmin-mail/tasks/user.yml b/webapps/evoadmin-mail/tasks/user.yml index 5ec87f78..a45d09ec 100644 --- a/webapps/evoadmin-mail/tasks/user.yml +++ b/webapps/evoadmin-mail/tasks/user.yml @@ -29,6 +29,13 @@ createhome: no when: ansible_distribution_major_version | version_compare('9', '>=') +- name: Add www-data to app's group + user: + name: 'www-data' + groups: "{{ evoadminmail_username }}" + append: yes + when: evoadminmail_webserver == "nginx" + - name: Install Git apt: name: git diff --git a/webapps/evoadmin-mail/templates/evoadminmail.conf.j2 b/webapps/evoadmin-mail/templates/apache_evoadminmail.conf.j2 similarity index 100% rename from webapps/evoadmin-mail/templates/evoadminmail.conf.j2 rename to webapps/evoadmin-mail/templates/apache_evoadminmail.conf.j2 diff --git a/webapps/evoadmin-mail/templates/nginx_evoadminmail.conf.j2 b/webapps/evoadmin-mail/templates/nginx_evoadminmail.conf.j2 new file mode 100644 index 00000000..b3502d17 --- /dev/null +++ b/webapps/evoadmin-mail/templates/nginx_evoadminmail.conf.j2 @@ -0,0 +1,56 @@ +server { + listen [::]:80; + listen 80; + server_name {{ evoadminmail_host }}; + + return 301 https://{{ evoadminmail_host }}$request_uri; +} +server { + listen 443 ssl; + # listen [::]:80 default_server ipv6only=on; ## listen for ipv6 + + ssl_certificate /etc/ssl/certs/{{ evoadminmail_host }}.crt; + ssl_certificate_key /etc/ssl/private/{{ evoadminmail_host }}.key; + + server_name {{ evoadminmail_host }}; + index index.php; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + root {{ evoadminmail_document_root }}/htdocs/; + + location / { + index index.html index.htm; + } + + location ~ \.php$ { + fastcgi_pass unix:/run/php/php7.0-evoadmin-mail-fpm.sock; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + } + + location /fpm-status { + fastcgi_pass unix:/run/php/php7.0-evoadmin-mail-fpm.sock; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + allow 127.0.0.1; +{% for ip in nginx_additional_ipaddr_whitelist_ips %} + allow {{ ip }}; +{% endfor %} + deny all; + } + + location /nginx_status { + stub_status on; + access_log off; + allow 127.0.0.1; +{% for ip in nginx_additional_ipaddr_whitelist_ips %} + allow {{ ip }}; +{% endfor %} + deny all; + } + +} diff --git a/webapps/evoadmin-web/handlers/main.yml b/webapps/evoadmin-web/handlers/main.yml index c4cdb576..edb3404e 100644 --- a/webapps/evoadmin-web/handlers/main.yml +++ b/webapps/evoadmin-web/handlers/main.yml @@ -4,3 +4,6 @@ service: name: apache2 state: reloaded + +- name: newaliases + command: newaliases diff --git a/webapps/evoadmin-web/tasks/user.yml b/webapps/evoadmin-web/tasks/user.yml index 39926c0c..947b3cd0 100644 --- a/webapps/evoadmin-web/tasks/user.yml +++ b/webapps/evoadmin-web/tasks/user.yml @@ -24,6 +24,23 @@ name: www-evoadmin when: ansible_distribution_major_version | version_compare('9', '>=') +- name: Is /etc/aliases present? + stat: + path: /etc/aliases + register: etc_aliases + +- name: Set evoadmin aliases + lineinfile: + dest: /etc/aliases + line: "{{ item.line }}" + regexp: "{{ item.regexp }}" + state: present + with_items: + - { line: 'evoadmin: root', regexp: '^evoadmin:'} + - { line: 'www-evoadmin: root', regexp: '^www-evoadmin:'} + notify: "newaliases" + when: etc_aliases.stat.exists + - name: Git is needed to clone the evoadmin repository apt: name: git @@ -75,7 +92,7 @@ args: creates: "{{ evoadmin_scripts_dir }}/web-add.sh" -# we use a shell command to have a "changed" thet really reflects the result. +# we use a shell command to have a "changed" that really reflects the result. - name: Fix permissions command: "chmod -R --verbose u=rwX,g=rX,o= {{ evoadmin_document_root }}" register: command_result diff --git a/webapps/roundcube/defaults/main.yml b/webapps/roundcube/defaults/main.yml index 5e0c1a81..2102ea8a 100644 --- a/webapps/roundcube/defaults/main.yml +++ b/webapps/roundcube/defaults/main.yml @@ -1,4 +1,5 @@ --- roundcube_host: "roundcube.{{ ansible_fqdn }}" +roundcube_webserver: apache roundcube_imap_host: "localhost" roundcube_imap_port: 143 diff --git a/webapps/roundcube/handlers/main.yml b/webapps/roundcube/handlers/main.yml index bdba6e6b..98b530d9 100644 --- a/webapps/roundcube/handlers/main.yml +++ b/webapps/roundcube/handlers/main.yml @@ -3,3 +3,13 @@ systemd: name: imapproxy state: restarted + +- name: reload apache2 + service: + name: apache2 + state: reloaded + +- name: reload nginx + service: + name: nginx + state: reloaded diff --git a/webapps/roundcube/tasks/main.yml b/webapps/roundcube/tasks/main.yml index 9eac3dd9..9efd6b6a 100644 --- a/webapps/roundcube/tasks/main.yml +++ b/webapps/roundcube/tasks/main.yml @@ -85,24 +85,41 @@ tags: - roundcube -- name: deploy roundcube vhost +- name: deploy apache roundcube vhost template: src: apache2.conf.j2 dest: /etc/apache2/sites-available/rouncube.conf mode: "0640" notify: reload apache2 + when: roundcube_webserver == "apache" tags: - roundcube -- name: enable roundcube vhost +- name: enable apache roundcube vhost file: src: /etc/apache2/sites-available/rouncube.conf dest: /etc/apache2/sites-enabled/rouncube.conf state: link notify: reload apache2 + when: roundcube_webserver == "apache" tags: - roundcube +- name: deploy Nginx roundcube vhost + template: + src: nginx.conf.j2 + dest: /etc/nginx/sites-available/rouncube.conf + when: roundcube_webserver == "nginx" + notify: reload nginx + +- name: enable Nginx roundcube vhost + file: + src: "/etc/nginx/sites-available/rouncube.conf" + dest: "/etc/nginx/sites-enabled/rouncube.conf" + state: link + when: roundcube_webserver == "nginx" + notify: reload nginx + - name: enable roundcube link in default site index lineinfile: dest: /var/www/index.html diff --git a/webapps/roundcube/templates/nginx.conf.j2 b/webapps/roundcube/templates/nginx.conf.j2 new file mode 100644 index 00000000..1719c407 --- /dev/null +++ b/webapps/roundcube/templates/nginx.conf.j2 @@ -0,0 +1,49 @@ +server { + listen 80; + server_name {{ roundcube_host }}; + return 301 https://{{ roundcube_host }}$request_uri; +} + +server { + listen 443 ssl; + server_name {{ roundcube_host }}; + access_log /var/log/nginx/.{{ roundcube_host }}.access.log; + error_log /var/log/nginx/.{{ roundcube_host }}.error.log; + + root /var/lib/roundcube/; + index index.php; + + location / { + try_files $uri $uri/ /index.php?q=$uri&$args; + } + + location ~ ^/(README.md|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ { + deny all; + } + + location ~ ^/(config|temp|logs)/ { + deny all; + } + + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + location ~ \.php$ { + try_files $uri =404; + fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; + ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; + ssl_prefer_server_ciphers On; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; + ssl_session_cache shared:SSL:20m; + ssl_session_timeout 10m; + add_header Strict-Transport-Security "max-age=31536000"; +}