From 8ce23f3a181dd3e30b8741ff2badb309d703d898 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Mon, 27 Dec 2021 14:29:05 +0100 Subject: [PATCH] initial version --- firefly_iii/CHANGELOG.md | 1 + firefly_iii/Dockerfile | 80 ++++++++++++++ firefly_iii/Readme.md | 68 ++++++++++++ firefly_iii/apparmor.txt | 48 +++++++++ firefly_iii/build.json | 8 ++ firefly_iii/config.json | 37 +++++++ firefly_iii/icon.png | Bin 0 -> 11275 bytes firefly_iii/logo.png | Bin 0 -> 11275 bytes firefly_iii/rootfs/entrypoint.sh | 16 +++ .../scripts/00-aaa_dockerfile_backup.sh | 18 ++++ firefly_iii/rootfs/scripts/00-banner.sh | 39 +++++++ firefly_iii/rootfs/scripts/00-global_var.sh | 33 ++++++ firefly_iii/rootfs/scripts/20-folders.sh | 12 +++ firefly_iii/rootfs/scripts/92-config_yaml.sh | 102 ++++++++++++++++++ firefly_iii/rootfs/scripts/99-run.sh | 68 ++++++++++++ 15 files changed, 530 insertions(+) create mode 100644 firefly_iii/CHANGELOG.md create mode 100644 firefly_iii/Dockerfile create mode 100644 firefly_iii/Readme.md create mode 100644 firefly_iii/apparmor.txt create mode 100644 firefly_iii/build.json create mode 100644 firefly_iii/config.json create mode 100644 firefly_iii/icon.png create mode 100644 firefly_iii/logo.png create mode 100644 firefly_iii/rootfs/entrypoint.sh create mode 100644 firefly_iii/rootfs/scripts/00-aaa_dockerfile_backup.sh create mode 100644 firefly_iii/rootfs/scripts/00-banner.sh create mode 100644 firefly_iii/rootfs/scripts/00-global_var.sh create mode 100644 firefly_iii/rootfs/scripts/20-folders.sh create mode 100644 firefly_iii/rootfs/scripts/92-config_yaml.sh create mode 100644 firefly_iii/rootfs/scripts/99-run.sh diff --git a/firefly_iii/CHANGELOG.md b/firefly_iii/CHANGELOG.md new file mode 100644 index 000000000..66f7e8b76 --- /dev/null +++ b/firefly_iii/CHANGELOG.md @@ -0,0 +1 @@ +- Initial release diff --git a/firefly_iii/Dockerfile b/firefly_iii/Dockerfile new file mode 100644 index 000000000..783ee21a1 --- /dev/null +++ b/firefly_iii/Dockerfile @@ -0,0 +1,80 @@ +#==========================# +# ALEXBELGIUM'S DOCKERFILE # +#==========================# +#           _.------. +#       _.-`    ('>.-`"""-. +# '.--'`       _'`   _ .--.) +#    -'         '-.-';`   ` +#    ' -      _.'  ``'--.  +#        '---`    .-'""` +#               /` + +################# +# 1 Build Image # +################# + +ARG BUILD_FROM +ARG BUILD_VERSION +FROM ${BUILD_FROM} + +################## +# 2 Modify Image # +################## + +ENV DB_CONNECTION=sqlite + +################## +# 3 Install apps # +################## + +# Copy local files +COPY rootfs/ / + +# Manual apps +ENV PACKAGES="" + +# 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); 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); fi && \ + curl -L -f -s "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/zzz_templates/automatic_packages.sh" --output /automatic_packages.sh && \ + chmod 777 /automatic_packages.sh && \ + /automatic_packages.sh "${PACKAGES:-}" && \ + rm /automatic_packages.sh || printf '%s\n' "${PACKAGES:-}" > /ENVFILE + +################ +# 4 Entrypoint # +################ + +RUN chmod 777 /entrypoint.sh +ENTRYPOINT [ "/usr/bin/env" ] +CMD [ "/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 +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/firefly_iii/Readme.md b/firefly_iii/Readme.md new file mode 100644 index 000000000..0119b880a --- /dev/null +++ b/firefly_iii/Readme.md @@ -0,0 +1,68 @@ +# Home assistant add-on: fireflyiii + +[![Donate][donation-badge]](https://www.buymeacoffee.com/alexbelgium) + +[donation-badge]: https://img.shields.io/badge/Buy%20me%20a%20coffee-%23d32f2f?logo=buy-me-a-coffee&style=flat&logoColor=white + +![Supports + Architecture][aarch64-shield] ![Supports amd64 Architecture][amd64-shield] ![Supports armhf Architecture][armhf-shield] ![Supports armv7 Architecture][armv7-shield] +![Supports smb mounts][smb-shield] + +_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 + +[fireflyiii](https://www.firefly-iii.org) a personal finances manager. +This addon is based on the docker image https://hub.docker.com/r/fireflyiii/core + +## Installation + +The installation of this add-on is pretty straightforward and not different in comparison to installing any other add-on. + +1. Add my add-ons repository to your home assistant instance (in supervisor addons store at top right, or click button below if you have configured my HA) + [![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) +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 and adapt the software options + +## Configuration + +Options can be configured through two ways : + +- Addon options + +```yaml +"CONFIG_LOCATION": location of the config.yaml file that allows setting additional environment variables (see below) +"DB_CONNECTION": "list(sqlite_internal|mariadb_addon|mysql|pgsql)" # Defines if you are using the built in sqlite ; the mariadb addon ; or a remote database +"DB_HOST": "CHANGEME" # only needed if using a remote database +"DB_PORT": "CHANGEME" # only needed if using a remote database +"DB_DATABASE": "CHANGEME" # only needed if using a remote database +"DB_USERNAME": "CHANGEME" # only needed if using a remote database +"DB_PASSWORD": "CHANGEME" # only needed if using a remote database +``` + +- Config.yaml + +Configuration is done by customizing the config.yaml in the location defined in your addon options + +The complete list of options can be seen here : https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/.env.example + +## Support + +Create an issue on github + +## Illustration + +![illustration](https://raw.githubusercontent.com/firefly-iii/firefly-iii/develop/.github/assets/img/imac-complete.png) + +[repository]: https://github.com/alexbelgium/hassio-addons +[smb-shield]: https://img.shields.io/badge/smb-yes-green.svg +[aarch64-shield]: https://img.shields.io/badge/aarch64-yes-green.svg +[amd64-shield]: https://img.shields.io/badge/amd64-yes-green.svg +[armhf-shield]: https://img.shields.io/badge/armhf-yes-green.svg +[armv7-shield]: https://img.shields.io/badge/armv7-yes-green.svg diff --git a/firefly_iii/apparmor.txt b/firefly_iii/apparmor.txt new file mode 100644 index 000000000..64fe0c328 --- /dev/null +++ b/firefly_iii/apparmor.txt @@ -0,0 +1,48 @@ +#include + +profile fireflyiii_addon flags=(attach_disconnected,mediate_deleted) { + #include + + capability, + file, + mount, + umount, + remount, + + capability setgid, + capability setuid, + capability sys_admin, + capability dac_read_search, + # capability dac_override, + # 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, + + # 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/firefly_iii/build.json b/firefly_iii/build.json new file mode 100644 index 000000000..b46b44d2d --- /dev/null +++ b/firefly_iii/build.json @@ -0,0 +1,8 @@ +{ + "build_from": { + "armhf": "fireflyiii/core:latest", + "armv7": "fireflyiii/core:latest", + "aarch64": "fireflyiii/core:latest", + "amd64": "fireflyiii/core:latest" + } +} diff --git a/firefly_iii/config.json b/firefly_iii/config.json new file mode 100644 index 000000000..c9de829cc --- /dev/null +++ b/firefly_iii/config.json @@ -0,0 +1,37 @@ +{ + "apparmor": true, + "arch": ["aarch64", "amd64", "armv7", "armhf"], + "boot": "auto", + "description": "A free and open source personal finance manager", + "devices": [], + "environment": { + "TRUSTED_PROXIES": "**" + }, + "map": ["config:rw", "share:rw", "ssl"], + "name": "fireflyiii", + "options": { + "DB_CONNECTION": "sqlite", + "CONFIG_LOCATION": "/config/addons_config/fireflyiii/config.yaml" + }, + "ports": { + "80/tcp": 3473 + }, + "ports_description": { + "80/tcp": "web interface" + }, + "schema": { + "CONFIG_LOCATION": "str", + "DB_CONNECTION": "list(sqlite|mariadb_addon|remotedb)", + "DB_HOST": "str?", + "DB_PORT": "str?", + "DB_DATABASE": "str?", + "DB_USERNAME": "str?", + "DB_PASSWORD": "str?" + }, + "slug": "fireflyiii", + "services": ["mysql:want"], + "upstream": "5.6.7", + "url": "https://github.com/alexbelgium/hassio-addons", + "version": "5.6.7", + "webui": "[PROTO:ssl]://[HOST]:[PORT:80]" +} diff --git a/firefly_iii/icon.png b/firefly_iii/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..af3334c9cee500ecc8dd1d606928e93b991fcfb8 GIT binary patch literal 11275 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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); 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); fi && + curl -L -f -s "https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/zzz_templates/automatic_packages.sh" --output /automatic_packages.sh && + chmod 777 /automatic_packages.sh && + eval /./automatic_packages.sh "$PACKAGES" && + rm /automatic_packages.sh + ) >/dev/null + +fi diff --git a/firefly_iii/rootfs/scripts/00-banner.sh b/firefly_iii/rootfs/scripts/00-banner.sh new file mode 100644 index 000000000..0ac294e9a --- /dev/null +++ b/firefly_iii/rootfs/scripts/00-banner.sh @@ -0,0 +1,39 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Displays a simple add-on banner on startup +# ============================================================================== + +if bashio::supervisor.ping; then + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue " Add-on: $(bashio::addon.name)" + bashio::log.blue " $(bashio::addon.description)" + bashio::log.blue \ + '-----------------------------------------------------------' + + bashio::log.blue " Add-on version: $(bashio::addon.version)" + if bashio::var.true "$(bashio::addon.update_available)"; then + bashio::log.magenta ' There is an update available for this add-on!' + bashio::log.magenta \ + " Latest add-on version: $(bashio::addon.version_latest)" + bashio::log.magenta ' Please consider upgrading as soon as possible.' + else + bashio::log.green ' You are running the latest version of this add-on.' + fi + + bashio::log.blue " System: $(bashio::info.operating_system)" \ + " ($(bashio::info.arch) / $(bashio::info.machine))" + bashio::log.blue " Home Assistant Core: $(bashio::info.homeassistant)" + bashio::log.blue " Home Assistant Supervisor: $(bashio::info.supervisor)" + + bashio::log.blue \ + '-----------------------------------------------------------' + bashio::log.blue \ + ' Please, share the above information when looking for help' + bashio::log.blue \ + ' or support in, e.g., GitHub, forums' + bashio::log.green \ + ' https://github.com/alexbelgium/hassio-addons' + bashio::log.blue \ + '-----------------------------------------------------------' +fi diff --git a/firefly_iii/rootfs/scripts/00-global_var.sh b/firefly_iii/rootfs/scripts/00-global_var.sh new file mode 100644 index 000000000..e88ad363a --- /dev/null +++ b/firefly_iii/rootfs/scripts/00-global_var.sh @@ -0,0 +1,33 @@ +#!/usr/bin/with-contenv bashio + +################################### +# Export all addon options as env # +################################### + +# For all keys in options.json +JSONSOURCE="/data/options.json" + +# Export keys as env variables +# echo "All addon options were exported as variables" +mapfile -t arr < <(jq -r 'keys[]' ${JSONSOURCE}) +for KEYS in ${arr[@]}; do + # export key + VALUE=$(jq .$KEYS ${JSONSOURCE}) + line="${KEYS}=${VALUE//[\"\']/}" + # Use locally + if ! bashio::config.false "verbose"; then bashio::log.blue "$line"; fi + export $line + # Export the variable to run scripts + line="${KEYS}=${VALUE//[\"\']/} &>/dev/null" + sed -i "1a export $line" /etc/services.d/*/*run* 2>/dev/null || sed -i "1a export $line" /scripts/*run* +done + +################ +# Set timezone # +################ +if [ ! -z "TZ" ] && [ -f /etc/localtime ]; then + if [ -f /usr/share/zoneinfo/$TZ ]; then + echo "Timezone set from $(cat /etc/timezone) to $TZ" + ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >/etc/timezone + fi +fi diff --git a/firefly_iii/rootfs/scripts/20-folders.sh b/firefly_iii/rootfs/scripts/20-folders.sh new file mode 100644 index 000000000..9d4bc21b6 --- /dev/null +++ b/firefly_iii/rootfs/scripts/20-folders.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bashio + +echo "Connecting database to /config/addons_config/firefly_iii" + +# Create directory +mkdir -p /config/addons_config/firefly_iii + +# Make sure permissions are right +chown $(id -u):$(id -g) /config/addons_config/firefly_iii + +# Make symlink +ln -snf /var/www/html/storage /config/addons_config/firefly_iii diff --git a/firefly_iii/rootfs/scripts/92-config_yaml.sh b/firefly_iii/rootfs/scripts/92-config_yaml.sh new file mode 100644 index 000000000..97a89cbaa --- /dev/null +++ b/firefly_iii/rootfs/scripts/92-config_yaml.sh @@ -0,0 +1,102 @@ +#!/usr/bin/with-contenv bashio + +################## +# INITIALIZATION # +################## + +# Where is the config +CONFIGSOURCE=$(bashio::config "CONFIG_LOCATION") + +# Check if config file is there, or create one from template +if [ -f $CONFIGSOURCE ]; then + echo "Using config file found in $CONFIGSOURCE" +else + echo "No config file, creating one from template" + # Create folder + mkdir -p "$(dirname "${CONFIGSOURCE}")" + # Placing template in config + if [ -f /templates/config.yaml ]; then + # Use available template + cp /templates/config.yaml "$(dirname "${CONFIGSOURCE}")" + else + # Download template + TEMPLATESOURCE="https://raw.githubusercontent.com/alexbelgium/hassio-addons/master/zzz_templates/config.template" + curl -L -f -s $TEMPLATESOURCE --output $CONFIGSOURCE + fi + # Need to restart + bashio::log.fatal "Config file not found, creating a new one. Please customize the file in $CONFIGSOURCE before restarting." + # bashio::exit.nok +fi + +# Check if yaml is valid +EXIT_CODE=0 +yamllint -d relaxed --no-warnings $CONFIGSOURCE &>ERROR || EXIT_CODE=$? +if [ $EXIT_CODE = 0 ]; then + echo "Config file is a valid yaml" +else + cat ERROR + bashio::log.fatal "Config file has an invalid yaml format. Please check the file in $CONFIGSOURCE. Errors list above." + # bashio::exit.nok +fi + +# Export all yaml entries as env variables +# Helper function +function parse_yaml { + local prefix=$2 || local prefix="" + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @ | tr @ '\034') + sed -ne "s|^\($s\):|\1|" \ + -e "s| #.*$||g" \ + -e "s|#.*$||g" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | + awk -F$fs '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]}} + if (length($3) > 0) { + vn=""; for (i=0; i/tmpfile +while IFS= read -r line; do + # Clean output + line=${line//[\"\']/} + # Check if secret + if [[ "${line}" == *'!secret '* ]]; then + echo "secret detected" + secret=${line#*secret } + # Check if single match + secretnum=$(sed -n "/$secret:/=" /config/secrets.yaml) + [[ $(echo $secretnum) == *' '* ]] && bashio::exit.nok "There are multiple matches for your password name. Please check your secrets.yaml file" + # Get text + secret=$(sed -n "/$secret:/p" /config/secrets.yaml) + secret=${secret#*: } + line="${line%%=*}=$secret" + fi + # Data validation + if [[ $line =~ ^.+[=].+$ ]]; then + export $line + # Export the variable + sed -i "1a export $line" /etc/services.d/*/*run* 2>/dev/null || true + sed -i "1a export $line" /scripts/*run* 2>/dev/null || true + # Show in log + if ! bashio::config.false "verbose";then bashio::log.blue "$line"; fi + else + bashio::exit.nok "$line does not follow the correct structure. Please check your yaml file." + fi +done <"/tmpfile" + +# Test mode +TZ=$(bashio::config "TZ") +if [ $TZ = "test" ]; then + echo "secret mode found, launching script in /config/test.sh" + cd /config + chmod 777 test.sh + ./test.sh +fi diff --git a/firefly_iii/rootfs/scripts/99-run.sh b/firefly_iii/rootfs/scripts/99-run.sh new file mode 100644 index 000000000..9e6df038d --- /dev/null +++ b/firefly_iii/rootfs/scripts/99-run.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bashio + +bashio::log.info "Launching app" + +# Create API key if needed +if ! bashio::fs.file_exists "/data/firefly/appkey.txt"; then + #Command fails without appkey set, this won't be used again + export APP_KEY=SomeRandomStringOf32CharsExactly + bashio::log.info "Generating app key" + key=$(php /var/www/firefly/artisan key:generate --show) + echo "${key}" >/data/firefly/appkey.txt + bashio::log.info "App Key generated: ${key}" +fi + +# Define database +case $(bashio::config 'DB_CONNECTION') in + +# Use sqlite +sqlite_internal) + bashio::log.info "Using built in sqlite" + touch ./storage/database/database.sqlite + php artisan migrate --seed + php artisan firefly-iii:upgrade-database + ;; + +# Use MariaDB +mariadb_addon) + bashio::log.info "Using MariaDB addon. Requirements : running MariaDB addon" + if ! bashio::services.available 'mysql'; then + bashio::log.fatal \ + "Local database access should be provided by the MariaDB addon" + bashio::exit.nok \ + "Please ensure it is installed and started" + fi + + host=$(bashio::services "mysql" "host") + password=$(bashio::services "mysql" "password") + port=$(bashio::services "mysql" "port") + username=$(bashio::services "mysql" "username") + + bashio::log.warning "Firefly-iii is using the Maria DB addon" + bashio::log.warning "Please ensure this is included in your backups" + bashio::log.warning "Uninstalling the MariaDB addon will remove any data" + + bashio::log.info "Creating database for Firefly-iii if required" + mysql \ + -u "${username}" -p"${password}" \ + -h "${host}" -P "${port}" \ + -e "CREATE DATABASE IF NOT EXISTS \`firefly\` ;" + ;; + +# Use remote +*) + bashio::log.info "Using remote database. Requirement : filling all addon options fields" + for conditions in "DB_HOST" "DB_PORT" "DB_DATABASE" "DB_USERNAME" "DB_PASSWORD"; do + if ! bashio::config.has_value "$conditions"; then + bashio::exit.nok "Remote database has been specified but $conditions is not defined in addon options" + fi + done + ;; + +esac + +############## +# LAUNCH APP # +############## + +/./usr/local/bin/entrypoint.sh