From 97f6a2b73dbefe9c039f13557e25e5d288d4e490 Mon Sep 17 00:00:00 2001 From: Ken Fong Date: Wed, 16 Jan 2019 00:00:44 +0800 Subject: [PATCH] first commit --- .gitignore | 4 + LICENSE | 201 ++++++++++++++++++++ README.md | 38 ++++ base-packages/tasks/main.yml | 32 ++++ pfa-dovecot/tasks/main.yml | 354 +++++++++++++++++++++++++++++++++++ 5 files changed, 629 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 base-packages/tasks/main.yml create mode 100644 pfa-dovecot/tasks/main.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a33b422 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.retry +*.log +.git +hosts diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7a77fe1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Ken Fong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..105eee5 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Ansible role: install postfixadmin, dovecot, and rainloop webmail +## URL: https://xpk.headdesk.me/git/xpk/postfixadmin + +## Prerequisites: +- This playbook was build on CentOS 7 +- EPEL and IUS repo are used in this playbook. + +## Usage +Clone this repo into the roles directory. Then for example create the following playbook in the ansible base directory. + +''' +--- +- hosts: all + become: yes + roles: + - base-packages + - pfa-dovecot +''' + +## Roles +- base-packages: installs apache, php, mysql. If you already have these, skip this role +- pfa-dovecot: installs pfa, dovecot, and rainloop webmail + +After playbook is ran, continue with pfa setup at http://your-server/postfixadmin/setup.php +Setup password is pfa-setup-2018, which is in $CONF['setup_password'] of config.local.php + +Setup rainloop webmail by going to http://your-server/webmail/?admin. Default setup password is admin/12345 +Delete all pre-configured domains and add yours. In the connection settings, enter 127.0.0.1 for incoming and outgoing. Change the setup password. + +## TODO +After this playbook is ran, the following should be performed before the mail server is open for service +* Setup https on pfa and rainloop +* Setup ssl on dovecot +* Implement relay control with SPF / RBL / postscreen / etc + +# References +* http://postfixadmin.sourceforge.net/ +* https://wiki2.dovecot.org/Variables diff --git a/base-packages/tasks/main.yml b/base-packages/tasks/main.yml new file mode 100644 index 0000000..0d8c836 --- /dev/null +++ b/base-packages/tasks/main.yml @@ -0,0 +1,32 @@ +- name: Install EPEL repo + yum: + name: epel-release + state: present + +- name: Install IUS repo + yum: + name: https://centos7.iuscommunity.org/ius-release.rpm + state: present + +- name: Install packages + yum: + name: "{{item}}" + state: present + with_items: + - httpd24u + - mariadb-server + - mariadb-devel + - php72u-mysqlnd + - php72u-xml + - php72u-json + - php72u-imap + - mod_php72u + +- name: Enable services + service: + name: "{{item}}" + state: started + enabled: yes + with_items: + - httpd + - mariadb diff --git a/pfa-dovecot/tasks/main.yml b/pfa-dovecot/tasks/main.yml new file mode 100644 index 0000000..532c173 --- /dev/null +++ b/pfa-dovecot/tasks/main.yml @@ -0,0 +1,354 @@ +- name: Install dovecot and postfix + # for EL6 w/o IUS: ['dovecot-mysql', 'dovecot', 'postfix', 'python-pip', 'gcc', 'python-devel', 'unzip'] + yum: + name: ['dovecot22u-mysql', 'dovecot22u', 'postfix', 'python2-pip', 'gcc', 'python-devel', 'unzip'] + state: present + +- name: Disable firewalls + service: + name: "{{item}}" + state: stopped + enabled: no + with_items: + - iptables + - firewalld + +- name: Download pfa + get_url: + url: https://netix.dl.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.2/postfixadmin-3.2-fedora.noarch.rpm + dest: /tmp/postfixadmin-3.2-fedora.noarch.rpm + force: no + +- name: Download rainloop webmail + get_url: + url: https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip + dest: /tmp/rainloop-community-latest.zip + force: no + +- name: Install pfa rpm + yum: + name: /tmp/postfixadmin-3.2-fedora.noarch.rpm + validate_certs: no + state: installed + +- name: Install MySQL-python + pip: + name: MySQL-python + state: present + +- name: Create postfix database + mysql_db: + name: postfix + encoding: utf8 + state: present + +- name: Create postfix database user + mysql_user: + name: pfa + password: pfa-rocks-2018 + priv: 'postfix.*:ALL' + state: present + +- name: Wipe pfa database config + copy: + content: "" + dest: /etc/postfixadmin/config.local.php + +- name: Create pfa database config + blockinfile: + create: yes + path: /etc/postfixadmin/config.local.php + marker: "" + block: | + + +- name: Create postfixadmin apache config + blockinfile: + path: /etc/httpd/conf.d/pfa.conf + create: yes + block: | + Alias /postfixadmin /usr/share/postfixadmin/public + + Require all granted + Options FollowSymLinks + php_admin_flag allow_url_include off + php_admin_flag allow_url_fopen off + php_admin_value open_basedir "/usr/share/postfixadmin:/etc/postfixadmin:/var/cache/postfixadmin:/usr/bin/doveadm" + php_admin_value session.save_path /var/cache/postfixadmin/sessions + + + require all granted + + +- name: Give apache read access to pfa config + file: + path: "{{item}}" + mode: 0644 + with_items: + - /etc/postfixadmin/config.inc.php + - /etc/postfixadmin/config.local.php + + +- name: Config postfix to listen to all + replace: + dest: /etc/postfix/main.cf + regexp: '^inet_interfaces.*' + replace: 'inet_interfaces = all' + +- name: Update postfix main.cf + blockinfile: + path: /etc/postfix/main.cf + block: | + virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf + virtual_alias_maps = + proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, + proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, + proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf + virtual_mailbox_maps = + proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, + proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf + virtual_mailbox_base = /var/vmail + virtual_uid_maps = static:1001 + virtual_gid_maps = static:12 + # smtpd tls + smtpd_use_tls = yes + smtpd_tls_security_level = may + smtpd_tls_key_file = /etc/postfix/server.key + smtpd_tls_cert_file = /etc/postfix/server.crt + smtpd_tls_loglevel = 1 + smtpd_tls_received_header = yes + smtpd_tls_session_cache_timeout = 3600s + tls_random_source = dev:/dev/urandom + smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 + # smtp auth + smtpd_sasl_type = dovecot + smtpd_sasl_path = private/auth + smtpd_sasl_auth_enable = yes + smtpd_sasl_security_options = noanonymous + smtpd_sasl_local_domain = $myhostname + broken_sasl_auth_clients = yes + # relay restrictions, bare minimal + smtpd_relay_restrictions = + permit_mynetworks, + permit_sasl_authenticated, + reject_unauth_destination + +- name: Setup submission port on postfix + blockinfile: + path: /etc/postfix/master.cf + block: + submission inet n - n - - smtpd + -o syslog_name=postfix/submission + -o smtpd_tls_security_level=encrypt + -o smtpd_sasl_type=dovecot + -o smtpd_sasl_path=private/auth + -o broken_sasl_auth_clients=yes + -o smtpd_sasl_local_domain=$myhostname + -o smtpd_tls_auth_only=yes + -o smtpd_sasl_auth_enable=yes + -o smtpd_reject_unlisted_recipient=no + -o smtpd_relay_restrictions=permit_sasl_authenticated,reject + +- name: Generate self-signed cert for postfix + shell: openssl req -new -x509 -newkey rsa:2048 -keyout /etc/postfix/server.key -nodes -out /etc/postfix/server.crt -days 3650 -set_serial 201811 -subj "/C=US/ST=NJ/L=SelfSigned City/O=SelfSigned Company/OU=Mail/CN=mail.domain.tld" + +- name: Create sql directory in postfix + file: + path: /etc/postfix/sql + state: directory + +- name: Create mysql_virtual_alias_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_alias_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT goto FROM alias WHERE address='%s' AND active = '1' + +- name: Create mysql_virtual_alias_domain_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1' + +- name: Create mysql_virtual_alias_domain_catchall_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1' + +- name: Create mysql_virtual_domains_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_domains_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT domain FROM domain WHERE domain='%s' AND active = '1' + +- name: Create mysql_virtual_mailbox_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_mailbox_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' + +- name: Create mysql_virtual_alias_domain_mailbox_maps.cf + blockinfile: + path: /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf + create: yes + block: | + user = pfa + password = pfa-rocks-2018 + hosts = localhost + dbname = postfix + query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1' + +- name: Create vmail directory + file: + path: /var/vmail + state: directory + owner: 1001 + group: mail + mode: 0755 + +- name: Wipe existing dovecot config + copy: + content: "" + dest: /etc/dovecot/dovecot.conf + +- name: Configure dovecot + blockinfile: + path: /etc/dovecot/dovecot.conf + create: yes + block: | + mail_location = maildir:/var/vmail/%d/%n/ + namespace inbox { + inbox = yes + location = + mailbox Drafts { + special_use = \Drafts + auto = subscribe + } + mailbox Junk { + special_use = \Junk + auto = subscribe + } + mailbox Sent { + special_use = \Sent + auto = subscribe + } + mailbox "Sent Messages" { + special_use = \Sent + auto = subscribe + } + mailbox Trash { + special_use = \Trash + auto = subscribe + } + prefix = + } + protocols = "imap pop3" + ssl = no + # login is for outlook express smtpd auth + auth_mechanisms = plain login + userdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf + } + passdb { + driver = sql + args = /etc/dovecot/dovecot-sql.conf + } + first_valid_uid = 1000 + disable_plaintext_auth = no + log_path = /var/log/dovecot.log + auth_verbose = yes + auth_debug = yes + mail_debug = yes + # postfix smtp auth + service auth { + unix_listener /var/spool/postfix/private/auth { + mode = 0666 + } + } + # enable ssl + ssl = yes + ssl_cert = + Require all granted + + + Require all denied + + +- name: Set rainloop data directory perm + file: + path: /var/www/rainloop/data + owner: apache + +- name: Restart apache, postfix, and dovecot + service: + name: "{{item}}" + state: restarted + enabled: yes + with_items: + - httpd + - postfix + - dovecot