From 9280faab4f7eb75bf0dddb66b2c0a906b93b65f3 Mon Sep 17 00:00:00 2001 From: hbaxter Date: Mon, 7 Jul 2025 12:10:00 +0100 Subject: [PATCH] Role: httpd templating updates --- ANSIBLE/group_vars/dev_roundcube/main.yml | 67 +++++++++++++++++++ ANSIBLE/roles/httpd/defaults/main.yml | 22 +++++- .../roles/httpd/tasks/httpd_certbot_tls.yml | 20 ++++++ .../httpd/tasks/httpd_default_config.yml | 15 ++++- ANSIBLE/roles/httpd/tasks/httpd_install.yml | 17 +++-- ANSIBLE/roles/httpd/tasks/httpd_vhost_tls.yml | 19 ++++++ ANSIBLE/roles/httpd/tasks/main.yml | 20 ++---- ANSIBLE/roles/httpd/tasks/php.yml | 9 ++- .../httpd/templates/httpd/tls_vhost.conf.j2 | 33 +++++++++ ANSIBLE/roles/httpd/templates/php/www.conf.j2 | 2 +- 10 files changed, 190 insertions(+), 34 deletions(-) create mode 100644 ANSIBLE/roles/httpd/tasks/httpd_certbot_tls.yml create mode 100644 ANSIBLE/roles/httpd/tasks/httpd_vhost_tls.yml create mode 100644 ANSIBLE/roles/httpd/templates/httpd/tls_vhost.conf.j2 diff --git a/ANSIBLE/group_vars/dev_roundcube/main.yml b/ANSIBLE/group_vars/dev_roundcube/main.yml index ad005a9..6e90482 100644 --- a/ANSIBLE/group_vars/dev_roundcube/main.yml +++ b/ANSIBLE/group_vars/dev_roundcube/main.yml @@ -1,2 +1,69 @@ --- httpd_php: true +httpd_tls_site_root: /srv/roundcube/roundcubemail-{{ roundcube_version }}/public_html +httpd_optional_enabled_modules: + - deflate + - expires + - headers +httpd_tls_vhost_raw: | + + Options +SymLinksIfOwnerMatch + RewriteEngine On + RewriteRule ^favicon\.ico$ skins/elastic/images/favicon.ico + + # security rules: + # - deny access to files not containing a dot or starting with a dot + # in all locations except installer directory + RewriteRule ^(?!installer|\.well-known\/|[a-zA-Z0-9]{16})(\.?[^\.]+)$ - [F] + # - deny access to some locations + RewriteRule ^/?(\.git|\.tx|SQL|bin|config|logs|temp|tests|vendor|program\/(include|lib|localization|steps)) - [F] + # - deny access to some documentation files + RewriteRule /?(README.*|CHANGELOG.*|SECURITY.*|meta\.json|composer\..*|jsdeps.json)$ - [F] + + + + SetOutputFilter DEFLATE + + + # prefer to brotli over gzip if brotli is available + + SetOutputFilter BROTLI_COMPRESS + # some assets have been compressed, so no need to do it again + SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|web[pm]|woff2?)$ no-brotli + + + + ExpiresActive On + ExpiresDefault "access plus 1 month" + + + FileETag MTime Size + + + Options -Indexes + + + + # Disable page indexing + Header set X-Robots-Tag "noindex, nofollow" + # replace 'merge' with 'append' for Apache < 2.2.9 + #Header merge Cache-Control public env=!NO_CACHE + # Optional security headers + # Only provides increased security if the browser supports those features + # Be careful! Testing is required! They should be adjusted to your installation / user environment + # HSTS - HTTP Strict Transport Security + #Header always set Strict-Transport-Security "max-age=31536000; preload" env=HTTPS + # HPKP - HTTP Public Key Pinning + # Only template - fill with your values + #Header always set Public-Key-Pins "max-age=3600; report-uri=\"\"; pin-sha256=\"\"; pin-sha256=\"\"" env=HTTPS + # X-Xss-Protection + # This header is used to configure the built in reflective XSS protection found in Internet Explorer, Chrome and Safari (Webkit). + #Header set X-XSS-Protection "1; mode=block" + # X-Frame-Options + # The X-Frame-Options header (RFC), or XFO header, protects your visitors against clickjacking attacks + # Already set by php code! Do not activate both options + #Header set X-Frame-Options SAMEORIGIN + # X-Content-Type-Options + # It prevents Google Chrome and Internet Explorer from trying to mime-sniff the content-type of a response away from the one being declared by the server. + #Header set X-Content-Type-Options "nosniff" + \ No newline at end of file diff --git a/ANSIBLE/roles/httpd/defaults/main.yml b/ANSIBLE/roles/httpd/defaults/main.yml index 5bedd1e..575905a 100644 --- a/ANSIBLE/roles/httpd/defaults/main.yml +++ b/ANSIBLE/roles/httpd/defaults/main.yml @@ -1,8 +1,25 @@ +httpd_pkgs: + - apache2 +httpd_pkgs_plugins: [] + httpd_site_name: 'default' httpd_site_root: '/var/www/html' +httpd_default_enabled_modules: + - ssl +httpd_optional_enabled_modules: [] + +httpd_tls_certbot: true +httpd_tls_auto_redirect: true +httpd_tls_certbot_additonal_args: '' +httpd_tls_site_root: + +httpd_tls_vhost_default: true + +httpd_tls_vhost_raw: '' httpd_php: false httpd_php_version: 8.3 +httpd_php_socket: '/run/php/php{{ httpd_php_version }}-fpm.sock' httpd_php_pkgs: - php - php-fpm @@ -13,4 +30,7 @@ httpd_php_pkgs: - php-mbstring - php-xml - php-zip - \ No newline at end of file +httpd_php_enabled_modules: + - proxy_fcgi + - setenvif + - php{{ httpd_php_version }} diff --git a/ANSIBLE/roles/httpd/tasks/httpd_certbot_tls.yml b/ANSIBLE/roles/httpd/tasks/httpd_certbot_tls.yml new file mode 100644 index 0000000..dc31599 --- /dev/null +++ b/ANSIBLE/roles/httpd/tasks/httpd_certbot_tls.yml @@ -0,0 +1,20 @@ +--- +- name: Install Certbot and Apache plugin + ansible.builtin.apt: + name: + - certbot + - python3-certbot-apache + state: present +- name: Ensure Apache is running and enabled + ansible.builtin.service: + name: apache2 + state: started + enabled: true +- name: Obtain Let's Encrypt certificate using certbot + ansible.builtin.command: > + certbot --apache -n --agree-tos --redirect + -d {{ httpd_site_name }} + --email {{ admin_email }} {{ httpd_tls_certbot_additonal_args }} + args: + creates: "/etc/letsencrypt/live/{{ httpd_site_name }}/fullchain.pem" + diff --git a/ANSIBLE/roles/httpd/tasks/httpd_default_config.yml b/ANSIBLE/roles/httpd/tasks/httpd_default_config.yml index 55a6b65..548d087 100644 --- a/ANSIBLE/roles/httpd/tasks/httpd_default_config.yml +++ b/ANSIBLE/roles/httpd/tasks/httpd_default_config.yml @@ -11,12 +11,21 @@ ansible.builtin.template: src: httpd/vhost.conf.j2 dest: "/etc/apache2/sites-available/{{ httpd_site_name }}.conf" + owner: www-data + group: www-data + mode: '0644' notify: Reload Apache -- name: Enable site +- name: "Enable http site {{ httpd_site_name }}" ansible.builtin.command: "a2ensite {{ httpd_site_name }}" + args: + creates: "/etc/apache2/sites-enabled/{{ httpd_site_name }}.conf" notify: Reload Apache -- name: Enable SSL module - ansible.builtin.command: a2enmod ssl +- name: Enable modules + ansible.builtin.command: " a2enmod {{ item }}" + args: + creates: "/etc/apache2/mods-enabled/{{ item }}*" + loop: "{{ httpd_default_enabled_modules + httpd_optional_enabled_modules }}" notify: Reload Apache + diff --git a/ANSIBLE/roles/httpd/tasks/httpd_install.yml b/ANSIBLE/roles/httpd/tasks/httpd_install.yml index 9c2cddb..057f776 100644 --- a/ANSIBLE/roles/httpd/tasks/httpd_install.yml +++ b/ANSIBLE/roles/httpd/tasks/httpd_install.yml @@ -1,17 +1,10 @@ --- -- name: Install Apache2 +- name: Install Apache2 and plugins ansible.builtin.apt: - name: apache2 + name: "{{ httpd_pkgs + httpd_pkgs_plugins }}" state: present update_cache: true -- name: Install Certbot and Apache plugin - ansible.builtin.apt: - name: - - certbot - - python3-certbot-apache - state: present - - name: Ensure site root exists ansible.builtin.file: path: "{{ httpd_site_root }}" @@ -20,3 +13,9 @@ group: www-data mode: '0755' +- name: Ensure Apache is running and enabled + ansible.builtin.service: + name: apache2 + state: started + enabled: true + diff --git a/ANSIBLE/roles/httpd/tasks/httpd_vhost_tls.yml b/ANSIBLE/roles/httpd/tasks/httpd_vhost_tls.yml new file mode 100644 index 0000000..2bcba07 --- /dev/null +++ b/ANSIBLE/roles/httpd/tasks/httpd_vhost_tls.yml @@ -0,0 +1,19 @@ +--- +- name: "Disable Certbot autocreated {{ httpd_site_name }}-le-ssl" + ansible.builtin.command: "a2dissite {{ httpd_site_name }}-le-ssl" + args: + removes: "/etc/apache2/sites-enabled/{{ httpd_site_name }}-le-ssl.conf" + notify: Reload Apache +- name: Create Apache TLS virtual host config + ansible.builtin.template: + src: httpd/tls_vhost.conf.j2 + dest: "/etc/apache2/sites-available/{{ httpd_site_name }}_tls.conf" + owner: www-data + group: www-data + mode: '0644' + notify: Reload Apache +- name: "Enable http site {{ httpd_site_name }}_tls" + ansible.builtin.command: "a2ensite {{ httpd_site_name }}_tls" + args: + creates: "/etc/apache2/sites-enabled/{{ httpd_site_name }}_tls.conf" + notify: Reload Apache diff --git a/ANSIBLE/roles/httpd/tasks/main.yml b/ANSIBLE/roles/httpd/tasks/main.yml index ee21aa9..e1e84ab 100644 --- a/ANSIBLE/roles/httpd/tasks/main.yml +++ b/ANSIBLE/roles/httpd/tasks/main.yml @@ -4,21 +4,11 @@ ansible.builtin.include_tasks: httpd_install.yml - name: Apache2 Default Config ansible.builtin.include_tasks: httpd_default_config.yml - -- name: Ensure Apache is running and enabled - ansible.builtin.service: - name: apache2 - state: started - enabled: true - -- name: Obtain Let's Encrypt certificate using certbot - ansible.builtin.command: > - certbot --apache -n --agree-tos --redirect - -d {{ httpd_site_name }} - --email {{ admin_email }} - args: - creates: "/etc/letsencrypt/live/{{ httpd_site_name }}/fullchain.pem" - +- name: Certbot TLS + when: httpd_tls_certbot + ansible.builtin.include_tasks: httpd_certbot_tls.yml - name: PHP Application when: httpd_php ansible.builtin.include_tasks: php.yml +- name: TLS Enabled Site + ansible.builtin.include_tasks: httpd_vhost_tls.yml diff --git a/ANSIBLE/roles/httpd/tasks/php.yml b/ANSIBLE/roles/httpd/tasks/php.yml index a430cad..2673c23 100644 --- a/ANSIBLE/roles/httpd/tasks/php.yml +++ b/ANSIBLE/roles/httpd/tasks/php.yml @@ -6,12 +6,12 @@ update_cache: true - name: Enable Apache modules for PHP-FPM ansible.builtin.command: a2enmod {{ item }} - loop: - - proxy_fcgi - - setenvif - - php{{ httpd_php_version }} # or php8.1 depending on your distro + args: + creates: "/etc/apache2/mods-enabled/{{ item }}*" + loop: "{{ httpd_php_enabled_modules }}" notify: Reload Apache ignore_errors: true # in case some modules aren't available + register: httpd_php_modules_errors - name: Ensure PHP-FPM service is running ansible.builtin.service: @@ -29,4 +29,3 @@ mode: '0644' notify: Restart PHP-FPM - diff --git a/ANSIBLE/roles/httpd/templates/httpd/tls_vhost.conf.j2 b/ANSIBLE/roles/httpd/templates/httpd/tls_vhost.conf.j2 new file mode 100644 index 0000000..cd573fe --- /dev/null +++ b/ANSIBLE/roles/httpd/templates/httpd/tls_vhost.conf.j2 @@ -0,0 +1,33 @@ + + + # General vhost config + ServerName {{ httpd_site_name }} + DocumentRoot {{ httpd_tls_site_root }} + #TLS Config + SSLCertificateFile /etc/letsencrypt/live/{{ httpd_site_name }}/fullchain.pem + SSLCertificateKeyFile /etc/letsencrypt/live/{{ httpd_site_name }}/privkey.pem + Include /etc/letsencrypt/options-ssl-apache.conf + # Standardised Access & error Logging locations + ErrorLog ${APACHE_LOG_DIR}/{{ httpd_site_name }}_error.log + CustomLog ${APACHE_LOG_DIR}/{{ httpd_site_name }}_access.log combined +{% if httpd_tls_vhost_default %} + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + {% if httpd_php %} + + SetHandler "proxy:unix:{{ httpd_php_socket }}|fcgi://localhost/" + + {% endif %} + +{% endif %} + +{% if httpd_tls_vhost_raw != '' %} + + {{ httpd_tls_vhost_raw }} + +{% endif %} + + + diff --git a/ANSIBLE/roles/httpd/templates/php/www.conf.j2 b/ANSIBLE/roles/httpd/templates/php/www.conf.j2 index a338f10..b7b688f 100644 --- a/ANSIBLE/roles/httpd/templates/php/www.conf.j2 +++ b/ANSIBLE/roles/httpd/templates/php/www.conf.j2 @@ -3,7 +3,7 @@ user = www-data group = www-data -listen = /run/php/php{{ httpd_php_version }}-fpm.sock +listen = {{ httpd_php_socket }} listen.owner = www-data listen.group = www-data