From 58f7d6d15c820c54ccfe1efb5b21dd539161801b Mon Sep 17 00:00:00 2001 From: zerox80 Date: Mon, 20 Apr 2026 15:10:48 +0200 Subject: [PATCH] docs: add HTTP/3 (QUIC) proxy configuration guide with context --- .../docker-compose/docker-external-proxy.md | 360 ++++++++++++++++++ 1 file changed, 360 insertions(+) diff --git a/docs/admin/getting-started/container/docker-compose/docker-external-proxy.md b/docs/admin/getting-started/container/docker-compose/docker-external-proxy.md index 598b5463..6b866cbe 100644 --- a/docs/admin/getting-started/container/docker-compose/docker-external-proxy.md +++ b/docs/admin/getting-started/container/docker-compose/docker-external-proxy.md @@ -276,3 +276,363 @@ sudo certbot renew --dry-run ``` Your OpenCloud instance is now running securely behind a fully configured external Nginx reverse proxy with HTTPS. + + +## Optional: HTTP/3 (QUIC) Support + +:::info Why use HTTP/3? +HTTP/3 represents a major leap in web performance and reliability by replacing the underlying TCP protocol with QUIC (built on UDP). + +**Key benefits for OpenCloud include:** +1. **Faster Connection Establishment:** Zero round-trip time (0-RTT) handshakes mean users connect to your cloud significantly faster, especially on mobile networks. +2. **No Head-of-Line Blocking:** If a single packet is lost during a large file upload or sync, only that specific transfer is delayed. Other concurrent requests (like loading the dashboard) continue instantly. +3. **Better Mobile Experience:** Connection migration allows users to switch between Wi-Fi and mobile data without dropping their active file syncs or video streams. +4. **Improved Security:** Encryption is built directly into the transport layer, reducing overhead and improving privacy. +::: + +:::warning Advanced Setup +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). + +Verify that your nginx supports QUIC before proceeding: + +```bash +nginx -V 2>&1 | grep -o -- '--with-http_v3_module' +``` + +If this returns nothing, your nginx does not support QUIC. +::: + +The following configurations replace the HTTP/2 configurations above. They use `upstream` blocks with keepalive connections and a `map` directive for cleaner WebSocket handling. Pick the configuration that matches your deployment. + +### Configuration 1: OpenCloud Only with HTTP/3 + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream opencloud_backend { server 127.0.0.1:9200; keepalive 32; } + +# ── HTTP → HTTPS redirect ────────────────────────────────── +server { + listen 80; + server_name cloud.YOUR.DOMAIN; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + return 301 https://$host$request_uri; + } +} + +# ── OpenCloud ─────────────────────────────────────────────── +server { + listen 443 quic reuseport; + listen 443 ssl; + http2 on; + server_name cloud.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + client_max_body_size 0; + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://opencloud_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_buffering off; + } +} +``` + +### Configuration 2: OpenCloud + Collabora with HTTP/3 + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream opencloud_backend { server 127.0.0.1:9200; keepalive 32; } +upstream wopi_backend { server 127.0.0.1:9300; keepalive 16; } +upstream collabora_backend { server 127.0.0.1:9980; keepalive 16; } + +# ── HTTP → HTTPS redirect ────────────────────────────────── +server { + listen 80; + server_name cloud.YOUR.DOMAIN collabora.YOUR.DOMAIN wopiserver.YOUR.DOMAIN; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + return 301 https://$host$request_uri; + } +} + +# ── OpenCloud ─────────────────────────────────────────────── +server { + listen 443 quic reuseport; + listen 443 ssl; + http2 on; + server_name cloud.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + client_max_body_size 0; + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://opencloud_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_buffering off; + } +} + +# ── Collabora ────────────────────────────────────────────── +server { + listen 443 quic; + listen 443 ssl; + http2 on; + server_name collabora.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://collabora_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_send_timeout 3600; + proxy_buffering off; + } +} + +# ── Collabora WOPI Server ────────────────────────────────── +server { + listen 443 quic; + listen 443 ssl; + http2 on; + server_name wopiserver.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://wopi_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_buffering off; + } +} +``` + +### Configuration 3: OpenCloud + Euro Office with HTTP/3 + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +upstream opencloud_backend { server 127.0.0.1:9200; keepalive 32; } +upstream wopi_backend { server 127.0.0.1:9300; keepalive 16; } +upstream euroffice_backend { server 127.0.0.1:9900; keepalive 16; } + +# ── HTTP → HTTPS redirect ────────────────────────────────── +server { + listen 80; + server_name cloud.YOUR.DOMAIN euro-office.YOUR.DOMAIN wopiserver.YOUR.DOMAIN; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + return 301 https://$host$request_uri; + } +} + +# ── OpenCloud ─────────────────────────────────────────────── +server { + listen 443 quic reuseport; + listen 443 ssl; + http2 on; + server_name cloud.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + client_max_body_size 0; + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://opencloud_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_buffering off; + } +} + +# ── Euro Office Document Server ──────────────────────────── +server { + listen 443 quic; + listen 443 ssl; + http2 on; + server_name euro-office.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + client_max_body_size 100M; + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://euroffice_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_send_timeout 3600; + proxy_buffering off; + } +} + +# ── Euro Office WOPI Server ──────────────────────────────── +server { + listen 443 quic; + listen 443 ssl; + http2 on; + server_name wopiserver.YOUR.DOMAIN; + + add_header Alt-Svc 'h3=":443"; ma=86400' always; + ssl_certificate /etc/letsencrypt/live/cloud.YOUR.DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/cloud.YOUR.DOMAIN/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + keepalive_requests 100000; + keepalive_timeout 5m; + http2_max_concurrent_streams 512; + + root /var/www/certbot; + location ^~ /.well-known/acme-challenge/ { try_files $uri =404; } + + location / { + proxy_pass http://wopi_backend; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Upgrade $http_upgrade; + proxy_read_timeout 3600; + proxy_buffering off; + } +} +``` + +### Key differences from the HTTP/2 configuration + +| Detail | HTTP/2 config | HTTP/3 config | +|---|---|---| +| Listen directives | `listen 443 ssl http2;` | `listen 443 quic;` + `listen 443 ssl;` + `http2 on;` | +| `reuseport` | Not needed | Required on the **first** `listen 443 quic` directive only | +| `Alt-Svc` header | Not needed | Required to advertise HTTP/3 to browsers | +| Upstream blocks | Inline `proxy_pass` to `127.0.0.1` | Named `upstream` blocks with `keepalive` | +| WebSocket upgrade | Per-location `Connection` / `Upgrade` | Global `map` directive | +| Firewall | TCP 443 only | TCP 443 **and** UDP 443 | + +:::warning Firewall +HTTP/3 uses UDP port 443. Make sure your firewall allows **both** TCP and UDP traffic on port 443: + +```bash +sudo ufw allow 443/tcp +sudo ufw allow 443/udp +``` +:::