From 4d1aa81c3abdaf0f76d9b53b1a2b0f9e2d03b0e6 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Thu, 10 Mar 2022 17:58:57 +0100 Subject: [PATCH] add scrutiny full access --- scrutiny/config.json | 1 - scrutiny_fa/CHANGELOG.md | 32 +++++ scrutiny_fa/Dockerfile | 105 ++++++++++++++++ scrutiny_fa/README.md | 112 ++++++++++++++++++ scrutiny_fa/apparmor.txt | 68 +++++++++++ scrutiny_fa/build.json | 7 ++ scrutiny_fa/config.json | 46 +++++++ scrutiny_fa/icon.png | Bin 0 -> 23635 bytes scrutiny_fa/logo.png | Bin 0 -> 23635 bytes .../cont-init.d/00-aaa_dockerfile_backup.sh | 33 ++++++ scrutiny_fa/rootfs/etc/cont-init.d/31-run.sh | 50 ++++++++ .../rootfs/etc/cont-init.d/32-nginx.sh | 33 ++++++ .../rootfs/etc/nginx/includes/mime.types | 96 +++++++++++++++ .../etc/nginx/includes/proxy_params.conf | 15 +++ .../rootfs/etc/nginx/includes/resolver.conf | 1 + .../etc/nginx/includes/server_params.conf | 6 + .../rootfs/etc/nginx/includes/ssl_params.conf | 9 ++ .../rootfs/etc/nginx/includes/upstream.conf | 3 + scrutiny_fa/rootfs/etc/nginx/nginx.conf | 56 +++++++++ .../rootfs/etc/nginx/servers/ingress.conf | 21 ++++ .../rootfs/etc/services.d/nginx/finish | 8 ++ scrutiny_fa/rootfs/etc/services.d/nginx/run | 10 ++ scrutiny_fa/rootfs/run.sh | 13 ++ 23 files changed, 724 insertions(+), 1 deletion(-) create mode 100644 scrutiny_fa/CHANGELOG.md create mode 100644 scrutiny_fa/Dockerfile create mode 100644 scrutiny_fa/README.md create mode 100644 scrutiny_fa/apparmor.txt create mode 100644 scrutiny_fa/build.json create mode 100644 scrutiny_fa/config.json create mode 100644 scrutiny_fa/icon.png create mode 100644 scrutiny_fa/logo.png create mode 100644 scrutiny_fa/rootfs/etc/cont-init.d/00-aaa_dockerfile_backup.sh create mode 100644 scrutiny_fa/rootfs/etc/cont-init.d/31-run.sh create mode 100644 scrutiny_fa/rootfs/etc/cont-init.d/32-nginx.sh create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/mime.types create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/proxy_params.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/resolver.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/server_params.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/ssl_params.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/includes/upstream.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/nginx.conf create mode 100644 scrutiny_fa/rootfs/etc/nginx/servers/ingress.conf create mode 100644 scrutiny_fa/rootfs/etc/services.d/nginx/finish create mode 100644 scrutiny_fa/rootfs/etc/services.d/nginx/run create mode 100644 scrutiny_fa/rootfs/run.sh diff --git a/scrutiny/config.json b/scrutiny/config.json index cdbdd6bd2..3760838c7 100644 --- a/scrutiny/config.json +++ b/scrutiny/config.json @@ -16,7 +16,6 @@ "ports_description": { "8080/tcp": "Web UI port" }, - "full_access": true, "devices": [ "/dev/sda", "/dev/sdb", diff --git a/scrutiny_fa/CHANGELOG.md b/scrutiny_fa/CHANGELOG.md new file mode 100644 index 000000000..b0d577a34 --- /dev/null +++ b/scrutiny_fa/CHANGELOG.md @@ -0,0 +1,32 @@ +- Added full access. Use only if you can't connect without +- New standardized logic for Dockerfile build and packages installation +- Added : "/dev/nvme0" + +## 0.3.13 (26-10-2021) + +- Update to latest version from analogj/scrutiny +- Allow mounting of devices up to sdg2 + +## 0.3.12 (29-09-2021) + +- Update to latest version from AnalogJ/scrutiny +- Aligned with AnalogJ namings + +## fd4f0429 + +- New ingress icon, thanks to @ElVit +- New features, selecting of update rate with addon option +- Add banner in log +- Align to upstream + +## 27b923b5-ls12 + +- Removed full access flag +- Improved code for local devices scanning after first installation +- Solved an issue that made a blank screen on mobile devices +- Implementation of Ingress with/without ssl + +## 27b923b5-ls11 + +- Enables PUID/GUID options +- Daily update of values diff --git a/scrutiny_fa/Dockerfile b/scrutiny_fa/Dockerfile new file mode 100644 index 000000000..f75d3d84f --- /dev/null +++ b/scrutiny_fa/Dockerfile @@ -0,0 +1,105 @@ +#============================# +# ALEXBELGIUM'S DOCKERFILE # +#============================# +# _.------. +# _.-` ('>.-`"""-. +# '.--'` _'` _ .--.) +# -' '-.-';` ` +# ' - _.' ``'--. +# '---` .-'""` +# /` +#=== Home Assistant Addon ===# + +################# +# 1 Build Image # +################# + +ARG BUILD_FROM +ARG BUILD_VERSION +FROM ${BUILD_FROM} + +################## +# 2 Modify Image # +################## + +# hadolint ignore=DL4006 +RUN \ + # Allow UID and GID setting + sed -i 's/bash/bashio/g' /etc/cont-init.d/10-adduser \ + && sed -i 's/{PUID:-911}/(bashio::config "PUID")/g' /etc/cont-init.d/10-adduser \ + && sed -i 's/{PGID:-911}/(bashio::config "PGID")/g' /etc/cont-init.d/10-adduser \ + # use /data instead of /config for database + && sed -i 's| /config| /data|g' /defaults/scrutiny.yaml \ + && sed -i 's| /config| /data|g' /etc/cont-init.d/* \ + && sed -i 's| /config| /data|g' /etc/logrotate.d/scrutiny \ + && sed -i 's| /config| /data|g' /etc/crontabs/root \ + # correct url paths + && grep -rl '/web/' /app/scrutiny-web/ | xargs sed -i 's|/web/|./|g' + +################## +# 3 Install apps # +################## + +# Add rootfs +COPY rootfs/ / + +# Modules +ARG MODULES="00-banner.sh" + +# Automatic modules download +RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && mkdir -p /etc/cont-init.d \ + && for scripts in $MODULES; do echo "$scripts" && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/$scripts" -o /etc/cont-init.d/"$scripts" && [ "$(sed -n '/\/bin/p;q' /etc/cont-init.d/"$scripts")" != "" ] || (echo "script failed to install $scripts" && exit 1); done \ + && chmod -R 755 /etc/cont-init.d || printf '%s\n' "${MODULES}" >/MODULESFILE + +# Manual apps +ENV PACKAGES="jq \ + curl \ + cifs-utils \ + nginx" + +# Automatic apps & bashio +RUN if ! command -v bash >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/automatic_packages.sh" --output /automatic_packages.sh \ + && chmod 777 /automatic_packages.sh \ + && eval /./automatic_packages.sh "${PACKAGES:-}" \ + && rm /automatic_packages.sh || printf '%s\n' "${PACKAGES:-}" > /ENVFILE + +################ +# 4 Entrypoint # +################ + +# Collector +RUN chmod 777 /run.sh + +############ +# 5 Labels # +############ + +ARG BUILD_ARCH +ARG BUILD_DATE +ARG BUILD_DESCRIPTION +ARG BUILD_NAME +ARG BUILD_REF +ARG BUILD_REPOSITORY +ARG BUILD_VERSION +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="alexbelgium (https://github.com/alexbelgium)" \ + org.opencontainers.image.title="${BUILD_NAME}" \ + org.opencontainers.image.description="${BUILD_DESCRIPTION}" \ + org.opencontainers.image.vendor="Home Assistant Add-ons" \ + org.opencontainers.image.authors="alexbelgium (https://github.com/alexbelgium)" \ + org.opencontainers.image.licenses="MIT" \ + org.opencontainers.image.url="https://github.com/alexbelgium" \ + org.opencontainers.image.source="https://github.com/${BUILD_REPOSITORY}" \ + org.opencontainers.image.documentation="https://github.com/${BUILD_REPOSITORY}/blob/main/README.md" \ + org.opencontainers.image.created=${BUILD_DATE} \ + org.opencontainers.image.revision=${BUILD_REF} \ + org.opencontainers.image.version=${BUILD_VERSION} diff --git a/scrutiny_fa/README.md b/scrutiny_fa/README.md new file mode 100644 index 000000000..96513fd68 --- /dev/null +++ b/scrutiny_fa/README.md @@ -0,0 +1,112 @@ +# Home assistant add-on: Scrutiny + +[![Donate][donation-badge]](https://www.buymeacoffee.com/alexbelgium) + +![Version](https://img.shields.io/badge/dynamic/json?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fscrutiny%2Fconfig.json) +![Ingress](https://img.shields.io/badge/dynamic/json?label=Ingress&query=%24.ingress&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fscrutiny%2Fconfig.json) +![Arch](https://img.shields.io/badge/dynamic/json?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Fscrutiny%2Fconfig.json) + +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9c6cf10bdbba45ecb202d7f579b5be0e)](https://www.codacy.com/gh/alexbelgium/hassio-addons/dashboard?utm_source=github.com&utm_medium=referral&utm_content=alexbelgium/hassio-addons&utm_campaign=Badge_Grade) +[![GitHub Super-Linter](https://github.com/alexbelgium/hassio-addons/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) +[![Builder](https://github.com/alexbelgium/hassio-addons/workflows/Builder/badge.svg)](https://github.com/alexbelgium/hassio-addons/actions/workflows/builder.yaml) + +[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white + +_Thanks to everyone having starred my repo! To star it click on the image below, then it will be on top right. Thanks!_ + +[![Stargazers repo roster for @alexbelgium/hassio-addons](https://reporoster.com/stars/alexbelgium/hassio-addons)](https://github.com/alexbelgium/hassio-addons/stargazers) + +## About + +--- + +[Scrutiny](https://github.com/AnalogJ/scrutiny) is a Hard Drive Health Dashboard & Monitoring solution, merging manufacturer provided S.M.A.R.T metrics with real-world failure rates. This addon is based on the [docker image](https://hub.docker.com/r/linuxserver/scrutiny) from [linuxserver.io](https://www.linuxserver.io/). + +Features : + +- SMART monitoring +- Automatic addition of local drives +- Hourly updates +- Ingress with/without ssl +- Automatic upstream updates + +## Configuration + +--- + +Webui can be found at , or through Ingress. +It automatically mounts all local drives. + +Enable full access only if you are encountering issues. SMART access should work without full access in all other scenarios. + +```yaml +GUID: user +GPID: user +ssl: true/false (for Ingress) +certfile: fullchain.pem #ssl certificate +keyfile: privkey.pem #sslkeyfile +``` + +## Installation + +--- + +The installation of this add-on is pretty straightforward and not different in comparison to installing any other add-on. + +1. [Add my Hass.io add-ons repository][repository] to your home assistant instance. +1. Install this add-on. +1. Click the `Save` button to store your configuration. +1. Set the add-on options to your preferences +1. Start the add-on. +1. Check the logs of the add-on to see if everything went well. +1. Open the webUI (Ingress based) and adapt the software options + +# Integration in home assistant + +--- + +Integration with HA can be done with the [rest platform](https://www.home-assistant.io/integrations/rest) in configuration.yaml. + +Two types of api endpoints are available: + +- Summary data : http://YOURIP:ADDONPORT/api/summary +- Detailed data : http://YOURIP:ADDONPORT/api/WWN/details + +For the detailed data, wmn can be found for each hdd within the scrutiny app. For example for me : http://192.168.178.23:8086/api/device/0x50014ee606c14537/details + +Example to get data from the first hdd. + +```yaml +rest: + - verify_ssl: false + scan_interval: 60 + resource: http://YOURIP:ADDONPORT/api/summary + sensor: + - name: "HDD disk 1" + json_attributes_path: "$.data[0].smart_results[0]" + value_template: "OK" + json_attributes: + - "device_wwn" + - "date" + - "smart_status" + - "temp" + - "power_on_hours" + - "power_cycle_count" + - "ata_attributes" + - "nvme_attributes" + - "scsi_attributes" +``` + +## Illustration + +--- + +![Illustration](https://github.com/AnalogJ/scrutiny/raw/master/docs/dashboard.png) + +## Support + +Create an issue on github, or ask on the [home assistant thread](https://community.home-assistant.io/t/home-assistant-addon-scrutiny-smart-dashboard/295747) + +https://github.com/alexbelgium/hassio-addons + +[repository]: https://github.com/alexbelgium/hassio-addons diff --git a/scrutiny_fa/apparmor.txt b/scrutiny_fa/apparmor.txt new file mode 100644 index 000000000..08a51a81f --- /dev/null +++ b/scrutiny_fa/apparmor.txt @@ -0,0 +1,68 @@ +#include + +profile db21ed7f_scrutiny flags=(attach_disconnected,mediate_deleted) { + #include + + capability, + file, + signal, + mount, + umount, + remount, + network udp, + network tcp, + network dgram, + network stream, + network inet, + network inet6, + network netlink raw, + + capability setgid, + capability setuid, + capability dac_override, + capability sys_admin, + capability dac_read_search, + capability sys_rawio, + +# S6-Overlay + /bin/** ix, + /usr/bin/** ix, + /usr/lib/bashio/** ix, + /etc/s6/** rix, + /run/s6/** rix, + /etc/services.d/** rwix, + /etc/cont-init.d/** rwix, + /etc/cont-finish.d/** rwix, + /init rix, + /var/run/** mrwkl, + /var/run/ mrwkl, + /dev/i2c-1 mrwkl, + # Files required + /dev/sda1 mrwkl, + /dev/sdb1 mrwkl, + /dev/mmcblk0p1 mrwkl, + /dev/* mrwkl, + /tmp/** mrkwl, + /dev/sda mrwkl, + /dev/sdb mrwkl, + /dev/sdc mrwkl, + /dev/sdd mrwkl, + /dev/sde mrwkl, + /dev/sdf mrwkl, + /dev/sdg mrwkl, + /dev/nvme0 mrwkl, + /dev/nvme1 mrwkl, + /dev/nvme2 mrwkl, + /dev/nvme3 mrwkl, + /dev/nvme4 mrwkl, + + # Data access + /data/** rw, + + # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container + ptrace (trace,read) peer=docker-default, + + # docker daemon confinement requires explict allow rule for signal + signal (receive) set=(kill,term) peer=/usr/bin/docker, + +} diff --git a/scrutiny_fa/build.json b/scrutiny_fa/build.json new file mode 100644 index 000000000..4fc0e6a89 --- /dev/null +++ b/scrutiny_fa/build.json @@ -0,0 +1,7 @@ +{ + "build_from": { + "armv7": "lscr.io/linuxserver/scrutiny:arm32v7-latest", + "aarch64": "lscr.io/linuxserver/scrutiny:arm64v8-latest", + "amd64": "lscr.io/linuxserver/scrutiny:amd64-latest" + } +} diff --git a/scrutiny_fa/config.json b/scrutiny_fa/config.json new file mode 100644 index 000000000..0882a2a8c --- /dev/null +++ b/scrutiny_fa/config.json @@ -0,0 +1,46 @@ +{ + "name": "Scrutiny (Full Access)", + "version": "0.3.13-7", + "upstream": "0.3.13", + "slug": "scrutiny_fa", + "description": "Scrutiny WebUI for smartd S.M.A.R.T monitoring (Full Access)", + "url": "https://github.com/AnalogJ/scrutiny", + "startup": "services", + "arch": ["aarch64", "amd64", "armv7"], + "ingress": true, + "ingress_port": 8099, + "panel_icon": "mdi:glasses", + "ports": { + "8080/tcp": 8086 + }, + "ports_description": { + "8080/tcp": "Web UI port" + }, + "full_access": true, + "udev": "true", + "apparmor": "true", + "map": [], + "boot": "auto", + "environment": { + "SCRUTINY_API_ENDPOINT": "http://localhost:8080", + "SCRUTINY_WEB": "true", + "SCRUTINY_COLLECTOR": "true" + }, + "options": { + "ssl": false, + "certfile": "fullchain.pem", + "keyfile": "privkey.pem", + "Updates": "Hourly", + "PUID": 0, + "PGID": 0 + }, + "schema": { + "ssl": "bool", + "certfile": "str", + "keyfile": "str", + "Updates": "list(|Hourly|Daily|Weekly)", + "PUID": "int", + "PGID": "int", + "TZ": "str?" + } +} diff --git a/scrutiny_fa/icon.png b/scrutiny_fa/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba94a22a0648a673ffd701de30bfa9a741185d6 GIT binary patch literal 23635 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%0AH?Oon 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%0AH?Oon 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/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && mkdir -p /etc/cont-init.d \ + && for scripts in $MODULES; do echo "$scripts" && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/$scripts" -o /etc/cont-init.d/"$scripts" && [ "$(sed -n '/\/bin/p;q' /etc/cont-init.d/"$scripts")" != "" ] || (echo "script failed to install $scripts" && exit 1); done \ + && chmod -R 755 /etc/cont-init.d +fi + +####################### +# Automatic installer # +####################### +if [ -e "/ENVFILE" ]; then + PACKAGES=$(/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends bash || apk add --no-cache bash) >/dev/null; fi \ + && if ! command -v curl >/dev/null 2>/dev/null; then (apt-get update && apt-get install -yqq --no-install-recommends curl || apk add --no-cache curl) >/dev/null; fi \ + && curl -f -L -s -S "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/automatic_packages.sh" --output /automatic_packages.sh \ + && chmod 777 /automatic_packages.sh \ + && eval /./automatic_packages.sh "${PACKAGES:-}" \ + && rm /automatic_packages.sh +fi diff --git a/scrutiny_fa/rootfs/etc/cont-init.d/31-run.sh b/scrutiny_fa/rootfs/etc/cont-init.d/31-run.sh new file mode 100644 index 000000000..4947166c4 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/cont-init.d/31-run.sh @@ -0,0 +1,50 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +############## +# Data usage # +############## + +bashio::log.info "Setting permissions" +chown -R abc:abc /data + +####################### +# VIEWPORT CORRECTION # +####################### + +# correct viewport bug +# grep -rl '"lt-md":"(max-width: 959px)"' /app | xargs sed -i 's|"lt-md":"(max-width: 959px)"|"lt-md":"(max-width: 100px)"|g' || true + +###################### +# API URL CORRECTION # +###################### + +# allow true url for ingress +grep -rl '/api/' /app | xargs sed -i 's|/api/|api/|g' || true +grep -rl 'api/' /app | xargs sed -i 's|api/|./api/|g' || true + +################ +# CRON OPTIONS # +################ + +rm /config/crontabs/* || true +sed -i '$d' /etc/crontabs/root +sed -i -e '$a @reboot /run.sh' /etc/crontabs/root + +# Align update with options +FREQUENCY=$(bashio::config 'Updates') +bashio::log.info "$FREQUENCY updates" + +case $FREQUENCY in +"Hourly") + sed -i -e '$a 0 * * * * /run.sh' /etc/crontabs/root + ;; + +"Daily") + sed -i -e '$a 0 0 * * * /run.sh' /etc/crontabs/root + ;; + +"Weekly") + sed -i -e '$a 0 0 * * 0 /run.sh' /etc/crontabs/root + ;; +esac diff --git a/scrutiny_fa/rootfs/etc/cont-init.d/32-nginx.sh b/scrutiny_fa/rootfs/etc/cont-init.d/32-nginx.sh new file mode 100644 index 000000000..6ac38a5b6 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/cont-init.d/32-nginx.sh @@ -0,0 +1,33 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +################# +# NGINX SETTING # +################# +declare port +declare certfile +declare ingress_interface +declare ingress_port +declare keyfile + +port=$(bashio::addon.port 80) +if bashio::var.has_value "${port}"; then + bashio::config.require.ssl + + if bashio::config.true 'ssl'; then + certfile=$(bashio::config 'certfile') + keyfile=$(bashio::config 'keyfile') + + 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 +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 diff --git a/scrutiny_fa/rootfs/etc/nginx/includes/mime.types b/scrutiny_fa/rootfs/etc/nginx/includes/mime.types new file mode 100644 index 000000000..7c7cdef2d --- /dev/null +++ b/scrutiny_fa/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/scrutiny_fa/rootfs/etc/nginx/includes/proxy_params.conf b/scrutiny_fa/rootfs/etc/nginx/includes/proxy_params.conf new file mode 100644 index 000000000..1990d4959 --- /dev/null +++ b/scrutiny_fa/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 Host $http_host; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-NginX-Proxy true; +proxy_set_header X-Real-IP $remote_addr; diff --git a/scrutiny_fa/rootfs/etc/nginx/includes/resolver.conf b/scrutiny_fa/rootfs/etc/nginx/includes/resolver.conf new file mode 100644 index 000000000..6485af141 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/nginx/includes/resolver.conf @@ -0,0 +1 @@ +resolver 127.0.0.11; diff --git a/scrutiny_fa/rootfs/etc/nginx/includes/server_params.conf b/scrutiny_fa/rootfs/etc/nginx/includes/server_params.conf new file mode 100644 index 000000000..09c06543e --- /dev/null +++ b/scrutiny_fa/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/scrutiny_fa/rootfs/etc/nginx/includes/ssl_params.conf b/scrutiny_fa/rootfs/etc/nginx/includes/ssl_params.conf new file mode 100644 index 000000000..6f1500599 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/nginx/includes/ssl_params.conf @@ -0,0 +1,9 @@ +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_session_timeout 10m; +ssl_session_cache shared:SSL:10m; +ssl_session_tickets off; +ssl_stapling on; +ssl_stapling_verify on; diff --git a/scrutiny_fa/rootfs/etc/nginx/includes/upstream.conf b/scrutiny_fa/rootfs/etc/nginx/includes/upstream.conf new file mode 100644 index 000000000..b292326bd --- /dev/null +++ b/scrutiny_fa/rootfs/etc/nginx/includes/upstream.conf @@ -0,0 +1,3 @@ +upstream backend { + server 127.0.0.1:8080; +} diff --git a/scrutiny_fa/rootfs/etc/nginx/nginx.conf b/scrutiny_fa/rootfs/etc/nginx/nginx.conf new file mode 100644 index 000000000..7e5bc6f7c --- /dev/null +++ b/scrutiny_fa/rootfs/etc/nginx/nginx.conf @@ -0,0 +1,56 @@ +# 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 Hass.io add-on log. +error_log /proc/1/fd/1 error; + +# Load allowed environment vars +env HASSIO_TOKEN; + +# Load dynamic modules. +include /etc/nginx/modules/*.conf; + +# Max num of simultaneous connections by a worker process. +events { + worker_connections 512; +} + +http { + include /etc/nginx/includes/mime.types; + + log_format hassio '[$time_local] $status ' + '$http_x_forwarded_for($remote_addr) ' + '$request ($http_user_agent)'; + + access_log /proc/1/fd/1 hassio; + 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/includes/resolver.conf; + include /etc/nginx/includes/upstream.conf; + + include /etc/nginx/servers/*.conf; +} diff --git a/scrutiny_fa/rootfs/etc/nginx/servers/ingress.conf b/scrutiny_fa/rootfs/etc/nginx/servers/ingress.conf new file mode 100644 index 000000000..6c82c3dc5 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/nginx/servers/ingress.conf @@ -0,0 +1,21 @@ +server { + listen %%interface%%:%%port%% default_server; + + include /etc/nginx/includes/server_params.conf; + include /etc/nginx/includes/proxy_params.conf; + + client_max_body_size 0; + + location / { + add_header Access-Control-Allow-Origin *; + proxy_read_timeout 30; + proxy_pass http://backend/web/; + } + + location /api/ { + add_header Access-Control-Allow-Origin *; + proxy_read_timeout 30; + proxy_pass http://backend/api/; + } + +} diff --git a/scrutiny_fa/rootfs/etc/services.d/nginx/finish b/scrutiny_fa/rootfs/etc/services.d/nginx/finish new file mode 100644 index 000000000..444240135 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/services.d/nginx/finish @@ -0,0 +1,8 @@ +#!/usr/bin/execlineb -S0 +# ============================================================================== +# Take down the S6 supervision tree when Nginx fails +# ============================================================================== +if { s6-test ${1} -ne 0 } +if { s6-test ${1} -ne 256 } + +s6-svscanctl -t /var/run/s6/services diff --git a/scrutiny_fa/rootfs/etc/services.d/nginx/run b/scrutiny_fa/rootfs/etc/services.d/nginx/run new file mode 100644 index 000000000..07447d8b8 --- /dev/null +++ b/scrutiny_fa/rootfs/etc/services.d/nginx/run @@ -0,0 +1,10 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +# ============================================================================== + +# Wait for transmission to become available +bashio::net.wait_for 8080 localhost 900 + +bashio::log.info "Starting NGinx..." + +exec nginx diff --git a/scrutiny_fa/rootfs/run.sh b/scrutiny_fa/rootfs/run.sh new file mode 100644 index 000000000..30bc73d68 --- /dev/null +++ b/scrutiny_fa/rootfs/run.sh @@ -0,0 +1,13 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash + +# wait for scrutiny to load +bashio::net.wait_for 8080 + +##################### +# ADD LOCAL DEVICES # +##################### + +# search for local devices +# shellcheck disable=SC2015 +scrutiny-collector-metrics run >/dev/null && bashio::log.info "Local Devices Added" || bashio::log.error "Local Devices Not Added"