From 3c5de77ae9994820c463f74f2344c6bd32713831 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 18 Jan 2023 19:54:27 +0100 Subject: [PATCH] Refactor NGINX configuration of Home Assistant Add-on (#4312) --- .../etc/nginx/includes/proxy_params.conf | 12 ++-- .../etc/nginx/includes/server_params.conf | 6 +- .../etc/nginx/includes/ssl_params.conf | 7 +- .../etc/nginx/includes/upstream.conf | 3 + docker/ha-addon-rootfs/etc/nginx/nginx.conf | 25 +++---- .../etc/nginx/servers/.gitkeep | 1 + .../etc/nginx/servers/direct.disabled | 12 ---- .../direct.gtpl} | 20 ++++-- .../ingress.conf => templates/ingress.gtpl} | 4 +- .../etc/s6-overlay/s6-rc.d/init-nginx/run | 70 +++++-------------- 10 files changed, 60 insertions(+), 100 deletions(-) create mode 100644 docker/ha-addon-rootfs/etc/nginx/includes/upstream.conf create mode 100644 docker/ha-addon-rootfs/etc/nginx/servers/.gitkeep delete mode 100644 docker/ha-addon-rootfs/etc/nginx/servers/direct.disabled rename docker/ha-addon-rootfs/etc/nginx/{servers/direct-ssl.disabled => templates/direct.gtpl} (61%) rename docker/ha-addon-rootfs/etc/nginx/{servers/ingress.conf => templates/ingress.gtpl} (76%) diff --git a/docker/ha-addon-rootfs/etc/nginx/includes/proxy_params.conf b/docker/ha-addon-rootfs/etc/nginx/includes/proxy_params.conf index c00b4800e8..a1ebb5079a 100644 --- a/docker/ha-addon-rootfs/etc/nginx/includes/proxy_params.conf +++ b/docker/ha-addon-rootfs/etc/nginx/includes/proxy_params.conf @@ -1,9 +1,9 @@ -proxy_http_version 1.1; -proxy_ignore_client_abort off; -proxy_read_timeout 86400s; -proxy_redirect off; -proxy_send_timeout 86400s; -proxy_max_temp_file_size 0; +proxy_http_version 1.1; +proxy_ignore_client_abort off; +proxy_read_timeout 86400s; +proxy_redirect off; +proxy_send_timeout 86400s; +proxy_max_temp_file_size 0; proxy_set_header Accept-Encoding ""; proxy_set_header Connection $connection_upgrade; diff --git a/docker/ha-addon-rootfs/etc/nginx/includes/server_params.conf b/docker/ha-addon-rootfs/etc/nginx/includes/server_params.conf index 479dfa10f6..debdf83a8c 100644 --- a/docker/ha-addon-rootfs/etc/nginx/includes/server_params.conf +++ b/docker/ha-addon-rootfs/etc/nginx/includes/server_params.conf @@ -1,5 +1,7 @@ -root /dev/null; -server_name $hostname; +root /dev/null; +server_name $hostname; + +client_max_body_size 512m; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; diff --git a/docker/ha-addon-rootfs/etc/nginx/includes/ssl_params.conf b/docker/ha-addon-rootfs/etc/nginx/includes/ssl_params.conf index 6f15005998..e6789cbb9b 100644 --- a/docker/ha-addon-rootfs/etc/nginx/includes/ssl_params.conf +++ b/docker/ha-addon-rootfs/etc/nginx/includes/ssl_params.conf @@ -1,7 +1,6 @@ -ssl_protocols TLSv1.2; -ssl_prefer_server_ciphers on; -ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA; -ssl_ecdh_curve secp384r1; +ssl_protocols TLSv1.2 TLSv1.3; +ssl_prefer_server_ciphers off; +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; diff --git a/docker/ha-addon-rootfs/etc/nginx/includes/upstream.conf b/docker/ha-addon-rootfs/etc/nginx/includes/upstream.conf new file mode 100644 index 0000000000..8e782bdc88 --- /dev/null +++ b/docker/ha-addon-rootfs/etc/nginx/includes/upstream.conf @@ -0,0 +1,3 @@ +upstream esphome { + server unix:/var/run/esphome.sock; +} diff --git a/docker/ha-addon-rootfs/etc/nginx/nginx.conf b/docker/ha-addon-rootfs/etc/nginx/nginx.conf index 8ebf572816..497427596d 100644 --- a/docker/ha-addon-rootfs/etc/nginx/nginx.conf +++ b/docker/ha-addon-rootfs/etc/nginx/nginx.conf @@ -2,7 +2,6 @@ daemon off; user root; pid /var/run/nginx.pid; worker_processes 1; -# Hass.io addon log error_log /proc/1/fd/1 error; events { worker_connections 1024; @@ -10,24 +9,22 @@ events { http { include /etc/nginx/includes/mime.types; - access_log stdout; - default_type application/octet-stream; - gzip on; - keepalive_timeout 65; - sendfile on; - server_tokens off; + + access_log off; + default_type application/octet-stream; + gzip on; + keepalive_timeout 65; + sendfile on; + server_tokens off; + + tcp_nodelay on; + tcp_nopush on; map $http_upgrade $connection_upgrade { default upgrade; '' close; } - # Use Hass.io supervisor as resolver - resolver 172.30.32.2; - - upstream esphome { - server unix:/var/run/esphome.sock; - } - + include /etc/nginx/includes/upstream.conf; include /etc/nginx/servers/*.conf; } diff --git a/docker/ha-addon-rootfs/etc/nginx/servers/.gitkeep b/docker/ha-addon-rootfs/etc/nginx/servers/.gitkeep new file mode 100644 index 0000000000..85ad51be5f --- /dev/null +++ b/docker/ha-addon-rootfs/etc/nginx/servers/.gitkeep @@ -0,0 +1 @@ +Without requirements or design, programming is the art of adding bugs to an empty text file. (Louis Srygley) diff --git a/docker/ha-addon-rootfs/etc/nginx/servers/direct.disabled b/docker/ha-addon-rootfs/etc/nginx/servers/direct.disabled deleted file mode 100644 index 80300fc6aa..0000000000 --- a/docker/ha-addon-rootfs/etc/nginx/servers/direct.disabled +++ /dev/null @@ -1,12 +0,0 @@ -server { - listen %%port%% default_server; - - include /etc/nginx/includes/server_params.conf; - include /etc/nginx/includes/proxy_params.conf; - # Clear Hass.io Ingress header - proxy_set_header X-HA-Ingress ""; - - location / { - proxy_pass http://esphome; - } -} diff --git a/docker/ha-addon-rootfs/etc/nginx/servers/direct-ssl.disabled b/docker/ha-addon-rootfs/etc/nginx/templates/direct.gtpl similarity index 61% rename from docker/ha-addon-rootfs/etc/nginx/servers/direct-ssl.disabled rename to docker/ha-addon-rootfs/etc/nginx/templates/direct.gtpl index 4ebc435dbb..4fb0ca3f90 100644 --- a/docker/ha-addon-rootfs/etc/nginx/servers/direct-ssl.disabled +++ b/docker/ha-addon-rootfs/etc/nginx/templates/direct.gtpl @@ -1,20 +1,26 @@ server { - listen %%port%% default_server ssl http2; + {{ if not .ssl }} + listen 6052 default_server; + {{ else }} + listen 6052 default_server ssl http2; + {{ end }} include /etc/nginx/includes/server_params.conf; include /etc/nginx/includes/proxy_params.conf; + + {{ if .ssl }} include /etc/nginx/includes/ssl_params.conf; - ssl on; - ssl_certificate /ssl/%%certfile%%; - ssl_certificate_key /ssl/%%keyfile%%; - - # Clear Hass.io Ingress header - proxy_set_header X-HA-Ingress ""; + ssl_certificate /ssl/{{ .certfile }}; + ssl_certificate_key /ssl/{{ .keyfile }}; # Redirect http requests to https on the same port. # https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/ error_page 497 https://$http_host$request_uri; + {{ end }} + + # Clear Home Assistant Ingress header + proxy_set_header X-HA-Ingress ""; location / { proxy_pass http://esphome; diff --git a/docker/ha-addon-rootfs/etc/nginx/servers/ingress.conf b/docker/ha-addon-rootfs/etc/nginx/templates/ingress.gtpl similarity index 76% rename from docker/ha-addon-rootfs/etc/nginx/servers/ingress.conf rename to docker/ha-addon-rootfs/etc/nginx/templates/ingress.gtpl index 9d0d2d3e66..91bd40d537 100644 --- a/docker/ha-addon-rootfs/etc/nginx/servers/ingress.conf +++ b/docker/ha-addon-rootfs/etc/nginx/templates/ingress.gtpl @@ -1,13 +1,13 @@ server { - listen %%interface%%:%%port%% default_server; + listen {{ .interface }}:{{ .port }} default_server; include /etc/nginx/includes/server_params.conf; include /etc/nginx/includes/proxy_params.conf; + # Set Home Assistant Ingress header proxy_set_header X-HA-Ingress "YES"; location / { - # Only allow from Hass.io supervisor allow 172.30.32.2; deny all; diff --git a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run index 52a211b99f..2725f56670 100755 --- a/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run +++ b/docker/ha-addon-rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run @@ -4,60 +4,24 @@ # Community Hass.io Add-ons: ESPHome # Configures NGINX for use with ESPHome # ============================================================================== -declare certfile -declare direct_port -declare ingress_interface -declare ingress_port -declare keyfile - mkdir -p /var/log/nginx -direct_port=$(bashio::addon.port 6052) -if bashio::var.has_value "${direct_port}"; then - # Check SSL requirements, if enabled - if bashio::config.true 'ssl'; then - if ! bashio::config.has_value 'certfile'; then - bashio::log.fatal 'SSL is enabled, but no certfile was specified.' - bashio::exit.nok - fi +# Generate Ingress configuration +bashio::var.json \ + interface "$(bashio::addon.ip_address)" \ + port "^$(bashio::addon.ingress_port)" \ + | tempio \ + -template /etc/nginx/templates/ingress.gtpl \ + -out /etc/nginx/servers/ingress.conf - if ! bashio::config.has_value 'keyfile'; then - bashio::log.fatal 'SSL is enabled, but no keyfile was specified' - bashio::exit.nok - fi - - certfile="/ssl/$(bashio::config 'certfile')" - keyfile="/ssl/$(bashio::config 'keyfile')" - - if ! bashio::fs.file_exists "/ssl/${certfile}"; then - if ! bashio::fs.file_exists "/ssl/${keyfile}"; then - # Both files are missing, let's print a friendlier error message - bashio::log.fatal 'You enabled encrypted connections using the "ssl": true option.' - bashio::log.fatal "However, the SSL files '${certfile}' and '${keyfile}'" - bashio::log.fatal "were not found. If you're using Hass.io on your local network and don't want" - bashio::log.fatal 'to encrypt connections to the ESPHome dashboard, you can manually disable' - bashio::log.fatal 'SSL by setting "ssl" to false."' - bashio::exit.nok - fi - bashio::log.fatal "The configured certfile '/ssl/${certfile}' was not found." - bashio::exit.nok - fi - - if ! bashio::fs.file_exists "/ssl/${keyfile}"; then - bashio::log.fatal "The configured keyfile '/ssl/${keyfile}' was not found." - bashio::exit.nok - fi - mv /etc/nginx/servers/direct-ssl.disabled /etc/nginx/servers/direct.conf - sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/servers/direct.conf - sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/servers/direct.conf - else - mv /etc/nginx/servers/direct.disabled /etc/nginx/servers/direct.conf - fi - - sed -i "s/%%port%%/${direct_port}/g" /etc/nginx/servers/direct.conf +# Generate direct access configuration, if enabled. +if bashio::var.has_value "$(bashio::addon.port 6052)"; then + bashio::config.require.ssl + bashio::var.json \ + certfile "$(bashio::config 'certfile')" \ + keyfile "$(bashio::config 'keyfile')" \ + ssl "^$(bashio::config 'ssl')" \ + | tempio \ + -template /etc/nginx/templates/direct.gtpl \ + -out /etc/nginx/servers/direct.conf fi - -ingress_port=$(bashio::addon.ingress_port) -ingress_interface=$(bashio::addon.ip_address) -sed -i "s/%%port%%/${ingress_port}/g" /etc/nginx/servers/ingress.conf -sed -i "s/%%interface%%/${ingress_interface}/g" /etc/nginx/servers/ingress.conf