1. The problem I’m having:
I try to get HTTP/3 to work with my Nextcloud instance, but for some reason Firefox keeps using HTTP/2.
Unfortunately, I cannot recreate this using curl, since it doesn’t support HTTP/3 at the moment (at least not the version that I am using).
So i can only show you the Firefox screenshots for now:
Of course, I opened port 443 UDP on my router and the Docker container, but still no luck.
And while I am writing this question I came up with the idea of trying Chromium as well, and apparently here Http/3 is used indeed.
So now my question is more like, why does Firefox not use HTTP/3 if it seems to be available?
2. Error messages and/or full log output:
I get no specific error, but I can still show you the logs.
For some reason the forums do not allow me to post the logs, so i put them on Pastebin: NF INF INF INF INF INF INF INF ts=1704614818.4108605 INF INF INF INF INF INF INF - Pastebin.com
I had to truncate it, because every request contains a lot of private information because of the filenames.
If you need more logs, I can provide them but it takes time to clean them.
3. Caddy version:
v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=
4. How I installed and ran Caddy:
a. System environment:
Docker on Ubuntu 22.04 which itself runs in a VM hosted by TrueNAS Scale
b. Command:
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
c. Service/unit/compose file:
I do not use compose for this container, but i can give you the output of docker inspect.
{
"AppArmorProfile": "docker-default",
"Args": [
"run",
"--config",
"/etc/caddy/Caddyfile",
"--adapter",
"caddyfile"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"caddy",
"run",
"--config",
"/etc/caddy/Caddyfile",
"--adapter",
"caddyfile"
],
"Domainname": "",
"Entrypoint": null,
"Env": [
"CADDY_DIST_COMMIT=80870b227ded910971ecace4a0c136bf0ef46342",
"CADDY_VERSION=v2.1.1",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"XDG_CONFIG_HOME=/config",
"XDG_DATA_HOME=/data"
],
"ExposedPorts": {
"2019/tcp": {},
"443/tcp": {},
"443/udp": {},
"80/tcp": {},
"8071/tcp": {}
},
"Hostname": "c323a69d3f0e",
"Image": "caddy:2",
"Labels": {
"org.opencontainers.image.description": "a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go",
"org.opencontainers.image.documentation": "https://caddyserver.com/docs",
"org.opencontainers.image.licenses": "Apache-2.0",
"org.opencontainers.image.source": "https://github.com/caddyserver/caddy-docker",
"org.opencontainers.image.title": "Caddy",
"org.opencontainers.image.url": "https://caddyserver.com",
"org.opencontainers.image.vendor": "Light Code Labs",
"org.opencontainers.image.version": "v2.1.1"
},
"OnBuild": null,
"OpenStdin": false,
"StdinOnce": false,
"Tty": false,
"User": "1100:1100",
"Volumes": {
"/config": {},
"/data": {},
"/etc/caddy/Caddyfile": {},
"/run/nextcloud": {},
"/run/notify_push": {},
"/var/www/html": {}
},
"WorkingDir": "/srv"
},
"Created": "2023-12-18T07:37:31.326447414Z",
"Driver": "overlay2",
"ExecIDs": [
"8e8603737427447890a73bd2928a6b8acc77658a108b3545107253e65ba780b7"
],
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/75b5bc48c8a1f20ce9e890f997e8d9c0078de6a5ba866612fefdae14eaebee8d-init/diff:/var/lib/docker/overlay2/bcb4964be788be4f24e9f2e92f676483f9294a6b9c4449663d6f831c203d74b1/diff:/var/lib/docker/overlay2/4cc80203fe51c0f30a96c7cee0a1aba76b9eb90b48ec046bf977d78b28f03f5c/diff:/var/lib/docker/overlay2/1386c1521d0389c0c572d180c9a1ff9a4e2d750c1d9e2859f74076e94f2d6c6f/diff:/var/lib/docker/overlay2/3202333ec3d80d387e23112eef927e931070bc77849ba9a4f8331a81e3f438be/diff",
"MergedDir": "/var/lib/docker/overlay2/75b5bc48c8a1f20ce9e890f997e8d9c0078de6a5ba866612fefdae14eaebee8d/merged",
"UpperDir": "/var/lib/docker/overlay2/75b5bc48c8a1f20ce9e890f997e8d9c0078de6a5ba866612fefdae14eaebee8d/diff",
"WorkDir": "/var/lib/docker/overlay2/75b5bc48c8a1f20ce9e890f997e8d9c0078de6a5ba866612fefdae14eaebee8d/work"
},
"Name": "overlay2"
},
"HostConfig": {
"AutoRemove": false,
"Binds": [
"/nfs/freenas/caddy/caddy2-config:/config",
"/nfs/freenas/caddy/caddy2-data:/data",
"/nfs/freenas/caddy/Caddyfile2:/etc/caddy/Caddyfile",
"/nfs/freenas/ncfpm:/var/www/html:ro",
"/nfs/freenas/caddy/nextcloud-unix-socket:/run/nextcloud",
"/nfs/freenas/caddy/notify-push-unix-socket:/run/notify_push"
],
"BlkioDeviceReadBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceWriteIOps": null,
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"CapAdd": [
"AUDIT_WRITE",
"CHOWN",
"DAC_OVERRIDE",
"FOWNER",
"FSETID",
"KILL",
"MKNOD",
"NET_BIND_SERVICE",
"NET_RAW",
"SETFCAP",
"SETGID",
"SETPCAP",
"SETUID",
"SYS_CHROOT"
],
"CapDrop": [
"AUDIT_CONTROL",
"BLOCK_SUSPEND",
"DAC_READ_SEARCH",
"IPC_LOCK",
"IPC_OWNER",
"LEASE",
"LINUX_IMMUTABLE",
"MAC_ADMIN",
"MAC_OVERRIDE",
"NET_ADMIN",
"NET_BROADCAST",
"SYSLOG",
"SYS_ADMIN",
"SYS_BOOT",
"SYS_MODULE",
"SYS_NICE",
"SYS_PACCT",
"SYS_PTRACE",
"SYS_RAWIO",
"SYS_RESOURCE",
"SYS_TIME",
"SYS_TTY_CONFIG",
"WAKE_ALARM"
],
"Cgroup": "",
"CgroupParent": "",
"CgroupnsMode": "host",
"ConsoleSize": [
0,
0
],
"ContainerIDFile": "",
"CpuCount": 0,
"CpuPercent": 0,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpuShares": 0,
"CpusetCpus": "",
"CpusetMems": "",
"DeviceCgroupRules": null,
"DeviceRequests": null,
"Devices": [],
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": [],
"GroupAdd": null,
"IOMaximumBandwidth": 0,
"IOMaximumIOps": 0,
"IpcMode": "private",
"Isolation": "",
"Links": null,
"LogConfig": {
"Config": {
"max-file": "3",
"max-size": "10m"
},
"Type": "local"
},
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"Memory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"NanoCpus": 0,
"NetworkMode": "bridge",
"OomKillDisable": null,
"OomScoreAdj": 0,
"PidMode": "",
"PidsLimit": null,
"PortBindings": {
"443/tcp": [
{
"HostIp": "",
"HostPort": "443"
}
],
"443/udp": [
{
"HostIp": "",
"HostPort": "443"
}
],
"80/tcp": [
{
"HostIp": "",
"HostPort": "80"
}
],
"8071/tcp": [
{
"HostIp": "",
"HostPort": "8071"
}
]
},
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
],
"ReadonlyRootfs": false,
"RestartPolicy": {
"MaximumRetryCount": 0,
"Name": "unless-stopped"
},
"Runtime": "runc",
"SecurityOpt": null,
"ShmSize": 67108864,
"UTSMode": "",
"Ulimits": null,
"UsernsMode": "",
"VolumeDriver": "",
"VolumesFrom": null
},
"HostnamePath": "/var/lib/docker/containers/d8c577fc18b1f6a3f23684121b1b280e3b3ab25cef1c0be9af86d8e87a62f4b4/hostname",
"HostsPath": "/var/lib/docker/containers/d8c577fc18b1f6a3f23684121b1b280e3b3ab25cef1c0be9af86d8e87a62f4b4/hosts",
"Id": "d8c577fc18b1f6a3f23684121b1b280e3b3ab25cef1c0be9af86d8e87a62f4b4",
"Image": "sha256:657b947906e764d7ff65a638b958cb7f84b3754e49ede071620658385e743168",
"LogPath": "",
"MountLabel": "",
"Mounts": [
{
"Destination": "/config",
"Mode": "",
"Propagation": "rprivate",
"RW": true,
"Source": "/nfs/freenas/caddy/caddy2-config",
"Type": "bind"
},
{
"Destination": "/data",
"Mode": "",
"Propagation": "rprivate",
"RW": true,
"Source": "/nfs/freenas/caddy/caddy2-data",
"Type": "bind"
},
{
"Destination": "/etc/caddy/Caddyfile",
"Mode": "",
"Propagation": "rprivate",
"RW": true,
"Source": "/nfs/freenas/caddy/Caddyfile2",
"Type": "bind"
},
{
"Destination": "/run/nextcloud",
"Mode": "",
"Propagation": "rprivate",
"RW": true,
"Source": "/nfs/freenas/caddy/nextcloud-unix-socket",
"Type": "bind"
},
{
"Destination": "/run/notify_push",
"Mode": "",
"Propagation": "rprivate",
"RW": true,
"Source": "/nfs/freenas/caddy/notify-push-unix-socket",
"Type": "bind"
},
{
"Destination": "/var/www/html",
"Mode": "ro",
"Propagation": "rprivate",
"RW": false,
"Source": "/nfs/freenas/ncfpm",
"Type": "bind"
}
],
"Name": "/Caddy2",
"NetworkSettings": {
"Bridge": "",
"EndpointID": "4247a740137669dece13846f8513f1d427353d3bb1f350689ef260743417e413",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "fd00::1:242:ac11:4",
"GlobalIPv6PrefixLen": 80,
"HairpinMode": false,
"IPAddress": "172.17.0.4",
"IPPrefixLen": 16,
"IPv6Gateway": "fd00::1:0:0:1",
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:04",
"Networks": {
"bridge": {
"Aliases": null,
"DriverOpts": null,
"EndpointID": "4247a740137669dece13846f8513f1d427353d3bb1f350689ef260743417e413",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "fd00::1:242:ac11:4",
"GlobalIPv6PrefixLen": 80,
"IPAMConfig": {},
"IPAddress": "172.17.0.4",
"IPPrefixLen": 16,
"IPv6Gateway": "fd00::1:0:0:1",
"Links": null,
"MacAddress": "02:42:ac:11:00:04",
"NetworkID": "0d4881f45cf74595942670be4672f8885f8097043b842fb960d98491dc1040df"
}
},
"Ports": {
"2019/tcp": null,
"443/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "443"
},
{
"HostIp": "::",
"HostPort": "443"
}
],
"443/udp": [
{
"HostIp": "0.0.0.0",
"HostPort": "443"
},
{
"HostIp": "::",
"HostPort": "443"
}
],
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "80"
},
{
"HostIp": "::",
"HostPort": "80"
}
],
"8071/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "8071"
},
{
"HostIp": "::",
"HostPort": "8071"
}
]
},
"SandboxID": "ff033d59cd042ab7d9d3ceee0a1504ec3088c80eae4dca3fd135c354595bfe3c",
"SandboxKey": "/var/run/docker/netns/ff033d59cd04",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null
},
"Path": "caddy",
"Platform": "linux",
"Portainer": {
"ResourceControl": {
"Id": 363,
"ResourceId": "d8c577fc18b1f6a3f23684121b1b280e3b3ab25cef1c0be9af86d8e87a62f4b4",
"SubResourceIds": [],
"Type": 1,
"UserAccesses": [],
"TeamAccesses": [],
"Public": false,
"AdministratorsOnly": true,
"System": false
}
},
"ProcessLabel": "",
"ResolvConfPath": "/var/lib/docker/containers/d8c577fc18b1f6a3f23684121b1b280e3b3ab25cef1c0be9af86d8e87a62f4b4/resolv.conf",
"RestartCount": 0,
"State": {
"Dead": false,
"Error": "",
"ExitCode": 0,
"FinishedAt": "2024-01-07T08:06:57.293128243Z",
"OOMKilled": false,
"Paused": false,
"Pid": 1345873,
"Restarting": false,
"Running": true,
"StartedAt": "2024-01-07T08:06:58.154325036Z",
"Status": "running"
}
}
d. My complete Caddy config:
# Global settings
{
log default {
format console {
time_format wall
}
}
debug
}
nc.example.com {
encode zstd gzip
root * /var/www/html
# Rules here are all from .htaccess
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
redir /.well-known/* /index.php{uri} 301 # Nextcloud front-controller handles routes to /.well-known
redir /remote/* /remote.php{uri} 301
# Secure headers, all from .htaccess except Permissions-Policy, STS and X-Powered-By
header {
Strict-Transport-Security max-age=31536000
Permissions-Policy interest-cohort=()
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Referrer-Policy no-referrer
X-XSS-Protection "1; mode=block"
X-Permitted-Cross-Domain-Policies none
X-Robots-Tag "noindex, nofollow"
-X-Powered-By
}
# Uncomment this block if you use the high speed files backend: https://github.com/nextcloud/notify_push
handle_path /push/* {
#reverse_proxy unix//run/notify_push/notify_push.sock
reverse_proxy 192.168.0.81:7867
}
# Uncomment this block if you use onlyoffice: https://github.com/nextcloud/all-in-one/blob/main/Containers/apache/Caddyfile
#handle_path /onlyoffice/* {
# reverse_proxy {$ONLYOFFICE_IP}:{$ONLYOFFICE_PORT} {
# header_up X-Forwarded-Host {host}/onlyoffice
# }
#}
# PicoCMS route
#route /sites* {
# uri strip_prefix /sites
# rewrite * /index.php/apps/cms_pico/pico_proxy/{uri}
# reverse_proxy 192.168.0.81:8080
#}
# PHP block
# As I said before, i'm a fan of Unix sockets, so I use them as much as I can. But you can do :9000 also for TCP.
php_fastcgi unix//run/nextcloud/nextcloud.sock {
# php_fastcgi app:9000 {
root /var/www/html # This is needed because inside the container the root directory is different from the one I put in the "root" directive of this Caddyfile. If you don't change this, php-fpm will not be able to find the files to process.
env front_controller_active true # Enable pretty urls
env modHeadersAvailable true # Avoid sending the security headers twice
trusted_proxies private_ranges
}
# From .htaccess, deny access to sensible files and directories
@forbidden {
path /build/* /tests/* /config/* /lib/* /3rdparty/* /templates/* /data/*
path /.* /autotest* /occ* /issue* /indie* /db_* /console*
not path /.well-known/*
}
error @forbidden 401
# From .htaccess, set cache for versioned static files (cache-busting)
@immutable {
path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite
query v=*
}
header @immutable Cache-Control "max-age=15778463, immutable"
# From .htaccess, set cache for normal static files
@static {
path *.css *.js *.mjs *.svg *.gif *.png *.jpg *.ico *.wasm *.tflite
not query v=*
}
header @static Cache-Control "max-age=15778463"
# From .htaccess, cache fonts for 1 week
@woff2 path *.woff2
header @woff2 Cache-Control "max-age=604800"
file_server
}
# Uncomment this in addition with the import admin_redir statement allow access to the admin interface only from local networks
(admin_redir) {
@admin {
path /admin*
not remote_ip private_ranges
}
redir @admin /
}