We’ve recently added LL-HLS to stream and one of the soft requirements for the feature is the use of an HTTP/2 or HTTP/3 reverse proxy. There are many different reverse proxies that you can use (although Apache is not recommended). NGINX is one reverse proxy that works well with aiohttp (the web server used by HA). I’ve been using a docker image built from the nginx-quic branch of NGINX and it has been working quite well for me, so I’m sharing my config here. There are other posts on creating SSL/TLS certificates and setting up NGINX with HA, so please reference those threads if you have any questions on those topics. Feel free to comment or edit this post if you have any suggestions or improvements.
Building the docker image:
Use the Dockerfile at the bottom of Our Roadmap for QUIC and HTTP/3 Support in NGINX - NGINX , but remove the argument --with-http_quic_module
as the http_quic_module has been merged into the http_v3_module.
Also remove the lines:
</s> <s>COPY nginx.conf /etc/nginx/nginx.conf</s> <s>COPY www.example.com.crt /etc/ssl/www.example.com.crt</s> <s>COPY www.example.com.key /etc/ssl/www.example.com.key</s> <s>COPY index.html /etc/nginx/html/index.html</s> <s>
There is a template Dockerfile at the bottom of Our Roadmap for QUIC and HTTP/3 Support in NGINX - NGINX , but this Dockerfile uses BoringSSL which does not support OCSP stapling. There is a fork of OpenSSL at GitHub - quictls/openssl: TLS/SSL and crypto library with QUIC APIs which supports QUIC and also supports OCSP stapling (this will slightly speed up client requests, and it is also a requirement for using TLSv1.3 with iOS clients). To build a docker image for nginx-quic using this branch, use the following Dockerfile:
FROM nginx AS build
WORKDIR /src
RUN apt-get update && \
apt-get install -y git gcc make g++ cmake perl libunwind-dev golang && \
git clone https://github.com/quictls/openssl.git && \
mkdir openssl/build && \
cd openssl/build && \
cd .. && \
./Configure && \
make
RUN apt-get install -y mercurial libperl-dev libpcre3-dev zlib1g-dev libxslt1-dev libgd-ocaml-dev libgeoip-dev && \
hg clone https://hg.nginx.org/nginx-quic && \
hg clone http://hg.nginx.org/njs -r "0.6.2" && \
cd nginx-quic && \
hg update quic && \
auto/configure `nginx -V 2>&1 | sed "s/ \-\-/ \\\ \n\t--/g" | grep "\-\-" | grep -ve opt= -e param= -e build=` \
--build=nginx-quic --with-debug \
--with-http_v3_module --with-stream_quic_module \
--with-openssl="/src/openssl" && \
make
FROM nginx
COPY --from=build /src/nginx-quic/objs/nginx /usr/sbin
RUN /usr/sbin/nginx -V > /dev/stderr
# The following line is the port that nginx will run on.
EXPOSE 443
Place this Dockerfile in a directory named nginx-quic
.
To build the container image, run docker build nginx-quic
(sudo permissions may be required). After it’s done, you should get the message “Successfully built <image id>”.
Creating the container:
The docker image is now built, and you can use it like you would the regular nginx docker image. You can create a container from the image using the following docker-compose.yaml
:
version: "3.9"
services:
nginx:
container_name: nginx
image: <image id>
volumes:
- <path to directory outside container>/ssl:/ssl
- <path to directory outside container>/conf.d:/etc/nginx/conf.d
network_mode: host
Above, <path to directory outside container> is a folder somewhere for this container, and beneath this folder are two subfolders named ssl
and conf.d
. The ssl
directory will contain your key, certificates, and dh parameters, while conf.d
will contain your nginx.conf
file.
Creating the nginx.conf file:
The following is my nginx.conf
:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream homeassistant {
server 127.0.0.1:8123;
keepalive 32;
}
server {
listen [::]:443 http3 reuseport ipv6only=off;
listen [::]:443 ssl http2 ipv6only=off;
server_name <your host name>;
ssl_certificate /ssl/fullchain.pem;
ssl_certificate_key /ssl/privkey.pem;
ssl_dhparam /ssl/dhparams.pem;
# Similar to the modern configuration from https://ssl-config.mozilla.org/
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:1m; # 1m should be more than enough
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
# Using proxy buffers may free up HA sooner on slower connections.
# Make sure that you don't see any "an upstream response is buffered to a temporary file" messages in your logs
# If you do, increase the buffer size
proxy_buffers 1024 4k;
proxy_connect_timeout 60;
proxy_read_timeout 60;
proxy_send_timeout 60;
proxy_intercept_errors off;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
location / {
add_header Alt-Svc 'h3=":443"; ma=86400';
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
proxy_pass http://homeassistant;
}
location /api/websocket {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://homeassistant/api/websocket;
}
# replace with the IP address of your resolver
resolver 9.9.9.9;
}
Port forwarding:
Since QUIC uses UDP, you’ll have to remember to configure your router to forward UDP in addition to TCP on your listening port (port 443 in the nginx.conf above).
Hopefully some of you can give this a try and see if you notice any speedup in Lovelace. If you use stream
you can try pairing this setup with LL-HLS.