@@ -430,3 +430,258 @@ sudo certbot renew --dry-run
430430```
431431
432432Your OpenCloud instance is now running securely behind a fully configured external Nginx reverse proxy with HTTPS.
433+
434+ ## Optional: HTTP/3 (QUIC) Support
435+
436+ :::warning Advanced Setup
437+ HTTP/3 over QUIC requires an nginx build with QUIC support. The stock nginx package on most distributions does ** not** include QUIC. At the time of writing, Ubuntu 26.04+ ships an nginx version with QUIC enabled out of the box. On older distributions you need to build nginx from source with ` --with-http_v3_module ` or use the [ official nginx QUIC packages] ( https://nginx.org/en/docs/quic.html ) .
438+
439+ Verify that your nginx supports QUIC before proceeding:
440+
441+ ``` bash
442+ nginx -V 2>&1 | grep -o -- ' --with-http_v3_module'
443+ ```
444+
445+ If this returns nothing, your nginx does not support QUIC.
446+ :::
447+
448+ HTTP/3 uses QUIC (UDP) alongside the traditional TCP connections for HTTP/1.1 and HTTP/2. This can improve performance for high-latency connections and reduce head-of-line blocking.
449+
450+ The following configuration replaces the HTTP/2 configuration above. It uses ` upstream ` blocks with keepalive connections and a ` map ` directive for cleaner WebSocket handling.
451+
452+ ### Full configuration with HTTP/3
453+
454+ ``` nginx
455+ map $http_upgrade $connection_upgrade {
456+ default upgrade;
457+ '' close;
458+ }
459+
460+ upstream opencloud_backend { server 127.0.0.1:9200; keepalive 32; }
461+ upstream wopi_backend { server 127.0.0.1:9300; keepalive 16; }
462+ upstream collabora_backend { server 127.0.0.1:9980; keepalive 16; }
463+ # Add these if using Euro Office:
464+ # upstream euroffice_backend { server 127.0.0.1:9900; keepalive 16; }
465+ # upstream wopi_eo_backend { server 127.0.0.1:9302; keepalive 16; }
466+
467+ # ── HTTP → HTTPS redirect ──────────────────────────────────
468+ server {
469+ listen 80;
470+ server_name cloud.YOUR.DOMAIN collabora.YOUR.DOMAIN wopiserver.YOUR.DOMAIN;
471+ # Add Euro Office domains if needed:
472+ # server_name cloud.YOUR.DOMAIN collabora.YOUR.DOMAIN wopiserver.YOUR.DOMAIN euro-office.YOUR.DOMAIN wopiserver-eo.YOUR.DOMAIN;
473+
474+ root /var/www/certbot;
475+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
476+
477+ location / {
478+ return 301 https://$host$request_uri;
479+ }
480+ }
481+
482+ # ── OpenCloud ───────────────────────────────────────────────
483+ server {
484+ # QUIC (UDP) — reuseport must only appear on the FIRST server block
485+ listen 443 quic reuseport;
486+ # HTTP/1.1 and HTTP/2 (TCP)
487+ listen 443 ssl;
488+ http2 on;
489+ server_name cloud.YOUR.DOMAIN;
490+
491+ # Advertise HTTP/3 availability to clients
492+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
493+
494+ ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem;
495+ ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem;
496+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
497+
498+ client_max_body_size 0;
499+ keepalive_requests 100000;
500+ keepalive_timeout 5m;
501+ http2_max_concurrent_streams 512;
502+
503+ root /var/www/certbot;
504+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
505+
506+ location / {
507+ proxy_pass http://opencloud_backend;
508+ proxy_set_header Host $host;
509+ proxy_set_header X-Forwarded-Proto https;
510+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
511+ proxy_set_header X-Real-IP $remote_addr;
512+ proxy_http_version 1.1;
513+ proxy_set_header Connection $connection_upgrade;
514+ proxy_set_header Upgrade $http_upgrade;
515+ proxy_read_timeout 3600;
516+ proxy_buffering off;
517+ }
518+ }
519+
520+ # ── Collabora ──────────────────────────────────────────────
521+ server {
522+ listen 443 quic;
523+ listen 443 ssl;
524+ http2 on;
525+ server_name collabora.YOUR.DOMAIN;
526+
527+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
528+
529+ ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem;
530+ ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem;
531+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
532+
533+ keepalive_requests 100000;
534+ keepalive_timeout 5m;
535+ http2_max_concurrent_streams 512;
536+
537+ root /var/www/certbot;
538+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
539+
540+ location / {
541+ proxy_pass http://collabora_backend;
542+ proxy_set_header Host $host;
543+ proxy_set_header X-Forwarded-Proto https;
544+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
545+ proxy_set_header X-Real-IP $remote_addr;
546+ proxy_http_version 1.1;
547+ proxy_set_header Connection $connection_upgrade;
548+ proxy_set_header Upgrade $http_upgrade;
549+ proxy_read_timeout 3600;
550+ proxy_send_timeout 3600;
551+ proxy_buffering off;
552+ }
553+ }
554+
555+ # ── Collabora WOPI Server ──────────────────────────────────
556+ server {
557+ listen 443 quic;
558+ listen 443 ssl;
559+ http2 on;
560+ server_name wopiserver.YOUR.DOMAIN;
561+
562+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
563+
564+ ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem;
565+ ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem;
566+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
567+
568+ keepalive_requests 100000;
569+ keepalive_timeout 5m;
570+ http2_max_concurrent_streams 512;
571+
572+ root /var/www/certbot;
573+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
574+
575+ location / {
576+ proxy_pass http://wopi_backend;
577+ proxy_set_header Host $host;
578+ proxy_set_header X-Forwarded-Proto https;
579+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
580+ proxy_set_header X-Real-IP $remote_addr;
581+ proxy_http_version 1.1;
582+ proxy_set_header Connection $connection_upgrade;
583+ proxy_set_header Upgrade $http_upgrade;
584+ proxy_read_timeout 3600;
585+ proxy_buffering off;
586+ }
587+ }
588+ ```
589+
590+ ### Euro Office blocks with HTTP/3
591+
592+ If using Euro Office, add the following ` upstream ` definitions to the top of your config and append these server blocks:
593+
594+ ``` nginx
595+ upstream euroffice_backend { server 127.0.0.1:9900; keepalive 16; }
596+ upstream wopi_eo_backend { server 127.0.0.1:9302; keepalive 16; }
597+
598+ # ── Euro Office Document Server ────────────────────────────
599+ server {
600+ listen 443 quic;
601+ listen 443 ssl;
602+ http2 on;
603+ server_name euro-office.YOUR.DOMAIN;
604+
605+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
606+
607+ ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem;
608+ ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem;
609+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
610+
611+ client_max_body_size 100M;
612+ keepalive_requests 100000;
613+ keepalive_timeout 5m;
614+ http2_max_concurrent_streams 512;
615+
616+ root /var/www/certbot;
617+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
618+
619+ location / {
620+ proxy_pass http://euroffice_backend;
621+ proxy_set_header Host $host;
622+ proxy_set_header X-Forwarded-Proto https;
623+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
624+ proxy_set_header X-Real-IP $remote_addr;
625+ proxy_http_version 1.1;
626+ proxy_set_header Connection $connection_upgrade;
627+ proxy_set_header Upgrade $http_upgrade;
628+ proxy_read_timeout 3600;
629+ proxy_send_timeout 3600;
630+ proxy_buffering off;
631+ }
632+ }
633+
634+ # ── Euro Office WOPI Server ────────────────────────────────
635+ server {
636+ listen 443 quic;
637+ listen 443 ssl;
638+ http2 on;
639+ server_name wopiserver-eo.YOUR.DOMAIN;
640+
641+ add_header Alt-Svc 'h3=":443"; ma=86400' always;
642+
643+ ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem;
644+ ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem;
645+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
646+
647+ keepalive_requests 100000;
648+ keepalive_timeout 5m;
649+ http2_max_concurrent_streams 512;
650+
651+ root /var/www/certbot;
652+ location ^~ /.well-known/acme-challenge/ { try_files $uri =404; }
653+
654+ location / {
655+ proxy_pass http://wopi_eo_backend;
656+ proxy_set_header Host $host;
657+ proxy_set_header X-Forwarded-Proto https;
658+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
659+ proxy_set_header X-Real-IP $remote_addr;
660+ proxy_http_version 1.1;
661+ proxy_set_header Connection $connection_upgrade;
662+ proxy_set_header Upgrade $http_upgrade;
663+ proxy_read_timeout 3600;
664+ proxy_buffering off;
665+ }
666+ }
667+ ```
668+
669+ ### Key differences from the HTTP/2 configuration
670+
671+ | Detail | HTTP/2 config | HTTP/3 config |
672+ | ---| ---| ---|
673+ | Listen directives | ` listen 443 ssl http2; ` | ` listen 443 quic; ` + ` listen 443 ssl; ` + ` http2 on; ` |
674+ | ` reuseport ` | Not needed | Required on the ** first** ` listen 443 quic ` directive only |
675+ | ` Alt-Svc ` header | Not needed | Required to advertise HTTP/3 to browsers |
676+ | Upstream blocks | Inline ` proxy_pass ` to ` 127.0.0.1 ` | Named ` upstream ` blocks with ` keepalive ` |
677+ | WebSocket upgrade | Per-location ` Connection ` / ` Upgrade ` | Global ` map ` directive |
678+ | Firewall | TCP 443 only | TCP 443 ** and** UDP 443 |
679+
680+ :::warning Firewall
681+ HTTP/3 uses UDP port 443. Make sure your firewall allows ** both** TCP and UDP traffic on port 443:
682+
683+ ``` bash
684+ sudo ufw allow 443/tcp
685+ sudo ufw allow 443/udp
686+ ```
687+ :::
0 commit comments