From d33bbaef4163e061711d6e57f7025a536a8a1d7d Mon Sep 17 00:00:00 2001 From: strarsis Date: Mon, 29 Jul 2024 19:17:01 +0200 Subject: [PATCH 01/20] Add adjustments for HTTP3 support. --- roles/ferm/defaults/main.yml | 2 + roles/ferm/tasks/main.yml | 23 ++++++++++ .../templates/wordpress-site.conf.j2 | 42 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/roles/ferm/defaults/main.yml b/roles/ferm/defaults/main.yml index 17f623b5d0..fe3a3ac40f 100644 --- a/roles/ferm/defaults/main.yml +++ b/roles/ferm/defaults/main.yml @@ -11,3 +11,5 @@ ferm_default_policy_forward: DROP ferm_input_list: [] ferm_input_group_list: [] ferm_input_host_list: [] + +sites_using_ssl: "[{% for name, site in wordpress_sites.items() | list if site.ssl.enabled %}'{{ name }}',{% endfor %}]" diff --git a/roles/ferm/tasks/main.yml b/roles/ferm/tasks/main.yml index ce779972d1..a10301ba02 100644 --- a/roles/ferm/tasks/main.yml +++ b/roles/ferm/tasks/main.yml @@ -35,6 +35,29 @@ notify: - restart ferm + +- name: allow conditionally inbound HTTPS + set_fact: + ferm_input_list: "{{ ferm_input_list + [ ferm_dport_nginx_https] }}" + when: sites_using_ssl | count + vars: + ferm_dport_nginx_https: + type: dport_accept + dport: [https] + filename: nginx_accept_https + +- name: allow conditionally port UDP/443 for HTTP/3 (QUIC) support + set_fact: + ferm_input_list: "{{ ferm_input_list + [ ferm_dport_nginx_http3] }}" + when: nginx_http3_enabled and (sites_using_ssl | count) + vars: + ferm_dport_nginx_http3: + type: dport_accept + dport: ['443'] + protocol: udp + filename: nginx_accept_http3 + + - name: ensure iptables INPUT rules are removed file: path: "/etc/ferm/filter-input.d/{{ item.weight | default('50') }}_{{ (item.filename is defined and item.filename) | ternary(item.filename, item.type + '_' + item.dport[0]) }}.conf" diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 95b406439a..bdef8dad8a 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -6,6 +6,13 @@ server { {% block server_id -%} listen {{ ssl_enabled | ternary('[::]:443 ssl', '[::]:80') }}; listen {{ ssl_enabled | ternary('443 ssl', '80') }}; + + {% if ssl_enabled and nginx_http3_enabled -%} + # Listen on UDP for QUIC+HTTP/3 + listen [::]:443 quic; + listen 443 quic; + {% endif -%} + http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ site_hosts_canonical | union(multisite_subdomains_wildcards) | join(' ') }}; @@ -16,6 +23,17 @@ server { error_log {{ www_root }}/{{ item.key }}/logs/error.log; {% endblock %} + {% if ssl_enabled and nginx_http3_enabled -%} + quic_retry on; + # enable 0-RTT + ssl_early_data on; + proxy_set_header Early-Data $ssl_early_data; + quic_gso on; + + # Add Alt-Svc header to negotiate HTTP/3. + add_header alt-svc 'h3=":443"; ma=86400'; + {% endif -%} + {% block server_basic -%} root {{ www_root }}/{{ item.key }}/{{ item.value.current_path | default('current') }}/{{ item.value.public_path | default('web') }}; index index.php index.htm index.html; @@ -277,6 +295,11 @@ server { {{ self.includes_d() -}} + {% if ssl_enabled and nginx_http3_enabled -%} + # Add Alt-Svc header to negotiate HTTP/3 (when redirecting from HTTP). + add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400'; + {% endif -%} + location / { return 301 https://$host$request_uri; } @@ -295,12 +318,31 @@ server { listen [::]:443 ssl; listen 443 ssl; {% endif -%} + listen [::]:80; listen 80; + + {% if ssl_enabled and nginx_http3_enabled -%} + # Listen on UDP for QUIC+HTTP/3 + listen [::]:443 quic; + listen 443 quic; + {% endif -%} + http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ host.redirects | join(' ') }}; + {% if ssl_enabled and nginx_http3_enabled -%} + quic_retry on; + # enable 0-RTT + ssl_early_data on; + proxy_set_header Early-Data $ssl_early_data; + quic_gso on; + + # Add Alt-Svc header to negotiate HTTP/3 (when redirecting from HTTP). + add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400'; + {% endif -%} + {{ self.https() -}} {{ self.acme_challenge() -}} From ae4f6896ce36d4a683b9613d46ba64770f6199af Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 30 Jul 2024 00:59:32 +0200 Subject: [PATCH 02/20] Use ferm `delete` attribute for toggling HTTP3 firewall allow rule. --- group_vars/all/security.yml | 5 +++++ roles/ferm/tasks/main.yml | 23 ----------------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/group_vars/all/security.yml b/group_vars/all/security.yml index 57c2bcdd7d..e9d7809b49 100644 --- a/group_vars/all/security.yml +++ b/group_vars/all/security.yml @@ -8,6 +8,11 @@ ferm_input_list: dport: [https] filename: nginx_accept_https delete: "{{ not (sites_use_ssl | bool) }}" + - type: dport_accept + dport: ['443'] + protocol: udp + filename: nginx_accept_http3 + delete: "{{ not (nginx_http3_enabled and (sites_use_ssl | bool)) }}" - type: dport_accept dport: [ssh] saddr: "{{ ip_whitelist }}" diff --git a/roles/ferm/tasks/main.yml b/roles/ferm/tasks/main.yml index a10301ba02..ce779972d1 100644 --- a/roles/ferm/tasks/main.yml +++ b/roles/ferm/tasks/main.yml @@ -35,29 +35,6 @@ notify: - restart ferm - -- name: allow conditionally inbound HTTPS - set_fact: - ferm_input_list: "{{ ferm_input_list + [ ferm_dport_nginx_https] }}" - when: sites_using_ssl | count - vars: - ferm_dport_nginx_https: - type: dport_accept - dport: [https] - filename: nginx_accept_https - -- name: allow conditionally port UDP/443 for HTTP/3 (QUIC) support - set_fact: - ferm_input_list: "{{ ferm_input_list + [ ferm_dport_nginx_http3] }}" - when: nginx_http3_enabled and (sites_using_ssl | count) - vars: - ferm_dport_nginx_http3: - type: dport_accept - dport: ['443'] - protocol: udp - filename: nginx_accept_http3 - - - name: ensure iptables INPUT rules are removed file: path: "/etc/ferm/filter-input.d/{{ item.weight | default('50') }}_{{ (item.filename is defined and item.filename) | ternary(item.filename, item.type + '_' + item.dport[0]) }}.conf" From 17c2c464b60b7b45004f67b4b5832970114c0593 Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 30 Jul 2024 01:14:23 +0200 Subject: [PATCH 03/20] Remove old variable from previous PR/ferm toggling. --- roles/ferm/defaults/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/roles/ferm/defaults/main.yml b/roles/ferm/defaults/main.yml index fe3a3ac40f..17f623b5d0 100644 --- a/roles/ferm/defaults/main.yml +++ b/roles/ferm/defaults/main.yml @@ -11,5 +11,3 @@ ferm_default_policy_forward: DROP ferm_input_list: [] ferm_input_group_list: [] ferm_input_host_list: [] - -sites_using_ssl: "[{% for name, site in wordpress_sites.items() | list if site.ssl.enabled %}'{{ name }}',{% endfor %}]" From 78737bfe07fd133482327ee211c98791ee51fe11 Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 30 Jul 2024 15:26:16 +0200 Subject: [PATCH 04/20] Use include files for re-using HTTP/3 specific `nginx` directives. --- roles/wordpress-setup/tasks/nginx.yml | 7 ++++++ .../http3-negotiate-redirect.conf | 2 ++ .../directive-only/http3-negotiate.conf | 2 ++ .../includes/directive-only/http3-tune.conf | 7 ++++++ .../templates/wordpress-site.conf.j2 | 23 ++++--------------- 5 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 roles/wordpress-setup/templates/includes/directive-only/http3-negotiate-redirect.conf create mode 100644 roles/wordpress-setup/templates/includes/directive-only/http3-negotiate.conf create mode 100644 roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf diff --git a/roles/wordpress-setup/tasks/nginx.yml b/roles/wordpress-setup/tasks/nginx.yml index 9f81d32c23..030b93f89e 100644 --- a/roles/wordpress-setup/tasks/nginx.yml +++ b/roles/wordpress-setup/tasks/nginx.yml @@ -23,6 +23,13 @@ - import_tasks: "{{ playbook_dir }}/roles/common/tasks/disable_challenge_sites.yml" +- name: Copy Nginx wordpress site configs + copy: + src: templates/includes + dest: "{{ nginx_path }}" + mode: '0755' + notify: reload nginx + - name: Create Nginx available sites template: src: "{{ item.src }}" diff --git a/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate-redirect.conf b/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate-redirect.conf new file mode 100644 index 0000000000..7f06e32b83 --- /dev/null +++ b/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate-redirect.conf @@ -0,0 +1,2 @@ +# Add Alt-Svc header to negotiate HTTP/3 (when redirecting from HTTP). +add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400'; diff --git a/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate.conf b/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate.conf new file mode 100644 index 0000000000..4fb2ef3abb --- /dev/null +++ b/roles/wordpress-setup/templates/includes/directive-only/http3-negotiate.conf @@ -0,0 +1,2 @@ +# Add Alt-Svc header to negotiate HTTP/3. +add_header alt-svc 'h3=":443"; ma=86400'; diff --git a/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf new file mode 100644 index 0000000000..366e526063 --- /dev/null +++ b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf @@ -0,0 +1,7 @@ +quic_retry on; + +# enable 0-RTT +ssl_early_data on; +proxy_set_header Early-Data $ssl_early_data; + +quic_gso on; diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index bdef8dad8a..18952e87f6 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -24,14 +24,8 @@ server { {% endblock %} {% if ssl_enabled and nginx_http3_enabled -%} - quic_retry on; - # enable 0-RTT - ssl_early_data on; - proxy_set_header Early-Data $ssl_early_data; - quic_gso on; - - # Add Alt-Svc header to negotiate HTTP/3. - add_header alt-svc 'h3=":443"; ma=86400'; + include includes/directive-only/http3-tune.conf; + include includes/directive-only/http3-negotiate.conf; {% endif -%} {% block server_basic -%} @@ -296,8 +290,7 @@ server { {{ self.includes_d() -}} {% if ssl_enabled and nginx_http3_enabled -%} - # Add Alt-Svc header to negotiate HTTP/3 (when redirecting from HTTP). - add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400'; + include includes/directive-only/http3-negotiate-redirect.conf; {% endif -%} location / { @@ -333,14 +326,8 @@ server { server_name {{ host.redirects | join(' ') }}; {% if ssl_enabled and nginx_http3_enabled -%} - quic_retry on; - # enable 0-RTT - ssl_early_data on; - proxy_set_header Early-Data $ssl_early_data; - quic_gso on; - - # Add Alt-Svc header to negotiate HTTP/3 (when redirecting from HTTP). - add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400'; + include includes/directive-only/http3-tune.conf; + include includes/directive-only/http3-negotiate-redirect.conf; {% endif -%} {{ self.https() -}} From be5e46e1dceec926895acc627e9ede3376561b44 Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 30 Jul 2024 15:29:52 +0200 Subject: [PATCH 05/20] Make http3 jinja conditions more readable. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 18952e87f6..e37ed0c3f6 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -7,7 +7,7 @@ server { listen {{ ssl_enabled | ternary('[::]:443 ssl', '[::]:80') }}; listen {{ ssl_enabled | ternary('443 ssl', '80') }}; - {% if ssl_enabled and nginx_http3_enabled -%} + {% if nginx_http3_enabled and ssl_enabled -%} # Listen on UDP for QUIC+HTTP/3 listen [::]:443 quic; listen 443 quic; @@ -23,7 +23,7 @@ server { error_log {{ www_root }}/{{ item.key }}/logs/error.log; {% endblock %} - {% if ssl_enabled and nginx_http3_enabled -%} + {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-tune.conf; include includes/directive-only/http3-negotiate.conf; {% endif -%} @@ -289,7 +289,7 @@ server { {{ self.includes_d() -}} - {% if ssl_enabled and nginx_http3_enabled -%} + {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-negotiate-redirect.conf; {% endif -%} @@ -315,7 +315,7 @@ server { listen [::]:80; listen 80; - {% if ssl_enabled and nginx_http3_enabled -%} + {% if nginx_http3_enabled and ssl_enabled -%} # Listen on UDP for QUIC+HTTP/3 listen [::]:443 quic; listen 443 quic; @@ -325,7 +325,7 @@ server { http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ host.redirects | join(' ') }}; - {% if ssl_enabled and nginx_http3_enabled -%} + {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-tune.conf; include includes/directive-only/http3-negotiate-redirect.conf; {% endif -%} From 2e02929715b76e0aab26417dbb23eb38b55ddd7a Mon Sep 17 00:00:00 2001 From: strarsis Date: Sat, 3 Aug 2024 02:36:55 +0200 Subject: [PATCH 06/20] Remove conditional firewall inbound rule for `https` (in separate PR). --- group_vars/all/security.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/group_vars/all/security.yml b/group_vars/all/security.yml index e9d7809b49..6249c63d20 100644 --- a/group_vars/all/security.yml +++ b/group_vars/all/security.yml @@ -2,12 +2,8 @@ ferm_input_list: - type: dport_accept - dport: [http] + dport: [http, https] filename: nginx_accept - - type: dport_accept - dport: [https] - filename: nginx_accept_https - delete: "{{ not (sites_use_ssl | bool) }}" - type: dport_accept dport: ['443'] protocol: udp From 73e5516ecbfb72146d3192feb0d9101a7b31b7b0 Mon Sep 17 00:00:00 2001 From: strarsis Date: Sat, 3 Aug 2024 02:40:15 +0200 Subject: [PATCH 07/20] Improve task name. --- roles/wordpress-setup/tasks/nginx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/wordpress-setup/tasks/nginx.yml b/roles/wordpress-setup/tasks/nginx.yml index 030b93f89e..a0a0c0cc9e 100644 --- a/roles/wordpress-setup/tasks/nginx.yml +++ b/roles/wordpress-setup/tasks/nginx.yml @@ -23,7 +23,7 @@ - import_tasks: "{{ playbook_dir }}/roles/common/tasks/disable_challenge_sites.yml" -- name: Copy Nginx wordpress site configs +- name: Copy Nginx Wordpress site include folder copy: src: templates/includes dest: "{{ nginx_path }}" From e08cb574ceb1881dd945e58120e81daf24eaace6 Mon Sep 17 00:00:00 2001 From: strarsis Date: Sat, 3 Aug 2024 22:51:41 +0200 Subject: [PATCH 08/20] Disable SSL early data. --- .../templates/includes/directive-only/http3-tune.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf index 366e526063..99c3047635 100644 --- a/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf +++ b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf @@ -1,7 +1,7 @@ quic_retry on; # enable 0-RTT -ssl_early_data on; -proxy_set_header Early-Data $ssl_early_data; +#ssl_early_data on; +#proxy_set_header Early-Data $ssl_early_data; quic_gso on; From f24fbde86e75c39cf7c9d8e121b3ec92aba5315f Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 27 Aug 2024 17:34:49 +0200 Subject: [PATCH 09/20] Use now merged conditional https ferm rule. --- group_vars/all/security.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/group_vars/all/security.yml b/group_vars/all/security.yml index 6249c63d20..e9d7809b49 100644 --- a/group_vars/all/security.yml +++ b/group_vars/all/security.yml @@ -2,8 +2,12 @@ ferm_input_list: - type: dport_accept - dport: [http, https] + dport: [http] filename: nginx_accept + - type: dport_accept + dport: [https] + filename: nginx_accept_https + delete: "{{ not (sites_use_ssl | bool) }}" - type: dport_accept dport: ['443'] protocol: udp From fc4239e04e607e0a7b8f869dfdc3576056746cc2 Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 27 Aug 2024 20:12:42 +0200 Subject: [PATCH 10/20] Move http3 includes into `server_basic` block. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index e37ed0c3f6..f3bd344631 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -23,11 +23,6 @@ server { error_log {{ www_root }}/{{ item.key }}/logs/error.log; {% endblock %} - {% if nginx_http3_enabled and ssl_enabled -%} - include includes/directive-only/http3-tune.conf; - include includes/directive-only/http3-negotiate.conf; - {% endif -%} - {% block server_basic -%} root {{ www_root }}/{{ item.key }}/{{ item.value.current_path | default('current') }}/{{ item.value.public_path | default('web') }}; index index.php index.htm index.html; @@ -43,6 +38,11 @@ server { # https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#virtualbox sendfile off; + {% endif -%} + + {% if nginx_http3_enabled and ssl_enabled -%} + include includes/directive-only/http3-tune.conf; + include includes/directive-only/http3-negotiate.conf; {% endif -%} {% endblock -%} From 9c2cfbd5c105f7065e1405eb2bbafd5dd8fcf6e1 Mon Sep 17 00:00:00 2001 From: strarsis Date: Tue, 27 Aug 2024 21:02:36 +0200 Subject: [PATCH 11/20] Add global quic listen with reuseport for working QUIC responses. --- group_vars/production/wordpress_sites.yml | 2 ++ roles/wordpress-setup/defaults/main.yml | 1 + .../templates/http3-reuseport.conf.j2 | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 roles/wordpress-setup/templates/http3-reuseport.conf.j2 diff --git a/group_vars/production/wordpress_sites.yml b/group_vars/production/wordpress_sites.yml index fc94943c51..e01876c733 100644 --- a/group_vars/production/wordpress_sites.yml +++ b/group_vars/production/wordpress_sites.yml @@ -2,6 +2,8 @@ # `wordpress_sites` options: https://roots.io/trellis/docs/wordpress-sites # Define accompanying passwords/secrets in group_vars/production/vault.yml +wordpress_default_site: example.com + wordpress_sites: example.com: site_hosts: diff --git a/roles/wordpress-setup/defaults/main.yml b/roles/wordpress-setup/defaults/main.yml index e654f59aa7..9d0fa23701 100644 --- a/roles/wordpress-setup/defaults/main.yml +++ b/roles/wordpress-setup/defaults/main.yml @@ -4,6 +4,7 @@ nginx_ssl_path: "{{ nginx_path }}/ssl" nginx_sites_confs: - src: no-default.conf.j2 + - src: http3-reuseport.conf.j2 - src: ssl.no-default.conf.j2 enabled: false diff --git a/roles/wordpress-setup/templates/http3-reuseport.conf.j2 b/roles/wordpress-setup/templates/http3-reuseport.conf.j2 new file mode 100644 index 0000000000..63847bf6c6 --- /dev/null +++ b/roles/wordpress-setup/templates/http3-reuseport.conf.j2 @@ -0,0 +1,23 @@ +# One global listen with reuseport is required for working QUIC+HTTP/3 responses +{% if nginx_http3_enabled and sites_use_ssl and wordpress_default_site -%} +server { + # Listen on UDP for QUIC+HTTP/3 globally with reuseport + listen [::]:443 quic default_server reuseport; + listen 443 quic default_server reuseport; + + {% if wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'manual' and wordpress_sites[wordpress_default_site].ssl.cert is defined and wordpress_sites[wordpress_default_site].ssl.key is defined -%} + ssl_certificate {{ nginx_path }}/ssl/{{ wordpress_sites[wordpress_default_site].ssl.cert | basename }}; + ssl_certificate_key {{ nginx_path }}/ssl/{{ wordpress_sites[wordpress_default_site].ssl.key | basename }}; + + {% elif wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'letsencrypt' -%} + ssl_certificate {{ nginx_path }}/ssl/letsencrypt/{{ wordpress_default_site }}-bundled.cert; + ssl_certificate_key {{ nginx_path }}/ssl/letsencrypt/{{ wordpress_default_site }}.key; + + {% elif wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'self-signed' -%} + ssl_certificate {{ nginx_path }}/ssl/{{ wordpress_default_site }}.cert; + ssl_trusted_certificate {{ nginx_path }}/ssl/{{ wordpress_default_site }}.cert; + ssl_certificate_key {{ nginx_path }}/ssl/{{ wordpress_default_site }}.key; + + {% endif -%} +} +{% endif -%} From a220796ad55125e54aa3cf9c0eac245a46ea7f6c Mon Sep 17 00:00:00 2001 From: strarsis Date: Thu, 29 Aug 2024 20:33:46 +0200 Subject: [PATCH 12/20] Conditionally add global listen quic reuseport config file. --- roles/wordpress-setup/defaults/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/roles/wordpress-setup/defaults/main.yml b/roles/wordpress-setup/defaults/main.yml index 9d0fa23701..49a123d2a5 100644 --- a/roles/wordpress-setup/defaults/main.yml +++ b/roles/wordpress-setup/defaults/main.yml @@ -5,6 +5,7 @@ nginx_ssl_path: "{{ nginx_path }}/ssl" nginx_sites_confs: - src: no-default.conf.j2 - src: http3-reuseport.conf.j2 + enabled: "{{ nginx_http3_enabled and (sites_use_ssl | bool) and wordpress_default_site }}" - src: ssl.no-default.conf.j2 enabled: false From b86a19ab24bbe05618f11ad486cdb279532da1e3 Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 18:39:14 +0200 Subject: [PATCH 13/20] Use `reuseport` in first HTTPS site config directly instead in global listener. --- group_vars/all/helpers.yml | 3 ++- group_vars/production/wordpress_sites.yml | 2 -- roles/wordpress-setup/defaults/main.yml | 2 -- roles/wordpress-setup/tasks/nginx.yml | 3 +++ .../templates/http3-reuseport.conf.j2 | 23 ------------------- .../templates/wordpress-site.conf.j2 | 7 +++--- 6 files changed, 9 insertions(+), 31 deletions(-) delete mode 100644 roles/wordpress-setup/templates/http3-reuseport.conf.j2 diff --git a/group_vars/all/helpers.yml b/group_vars/all/helpers.yml index 29d2c29d8a..a41b17afba 100644 --- a/group_vars/all/helpers.yml +++ b/group_vars/all/helpers.yml @@ -18,7 +18,8 @@ multisite_subdomains_wildcards: "{{ item.value.multisite.subdomains | default(fa ssl_enabled: "{{ item.value.ssl is defined and item.value.ssl.enabled | default(false) }}" ssl_stapling_enabled: "{{ item.value.ssl is defined and item.value.ssl.stapling_enabled | default(true) }}" cron_enabled: "{{ site_env.disable_wp_cron and (not item.value.multisite.enabled | default(false) or (item.value.multisite.enabled | default(false) and item.value.multisite.cron | default(true))) }}" -sites_use_ssl: "{{ wordpress_sites.values() | map(attribute='ssl') | selectattr('enabled') | list | count > 0 }}" +sites_using_ssl: "{{ wordpress_sites | dict2items | selectattr('value.ssl.enabled', 'equalto', true) | items2dict }}" +sites_use_ssl: "{{ sites_using_ssl | length > 0 }}" composer_authentications: "{{ vault_wordpress_sites[site].composer_authentications | default([]) }}" # Default `type` is `http-basic`. diff --git a/group_vars/production/wordpress_sites.yml b/group_vars/production/wordpress_sites.yml index e01876c733..fc94943c51 100644 --- a/group_vars/production/wordpress_sites.yml +++ b/group_vars/production/wordpress_sites.yml @@ -2,8 +2,6 @@ # `wordpress_sites` options: https://roots.io/trellis/docs/wordpress-sites # Define accompanying passwords/secrets in group_vars/production/vault.yml -wordpress_default_site: example.com - wordpress_sites: example.com: site_hosts: diff --git a/roles/wordpress-setup/defaults/main.yml b/roles/wordpress-setup/defaults/main.yml index 49a123d2a5..e654f59aa7 100644 --- a/roles/wordpress-setup/defaults/main.yml +++ b/roles/wordpress-setup/defaults/main.yml @@ -4,8 +4,6 @@ nginx_ssl_path: "{{ nginx_path }}/ssl" nginx_sites_confs: - src: no-default.conf.j2 - - src: http3-reuseport.conf.j2 - enabled: "{{ nginx_http3_enabled and (sites_use_ssl | bool) and wordpress_default_site }}" - src: ssl.no-default.conf.j2 enabled: false diff --git a/roles/wordpress-setup/tasks/nginx.yml b/roles/wordpress-setup/tasks/nginx.yml index a0a0c0cc9e..8bad0fdea7 100644 --- a/roles/wordpress-setup/tasks/nginx.yml +++ b/roles/wordpress-setup/tasks/nginx.yml @@ -75,6 +75,9 @@ loop: "{{ wordpress_sites | dict2items }}" loop_control: label: "{{ item.key }}" + vars: + first_site_using_ssl: "{{ (sites_using_ssl | dict2items | first | default(None, True)) }}" + is_first_site_use_ssl: "{{ first_site_using_ssl.key == item.key }}" notify: reload nginx tags: nginx-includes diff --git a/roles/wordpress-setup/templates/http3-reuseport.conf.j2 b/roles/wordpress-setup/templates/http3-reuseport.conf.j2 deleted file mode 100644 index 63847bf6c6..0000000000 --- a/roles/wordpress-setup/templates/http3-reuseport.conf.j2 +++ /dev/null @@ -1,23 +0,0 @@ -# One global listen with reuseport is required for working QUIC+HTTP/3 responses -{% if nginx_http3_enabled and sites_use_ssl and wordpress_default_site -%} -server { - # Listen on UDP for QUIC+HTTP/3 globally with reuseport - listen [::]:443 quic default_server reuseport; - listen 443 quic default_server reuseport; - - {% if wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'manual' and wordpress_sites[wordpress_default_site].ssl.cert is defined and wordpress_sites[wordpress_default_site].ssl.key is defined -%} - ssl_certificate {{ nginx_path }}/ssl/{{ wordpress_sites[wordpress_default_site].ssl.cert | basename }}; - ssl_certificate_key {{ nginx_path }}/ssl/{{ wordpress_sites[wordpress_default_site].ssl.key | basename }}; - - {% elif wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'letsencrypt' -%} - ssl_certificate {{ nginx_path }}/ssl/letsencrypt/{{ wordpress_default_site }}-bundled.cert; - ssl_certificate_key {{ nginx_path }}/ssl/letsencrypt/{{ wordpress_default_site }}.key; - - {% elif wordpress_sites[wordpress_default_site].ssl.provider | default('manual') == 'self-signed' -%} - ssl_certificate {{ nginx_path }}/ssl/{{ wordpress_default_site }}.cert; - ssl_trusted_certificate {{ nginx_path }}/ssl/{{ wordpress_default_site }}.cert; - ssl_certificate_key {{ nginx_path }}/ssl/{{ wordpress_default_site }}.key; - - {% endif -%} -} -{% endif -%} diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index f3bd344631..7feb0fef37 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -8,9 +8,10 @@ server { listen {{ ssl_enabled | ternary('443 ssl', '80') }}; {% if nginx_http3_enabled and ssl_enabled -%} - # Listen on UDP for QUIC+HTTP/3 - listen [::]:443 quic; - listen 443 quic; + # Listen on UDP for QUIC+HTTP/3 | {{ is_first_site_use_ssl }}{{ sites_use_ssl }} + listen [::]:443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; + listen 443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; + {% if is_first_site_use_ssl -%}# there has to be one listen quic directive with reusport for working QUIC responses in current nginx version, using the first site.{% endif %} {% endif -%} http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; From 229f7c801e76f67bf927640afb0fe885ca2e9959 Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 18:43:05 +0200 Subject: [PATCH 14/20] Remove debug output in template. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 7feb0fef37..338aa0ff2b 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -8,7 +8,7 @@ server { listen {{ ssl_enabled | ternary('443 ssl', '80') }}; {% if nginx_http3_enabled and ssl_enabled -%} - # Listen on UDP for QUIC+HTTP/3 | {{ is_first_site_use_ssl }}{{ sites_use_ssl }} + # Listen on UDP for QUIC+HTTP/3 listen [::]:443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; listen 443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; {% if is_first_site_use_ssl -%}# there has to be one listen quic directive with reusport for working QUIC responses in current nginx version, using the first site.{% endif %} From ea3461bc1523ae84173302593cd84815c8cd8c93 Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 19:12:12 +0200 Subject: [PATCH 15/20] Fix newline in comment. Improve newlines in config. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 338aa0ff2b..e08709a279 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -11,8 +11,9 @@ server { # Listen on UDP for QUIC+HTTP/3 listen [::]:443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; listen 443 quic{% if is_first_site_use_ssl %} reuseport{% endif -%}; - {% if is_first_site_use_ssl -%}# there has to be one listen quic directive with reusport for working QUIC responses in current nginx version, using the first site.{% endif %} - {% endif -%} + {% if is_first_site_use_ssl -%}# there has to be one listen quic directive with reusport for working QUIC responses in current nginx version, using the first site. + {% endif %} + {% endif %} http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; From b6adf2e0570f6657f5351708e19dfa547d76ae57 Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 19:12:30 +0200 Subject: [PATCH 16/20] Make `first_site_using_ssl` a normal variable. --- group_vars/all/helpers.yml | 1 + roles/wordpress-setup/tasks/nginx.yml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/group_vars/all/helpers.yml b/group_vars/all/helpers.yml index a41b17afba..dd5a9e0451 100644 --- a/group_vars/all/helpers.yml +++ b/group_vars/all/helpers.yml @@ -19,6 +19,7 @@ ssl_enabled: "{{ item.value.ssl is defined and item.value.ssl.enabled | default( ssl_stapling_enabled: "{{ item.value.ssl is defined and item.value.ssl.stapling_enabled | default(true) }}" cron_enabled: "{{ site_env.disable_wp_cron and (not item.value.multisite.enabled | default(false) or (item.value.multisite.enabled | default(false) and item.value.multisite.cron | default(true))) }}" sites_using_ssl: "{{ wordpress_sites | dict2items | selectattr('value.ssl.enabled', 'equalto', true) | items2dict }}" +first_site_using_ssl: "{{ (sites_using_ssl | dict2items | first | default(None, True)) }}" sites_use_ssl: "{{ sites_using_ssl | length > 0 }}" composer_authentications: "{{ vault_wordpress_sites[site].composer_authentications | default([]) }}" diff --git a/roles/wordpress-setup/tasks/nginx.yml b/roles/wordpress-setup/tasks/nginx.yml index 8bad0fdea7..4188bf568a 100644 --- a/roles/wordpress-setup/tasks/nginx.yml +++ b/roles/wordpress-setup/tasks/nginx.yml @@ -76,7 +76,6 @@ loop_control: label: "{{ item.key }}" vars: - first_site_using_ssl: "{{ (sites_using_ssl | dict2items | first | default(None, True)) }}" is_first_site_use_ssl: "{{ first_site_using_ssl.key == item.key }}" notify: reload nginx tags: nginx-includes From b007d664b4e902b3ef38374feedb2afbe723603d Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 19:15:58 +0200 Subject: [PATCH 17/20] Improve newlines in config. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index e08709a279..6f31983c87 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -45,7 +45,7 @@ server { {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-tune.conf; include includes/directive-only/http3-negotiate.conf; - {% endif -%} + {% endif %} {% endblock -%} {% block cache_conditions -%} @@ -321,7 +321,7 @@ server { # Listen on UDP for QUIC+HTTP/3 listen [::]:443 quic; listen 443 quic; - {% endif -%} + {% endif %} http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; @@ -330,7 +330,7 @@ server { {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-tune.conf; include includes/directive-only/http3-negotiate-redirect.conf; - {% endif -%} + {% endif %} {{ self.https() -}} From a6aaac964ceea785422648a0e21e20ade076522b Mon Sep 17 00:00:00 2001 From: strarsis Date: Fri, 30 Aug 2024 19:16:39 +0200 Subject: [PATCH 18/20] Improve newlines in config. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 6f31983c87..a88b3cd17f 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -293,7 +293,7 @@ server { {% if nginx_http3_enabled and ssl_enabled -%} include includes/directive-only/http3-negotiate-redirect.conf; - {% endif -%} + {% endif %} location / { return 301 https://$host$request_uri; From 64148cfbbe19cf8d661d9e8bb6717ef6119fc1ad Mon Sep 17 00:00:00 2001 From: strarsis Date: Sat, 31 Aug 2024 19:45:54 +0200 Subject: [PATCH 19/20] Also enable `http3_hq`. --- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index a88b3cd17f..258181ae02 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -17,6 +17,7 @@ server { http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; + http3_hq {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ site_hosts_canonical | union(multisite_subdomains_wildcards) | join(' ') }}; {% endblock %} @@ -325,6 +326,7 @@ server { http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; + http3_hq {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ host.redirects | join(' ') }}; {% if nginx_http3_enabled and ssl_enabled -%} From b5d54fcd5e8a6e9a8c60aec23860b7f4e0c8a8d1 Mon Sep 17 00:00:00 2001 From: strarsis Date: Sat, 31 Aug 2024 19:48:23 +0200 Subject: [PATCH 20/20] Enable `http3_hq` in http3 tune config instead. --- .../templates/includes/directive-only/http3-tune.conf | 4 ++-- roles/wordpress-setup/templates/wordpress-site.conf.j2 | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf index 99c3047635..dae5850fae 100644 --- a/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf +++ b/roles/wordpress-setup/templates/includes/directive-only/http3-tune.conf @@ -1,7 +1,7 @@ +http3_hq on; quic_retry on; +quic_gso on; # enable 0-RTT #ssl_early_data on; #proxy_set_header Early-Data $ssl_early_data; - -quic_gso on; diff --git a/roles/wordpress-setup/templates/wordpress-site.conf.j2 b/roles/wordpress-setup/templates/wordpress-site.conf.j2 index 258181ae02..a88b3cd17f 100644 --- a/roles/wordpress-setup/templates/wordpress-site.conf.j2 +++ b/roles/wordpress-setup/templates/wordpress-site.conf.j2 @@ -17,7 +17,6 @@ server { http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; - http3_hq {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ site_hosts_canonical | union(multisite_subdomains_wildcards) | join(' ') }}; {% endblock %} @@ -326,7 +325,6 @@ server { http2 {{ nginx_http2_enabled | default(false) | ternary('on', 'off') }}; http3 {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; - http3_hq {{ nginx_http3_enabled | default(false) | ternary('on', 'off') }}; server_name {{ host.redirects | join(' ') }}; {% if nginx_http3_enabled and ssl_enabled -%}