diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml
index 21f8b4a28..cc441d1a1 100644
--- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml
+++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml
@@ -173,6 +173,13 @@
Enable the HTTP/2 protocol.
true
+
+ httpserver.enable_http3
+
+ checkbox
+ Enable HTTP/3/QUIC for this server (adds QUIC listeners and Alt-Svc header).
+ true
+
httpserver.tls_protocols
diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml
index 88d65ee88..58c73dd62 100644
--- a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml
+++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml
@@ -801,6 +801,10 @@
1
Y
+
+ 0
+ Y
+
Y
Y
diff --git a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf
index f787eff2c..cc316538a 100644
--- a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf
+++ b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf
@@ -120,8 +120,19 @@ server {
{% endif %}
{% if server.listen_https_address is defined and server.listen_https_address != '' %}
+{% set http3_alt_svc_ports = [] %}
{% for listen_address in server.listen_https_address.split(',') %}
listen {{ listen_address }} ssl{% if server.proxy_protocol is defined and server.proxy_protocol == '1' %} proxy_protocol{% endif %}{% if server.default_server is defined and server.default_server == '1' %} default_server{% endif %};
+{% if server.enable_http3|default("0") == "1" %}
+ listen {{ listen_address }} quic reuseport{% if server.default_server is defined and server.default_server == '1' %} default_server{% endif %};
+{% set listen_address_clean = listen_address.replace(' ', '') %}
+{% if listen_address_clean != '' %}
+{% set listen_port = listen_address_clean.split(':')[-1] %}
+{% if listen_port not in http3_alt_svc_ports %}
+{% do http3_alt_svc_ports.append(listen_port) %}
+{% endif %}
+{% endif %}
+{% endif %}
{% endfor %}
http2 {% if server.http2|default("1") == "1" %}on{% else %}off{% endif %};
{% if server.tls_reject_handshake is defined and server.tls_reject_handshake == '1'%}
@@ -155,6 +166,9 @@ server {
{% else %}
ssl_stapling off;
{% endif %}
+{% if server.enable_http3|default("0") == "1" and http3_alt_svc_ports|length > 0 %}
+ add_header Alt-Svc '{% for listen_port in http3_alt_svc_ports %}h3=":{{ listen_port }}"; ma=86400{% if not loop.last %}, {% endif %}{% endfor %}' always;
+{% endif %}
{% endif %}
{% endif %}
{% if server.resolver is defined and server.resolver != '' %}