diff --git a/esphome_proxy/CHANGELOG.md b/esphome_proxy/CHANGELOG.md new file mode 100644 index 0000000..05bc96b --- /dev/null +++ b/esphome_proxy/CHANGELOG.md @@ -0,0 +1,3 @@ +### 0.1 + +- Initial release diff --git a/esphome_proxy/DOCS.md b/esphome_proxy/DOCS.md new file mode 100644 index 0000000..8e501f5 --- /dev/null +++ b/esphome_proxy/DOCS.md @@ -0,0 +1,38 @@ +This addon creates a proxy to a ESPHome server run separately from Home Assistant so that you can have the benefit of access in the sidebar without running ESPHome as an addon. + +Note that this addon does not run ESPHome itself. + +## Configuration + +### Option: `server` + +The `server` option sets the address of the ESPHome server. + +This must be in the format `http[s]://host:port`. The following are valid examples: + +- `http://ESPHome.local:6052` +- `http://192.168.0.101:6052` +- `https://192.168.0.101:443` + +### Option: `proxy_pass_host` + +Determines whether we should pass the host we're running on (for example, +`homeassistant.local`) to the server we're proxying to. In general, you probably +want this to be set to `true`. + +Set to `false` if the server needs to receive the host of the ESPHome instance +(not the host Home Assistant or this addon are running on). This might be the case +if your ESPHome instance is behind an SSL proxy (like Traefik or Caddy), which +needs to receive the ESPHome host in order to route the request correctly. + +### Option: `proxy_pass_real_ip` + +Determines whether we should pass the client's real IP address to the server we're proxying to. In general, you probably +want this to be set to `true`. + +Set to `false` if you need to know the request is coming from the HA IP. This might be the case if your ESPHome instance is behind a proxy which only allows specific IPs to connect. + +## Required Dependencies + +- Network access to running ESPHome server + diff --git a/esphome_proxy/Dockerfile b/esphome_proxy/Dockerfile new file mode 100644 index 0000000..2829fb1 --- /dev/null +++ b/esphome_proxy/Dockerfile @@ -0,0 +1,38 @@ +FROM ghcr.io/hassio-addons/debian-base:7.8.2 + +# Setup base +# hadolint ignore=DL3003 +RUN apt-get -qq update \ + && apt-get install -qq --no-install-recommends nginx \ + && rm -rf /var/lib/apt/lists/* + +# Copy root filesystem +COPY rootfs / + +# Build arguments +ARG BUILD_ARCH +ARG BUILD_DATE +ARG BUILD_DESCRIPTION +ARG BUILD_NAME +ARG BUILD_REF +ARG BUILD_REPOSITORY +ARG BUILD_VERSION + +# Labels +LABEL \ + io.hass.name="${BUILD_NAME}" \ + io.hass.description="${BUILD_DESCRIPTION}" \ + io.hass.arch="${BUILD_ARCH}" \ + io.hass.type="addon" \ + io.hass.version=${BUILD_VERSION} \ + maintainer="Blake Blackshear " \ + org.opencontainers.image.title="${BUILD_NAME}" \ + org.opencontainers.image.description="${BUILD_DESCRIPTION}" \ + org.opencontainers.image.vendor="Buchhorster Add-ons" \ + org.opencontainers.image.authors="PAtrick Gniza " \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \ + org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/frigate_proxy/README.md" \ + org.opencontainers.image.created=${BUILD_DATE} \ + org.opencontainers.image.revision=${BUILD_REF} \ + org.opencontainers.image.version=${BUILD_VERSION} diff --git a/esphome_proxy/README.md b/esphome_proxy/README.md new file mode 100644 index 0000000..253d2cd --- /dev/null +++ b/esphome_proxy/README.md @@ -0,0 +1,13 @@ +# Home Assistant Add-on: ESPHome Proxy + +![Supports aarch64 Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] ![Supports i386 Architecture][i386-shield] + +This addon creates a proxy to a ESPHome server run separately from Home Assistant so that you can have the benefit of access in the sidebar without running ESPHome as an addon. + +Note that this addon does not run ESPHome itself. + +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg +[i386-shield]: https://img.shields.io/badge/i386-yes-green.svg diff --git a/esphome_proxy/config.yaml b/esphome_proxy/config.yaml new file mode 100644 index 0000000..0efaf0e --- /dev/null +++ b/esphome_proxy/config.yaml @@ -0,0 +1,42 @@ +name: ESPHome Proxy +version: 0.1 +panel_icon: "mdi:cctv" +panel_title: ESPHome +slug: esphome-proxy +description: Proxy addon for ESPHome +url: "https://gitea.buchhorster.de/patrick/ha-Buchhorster-Addons" +startup: application +boot: auto +init: false +webui: "http://[HOST]:[PORT:6052]/" +watchdog: "http://[HOST]:[PORT:6252]/" +ingress: true +ingress_port: 6052 +ingress_entry: / +panel_admin: false +ports: + 6052/tcp: 6052 +ports_description: + 6052/tcp: Web interface (not required for Home Assistant Ingress) +host_network: false +devices: [] +usb: false +tmpfs: false +full_access: false +environment: {} +options: + server: "http://esphome.local:6052" + proxy_pass_host: true + proxy_pass_real_ip: true +schema: + server: "match(^https?://.+:\\d+$)" + proxy_pass_host: bool + proxy_pass_real_ip: bool +services: [] +arch: + - aarch64 + - amd64 + - armhf + - armv7 + - i386 +map: [] diff --git a/esphome_proxy/icon.png b/esphome_proxy/icon.png new file mode 100644 index 0000000..dcdeed9 Binary files /dev/null and b/esphome_proxy/icon.png differ diff --git a/esphome_proxy/logo.png b/esphome_proxy/logo.png new file mode 100644 index 0000000..eb2808c Binary files /dev/null and b/esphome_proxy/logo.png differ diff --git a/esphome_proxy/rootfs/etc/nginx/includes/mime.types b/esphome_proxy/rootfs/etc/nginx/includes/mime.types new file mode 100644 index 0000000..7c7cdef --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/includes/mime.types @@ -0,0 +1,96 @@ +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + font/woff woff; + font/woff2 woff2; + + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/esphome_proxy/rootfs/etc/nginx/includes/proxy_params.conf b/esphome_proxy/rootfs/etc/nginx/includes/proxy_params.conf new file mode 100644 index 0000000..518c6ec --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/includes/proxy_params.conf @@ -0,0 +1,15 @@ +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; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-NginX-Proxy true; + +proxy_ssl_server_name on; +proxy_ssl_session_reuse off; diff --git a/esphome_proxy/rootfs/etc/nginx/includes/server_params.conf b/esphome_proxy/rootfs/etc/nginx/includes/server_params.conf new file mode 100644 index 0000000..09c0654 --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/includes/server_params.conf @@ -0,0 +1,6 @@ +root /dev/null; +server_name $hostname; + +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; +add_header X-Robots-Tag none; diff --git a/esphome_proxy/rootfs/etc/nginx/includes/ssl_params.conf b/esphome_proxy/rootfs/etc/nginx/includes/ssl_params.conf new file mode 100644 index 0000000..e6789cb --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/includes/ssl_params.conf @@ -0,0 +1,8 @@ +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; +ssl_stapling on; +ssl_stapling_verify on; diff --git a/esphome_proxy/rootfs/etc/nginx/nginx.conf b/esphome_proxy/rootfs/etc/nginx/nginx.conf new file mode 100644 index 0000000..3fae5ac --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/nginx.conf @@ -0,0 +1,43 @@ +# Run nginx in foreground. +daemon off; + +# This is run inside Docker. +user root; + +# Pid storage location. +pid /var/run/nginx.pid; + +# Set number of worker processes. +worker_processes 1; + +# Enables the use of JIT for regular expressions to speed-up their processing. +pcre_jit on; + +# Write error log to the add-on log. +error_log /proc/1/fd/1 error; + +# Max num of simultaneous connections by a worker process. +events { + worker_connections 512; +} + +http { + include /etc/nginx/includes/mime.types; + + access_log off; + client_max_body_size 4G; + 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; + } + + include /etc/nginx/servers/*.conf; +} diff --git a/esphome_proxy/rootfs/etc/nginx/servers/.gitkeep b/esphome_proxy/rootfs/etc/nginx/servers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/esphome_proxy/rootfs/etc/nginx/templates/ingress.gtpl b/esphome_proxy/rootfs/etc/nginx/templates/ingress.gtpl new file mode 100644 index 0000000..92773cb --- /dev/null +++ b/esphome_proxy/rootfs/etc/nginx/templates/ingress.gtpl @@ -0,0 +1,23 @@ +server { + listen 6052 default_server; + + include /etc/nginx/includes/server_params.conf; + + location / { + allow 172.30.32.2; + deny all; + + proxy_pass {{ .server }}; + proxy_set_header X-Ingress-Path {{ .entry }}; + + {{ if .proxy_pass_host }} + proxy_set_header Host $http_host; + {{ end }} + {{ if .proxy_pass_real_ip }} + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + {{ end }} + + include /etc/nginx/includes/proxy_params.conf; + } +} diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/dependencies.d/base b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/dependencies.d/base new file mode 100644 index 0000000..e69de29 diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run new file mode 100755 index 0000000..bfc549e --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run @@ -0,0 +1,15 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Configures NGINX for use with this add-on. +# ============================================================================== + +# Note the ^ at the beginning of the proxy_pass_host value +# This stops bashio:var.json from passing the value as a string +bashio::var.json \ + entry "$(bashio::addon.ingress_entry)" \ + server "$(bashio::config 'server')" \ + proxy_pass_host "^$(bashio::config 'proxy_pass_host')" \ + | tempio \ + -template /etc/nginx/templates/ingress.gtpl \ + -out /etc/nginx/servers/ingress.conf diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/type b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/type new file mode 100644 index 0000000..bdd22a1 --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/type @@ -0,0 +1 @@ +oneshot diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/up b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/up new file mode 100755 index 0000000..b3b5b49 --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/up @@ -0,0 +1 @@ +/etc/s6-overlay/s6-rc.d/init-nginx/run diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/dependencies.d/init-nginx b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/dependencies.d/init-nginx new file mode 100644 index 0000000..e69de29 diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish new file mode 100755 index 0000000..1b0f0bc --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/finish @@ -0,0 +1,28 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Take down the S6 supervision tree when the NGINX fails +# ============================================================================== +readonly exit_code_service="${1}" +readonly exit_code_signal="${2}" +exit_code_container=$(cat /run/s6-linux-init-container-results/exitcode) +readonly exit_code_container +readonly service="nginx" + +bashio::log.info \ + "Service ${service} exited with code ${exit_code_service}" \ + "(by signal ${exit_code_signal})" + +if [[ "${exit_code_service}" -eq 256 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo $((128 + exit_code_signal)) > /run/s6-linux-init-container-results/exitcode + fi + if [[ "${exit_code_signal}" -eq 15 ]]; then + exec /run/s6/basedir/bin/halt + fi +elif [[ "${exit_code_service}" -ne 0 ]]; then + if [[ "${exit_code_container}" -eq 0 ]]; then + echo "${exit_code_service}" > /run/s6-linux-init-container-results/exitcode + fi + exec /run/s6/basedir/bin/halt +fi diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run new file mode 100755 index 0000000..3acc0b2 --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/run @@ -0,0 +1,8 @@ +#!/command/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== +# Runs the NGINX daemon +# ============================================================================== + +bashio::log.info "Starting NGINX..." +exec nginx diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type new file mode 100644 index 0000000..5883cff --- /dev/null +++ b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/nginx/type @@ -0,0 +1 @@ +longrun diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-nginx b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/init-nginx new file mode 100644 index 0000000..e69de29 diff --git a/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx b/esphome_proxy/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/nginx new file mode 100644 index 0000000..e69de29