From 5a7eb72d4bda9f90d17440deed84c442fd410047 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Tue, 2 Feb 2021 22:36:04 +0100 Subject: [PATCH] Refactor add-on (#232) * Refactor add-on * Replace NGinx Configuration * Ingress!!! * More tweaks, renames and other touches * Revert accidental upgrade of JupyterLab --- .github/workflows/ci.yaml | 2 +- .github/workflows/deploy.yaml | 2 +- CONTRIBUTING.md | 4 +- README.md | 22 ++--- jupyterlab/.README.j2 | 4 +- jupyterlab/DOCS.md | 53 ++-------- jupyterlab/Dockerfile | 27 +++--- jupyterlab/build.json | 5 +- jupyterlab/config.json | 22 ++--- jupyterlab/requirements.txt | 4 +- .../rootfs/etc/cont-init.d/10-requirements.sh | 6 -- jupyterlab/rootfs/etc/cont-init.d/11-nginx.sh | 24 ----- .../rootfs/etc/cont-init.d/51-github.sh | 13 --- .../rootfs/etc/cont-init.d/81-user-scripts.sh | 11 --- .../{21-persistent-storage.sh => jupyter.sh} | 14 ++- jupyterlab/rootfs/etc/cont-init.d/nginx.sh | 12 +++ .../{20-notebooks-dir.sh => notebooks.sh} | 7 +- ...-system-packages.sh => system-packages.sh} | 11 ++- ...config.py => jupyter_notebook_config.gtpl} | 4 +- jupyterlab/rootfs/etc/nginx/ha-auth.lua | 83 ---------------- .../rootfs/etc/nginx/includes/mime.types | 96 +++++++++++++++++++ .../etc/nginx/includes/proxy_params.conf | 15 +++ .../etc/nginx/includes/server_params.conf | 10 ++ .../rootfs/etc/nginx/includes/upstream.conf | 3 + jupyterlab/rootfs/etc/nginx/nginx-ssl.conf | 73 -------------- jupyterlab/rootfs/etc/nginx/nginx.conf | 79 +++++++-------- jupyterlab/rootfs/etc/nginx/servers/.gitkeep | 1 + .../rootfs/etc/nginx/templates/ingress.gtpl | 13 +++ .../rootfs/etc/services.d/jupyter/finish | 2 +- jupyterlab/rootfs/etc/services.d/jupyter/run | 2 +- jupyterlab/rootfs/etc/services.d/nginx/finish | 2 +- jupyterlab/rootfs/etc/services.d/nginx/run | 11 +-- 32 files changed, 260 insertions(+), 377 deletions(-) delete mode 100644 jupyterlab/rootfs/etc/cont-init.d/10-requirements.sh delete mode 100644 jupyterlab/rootfs/etc/cont-init.d/11-nginx.sh delete mode 100644 jupyterlab/rootfs/etc/cont-init.d/51-github.sh delete mode 100644 jupyterlab/rootfs/etc/cont-init.d/81-user-scripts.sh rename jupyterlab/rootfs/etc/cont-init.d/{21-persistent-storage.sh => jupyter.sh} (70%) create mode 100644 jupyterlab/rootfs/etc/cont-init.d/nginx.sh rename jupyterlab/rootfs/etc/cont-init.d/{20-notebooks-dir.sh => notebooks.sh} (90%) rename jupyterlab/rootfs/etc/cont-init.d/{80-system-packages.sh => system-packages.sh} (62%) rename jupyterlab/rootfs/etc/jupyter/{jupyter_notebook_config.py => jupyter_notebook_config.gtpl} (91%) delete mode 100644 jupyterlab/rootfs/etc/nginx/ha-auth.lua create mode 100644 jupyterlab/rootfs/etc/nginx/includes/mime.types create mode 100644 jupyterlab/rootfs/etc/nginx/includes/proxy_params.conf create mode 100644 jupyterlab/rootfs/etc/nginx/includes/server_params.conf create mode 100644 jupyterlab/rootfs/etc/nginx/includes/upstream.conf delete mode 100644 jupyterlab/rootfs/etc/nginx/nginx-ssl.conf create mode 100644 jupyterlab/rootfs/etc/nginx/servers/.gitkeep create mode 100644 jupyterlab/rootfs/etc/nginx/templates/ingress.gtpl diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d99235c..75bdd98 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: build: ${{ steps.information.outputs.build }} description: ${{ steps.information.outputs.description }} name: ${{ steps.information.outputs.name }} - slug: ${{ steps.information.outputs.slug }} + slug: "jupyterlab" target: ${{ steps.information.outputs.target }} steps: - name: ⤵️ Check out code from GitHub diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 1190d75..2920e6c 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -28,7 +28,7 @@ jobs: description: ${{ steps.information.outputs.description }} environment: ${{ steps.release.outputs.environment }} name: ${{ steps.information.outputs.name }} - slug: ${{ steps.information.outputs.slug }} + slug: "jupyterlab" target: ${{ steps.information.outputs.target }} version: ${{ steps.release.outputs.version }} steps: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 98f1dd2..cb36f78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,5 +25,5 @@ Even better: You could submit a pull request with a fix / new feature! developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you. -[github]: https://github.com/hassio-addons/addon-jupyterlab-lite/issues -[prs]: https://github.com/hassio-addons/addon-jupyterlab-lite/pulls +[github]: https://github.com/hassio-addons/addon-jupyterlab/issues +[prs]: https://github.com/hassio-addons/addon-jupyterlab/pulls diff --git a/README.md b/README.md index 415a065..3fd6b30 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab [![GitHub Release][releases-shield]][releases] ![Project Stage][project-stage-shield] @@ -105,30 +105,30 @@ SOFTWARE. [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-no-red.svg -[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-jupyterlab-lite.svg -[commits]: https://github.com/hassio-addons/addon-jupyterlab-lite/commits/main -[contributors]: https://github.com/hassio-addons/addon-jupyterlab-lite/graphs/contributors +[commits-shield]: https://img.shields.io/github/commit-activity/y/hassio-addons/addon-jupyterlab.svg +[commits]: https://github.com/hassio-addons/addon-jupyterlab/commits/main +[contributors]: https://github.com/hassio-addons/addon-jupyterlab/graphs/contributors [discord-ha]: https://discord.gg/c5DvZ4e [discord-shield]: https://img.shields.io/discord/478094546522079232.svg [discord]: https://discord.me/hassioaddons -[docs]: https://github.com/hassio-addons/addon-jupyterlab-lite/blob/main/jupyterlab-lite/DOCS.md +[docs]: https://github.com/hassio-addons/addon-jupyterlab/blob/main/jupyterlab/DOCS.md [forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg [forum]: https://community.home-assistant.io/t/home-assistant-community-add-on-jupyterlab-lite/87337?u=frenck [frenck]: https://github.com/frenck -[github-actions-shield]: https://github.com/hassio-addons/addon-jupyterlab-lite/workflows/CI/badge.svg -[github-actions]: https://github.com/hassio-addons/addon-jupyterlab-lite/actions +[github-actions-shield]: https://github.com/hassio-addons/addon-jupyterlab/workflows/CI/badge.svg +[github-actions]: https://github.com/hassio-addons/addon-jupyterlab/actions [github-sponsors-shield]: https://frenck.dev/wp-content/uploads/2019/12/github_sponsor.png [github-sponsors]: https://github.com/sponsors/frenck [home-assistant]: https://home-assistant.io [i386-shield]: https://img.shields.io/badge/i386-no-red.svg -[issue]: https://github.com/hassio-addons/addon-jupyterlab-lite/issues -[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-jupyterlab-lite.svg +[issue]: https://github.com/hassio-addons/addon-jupyterlab/issues +[license-shield]: https://img.shields.io/github/license/hassio-addons/addon-jupyterlab.svg [maintenance-shield]: https://img.shields.io/maintenance/yes/2021.svg [patreon-shield]: https://frenck.dev/wp-content/uploads/2019/12/patreon.png [patreon]: https://www.patreon.com/frenck [project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg [python-packages]: https://pypi.org/ [reddit]: https://reddit.com/r/homeassistant -[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-jupyterlab-lite.svg -[releases]: https://github.com/hassio-addons/addon-jupyterlab-lite/releases +[releases-shield]: https://img.shields.io/github/release/hassio-addons/addon-jupyterlab.svg +[releases]: https://github.com/hassio-addons/addon-jupyterlab/releases [repository]: https://github.com/hassio-addons/repository diff --git a/jupyterlab/.README.j2 b/jupyterlab/.README.j2 index 5f1e0e2..89b5cf4 100644 --- a/jupyterlab/.README.j2 +++ b/jupyterlab/.README.j2 @@ -1,4 +1,4 @@ -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab [![Release][release-shield]][release] ![Project Stage][project-stage-shield] ![Project Maintenance][maintenance-shield] @@ -76,4 +76,4 @@ If you are more interested in stable releases of our add-ons: [project-stage-shield]: https://img.shields.io/badge/project%20stage-experimental-yellow.svg [release-shield]: https://img.shields.io/badge/version-{{ version }}-blue.svg [release]: {{ repo }}/tree/{{ version }} -[screenshot]: https://github.com/hassio-addons/addon-jupyterlab-lite/raw/main/images/screenshot.png +[screenshot]: https://github.com/hassio-addons/addon-jupyterlab/raw/main/images/screenshot.png diff --git a/jupyterlab/DOCS.md b/jupyterlab/DOCS.md index d43d6d5..9af340d 100644 --- a/jupyterlab/DOCS.md +++ b/jupyterlab/DOCS.md @@ -1,4 +1,4 @@ -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab JupyterLab is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. @@ -14,10 +14,10 @@ reproducible computing, based on the Jupyter Notebook and Architecture. The installation of this add-on is pretty straightforward and not different in comparison to installing any other Home Assistant add-on. -1. Search for the "JupyterLab Lite" add-on in the Supervisor add-on store +1. Search for the "JupyterLab" add-on in the Supervisor add-on store and install it. -1. Start the "JupyterLab Lite" add-on -1. Check the logs of the "JupyterLab Lite" add-on to see if everything went well. +1. Start the "JupyterLab" add-on +1. Check the logs of the "JupyterLab" add-on to see if everything went well. ## Configuration @@ -28,9 +28,6 @@ Example add-on configuration: ```yaml log_level: info github_access_token: abcdef1234567890abcdef0123456789abcdef01 -ssl: true -certfile: fullchain.pem -keyfile: privkey.pem system_packages: - ffmpeg init_commands: @@ -69,23 +66,6 @@ There is a chapter in this document with instruction on obtaining such a token. **Note**: _This option support secrets, e.g., `!secret github_token`._ -### Option: `ssl` - -Enables/Disables SSL (HTTPS) on the JupyterLab Set it `true` to enable it, -`false` otherwise. - -### Option: `certfile` - -The certificate file to use for SSL. - -**Note**: _The file MUST be stored in `/ssl/`, which is the default_ - -### Option: `keyfile` - -The private key file to use for SSL. - -**Note**: _The file MUST be stored in `/ssl/`, which is the default_ - ### Option: `system_packages` Allows you to specify additional [Alpine packages][alpine-packages] to be @@ -100,23 +80,6 @@ Customize your environment even more with the `init_commands` option. Add one or more shell commands to the list, and they will be executed every single time this add-on starts. -## Embedding into Home Assistant - -It is possible to embed JupyterLab directly into Home Assistant, allowing -you to access the JupyterLab through the Home Assistant frontend. - -Home Assistant provides the `panel_iframe` integration, for these purposes. - -Example configuration: - -```yaml -panel_iframe: - jupyterlab: - title: JupyterLab - icon: mdi:flask - url: https://addres.to.your.home.assistant:7777 -``` - ## Getting a GitHub access token You can get an access token by following these steps: @@ -194,15 +157,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [alpine-packages]: https://pkgs.alpinelinux.org/packages -[contributors]: https://github.com/hassio-addons/addon-jupyterlab-lite/graphs/contributors +[contributors]: https://github.com/hassio-addons/addon-jupyterlab/graphs/contributors [discord-ha]: https://discord.gg/c5DvZ4e [discord]: https://discord.me/hassioaddons [forum-shield]: https://img.shields.io/badge/community-forum-brightgreen.svg -[forum]: https://community.home-assistant.io/t/home-assistant-community-add-on-jupyterlab-lite/87337?u=frenck +[forum]: https://community.home-assistant.io/t/home-assistant-community-add-on-jupyterlab/87337?u=frenck [frenck]: https://github.com/frenck [github-verify]: https://help.github.com/articles/verifying-your-email-address -[issue]: https://github.com/hassio-addons/addon-jupyterlab-lite/issues +[issue]: https://github.com/hassio-addons/addon-jupyterlab/issues [python-packages]: https://pypi.org/ [reddit]: https://reddit.com/r/homeassistant -[releases]: https://github.com/hassio-addons/addon-jupyterlab-lite/releases +[releases]: https://github.com/hassio-addons/addon-jupyterlab/releases [semver]: http://semver.org/spec/v2.0.0.htm diff --git a/jupyterlab/Dockerfile b/jupyterlab/Dockerfile index 2b39ee8..52f2af5 100644 --- a/jupyterlab/Dockerfile +++ b/jupyterlab/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_FROM=hassioaddons/debian-base:3.2.3 +ARG BUILD_FROM=ghcr.io/hassio-addons/debian-base/amd64:4.1.2 # hadolint ignore=DL3006 FROM ${BUILD_FROM} @@ -25,26 +25,25 @@ RUN \ gpg=2.2.12-1+deb10u1 \ libffi-dev=3.2.1-9 \ libffi6=3.2.1-9 \ - libfreetype6-dev=2.9.1-3+deb10u1 \ - libfreetype6=2.9.1-3+deb10u1 \ - libjpeg62-turbo-dev=1:1.5.2-2+b1 \ - libjpeg62-turbo=1:1.5.2-2+b1 \ + libfreetype6-dev=2.9.1-3+deb10u2 \ + libfreetype6=2.9.1-3+deb10u2 \ + libjpeg62-turbo-dev=1:1.5.2-2+deb10u1 \ + libjpeg62-turbo=1:1.5.2-2+deb10u1 \ libmariadb-dev=1:10.3.25-0+deb10u1 \ libmariadb3=1:10.3.25-0+deb10u1 \ libnginx-mod-http-lua=1.14.2-2+deb10u3 \ libpng-dev=1.6.36-6 \ libpng16-16=1.6.36-6 \ - libpq-dev=11.7-0+deb10u1 \ - libpq5=11.7-0+deb10u1 \ - libssl-dev=1.1.1d-0+deb10u3 \ + libpq-dev=11.9-0+deb10u1 \ + libpq5=11.9-0+deb10u1 \ + libssl-dev=1.1.1d-0+deb10u4 \ libtiff5-dev=4.1.0+git191117-2~deb10u1 \ - libxml2-dev=2.9.4+dfsg1-7+b3 \ - libxml2=2.9.4+dfsg1-7+b3 \ + libxml2-dev=2.9.4+dfsg1-7+deb10u1 \ + libxml2=2.9.4+dfsg1-7+deb10u1 \ libxslt1-dev=1.1.32-2.2~deb10u1 \ libxslt1.1=1.1.32-2.2~deb10u1 \ libzmq3-dev=4.3.1-4+deb10u2 \ libzmq5=4.3.1-4+deb10u2 \ - luarocks=2.4.2+dfsg-1 \ nginx=1.14.2-2+deb10u3 \ pandoc>=2.2.1-3 \ pkg-config=0.29-6 \ @@ -54,19 +53,17 @@ RUN \ python3-minimal=3.7.3-1 \ zlib1g-dev=1:1.2.11.dfsg-1 \ \ - && luarocks install lua-resty-http 0.15-0 \ - \ && curl -sL https://deb.nodesource.com/setup_12.x | bash - \ \ && apt-get install -y --no-install-recommends \ - nodejs=12.19.0-1nodesource1 \ + nodejs=12.20.1-1nodesource1 \ \ && curl https://bootstrap.pypa.io/get-pip.py | python3 \ \ && update-alternatives \ --install /usr/bin/python python /usr/bin/python3 10 \ \ - && pip3 install --no-cache-dir numpy==1.19.4 \ + && pip3 install --no-cache-dir numpy==1.20.0 \ && pip3 install --no-cache-dir -r /opt/requirements.txt \ \ && jupyter labextension install \ diff --git a/jupyterlab/build.json b/jupyterlab/build.json index e56bf84..616ce96 100644 --- a/jupyterlab/build.json +++ b/jupyterlab/build.json @@ -1,7 +1,6 @@ { "build_from": { - "aarch64": "hassioaddons/debian-base-aarch64:3.2.3", - "amd64": "hassioaddons/debian-base-amd64:3.2.3", - "armhf": "hassioaddons/debian-base-armhf:3.2.3" + "aarch64": "ghcr.io/hassio-addons/debian-base/aarch64:4.1.2", + "amd64": "ghcr.io/hassio-addons/debian-base/amd64:4.1.2" } } diff --git a/jupyterlab/config.json b/jupyterlab/config.json index 00d2658..89fdd7a 100644 --- a/jupyterlab/config.json +++ b/jupyterlab/config.json @@ -1,32 +1,22 @@ { - "name": "JupyterLab Lite", + "name": "JupyterLab", "version": "dev", "slug": "jupyterlablite", "description": "Create documents containing live code, equations, visualizations, and explanatory text", - "url": "https://github.com/hassio-addons/addon-jupyterlab-lite", - "webui": "[PROTO:ssl]://[HOST]:[PORT:7777]", - "arch": ["aarch64", "amd64", "armhf"], - "hassio_api": true, - "auth_api": true, + "url": "https://github.com/hassio-addons/addon-jupyterlab", + "ingress": true, + "panel_icon": "mdi:flask-outline", + "arch": ["aarch64", "amd64"], "homeassistant_api": true, - "ports": { - "7777/tcp": 7777 - }, - "map": ["config:rw", "share:rw", "ssl"], + "map": ["config:rw", "share:rw"], "options": { "github_access_token": "", - "ssl": false, - "certfile": "fullchain.pem", - "keyfile": "privkey.pem", "system_packages": [], "init_commands": [] }, "schema": { "log_level": "list(trace|debug|info|notice|warning|error|fatal)?", "github_access_token": "password", - "ssl": "bool", - "certfile": "str", - "keyfile": "str", "system_packages": ["str"], "init_commands": ["str"] } diff --git a/jupyterlab/requirements.txt b/jupyterlab/requirements.txt index 995fb73..30afce3 100644 --- a/jupyterlab/requirements.txt +++ b/jupyterlab/requirements.txt @@ -10,10 +10,10 @@ jupyterlab==2.2.9 matplotlib==3.3.3 mysqlclient==2.0.3 nbconvert==6.0.7 -numpy==1.19.5 +numpy==1.20.0 pandas-datareader==0.9.0 pandas==1.2.1 psycopg2==2.8.6 python-dateutil==2.8.1 scrapy==2.4.1 -SQLAlchemy==1.3.22 +SQLAlchemy==1.3.23 diff --git a/jupyterlab/rootfs/etc/cont-init.d/10-requirements.sh b/jupyterlab/rootfs/etc/cont-init.d/10-requirements.sh deleted file mode 100644 index de034f5..0000000 --- a/jupyterlab/rootfs/etc/cont-init.d/10-requirements.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# This files check if all user configuration requirements are met -# ============================================================================== -bashio::config.require.ssl diff --git a/jupyterlab/rootfs/etc/cont-init.d/11-nginx.sh b/jupyterlab/rootfs/etc/cont-init.d/11-nginx.sh deleted file mode 100644 index 0296184..0000000 --- a/jupyterlab/rootfs/etc/cont-init.d/11-nginx.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# Configures NGINX for use with JupyterLab -# ============================================================================== -declare certfile -declare keyfile -declare dns_host - -mkdir -p /var/log/nginx - -if bashio::config.true 'ssl'; then - rm /etc/nginx/nginx.conf - mv /etc/nginx/nginx-ssl.conf /etc/nginx/nginx.conf - - certfile=$(bashio::config 'certfile') - keyfile=$(bashio::config 'keyfile') - - sed -i "s#%%certfile%%#${certfile}#g" /etc/nginx/nginx.conf - sed -i "s#%%keyfile%%#${keyfile}#g" /etc/nginx/nginx.conf -fi - -dns_host=$(bashio::dns.host) -sed -i "s/%%dns_host%%/${dns_host}/g" /etc/nginx/nginx.conf diff --git a/jupyterlab/rootfs/etc/cont-init.d/51-github.sh b/jupyterlab/rootfs/etc/cont-init.d/51-github.sh deleted file mode 100644 index aeaaf36..0000000 --- a/jupyterlab/rootfs/etc/cont-init.d/51-github.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# Install the users GitHub Access token into JupyterLab -# ============================================================================== -readonly CONFIG_PATH="/etc/jupyter/jupyter_notebook_config.py" - -# Set password -if bashio::config.has_value 'github_access_token'; then - token=$(bashio::config 'github_access_token') - sed -i "s/c.GitHubConfig.access_token\\ .*/c.GitHubConfig.access_token\\ =\\ '${token}'/" "${CONFIG_PATH}" \ - || bashio::exit.nok 'Failed setting up GitHub access token' -fi diff --git a/jupyterlab/rootfs/etc/cont-init.d/81-user-scripts.sh b/jupyterlab/rootfs/etc/cont-init.d/81-user-scripts.sh deleted file mode 100644 index 70cd097..0000000 --- a/jupyterlab/rootfs/etc/cont-init.d/81-user-scripts.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/with-contenv bashio -# ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# Executes user configured/requested commands on startup -# ============================================================================== -if bashio::config.has_value 'init_commands'; then - while read -r cmd; do - eval "${cmd}" \ - || bashio::exit.nok "Failed executing init command: ${cmd}" - done <<< "$(bashio::config 'init_commands')" -fi diff --git a/jupyterlab/rootfs/etc/cont-init.d/21-persistent-storage.sh b/jupyterlab/rootfs/etc/cont-init.d/jupyter.sh similarity index 70% rename from jupyterlab/rootfs/etc/cont-init.d/21-persistent-storage.sh rename to jupyterlab/rootfs/etc/cont-init.d/jupyter.sh index 6351de0..fb5ee05 100644 --- a/jupyterlab/rootfs/etc/cont-init.d/21-persistent-storage.sh +++ b/jupyterlab/rootfs/etc/cont-init.d/jupyter.sh @@ -1,7 +1,7 @@ #!/usr/bin/with-contenv bashio # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# Ensure directories in the persistent storage exists +# Home Assistant Community Add-on: JupyterLab +# Configure JupterLabs # ============================================================================== if ! bashio::fs.directory_exists '/data/user-settings'; then mkdir -p /data/user-settings \ @@ -20,4 +20,14 @@ if ! bashio::fs.directory_exists '/data/local'; then || bashio::exit.nok \ 'Failed creating persistent local directory' fi + ln -s /data/local /root/.local + +bashio::var.json \ + entry "$(bashio::addon.ingress_entry)" \ + token "$(bashio::config 'github_access_token')" \ + | tempio \ + -template /etc/jupyter/jupyter_notebook_config.gtpl \ + -out /etc/jupyter/jupyter_notebook_config.py + + diff --git a/jupyterlab/rootfs/etc/cont-init.d/nginx.sh b/jupyterlab/rootfs/etc/cont-init.d/nginx.sh new file mode 100644 index 0000000..d492d23 --- /dev/null +++ b/jupyterlab/rootfs/etc/cont-init.d/nginx.sh @@ -0,0 +1,12 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: JupyterLab +# Configures NGINX for use with JupyterLab +# ============================================================================== + +# Generate Ingress configuration +bashio::var.json \ + entry "$(bashio::addon.ingress_entry)" \ + | tempio \ + -template /etc/nginx/templates/ingress.gtpl \ + -out /etc/nginx/servers/ingress.conf diff --git a/jupyterlab/rootfs/etc/cont-init.d/20-notebooks-dir.sh b/jupyterlab/rootfs/etc/cont-init.d/notebooks.sh similarity index 90% rename from jupyterlab/rootfs/etc/cont-init.d/20-notebooks-dir.sh rename to jupyterlab/rootfs/etc/cont-init.d/notebooks.sh index 90c9f7d..6388ae3 100644 --- a/jupyterlab/rootfs/etc/cont-init.d/20-notebooks-dir.sh +++ b/jupyterlab/rootfs/etc/cont-init.d/notebooks.sh @@ -1,6 +1,6 @@ #!/usr/bin/with-contenv bashio # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab # Ensures the JupyterLab notebooks directory exists # ============================================================================== readonly BOOKS="/config/notebooks/" @@ -20,11 +20,6 @@ if ! bashio::fs.directory_exists '/config/notebooks'; then "${BOOKS}bokeh-examples" \ || bashio::exit.nok \ 'Failed installing Bokeh example notebooks' - - ln -sf \ - "${BOOKS}home-assistant/~ GETTING STARTED.ipynb" \ - "${BOOKS}GETTING STARTED.ipynb" - else if [ -z "$(git -C ${BOOKS}/home-assistant status --untracked-files=no --porcelain)" ]; then diff --git a/jupyterlab/rootfs/etc/cont-init.d/80-system-packages.sh b/jupyterlab/rootfs/etc/cont-init.d/system-packages.sh similarity index 62% rename from jupyterlab/rootfs/etc/cont-init.d/80-system-packages.sh rename to jupyterlab/rootfs/etc/cont-init.d/system-packages.sh index 4b2780a..81eb9a5 100644 --- a/jupyterlab/rootfs/etc/cont-init.d/80-system-packages.sh +++ b/jupyterlab/rootfs/etc/cont-init.d/system-packages.sh @@ -1,7 +1,7 @@ #!/usr/bin/with-contenv bashio # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite -# Install user configured/requested packages +# Home Assistant Community Add-on: JupyterLab +# Install user configured requested packages & commands # ============================================================================== if bashio::config.has_value 'system_packages'; then apt-get update \ @@ -12,3 +12,10 @@ if bashio::config.has_value 'system_packages'; then || bashio::exit.nok "Failed installing package ${package}" done fi + +if bashio::config.has_value 'init_commands'; then + while read -r cmd; do + eval "${cmd}" \ + || bashio::exit.nok "Failed executing init command: ${cmd}" + done <<< "$(bashio::config 'init_commands')" +fi diff --git a/jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.py b/jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.gtpl similarity index 91% rename from jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.py rename to jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.gtpl index cd93571..822d3b9 100644 --- a/jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.py +++ b/jupyterlab/rootfs/etc/jupyter/jupyter_notebook_config.gtpl @@ -6,7 +6,7 @@ c = get_config() # NotebookApp configuration # ------------------------------------------------------------------------------ -c.GitHubConfig.access_token = '' +c.GitHubConfig.access_token = '{{ .token }}' c.JupyterApp.answer_yes = True c.LabApp.user_settings_dir = '/data/user-settings' c.LabApp.workspaces_dir = '/data/workspaces' @@ -14,7 +14,7 @@ c.NotebookApp.allow_origin = '*' c.NotebookApp.allow_password_change = False c.NotebookApp.allow_remote_access = True c.NotebookApp.allow_root = True -c.NotebookApp.base_url = '/' +c.NotebookApp.base_url = '{{ .entry }}' c.NotebookApp.ip = '127.0.0.1' c.NotebookApp.notebook_dir = '/config/notebooks' c.NotebookApp.open_browser = False diff --git a/jupyterlab/rootfs/etc/nginx/ha-auth.lua b/jupyterlab/rootfs/etc/nginx/ha-auth.lua deleted file mode 100644 index a2c633c..0000000 --- a/jupyterlab/rootfs/etc/nginx/ha-auth.lua +++ /dev/null @@ -1,83 +0,0 @@ -local http = require "resty.http" -local auths = ngx.shared.auths - -function authenticate() - - --- Test Authentication header is set and with a value - local header = ngx.req.get_headers()['Authorization'] - if header == nil or header:find(" ") == nil then - return false - end - - local divider = header:find(' ') - if header:sub(0, divider-1) ~= 'Basic' then - return false - end - - local auth = ngx.decode_base64(header:sub(divider+1)) - if auth == nil or auth:find(':') == nil then - return false - end - - divider = auth:find(':') - local username = auth:sub(0, divider-1) - local password = auth:sub(divider+1) - - --- Check if authentication is cached - if auths:get(username) == password then - ngx.log(ngx.DEBUG, "Authenticated user against Home Assistant (cache).") - return true - end - - --- HTTP request against the Supervisor API - local httpc = http.new() - local res, err = httpc:request_uri("http://supervisor.local.hass.io/auth", { - method = "POST", - body = ngx.encode_args({["username"]=username, ["password"]=password}), - headers = { - ["Content-Type"] = "application/x-www-form-urlencoded", - ["X-Supervisor-Token"] = os.getenv("SUPERVISOR_TOKEN"), - }, - keepalive_timeout = 60, - keepalive_pool = 10 - }) - - --- Error during API request - if err then - ngx.log(ngx.WARN, "Error during Home Assistant user authentication.", err) - return false - end - - --- No result? Something went wrong... - if not res then - ngx.log(ngx.WARN, "Error during Home Assistant user authentication.") - return false - end - - --- Valid response, the username/password is valid - if res.status == 200 then - ngx.log(ngx.INFO, "Authenticated user against Home Assistant.") - auths:set(username, password, 60) - return true - end - - --- Whatever the response is, it is invalid - ngx.log(ngx.WARN, "Authentication against Home Assistant failed!") - return false -end - --- Only authenticate if its not disabled -if not os.getenv('DISABLE_HA_AUTHENTICATION') then - - --- Try to authenticate against HA - local authenticated = authenticate() - - --- If authentication failed, throw a basic auth - if not authenticated then - ngx.header.content_type = 'text/plain' - ngx.header.www_authenticate = 'Basic realm="Home Assistant"' - ngx.status = ngx.HTTP_UNAUTHORIZED - ngx.say('401 Access Denied') - ngx.exit(ngx.HTTP_UNAUTHORIZED) - end -end diff --git a/jupyterlab/rootfs/etc/nginx/includes/mime.types b/jupyterlab/rootfs/etc/nginx/includes/mime.types new file mode 100644 index 0000000..7c7cdef --- /dev/null +++ b/jupyterlab/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/jupyterlab/rootfs/etc/nginx/includes/proxy_params.conf b/jupyterlab/rootfs/etc/nginx/includes/proxy_params.conf new file mode 100644 index 0000000..1990d49 --- /dev/null +++ b/jupyterlab/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/jupyterlab/rootfs/etc/nginx/includes/server_params.conf b/jupyterlab/rootfs/etc/nginx/includes/server_params.conf new file mode 100644 index 0000000..55ed565 --- /dev/null +++ b/jupyterlab/rootfs/etc/nginx/includes/server_params.conf @@ -0,0 +1,10 @@ +root /dev/null; +server_name $hostname; + +client_max_body_size 64m; + +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; +add_header X-Robots-Tag none; +add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; +expires off; diff --git a/jupyterlab/rootfs/etc/nginx/includes/upstream.conf b/jupyterlab/rootfs/etc/nginx/includes/upstream.conf new file mode 100644 index 0000000..bfe271d --- /dev/null +++ b/jupyterlab/rootfs/etc/nginx/includes/upstream.conf @@ -0,0 +1,3 @@ +upstream backend { + server 127.0.0.1:28459; +} diff --git a/jupyterlab/rootfs/etc/nginx/nginx-ssl.conf b/jupyterlab/rootfs/etc/nginx/nginx-ssl.conf deleted file mode 100644 index 96f0605..0000000 --- a/jupyterlab/rootfs/etc/nginx/nginx-ssl.conf +++ /dev/null @@ -1,73 +0,0 @@ -worker_processes 1; -pid /var/run/nginx.pid; -error_log stderr; -env SUPERVISOR_TOKEN; -env DISABLE_HA_AUTHENTICATION; -load_module "/usr/lib/nginx/modules/ndk_http_module.so"; -load_module "/usr/lib/nginx/modules/ngx_http_lua_module.so"; - -events { - worker_connections 1024; -} - -http { - access_log stdout; - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - lua_shared_dict auths 16k; - resolver %%dns_host%%; - - upstream jupyter { - ip_hash; - server 127.0.0.1:28459; - } - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - server { - server_name hassio.local; - listen 7777 default_server ssl; - root /dev/null; - - ssl_certificate /ssl/%%certfile%%; - ssl_certificate_key /ssl/%%keyfile%%; - 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; - - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header X-Robots-Tag none; - - location / { - access_by_lua_file /etc/nginx/ha-auth.lua; - - proxy_redirect off; - proxy_pass http://jupyter; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Authorization ""; - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - proxy_set_header X-NginX-Proxy true; - proxy_read_timeout 86400s; - proxy_send_timeout 86400s; - } - } -} diff --git a/jupyterlab/rootfs/etc/nginx/nginx.conf b/jupyterlab/rootfs/etc/nginx/nginx.conf index 14e941b..2df3c25 100644 --- a/jupyterlab/rootfs/etc/nginx/nginx.conf +++ b/jupyterlab/rootfs/etc/nginx/nginx.conf @@ -1,58 +1,45 @@ -worker_processes 1; -pid /var/run/nginx.pid; -error_log stderr; -env SUPERVISOR_TOKEN; -env DISABLE_HA_AUTHENTICATION; -load_module "/usr/lib/nginx/modules/ndk_http_module.so"; -load_module "/usr/lib/nginx/modules/ngx_http_lua_module.so"; +# 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 off; + +# Load allowed environment vars +env SUPERVISOR_TOKEN; + +# Max num of simultaneous connections by a worker process. events { - worker_connections 1024; + worker_connections 512; } http { - access_log stdout; - include mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - lua_shared_dict auths 16k; - resolver %%dns_host%%; - client_max_body_size 0; - - upstream jupyter { - ip_hash; - server 127.0.0.1:28459; - } + 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; } - server { - server_name hassio.local; - listen 7777 default_server; - root /dev/null; - - location / { - access_by_lua_file /etc/nginx/ha-auth.lua; - - proxy_redirect off; - proxy_pass http://jupyter; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header Authorization ""; - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - proxy_set_header X-NginX-Proxy true; - proxy_read_timeout 86400s; - proxy_send_timeout 86400s; - } - } + include /etc/nginx/includes/upstream.conf; + include /etc/nginx/servers/*.conf; } diff --git a/jupyterlab/rootfs/etc/nginx/servers/.gitkeep b/jupyterlab/rootfs/etc/nginx/servers/.gitkeep new file mode 100644 index 0000000..85ad51b --- /dev/null +++ b/jupyterlab/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/jupyterlab/rootfs/etc/nginx/templates/ingress.gtpl b/jupyterlab/rootfs/etc/nginx/templates/ingress.gtpl new file mode 100644 index 0000000..bf8ee4e --- /dev/null +++ b/jupyterlab/rootfs/etc/nginx/templates/ingress.gtpl @@ -0,0 +1,13 @@ +server { + listen 8099 default_server; + + include /etc/nginx/includes/server_params.conf; + include /etc/nginx/includes/proxy_params.conf; + + location / { + allow 172.30.32.2; + deny all; + + proxy_pass http://backend{{ .entry }}/; + } +} diff --git a/jupyterlab/rootfs/etc/services.d/jupyter/finish b/jupyterlab/rootfs/etc/services.d/jupyter/finish index 060d272..19f374d 100644 --- a/jupyterlab/rootfs/etc/services.d/jupyter/finish +++ b/jupyterlab/rootfs/etc/services.d/jupyter/finish @@ -1,6 +1,6 @@ #!/usr/bin/execlineb -S0 # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab # Take down the S6 supervision tree when the Jupyter daemon fails # ============================================================================== if -n { s6-test $# -ne 0 } diff --git a/jupyterlab/rootfs/etc/services.d/jupyter/run b/jupyterlab/rootfs/etc/services.d/jupyter/run index 632fe44..af98ad8 100644 --- a/jupyterlab/rootfs/etc/services.d/jupyter/run +++ b/jupyterlab/rootfs/etc/services.d/jupyter/run @@ -1,7 +1,7 @@ #!/usr/bin/with-contenv bashio # shellcheck disable=SC2191 # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab # Runs Jupyter # ============================================================================== declare -a options diff --git a/jupyterlab/rootfs/etc/services.d/nginx/finish b/jupyterlab/rootfs/etc/services.d/nginx/finish index 7c06f65..d162cc1 100644 --- a/jupyterlab/rootfs/etc/services.d/nginx/finish +++ b/jupyterlab/rootfs/etc/services.d/nginx/finish @@ -1,6 +1,6 @@ #!/usr/bin/execlineb -S0 # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab # Take down the S6 supervision tree when Nginx fails # ============================================================================== if -n { s6-test $# -ne 0 } diff --git a/jupyterlab/rootfs/etc/services.d/nginx/run b/jupyterlab/rootfs/etc/services.d/nginx/run index 2b44d69..0fd88ef 100644 --- a/jupyterlab/rootfs/etc/services.d/nginx/run +++ b/jupyterlab/rootfs/etc/services.d/nginx/run @@ -1,16 +1,11 @@ #!/usr/bin/with-contenv bashio # ============================================================================== -# Home Assistant Community Add-on: JupyterLab Lite +# Home Assistant Community Add-on: JupyterLab # Runs the Nginx daemon # ============================================================================== # Wait for JupyterLab to become available -s6-svwait -u -t 5000 /var/run/s6/services/jupyter -timeout 15 \ - bash -c \ - 'until echo > /dev/tcp/localhost/28459 ; do sleep 0.5; done' \ - > /dev/null 2>&1 +bashio::net.wait_for 28459 bashio::log.info "Starting NGinx..." - -exec nginx -g "daemon off;" +exec nginx