From 7fe517c328906d0f962c3dc33d7bc773f2348bb4 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 15 Dec 2013 23:46:29 +0100 Subject: Configure the webmail. --- all.yml | 1 + group_vars/all.yml | 1 + roles/IMAP/files/etc/dovecot/conf.d/10-master.conf | 1 + roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf | 8 ++ .../files/etc/fail2ban/filter.d/roundcube.conf | 16 +++ roles/common/files/etc/postfix/master.cf | 1 + roles/common/tasks/fail2ban.yml | 15 ++- roles/common/templates/etc/fail2ban/jail.local.j2 | 10 ++ roles/common/templates/etc/iptables/services.j2 | 3 + .../files/etc/nginx/sites-available/roundcube | 69 ++++++++++ .../skins/default/images/logo_webmail.png | Bin 0 -> 6567 bytes roles/webmail/handlers/main.yml | 9 ++ roles/webmail/tasks/mail.yml | 20 +++ roles/webmail/tasks/main.yml | 2 + roles/webmail/tasks/roundcube.yml | 85 ++++++++++++ roles/webmail/templates/etc/postfix/main.cf.j2 | 99 ++++++++++++++ .../additional_message_headers/config.inc.php.j2 | 14 ++ .../roundcube/plugins/password/config.inc.php.j2 | 149 +++++++++++++++++++++ webmail.yml | 5 + 19 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 roles/common/files/etc/fail2ban/filter.d/roundcube.conf create mode 100644 roles/webmail/files/etc/nginx/sites-available/roundcube create mode 100644 roles/webmail/files/var/lib/roundcube/skins/default/images/logo_webmail.png create mode 100644 roles/webmail/handlers/main.yml create mode 100644 roles/webmail/tasks/mail.yml create mode 100644 roles/webmail/tasks/main.yml create mode 100644 roles/webmail/tasks/roundcube.yml create mode 100644 roles/webmail/templates/etc/postfix/main.cf.j2 create mode 100644 roles/webmail/templates/usr/share/roundcube/plugins/additional_message_headers/config.inc.php.j2 create mode 100644 roles/webmail/templates/usr/share/roundcube/plugins/password/config.inc.php.j2 create mode 100644 webmail.yml diff --git a/all.yml b/all.yml index 132123a..b4ea79d 100644 --- a/all.yml +++ b/all.yml @@ -6,3 +6,4 @@ - include: IMAP.yml - include: MX.yml - include: MSA.yml +- include: webmail.yml diff --git a/group_vars/all.yml b/group_vars/all.yml index 26448c4..5755086 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -7,6 +7,7 @@ postfix_instance: MX: { name: mx, group: mta } MTA-out: { name: mta-out,group: mta } MSA: { name: msa } + webmail: { name: webmail } MTA_out: { IPv4: outgoing.fripost.org, port: 2525 } LDA: { IPv4: lda.fripost.org, port: 2526 } diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf index 51ed7c6..d477d01 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/10-master.conf @@ -18,6 +18,7 @@ service imap-login { inet_listener imap { address = 172.16.0.1 port = 143 + ssl = no } inet_listener imaps { port = 993 diff --git a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf index a733e94..4eabe53 100644 --- a/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf +++ b/roles/IMAP/files/etc/dovecot/conf.d/10-ssl.conf @@ -5,6 +5,14 @@ # SSL/TLS support: yes, no, required. ssl = required +# No need for SSL if the packets are protected by IPSec. +local 172.16.0.1 { + protocol imap { + disable_plaintext_auth = no + ssl = no + } +} + # PEM encoded X.509 SSL/TLS certificate and private key. They're opened before # dropping root privileges, so keep the key file unreadable by anyone but # root. Included doc/mkcert.sh can be used to easily generate self-signed diff --git a/roles/common/files/etc/fail2ban/filter.d/roundcube.conf b/roles/common/files/etc/fail2ban/filter.d/roundcube.conf new file mode 100644 index 0000000..c8cb5d3 --- /dev/null +++ b/roles/common/files/etc/fail2ban/filter.d/roundcube.conf @@ -0,0 +1,16 @@ +[Definition] + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# +failregex = IMAP Error: Login failed for \S+ from \. AUTHENTICATE \S+: Authentication failed\. + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = diff --git a/roles/common/files/etc/postfix/master.cf b/roles/common/files/etc/postfix/master.cf index 3540e32..38b2ecb 100644 --- a/roles/common/files/etc/postfix/master.cf +++ b/roles/common/files/etc/postfix/master.cf @@ -11,6 +11,7 @@ smtp inet n - - - - smtpd 16132 inet n - - - - smtpd 2526 inet n - - - - smtpd +2580 inet n - - - - smtpd submission inet n - - - - smtpd pickup fifo n - - 60 1 pickup cleanup unix n - - - 0 cleanup diff --git a/roles/common/tasks/fail2ban.yml b/roles/common/tasks/fail2ban.yml index d5007b9..be26c79 100644 --- a/roles/common/tasks/fail2ban.yml +++ b/roles/common/tasks/fail2ban.yml @@ -1,17 +1,28 @@ - name: Install fail2ban apt: pkg=fail2ban +- name: Add addititional filters + copy: src=etc/fail2ban/filter.d/{{ item }} + dest=/etc/fail2ban/filter.d/{{ item }} + owner=root group=root + mode=0644 + register: r1 + with_items: + - roundcube.conf + notify: + - Restart fail2ban + - name: Configure fail2ban template: src=etc/fail2ban/jail.local.j2 dest=/etc/fail2ban/jail.local owner=root group=root mode=0644 - register: r + register: r2 notify: - Restart fail2ban - name: Start fail2ban service: name=fail2ban state=started - when: not r.changed + when: not (r1.changed or r2.changed) - meta: flush_handlers diff --git a/roles/common/templates/etc/fail2ban/jail.local.j2 b/roles/common/templates/etc/fail2ban/jail.local.j2 index 661c862..7c5bc0e 100644 --- a/roles/common/templates/etc/fail2ban/jail.local.j2 +++ b/roles/common/templates/etc/fail2ban/jail.local.j2 @@ -81,3 +81,13 @@ port = submission filter = sasl logpath = /var/log/mail.warn {% endif %} + + +{% if 'webmail' in group_names %} +[roundcube] + +enabled = true +port = http,https +filter = roundcube +logpath = /var/log/roundcube/errors +{% endif %} diff --git a/roles/common/templates/etc/iptables/services.j2 b/roles/common/templates/etc/iptables/services.j2 index 2a36932..3ddb87e 100644 --- a/roles/common/templates/etc/iptables/services.j2 +++ b/roles/common/templates/etc/iptables/services.j2 @@ -25,3 +25,6 @@ in tcp 993 # IMAPS {% if 'MSA' in group_names %} in tcp 587 # SMTP-AUTH {% endif %} +{% if 'webmail' in group_names %} +in tcp 80,443 # HTTP/HTTPS +{% endif %} diff --git a/roles/webmail/files/etc/nginx/sites-available/roundcube b/roles/webmail/files/etc/nginx/sites-available/roundcube new file mode 100644 index 0000000..72f5a40 --- /dev/null +++ b/roles/webmail/files/etc/nginx/sites-available/roundcube @@ -0,0 +1,69 @@ +server { + + listen 80; + listen [::]:80 ipv6only=on; + + server_name mail.fripost.org; + + access_log /var/log/nginx/roundcube.access.log; + error_log /var/log/nginx/roundcube.error.log info; + + return 301 https://$http_host$request_uri; +} + + +server { + listen 443; + listen [::]:443 ipv6only=on; + + server_name mail.fripost.org; + root /var/lib/roundcube; + + include ssl/config; + ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; + ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; + + location = /favicon.ico { + root /usr/share/roundcube/skins/default/images; + log_not_found off; + access_log off; + expires max; + } + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # Deny all attempts to access hidden files, or files under hidden + # directories. + location ~ /\. { return 404; } + + access_log /var/log/nginx/roundcube.access.log; + error_log /var/log/nginx/roundcube.error.log info; + + index index.php; + location = /index.php { + include fastcgi/php; + include fastcgi/php-ssl; + + # From /var/lib/roundcube/.htaccess + fastcgi_param PHP_VALUE "upload_max_filesize=25M + post_max_size=30M + memory_limit=64M + session.gc_maxlifetime=21600 + session.gc_divisor=500 + session.gc_probability=1"; + fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/usr/share/roundcube:/etc/roundcube:/var/log/roundcube:/usr/share/php:/usr/share/misc/magic + upload_tmp_dir=$document_root/temp"; + } + + # Security rules + location ~ ^/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ { + return 404; + } + location ~ ^/(bin|SQL)/ { + return 404; + } +} diff --git a/roles/webmail/files/var/lib/roundcube/skins/default/images/logo_webmail.png b/roles/webmail/files/var/lib/roundcube/skins/default/images/logo_webmail.png new file mode 100644 index 0000000..7af586a Binary files /dev/null and b/roles/webmail/files/var/lib/roundcube/skins/default/images/logo_webmail.png differ diff --git a/roles/webmail/handlers/main.yml b/roles/webmail/handlers/main.yml new file mode 100644 index 0000000..308f708 --- /dev/null +++ b/roles/webmail/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: Restart Postfix + service: name=postfix state=restarted + +- name: Reload Postfix + service: name=postfix state=reloaded + +- name: Restart Nginx + service: name=nginx state=restarted diff --git a/roles/webmail/tasks/mail.yml b/roles/webmail/tasks/mail.yml new file mode 100644 index 0000000..d3fb64e --- /dev/null +++ b/roles/webmail/tasks/mail.yml @@ -0,0 +1,20 @@ +- name: Install Postfix + apt: pkg={{ item }} + with_items: + - postfix + - postfix-pcre + +- name: Configure Postfix + template: src=etc/postfix/main.cf.j2 + dest=/etc/postfix-{{ postfix_instance[inst].name }}/main.cf + owner=root group=root + mode=0644 + register: r + notify: + - Restart Postfix + +- name: Start Postfix + service: name=postfix state=started + when: not r.changed + +- meta: flush_handlers diff --git a/roles/webmail/tasks/main.yml b/roles/webmail/tasks/main.yml new file mode 100644 index 0000000..a6eeee2 --- /dev/null +++ b/roles/webmail/tasks/main.yml @@ -0,0 +1,2 @@ +- include: mail.yml tags=postfix,mail +- include: roundcube.yml tags=roundcube,webmail diff --git a/roles/webmail/tasks/roundcube.yml b/roles/webmail/tasks/roundcube.yml new file mode 100644 index 0000000..e76b896 --- /dev/null +++ b/roles/webmail/tasks/roundcube.yml @@ -0,0 +1,85 @@ +- name: Install Roundcube + apt: pkg={{ item }} + with_items: + - roundcube-core + - roundcube-mysql + - roundcube-plugins + - php5-fpm + - php5-ldap + +- name: Copy fripost's logo + copy: src=var/lib/roundcube/skins/default/images/logo_webmail.png + dest=/var/lib/roundcube/skins/default/images/logo_webmail.png + owner=root group=root + mode=0644 + +- name: Configure Roundcube + lineinfile: dest=/etc/roundcube/main.inc.php + "regexp=^\s*\$rcmail_config\['{{ item.var }}']\s*=" + "line=$rcmail_config['{{ item.var }}'] = {{ item.value }};" + owner=root group=www-data + mode=0640 + with_items: + # Logging/Debugging + - { var: smtp_log, value: "FALSE" } + # IMAP + - { var: default_host, value: "'ssl://imap.fripost.org'" } + - { var: imap_auth_type, value: "'plain'" } + - { var: imap_cache, value: "'db'" } + - { var: message_cache, value: "'db'" } + # SMTP + - { var: smtp_server, value: "localhost" } + - { var: smtp_port, value: "2580" } + # System + - { var: force_https, value: "TRUE" } + - { var: login_autocomplete, value: "2" } + - { var: skin_logo, value: "'skins/default/images/logo_webmail.png'" } + - { var: username_domain, value: "'fripost.org'" } + - { var: product_name, value: "'Fripost'" } + # Plugins + - { var: plugins, value: "array('password','additional_message_headers')" } + # User Interface + - { var: language, value: "'sv_SE'" } + - { var: create_default_folders, value: "TRUE" } + # User Preferences + - { var: htmleditor, value: "TRUE" } + - { var: skip_deleted, value: "TRUE" } + - { var: check_all_folders, value: "FALSE" } + +- name: Make the logo a hyperlink to the website + lineinfile: dest=/usr/share/roundcube/skins/default/templates/login.html + regexp='^(