- A self-managed VPS or dedicated server with Ubuntu 24.04 running Apache 2.4.xx.
- A registered domain name with working HTTPS (TLS/SSL). HTTP/2 and HTTP/3 only works alongside HTTPS because most browsers, including Firefox and Chrome, don’t support HTTP/2 or HTTP/3 in cleartext (non-TLS) mode.
After multiple tries with apche2 recompiling with a different modules to support quic and http3
, I simply run nginx
container that will overtake only UDP
traffic and forward it to the apache2 as http2 via TCP
. So, no, it is not real "http3 apache2 support", but works pretty well and you do not need to change anything on your Apache2 sever.
User
┌────── http
│┌───── https (http2)
││ - https (http3)──────────────3────────────────────────────────────┐
1│ ┌───────────────────┐ ┌────────────────────────┐ │
││ │ │ │ │ │
│2 │ Apache2 │ │ Docker │ │
││ │ │ │ │ │
└┼─────────────────┼ http - 80 TCP │ │ ┌────────────────────┐ │ │
│ │ │ │ │ │ │ │
└─────────────────┼ https - 443 TCP──┼─4┐ │ │ nginx │ │ │
│ │ │ │ │ │ │ │
├───────────────────┘ └─┼─┼───https - 443 UDP ─┼─┼──┘
│ ┌───────5───────┼─┼ │ │
│ │ │ └────────────────────┘ │
│ │ └────────────────────────┘
│ │
└─6──────┴─/etc/letsencrypt/live/FQDN
I tries to paint how it works.
We do have our Apache2 server that runs on ports 80 and 443 for TCP
traffic. Now we will create simple nginx
configuration to enable http3 support via UDP
and forward it to our apache2 in a http2 form.
- User called our service via
http
and get an aswer to redirect traffic to the https - port443
. - User called our apache2 via
https
now it is stillTCP
, but port443
and get response header that we do support http3 on port443
UDP
. - User called our service via
https
on port443
viaUDP
and goes to the nginx with http3 support. - Nginx will forward all traffic to fixed apache2 address as http2
- To ensure transparent encryption nginx has read only access to the Server Certificate
- As apache2 has this access too
Check this out https://gist.github.com/GAS85/38eb5954a27d64ae9ac17d01bfe9898c
Additionally it is recommended to add header that will tell browsers that we can support http3. Add to your virtual host:
Header always set alt-svc 'h3=":443"; ma=86400'
Please enable incomming UDP
traffic on port 443. Depends on your system it could be done via different commands, for iptables
it is:
iptables -I INPUT -p udp --dport 443 -j ACCEPT
I will use official nginx
image with docker-compose, my compose file looks following:
version: "3.7"
services:
quic:
container_name: quic
image: nginx:alpine
restart: unless-stopped
ports:
# Open 443 UDP port to listen http3 traffic
- 443:443/udp
volumes:
# Configuration
- /var/docker/quic/conf.d:/etc/nginx/conf.d
# Logs
- /var/docker/quic/logs:/var/log/nginx/
# Access to Certificated
- /etc/letsencrypt:/etc/letsencrypt:ro
healthcheck:
test: ls -l /proc/*/exe | grep nginx
interval: 5m00s
timeout: 10s
retries: 2
start_period: 30s
deploy:
resources:
limits:
cpus: '0.20'
memory: 100M
Save it e.g. under your home directory as quic-compose.yml
and run:
docker compose -f ~/quic-compose.yaml up -d
After we run our compose file docker will create 2 folders:
/var/docker/quic/conf.d
/var/docker/quic/logs
We need to create config iside conf.d
folder. E.g. sudo
needed because nginx container runned as privilidget user inside:
sudo nano /var/docker/quic/conf.d/defalut.conf
Then add following config into it:
server {
# for better compatibility it's recommended
# to use the same port for quic and https
listen 443 quic reuseport;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/sitnikov.eu/cert.pem;
ssl_certificate_key /etc/letsencrypt/live/sitnikov.eu/privkey.pem;
location / {
# required for browsers to direct them to quic port
add_header Alt-Svc 'h3=":443"; ma=86400';
proxy_pass https://<APACHE2 IP>:443;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
After save you can apply config by telling nginx to reload himself (docker exec quic nginx -s reload
), or via docker restart quic
.
Visit your site and check if http3 enabled via console.