Skip to content

Commit 795237a

Browse files
committed
docs: add guide for running OpenCloud behind an external Nginx proxy with Certbot
1 parent d7dd502 commit 795237a

1 file changed

Lines changed: 255 additions & 0 deletions

File tree

docs/admin/getting-started/container/docker-compose/docker-external-proxy.md

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,258 @@ sudo certbot renew --dry-run
430430
```
431431

432432
Your 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

Comments
 (0)