diff --git a/filebrowser_quantum/CHANGELOG.md b/filebrowser_quantum/CHANGELOG.md new file mode 100644 index 000000000..27cd5bec0 --- /dev/null +++ b/filebrowser_quantum/CHANGELOG.md @@ -0,0 +1,4 @@ +# Changelog + +## 1.1.0 +- Initial FileBrowser Quantum add-on. diff --git a/filebrowser_quantum/Dockerfile b/filebrowser_quantum/Dockerfile new file mode 100644 index 000000000..7b34b3a03 --- /dev/null +++ b/filebrowser_quantum/Dockerfile @@ -0,0 +1,142 @@ +#============================# +# ALEXBELGIUM'S DOCKERFILE # +#============================# +# _.------. +# _.-` ('>.-`"""-. +# '.--'` _'` _ .--.) +# -' '-.-';` ` +# ' - _.' ``'--. +# '---` .-'""` +# /` +#=== Home Assistant Addon ===# + +################# +# 1 Build Image # +################# + +ARG BUILD_FROM +ARG BUILD_VERSION +FROM ${BUILD_FROM} + +################## +# 2 Modify Image # +################## + +# Set S6 wait time +ENV S6_CMD_WAIT_FOR_SERVICES=1 \ + S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \ + S6_SERVICES_GRACETIME=0 + +USER root + +################## +# 3 Install apps # +################## + +# Add rootfs +COPY rootfs/ / + +# Uses /bin for compatibility purposes +# hadolint ignore=DL4005 +RUN if [ ! -f /bin/sh ] && [ -f /usr/bin/sh ]; then ln -s /usr/bin/sh /bin/sh; fi && \ + if [ ! -f /bin/bash ] && [ -f /usr/bin/bash ]; then ln -s /usr/bin/bash /bin/bash; fi + +# Modules +ARG MODULES="00-banner.sh 01-custom_script.sh 00-local_mounts.sh 00-smb_mounts.sh" + +# Automatic modules download +ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_automodules.sh" "/ha_automodules.sh" +RUN chmod 744 /ha_automodules.sh && /ha_automodules.sh "$MODULES" && rm /ha_automodules.sh + +# Manual apps +ENV PACKAGES="bind-tools \ + nginx \ + python3" + +# Automatic apps & bashio +ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_autoapps.sh" "/ha_autoapps.sh" +RUN chmod 744 /ha_autoapps.sh && /ha_autoapps.sh "$PACKAGES" && rm /ha_autoapps.sh + +################ +# 4 Entrypoint # +################ + +# Add entrypoint +# ENV S6_STAGE2_HOOK=/ha_entrypoint.sh +ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_entrypoint.sh" "/ha_entrypoint.sh" + +# Entrypoint modifications +ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/ha_entrypoint_modif.sh" "/ha_entrypoint_modif.sh" +RUN chmod 777 /ha_entrypoint.sh /ha_entrypoint_modif.sh && /ha_entrypoint_modif.sh && rm /ha_entrypoint_modif.sh + +# Standalone bashio command +ADD "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.templates/bashio-standalone.sh" "/.bashio-standalone.sh" +RUN chmod 777 /.bashio-standalone.sh + +RUN sed -i "s|/command/with-contenv|/usr/bin/env|g" "/ha_entrypoint.sh" + +VOLUME [ "/data" ] +WORKDIR / + +ENTRYPOINT [ "/usr/bin/env" ] +CMD [ "/ha_entrypoint.sh" ] + +############ +# 5 Labels # +############ + +ARG BUILD_ARCH +ARG BUILD_DATE +ARG BUILD_DESCRIPTION +ARG BUILD_NAME +ARG BUILD_REF +ARG BUILD_REPOSITORY +ARG BUILD_VERSION +ENV BUILD_VERSION="${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} + +################# +# 6 Healthcheck # +################# + +# Avoid spamming logs +# hadolint ignore=SC2016 +RUN \ + # Handle Apache configuration + if [ -d /etc/apache2/sites-available ]; then \ + for file in /etc/apache2/sites-*/*.conf; do \ + sed -i '/ /etc/nginx/nginx.conf.new && \ + mv /etc/nginx/nginx.conf.new /etc/nginx/nginx.conf; \ + fi + +ENV HEALTH_PORT="8080" \ + HEALTH_URL="" +HEALTHCHECK \ + --interval=5s \ + --retries=5 \ + --start-period=30s \ + --timeout=25s \ + CMD curl -A "HealthCheck: Docker/1.0" -s -f "http://127.0.0.1:${HEALTH_PORT}${HEALTH_URL}" &>/dev/null || curl -k --fail "https://127.0.0.1:${HEALTH_PORT}${HEALTH_URL}" &>/dev/null || exit 1 diff --git a/filebrowser_quantum/README.md b/filebrowser_quantum/README.md new file mode 100644 index 000000000..761360141 --- /dev/null +++ b/filebrowser_quantum/README.md @@ -0,0 +1,152 @@ +# Home assistant add-on: FileBrowser Quantum + + +I maintain this and other Home Assistant add-ons in my free time: keeping up with upstream changes, HA changes, and testing on real hardware takes a lot of time (and some money). I use around 5-10 of my >110 addons so regularly I install test machines (and purchase some test services such as vpn) that I don't use myself to troubleshoot and improve the addons + +If this add-on saves you time or makes your setup easier, I would be very grateful for your support! + +[![Buy me a coffee][donation-badge]](https://www.buymeacoffee.com/alexbelgium) +[![Donate via PayPal][paypal-badge]](https://www.paypal.com/donate/?hosted_button_id=DZFULJZTP3UQA) + +## Addon informations + +![Version](https://img.shields.io/badge/dynamic/yaml?label=Version&query=%24.version&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffilebrowser_quantum%2Fconfig.yaml) +![Ingress](https://img.shields.io/badge/dynamic/yaml?label=Ingress&query=%24.ingress&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffilebrowser_quantum%2Fconfig.yaml) +![Arch](https://img.shields.io/badge/dynamic/yaml?color=success&label=Arch&query=%24.arch&url=https%3A%2F%2Fraw.githubusercontent.com%2Falexbelgium%2Fhassio-addons%2Fmaster%2Ffilebrowser_quantum%2Fconfig.yaml) + +[![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://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/weekly-supelinter.yaml?label=Lint%20code%20base)](https://github.com/alexbelgium/hassio-addons/actions/workflows/weekly-supelinter.yaml) +[![Builder](https://img.shields.io/github/actions/workflow/status/alexbelgium/hassio-addons/onpush_builder.yaml?label=Builder)](https://github.com/alexbelgium/hassio-addons/actions/workflows/onpush_builder.yaml) + +[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white +[paypal-badge]: https://img.shields.io/badge/Donate%20via%20PayPal-0070BA?logo=paypal&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://raw.githubusercontent.com/alexbelgium/hassio-addons/master/.github/stars2.svg)](https://github.com/alexbelgium/hassio-addons/stargazers) + +## About + +FileBrowser Quantum is a modern, responsive, multi-source file manager with realtime indexing, advanced sharing, and expanded authentication options (password, proxy, OIDC, or no-auth). It is a major fork of the original Filebrowser project, designed for faster browsing and richer previews. + +This addon is based on the [docker image](https://hub.docker.com/r/gtstef/filebrowser) from the FileBrowser Quantum project. + +## Installation + +The installation of this add-on is pretty straightforward and not different in +comparison to installing any other Home Assistant add-on. + +1. [Add my Home Assistant add-ons repository][repository] to your Home Assistant instance. +1. Install this add-on. +1. Click the `Save` button to store your configuration. +1. Start the add-on. +1. Check the logs of the add-on to see if everything went well. +1. Access the web UI through the sidebar or at `:8071`. + +## Configuration + +The web UI can be found at `:8071` or through the Home Assistant sidebar when using Ingress. + +**Default credentials:** +- Username: `admin` +- Password: `admin` + +**Important:** Change the default credentials immediately after first login for security. + +### Options + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `ssl` | bool | `false` | Enable HTTPS for web interface | +| `certfile` | str | `fullchain.pem` | SSL certificate file (in `/ssl/`) | +| `keyfile` | str | `privkey.pem` | SSL private key file (in `/ssl/`) | +| `auth_method` | list | `password` | Authentication method (`password`, `noauth`, `proxy`, `oidc`) | +| `admin_username` | str | `admin` | Admin username for initial setup | +| `admin_password` | str | `admin` | Admin password for initial setup | +| `token_expiration_hours` | int | `2` | Auth session token lifetime | +| `password_min_length` | int | `5` | Minimum password length for password auth | +| `password_signup` | bool | `false` | Allow signup on login page (password auth) | +| `password_enforced_otp` | bool | `false` | Enforce OTP for password users | +| `proxy_auth_header` | str | _(optional)_ | Header name for proxy auth | +| `proxy_auth_create_user` | bool | `false` | Auto-create users with proxy auth | +| `proxy_auth_logout_redirect_url` | str | _(optional)_ | Logout redirect URL for proxy auth | +| `oidc_client_id` | str | _(optional)_ | OIDC client ID | +| `oidc_client_secret` | str | _(optional)_ | OIDC client secret | +| `oidc_issuer_url` | str | _(optional)_ | OIDC issuer URL | +| `oidc_scopes` | str | _(optional)_ | OIDC scopes (space-separated) | +| `oidc_user_identifier` | str | _(optional)_ | OIDC user identifier claim | +| `oidc_admin_group` | str | _(optional)_ | OIDC admin group | +| `oidc_groups_claim` | str | _(optional)_ | OIDC groups claim | +| `oidc_logout_redirect_url` | str | _(optional)_ | OIDC logout redirect URL | +| `oidc_create_user` | bool | `false` | Auto-create users with OIDC | +| `oidc_disable_verify_tls` | bool | `false` | Disable TLS verification for OIDC | +| `base_url` | str | _(optional)_ | Base URL override (defaults to ingress path) | +| `external_url` | str | _(optional)_ | External URL used for share links | +| `internal_url` | str | _(optional)_ | Internal URL used for integrations | +| `disable_update_check` | bool | `false` | Disable update checking | +| `disable_previews` | bool | `false` | Disable all previews | +| `disable_preview_resize` | bool | `false` | Disable preview resizing | +| `disable_type_detection_by_header` | bool | `false` | Disable type detection by header | +| `cache_dir_cleanup` | bool | `true` | Automatically clean cache directory | +| `max_archive_size_gb` | int | `0` | Max archive size in GB (0 = default) | +| `log_levels` | str | `info|warning|error` | Log levels configuration | +| `sources` | list | _(see example)_ | File sources to expose | +| `localdisks` | str | _(optional)_ | Local drives to mount (e.g., `sda1,sdb1,MYNAS`) | +| `networkdisks` | str | _(optional)_ | SMB shares to mount (e.g., `//SERVER/SHARE`) | +| `cifsusername` | str | _(optional)_ | SMB username for network shares | +| `cifspassword` | str | _(optional)_ | SMB password for network shares | +| `cifsdomain` | str | _(optional)_ | SMB domain for network shares | + +### Example Configuration + +```yaml +ssl: true +certfile: "fullchain.pem" +keyfile: "privkey.pem" +auth_method: password +admin_username: "admin" +admin_password: "supersecret" +password_min_length: 8 +sources: + - path: "/share" + name: "Share" + default_enabled: true + default_user_scope: "/" + create_user_dir: false + disable_indexing: false + deny_by_default: false + private: false +``` + +## Setup + +1. Start the add-on and wait for it to initialize. +1. Access the web interface through the Home Assistant sidebar or at `:8071`. +1. Log in using the default credentials: + - Username: `admin` + - Password: `admin` +1. **Important:** Immediately change the default password by clicking on "Settings" > "User Management". +1. Configure additional sources and authentication settings through the add-on options or the web interface. + +### Mounting Drives + +This addon supports mounting both local drives and remote SMB shares: + +- **Local drives**: See [Mounting Local Drives in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Mounting-Local-Drives-in-Addons) +- **Remote shares**: See [Mounting Remote Shares in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Mounting-remote-shares-in-Addons) + +### Custom Scripts and Environment Variables + +This addon supports custom scripts and environment variables through the `addon_config` mapping: + +- **Custom scripts**: See [Running Custom Scripts in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Running-custom-scripts-in-Addons) +- **env_vars option**: Use the add-on `env_vars` option to pass extra environment variables (uppercase or lowercase names). See https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2 for details. + +## Support + +Create an issue on GitHub, or ask on the [Home Assistant Community thread](https://community.home-assistant.io/t/home-assistant-addon-filebrowser/282108/3). + +[repository]: https://github.com/alexbelgium/hassio-addons +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg diff --git a/filebrowser_quantum/apparmor.txt b/filebrowser_quantum/apparmor.txt new file mode 100644 index 000000000..98e97c11d --- /dev/null +++ b/filebrowser_quantum/apparmor.txt @@ -0,0 +1,66 @@ +#include + +profile db21ed7f_qbittorrent 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, + network unix dgram, + + capability setgid, + capability setuid, + capability sys_admin, + capability dac_read_search, + # capability dac_override, + # capability sys_rawio, + +# S6-Overlay + /init ix, + /run/{s6,s6-rc*,service}/** ix, + /package/** ix, + /command/** ix, + /run/{,**} rwk, + /dev/tty rw, + /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/fuse mrwkl, + /dev/sda1 mrwkl, + /dev/sdb1 mrwkl, + /dev/nvme0 mrwkl, + /dev/nvme1 mrwkl, + /dev/mmcblk0p1 mrwkl, + /dev/* mrwkl, + /tmp/** mrkwl, + + # 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/filebrowser_quantum/build.json b/filebrowser_quantum/build.json new file mode 100644 index 000000000..7a79b922b --- /dev/null +++ b/filebrowser_quantum/build.json @@ -0,0 +1,6 @@ +{ + "build_from": { + "aarch64": "gtstef/filebrowser:latest", + "amd64": "gtstef/filebrowser:latest" + } +} diff --git a/filebrowser_quantum/config.yaml b/filebrowser_quantum/config.yaml new file mode 100644 index 000000000..37b46bdc6 --- /dev/null +++ b/filebrowser_quantum/config.yaml @@ -0,0 +1,211 @@ +arch: + - aarch64 + - amd64 +description: + FileBrowser Quantum provides a modern, responsive file manager with multi-source + support, advanced authentication options, and realtime indexing for your Home + Assistant files. +devices: + - /dev/dri + - /dev/dri/card0 + - /dev/dri/card1 + - /dev/dri/renderD128 + - /dev/vchiq + - /dev/video10 + - /dev/video11 + - /dev/video12 + - /dev/video13 + - /dev/video14 + - /dev/video15 + - /dev/video16 + - /dev/ttyUSB0 + - /dev/sda + - /dev/sdb + - /dev/sdc + - /dev/sdd + - /dev/sde + - /dev/sdf + - /dev/sdg + - /dev/nvme + - /dev/nvme0 + - /dev/nvme0n1 + - /dev/nvme0n1p1 + - /dev/nvme0n1p2 + - /dev/nvme0n1p3 + - /dev/nvme1n1 + - /dev/nvme1n1p1 + - /dev/nvme1n1p2 + - /dev/nvme1n1p3 + - /dev/nvme2n1 + - /dev/nvme2n1p1 + - /dev/nvme2n1p2 + - /dev/nvme2n3p3 + - /dev/mmcblk + - /dev/fuse + - /dev/sda1 + - /dev/sdb1 + - /dev/sdc1 + - /dev/sdd1 + - /dev/sde1 + - /dev/sdf1 + - /dev/sdg1 + - /dev/sda2 + - /dev/sdb2 + - /dev/sdc2 + - /dev/sdd2 + - /dev/sde2 + - /dev/sdf2 + - /dev/sdg2 + - /dev/sda3 + - /dev/sdb3 + - /dev/sda4 + - /dev/sdb4 + - /dev/sda5 + - /dev/sda6 + - /dev/sda7 + - /dev/sda8 + - /dev/nvme0 + - /dev/nvme1 + - /dev/nvme2 + - /dev/md0 + - /dev/md1 + - /dev/md2 + - /dev/md3 +environment: + FB_BASEURL: /filebrowser_quantum + PGID: "0" + PUID: "0" +homeassistant: 2025.5.0 +image: ghcr.io/alexbelgium/filebrowser_quantum-{arch} +ingress: true +ingress_port: 8071 +ingress_stream: true +map: + - addon_config:rw + - media:rw + - all_addon_configs:rw + - homeassistant_config:rw + - addons:rw + - backup:rw + - share:rw + - ssl:rw +name: FileBrowser Quantum +options: + admin_password: admin + admin_username: admin + auth_method: password + base_url: "" + cache_dir_cleanup: true + disable_preview_resize: false + disable_previews: false + disable_type_detection_by_header: false + disable_update_check: false + env_vars: [] + external_url: "" + internal_url: "" + localdisks: "" + log_levels: info|warning|error + max_archive_size_gb: 0 + networkdisks: "" + password_enforced_otp: false + password_min_length: 5 + password_signup: false + proxy_auth_create_user: false + proxy_auth_header: "" + proxy_auth_logout_redirect_url: "" + sources: + - create_user_dir: false + default_enabled: true + default_user_scope: "/" + deny_by_default: false + disable_indexing: false + ignore_hidden: false + ignore_zero_size_folders: false + indexing_interval_minutes: 0 + name: Root + path: "/" + private: false + ssl: false + certfile: fullchain.pem + keyfile: privkey.pem + token_expiration_hours: 2 + oidc_admin_group: "" + oidc_client_id: "" + oidc_client_secret: "" + oidc_create_user: false + oidc_disable_verify_tls: false + oidc_groups_claim: "" + oidc_issuer_url: "" + oidc_logout_redirect_url: "" + oidc_scopes: "" + oidc_user_identifier: "" + cifsdomain: "" + cifspassword: "" + cifsusername: "" +panel_admin: false +panel_icon: mdi:file-search +ports: + 8080/tcp: 8071 +ports_description: + 8080/tcp: Web UI port +privileged: + - SYS_ADMIN + - DAC_READ_SEARCH +schema: + admin_password: password + admin_username: str + auth_method: list(password|noauth|proxy|oidc) + base_url: str? + cache_dir_cleanup: bool + disable_preview_resize: bool + disable_previews: bool + disable_type_detection_by_header: bool + disable_update_check: bool + env_vars: + - name: match(^[A-Za-z0-9_]+$) + value: str? + external_url: str? + internal_url: str? + localdisks: str? + log_levels: str + max_archive_size_gb: int + networkdisks: str? + password_enforced_otp: bool + password_min_length: int + password_signup: bool + proxy_auth_create_user: bool + proxy_auth_header: str? + proxy_auth_logout_redirect_url: str? + sources: + - create_user_dir: bool? + default_enabled: bool? + default_user_scope: str? + deny_by_default: bool? + disable_indexing: bool? + ignore_hidden: bool? + ignore_zero_size_folders: bool? + indexing_interval_minutes: int? + name: str? + path: str + private: bool? + ssl: bool + certfile: str + keyfile: str + token_expiration_hours: int + oidc_admin_group: str? + oidc_client_id: str? + oidc_client_secret: password? + oidc_create_user: bool + oidc_disable_verify_tls: bool + oidc_groups_claim: str? + oidc_issuer_url: str? + oidc_logout_redirect_url: str? + oidc_scopes: str? + oidc_user_identifier: str? + cifsdomain: str? + cifspassword: str? + cifsusername: str? +slug: filebrowser_quantum +udev: true +url: https://github.com/alexbelgium/hassio-addons +version: "1.1.0" diff --git a/filebrowser_quantum/rootfs/etc/cont-init.d/20-folders.sh b/filebrowser_quantum/rootfs/etc/cont-init.d/20-folders.sh new file mode 100755 index 000000000..a522359ad --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/cont-init.d/20-folders.sh @@ -0,0 +1,42 @@ +#!/usr/bin/with-contenv bashio +# shellcheck shell=bash +set -e + +#################### +# Migrate database # +#################### + +if [ -f /homeassistant/addons_config/filebrowser_quantum/filebrowser_quantum.db ]; then + echo "Moving database to new location /config" + cp -rnf /homeassistant/addons_config/filebrowser_quantum/* /config/ + rm -r /homeassistant/addons_config/filebrowser_quantum +fi + +###################### +# Link addon folders # +###################### + +# Clean symlinks +find /config -maxdepth 1 -type l -delete +if [ -d /homeassistant/addons_config ]; then + find /homeassistant/addons_config -maxdepth 1 -type l -delete +fi + +# Remove erroneous folders +if [ -d /homeassistant ]; then + if [ -d /config/addons_config ]; then + rm -r /config/addons_config + fi + if [ -d /config/addons_autoscripts ]; then + rm -r /config/addons_autoscripts + fi +fi + +# Create symlinks with legacy folders +if [ -d /homeassistant/addons_config ]; then + ln -s /homeassistant/addons_config /config + find /addon_configs/ -maxdepth 1 -mindepth 1 -type d -not -name "*filebrowser_quantum*" -exec ln -s {} /config/addons_config/ \; +fi +if [ -d /homeassistant/addons_autoscripts ]; then + ln -s /homeassistant/addons_autoscripts /config +fi diff --git a/filebrowser_quantum/rootfs/etc/cont-init.d/99-run.sh b/filebrowser_quantum/rootfs/etc/cont-init.d/99-run.sh new file mode 100755 index 000000000..3c44347eb --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/cont-init.d/99-run.sh @@ -0,0 +1,241 @@ +#!/usr/bin/env bashio +# shellcheck shell=bash +set -e + +############ +# TIMEZONE # +############ + +if bashio::config.has_value 'TZ'; then + TIMEZONE=$(bashio::config 'TZ') + bashio::log.info "Setting timezone to $TIMEZONE" + if [ -f /usr/share/zoneinfo/"$TIMEZONE" ]; then + ln -snf /usr/share/zoneinfo/"$TIMEZONE" /etc/localtime + echo "$TIMEZONE" > /etc/timezone + else + bashio::log.fatal "$TIMEZONE not found, are you sure it is a valid timezone?" + fi +fi + +################### +# SSL CONFIG v1.0 # +################### + +bashio::config.require.ssl +if bashio::config.true 'ssl'; then + bashio::log.info "ssl enabled. If webui don't work, disable ssl or check your certificate paths" + #set variables + CERTFILE="/ssl/$(bashio::config 'certfile')" + KEYFILE="/ssl/$(bashio::config 'keyfile')" +else + CERTFILE="" + KEYFILE="" +fi +export CERTFILE KEYFILE + +################# +# NGINX SETTING # +################# + +#declare port +#declare certfile +declare ingress_interface +declare ingress_port +#declare keyfile + +FB_BASEURL=$(bashio::addon.ingress_entry) +export FB_BASEURL + +declare ADDON_PROTOCOL=http +# Generate Ingress configuration +if bashio::config.true 'ssl'; then + ADDON_PROTOCOL=https +fi + +#port=$(bashio::addon.port 80) +ingress_port=$(bashio::addon.ingress_port) +ingress_interface=$(bashio::addon.ip_address) +sed -i "s|%%protocol%%|${ADDON_PROTOCOL}|g" /etc/nginx/servers/ingress.conf +sed -i "s|%%port%%|${ingress_port}|g" /etc/nginx/servers/ingress.conf +sed -i "s|%%interface%%|${ingress_interface}|g" /etc/nginx/servers/ingress.conf +sed -i "s|%%subpath%%|${FB_BASEURL}/|g" /etc/nginx/servers/ingress.conf +mkdir -p /var/log/nginx && touch /var/log/nginx/error.log + +############################ +# FILEBROWSER CONFIGURATION # +############################ + +CONFIG_PATH="/config/filebrowser_quantum.yaml" +mkdir -p /config /cache + +export FILEBROWSER_CONFIG="${CONFIG_PATH}" + +python3 - <<'PY' +import json +import os + +options_path = "/data/options.json" +config_path = os.environ["FILEBROWSER_CONFIG"] + +with open(options_path, "r", encoding="utf-8") as f: + options = json.load(f) + +base_url = options.get("base_url") or os.environ.get("FB_BASEURL") or "/" + +def bool_or_none(value): + return value if isinstance(value, bool) else None + +sources = [] +for source in options.get("sources") or [{"path": "/", "name": "Root", "default_enabled": True}]: + entry = {"path": source.get("path", "/")} + if source.get("name"): + entry["name"] = source["name"] + + source_config = {} + config_mappings = { + "default_enabled": "defaultEnabled", + "default_user_scope": "defaultUserScope", + "create_user_dir": "createUserDir", + "disable_indexing": "disableIndexing", + "deny_by_default": "denyByDefault", + "private": "private", + "indexing_interval_minutes": "indexingIntervalMinutes", + } + for option_key, config_key in config_mappings.items(): + if option_key in source and source[option_key] not in (None, ""): + value = source[option_key] + if option_key == "indexing_interval_minutes" and not value: + continue + source_config[config_key] = value + + conditionals = {} + if "ignore_hidden" in source: + value = bool_or_none(source.get("ignore_hidden")) + if value is not None: + conditionals["ignoreHidden"] = value + if "ignore_zero_size_folders" in source: + value = bool_or_none(source.get("ignore_zero_size_folders")) + if value is not None: + conditionals["ignoreZeroSizeFolders"] = value + if conditionals: + source_config["conditionals"] = conditionals + + if source_config: + entry["config"] = source_config + sources.append(entry) + +server = { + "port": 8080, + "listen": "0.0.0.0", + "baseURL": base_url, + "logging": [ + { + "levels": options.get("log_levels", "info|warning|error"), + } + ], + "database": "/config/filebrowser_quantum.db", + "cacheDir": "/cache", + "cacheDirCleanup": options.get("cache_dir_cleanup", True), + "disablePreviews": options.get("disable_previews", False), + "disablePreviewResize": options.get("disable_preview_resize", False), + "disableTypeDetectionByHeader": options.get("disable_type_detection_by_header", False), + "disableUpdateCheck": options.get("disable_update_check", False), + "sources": sources, +} + +if options.get("external_url"): + server["externalUrl"] = options["external_url"] +if options.get("internal_url"): + server["internalUrl"] = options["internal_url"] +if options.get("max_archive_size_gb"): + server["maxArchiveSize"] = options["max_archive_size_gb"] + +certfile = os.environ.get("CERTFILE") +keyfile = os.environ.get("KEYFILE") +if certfile and keyfile: + server["tlsCert"] = certfile + server["tlsKey"] = keyfile + +auth_method = options.get("auth_method", "password") + +password_config = { + "enabled": auth_method == "password", + "minLength": options.get("password_min_length", 5), + "signup": options.get("password_signup", False), + "enforcedOtp": options.get("password_enforced_otp", False), +} + +proxy_config = { + "enabled": auth_method == "proxy", +} +if options.get("proxy_auth_header"): + proxy_config["header"] = options["proxy_auth_header"] +proxy_config["createUser"] = options.get("proxy_auth_create_user", False) +if options.get("proxy_auth_logout_redirect_url"): + proxy_config["logoutRedirectUrl"] = options["proxy_auth_logout_redirect_url"] + +oidc_config = { + "enabled": auth_method == "oidc", +} +if options.get("oidc_client_id"): + oidc_config["clientId"] = options["oidc_client_id"] +if options.get("oidc_client_secret"): + oidc_config["clientSecret"] = options["oidc_client_secret"] +if options.get("oidc_issuer_url"): + oidc_config["issuerUrl"] = options["oidc_issuer_url"] +if options.get("oidc_scopes"): + oidc_config["scopes"] = options["oidc_scopes"] +if options.get("oidc_user_identifier"): + oidc_config["userIdentifier"] = options["oidc_user_identifier"] +if options.get("oidc_admin_group"): + oidc_config["adminGroup"] = options["oidc_admin_group"] +if options.get("oidc_groups_claim"): + oidc_config["groupsClaim"] = options["oidc_groups_claim"] +if options.get("oidc_logout_redirect_url"): + oidc_config["logoutRedirectUrl"] = options["oidc_logout_redirect_url"] +oidc_config["createUser"] = options.get("oidc_create_user", False) +oidc_config["disableVerifyTLS"] = options.get("oidc_disable_verify_tls", False) + +auth = { + "tokenExpirationHours": options.get("token_expiration_hours", 2), + "adminUsername": options.get("admin_username", "admin"), + "adminPassword": options.get("admin_password", "admin"), + "methods": { + "noauth": auth_method == "noauth", + "password": password_config, + "proxy": proxy_config, + "oidc": oidc_config, + }, +} + +frontend = { + "name": "FileBrowser Quantum", +} + +config = { + "server": server, + "auth": auth, + "frontend": frontend, +} + +with open(config_path, "w", encoding="utf-8") as f: + json.dump(config, f, indent=2) + f.write("\n") +PY + +###################### +# LAUNCH FILEBROWSER # +###################### + +# Prevent conflicts +for folders in /etc/services.d /etc/s6-overlay; do + [[ -d "$folders" ]] && rm -r "$folders" +done + +bashio::log.info "Starting..." + +cd /home/filebrowser +./filebrowser & +bashio::net.wait_for 8080 localhost 900 || true +bashio::log.info "Started !" +nginx || bashio::log.fatal "Nginx failed" diff --git a/filebrowser_quantum/rootfs/etc/nginx/includes/mime.types b/filebrowser_quantum/rootfs/etc/nginx/includes/mime.types new file mode 100644 index 000000000..7c7cdef2d --- /dev/null +++ b/filebrowser_quantum/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/filebrowser_quantum/rootfs/etc/nginx/includes/proxy_params.conf b/filebrowser_quantum/rootfs/etc/nginx/includes/proxy_params.conf new file mode 100644 index 000000000..924ba949e --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/nginx/includes/proxy_params.conf @@ -0,0 +1,16 @@ +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_hide_header X-Frame-Options; +proxy_set_header Accept-Encoding ""; +proxy_set_header Connection $connection_upgrade; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Host $http_host; +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/filebrowser_quantum/rootfs/etc/nginx/includes/resolver.conf b/filebrowser_quantum/rootfs/etc/nginx/includes/resolver.conf new file mode 100644 index 000000000..70f4982b9 --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/nginx/includes/resolver.conf @@ -0,0 +1 @@ +resolver 127.0.0.11 ipv6=off; diff --git a/filebrowser_quantum/rootfs/etc/nginx/includes/server_params.conf b/filebrowser_quantum/rootfs/etc/nginx/includes/server_params.conf new file mode 100644 index 000000000..09c06543e --- /dev/null +++ b/filebrowser_quantum/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/filebrowser_quantum/rootfs/etc/nginx/includes/ssl_params.conf b/filebrowser_quantum/rootfs/etc/nginx/includes/ssl_params.conf new file mode 100644 index 000000000..6f1500599 --- /dev/null +++ b/filebrowser_quantum/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/filebrowser_quantum/rootfs/etc/nginx/includes/upstream.conf b/filebrowser_quantum/rootfs/etc/nginx/includes/upstream.conf new file mode 100644 index 000000000..61ecbf251 --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/nginx/includes/upstream.conf @@ -0,0 +1,3 @@ +upstream backend { + server 127.0.0.1:8080; +} diff --git a/filebrowser_quantum/rootfs/etc/nginx/nginx.conf b/filebrowser_quantum/rootfs/etc/nginx/nginx.conf new file mode 100644 index 000000000..b63c45454 --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/nginx/nginx.conf @@ -0,0 +1,59 @@ + +# 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. +# Disabled for compatibility with CPUs that do not support PCRE JIT, which caused +# crashes on some systems (see issue #1993). +pcre_jit off; + +# 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/filebrowser_quantum/rootfs/etc/nginx/servers/ingress.conf b/filebrowser_quantum/rootfs/etc/nginx/servers/ingress.conf new file mode 100644 index 000000000..f62b732e2 --- /dev/null +++ b/filebrowser_quantum/rootfs/etc/nginx/servers/ingress.conf @@ -0,0 +1,17 @@ +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_connect_timeout 30m; + proxy_send_timeout 30m; + proxy_read_timeout 30m; + proxy_pass %%protocol%%://backend%%subpath%%; + } + +} diff --git a/filebrowser_quantum/updater.json b/filebrowser_quantum/updater.json new file mode 100644 index 000000000..ad483cb75 --- /dev/null +++ b/filebrowser_quantum/updater.json @@ -0,0 +1,10 @@ +{ + "github_beta": "true", + "last_update": "20-12-2025", + "paused": false, + "repository": "alexbelgium/hassio-addons", + "slug": "filebrowser_quantum", + "source": "github", + "upstream_repo": "gtsteffaniak/filebrowser", + "upstream_version": "1.1.0-stable" +}