From 3c0ab7279fe373c5901acf15c6c05f460a4f6716 Mon Sep 17 00:00:00 2001 From: Aaron Guise Date: Thu, 30 Nov 2023 15:19:54 +1300 Subject: [PATCH] Initial commit --- README.md | 38 +++ defaults/main.yml | 116 ++++++++ .../scripts/custom/user_create_post.sh | 31 ++ handlers/main.yml | 60 ++++ meta/main.yml | 21 ++ tasks/config.yml | 17 ++ tasks/config/directadmin.yml | 42 +++ tasks/config/mail.yml | 17 ++ tasks/config/mail/apache.yml | 47 +++ tasks/config/mail/dovecot.yml | 113 +++++++ tasks/config/mail/exim.yml | 21 ++ tasks/config/mail/nginx.yml | 276 ++++++++++++++++++ tasks/config/mail/spamassassin.yml | 16 + tasks/config/users.yml | 19 ++ tasks/letsencrypt.yml | 33 +++ tasks/main.yml | 109 +++++++ templates/cli/directadmin-setup.j2 | 7 + templates/custombuild/options.conf.j2 | 105 +++++++ templates/custombuild/php_extensions.conf.j2 | 20 ++ templates/da-ip.j2 | 9 + templates/exim/strings.conf.custom.j2 | 12 + tests/inventory | 2 + tests/test.yml | 5 + vars/Debian.yml | 28 ++ vars/RedHat.yml | 41 +++ 25 files changed, 1205 insertions(+) create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100755 files/directadmin/scripts/custom/user_create_post.sh create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/config.yml create mode 100644 tasks/config/directadmin.yml create mode 100644 tasks/config/mail.yml create mode 100644 tasks/config/mail/apache.yml create mode 100644 tasks/config/mail/dovecot.yml create mode 100644 tasks/config/mail/exim.yml create mode 100644 tasks/config/mail/nginx.yml create mode 100644 tasks/config/mail/spamassassin.yml create mode 100644 tasks/config/users.yml create mode 100644 tasks/letsencrypt.yml create mode 100644 tasks/main.yml create mode 100644 templates/cli/directadmin-setup.j2 create mode 100644 templates/custombuild/options.conf.j2 create mode 100644 templates/custombuild/php_extensions.conf.j2 create mode 100644 templates/da-ip.j2 create mode 100644 templates/exim/strings.conf.custom.j2 create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 vars/Debian.yml create mode 100644 vars/RedHat.yml diff --git a/README.md b/README.md new file mode 100644 index 0000000..225dd44 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well. + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..c5bdb88 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,116 @@ +--- +# defaults file for ansible-role-directadmin +--- +directadmin_license: ~ + +# Directadmin automated setup - http://help.directadmin.com/item.php?id=578 +directadmin_install: True +directadmin_setup_url: http://www.directadmin.com/setup.sh +directadmin_setup_path: /root +# directadmin_client_id: +# directadmin_license_id: +directadmin_hostname: "{{ ansible_fqdn }}" +# directadmin_ip_address: # Optional, will be obtained from server +directadmin_ethernet_device: eth0 +directadmin_custombuild_options_conf: # like http://yourdomain.com/options.conf +directadmin_custombuild_version: 2.0 +directadmin_custombuild_path: /usr/local/directadmin/custombuild +directadmin_config_path: /usr/local/directadmin/conf/directadmin.conf +directadmin_cache_timeout: 3600 +# Download channel: alpha, beta, current, stable ( For initial installtion only ) +directadmin_channel: current +# Email address for administrator account +directadmin_admin_email: admin@someplace.co.nz + +# Options Configuration + +# PHP Version Options +directadmin_php1_release: 8.1 +directadmin_php1_mode: php-fpm +directadmin_php2_release: 5.6 +directadmin_php2_mode: php-fpm +directadmin_php3_release: 7.3 +directadmin_php3_mode: php-fpm +directadmin_php4_release: 7.4 +directadmin_php4_mode: php-fpm +# Additional Optional settings +# directadmin_secure_php: 'no' +# directadmin_php_ini: 'no' +# directadmin_php_timezone: Pacific/Auckland +# directadmin_php_ini_type: production +# directadmin_x_mail_header: 'yes' + +# PHP Extension Options +# These are all default options +#directadmin_php_module_bz2: 'no' +#directadmin_php_module_gmp: 'no' +#directadmin_php_module_htscanner: 'no' +#directadmin_php_module_igbinary: 'no' +#directadmin_php_module_imagick: 'no' +#directadmin_php_module_imap: 'no' +#directadmin_php_module_ioncube: 'yes' +#directadmin_php_module_ldap: 'no' +#directadmin_php_module_opcache: 'no' +#directadmin_php_module_phalcon: 'no' +#directadmin_php_module_readline: 'no' +#directadmin_php_module_redis: 'no' +#directadmin_php_module_snuffleupagus: 'no' +#directadmin_php_module_suhosin: 'no' +#directadmin_php_module_xmlrpc: 'no' +#directadmin_php_module_zend: 'no' + +# MySQL Options +directadmin_mysql_version: "8.0" +directadmin_mariadb_version: "10.6" +# Shall we install MySQL/MariaDB? Options: (mysql,mariadb,no) +directadmin_mysql_install: mariadb + +# WEB Server Options +# Install Unit? +# directadmin_unit: 'no' +# What webserver do we need? Options: (apache,nginx_apache,nginx) +# directadmin_webserver: apache +# HTTP methods allowed: Default "ALL" +# directadmin_http_methods: 'ALL' +# directadmin_litespeed_serialno: trial +# directadmin_modsecurity: 'no' +# Ruleset to apply +# directadmin_modsecurity_ruleset: 'no' +# directadmin_apache_mpm: 'auto' +# directadmin_mod_ruid2: 'no' +# directadmin_userdir_access: 'no' +# directadmin_harden_symlinks_patch: 'yes' +# directadmin_use_hostname_for_alias: 'no' +# directadmin_redirect_host_https: 'yes' + +# Mail Settings +directadmin_exim: 'yes' +directadmin_eximconf: 'no' +directadmin_blockcracking: 'yes' +directadmin_easy_spam_fighter: 'yes' +directadmin_spamd: spamassassin +directadmin_sa_update: daily +directadmin_dovecot: 'yes' +directadmin_dovecot_conf: 'yes' +directadmin_mail_compress: 'yes' +directadmin_pigeonhole: 'yes' +directadmin_exim_rbl_list: + - bl.spamcop.net + - bl.mxrbl.com + - zen.spamhaus.org + - psbl.surriel.com + - xbl.spamhaus.org + - cbl.abuseat.org + - bl.score.senderscore.com +directadmin_exim_ignore_smtp_line_length: true + + +# Directadmin Generics +directadmin_email: admin@somehost.co.nz +directadmin_ns1: ns1.somehost.com +directadmin_ns2: ns2.somehost.com + +directadmin_custom_conf: + - name: Don't allow "+" in email account + option: allow_email_plus + value: 0 \ No newline at end of file diff --git a/files/directadmin/scripts/custom/user_create_post.sh b/files/directadmin/scripts/custom/user_create_post.sh new file mode 100755 index 0000000..e4f0faa --- /dev/null +++ b/files/directadmin/scripts/custom/user_create_post.sh @@ -0,0 +1,31 @@ +#!/bin/sh +if [ "$spam" = "ON" ]; then + DIR=/home/$username/.spamassassin + mkdir -p $DIR + UP=$DIR/user_prefs + if [ ! -s ${UP} ]; then + echo 'required_score 5.0' > ${UP} + echo 'report_safe 1' >> ${UP} + chown $username:$username ${UP} + chmod 644 ${UP} + fi + chown ${username}:mail $DIR + chmod 771 $DIR + + if grep -m1 -q "^spamd=rspamd$" /usr/local/directadmin/custombuild/options.conf; then + echo "action=rewrite&value=rspamd&user=${username}" >> /usr/local/directadmin/data/task.queue + fi + + if [ "${domain}" != "" ]; then + FCONF=/etc/virtual/${domain}/filter.conf + if [ ! -s ${FCONF} ]; then + echo 'high_score=15' > ${FCONF} + echo 'high_score_block=no' >> ${FCONF} + echo 'where=inbox' >> ${FCONF} + chown mail:mail ${FCONF} + + echo "action=rewrite&value=filter&user=$username" >> /usr/local/directadmin/data/task.queue + fi + fi +fi +exit 0; diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..a1adedf --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,60 @@ +--- +- name: Restart DirectAdmin + service: + name: directadmin + state: restarted + +- name: Restart Dovecot + service: + name: dovecot + state: restarted + +- name: Restart Exim + service: + name: exim + state: restarted + +- name: Build phpMyAdmin + command: > + /usr/bin/da build phpmyadmin + +- name: Build Roundcube + command: > + /usr/bin/da build roundcube + +- name: Rewrite confs + command: > + /usr/bin/da build rewrite_confs + +- name: Ensure Dovecot custom for custombuild is present + file: + path: /usr/local/directadmin/custombuild/custom/dovecot/conf + state: directory + +- name: Persist mail plugins + copy: + dest: /usr/local/directadmin/custombuild/custom/dovecot/conf/imap_mail_plugins.conf + src: /etc/dovecot/conf/imap_mail_plugins.conf + remote_src: true + +- name: Reload Systemd + shell: systemctl daemon-reload + +- name: Restart Spamassassin + service: + name: spamassassin + state: restarted + +- name: Compile and fix permissions report-spam script + shell: | + sievec report-spam.sieve + chown mail. report-spam.sieve + args: + chdir: /usr/local/bin/dovecot-sieve + +- name: Compile and fix permissions report-ham script + shell: | + sievec report-ham.sieve + chown mail. report-ham.sieve + args: + chdir: /usr/local/bin/dovecot-sieve \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..99af1c2 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,21 @@ +galaxy_info: + author: Aaron Guise + description: DirectAdmin via Ansible - Install,Configure and Manage + company: CyberCinch + + issue_tracker_url: http://example.com/issue/tracker + + license: CC-BY-4.0 + + min_ansible_version: "2.1" + + platforms: + - name: EL + versions: + - all + + galaxy_tags: + - system + - hosting + +dependencies: [] \ No newline at end of file diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..3b5b681 --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,17 @@ +--- +- name: Ensure custom scripts directory exists + file: + path: /usr/local/directadmin/scripts/custom + state: directory + +- name: Include user configuration + include_tasks: config/users.yml + +- name: Include mail configuration + include_tasks: config/mail.yml + +- name: Include DirectAdmin configuration + include_tasks: config/directadmin.yml + +- name: Flush handlers + meta: flush_handlers \ No newline at end of file diff --git a/tasks/config/directadmin.yml b/tasks/config/directadmin.yml new file mode 100644 index 0000000..30585cf --- /dev/null +++ b/tasks/config/directadmin.yml @@ -0,0 +1,42 @@ +--- +- name: Setup One-Click logon + ini_file: + path: /usr/local/directadmin/conf/directadmin.conf + section: null + option: "{{ item.option }}" + value: "{{ item.value }}" + backup: false + state: present + no_extra_spaces: true + create: true + loop: + - name: Allow one-click logon Roundcube + option: one_click_webmail_login + value: 1 + - name: Allow on-click logon phpMyAdmin + option: one_click_pma_login + value: 1 + loop_control: + label: "{{ item.name }}" + notify: + - "directadmin : Restart DirectAdmin" + - "directadmin : Build phpMyAdmin" + - "directadmin : Build Roundcube" + - "directadmin : Rewrite confs" + +- name: Ensure custom configs are present + ini_file: + path: /usr/local/directadmin/conf/directadmin.conf + section: null + option: "{{ item.option }}" + value: "{{ item.value }}" + backup: false + state: present + no_extra_spaces: true + create: true + loop: "{{ directadmin_custom_conf }}" + loop_control: + label: "{{ item.name }}" + notify: + - "directadmin : Restart DirectAdmin" + - "directadmin : Rewrite confs" \ No newline at end of file diff --git a/tasks/config/mail.yml b/tasks/config/mail.yml new file mode 100644 index 0000000..a8c0d91 --- /dev/null +++ b/tasks/config/mail.yml @@ -0,0 +1,17 @@ +--- +- name: Include Spamassasin configuration + import_tasks: mail/spamassassin.yml + +- name: Import Dovecot configuration + import_tasks: mail/dovecot.yml + +- name: Import Exim configuration + import_tasks: mail/exim.yml + +- name: Ensure DirectAdmin Custom Templates exists + file: + path: /usr/local/directadmin/data/templates/custom + state: directory + +- name: Import Apache configuration + import_tasks: mail/apache.yml \ No newline at end of file diff --git a/tasks/config/mail/apache.yml b/tasks/config/mail/apache.yml new file mode 100644 index 0000000..37fa88b --- /dev/null +++ b/tasks/config/mail/apache.yml @@ -0,0 +1,47 @@ + +- name: Create Webmail V-Host + copy: + dest: /usr/local/directadmin/data/templates/custom/virtual_host2.conf.CUSTOM.4.post + content: | + + + ServerName webmail.|DOMAIN| + ServerAdmin |ADMIN| + DocumentRoot /var/www/html/roundcube/ + CustomLog /var/log/httpd/domains/|DOMAIN|.bytes bytes + CustomLog /var/log/httpd/domains/|DOMAIN|.log combined + ErrorLog /var/log/httpd/domains/|DOMAIN|.error.log + + SuexecUserGroup webapps webapps + + notify: + - "directadmin : Rewrite confs" + +- name: Create Webmail V-Host (Secure) + copy: + dest: /usr/local/directadmin/data/templates/custom/virtual_host2_secure.conf.CUSTOM.4.post + content: | + + + ServerName webmail.|DOMAIN| + ServerAdmin |ADMIN| + DocumentRoot /var/www/html/roundcube/ + + SSLEngine on + SSLCertificateFile |CERT| + SSLCertificateKeyFile |KEY| + |CAROOT| + + CustomLog /var/log/httpd/domains/|DOMAIN|.bytes bytes + CustomLog /var/log/httpd/domains/|DOMAIN|.log combined + ErrorLog /var/log/httpd/domains/|DOMAIN|.error.log + + SuexecUserGroup webapps webapps + + notify: + - "directadmin : Rewrite confs" + +- name: Include NGINX if running as proxy + include_tasks: nginx.yml + + \ No newline at end of file diff --git a/tasks/config/mail/dovecot.yml b/tasks/config/mail/dovecot.yml new file mode 100644 index 0000000..6632c80 --- /dev/null +++ b/tasks/config/mail/dovecot.yml @@ -0,0 +1,113 @@ +--- +- name: Add imap_sieve to mail_plugins for dovecot + lineinfile: + path: /etc/dovecot/conf/imap_mail_plugins.conf + regex: "^mail_plugins = (?!.*imap_sieve)(.*)$" + line: "mail_plugins = \\1 imap_sieve" + backrefs: true + notify: + - "directadmin : Ensure Dovecot custom for custombuild is present" + - "directadmin : Persist mail plugins" + - "directadmin : Restart Dovecot" + +- name: Configure plusaddressing for Dovecot + copy: + dest: /etc/dovecot/conf.d/subaddressing.conf + content: | + recipient_delimiter = + + lmtp_save_to_detail_mailbox = no + lda_mailbox_autocreate = yes + lda_mailbox_autosubscribe = yes + notify: + - "directadmin : Restart Dovecot" + +- name: Configure imap_sieve for Dovecot + copy: + dest: /etc/dovecot/conf.d/99-imap-sieve.conf + content: | + plugin { + sieve_plugins = sieve_imapsieve sieve_extprograms + + # From elsewhere to Spam folder + imapsieve_mailbox1_name = Spam + imapsieve_mailbox1_causes = COPY + imapsieve_mailbox1_before = file:/usr/local/bin/dovecot-sieve/report-spam.sieve + + # From Spam folder to elsewhere + imapsieve_mailbox2_name = * + imapsieve_mailbox2_from = Spam + imapsieve_mailbox2_causes = COPY + imapsieve_mailbox2_before = file:/usr/local/bin/dovecot-sieve/report-ham.sieve + + sieve_pipe_bin_dir = /usr/local/bin/dovecot-sieve + + sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment + } + notify: + - "directadmin : Restart Dovecot" + +- name: Ensure dovecot-sieve script directory is present + file: + path: /usr/local/bin/dovecot-sieve + state: directory + owner: mail + +- name: Create report-spam script + copy: + dest: /usr/local/bin/dovecot-sieve/report-spam.sieve + content: | + require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; + + if environment :matches "imap.user" "*" { + set "username" "${1}"; + } + + pipe :copy "sa-learn-spam.sh" [ "${username}" ]; + notify: + - "directadmin : Compile and fix permissions report-spam script" + +- name: Create report-ham script + copy: + dest: /usr/local/bin/dovecot-sieve/report-ham.sieve + content: | + require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; + + if environment :matches "imap.mailbox" "*" { + set "mailbox" "${1}"; + } + + if string "${mailbox}" "Trash" { + stop; + } + + if environment :matches "imap.user" "*" { + set "username" "${1}"; + } + + pipe :copy "sa-learn-ham.sh" [ "${username}" ]; + notify: + - "directadmin : Compile and fix permissions report-ham script" + +- name: Create spam learning script + copy: + dest: /usr/local/bin/dovecot-sieve/sa-learn-spam.sh + content: | + #!/bin/bash + # you can also use tcp/ip here, consult spamc(1) + inputmail=`/usr/bin/cat` + ddomain=`/usr/bin/echo "${1}"| /usr/bin/cut -d'@' -f2` + dusername=`/usr/bin/egrep "^${ddomain}:" /etc/virtual/domainowners| /usr/bin/cut -d' ' -f2` + exec /usr/bin/spamc -u ${dusername} -L spam <<< "${inputmail}" + mode: "0755" + +- name: Create ham learning script + copy: + dest: /usr/local/bin/dovecot-sieve/sa-learn-ham.sh + content: | + #!/bin/bash + # you can also use tcp/ip here, consult spamc(1) + inputmail=`/usr/bin/cat` + ddomain=`/usr/bin/echo "${1}"| /usr/bin/cut -d'@' -f2` + dusername=`/usr/bin/egrep "^${ddomain}:" /etc/virtual/domainowners| /usr/bin/cut -d' ' -f2` + exec /usr/bin/spamc -u ${dusername} -L ham <<< "${inputmail}" + mode: "0755" diff --git a/tasks/config/mail/exim.yml b/tasks/config/mail/exim.yml new file mode 100644 index 0000000..32700aa --- /dev/null +++ b/tasks/config/mail/exim.yml @@ -0,0 +1,21 @@ +--- +- name: Ensure /etc/exim is present + file: + path: /etc/exim + state: directory + +- name: Add plusaddressing to Exim + copy: + dest: /etc/exim/local_part_suffix.conf + content: | + local_part_suffix = +* + local_part_suffix_optional + notify: + - "directadmin : Restart Exim" + +- name: Ensure Exim custom strings configured + template: + src: templates/exim/strings.conf.custom.j2 + dest: /etc/exim.strings.conf.custom + notify: + - "directadmin : Restart Exim" \ No newline at end of file diff --git a/tasks/config/mail/nginx.yml b/tasks/config/mail/nginx.yml new file mode 100644 index 0000000..b001572 --- /dev/null +++ b/tasks/config/mail/nginx.yml @@ -0,0 +1,276 @@ +- name: Ensure Custom SSL config for NGINX is created + copy: + dest: /etc/nginx/webapps.ssl.conf.custom + content: | + location ~ /(\.htaccess|\.htpasswd|\.user\.ini|\.env|\.git) { + deny all; + } + location ^~ /.well-known/acme-challenge { + root /var/www/html/; + index index.php index.html index.htm; + location ~ ^/.well-known/acme-challenge/ { + access_log off; + set $my_server_addr $server_addr; + if ($server_addr ~ ^[0-9a-fA-F:]+$) { set $my_server_addr [$server_addr]; } + proxy_pass https://$my_server_addr:8081; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /.well-known/acme-challenge/nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_hide_header Upgrade; + } + location ~ ^/.well-known/acme-challenge/nginx_static_files/ { + access_log /var/log/nginx/access_log_proxy; + alias /var/www/html/; + internal; + } + } + location ^~ /roundcube { + root /var/www/html/; + index index.php index.html index.htm; + location ~ ^/roundcube/ { + access_log off; + set $my_server_addr $server_addr; + if ($server_addr ~ ^[0-9a-fA-F:]+$) { set $my_server_addr [$server_addr]; } + proxy_pass https://$my_server_addr:8081; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /roundcube/nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_hide_header Upgrade; + } + location ~ ^/roundcube/nginx_static_files/ { + access_log /var/log/nginx/access_log_proxy; + alias /var/www/html/; + internal; + } + } + location ^~ /phpMyAdmin { + root /var/www/html/; + index index.php index.html index.htm; + location ~ ^/phpMyAdmin/ { + access_log off; + set $my_server_addr $server_addr; + if ($server_addr ~ ^[0-9a-fA-F:]+$) { set $my_server_addr [$server_addr]; } + proxy_pass https://$my_server_addr:8081; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /phpMyAdmin/nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_hide_header Upgrade; + } + location ~ ^/phpMyAdmin/nginx_static_files/ { + access_log /var/log/nginx/access_log_proxy; + alias /var/www/html/; + internal; + } + } + location ~ ^/phpmyadmin { + rewrite ^/* /phpMyAdmin last; + } + location ~ ^/pma { + rewrite ^/* /phpMyAdmin last; + } + location ~ ^/webmail { + rewrite ^/* /roundcube last; + } + +- name: Create Webmail V-Host (Nginx) + copy: + dest: /usr/local/directadmin/data/templates/custom/nginx_server.conf + content: | + server + { + listen |IP|:|PORT_80|; + |MULTI_IP| + + server_name webmail.|DOMAIN|; + + root /var/www/html/roundcube; + index index.php index.html index.htm; + access_log /var/log/nginx/domains/|DOMAIN|.log; + access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes; + error_log /var/log/nginx/domains/|DOMAIN|.error.log; + + |*if HAVE_PHP1_FPM="1"| + # use fastcgi for all php files + location ~ \.php$ + { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + include /etc/nginx/fastcgi_params; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include /etc/nginx/nginx_limits.conf; + + if (-f $request_filename) + { + fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock; + } + } + |*endif| + + |*if HAVE_NGINX_PROXY="1"| + location / + { + # access_log off; + proxy_pass http://127.0.0.1:|PORT_8080|; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location /nginx_static_files/ + { + # access_log /var/log/nginx/access_log_proxy; + alias /var/www/html/roundcube/; + internal; + } + |*endif| + + # deny access to apache .htaccess files + location ~ /\.ht + { + deny all; + } + } + notify: + - "directadmin : Rewrite confs" + when: > + directadmin_webserver == 'nginx' or + directadmin_webserver == 'nginx_apache' + +- name: Create Webmail V-Host (Secure - Nginx) + copy: + dest: /usr/local/directadmin/data/templates/custom/nginx_server_secure.conf + content: | + |CUSTOM1| + |?DOCROOT=`HOME`/domains/`DOMAIN`/private_html| + |?REALDOCROOT=`HOME`/domains/`DOMAIN`/private_html| + |?OPEN_BASEDIR_PATH=`HOME`/:/tmp:/opt/alt/php`PHP1_RELEASE`/usr/share/pear/:/dev/urandom:/var/tmp:/usr/local/lib/php/| + |?HOST_DOMAIN=`DOMAIN`| + |*if HOST_POINTER| + |?HOST_DOMAIN=`HOST_POINTER`| + |*endif| + server + { + |CUSTOM| + + listen |IP|:|PORT_443| ssl|SPACE_HTTP2|; + |MULTI_IP| + + server_name |HOST_DOMAIN| www.|HOST_DOMAIN| |SERVER_ALIASES|; + + access_log /var/log/nginx/domains/|DOMAIN|.log; + access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes; + error_log /var/log/nginx/domains/|DOMAIN|.error.log; + + root |DOCROOT|; + + index index.php index.html index.htm; + + ssl_certificate |CERT|; + ssl_certificate_key |KEY|; + + |FORCE_SSL_REDIRECT| + + |NGINX_PHP_CONF| + + |*if HAVE_NGINX_PROXY="1"| + location / + { + |CUSTOM2| + |LOCATION_INSERT| + # access_log off; + proxy_buffering |PROXY_BUFFERING|; + proxy_pass https://|PROXY_IP|:|PORT_8081|; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_hide_header Upgrade; + } + location /nginx_static_files/ + { + # access_log /var/log/nginx/access_log_proxy; + alias |DOCROOT|/; + internal; + } + |*else| + |NGINX_REDIRECTS| + |PROTECTED_DIRECTORIES| + |HOTLINK_PROTECTION| + |EXTRA_LOCATIONS| + |*endif| + + |CUSTOM3| + + include /etc/nginx/webapps.ssl.conf.custom; + + |CUSTOM4| + } + server + { + listen |IP|:|PORT_443| ssl|SPACE_HTTP2|; + |MULTI_IP| + + server_name webmail.|DOMAIN|; + + root /var/www/html/roundcube; + index index.php index.html index.htm; + access_log /var/log/nginx/domains/|DOMAIN|.log; + access_log /var/log/nginx/domains/|DOMAIN|.bytes bytes; + error_log /var/log/nginx/domains/|DOMAIN|.error.log; + + ssl_certificate |CERT|; + ssl_certificate_key |KEY|; + + + |*if HAVE_PHP1_FPM="1"| + # use fastcgi for all php files + location ~ \.php$ + { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + include /etc/nginx/fastcgi_params; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include /etc/nginx/nginx_limits.conf; + + if (-f $request_filename) + { + fastcgi_pass unix:/usr/local/php|PHP1_RELEASE|/sockets/webapps.sock; + } + } + |*endif| + + |*if HAVE_NGINX_PROXY="1"| + location / + { + # access_log off; + proxy_pass http://127.0.0.1:|PORT_8080|; + proxy_set_header X-Client-IP $remote_addr; + proxy_set_header X-Accel-Internal /nginx_static_files; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location /nginx_static_files/ + { + # access_log /var/log/nginx/access_log_proxy; + alias /var/www/html/roundcube/; + internal; + } + |*endif| + + # deny access to apache .htaccess files + location ~ /\.ht + { + deny all; + } + } + + notify: + - "directadmin : Rewrite confs" + when: > + directadmin_webserver == 'nginx' or + directadmin_webserver == 'nginx_apache' \ No newline at end of file diff --git a/tasks/config/mail/spamassassin.yml b/tasks/config/mail/spamassassin.yml new file mode 100644 index 0000000..a73c6b0 --- /dev/null +++ b/tasks/config/mail/spamassassin.yml @@ -0,0 +1,16 @@ +--- +- name: Enable Spamassassin learning + blockinfile: + path: /etc/systemd/system/spamassassin.service.d/override.conf + state: present + marker: "# {mark} ANSIBLE MANAGED BLOCK" + block: | + [Service] + ExecStart= + # Add "-l" flag to spamd + ExecStart=/usr/bin/spamd --pidfile /var/run/spamd.pid -d -c -m 15 --ipv4 -l + create: true + backup: false + notify: + - "directadmin : Reload Systemd" + - "directadmin : Restart Spamassassin" \ No newline at end of file diff --git a/tasks/config/users.yml b/tasks/config/users.yml new file mode 100644 index 0000000..5f0fc54 --- /dev/null +++ b/tasks/config/users.yml @@ -0,0 +1,19 @@ +--- +# This file contains configuration actions related to Users +- name: Enable spamassassin on user create + copy: + src: directadmin/scripts/custom/user_create_post.sh + dest: /usr/local/directadmin/scripts/custom/user_create_post.sh + mode: "0755" + +- name: Set Spam defaults on domain create + copy: + dest: /usr/local/directadmin/scripts/custom/domain_create_post.sh + content: | + #!/bin/sh + F=/etc/virtual/$domain/filter.conf + if [ -e $F ]; then + echo "where=userspamfolder" >> $F + echo "action=rewrite&value=filter&user=$username" >> /usr/local/directadmin/data/task.queue + fi + mode: "0755" \ No newline at end of file diff --git a/tasks/letsencrypt.yml b/tasks/letsencrypt.yml new file mode 100644 index 0000000..cf94249 --- /dev/null +++ b/tasks/letsencrypt.yml @@ -0,0 +1,33 @@ +--- +- name: execute LetsEncrypt setup script + command: /usr/local/directadmin/scripts/letsencrypt.sh request_single {{ directadmin_hostname }} 4096 + register: directadmin_letsencrypt_output + +- debug: + var: directadmin_letsencrypt_output.stdout_lines + +- name: enable SSL with LetsEncrypt for DirectAdmin + lineinfile: + path: "{{ directadmin_config_path }}" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + loop: + - name: Turn SSL on + regexp: '^SSL\=0' + line: 'SSL=1' + - name: Configure CA Root Cert + regexp: '^carootcert=' + line: 'carootcert=/usr/local/directadmin/conf/carootcert.pem' + - name: Force hostname + regexp: '^force_hostname=' + line: "force_hostname={{ directadmin_hostname }}" + - name: SSL Redirect Setup + regexp: '^ssl_redirect_host=' + line: "ssl_redirect_host={{ directadmin_hostname }}" + - name: Enable LetsEncrypt + regexp: '^letsencrypt=' + line: "letsencrypt=1" + loop_control: + label: "{{ item.name }}" + notify: + - Restart DirectAdmin \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..a9f316c --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,109 @@ +--- + +- name: Check if DirectAdmin exists + stat: + path: /usr/local/directadmin/directadmin + register: da + +- name: Configure pre-install options + when: not da.stat.exists + block: + - name: Ensure custombuild directory exists + file: + path: "{{ directadmin_custombuild_path }}" + state: directory + + - name: Setup options for base install + template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + loop: + - name: options.conf + src: custombuild/options.conf.j2 + dest: "{{ directadmin_custombuild_path }}/options.conf" + - name: php_extensions.conf + src: custombuild/php_extensions.conf.j2 + dest: "{{ directadmin_custombuild_path }}/php_extensions.conf" + loop_control: + label: "{{ item.name }}" + # vars: + # directadmin_webserver: apache # Ensure is apache install for server name SSL + + - name: Download DirectAdmin installer + get_url: + url: https://download.directadmin.com/setup.sh + dest: /tmp/directadmin-setup.sh + mode: "0700" + + - name: 'Coffee Time!' + debug: + msg: "Have a nice break, I'll be busy a while..." + + - name: Send ntfy ping + uri: + url: https://ntfy.cybercinch.nz/ + method: POST + body_format: json + body: + topic: ansiballz + title: DirectAdmin provisioning + tags: + - robot + - warning + - cd + message: DirectAdmin install is beginning on {{ inventory_hostname }} + + - name: Run installer + shell: "{{ lookup('ansible.builtin.template', 'templates/cli/directadmin-setup.j2') }}" + + - name: Send ntfy ping + uri: + url: https://ntfy.cybercinch.nz/ + method: POST + body_format: json + body: + topic: ansiballz + title: DirectAdmin provisioning + tags: + - robot + - heavy_check_mark + message: DirectAdmin install is completed on {{ inventory_hostname }} + + - name: Add new IPv6 to DA + template: + src: da-ip.j2 + dest: /usr/local/directadmin/data/admin/ips/{{ hostvars[inventory_hostname]['ansible_default_ipv6']['address'] }} + owner: diradmin + group: diradmin + mode: "0600" + notify: + - Restart DirectAdmin + - Rewrite confs + + - name: Reciprocal Link from Main IPv4 + lineinfile: + path: /usr/local/directadmin/data/admin/ips/{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address']}} + line: "linked_ips={{ hostvars[inventory_hostname]['ansible_default_ipv6']['address'] | encode_ip }}=apache%3Dyes%26dns%3Dyes" + create: true + notify: + - Restart DirectAdmin + - Rewrite confs + + - name: Add IP to admin ip.list + ansible.builtin.lineinfile: + path: /usr/local/directadmin/data/admin/ip.list + line: "{{ hostvars[inventory_hostname]['ansible_default_ipv6']['address'] }}" + create: true + notify: + - Restart DirectAdmin + - Rewrite confs + + - name: Flushing handlers + meta: flush_handlers + + - name: Get Server Hostname SSL Certificate + import_tasks: letsencrypt.yml + +# Tasks which can run whether new install or just config +- name: Include configuration tasks + include_tasks: config.yml diff --git a/templates/cli/directadmin-setup.j2 b/templates/cli/directadmin-setup.j2 new file mode 100644 index 0000000..f2e5d46 --- /dev/null +++ b/templates/cli/directadmin-setup.j2 @@ -0,0 +1,7 @@ +DA_HOSTNAME={{ ansible_nodename }} \ +DA_CHANNEL={{ directadmin_channel }} \ +DA_EMAIL={{ directadmin_admin_email }} \ +DA_NS1={{ directadmin_ns1 }} \ +DA_NS2={{ directadmin_ns2 }} \ +DA_FOREGROUND_CUSTOMBUILD=true \ +/tmp/directadmin-setup.sh {{ directadmin_license }} \ No newline at end of file diff --git a/templates/custombuild/options.conf.j2 b/templates/custombuild/options.conf.j2 new file mode 100644 index 0000000..b37ef58 --- /dev/null +++ b/templates/custombuild/options.conf.j2 @@ -0,0 +1,105 @@ +# PHP Settings +php1_release={{ directadmin_php1_release }} +php1_mode={{ directadmin_php1_mode }} +php2_release={{ directadmin_php2_release }} +php2_mode={{ directadmin_php2_mode }} +php3_release={{ directadmin_php3_release }} +php3_mode={{ directadmin_php3_mode }} +php4_release={{ directadmin_php4_release }} +php4_mode={{ directadmin_php4_mode }} +secure_php={{ directadmin_secure_php | default ('no') }} +php_ini={{ directadmin_php_ini | default ('no') }} +php_timezone={{ directadmin_php_timezone | default ('Pacific/Auckland') }} +php_ini_type={{ directadmin_php_ini_type | default ('production') }} +x_mail_header={{ directadmin_x_mail_header | default ('yes') }} + +# MySQL Settings +mysql={{ directadmin_mysql_version }} +mariadb={{ directadmin_mariadb_version }} +mysql_inst={{ directadmin_mysql_install }} +mysql_backup=yes +mysql_backup_gzip=yes +mysql_backup_dir=/usr/local/directadmin/custombuild/mysql_backups +mysql_force_compile=no + +# WEB Server Settings +unit={{ directadmin_unit | default('no') }} +webserver={{ directadmin_webserver | default('apache') }} +http_methods={{ directadmin_http_methods | default('ALL') }} +litespeed_serialno={{ directadmin_litespeed_serialno | default('trial') }} +modsecurity={{ directadmin_modsecurity | default('no') }} +modsecurity_ruleset={{ directadmin_modsecurity_ruleset | default('no') }} +apache_mpm={{ directadmin_apache_mpm | default('auto') }} +mod_ruid2={{ directadmin_mod_ruid2 | default('no') }} +userdir_access={{ directadmin_userdir_access | default('no') }} +harden_symlinks_patch={{ directadmin_harden_symlinks_patch | default('yes') }} +use_hostname_for_alias={{ directadmin_use_hostname_for_alias | default('no') }} +redirect_host={{ directadmin_hostname }} +redirect_host_https={{ directadmin_redirect_host_https | default('yes') }} + +# WEB Applications Settings +phpmyadmin=yes +phpmyadmin_public=yes +squirrelmail=no +roundcube=yes +webapps_inbox_prefix=no + +# ClamAV-related Settings +clamav=yes +clamav_exim=no +modsecurity_uploadscan=yes +proftpd_uploadscan=no +pureftpd_uploadscan=yes +suhosin_php_uploadscan=yes + +directadmin_exim: 'yes' +directadmin_eximconf: 'yes' +directadmin_blockcracking: 'yes' +directadmin_easy_spam_fighter: 'yes' +directadmin_spamd: spamassassin +directadmin_sa_update: daily +directadmin_dovecot: 'yes' +directadmin_dovecot_conf: 'yes' +directadmin_mail_compress: 'yes' +directadmin_pigeonhole: 'yes' +# Mail Settings +exim={{ directadmin_exim | default('yes') }} +eximconf={{ directadmin_eximconf | default('yes') }} +blockcracking={{ directadmin_blockcracking | default('yes') }} +easy_spam_fighter={{ directadmin_easy_spam_fighter | default('yes') }} +spamd={{ directadmin_spamd | default('spamassassin') }} +sa_update={{ directadmin_sa_update | default('daily') }} +dovecot={{ directadmin_dovecot | default('yes') }} +dovecot_conf={{ directadmin_dovecot_conf | default('yes') }} +mail_compress={{ directadmin_mail_compress | default('no') }} +pigeonhole={{ directadmin_mail_compress | default('yes') }} + +# FTP Settings +ftpd=pureftpd + +# Statistics Settings +awstats=yes +webalizer=yes + +# CustomBuild Settings +bold=yes +clean=yes +clean_old_tarballs=yes +clean_old_webapps=yes + +# Cronjob Settings +cron=yes +cron_frequency=weekly +email=root@{{ directadmin_hostname }} +notifications=yes +updates=no +webapps_updates=yes + +# CloudLinux Settings +cloudlinux={{ directadmin_cloudlinux | default('no')}} +cagefs={{ directadmin_cagefs | default('no')}} + +# Advanced Settings +csf={{ directadmin_csf | default('yes') }} +ssl_configuration={{ directadmin_ssl_configuration | default('intermediate')}} +redis={{ directadmin_redis | default('no') }} diff --git a/templates/custombuild/php_extensions.conf.j2 b/templates/custombuild/php_extensions.conf.j2 new file mode 100644 index 0000000..bcbba12 --- /dev/null +++ b/templates/custombuild/php_extensions.conf.j2 @@ -0,0 +1,20 @@ +####### Managed by Ansible ###### +# +# +# PHP Extension Settings +bz2={{ directadmin_php_module_bz2 | default('no') }} +gmp={{ directadmin_php_module_gmp | default('no') }} +htscanner={{ directadmin_php_module_htscanner | default('no') }} +igbinary={{ directadmin_php_module_igbinary | default('no') }} +imagick={{ directadmin_php_module_imagick | default('no') }} +imap={{ directadmin_php_module_imap | default('no') }} +ioncube={{ directadmin_php_module_ioncube | default('yes') }} +ldap={{ directadmin_php_module_ldap | default('no') }} +opcache={{ directadmin_php_module_opcache | default('no') }} +phalcon={{ directadmin_php_module_phalcon | default('no') }} +readline={{ directadmin_php_module_readline | default('no') }} +redis={{ directadmin_php_module_redis | default('no') }} +snuffleupagus={{ directadmin_php_module_snuffleupagus | default('no') }} +suhosin={{ directadmin_php_module_suhosin | default('no') }} +xmlrpc={{ directadmin_php_module_xmlrpc | default('no') }} +zend={{ directadmin_php_module_zend | default('no') }} diff --git a/templates/da-ip.j2 b/templates/da-ip.j2 new file mode 100644 index 0000000..6fa78fd --- /dev/null +++ b/templates/da-ip.j2 @@ -0,0 +1,9 @@ +add_to_device=no +gateway= +global=no +linked_ips={{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] | encode_ip }}=apache%3Dyes%26dns%3Dyes +netmask=/64 +ns= +reseller= +status=free +value= \ No newline at end of file diff --git a/templates/exim/strings.conf.custom.j2 b/templates/exim/strings.conf.custom.j2 new file mode 100644 index 0000000..905ed42 --- /dev/null +++ b/templates/exim/strings.conf.custom.j2 @@ -0,0 +1,12 @@ +RBL_DNS_LIST==\ + {% for rbl in directadmin_exim_rbl_list %} + {%- if not loop.last %} + {{ rbl }} : \ + {% else %} + {{ rbl }} + {% endif %} + {% endfor %} + +{% if directadmin_exim_ignore_smtp_line_length %} +IGNORE_SMTP_LINE_LENGTH_LIMIT=1 +{% endif %} diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..22383fc --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - ansible-role-directadmin diff --git a/vars/Debian.yml b/vars/Debian.yml new file mode 100644 index 0000000..6fc9da6 --- /dev/null +++ b/vars/Debian.yml @@ -0,0 +1,28 @@ +directadmin_prereq_packages: + - gcc + - g++ + - make + - flex + - bison + - openssl + - libssl-dev + - perl + - perl-base + - perl-modules + - libperl-dev + - libaio1 + - libaio-dev + - zlib1g + - zlib1g-dev + - libcap-dev + - bzip2 + - automake + - autoconf + - libtool + - cmake + - pkg-config + - python + - libreadline-dev + - libdb4.8-dev + - libsasl2-dev + - patch diff --git a/vars/RedHat.yml b/vars/RedHat.yml new file mode 100644 index 0000000..7ce57ec --- /dev/null +++ b/vars/RedHat.yml @@ -0,0 +1,41 @@ +--- +directadmin_prereq_packages: + - gcc + - gcc-c++ + - flex + - bison + - make + - bind + - bind-libs + - bind-utils + - openssl + - openssl-devel + - perl + - quota + - libaio + - libcom_err-devel + - libcurl-devel + - gd + - zlib-devel + - zip + - unzip + - libcap-devel + - cronie + - bzip2 + - cyrus-sasl-devel + - perl-ExtUtils-Embed + - autoconf + - automake + - libtool + - which + - patch + - mailx + - bzip2-devel + - lsof + - db4-devel + - psmisc + - net-tools + - systemd-devel + - libdb-devel + - perl-DBI + - xfsprogs \ No newline at end of file