diff --git a/roles/archive_web/templates/nginx.d.conf.j2 b/roles/archive_web/templates/nginx.d.conf.j2 index 17e2beab..e1dda57f 100644 --- a/roles/archive_web/templates/nginx.d.conf.j2 +++ b/roles/archive_web/templates/nginx.d.conf.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ archive_domain }}; access_log /var/log/nginx/{{ archive_domain }}/access.log reduced; diff --git a/roles/archmanweb/templates/nginx.d.conf.j2 b/roles/archmanweb/templates/nginx.d.conf.j2 index 3c51fe12..b32e0c14 100644 --- a/roles/archmanweb/templates/nginx.d.conf.j2 +++ b/roles/archmanweb/templates/nginx.d.conf.j2 @@ -23,9 +23,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ archmanweb_domain }}; access_log /var/log/nginx/{{ archmanweb_domain }}/access.log reduced; diff --git a/roles/archweb/templates/ipxe.archlinux.org.j2 b/roles/archweb/templates/ipxe.archlinux.org.j2 index dd6c6f37..956741ad 100644 --- a/roles/archweb/templates/ipxe.archlinux.org.j2 +++ b/roles/archweb/templates/ipxe.archlinux.org.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain['domain_name'] }}; access_log /var/log/nginx/{{ archweb_domain }}/access.log reduced; diff --git a/roles/archweb/templates/maintenance-nginx.d.conf.j2 b/roles/archweb/templates/maintenance-nginx.d.conf.j2 index e9f74377..332fb120 100644 --- a/roles/archweb/templates/maintenance-nginx.d.conf.j2 +++ b/roles/archweb/templates/maintenance-nginx.d.conf.j2 @@ -21,9 +21,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; @@ -60,9 +58,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; @@ -98,9 +94,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ service_domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; diff --git a/roles/archweb/templates/nginx.d.conf.j2 b/roles/archweb/templates/nginx.d.conf.j2 index 186befa2..284da1c4 100644 --- a/roles/archweb/templates/nginx.d.conf.j2 +++ b/roles/archweb/templates/nginx.d.conf.j2 @@ -54,9 +54,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain['domain'] }}; access_log /var/log/nginx/{{ archweb_domain }}/access.log reduced; @@ -102,9 +100,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ archweb_domain }}; access_log /var/log/nginx/{{ archweb_domain }}/access.log reduced; diff --git a/roles/archwiki/templates/nginx.d.conf.j2 b/roles/archwiki/templates/nginx.d.conf.j2 index 0be7fe31..a886a16d 100644 --- a/roles/archwiki/templates/nginx.d.conf.j2 +++ b/roles/archwiki/templates/nginx.d.conf.j2 @@ -59,9 +59,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ archwiki_domain }}; access_log /var/log/nginx/{{ archwiki_domain }}/access.log reduced; diff --git a/roles/aurweb/templates/nginx.d.conf.j2 b/roles/aurweb/templates/nginx.d.conf.j2 index a594ef98..cb883758 100644 --- a/roles/aurweb/templates/nginx.d.conf.j2 +++ b/roles/aurweb/templates/nginx.d.conf.j2 @@ -35,9 +35,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ aurweb_domain }}; access_log /var/log/nginx/{{ aurweb_domain }}/access.log main; diff --git a/roles/dbscripts/templates/nginx.d.conf.j2 b/roles/dbscripts/templates/nginx.d.conf.j2 index 2943dcc8..86e349c0 100644 --- a/roles/dbscripts/templates/nginx.d.conf.j2 +++ b/roles/dbscripts/templates/nginx.d.conf.j2 @@ -3,9 +3,7 @@ proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=auth_cache:5m inacti server { listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ repos_domain }} {{repos_rsync_domain}}; root /srv/ftp; diff --git a/roles/debuginfod/templates/nginx.d.conf.j2 b/roles/debuginfod/templates/nginx.d.conf.j2 index b9396f08..b5d7bb68 100644 --- a/roles/debuginfod/templates/nginx.d.conf.j2 +++ b/roles/debuginfod/templates/nginx.d.conf.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ debuginfod_domain }}; access_log /var/log/nginx/{{ debuginfod_domain }}/access.log reduced; diff --git a/roles/fluxbb/templates/nginx.conf.j2 b/roles/fluxbb/templates/nginx.conf.j2 index 563cfb13..5701ef71 100644 --- a/roles/fluxbb/templates/nginx.conf.j2 +++ b/roles/fluxbb/templates/nginx.conf.j2 @@ -23,9 +23,7 @@ limit_req_zone $binary_remote_addr zone=bbslimit:10m rate=10r/s; limit_req_status 429; server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ fluxbb_domain }}; root {{ fluxbb_dir }}; index index.php; diff --git a/roles/grafana/templates/nginx.d.conf.j2 b/roles/grafana/templates/nginx.d.conf.j2 index 7a8583a0..288e9290 100644 --- a/roles/grafana/templates/nginx.d.conf.j2 +++ b/roles/grafana/templates/nginx.d.conf.j2 @@ -25,9 +25,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ grafana_domain }}; access_log /var/log/nginx/{{ grafana_domain }}/access.log main; diff --git a/roles/hedgedoc/templates/nginx.d.conf.j2 b/roles/hedgedoc/templates/nginx.d.conf.j2 index d1257ce2..7c97d697 100644 --- a/roles/hedgedoc/templates/nginx.d.conf.j2 +++ b/roles/hedgedoc/templates/nginx.d.conf.j2 @@ -24,9 +24,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ hedgedoc_domain }}; access_log /var/log/nginx/{{ hedgedoc_domain }}/access.log main; diff --git a/roles/keycloak/templates/nginx.d.conf.j2 b/roles/keycloak/templates/nginx.d.conf.j2 index 622e396c..d0e637be 100644 --- a/roles/keycloak/templates/nginx.d.conf.j2 +++ b/roles/keycloak/templates/nginx.d.conf.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ keycloak_domain }}; access_log /var/log/nginx/{{ keycloak_domain }}/access.log reduced; diff --git a/roles/mailman/templates/nginx.d.conf.j2 b/roles/mailman/templates/nginx.d.conf.j2 index eceb66e0..e9b3016c 100644 --- a/roles/mailman/templates/nginx.d.conf.j2 +++ b/roles/mailman/templates/nginx.d.conf.j2 @@ -35,9 +35,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ lists_domain }}; access_log /var/log/nginx/{{ lists_domain }}/access.log main; diff --git a/roles/maintenance/templates/nginx-maintenance.conf.j2 b/roles/maintenance/templates/nginx-maintenance.conf.j2 index 2493c1b7..b4ab8551 100644 --- a/roles/maintenance/templates/nginx-maintenance.conf.j2 +++ b/roles/maintenance/templates/nginx-maintenance.conf.j2 @@ -17,9 +17,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; @@ -56,9 +54,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; @@ -94,9 +90,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ service_domain }}; access_log {{ maintenance_logs_dir }}/{{ service_domain }}-access.log reduced; diff --git a/roles/matrix/templates/nginx.d.conf.j2 b/roles/matrix/templates/nginx.d.conf.j2 index 85fdc500..d2dc9ac5 100644 --- a/roles/matrix/templates/nginx.d.conf.j2 +++ b/roles/matrix/templates/nginx.d.conf.j2 @@ -22,9 +22,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ matrix_domain }}; access_log /var/log/nginx/{{ matrix_domain }}/access.log reduced; diff --git a/roles/mirrorsync/templates/nginx.d.conf.j2 b/roles/mirrorsync/templates/nginx.d.conf.j2 index 4eb9cd84..26bd9989 100644 --- a/roles/mirrorsync/templates/nginx.d.conf.j2 +++ b/roles/mirrorsync/templates/nginx.d.conf.j2 @@ -1,9 +1,7 @@ server { listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ item.value.mirror_domain }}; root {{ item.value.target }}; diff --git a/roles/mta_sts/templates/nginx.d.conf.j2 b/roles/mta_sts/templates/nginx.d.conf.j2 index abdced54..992e529a 100644 --- a/roles/mta_sts/templates/nginx.d.conf.j2 +++ b/roles/mta_sts/templates/nginx.d.conf.j2 @@ -18,9 +18,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name mta-sts.{{ config.domains | join(' mta-sts.') }}; access_log /var/log/nginx/{{ domain }}/access.log reduced; diff --git a/roles/nginx/defaults/main.yml b/roles/nginx/defaults/main.yml index 19c93170..abc8e3ba 100644 --- a/roles/nginx/defaults/main.yml +++ b/roles/nginx/defaults/main.yml @@ -1,3 +1,4 @@ letsencrypt_validation_dir: "/var/lib/letsencrypt" nginx_firewall_zone: nginx_extra_modules: [] +nginx_enable_http3: false diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml index 1129b280..5c0420f8 100644 --- a/roles/nginx/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -19,11 +19,12 @@ - snippets - name: Copy snippets - template: src={{ item }} dest=/etc/nginx/snippets owner=root group=root mode=0644 + template: src={{ item }} dest=/etc/nginx/snippets/{{ item | regex_replace('\\.j2$', '') }} owner=root group=root mode=0644 with_items: - letsencrypt.conf - sslsettings.conf - headers.conf + - listen-443.conf.j2 notify: - Reload nginx @@ -66,6 +67,7 @@ with_items: - http - https + - "{{ 'http3' if nginx_enable_http3 else omit }}" when: configure_firewall tags: - firewall diff --git a/roles/nginx/templates/headers.conf b/roles/nginx/templates/headers.conf index d4274303..9e3a1eff 100644 --- a/roles/nginx/templates/headers.conf +++ b/roles/nginx/templates/headers.conf @@ -1 +1,4 @@ add_header Strict-Transport-Security $hsts_header always; +{% if nginx_enable_http3 %} +add_header Alt-Svc $alt_svc_header always; +{% endif %} diff --git a/roles/nginx/templates/listen-443.conf.j2 b/roles/nginx/templates/listen-443.conf.j2 new file mode 100644 index 00000000..2dd4cfdc --- /dev/null +++ b/roles/nginx/templates/listen-443.conf.j2 @@ -0,0 +1,7 @@ +listen 443 ssl; +listen [::]:443 ssl; +{% if nginx_enable_http3 %} +listen 443 quic; +listen [::]:443 quic; +{% endif %} +http2 on; diff --git a/roles/nginx/templates/nginx-hostname-vhost.conf.j2 b/roles/nginx/templates/nginx-hostname-vhost.conf.j2 index b34be7a8..e19d6d63 100644 --- a/roles/nginx/templates/nginx-hostname-vhost.conf.j2 +++ b/roles/nginx/templates/nginx-hostname-vhost.conf.j2 @@ -1,6 +1,14 @@ server { listen 80 default_server; listen [::]:80 default_server; + listen 443 default_server ssl; + listen [::]:443 default_server ssl; +{% if nginx_enable_http3 %} + listen 443 default_server quic reuseport; + listen [::]:443 default_server quic reuseport; +{% endif %} + http2 on; + ssl_reject_handshake on; root /srv/http; include snippets/letsencrypt.conf; diff --git a/roles/nginx/templates/nginx.conf.j2 b/roles/nginx/templates/nginx.conf.j2 index 29ba7141..2a075eeb 100644 --- a/roles/nginx/templates/nginx.conf.j2 +++ b/roles/nginx/templates/nginx.conf.j2 @@ -27,12 +27,13 @@ http { log_format main '$remote_addr $host $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for" $request_time'; + '"$http_user_agent" "$http_x_forwarded_for" $request_time' + '$server_protocol'; log_format reduced '$host [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent"'; + '"$http_user_agent" $server_protocol'; log_format json_main escape=json '{' @@ -48,6 +49,7 @@ http { '"http_user_agent":"$http_user_agent",' '"http_x_forwarded_for":"$http_x_forwarded_for",' '"request_time":"$request_time",' + '"server_protocol":"$server_protocol",' # This was added to keep every log line unique as Loki drops # log line with the same timestamp and log text: # https://grafana.com/docs/loki/latest/overview/#timestamp-ordering @@ -65,6 +67,7 @@ http { '"body_bytes_sent":"$body_bytes_sent",' '"http_referrer":"$http_referer",' '"http_user_agent":"$http_user_agent",' + '"server_protocol":"$server_protocol",' # This was added to keep every log line unique as Loki drops # log line with the same timestamp and log text: # https://grafana.com/docs/loki/latest/overview/#timestamp-ordering diff --git a/roles/nginx/templates/sslsettings.conf b/roles/nginx/templates/sslsettings.conf index 43d7f938..2f435202 100644 --- a/roles/nginx/templates/sslsettings.conf +++ b/roles/nginx/templates/sslsettings.conf @@ -18,4 +18,17 @@ map $scheme $hsts_header { https "max-age=31536000; includeSubdomains; preload"; } +{% if nginx_enable_http3 %} +# Chrome, Firefox and curl only use the header from secure origins. +# https://issues.chromium.org/issues/40471032 +# https://bugzilla.mozilla.org/show_bug.cgi?id=1730935 +# https://everything.curl.dev/libcurl-http/alt-svc.html +# See headers.conf for the Alt-Svc add_header line. +map $scheme $alt_svc_header { + # Keep a low max-age for HTTP/3 while testing. + # Bump to 2592000 when we are done testing. + https 'h3=":443"; ma=3600'; +} + +{% endif %} resolver 127.0.0.53; diff --git a/roles/ping/templates/nginx.d.conf.j2 b/roles/ping/templates/nginx.d.conf.j2 index ea375742..d794023a 100644 --- a/roles/ping/templates/nginx.d.conf.j2 +++ b/roles/ping/templates/nginx.d.conf.j2 @@ -2,9 +2,7 @@ server { # We don't redirect to HTTPS because a redirect is considered a captive portal. listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ ping_domain }}; access_log /var/log/nginx/{{ ping_domain }}/access.log reduced; diff --git a/roles/public_html/templates/nginx.d.conf.j2 b/roles/public_html/templates/nginx.d.conf.j2 index 619ad61e..d795444f 100644 --- a/roles/public_html/templates/nginx.d.conf.j2 +++ b/roles/public_html/templates/nginx.d.conf.j2 @@ -17,9 +17,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ public_domain }} www.{{ public_domain }}; root /srv/public_html; diff --git a/roles/rebuilderd/templates/nginx.d.conf.j2 b/roles/rebuilderd/templates/nginx.d.conf.j2 index bd4cc6c5..a743e78f 100644 --- a/roles/rebuilderd/templates/nginx.d.conf.j2 +++ b/roles/rebuilderd/templates/nginx.d.conf.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ rebuilderd_domain }}; access_log /var/log/nginx/{{ rebuilderd_domain }}/access.log reduced; diff --git a/roles/redirects/templates/nginx.d.conf.j2 b/roles/redirects/templates/nginx.d.conf.j2 index 99bd9db9..8e4cf884 100644 --- a/roles/redirects/templates/nginx.d.conf.j2 +++ b/roles/redirects/templates/nginx.d.conf.j2 @@ -9,9 +9,7 @@ map $uri ${{ redirect.map | hash('md5') }} { server { listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ redirect.domain }}; access_log /var/log/nginx/{{ redirect.domain }}/access.log reduced; diff --git a/roles/repo_archive_split_temp/templates/nginx.d.conf.j2 b/roles/repo_archive_split_temp/templates/nginx.d.conf.j2 index 0418761b..5b8114b7 100644 --- a/roles/repo_archive_split_temp/templates/nginx.d.conf.j2 +++ b/roles/repo_archive_split_temp/templates/nginx.d.conf.j2 @@ -1,9 +1,7 @@ server { listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ repos_rsync_domain }}; root /srv/ftp; diff --git a/roles/security_tracker/templates/nginx.d.conf.j2 b/roles/security_tracker/templates/nginx.d.conf.j2 index d96a29a2..6eeddfdb 100644 --- a/roles/security_tracker/templates/nginx.d.conf.j2 +++ b/roles/security_tracker/templates/nginx.d.conf.j2 @@ -29,9 +29,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ security_tracker_domain }}; access_log /var/log/nginx/{{ security_tracker_domain }}/access.log reduced; diff --git a/roles/sources/templates/nginx.d.conf.j2 b/roles/sources/templates/nginx.d.conf.j2 index 4420e207..3c7cdc6f 100644 --- a/roles/sources/templates/nginx.d.conf.j2 +++ b/roles/sources/templates/nginx.d.conf.j2 @@ -16,9 +16,7 @@ server { } server { - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ sources_domain }}; access_log /var/log/nginx/{{ sources_domain }}/access.log reduced; diff --git a/roles/syncrepo/templates/nginx.d.conf.j2 b/roles/syncrepo/templates/nginx.d.conf.j2 index c5743639..d164c1f5 100644 --- a/roles/syncrepo/templates/nginx.d.conf.j2 +++ b/roles/syncrepo/templates/nginx.d.conf.j2 @@ -2,9 +2,7 @@ server { listen 80; listen [::]:80; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; + include snippets/listen-443.conf; server_name {{ domain }}; root /srv/ftp;