diff --git a/containers/adguard/adguard.sh b/containers/adguard/adguard.sh deleted file mode 100644 index 91f8104..0000000 --- a/containers/adguard/adguard.sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : AdGuard - DNS based Ad Blocking (c/u/s/r/i): - -installAdguard() -{ - local config_variables="$1" - - if [[ "$adguard" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent adguard; - local app_name=$CFG_ADGUARD_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$adguard" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$adguard" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$adguard" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$adguard" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$adguard" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Completing AdGuardHome initial setup automatically" - echo "" - - # The legacy `$usedport1` variable is no longer populated by the - # current install pipeline; the resolved host port is stored in the - # PORTS_TAG_1 docker-compose tag (format `external:internal`). Pull - # it from there so the curl + URL printout actually point somewhere. - local adguard_compose_file="$containers_dir$app_name/docker-compose.yml" - local adguard_port_pair - adguard_port_pair=$(tagsManagerGetTagContent "$adguard_compose_file" "PORTS_TAG_1") - local adguard_admin_port="${adguard_port_pair%%:*}" - - if [[ -n "$public_ip_v4" && -n "$adguard_admin_port" ]]; then - echo " External : http://$public_ip_v4:$adguard_admin_port/" - fi - if [[ -n "$host_setup" ]]; then - echo " Hostname : http://$host_setup/" - fi - echo "" - - # AdGuardHome ships a setup wizard that normally needs five clicks in a - # browser before the daemon writes its config file. Same wizard is - # exposed as an HTTP API (POST /control/install/configure), so we - # drive it from here and skip the manual interaction. We pre-poll the - # admin endpoint until the container is up, then send the form, then - # let the existing post-install sed edits run against the freshly - # written AdGuardHome.yaml. - local adguard_setup_url="http://127.0.0.1:${adguard_admin_port}" - local adguard_attempts=0 - local adguard_max_attempts=60 - while ((adguard_attempts < adguard_max_attempts)); do - if curl -fsS -o /dev/null --max-time 2 "${adguard_setup_url}/control/status" 2>/dev/null \ - || curl -fsS -o /dev/null --max-time 2 "${adguard_setup_url}/control/install/get_addresses" 2>/dev/null; then - break - fi - sleep 2 - ((adguard_attempts++)) - done - - if ((adguard_attempts >= adguard_max_attempts)); then - isError "AdGuardHome admin endpoint did not respond on $adguard_setup_url within $((adguard_max_attempts * 2))s — open the URL and complete setup manually, then re-run the installer to apply the post-setup tweaks." - else - local adguard_user="${CFG_ADGUARD_USER:-admin}" - local adguard_pass="${CFG_ADGUARD_PASSWORD:-}" - if [[ -z "$adguard_pass" ]]; then - adguard_pass=$(generateRandomPassword) - updateConfigOption "CFG_ADGUARD_PASSWORD" "$adguard_pass" >/dev/null 2>&1 || true - isNotice "Generated a random AdGuardHome admin password and saved it to CFG_ADGUARD_PASSWORD." - fi - - # Internal container ports are fixed (3000 admin, 53 DNS); host - # mapping is what `usedport1` etc. handle. - local adguard_payload - adguard_payload=$(cat </dev/null 2>&1; then - isSuccessful "AdGuardHome admin setup completed automatically (user: $adguard_user)." - else - # 422/403 here typically means setup was already done on a - # previous install; the post-setup tweaks below are still - # safe to run against the existing yaml. - isNotice "AdGuardHome /control/install/configure rejected the request — assuming it's already configured. If this is a fresh install, complete setup manually at $adguard_setup_url." - fi - # Small breather so AdGuardHome finishes flushing AdGuardHome.yaml - # to disk before the sed edits below touch it. - #sleep 3 - fi - - #result=$(sudo sed -i "s/address: 0.0.0.0:80/address: 0.0.0.0:${usedport2}/g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - #checkSuccess "Changing port 80 to $usedport2 for Admin Panel" - - #result=$(sudo sed -i "s/port: 53/port: ${usedport3}/g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - #checkSuccess "Changing port 53 to $usedport3 for DNS Port" - - #result=$(sudo sed -i "s/port_https: 443/port_https: ${usedport4}/g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - #checkSuccess "Changing port 443 to $usedport4 for DNS Port" - - #result=$(sudo sed -i "s/port_dns_over_tls: 853/port_dns_over_tls: ${usedport5}/g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - #checkSuccess "Changing port 853 to $usedport5 for port_dns_over_tls" - - #result=$(sudo sed -i "s/port_dns_over_quic: 853/port_dns_over_quic: ${usedport5}/g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - #checkSuccess "Changing port 853 to $usedport5 for port_dns_over_quic" - - # NOTE: We deliberately do *not* force `tls.enabled: true` here. - # That section configures encrypted DNS (DoT/DoH/DoQ) and AdGuardHome - # crash-loops on startup with `[fatal] creating dns server: parsing - # tls key pair: tls: failed to find any PEM data in certificate input` - # if `enabled: true` is set without a real certificate pair pointed - # at by `certificate_path` / `private_key_path`. The admin user can - # opt into encrypted DNS from Settings → Encryption once they've - # provided a cert. - - if [[ $public == "true" ]]; then - result=$(runFileOp sed -i "s|allow_unencrypted_doh: false|allow_unencrypted_doh: true|g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - checkSuccess "Setting allow_unencrypted_doh to false for Traefik" - fi - - result=$(runFileOp sed -i "s|anonymize_client_ip: false: false|anonymize_client_ip: true|g" "$containers_dir$app_name/conf/AdGuardHome.yaml") - checkSuccess "Setting anonymize_client_ip to true for privacy reasons" - - # Force the admin web bind back to 0.0.0.0:3000 inside the container. - # The docker-compose mapping is `:3000`, so the container - # MUST listen on 3000 internally for the host port to reach it. After - # the install API call AdGuardHome sometimes ends up bound to 0.0.0.0:80 - # (its build-time default) instead of the port we sent — which is - # exactly what causes "unable to connect" on the host port. - local adguard_yaml="$containers_dir$app_name/conf/AdGuardHome.yaml" - if [[ -f "$adguard_yaml" ]]; then - # New schema (v0.107+): single `address: 0.0.0.0:NN` line under `http:`. - runFileOp sed -i 's|^\(\s*address:\s*\)0\.0\.0\.0:[0-9]\+|\10.0.0.0:3000|' "$adguard_yaml" - # Old schema fallback: separate `bind_host:` / `bind_port:` keys. - runFileOp sed -i 's|^\(\s*bind_host:\s*\).*|\10.0.0.0|' "$adguard_yaml" - runFileOp sed -i 's|^\(\s*bind_port:\s*\)[0-9]\+|\13000|' "$adguard_yaml" - checkSuccess "Pinned AdGuardHome admin bind to 0.0.0.0:3000 (matches the compose port mapping)." - fi - - dockerComposeRestart "$app_name"; - - # Health-check after the restart so the user finds out *here* if - # AdGuardHome didn't come back up cleanly, rather than later when - # they try to open the URL and just see "unable to connect". - # - # Drop `-f` and accept any HTTP status code: now that the admin - # account is configured, `/control/status` returns 401 to an - # unauthenticated request — which is fine, it means the server is - # up and answering. We only care whether the connection succeeded - # at all, not what the response body says. `-w '%{http_code}'` - # gives us a 3-digit code on success and an empty string on a - # connection failure / timeout. - local adguard_health_attempts=0 - while ((adguard_health_attempts < 20)); do - local adguard_health_code - adguard_health_code=$(curl -sS -o /dev/null --max-time 2 \ - -w '%{http_code}' "${adguard_setup_url}/control/status" 2>/dev/null) - if [[ "$adguard_health_code" =~ ^[1-5][0-9][0-9]$ ]]; then - isSuccessful "AdGuardHome admin UI is reachable on $adguard_setup_url (HTTP $adguard_health_code)" - break - fi - sleep 1 - ((adguard_health_attempts++)) - done - if ((adguard_health_attempts >= 20)); then - isError "AdGuardHome admin UI did not respond after restart on $adguard_setup_url. Check the container logs (\`docker logs adguard-service\`) and the conf/AdGuardHome.yaml bind address." - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating the WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - # Same final-summary call shape as wireguard / vaultwarden. Pass the - # admin user/password we just configured so the user sees the - # credentials exactly once, at the end of the install. - menuShowFinalMessages "$app_name" "${CFG_ADGUARD_USER:-admin}" "$CFG_ADGUARD_PASSWORD"; - - menu_number=0 - #sleep 3s - cd - fi - adguard=n -} diff --git a/containers/adguard/scripts/adguard_install_hooks.sh b/containers/adguard/scripts/adguard_install_hooks.sh new file mode 100644 index 0000000..ebbc8c0 --- /dev/null +++ b/containers/adguard/scripts/adguard_install_hooks.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# AdGuard Home install hooks — drive the first-boot setup wizard via its +# HTTP API so the admin doesn't have to click through five pages, then +# pin the admin bind back to 0.0.0.0:3000 (matches the compose mapping) +# and health-check the result. + +adguard_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Completing AdGuardHome initial setup automatically" + echo "" + + # The legacy `$usedport1` variable isn't populated by the current + # install pipeline; the resolved host port is stored in the PORTS_TAG_1 + # docker-compose tag (format `external:internal`). Pull it from there + # so the curl + URL printout actually point somewhere real. + local adguard_compose_file="$containers_dir$app_name/docker-compose.yml" + local adguard_port_pair + adguard_port_pair=$(tagsManagerGetTagContent "$adguard_compose_file" "PORTS_TAG_1") + local adguard_admin_port="${adguard_port_pair%%:*}" + + if [[ -n "$public_ip_v4" && -n "$adguard_admin_port" ]]; then + echo " External : http://$public_ip_v4:$adguard_admin_port/" + fi + if [[ -n "$host_setup" ]]; then + echo " Hostname : http://$host_setup/" + fi + echo "" + + # AdGuardHome ships a setup wizard that normally needs five clicks in + # a browser before the daemon writes its config file. Same wizard is + # exposed as an HTTP API (POST /control/install/configure), so drive + # it from here and skip the manual interaction. Pre-poll the admin + # endpoint until the container is up, then send the form, then let + # the post-install sed edits run against the freshly written + # AdGuardHome.yaml. + local adguard_setup_url="http://127.0.0.1:${adguard_admin_port}" + local adguard_attempts=0 + local adguard_max_attempts=60 + while ((adguard_attempts < adguard_max_attempts)); do + if curl -fsS -o /dev/null --max-time 2 "${adguard_setup_url}/control/status" 2>/dev/null \ + || curl -fsS -o /dev/null --max-time 2 "${adguard_setup_url}/control/install/get_addresses" 2>/dev/null; then + break + fi + sleep 2 + ((adguard_attempts++)) + done + + if ((adguard_attempts >= adguard_max_attempts)); then + isError "AdGuardHome admin endpoint did not respond on $adguard_setup_url within $((adguard_max_attempts * 2))s — open the URL and complete setup manually, then re-run the installer to apply the post-setup tweaks." + else + local adguard_user="${CFG_ADGUARD_USER:-admin}" + local adguard_pass="${CFG_ADGUARD_PASSWORD:-}" + if [[ -z "$adguard_pass" ]]; then + adguard_pass=$(generateRandomPassword) + updateConfigOption "CFG_ADGUARD_PASSWORD" "$adguard_pass" >/dev/null 2>&1 || true + isNotice "Generated a random AdGuardHome admin password and saved it to CFG_ADGUARD_PASSWORD." + fi + + # Internal container ports are fixed (3000 admin, 53 DNS); host + # mapping is what `usedport1` etc. handle. + local adguard_payload + adguard_payload=$(cat </dev/null 2>&1; then + isSuccessful "AdGuardHome admin setup completed automatically (user: $adguard_user)." + else + # 422/403 here typically means setup was already done on a + # previous install; the post-setup tweaks below are still + # safe to run against the existing yaml. + isNotice "AdGuardHome /control/install/configure rejected the request — assuming it's already configured. If this is a fresh install, complete setup manually at $adguard_setup_url." + fi + fi + + local result + if [[ "$public" == "true" ]]; then + result=$(runFileOp sed -i "s|allow_unencrypted_doh: false|allow_unencrypted_doh: true|g" "$containers_dir$app_name/conf/AdGuardHome.yaml") + checkSuccess "Setting allow_unencrypted_doh to false for Traefik" + fi + + result=$(runFileOp sed -i "s|anonymize_client_ip: false: false|anonymize_client_ip: true|g" "$containers_dir$app_name/conf/AdGuardHome.yaml") + checkSuccess "Setting anonymize_client_ip to true for privacy reasons" + + # Force the admin web bind back to 0.0.0.0:3000 inside the container. + # The docker-compose mapping is `:3000`, so the container + # MUST listen on 3000 internally for the host port to reach it. After + # the install API call AdGuardHome sometimes ends up bound to + # 0.0.0.0:80 (its build-time default) — exactly what causes "unable + # to connect" on the host port. + local adguard_yaml="$containers_dir$app_name/conf/AdGuardHome.yaml" + if [[ -f "$adguard_yaml" ]]; then + runFileOp sed -i 's|^\(\s*address:\s*\)0\.0\.0\.0:[0-9]\+|\10.0.0.0:3000|' "$adguard_yaml" + runFileOp sed -i 's|^\(\s*bind_host:\s*\).*|\10.0.0.0|' "$adguard_yaml" + runFileOp sed -i 's|^\(\s*bind_port:\s*\)[0-9]\+|\13000|' "$adguard_yaml" + checkSuccess "Pinned AdGuardHome admin bind to 0.0.0.0:3000 (matches the compose port mapping)." + fi + + dockerComposeRestart "$app_name" + + # Drop `-f` and accept any HTTP status code: now that the admin + # account is configured, /control/status returns 401 to an + # unauthenticated request — which is fine, it means the server is up + # and answering. We only care whether the connection succeeded at + # all, not what the response body says. + local adguard_health_attempts=0 + local adguard_health_code + while ((adguard_health_attempts < 20)); do + adguard_health_code=$(curl -sS -o /dev/null --max-time 2 \ + -w '%{http_code}' "${adguard_setup_url}/control/status" 2>/dev/null) + if [[ "$adguard_health_code" =~ ^[1-5][0-9][0-9]$ ]]; then + isSuccessful "AdGuardHome admin UI is reachable on $adguard_setup_url (HTTP $adguard_health_code)" + break + fi + sleep 1 + ((adguard_health_attempts++)) + done + if ((adguard_health_attempts >= 20)); then + isError "AdGuardHome admin UI did not respond after restart on $adguard_setup_url. Check the container logs (\`docker logs adguard-service\`) and the conf/AdGuardHome.yaml bind address." + fi +} + +adguard_install_message_data() +{ + # Echo the admin user + password as space-separated tokens so they + # become $username $password positional args to menuShowFinalMessages. + echo "${CFG_ADGUARD_USER:-admin} $CFG_ADGUARD_PASSWORD" +} diff --git a/containers/authelia/authelia.sh b/containers/authelia/authelia.sh deleted file mode 100755 index e21bfdc..0000000 --- a/containers/authelia/authelia.sh +++ /dev/null @@ -1,208 +0,0 @@ -#!/bin/bash - -# Category : Security -# Description : Authelia - Authentication & SSO (c/u/s/r/i): - -installAuthelia() -{ - local config_variables="$1" - - if [[ "$authelia" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent authelia; - local app_name=$CFG_AUTHELIA_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$authelia" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$authelia" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$authelia" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$authelia" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$authelia" == *[iI]* ]]; then - isHeader "Install $app_name" - - # Pre-flight: bail out before touching any compose/config if the - # global prerequisites aren't met. CFG_AUTHELIA_REQUIRES lists - # what's needed (currently "domain,traefik"); the helper prints a - # clear list of what's missing so the user knows what to fix. - if ! appInstallCheckRequirements "$app_name" "$CFG_AUTHELIA_REQUIRES"; then - authelia=n - return 1 - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - local result=$(copyResource "$app_name" "configuration.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) - checkSuccess "Copying configuration.yml to $containers_dir$app_name/config" - - local result=$(copyResource "$app_name" "users_database.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) - checkSuccess "Copying users_database.yml to $containers_dir$app_name/config" - - local authelia_config_file="$containers_dir$app_name/config/configuration.yml" - runFileOp sed -i "s|AUTHELIA_THEME_PLACEHOLDER|$CFG_AUTHELIA_THEME|g" "$authelia_config_file" - runFileOp sed -i "s|AUTHELIA_DOMAIN_PLACEHOLDER|$domain_full|g" "$authelia_config_file" - runFileOp sed -i "s|AUTHELIA_HOST_PLACEHOLDER|$host_setup|g" "$authelia_config_file" - checkSuccess "Substituting Authelia configuration values (theme=$CFG_AUTHELIA_THEME domain=$domain_full host=$host_setup)" - - local authelia_secrets_dir="$containers_dir$app_name/secrets" - runFileOp mkdir -p "$authelia_secrets_dir" - for secret_name in JWT_SECRET SESSION_SECRET STORAGE_ENCRYPTION_KEY; do - local secret_file="$authelia_secrets_dir/$secret_name" - if [[ ! -s "$secret_file" ]]; then - openssl rand -hex 64 | runFileWrite "$secret_file" - runFileOp chmod 600 "$secret_file" - fi - done - runFileOp chown -R "$docker_install_user":"$docker_install_user" "$authelia_secrets_dir" - checkSuccess "Generated Authelia secrets at $authelia_secrets_dir" - - # Enable Authelia's telemetry/metrics endpoint only when - # CFG_AUTHELIA_MONITORING=true (toggles the libreportal-monitoring - # marker block in configuration.yml). - monitoringToggleAppConfig "$app_name" "config/configuration.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Configuring Authelia admin account" - echo "" - - local authelia_admin_user="${CFG_AUTHELIA_ADMIN_USERNAME:-admin}" - local authelia_admin_pass="${CFG_AUTHELIA_ADMIN_PASSWORD:-authelia}" - local authelia_users_file="$containers_dir$app_name/config/users_database.yml" - local authelia_attempts=0 - while ((authelia_attempts < 30)); do - if runFileOp docker exec authelia-service authelia --version >/dev/null 2>&1; then - break - fi - sleep 2 - ((authelia_attempts++)) - done - - if ((authelia_attempts >= 30)); then - isNotice "Authelia container did not become responsive in time — admin left at default (admin / authelia)." - else - local authelia_hash - authelia_hash=$(runFileOp docker exec authelia-service authelia crypto hash generate argon2 --password "$authelia_admin_pass" 2>/dev/null \ - | grep -oE '\$argon2[^[:space:]]+') - if [[ -z "$authelia_hash" ]]; then - isNotice "Could not generate Authelia password hash — admin left at default (admin / authelia)." - else - runFileWrite "$authelia_users_file" <&1) + checkSuccess "Copying configuration.yml to $containers_dir$app_name/config" + + result=$(copyResource "$app_name" "users_database.yml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) + checkSuccess "Copying users_database.yml to $containers_dir$app_name/config" + + local authelia_config_file="$containers_dir$app_name/config/configuration.yml" + runFileOp sed -i "s|AUTHELIA_THEME_PLACEHOLDER|$CFG_AUTHELIA_THEME|g" "$authelia_config_file" + runFileOp sed -i "s|AUTHELIA_DOMAIN_PLACEHOLDER|$domain_full|g" "$authelia_config_file" + runFileOp sed -i "s|AUTHELIA_HOST_PLACEHOLDER|$host_setup|g" "$authelia_config_file" + checkSuccess "Substituting Authelia configuration values (theme=$CFG_AUTHELIA_THEME domain=$domain_full host=$host_setup)" + + local authelia_secrets_dir="$containers_dir$app_name/secrets" + runFileOp mkdir -p "$authelia_secrets_dir" + local secret_name secret_file + for secret_name in JWT_SECRET SESSION_SECRET STORAGE_ENCRYPTION_KEY; do + secret_file="$authelia_secrets_dir/$secret_name" + if [[ ! -s "$secret_file" ]]; then + openssl rand -hex 64 | runFileWrite "$secret_file" + runFileOp chmod 600 "$secret_file" + fi + done + runFileOp chown -R "$docker_install_user":"$docker_install_user" "$authelia_secrets_dir" + checkSuccess "Generated Authelia secrets at $authelia_secrets_dir" + + # Authelia's metrics block lives in configuration.yml (not the compose), + # so toggle it here. The driver already toggled docker-compose.yml. + monitoringToggleAppConfig "$app_name" "config/configuration.yml" +} + +authelia_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Configuring Authelia admin account" + echo "" + + local authelia_admin_user="${CFG_AUTHELIA_ADMIN_USERNAME:-admin}" + local authelia_admin_pass="${CFG_AUTHELIA_ADMIN_PASSWORD:-authelia}" + local authelia_users_file="$containers_dir$app_name/config/users_database.yml" + local authelia_attempts=0 + while ((authelia_attempts < 30)); do + if runFileOp docker exec authelia-service authelia --version >/dev/null 2>&1; then + break + fi + sleep 2 + ((authelia_attempts++)) + done + + if ((authelia_attempts >= 30)); then + isNotice "Authelia container did not become responsive in time — admin left at default (admin / authelia)." + return 0 + fi + + local authelia_hash + authelia_hash=$(runFileOp docker exec authelia-service authelia crypto hash generate argon2 --password "$authelia_admin_pass" 2>/dev/null \ + | grep -oE '\$argon2[^[:space:]]+') + if [[ -z "$authelia_hash" ]]; then + isNotice "Could not generate Authelia password hash — admin left at default (admin / authelia)." + return 0 + fi + + runFileWrite "$authelia_users_file" </dev/null) - if [[ "$bookstack_http_code" =~ ^(200|302)$ ]]; then - bookstack_ready=1 - break - fi - sleep 2 - ((bookstack_attempts++)) - done - - if ((bookstack_ready == 0)); then - isNotice "Bookstack did not respond on ${bookstack_probe_url} within $((60 * 2))s — admin account left at upstream defaults." - echo "" - isNotice "Bookstack admin login (default):" - echo "" - echo " Email : admin@admin.com" - echo " Password : password" - echo "" - else - isSuccessful "Bookstack is online (HTTP ${bookstack_http_code})." - - bookstack_create_output=$(runFileOp docker exec \ - -e EZ_BS_NEW_EMAIL="$bookstack_target_email" \ - -e EZ_BS_NEW_PASS="$bookstack_target_pass" \ - bookstack sh -c 'cd /app/www && s6-setuidgid abc php artisan bookstack:create-admin --no-ansi --email="$EZ_BS_NEW_EMAIL" --name=Admin --password="$EZ_BS_NEW_PASS" 2>&1') - bookstack_create_rc=$? - if [[ $bookstack_create_rc -eq 0 ]]; then - isSuccessful "Bookstack admin account created (email: $bookstack_target_email)." - - if [[ "$bookstack_target_email" != "admin@admin.com" ]]; then - runFileOp docker exec -i bookstack php /app/www/artisan tinker --no-ansi >/dev/null 2>&1 <<'PHP' -$c = class_exists('\BookStack\Users\Models\User') ? '\BookStack\Users\Models\User' : '\BookStack\Auth\User'; -optional($c::where('email', 'admin@admin.com')->first())->delete(); -PHP - isSuccessful "Removed seeded admin@admin.com account." - fi - - echo "" - isNotice "Bookstack admin login:" - echo "" - echo " Email : ${bookstack_target_email}" - echo " Password : ${bookstack_target_pass}" - echo "" - else - isNotice "Bookstack admin auto-create failed (exit $bookstack_create_rc). Output:" - echo "$bookstack_create_output" | sed 's/^/ /' - echo "" - isNotice "Falling back to upstream defaults — update from inside Bookstack." - echo "" - isNotice "Bookstack admin login (default):" - echo "" - echo " Email : admin@admin.com" - echo " Password : password" - echo "" - fi - fi - - menu_number=0 - #sleep 3s - cd - fi - bookstack=n -} diff --git a/containers/bookstack/scripts/bookstack_install_hooks.sh b/containers/bookstack/scripts/bookstack_install_hooks.sh new file mode 100644 index 0000000..0b68649 --- /dev/null +++ b/containers/bookstack/scripts/bookstack_install_hooks.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +# Bookstack install hooks — drive the post-start admin account bootstrap. +# Generic installApp driver handles compose / start / db / monitoring; this +# adds the readiness probe + first-admin provisioning the original +# installBookstack() did inline. + +bookstack_install_post_start() +{ + local app_name="$1" + + local bookstack_target_email="${CFG_BOOKSTACK_ADMIN_EMAIL:-admin@admin.com}" + local bookstack_target_pass="${CFG_BOOKSTACK_ADMIN_PASSWORD:-password}" + + local bookstack_compose_file="$containers_dir$app_name/docker-compose.yml" + local bookstack_port_pair + bookstack_port_pair=$(tagsManagerGetTagContent "$bookstack_compose_file" "PORTS_TAG_1") + local bookstack_host_port="${bookstack_port_pair%%:*}" + local bookstack_probe_url="http://127.0.0.1:${bookstack_host_port}/login" + + isNotice "Waiting for Bookstack to come online at ${bookstack_probe_url} ..." + isNotice "This may take up to 20 seconds, please wait..." + + local bookstack_attempts=0 + local bookstack_ready=0 + local bookstack_http_code + while ((bookstack_attempts < 60)); do + bookstack_http_code=$(curl -sS -o /dev/null --max-time 3 -w '%{http_code}' "$bookstack_probe_url" 2>/dev/null) + if [[ "$bookstack_http_code" =~ ^(200|302)$ ]]; then + bookstack_ready=1 + break + fi + sleep 2 + ((bookstack_attempts++)) + done + + if ((bookstack_ready == 0)); then + isNotice "Bookstack did not respond on ${bookstack_probe_url} within $((60 * 2))s — admin account left at upstream defaults." + echo "" + isNotice "Bookstack admin login (default):" + echo "" + echo " Email : admin@admin.com" + echo " Password : password" + echo "" + return 0 + fi + isSuccessful "Bookstack is online (HTTP ${bookstack_http_code})." + + local bookstack_create_output + bookstack_create_output=$(runFileOp docker exec \ + -e EZ_BS_NEW_EMAIL="$bookstack_target_email" \ + -e EZ_BS_NEW_PASS="$bookstack_target_pass" \ + bookstack sh -c 'cd /app/www && s6-setuidgid abc php artisan bookstack:create-admin --no-ansi --email="$EZ_BS_NEW_EMAIL" --name=Admin --password="$EZ_BS_NEW_PASS" 2>&1') + local bookstack_create_rc=$? + if [[ $bookstack_create_rc -eq 0 ]]; then + isSuccessful "Bookstack admin account created (email: $bookstack_target_email)." + + if [[ "$bookstack_target_email" != "admin@admin.com" ]]; then + runFileOp docker exec -i bookstack php /app/www/artisan tinker --no-ansi >/dev/null 2>&1 <<'PHP' +$c = class_exists('\BookStack\Users\Models\User') ? '\BookStack\Users\Models\User' : '\BookStack\Auth\User'; +optional($c::where('email', 'admin@admin.com')->first())->delete(); +PHP + isSuccessful "Removed seeded admin@admin.com account." + fi + + echo "" + isNotice "Bookstack admin login:" + echo "" + echo " Email : ${bookstack_target_email}" + echo " Password : ${bookstack_target_pass}" + echo "" + else + isNotice "Bookstack admin auto-create failed (exit $bookstack_create_rc). Output:" + echo "$bookstack_create_output" | sed 's/^/ /' + echo "" + isNotice "Falling back to upstream defaults — update from inside Bookstack." + echo "" + isNotice "Bookstack admin login (default):" + echo "" + echo " Email : admin@admin.com" + echo " Password : password" + echo "" + fi +} diff --git a/containers/dashy/dashy.sh b/containers/dashy/dashy.sh deleted file mode 100755 index ba9eef8..0000000 --- a/containers/dashy/dashy.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash - -# Category : Miscellaneous -# Description : Dashy - Dashboard Tool (c/t/u/s/r/i): - -installDashy() -{ - local config_variables="$1" - - if [[ "$dashy" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent dashy; - local app_name=$CFG_DASHY_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$dashy" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$dashy" == *[tT]* ]]; then - dashyToolsMenu; - fi - - if [[ "$dashy" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$dashy" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$dashy" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$dashy" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - dashy=n -} diff --git a/containers/focalboard/focalboard.sh b/containers/focalboard/focalboard.sh deleted file mode 100755 index 0ce9317..0000000 --- a/containers/focalboard/focalboard.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# Category : Productivity -# Description : Focalboard - Project Management (c/u/s/r/i): - -installFocalboard() -{ - local config_variables="$1" - - if [[ "$focalboard" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent focalboard; - local app_name=$CFG_FOCALBOARD_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$focalboard" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$focalboard" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$focalboard" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$focalboard" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$focalboard" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - focalboard=n -} diff --git a/containers/gitea/gitea.sh b/containers/gitea/gitea.sh deleted file mode 100755 index 7339bc8..0000000 --- a/containers/gitea/gitea.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash - -# Category : Development & Version Control -# Description : Gitea - Git Repository Management (c/u/s/r/i): - -installGitea() -{ - local config_variables="$1" - - if [[ "$gitea" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent gitea; - local app_name=$CFG_GITEA_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$gitea" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$gitea" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$gitea" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$gitea" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$gitea" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - # Enable Gitea's /metrics endpoint only when CFG_GITEA_MONITORING=true - # (toggles the libreportal-monitoring marker block in the compose). - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - # /metrics rides Gitea's public web port, so it's locked behind a - # bearer token. CFG_GITEA_METRICS_TOKEN lives in the .config (filled - # once by the RANDOMIZEDPASSWORD scanner, preserved across reinstalls) - # and reaches the compose via the GITEA_METRICS_TOKEN_TAG tag — mirror - # that same value into the Prometheus scrape fragment so the two agree. - if monitoringAppEnabled "$app_name"; then - if [[ -n "$CFG_GITEA_METRICS_TOKEN" ]]; then - local result=$(runFileOp sed -i "s|GITEA_METRICS_TOKEN_PLACEHOLDER|${CFG_GITEA_METRICS_TOKEN}|g" \ - "$containers_dir$app_name/resources/monitoring/prometheus-scrape.yml") - checkSuccess "Synced Gitea /metrics token to the Prometheus scrape config" - else - isNotice "CFG_GITEA_METRICS_TOKEN is empty — Gitea /metrics scrape may 401." - fi - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - # Self-correcting: adds Gitea's scrape target + dashboard to - # Prometheus/Grafana when CFG_GITEA_MONITORING=true, removes them when - # it's off. No-ops with a notice if either app isn't installed. - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - gitea=n -} diff --git a/containers/gitea/scripts/gitea_install_hooks.sh b/containers/gitea/scripts/gitea_install_hooks.sh new file mode 100644 index 0000000..4a77bbf --- /dev/null +++ b/containers/gitea/scripts/gitea_install_hooks.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Gitea install hooks — mirror CFG_GITEA_METRICS_TOKEN into the Prometheus +# scrape fragment so the bearer token in the compose env matches what the +# Prometheus side sends. + +gitea_install_post_compose() +{ + local app_name="$1" + + # The driver already ran monitoringToggleAppConfig "$app_name" docker-compose.yml, + # so the metrics block reflects CFG_GITEA_MONITORING. /metrics rides + # Gitea's public web port and is token-protected; sync the token into + # the scrape config so the two sides agree. + if monitoringAppEnabled "$app_name"; then + if [[ -n "$CFG_GITEA_METRICS_TOKEN" ]]; then + local result + result=$(runFileOp sed -i "s|GITEA_METRICS_TOKEN_PLACEHOLDER|${CFG_GITEA_METRICS_TOKEN}|g" \ + "$containers_dir$app_name/resources/monitoring/prometheus-scrape.yml") + checkSuccess "Synced Gitea /metrics token to the Prometheus scrape config" + else + isNotice "CFG_GITEA_METRICS_TOKEN is empty — Gitea /metrics scrape may 401." + fi + fi +} diff --git a/containers/gluetun/gluetun.sh b/containers/gluetun/gluetun.sh deleted file mode 100644 index 5e6ef9a..0000000 --- a/containers/gluetun/gluetun.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Gluetun - VPN client for routing other containers (c/u/s/r/i): - -installGluetun() -{ - local config_variables="$1" - - if [[ "$gluetun" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent gluetun; - local app_name=$CFG_GLUETUN_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$gluetun" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$gluetun" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$gluetun" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$gluetun" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$gluetun" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating the WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing Gluetun provider snapshot." - echo "" - - appWebuiRefresh_gluetun; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Re-attaching gluetun-routed apps (post-recreate)." - echo "" - - # Gluetun was just (re)created — every existing routed app holds a - # stale container ID in its network_mode. Reattach them now so the - # user doesn't have to chase silent netns drift later. - appGluetunRoutedRecreate - - ((menu_number++)) - echo "" - echo "---- $menu_number. Routing existing apps through Gluetun (optional)." - echo "" - - gluetunRouteExistingAppsPrompt; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - - menuShowFinalMessages "$app_name"; - - menu_number=0 - cd - fi - gluetun=n -} diff --git a/containers/gluetun/scripts/gluetun_install_hooks.sh b/containers/gluetun/scripts/gluetun_install_hooks.sh new file mode 100644 index 0000000..3068167 --- /dev/null +++ b/containers/gluetun/scripts/gluetun_install_hooks.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# Gluetun install hooks — post-start provider snapshot refresh + reattach +# any apps routed through gluetun (their network_mode holds a stale +# container ID after gluetun was just recreated) + offer to onboard +# existing apps. + +gluetun_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Refreshing Gluetun provider snapshot." + echo "" + + appWebuiRefresh_gluetun + + ((menu_number++)) + echo "" + echo "---- $menu_number. Re-attaching gluetun-routed apps (post-recreate)." + echo "" + + # Gluetun was just (re)created — every existing routed app holds a + # stale container ID in its network_mode. Reattach them now so the + # user doesn't have to chase silent netns drift later. + appGluetunRoutedRecreate + + ((menu_number++)) + echo "" + echo "---- $menu_number. Routing existing apps through Gluetun (optional)." + echo "" + + gluetunRouteExistingAppsPrompt +} diff --git a/containers/grafana/grafana.sh b/containers/grafana/grafana.sh deleted file mode 100755 index 0be5b1b..0000000 --- a/containers/grafana/grafana.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash - -# Category : Development & Version Control -# Description : Grafana - Metrics Visualizer (c/u/s/r/i): - -installGrafana() -{ - local config_variables="$1" - - if [[ "$grafana" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent grafana; - local app_name=$CFG_GRAFANA_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$grafana" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$grafana" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$grafana" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$grafana" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$grafana" == *[iI]* ]]; then - isHeader "Install $app_name" - - if ! appInstallCheckRequirements "$app_name" "$CFG_GRAFANA_REQUIRES"; then - grafana=n - return 1 - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - # Grafana - if [ -d "${containers_dir}grafana/grafana_storage" ]; then - local result=$(sudo chmod -R 777 "${containers_dir}grafana/grafana_storage") - checkSuccess "Set permissions to grafana_storage folder." - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Provisioning monitoring dashboards from installed apps." - echo "" - - # Re-gather the Prometheus datasource + every monitoring-enabled app's - # dashboards into provisioning/ — so a fresh (or re-)install of Grafana - # picks up the apps that already had CFG__MONITORING=true. - # monitoringRefreshAll also covers Grafana's own scrape target when - # CFG_GRAFANA_MONITORING=true. - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - grafana=n -} diff --git a/containers/grafana/scripts/grafana_install_hooks.sh b/containers/grafana/scripts/grafana_install_hooks.sh new file mode 100644 index 0000000..cfa2a26 --- /dev/null +++ b/containers/grafana/scripts/grafana_install_hooks.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Grafana install hooks — pre-flight prereq check + post-start 0777 on the +# storage folder so Grafana can write its sqlite db regardless of host UID. + +grafana_install_pre() +{ + local app_name="$1" + if ! appInstallCheckRequirements "$app_name" "$CFG_GRAFANA_REQUIRES"; then + grafana=n + return 1 + fi +} + +grafana_install_post_start() +{ + local app_name="$1" + if [ -d "${containers_dir}grafana/grafana_storage" ]; then + local result + result=$(sudo chmod -R 777 "${containers_dir}grafana/grafana_storage") + checkSuccess "Set permissions to grafana_storage folder." + fi +} diff --git a/containers/headscale/headscale.sh b/containers/headscale/headscale.sh deleted file mode 100755 index f7f911a..0000000 --- a/containers/headscale/headscale.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Self-hosted WireGuard orchestrator (c/u/s/r/i): - -installHeadscale() -{ - local config_variables="$1" - - if [[ "$headscale" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent headscale; - local app_name=$CFG_HEADSCALE_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$headscale" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$headscale" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$headscale" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$headscale" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$headscale" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/config) - checkSuccess "Create config folder" - - local result=$(copyResource "$app_name" "config.yaml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) - checkSuccess "Copying config.yaml to config folder." - - configSetupFileWithData $app_name "config.yaml" "config"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up database records" - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - echo " NOTE - The password to login in defined in the yml install file that was installed" - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - headscale=n -} diff --git a/containers/headscale/scripts/headscale_install_hooks.sh b/containers/headscale/scripts/headscale_install_hooks.sh new file mode 100644 index 0000000..c11fcfe --- /dev/null +++ b/containers/headscale/scripts/headscale_install_hooks.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# Headscale install hooks — drop the config.yaml template into the +# container's config folder before start so the daemon has its config on +# first boot. + +headscale_install_post_compose() +{ + local app_name="$1" + + local result + result=$(createFolders "loud" $docker_install_user $containers_dir$app_name/config) + checkSuccess "Create config folder" + + result=$(copyResource "$app_name" "config.yaml" "config" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) + checkSuccess "Copying config.yaml to config folder." + + configSetupFileWithData $app_name "config.yaml" "config" +} diff --git a/containers/invidious/invidious.sh b/containers/invidious/invidious.sh deleted file mode 100755 index 8ead100..0000000 --- a/containers/invidious/invidious.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash - -# Category : Media & Streaming -# Description : Invidious - Privacy-focused YouTube Frontend (c/u/s/r/i/t): - -installInvidious() -{ - local config_variables="$1" - - if [[ "$invidious" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent invidious; - local app_name=$CFG_INVIDIOUS_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$invidious" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$invidious" == *[tT]* ]]; then - invidiousToolsMenu; - fi - - if [[ "$invidious" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$invidious" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$invidious" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$invidious" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - invidious=n -} diff --git a/containers/ipinfo/ipinfo.sh b/containers/ipinfo/ipinfo.sh deleted file mode 100755 index 51d2416..0000000 --- a/containers/ipinfo/ipinfo.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : IPinfo - IP Geolocation and Information (c/u/s/r/i): - -installIpinfo() -{ - local config_variables="$1" - - if [[ "$ipinfo" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent ipinfo; - local app_name=$CFG_IPINFO_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$ipinfo" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$ipinfo" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$ipinfo" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$ipinfo" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$ipinfo" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - ipinfo=n -} diff --git a/containers/jellyfin/jellyfin.sh b/containers/jellyfin/jellyfin.sh deleted file mode 100755 index bf65624..0000000 --- a/containers/jellyfin/jellyfin.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash - -# Category : Media & Streaming -# Description : Jellyfin - Media Server (c/u/s/r/i): - -installJellyfin() -{ - local config_variables="$1" - - if [[ "$jellyfin" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent jellyfin; - local app_name=$CFG_JELLYFIN_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$jellyfin" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$jellyfin" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$jellyfin" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$jellyfin" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$jellyfin" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Pulling a default Jellyfin docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start Jellyfin" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - jellyfin=n -} diff --git a/containers/jitsimeet/jitsimeet.sh b/containers/jitsimeet/jitsimeet.sh deleted file mode 100755 index f071378..0000000 --- a/containers/jitsimeet/jitsimeet.sh +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash - -# Category : Communication & Collaboration Tools -# Description : Jitsi Meet - Video Conferencing *UNFINISHED* (c/u/s/r/i): - -installJitsimeet() -{ - local config_variables="$1" - - if [[ "$jitsimeet" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent jitsimeet; - local app_name=$CFG_JITSIMEET_APP_NAME - git_url=$CFG_JITSIMEET_GIT - initializeAppVariables $app_name; - fi - - if [[ "$jitsimeet" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$jitsimeet" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$jitsimeet" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$jitsimeet" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$jitsimeet" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Downloading latest GitHub release" - echo "" - - latest_tag=$(git ls-remote --refs --sort="version:refname" --tags $git_url | cut -d/ -f3- | tail -n1) - echo "The latest tag is: $latest_tag" - - local result=$(createFolders "loud" $docker_install_user $containers_dir$app_name) - checkSuccess "Creating $app_name container installation folder" - local result=$(cd $containers_dir$app_name && runFileOp rm -rf $containers_dir$app_name/$latest_tag.zip) - checkSuccess "Deleting zip file to prevent conflicts" - local result=$(createTouch $containers_dir$app_name/$latest_tag.txt $docker_install_user && echo 'Installed "$latest_tag" on "$backupDate"!' > $latest_tag.txt) - checkSuccess "Create logging txt file" - - - # Download files and unzip - local result=$(runFileOp wget -O $containers_dir$app_name/$latest_tag.zip $git_url/archive/refs/tags/$latest_tag.zip) - checkSuccess "Downloading tagged zip file from GitHub" - local result=$(runFileOp unzip -o $containers_dir$app_name/$latest_tag.zip -d $containers_dir$app_name) - checkSuccess "Unzip downloaded file" - local result=$(runFileOp mv $containers_dir$app_name/docker-jitsi-meet-$latest_tag/* $containers_dir$app_name) - checkSuccess "Moving all files from zip file to install directory" - local result=$(runFileOp rm -rf $containers_dir$app_name/$latest_tag.zip && runFileOp rm -rf $containers_dir$app_name/$latest_tag/) - checkSuccess "Removing downloaded zip file as no longer needed" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up .env file for setup" - echo "" - - dockerSetupEnvFile; - - # Updating custom .env values - local result=$(runFileOp sed -i "s|CONFIG=~/.jitsi-meet-cfg|CONFIG=$containers_dir$app_name/.jitsi-meet-cfg|g" $containers_dir$app_name/.env) - checkSuccess "Updating .env file with new install path" - - local result=$(runFileOp sed -i "s|#PUBLIC_URL=https://meet.example.com|PUBLIC_URL=https://$host_setup|g" $containers_dir$app_name/.env) - checkSuccess "Updating .env file with Public URL to $host_setup" - - local result=$(runFileOp sed -i "s|HTTP_PORT=8000|HTTP_PORT=$usedport1|g" $containers_dir$app_name/.env) - checkSuccess "Updating .env file with HTTP_PORT to $usedport1" - - local result=$(runFileOp sed -i "s|HTTPS_PORT=8443|HTTPS_PORT=$usedport2|g" $containers_dir$app_name/.env) - checkSuccess "Updating .env file with HTTP_PORT to $usedport2" - - #local result=$(echo "ENABLE_HTTP_REDIRECT=1" | runFileWrite -a "$containers_dir$app_name/.env") - #checkSuccess "Updating .env file with option : ENABLE_HTTP_REDIRECT" - - # Values are missing from the .env by default for some reason - # https://github.com/jitsi/docker-jitsi-meet/commit/12051700562d9826f9e024ad649c4dd9b88f94de#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5 - local result=$(echo "XMPP_DOMAIN=meet.jitsi" | runFileWrite -a "$containers_dir$app_name/.env") - checkSuccess "Updating .env file with missing option : XMPP_DOMAIN" - - local result=$(echo "XMPP_SERVER=xmpp.meet.jitsi" | runFileWrite -a "$containers_dir$app_name/.env") - checkSuccess "Updating .env file with missing option : XMPP_SERVER" - - local result=$(echo "JVB_PORT=$usedport4" | runFileWrite -a "$containers_dir$app_name/.env") - checkSuccess "Updating .env file with missing option : JVB_PORT" - - local result=$(echo "JVB_TCP_MAPPED_PORT=$usedport5" | runFileWrite -a "$containers_dir$app_name/.env") - checkSuccess "Updating .env file with missing option : JVB_TCP_MAPPED_PORT" - - local result=$(echo "JVB_TCP_PORT=$usedport5" | runFileWrite -a "$containers_dir$app_name/.env") - checkSuccess "Updating .env file with missing option : JVB_TCP_PORT" - - local result=$(cd "$containers_dir$app_name" && runFileOp ./gen-passwords.sh) - checkSuccess "Running Jitsi Meet gen-passwords.sh script" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adjusting $app_name docker system files for port changes." - echo "" - - #dockerCommandRun "docker exec -it $app_name /bin/bash && cd /" - - #local result=$(sudo sed -i "s|80|$usedport1|g" $containers_dir$app_nameweb/default) - #checkSuccess "Updating Docker NGINX default site port 80 to $usedport1" - - #local result=$(sudo sed -i "s|443|$usedport2|g" $containers_dir$app_nameweb/default) - #checkSuccess "Updating Docker NGINX default site port 443 to $usedport2" - - local result=$(runFileOp sed -i "s|80|$usedport1|g" $containers_dir$app_name/web/rootfs/defaults/default) - checkSuccess "Updating NGINX default site port 80 to $usedport1" - - local result=$(runFileOp sed -i "s|443|$usedport2|g" $containers_dir$app_name/web/rootfs/defaults/default) - checkSuccess "Updating NGINX default site port 443 to $usedport2" - - #dockerCommandRun "docker cp '$containers_dir$app_name' '$app_name:/etc/nginx/sites-available/default'" - dockerComposeRestart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - jitsimeet=n -} diff --git a/containers/jitsimeet/scripts/jitsimeet_install_hooks.sh b/containers/jitsimeet/scripts/jitsimeet_install_hooks.sh new file mode 100644 index 0000000..00f5c96 --- /dev/null +++ b/containers/jitsimeet/scripts/jitsimeet_install_hooks.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +# Jitsi Meet install hooks — Jitsi ships its docker layout as a tagged +# release zip on GitHub, so we download + unpack it before compose setup. +# Then mass-edit the .env, generate passwords, and rewire the nginx ports. + +jitsimeet_install_post_setup() +{ + local app_name="$1" + local git_url="$CFG_JITSIMEET_GIT" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Downloading latest GitHub release" + echo "" + + local latest_tag + latest_tag=$(git ls-remote --refs --sort="version:refname" --tags "$git_url" | cut -d/ -f3- | tail -n1) + echo "The latest tag is: $latest_tag" + + local result + result=$(createFolders "loud" $docker_install_user $containers_dir$app_name) + checkSuccess "Creating $app_name container installation folder" + result=$(cd $containers_dir$app_name && runFileOp rm -rf $containers_dir$app_name/$latest_tag.zip) + checkSuccess "Deleting zip file to prevent conflicts" + result=$(createTouch $containers_dir$app_name/$latest_tag.txt $docker_install_user && echo "Installed \"$latest_tag\" on \"$backupDate\"!" > $latest_tag.txt) + checkSuccess "Create logging txt file" + + result=$(runFileOp wget -O $containers_dir$app_name/$latest_tag.zip $git_url/archive/refs/tags/$latest_tag.zip) + checkSuccess "Downloading tagged zip file from GitHub" + result=$(runFileOp unzip -o $containers_dir$app_name/$latest_tag.zip -d $containers_dir$app_name) + checkSuccess "Unzip downloaded file" + result=$(runFileOp mv $containers_dir$app_name/docker-jitsi-meet-$latest_tag/* $containers_dir$app_name) + checkSuccess "Moving all files from zip file to install directory" + result=$(runFileOp rm -rf $containers_dir$app_name/$latest_tag.zip && runFileOp rm -rf $containers_dir$app_name/$latest_tag/) + checkSuccess "Removing downloaded zip file as no longer needed" +} + +jitsimeet_install_post_compose() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Setting up .env file for setup" + echo "" + + dockerSetupEnvFile + + local result + result=$(runFileOp sed -i "s|CONFIG=~/.jitsi-meet-cfg|CONFIG=$containers_dir$app_name/.jitsi-meet-cfg|g" $containers_dir$app_name/.env) + checkSuccess "Updating .env file with new install path" + + result=$(runFileOp sed -i "s|#PUBLIC_URL=https://meet.example.com|PUBLIC_URL=https://$host_setup|g" $containers_dir$app_name/.env) + checkSuccess "Updating .env file with Public URL to $host_setup" + + result=$(runFileOp sed -i "s|HTTP_PORT=8000|HTTP_PORT=$usedport1|g" $containers_dir$app_name/.env) + checkSuccess "Updating .env file with HTTP_PORT to $usedport1" + + result=$(runFileOp sed -i "s|HTTPS_PORT=8443|HTTPS_PORT=$usedport2|g" $containers_dir$app_name/.env) + checkSuccess "Updating .env file with HTTP_PORT to $usedport2" + + # Defaults missing from the shipped .env (see jitsi/docker-jitsi-meet + # commit 12051700562d…). Append them here so the install boots. + result=$(echo "XMPP_DOMAIN=meet.jitsi" | runFileWrite -a "$containers_dir$app_name/.env") + checkSuccess "Updating .env file with missing option : XMPP_DOMAIN" + + result=$(echo "XMPP_SERVER=xmpp.meet.jitsi" | runFileWrite -a "$containers_dir$app_name/.env") + checkSuccess "Updating .env file with missing option : XMPP_SERVER" + + result=$(echo "JVB_PORT=$usedport4" | runFileWrite -a "$containers_dir$app_name/.env") + checkSuccess "Updating .env file with missing option : JVB_PORT" + + result=$(echo "JVB_TCP_MAPPED_PORT=$usedport5" | runFileWrite -a "$containers_dir$app_name/.env") + checkSuccess "Updating .env file with missing option : JVB_TCP_MAPPED_PORT" + + result=$(echo "JVB_TCP_PORT=$usedport5" | runFileWrite -a "$containers_dir$app_name/.env") + checkSuccess "Updating .env file with missing option : JVB_TCP_PORT" + + result=$(cd "$containers_dir$app_name" && runFileOp ./gen-passwords.sh) + checkSuccess "Running Jitsi Meet gen-passwords.sh script" +} + +jitsimeet_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Adjusting $app_name docker system files for port changes." + echo "" + + local result + result=$(runFileOp sed -i "s|80|$usedport1|g" $containers_dir$app_name/web/rootfs/defaults/default) + checkSuccess "Updating NGINX default site port 80 to $usedport1" + + result=$(runFileOp sed -i "s|443|$usedport2|g" $containers_dir$app_name/web/rootfs/defaults/default) + checkSuccess "Updating NGINX default site port 443 to $usedport2" + + dockerComposeRestart $app_name +} diff --git a/containers/mastodon/mastodon.sh b/containers/mastodon/mastodon.sh deleted file mode 100755 index 6a20aca..0000000 --- a/containers/mastodon/mastodon.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - -# Category : Communication & Collaboration Tools -# Description : Mastodon - Decentralized Social Network (c/u/s/r/i): - -installMastodon() -{ - local config_variables="$1" - - if [[ "$mastodon" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent mastodon; - local app_name=$CFG_MASTODON_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$mastodon" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$mastodon" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$mastodon" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$mastodon" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$mastodon" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - mastodon=n -} diff --git a/containers/moneyapp/moneyapp.sh b/containers/moneyapp/moneyapp.sh deleted file mode 100644 index 0dd9b28..0000000 --- a/containers/moneyapp/moneyapp.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash - -# Category : Productivity -# Description : MoneyApp - Self-hosted household money management (c/u/s/r/i): - -installMoneyapp() -{ - local config_variables="$1" - - if [[ "$moneyapp" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent moneyapp; - local app_name=$CFG_MONEYAPP_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$moneyapp" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$moneyapp" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$moneyapp" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$moneyapp" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$moneyapp" == *[iI]* ]]; then - isHeader "Install $app_name" - - # Pre-flight: bail out before touching any compose/config if the - # global prerequisites aren't met. CFG_MONEYAPP_REQUIRES lists - # what's needed (currently "domain,traefik"); the helper prints a - # clear list of what's missing so the user knows what to fix. - if ! appInstallCheckRequirements "$app_name" "$CFG_MONEYAPP_REQUIRES"; then - moneyapp=n - return 1 - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Resolving Auth.js callback URL (AUTH_URL)." - echo "" - - # Auth.js requires a fixed AUTH_URL that matches what the browser - # actually hits — otherwise OAuth-style callbacks bounce. We pick: - # * https://. when traefik is on AND a real - # domain is configured (CFG_DOMAIN_) - # * http://: otherwise (raw port exposure) - local moneyapp_compose_file="$containers_dir$app_name/docker-compose.yml" - local moneyapp_auth_url="" - # `host_setup` is built as `.` — when CFG_DOMAIN_ is - # empty it ends up as `.` which is a valid-but-broken hostname. - # Reject that explicitly: we want a real TLD before going https. - local _has_real_domain=0 - if [[ -n "$host_setup" && "$host_setup" != *. ]] && [[ "$host_setup" == *.* ]]; then - _has_real_domain=1 - fi - if [[ "$public" == "true" && $_has_real_domain -eq 1 ]]; then - moneyapp_auth_url="https://$host_setup" - else - local moneyapp_port_pair - moneyapp_port_pair=$(tagsManagerGetTagContent "$moneyapp_compose_file" "PORTS_TAG_1") - local moneyapp_external_port="${moneyapp_port_pair%%:*}" - local moneyapp_host="${public_ip_v4:-localhost}" - moneyapp_auth_url="http://${moneyapp_host}:${moneyapp_external_port}" - if [[ "$public" == "true" && $_has_real_domain -eq 0 ]]; then - isNotice "PORT_1 has traefik=true but no domain configured — falling back to direct port URL." - fi - fi - tagsManagerUpdateUniversalTag "$moneyapp_compose_file" "MONEYAPP_AUTH_URL_TAG" "$moneyapp_auth_url" - isSuccessful "AUTH_URL set to $moneyapp_auth_url" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating the WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " First account to sign up becomes the household owner." - echo "" - - menuShowFinalMessages "$app_name"; - - menu_number=0 - cd - fi - moneyapp=n -} diff --git a/containers/moneyapp/scripts/moneyapp_install_hooks.sh b/containers/moneyapp/scripts/moneyapp_install_hooks.sh new file mode 100644 index 0000000..ec7cd34 --- /dev/null +++ b/containers/moneyapp/scripts/moneyapp_install_hooks.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# MoneyApp install hooks — pre-flight requirements + Auth.js callback URL. + +moneyapp_install_pre() +{ + local app_name="$1" + # Bail out before any compose/config work if global prerequisites are + # missing (currently "domain,traefik"). The helper prints what's + # missing. + if ! appInstallCheckRequirements "$app_name" "$CFG_MONEYAPP_REQUIRES"; then + moneyapp=n + return 1 + fi +} + +moneyapp_install_post_compose() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Resolving Auth.js callback URL (AUTH_URL)." + echo "" + + # Auth.js requires a fixed AUTH_URL matching what the browser actually + # hits — otherwise OAuth-style callbacks bounce. Pick: + # * https://. when traefik is on AND a real domain + # is configured (CFG_DOMAIN_) + # * http://: otherwise (raw port exposure) + local moneyapp_compose_file="$containers_dir$app_name/docker-compose.yml" + local moneyapp_auth_url="" + # host_setup is built as `.` — when CFG_DOMAIN_ is + # empty it ends up as `.`, a valid-but-broken hostname. Reject + # that explicitly: we want a real TLD before going https. + local _has_real_domain=0 + if [[ -n "$host_setup" && "$host_setup" != *. ]] && [[ "$host_setup" == *.* ]]; then + _has_real_domain=1 + fi + if [[ "$public" == "true" && $_has_real_domain -eq 1 ]]; then + moneyapp_auth_url="https://$host_setup" + else + local moneyapp_port_pair + moneyapp_port_pair=$(tagsManagerGetTagContent "$moneyapp_compose_file" "PORTS_TAG_1") + local moneyapp_external_port="${moneyapp_port_pair%%:*}" + local moneyapp_host="${public_ip_v4:-localhost}" + moneyapp_auth_url="http://${moneyapp_host}:${moneyapp_external_port}" + if [[ "$public" == "true" && $_has_real_domain -eq 0 ]]; then + isNotice "PORT_1 has traefik=true but no domain configured — falling back to direct port URL." + fi + fi + tagsManagerUpdateUniversalTag "$moneyapp_compose_file" "MONEYAPP_AUTH_URL_TAG" "$moneyapp_auth_url" + isSuccessful "AUTH_URL set to $moneyapp_auth_url" +} diff --git a/containers/nextcloud/nextcloud.sh b/containers/nextcloud/nextcloud.sh deleted file mode 100755 index 43bfb19..0000000 --- a/containers/nextcloud/nextcloud.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# Category : Cloud Storage & File Sharing -# Description : Nextcloud - Self-hosted Cloud Storage (c/t/u/s/r/i): - -installNextcloud() -{ - local config_variables="$1" - - if [[ "$nextcloud" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent nextcloud; - local app_name=$CFG_NEXTCLOUD_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$nextcloud" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$nextcloud" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$nextcloud" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$nextcloud" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$nextcloud" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - nextcloud=n -} diff --git a/containers/ollama/ollama.sh b/containers/ollama/ollama.sh deleted file mode 100755 index a6db4fd..0000000 --- a/containers/ollama/ollama.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# Category : Development & Version Control -# Description : Ollama - Local AI Model Hosting (c/u/s/r/i): - -installOllama() -{ - local config_variables="$1" - - if [[ "$ollama" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent ollama; - local app_name=$CFG_OLLAMA_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$ollama" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$ollama" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$ollama" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$ollama" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$ollama" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - ollama=n -} diff --git a/containers/onlyoffice/onlyoffice.sh b/containers/onlyoffice/onlyoffice.sh deleted file mode 100755 index ca16dde..0000000 --- a/containers/onlyoffice/onlyoffice.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash - -# Category : Cloud Storage & File Sharing -# Description : OnlyOffice - Collaborative Office Suite (c/t/u/s/r/i): - -installOnlyoffice() -{ - local config_variables="$1" - - if [[ "$onlyoffice" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent onlyoffice; - local app_name=$CFG_ONLYOFFICE_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$onlyoffice" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$onlyoffice" == *[tT]* ]]; then - onlyofficeToolsMenu; - fi - - if [[ "$onlyoffice" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$onlyoffice" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$onlyoffice" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$onlyoffice" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - # Extract the content after the equals sign for username and password - local username=$(grep -oP 'username=\K[^ ]+' "$containers_dir$app_name/docker-compose.yml") - local password=$(grep -oP 'password=\K[^ ]+' "$containers_dir$app_name/docker-compose.yml") - menuShowFinalMessages $app_name $username $password; - - menu_number=0 - #sleep 3s - cd - fi - onlyoffice=n -} diff --git a/containers/onlyoffice/scripts/onlyoffice_install_hooks.sh b/containers/onlyoffice/scripts/onlyoffice_install_hooks.sh new file mode 100644 index 0000000..9b22460 --- /dev/null +++ b/containers/onlyoffice/scripts/onlyoffice_install_hooks.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# OnlyOffice install hooks — pull the compose-resolved username/password +# into the final-message argv so the user sees the credentials at the +# end of the install. + +onlyoffice_install_message_data() +{ + local app_name="$1" + local username password + username=$(grep -oP 'username=\K[^ ]+' "$containers_dir$app_name/docker-compose.yml" 2>/dev/null) + password=$(grep -oP 'password=\K[^ ]+' "$containers_dir$app_name/docker-compose.yml" 2>/dev/null) + echo "$username $password" +} diff --git a/containers/owncloud/owncloud.sh b/containers/owncloud/owncloud.sh deleted file mode 100755 index e931ac7..0000000 --- a/containers/owncloud/owncloud.sh +++ /dev/null @@ -1,152 +0,0 @@ -#!/bin/bash - -# Category : Cloud Storage & File Sharing -# Description : OwnCloud - Cloud Storage (c/u/s/r/i): - -installOwncloud() -{ - local config_variables="$1" - - if [[ "$owncloud" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent owncloud; - local app_name=$CFG_OWNCLOUD_APP_NAME - owncloud_version=$CFG_OWNCLOUD_VERSION - initializeAppVariables $app_name; - fi - - if [[ "$owncloud" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$owncloud" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$owncloud" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$owncloud" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$owncloud" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Obtain latest version number of $app_name" - echo "" - - local webpage_file="/tmp/webpage.html" - - # Download the webpage to the temporary directory - curl -s "https://doc.owncloud.com/docs/next/server_release_notes.html" > "$webpage_file" - if [ $? -eq 0 ]; then - # Extract the latest version from the temporary HTML file - local latest_version=$(grep -o 'Changes in [0-9.-]*' "$webpage_file" | awk -F " " '{print $3}' | sort -V | tail -n 1) - if [ -n "$latest_version" ]; then - isSuccessful "Latest Retrieved Version: $latest_version" - isSuccessful "Using for installation" - owncloud_version="$latest_version" - else - isNotice "Failed to extract the latest version from the OwnCloud website." - isNotice "Defaulting to config value : $CFG_OWNCLOUD_VERSION." - owncloud_version="$CFG_OWNCLOUD_VERSION" - fi - - # Remove the temporary HTML file - rm "$webpage_file" - if [ $? -eq 0 ]; then - isSuccessful "Removed the temporary HTML file" - else - isNotice "Failed to remove the temporary HTML file" - fi - else - isNotice "Failed to retrieve the web page." - fi - - local result=$(runFileOp sed -i \ - -e "s|OWNCLOUD_SETUP_VERSION|$owncloud_version|g" \ - -e "s|OWNCLOUD_SETUP_ADMIN_USERNAME|$CFG_OWNCLOUD_ADMIN_USERNAME|g" \ - -e "s|OWNCLOUD_SETUP_ADMIN_PASSWORD|$CFG_OWNCLOUD_ADMIN_PASSWORD|g" \ - -e "s|OWNCLOUD_SETUP_HTTP_PORT|$usedport1|g" \ - "$file_path") - checkSuccess "Updating $file_name for $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your new service using one of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - owncloud=n -} diff --git a/containers/owncloud/scripts/owncloud_install_hooks.sh b/containers/owncloud/scripts/owncloud_install_hooks.sh new file mode 100644 index 0000000..e1df15f --- /dev/null +++ b/containers/owncloud/scripts/owncloud_install_hooks.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# OwnCloud install hooks — latest-version scrape + compose substitution. + +owncloud_install_post_compose() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Obtain latest version number of $app_name" + echo "" + + local owncloud_version="$CFG_OWNCLOUD_VERSION" + local webpage_file="/tmp/webpage.html" + + curl -s "https://doc.owncloud.com/docs/next/server_release_notes.html" > "$webpage_file" + if [ $? -eq 0 ]; then + local latest_version + latest_version=$(grep -o 'Changes in [0-9.-]*' "$webpage_file" | awk -F " " '{print $3}' | sort -V | tail -n 1) + if [ -n "$latest_version" ]; then + isSuccessful "Latest Retrieved Version: $latest_version" + isSuccessful "Using for installation" + owncloud_version="$latest_version" + else + isNotice "Failed to extract the latest version from the OwnCloud website." + isNotice "Defaulting to config value : $CFG_OWNCLOUD_VERSION." + fi + rm -f "$webpage_file" + else + isNotice "Failed to retrieve the web page." + fi + + local file_path="$containers_dir$app_name/docker-compose.yml" + local file_name="docker-compose.yml" + local result + result=$(runFileOp sed -i \ + -e "s|OWNCLOUD_SETUP_VERSION|$owncloud_version|g" \ + -e "s|OWNCLOUD_SETUP_ADMIN_USERNAME|$CFG_OWNCLOUD_ADMIN_USERNAME|g" \ + -e "s|OWNCLOUD_SETUP_ADMIN_PASSWORD|$CFG_OWNCLOUD_ADMIN_PASSWORD|g" \ + -e "s|OWNCLOUD_SETUP_HTTP_PORT|$usedport1|g" \ + "$file_path") + checkSuccess "Updating $file_name for $app_name" +} diff --git a/containers/pihole/pihole.sh b/containers/pihole/pihole.sh deleted file mode 100755 index 2bd0d08..0000000 --- a/containers/pihole/pihole.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : PiHole - DNS-based Ad Blocking (c/u/s/r/i): - -installPihole() -{ - local config_variables="$1" - - if [[ "$pihole" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent pihole; - local app_name=$CFG_PIHOLE_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$pihole" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$pihole" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$pihole" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$pihole" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$pihole" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up database records" - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - echo " NOTE - The password to login in defined in the yml install file that was installed" - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - pihole=n -} diff --git a/containers/prometheus/prometheus.sh b/containers/prometheus/prometheus.sh deleted file mode 100755 index 0a34ef1..0000000 --- a/containers/prometheus/prometheus.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -# Category : Development & Version Control -# Description : Prometheus - Monitoring and Alerting (c/u/s/r/i): - -installPrometheus() -{ - local config_variables="$1" - - if [[ "$prometheus" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent prometheus; - local app_name=$CFG_PROMETHEUS_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$prometheus" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$prometheus" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$prometheus" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$prometheus" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$prometheus" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - local result=$(createFolders "loud" $docker_install_user "$containers_dir$app_name/$app_name") - checkSuccess "Created $app_name folder in $app_name" - - local result=$(createTouch "$containers_dir$app_name/$app_name/$app_name.yml" $docker_install_user) - checkSuccess "Created $app_name.yml file for $app_name" - - local result=$(copyResource "$app_name" "$app_name.yml" "$app_name" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) - checkSuccess "Copying $app_name.yml to containers folder." - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - # Prometheus - if [ -f "${containers_dir}prometheus/prometheus/prometheus.yml" ]; then - updateFileOwnership "${containers_dir}prometheus/prometheus/prometheus.yml" $docker_install_user $docker_install_user - fi - if [ -d "${containers_dir}prometheus/prometheus" ]; then - local result=$(sudo chmod -R 777 "${containers_dir}prometheus/prometheus") - checkSuccess "Set permissions to prometheus folder." - fi - if [ -d "${containers_dir}prometheus/prom_data" ]; then - local result=$(sudo chmod -R 777 "${containers_dir}prometheus/prom_data") - checkSuccess "Set permissions to prom_data folder." - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Gathering monitoring scrape targets from installed apps." - echo "" - - # Re-gather every monitoring-enabled app's scrape fragment into - # scrape.d/ — so a fresh (or re-)install of Prometheus picks up the - # apps that already had CFG__MONITORING=true. - monitoringRefreshPrometheus; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - prometheus=n -} diff --git a/containers/prometheus/scripts/prometheus_install_hooks.sh b/containers/prometheus/scripts/prometheus_install_hooks.sh new file mode 100644 index 0000000..00588fa --- /dev/null +++ b/containers/prometheus/scripts/prometheus_install_hooks.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Prometheus install hooks — drop the prometheus.yml template alongside the +# compose, and 0777 the storage dirs so the container can write its TSDB +# regardless of the host UID mapping. + +prometheus_install_post_compose() +{ + local app_name="$1" + + local result + result=$(createFolders "loud" $docker_install_user "$containers_dir$app_name/$app_name") + checkSuccess "Created $app_name folder in $app_name" + + result=$(createTouch "$containers_dir$app_name/$app_name/$app_name.yml" $docker_install_user) + checkSuccess "Created $app_name.yml file for $app_name" + + result=$(copyResource "$app_name" "$app_name.yml" "$app_name" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) + checkSuccess "Copying $app_name.yml to containers folder." +} + +prometheus_install_post_start() +{ + local app_name="$1" + + if [ -f "${containers_dir}prometheus/prometheus/prometheus.yml" ]; then + updateFileOwnership "${containers_dir}prometheus/prometheus/prometheus.yml" $docker_install_user $docker_install_user + fi + if [ -d "${containers_dir}prometheus/prometheus" ]; then + local result + result=$(sudo chmod -R 777 "${containers_dir}prometheus/prometheus") + checkSuccess "Set permissions to prometheus folder." + fi + if [ -d "${containers_dir}prometheus/prom_data" ]; then + local result + result=$(sudo chmod -R 777 "${containers_dir}prometheus/prom_data") + checkSuccess "Set permissions to prom_data folder." + fi +} diff --git a/containers/searxng/scripts/searxng_install_hooks.sh b/containers/searxng/scripts/searxng_install_hooks.sh new file mode 100644 index 0000000..dab2a8f --- /dev/null +++ b/containers/searxng/scripts/searxng_install_hooks.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# SearxNG install hooks — wait for settings.yml, apply theme, restart. + +searxng_install_post_start() +{ + local app_name="$1" + + local searxng_timeout=10 + local searxng_counter=0 + while [ ! -f "$containers_dir$app_name/searxng-data/settings.yml" ]; do + if [ "$searxng_counter" -ge "$searxng_timeout" ]; then + isNotice "File not found after 10 seconds. Exiting..." + return 0 + fi + isNotice "Waiting for the file to appear..." + read -t 1 + searxng_counter=$((searxng_counter + 1)) + done + + local result + result=$(runFileOp sed -i "s/simple_style: auto/simple_style: $CFG_SEARXNG_THEME/" "$containers_dir$app_name/searxng-data/settings.yml") + checkSuccess "Changing from light mode to dark mode to avoid eye strain installs" + + dockerComposeRestart $app_name +} diff --git a/containers/searxng/searxng.sh b/containers/searxng/searxng.sh deleted file mode 100755 index 0876f2f..0000000 --- a/containers/searxng/searxng.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash - -# Category : Privacy & Security Tools -# Description : SearxNG - Privacy-focused Search Engine (c/u/s/r/i): - -installSearxng() -{ - local config_variables="$1" - - if [[ "$searxng" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent searxng; - local app_name=$CFG_SEARXNG_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$searxng" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$searxng" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$searxng" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$searxng" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$searxng" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - local searxng_timeout=10 - local searxng_counter=0 - # Loop to check for the existence of the file every second - while [ ! -f "$containers_dir$app_name/searxng-data/settings.yml" ]; do - if [ "$searxng_counter" -ge "$searxng_timeout" ]; then - isNotice "File not found after 10 seconds. Exiting..." - break - fi - - isNotice "Waiting for the file to appear..." - read -t 1 # Wait for 1 second - - # Increment the counter - local searxng_counter=$((searxng_counter + 1)) - done - - # Check if the file was found or if we timed out - if [ -f "$containers_dir$app_name/searxng-data/settings.yml" ]; then - # Perform the required operation on the file once it exists - local result=$(runFileOp sed -i "s/simple_style: auto/simple_style: $CFG_SEARXNG_THEME/" "$containers_dir$app_name/searxng-data/settings.yml") - checkSuccess "Changing from light mode to dark mode to avoid eye strain installs" - - dockerComposeRestart $app_name; - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - searxng=n -} diff --git a/containers/speedtest/speedtest.sh b/containers/speedtest/speedtest.sh deleted file mode 100755 index 2918e52..0000000 --- a/containers/speedtest/speedtest.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Speedtest - Network Performance Monitoring (c/u/s/r/i): - -installSpeedtest() -{ - local config_variables="$1" - - if [[ "$speedtest" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent speedtest; - local app_name=$CFG_SPEEDTEST_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$speedtest" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$speedtest" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$speedtest" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$speedtest" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$speedtest" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - speedtest=n -} diff --git a/containers/traefik/scripts/traefik_install_hooks.sh b/containers/traefik/scripts/traefik_install_hooks.sh new file mode 100644 index 0000000..249f584 --- /dev/null +++ b/containers/traefik/scripts/traefik_install_hooks.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +# Traefik install hooks — interactive email prompt (LE notices), static + +# dynamic config copy, dashboard-access mode wiring (local-only / domain- +# only / public), monitoring toggle on traefik.yml, whitelist + login. + +traefik_install_pre() +{ + local app_name="$1" + + if [[ -z "$CFG_TRAEFIK_EMAIL" || "$CFG_TRAEFIK_EMAIL" == "changeme" || "$CFG_TRAEFIK_EMAIL" == "Change-Me" ]]; then + if [[ "$LIBREPORTAL_NONINTERACTIVE" == "1" ]]; then + isError "CFG_TRAEFIK_EMAIL not set. Run 'libreportal config update CFG_TRAEFIK_EMAIL=you@example.com' first." + return 1 + fi + local traefik_email="" + while true; do + isQuestion "Administrator email for LetsEncrypt (cert-expiry notices) : " + read -p "" traefik_email + emailValidation "$traefik_email" + [[ $? -eq 0 ]] && break + isNotice "Please provide a valid email address." + done + updateConfigOption "CFG_TRAEFIK_EMAIL" "$traefik_email" + sourceScanFiles "libreportal_configs" + fi +} + +traefik_install_post_compose() +{ + local app_name="$1" + + local result + result=$(createFolders "loud" $docker_install_user "$containers_dir$app_name/etc" "$containers_dir$app_name/etc/certs" "$containers_dir$app_name/etc/dynamic" "$containers_dir$app_name/etc/dynamic/middlewears") + checkSuccess "Created etc and certs & dynamic Directories" + + result=$(copyResource "$app_name" "traefik.yml" "etc") + checkSuccess "Copy Traefik configuration file for $app_name" + + result=$(runFileOp sed -i "s|DEBUGLEVEL|$CFG_TRAEFIK_LOGGING|g" "$containers_dir$app_name/etc/traefik.yml") + checkSuccess "Configured Traefik debug level with: $CFG_TRAEFIK_LOGGING for $app_name" + + configSetupFileWithData $app_name "traefik.yml" "etc" + + # Apply CFG_TRAEFIK_DASHBOARD_ACCESS: rewrites api.insecure + the + # `traefik:` entrypoint in traefik.yml, and (for local-only) prefixes + # the compose port mapping with 127.0.0.1: so :8080 binds to loopback. + local traefik_yml="$containers_dir$app_name/etc/traefik.yml" + local compose_yml="$containers_dir$app_name/docker-compose.yml" + local access="${CFG_TRAEFIK_DASHBOARD_ACCESS:-local-only}" + + case "$access" in + local-only) + runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1true|' "$traefik_yml" + runFileOp sed -i '/#LIBREPORTAL|PORTS_TAG_1|/ { + /127\.0\.0\.1:/! s|"\([0-9]\+:[0-9]\+\)"|"127.0.0.1:\1"| + }' "$compose_yml" + checkSuccess "Dashboard access: local-only (loopback :8080 + auth-protected domain)" + ;; + domain-only) + runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1false|' "$traefik_yml" + runFileOp sed -i '/^\s*traefik:\s*$/,/^\s*address:\s*:8080\s*$/d' "$traefik_yml" + checkSuccess "Dashboard access: domain-only (auth-protected via Host route only)" + ;; + public) + runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1true|' "$traefik_yml" + runFileOp sed -i '/#LIBREPORTAL|PORTS_TAG_1|/ s|"127\.0\.0\.1:\([0-9]\+:[0-9]\+\)"|"\1"|' "$compose_yml" + checkSuccess "Dashboard access: public (unauthenticated :8080 on all interfaces — legacy)" + ;; + *) + isNotice "Unknown CFG_TRAEFIK_DASHBOARD_ACCESS='$access'; leaving traefik.yml at defaults." + ;; + esac + + # Traefik's metrics block lives in traefik.yml; toggle that here. The + # driver already toggled docker-compose.yml. + monitoringToggleAppConfig "$app_name" "etc/traefik.yml" + + result=$(copyResource "$app_name" "config.yml" "etc/dynamic") + checkSuccess "Copy Traefik Dynamic config.yml configuration file for $app_name" + + result=$(runFileOp sed -i "s|ERRORWEBSITE|$CFG_TRAEFIK_404_SITE|g" "$containers_dir$app_name/etc/dynamic/config.yml") + checkSuccess "Configured Traefik error website with URL: $CFG_TRAEFIK_404_SITE for $app_name" + + configSetupFileWithData $app_name "config.yml" "etc/dynamic" + + result=$(copyResource "$app_name" "whitelist.yml" "etc/dynamic") + checkSuccess "Copy Traefik Dynamic whitelist.yml configuration file for $app_name" + + result=$(copyResource "$app_name" "protectionauth.yml" "etc/dynamic/middlewears") + checkSuccess "Copy Traefik Dynamic protectionauth.yml configuration file for $app_name" + + traefikUpdateWhitelist + + result=$(copyResource "$app_name" "tls.yml" "etc/dynamic") + checkSuccess "Copy Traefik Dynamic tls.yml configuration file for $app_name" + + traefikSetupLoginCredentials +} diff --git a/containers/traefik/traefik.sh b/containers/traefik/traefik.sh deleted file mode 100755 index d5798fc..0000000 --- a/containers/traefik/traefik.sh +++ /dev/null @@ -1,222 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Traefik - Reverse Proxy & Load Balancer (c/u/s/r/i): - -installTraefik() -{ - local config_variables="$1" - - if [[ "$traefik" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent traefik; - local app_name=$CFG_TRAEFIK_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$traefik" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$traefik" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$traefik" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$traefik" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$traefik" == *[iI]* ]]; then - isHeader "Install $app_name" - - if [[ -z "$CFG_TRAEFIK_EMAIL" || "$CFG_TRAEFIK_EMAIL" == "changeme" || "$CFG_TRAEFIK_EMAIL" == "Change-Me" ]]; then - if [[ "$LIBREPORTAL_NONINTERACTIVE" == "1" ]]; then - isError "CFG_TRAEFIK_EMAIL not set. Run 'libreportal config update CFG_TRAEFIK_EMAIL=you@example.com' first." - return 1 - fi - local traefik_email="" - while true; do - isQuestion "Administrator email for LetsEncrypt (cert-expiry notices) : " - read -p "" traefik_email - emailValidation "$traefik_email" - [[ $? -eq 0 ]] && break - isNotice "Please provide a valid email address." - done - updateConfigOption "CFG_TRAEFIK_EMAIL" "$traefik_email" - sourceScanFiles "libreportal_configs" - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - # Create necessary directories and set permissions - local result=$(createFolders "loud" $docker_install_user "$containers_dir$app_name/etc" "$containers_dir$app_name/etc/certs" "$containers_dir$app_name/etc/dynamic" "$containers_dir$app_name/etc/dynamic/middlewears") - checkSuccess "Created etc and certs & dynamic Directories" - - # Static traefik.yml File - # Copy the Traefik configuration file and customize it - local result=$(copyResource "$app_name" "traefik.yml" "etc") - checkSuccess "Copy Traefik configuration file for $app_name" - - # Setup Debug Level - local result=$(runFileOp sed -i "s|DEBUGLEVEL|$CFG_TRAEFIK_LOGGING|g" "$containers_dir$app_name/etc/traefik.yml") - checkSuccess "Configured Traefik debug level with: $CFG_TRAEFIK_LOGGING for $app_name" - - configSetupFileWithData $app_name "traefik.yml" "etc"; - - # Apply CFG_TRAEFIK_DASHBOARD_ACCESS: rewrites api.insecure + the - # `traefik:` entrypoint in traefik.yml, and (for local-only) prefixes - # the compose port mapping with 127.0.0.1: so :8080 binds to loopback. - local traefik_yml="$containers_dir$app_name/etc/traefik.yml" - local compose_yml="$containers_dir$app_name/docker-compose.yml" - local access="${CFG_TRAEFIK_DASHBOARD_ACCESS:-local-only}" - - case "$access" in - local-only) - runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1true|' "$traefik_yml" - # Bind PORT_1 mapping to 127.0.0.1 only. Idempotent — only - # adds the prefix if it isn't already there. - runFileOp sed -i '/#LIBREPORTAL|PORTS_TAG_1|/ { - /127\.0\.0\.1:/! s|"\([0-9]\+:[0-9]\+\)"|"127.0.0.1:\1"| - }' "$compose_yml" - checkSuccess "Dashboard access: local-only (loopback :8080 + auth-protected domain)" - ;; - domain-only) - runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1false|' "$traefik_yml" - # Drop the :8080 entrypoint entirely — nothing should listen - # there if the dashboard is domain-only. - runFileOp sed -i '/^\s*traefik:\s*$/,/^\s*address:\s*:8080\s*$/d' "$traefik_yml" - checkSuccess "Dashboard access: domain-only (auth-protected via Host route only)" - ;; - public) - runFileOp sed -i 's|^\(\s*insecure:\s*\).*$|\1true|' "$traefik_yml" - # Strip any 127.0.0.1: prefix the compose port may have - # picked up from a previous local-only install. - runFileOp sed -i '/#LIBREPORTAL|PORTS_TAG_1|/ s|"127\.0\.0\.1:\([0-9]\+:[0-9]\+\)"|"\1"|' "$compose_yml" - checkSuccess "Dashboard access: public (unauthenticated :8080 on all interfaces — legacy)" - ;; - *) - isNotice "Unknown CFG_TRAEFIK_DASHBOARD_ACCESS='$access'; leaving traefik.yml at defaults." - ;; - esac - - # Enable the Prometheus metrics endpoint + provider only when - # CFG_TRAEFIK_MONITORING=true (toggles the libreportal-monitoring - # marker blocks in traefik.yml). monitoringRefreshAll later in this - # install picks up the scrape fragment + dashboard. - monitoringToggleAppConfig "$app_name" "etc/traefik.yml"; - - # Dynamic config.yml File - # Copy the Traefik configuration file and customize it - local result=$(copyResource "$app_name" "config.yml" "etc/dynamic") - checkSuccess "Copy Traefik Dynamic config.yml configuration file for $app_name" - - # Setup Error 404 Website - local result=$(runFileOp sed -i "s|ERRORWEBSITE|$CFG_TRAEFIK_404_SITE|g" "$containers_dir$app_name/etc/dynamic/config.yml") - checkSuccess "Configured Traefik error website with URL: $CFG_TRAEFIK_404_SITE for $app_name" - - configSetupFileWithData $app_name "config.yml" "etc/dynamic"; - - # Dynamic whitelist.yml File - local result=$(copyResource "$app_name" "whitelist.yml" "etc/dynamic") - checkSuccess "Copy Traefik Dynamic whitelist.yml configuration file for $app_name" - - # Middlewears - # Dynamic protectionauth.yml File - local result=$(copyResource "$app_name" "protectionauth.yml" "etc/dynamic/middlewears") - checkSuccess "Copy Traefik Dynamic protectionauth.yml configuration file for $app_name" - - traefikUpdateWhitelist; - - # Dynamic tls.yml File - local result=$(copyResource "$app_name" "tls.yml" "etc/dynamic") - checkSuccess "Copy Traefik Dynamic tls.yml configuration file for $app_name" - - traefikSetupLoginCredentials; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - # Self-correcting: adds Traefik's scrape target + dashboard to - # Prometheus/Grafana when CFG_TRAEFIK_MONITORING=true, removes them - # when it's off. No-ops with a notice if either app isn't installed. - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - traefik=n -} diff --git a/containers/trilium/scripts/trilium_install_hooks.sh b/containers/trilium/scripts/trilium_install_hooks.sh new file mode 100644 index 0000000..90d3ca0 --- /dev/null +++ b/containers/trilium/scripts/trilium_install_hooks.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Trilium install hooks — wait for first-boot config.ini, retune port, restart. + +trilium_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Updating default port and restarting $app_name" + echo "" + + local trilium_timeout=10 + local trilium_counter=0 + while [ ! -f "$containers_dir$app_name/trilium-data/config.ini" ]; do + if [ "$trilium_counter" -ge "$trilium_timeout" ]; then + isNotice "File not found after 10 seconds. Exiting..." + return 0 + fi + isNotice "Waiting for the file to appear..." + read -t 1 + trilium_counter=$((trilium_counter + 1)) + done + + local result + result=$(runFileOp sed -i "s|port=8080|port=$usedport1|g" "$containers_dir$app_name/trilium-data/config.ini") + checkSuccess "Configured $app_name from default 8080 to $usedport1" + + dockerComposeRestart $app_name +} diff --git a/containers/trilium/trilium.sh b/containers/trilium/trilium.sh deleted file mode 100755 index 888cfd3..0000000 --- a/containers/trilium/trilium.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -# Category : Knowledge Management -# Description : Trilium - Notes & Knowledge Management (c/u/s/r/i): - -installTrilium() -{ - local config_variables="$1" - - if [[ "$trilium" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent trilium; - local app_name=$CFG_TRILIUM_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$trilium" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$trilium" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$trilium" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$trilium" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$trilium" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating defaul port and restarting $app_name" - echo "" - - local trilium_timeout=10 - local trilium_counter=0 - # Loop to check for the existence of the file every second - while [ ! -f "$containers_dir$app_name/trilium-data/config.ini" ]; do - if [ "$trilium_counter" -ge "$trilium_timeout" ]; then - isNotice "File not found after 10 seconds. Exiting..." - break - fi - - isNotice "Waiting for the file to appear..." - read -t 1 # Wait for 1 second - - # Increment the counter - local trilium_counter=$((trilium_counter + 1)) - done - - result=$(runFileOp sed -i "s|port=8080|port=$usedport1|g" "$containers_dir$app_name/trilium-data/config.ini") - checkSuccess "Configured $app_name from default 8080 to $usedport1" - - dockerComposeRestart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - trilium=n -} diff --git a/containers/unbound/scripts/unbound_install_hooks.sh b/containers/unbound/scripts/unbound_install_hooks.sh new file mode 100644 index 0000000..1d7926c --- /dev/null +++ b/containers/unbound/scripts/unbound_install_hooks.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Unbound install hooks — drop unbound.conf into etc/ and toggle the +# monitoring marker in it (the driver already handled docker-compose.yml). + +unbound_install_post_compose() +{ + local app_name="$1" + + local result + result=$(copyResource "$app_name" "unbound.conf" "etc" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) + checkSuccess "Copying unbound.conf to containers folder." + + monitoringToggleAppConfig "$app_name" "etc/unbound.conf" +} diff --git a/containers/unbound/unbound.sh b/containers/unbound/unbound.sh deleted file mode 100755 index 2adb113..0000000 --- a/containers/unbound/unbound.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Unbound - DNS Resolver (c/u/s/r/i): - -installUnbound() -{ - local config_variables="$1" - - if [[ "$unbound" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent unbound; - local app_name=$CFG_UNBOUND_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$unbound" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$unbound" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$unbound" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$unbound" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$unbound" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - local result=$(copyResource "$app_name" "unbound.conf" "etc" | runInstallWrite -a "$logs_dir/$docker_log_file" 2>&1) - checkSuccess "Copying unbound.conf to containers folder." - - monitoringToggleAppConfig "$app_name" "etc/unbound.conf"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - echo " NOTICE : Below are the URLs for the admin panel to use after you have setup Unbound" - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - unbound=n -} diff --git a/containers/vaultwarden/vaultwarden.sh b/containers/vaultwarden/vaultwarden.sh deleted file mode 100755 index 9e3b887..0000000 --- a/containers/vaultwarden/vaultwarden.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# Category : Privacy & Security Tools -# Description : Vaultwarden - Password Manager (c/u/s/r/i): - -installVaultwarden() -{ - local config_variables="$1" - - if [[ "$vaultwarden" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent vaultwarden; - local app_name=$CFG_VAULTWARDEN_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$vaultwarden" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$vaultwarden" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$vaultwarden" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$vaultwarden" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$vaultwarden" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to install and start $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - vaultwarden=n -} diff --git a/containers/wireguard/scripts/wireguard_install_hooks.sh b/containers/wireguard/scripts/wireguard_install_hooks.sh new file mode 100644 index 0000000..b5ab878 --- /dev/null +++ b/containers/wireguard/scripts/wireguard_install_hooks.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# WireGuard install hooks — host-conflict guard, tunnel subnet generation, +# WG_HOST resolution, IP forwarding setup, and a post-start restart so +# the firewall rules from wg-easy take effect cleanly. + +wireguard_install_pre() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Checking if $app_name can be installed." + echo "" + + # Host-conflict guard: a host-level WireGuard (e.g. the angristan + # wireguard-install script — marker /etc/wireguard/params) collides + # with this container on the wg kernel module + UDP 51820. Abort. + if [[ -e /etc/wireguard/params ]]; then + isError "WireGuard is already installed on the host — this conflicts with the $app_name app." + isError "Installation is now aborting..." + dockerUninstallApp "$app_name" + return 1 + fi +} + +wireguard_install_post_compose() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Resolving wireguard tunnel subnet (WG_DEFAULT_ADDRESS)" + echo "" + + # Generate-once-and-persist tunnel subnet. Second-octet 200-250 is + # outside the docker network generator range (100-149), so the two + # subnets cannot collide. Reusing the persisted value keeps existing + # peer configs valid across reinstalls. + local _wg_compose_for_subnet="$containers_dir$app_name/docker-compose.yml" + if [[ -z "$CFG_WIREGUARD_SUBNET" ]]; then + local _wg_second=$(( RANDOM % 51 + 200 )) + local _wg_third=$(( RANDOM % 256 )) + CFG_WIREGUARD_SUBNET="10.${_wg_second}.${_wg_third}.0" + updateConfigOption "CFG_WIREGUARD_SUBNET" "$CFG_WIREGUARD_SUBNET" + isSuccessful "Generated wireguard tunnel subnet: $CFG_WIREGUARD_SUBNET" + else + isNotice "Reusing existing wireguard tunnel subnet: $CFG_WIREGUARD_SUBNET" + fi + # wg-easy expects the address pattern `.x` (literal x). + local _wg_addr_pattern="${CFG_WIREGUARD_SUBNET%.0}.x" + tagsManagerUpdateUniversalTag "$_wg_compose_for_subnet" "WIREGUARD_SUBNET_TAG" "$_wg_addr_pattern" + isSuccessful "WG_DEFAULT_ADDRESS set to $_wg_addr_pattern" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Resolving WG_HOST for peer configs" + echo "" + + local wg_compose_file="$containers_dir$app_name/docker-compose.yml" + local wg_host_value="" + local _wg_traefik_installed=0 + if declare -f checkServiceInstalled >/dev/null 2>&1 && checkServiceInstalled "traefik"; then + _wg_traefik_installed=1 + fi + if [[ -n "$domain_full" && $_wg_traefik_installed -eq 1 ]]; then + wg_host_value="$host_setup" + isNotice "Domain + Traefik present — peer configs will use $wg_host_value" + else + wg_host_value="${public_ip_v4:-127.0.0.1}" + if [[ -n "$domain_full" && $_wg_traefik_installed -eq 0 ]]; then + isNotice "Domain configured but Traefik not installed — falling back to IP $wg_host_value so peer configs actually resolve." + else + isNotice "No domain configured — peer configs will use IP $wg_host_value (LAN only)" + fi + fi + tagsManagerUpdateUniversalTag "$wg_compose_file" "PUBLIC_IP_TAG" "$wg_host_value" + isSuccessful "WG_HOST set to $wg_host_value" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Enabling IP forwarding" + echo "" + + # Drop in /etc/sysctl.d/99-libreportal-wireguard.conf + reload — the + # whole thing runs as root through libreportal-appcfg so the manager + # never needs blanket /etc write or `sudo sysctl` itself. + local result + result=$(runAppCfg wireguard-ip-forward) + checkSuccess "Enabling IPv4 IP Forwarding (sysctl drop-in + reload)" +} + +wireguard_install_post_start() +{ + local app_name="$1" + + ((menu_number++)) + echo "" + echo "---- $menu_number. Restarting $app_name after firewall changes" + echo "" + + dockerComposeRestart $app_name +} diff --git a/containers/wireguard/wireguard.sh b/containers/wireguard/wireguard.sh deleted file mode 100755 index 0b04673..0000000 --- a/containers/wireguard/wireguard.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/bin/bash - -# Category : Networking -# Description : Wireguard Easy - VPN Server (c/u/s/r/i): - -installWireguard() -{ - local config_variables="$1" - - if [[ "$wireguard" == *[cCtTuUsSrRiI]* ]]; then - dockerConfigSetupToContainer silent wireguard; - local app_name=$CFG_WIREGUARD_APP_NAME - initializeAppVariables $app_name; - fi - - if [[ "$wireguard" == *[cC]* ]]; then - editAppConfig $app_name; - fi - - if [[ "$wireguard" == *[uU]* ]]; then - dockerUninstallApp $app_name; - fi - - if [[ "$wireguard" == *[sS]* ]]; then - dockerComposeDown $app_name; - fi - - if [[ "$wireguard" == *[rR]* ]]; then - dockerComposeRestart $app_name; - fi - - if [[ "$wireguard" == *[iI]* ]]; then - isHeader "Install $app_name" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Checking if $app_name can be installed." - echo "" - - # Host-conflict guard: a host-level WireGuard (e.g. the angristan - # wireguard-install script — marker /etc/wireguard/params) collides with - # this container on the wg kernel module + UDP 51820. Abort if present. - if [[ -e /etc/wireguard/params ]]; then - isError "WireGuard is already installed on the host — this conflicts with the $app_name app." - isError "Installation is now aborting..." - dockerUninstallApp "$app_name" - return 1 - fi - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up install folder and config file for $app_name." - echo "" - - dockerConfigSetupToContainer "loud" "$app_name" "install" "$config_variables"; - isSuccessful "Install folders and Config files have been setup for $app_name." - - ((menu_number++)) - echo "" - - - ((menu_number++)) - echo "" - echo "---- $menu_number. Setting up the $app_name docker-compose.yml file." - echo "" - - dockerComposeSetupFile $app_name; - - monitoringToggleAppConfig "$app_name" "docker-compose.yml"; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Resolving wireguard tunnel subnet (WG_DEFAULT_ADDRESS)" - echo "" - - # Generate-once-and-persist tunnel subnet. Second-octet 200-250 is - # outside the docker network generator range (100-149), so the two - # subnets cannot collide. Reusing the persisted value keeps existing - # peer configs valid across reinstalls. - local _wg_compose_for_subnet="$containers_dir$app_name/docker-compose.yml" - if [[ -z "$CFG_WIREGUARD_SUBNET" ]]; then - local _wg_second=$(( RANDOM % 51 + 200 )) # 200-250 - local _wg_third=$(( RANDOM % 256 )) # 0-255 - CFG_WIREGUARD_SUBNET="10.${_wg_second}.${_wg_third}.0" - updateConfigOption "CFG_WIREGUARD_SUBNET" "$CFG_WIREGUARD_SUBNET" - isSuccessful "Generated wireguard tunnel subnet: $CFG_WIREGUARD_SUBNET" - else - isNotice "Reusing existing wireguard tunnel subnet: $CFG_WIREGUARD_SUBNET" - fi - # wg-easy expects the address pattern `.x` (literal x). - local _wg_addr_pattern="${CFG_WIREGUARD_SUBNET%.0}.x" - tagsManagerUpdateUniversalTag "$_wg_compose_for_subnet" "WIREGUARD_SUBNET_TAG" "$_wg_addr_pattern" - isSuccessful "WG_DEFAULT_ADDRESS set to $_wg_addr_pattern" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Resolving WG_HOST for peer configs" - echo "" - - local wg_compose_file="$containers_dir$app_name/docker-compose.yml" - local wg_host_value="" - local _wg_traefik_installed=0 - if declare -f checkServiceInstalled >/dev/null 2>&1 && checkServiceInstalled "traefik"; then - _wg_traefik_installed=1 - fi - if [[ -n "$domain_full" && $_wg_traefik_installed -eq 1 ]]; then - wg_host_value="$host_setup" - isNotice "Domain + Traefik present — peer configs will use $wg_host_value" - else - wg_host_value="${public_ip_v4:-127.0.0.1}" - if [[ -n "$domain_full" && $_wg_traefik_installed -eq 0 ]]; then - isNotice "Domain configured but Traefik not installed — falling back to IP $wg_host_value so peer configs actually resolve." - else - isNotice "No domain configured — peer configs will use IP $wg_host_value (LAN only)" - fi - fi - tagsManagerUpdateUniversalTag "$wg_compose_file" "PUBLIC_IP_TAG" "$wg_host_value" - isSuccessful "WG_HOST set to $wg_host_value" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Enabling IP forwarding" - echo "" - - # Drop in /etc/sysctl.d/99-libreportal-wireguard.conf + reload — the - # whole thing runs as root through libreportal-appcfg so the manager - # never needs blanket /etc write or `sudo sysctl` itself. - local result=$(runAppCfg wireguard-ip-forward) - checkSuccess "Enabling IPv4 IP Forwarding (sysctl drop-in + reload)" - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating file permissions before starting." - echo "" - - fixPermissionsBeforeStart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running the docker-compose.yml to Install $app_name" - echo "" - - dockerComposeUpdateAndStartApp $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Restarting $app_name after firewall changes" - echo "" - - dockerComposeRestart $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Application specific updates (if required)" - echo "" - - appUpdateSpecifics $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Running Headscale setup (if required)" - echo "" - - setupHeadscale $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Adding $app_name to the Apps Database table." - echo "" - - databaseInstallApp $app_name; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Updating WebUI config file." - echo "" - - webuiContainerSetup $app_name install; - - ((menu_number++)) - echo "" - echo "---- $menu_number. Refreshing monitoring integration." - echo "" - - monitoringRefreshAll; - - ((menu_number++)) - echo "" - echo "---- $menu_number. You can find $app_name files at $containers_dir$app_name" - echo "" - echo " You can now navigate to your $app_name service using any of the options below : " - echo "" - - menuShowFinalMessages $app_name; - - menu_number=0 - #sleep 3s - cd - fi - wireguard=n -} diff --git a/scripts/app/install/app_install.sh b/scripts/app/install/app_install.sh index 2cda39a..e15c182 100644 --- a/scripts/app/install/app_install.sh +++ b/scripts/app/install/app_install.sh @@ -58,12 +58,10 @@ _appPostStartIntegrations() databaseInstallApp "$app_name" webuiContainerSetup "$app_name" install - # Monitoring registration — 6 of the 31 apps used to call these inline. - # Idempotent + no-op-safe for apps without monitoring tags, so we run - # them unconditionally now and let each function handle its own gating. - if declare -F monitoringToggleAppConfig >/dev/null 2>&1; then - monitoringToggleAppConfig "$app_name" "docker-compose.yml" 2>/dev/null || true - fi + # Scrape-target + dashboard re-gather. The compose-level toggle ran + # already (post-compose, so the running container reflects it). + # monitoringRefreshAll is self-correcting and no-ops when Prometheus + # / Grafana aren't installed. if declare -F monitoringRefreshAll >/dev/null 2>&1; then monitoringRefreshAll 2>/dev/null || true fi @@ -126,6 +124,18 @@ installApp() echo "---- $menu_number. Setting up the $app_name docker-compose.yml." echo "" dockerComposeSetupFile "$app_name" + + # Compose-level monitoring toggle MUST run before docker-compose up + # — the compose file is the source of truth for the running + # container, so editing it post-start wouldn't take effect until + # the next restart. Idempotent + no-op for apps without a marker + # block; apps that toggle additional files (authelia config.yml, + # traefik traefik.yml, unbound unbound.conf …) call it again from + # their _install_post_compose hook. + if declare -F monitoringToggleAppConfig >/dev/null 2>&1; then + monitoringToggleAppConfig "$app_name" "docker-compose.yml" 2>/dev/null || true + fi + _appCallHook "${app_slug}_install_post_compose" "$app_name" # Optional .env handling — apps that ship a .env in their template diff --git a/scripts/source/files/arrays/function_manifest.sh b/scripts/source/files/arrays/function_manifest.sh index dd39f24..74251f3 100644 --- a/scripts/source/files/arrays/function_manifest.sh +++ b/scripts/source/files/arrays/function_manifest.sh @@ -12,6 +12,8 @@ # "containers" entries — see LP_FN_ROOT below. declare -gA LP_FN_MAP=( [acquireSingletonLock]="crontab/task/crontab_task_processor.sh" + [adguard_install_message_data]="adguard/scripts/adguard_install_hooks.sh" + [adguard_install_post_start]="adguard/scripts/adguard_install_hooks.sh" [adoptDockerSubnet]="checks/requirements/check_docker_network.sh" [appAdguardApplyDnsUpdater]="adguard/tools/adguard_apply_dns_updater.sh" [appAdguardResetPassword]="adguard/tools/adguard_reset_password.sh" @@ -134,6 +136,10 @@ declare -gA LP_FN_MAP=( [authAdapter_nextcloud_setAdmin]="nextcloud/scripts/nextcloud_auth.sh" [authAdapter_nextcloud_setPassword]="nextcloud/scripts/nextcloud_auth.sh" [authAdapter_traefik_setPassword]="traefik/scripts/traefik_auth.sh" + [authelia_install_post]="authelia/scripts/authelia_install_hooks.sh" + [authelia_install_post_compose]="authelia/scripts/authelia_install_hooks.sh" + [authelia_install_post_start]="authelia/scripts/authelia_install_hooks.sh" + [authelia_install_pre]="authelia/scripts/authelia_install_hooks.sh" [authPersistCfg]="app/auth_adapter.sh" [authToolArg]="app/auth_adapter.sh" [backupAllApps]="backup/app/backup_app_all.sh" @@ -183,6 +189,7 @@ declare -gA LP_FN_MAP=( [backupSystemConfig]="backup/system/backup_system.sh" [backupVerifySnapshot]="backup/verify/backup_verify.sh" [_bookstackArtisan]="bookstack/scripts/bookstack_auth.sh" + [bookstack_install_post_start]="bookstack/scripts/bookstack_install_hooks.sh" [borgArchiveName]="backup/engine/borg_env.sh" [borgBackupAppToLocation]="backup/engine/borg_backup.sh" [borgBackupSystemToLocation]="backup/engine/borg_backup.sh" @@ -423,15 +430,20 @@ declare -gA LP_FN_MAP=( [gitCheckGitDetails]="update/git/check_git_details.sh" [gitCleanInstallBackups]="update/backup/install_git_backup.sh" [_giteaCmd]="gitea/scripts/gitea_auth.sh" + [gitea_install_post_compose]="gitea/scripts/gitea_install_hooks.sh" [gitFolderResetAndBackup]="update/backup/reset_git_backup.sh" [gitPerformUpdate]="update/backup/reset_git_backup.sh" [gitReset]="update/git/reset_git.sh" [gitUntrackFiles]="update/git/untrack_files.sh" [gitUseExistingBackup]="update/backup/use_git_backup.sh" + [gluetun_install_post_start]="gluetun/scripts/gluetun_install_hooks.sh" [gluetunRouteExistingAppsPrompt]="gluetun/scripts/gluetun_route_apps.sh" + [grafana_install_post_start]="grafana/scripts/grafana_install_hooks.sh" + [grafana_install_pre]="grafana/scripts/grafana_install_hooks.sh" [hashPassword]="config/password/password_hash.sh" [headscaleCommands]="headscale/scripts/headscale_commands.sh" [headscaleEditConfig]="headscale/scripts/headscale_edit_config.sh" + [headscale_install_post_compose]="headscale/scripts/headscale_install_hooks.sh" [healthLogError]="crontab/task/crontab_check_processor.sh" [healthLogInfo]="crontab/task/crontab_check_processor.sh" [healthLogSuccess]="crontab/task/crontab_check_processor.sh" @@ -448,15 +460,11 @@ declare -gA LP_FN_MAP=( [hostSshSetPasswordAuth]="ssh/host_access.sh" [hostSshUser]="ssh/host_access.sh" [initializeAppVariables]="network/variables/variables_init_app.sh" - [installAdguard]="adguard/adguard.sh" [installApp]="app/install/app_install.sh" [installArch]="os/install/arch.sh" - [installAuthelia]="authelia/authelia.sh" - [installBookstack]="bookstack/bookstack.sh" [installCrontab]="crontab/crontab_install.sh" [installCrowdsec]="crowdsec/crowdsec.sh" [installCrowdsecHost]="crowdsec/scripts/crowdsec_install_host.sh" - [installDashy]="dashy/dashy.sh" [installDebianUbuntu]="os/install/ubuntu.sh" [installDockerNetwork]="docker/network/network_setup.sh" [installDockerRooted]="docker/install/rooted/rooted_docker.sh" @@ -465,44 +473,20 @@ declare -gA LP_FN_MAP=( [installDockerRootless]="docker/install/rootless/rootless_docker.sh" [installDockerRootlessStartSetup]="docker/install/rootless/rootless_start_setup.sh" [installDockerRootlessUser]="docker/install/rootless/rootless_user.sh" - [installFocalboard]="focalboard/focalboard.sh" - [installGitea]="gitea/gitea.sh" - [installGluetun]="gluetun/gluetun.sh" - [installGrafana]="grafana/grafana.sh" - [installHeadscale]="headscale/headscale.sh" - [installInvidious]="invidious/invidious.sh" - [installIpinfo]="ipinfo/ipinfo.sh" - [installJellyfin]="jellyfin/jellyfin.sh" - [installJitsimeet]="jitsimeet/jitsimeet.sh" [installLibrePortal]="libreportal/libreportal.sh" [installLibrePortalAppWebUI]="webui/webui_install_app.sh" [installLibrePortalImageWebUI]="webui/webui_install_image.sh" [installLibrePortalWebUITaskService]="webui/webui_install_systemd.sh" - [installMastodon]="mastodon/mastodon.sh" - [installMoneyapp]="moneyapp/moneyapp.sh" - [installNextcloud]="nextcloud/nextcloud.sh" - [installOllama]="ollama/ollama.sh" - [installOnlyoffice]="onlyoffice/onlyoffice.sh" [installOptionalMetricsApps]="start/start_recommended.sh" - [installOwncloud]="owncloud/owncloud.sh" - [installPihole]="pihole/pihole.sh" - [installPrometheus]="prometheus/prometheus.sh" [installRecommendedApps]="start/start_recommended.sh" [installResticHost]="install/install_restic.sh" [installResticMigrateLegacyPasswords]="install/install_restic.sh" [installRootlessApparmorForPasta]="docker/install/rootless/rootless_apparmor.sh" - [installSearxng]="searxng/searxng.sh" - [installSpeedtest]="speedtest/speedtest.sh" [installSQLiteDatabase]="database/install_sqlite.sh" [installSSLCertificate]="install/install_certificate.sh" [installSwapfile]="install/install_swapfile.sh" - [installTraefik]="traefik/traefik.sh" - [installTrilium]="trilium/trilium.sh" [installUFW]="install/install_ufw.sh" [installUFWDocker]="install/install_ufwd.sh" - [installUnbound]="unbound/unbound.sh" - [installVaultwarden]="vaultwarden/vaultwarden.sh" - [installWireguard]="wireguard/wireguard.sh" [_invidiousBcrypt]="invidious/scripts/invidious_auth.sh" [_invidiousPsql]="invidious/scripts/invidious_auth.sh" [invidiousToolsMenu]="menu/tools/manage_invidious.sh" @@ -526,6 +510,9 @@ declare -gA LP_FN_MAP=( [isQuestion]="menu/message/markers.sh" [isSetupWizardComplete]="setup/setup_lock.sh" [isSuccessful]="menu/message/markers.sh" + [jitsimeet_install_post_compose]="jitsimeet/scripts/jitsimeet_install_hooks.sh" + [jitsimeet_install_post_setup]="jitsimeet/scripts/jitsimeet_install_hooks.sh" + [jitsimeet_install_post_start]="jitsimeet/scripts/jitsimeet_install_hooks.sh" [kopiaBackupAppToLocation]="backup/engine/kopia_backup.sh" [kopiaBackupSystemToLocation]="backup/engine/kopia_backup.sh" [kopiaCheckLocation]="backup/engine/kopia_check.sh" @@ -605,6 +592,8 @@ declare -gA LP_FN_MAP=( [migrateRunHook]="migrate/migrate_hooks.sh" [migrateSystem]="migrate/migrate_apply.sh" [migrateUrlRewriteEnabled]="migrate/migrate_url_rewrite.sh" + [moneyapp_install_post_compose]="moneyapp/scripts/moneyapp_install_hooks.sh" + [moneyapp_install_pre]="moneyapp/scripts/moneyapp_install_hooks.sh" [monitoringAppEnabled]="network/monitoring/monitoring.sh" [monitoringInstalledApps]="network/monitoring/monitoring.sh" [monitoringIsInstalled]="network/monitoring/monitoring.sh" @@ -616,7 +605,9 @@ declare -gA LP_FN_MAP=( [moveFile]="function/file/move_file.sh" [_nextcloudOcc]="nextcloud/scripts/nextcloud_auth.sh" [_nextcloudOccWithPass]="nextcloud/scripts/nextcloud_auth.sh" + [onlyoffice_install_message_data]="onlyoffice/scripts/onlyoffice_install_hooks.sh" [openFifoReader]="crontab/task/crontab_task_processor.sh" + [owncloud_install_post_compose]="owncloud/scripts/owncloud_install_hooks.sh" [passwordValidation]="function/validation/password.sh" [peerAdd]="peer/peer_add.sh" [peerCheckAll]="peer/peer_check.sh" @@ -667,6 +658,8 @@ declare -gA LP_FN_MAP=( [portStoreMapping]="network/ports/allocation/port_store_mapping.sh" [portUpdateComposeTags]="network/ports/allocation/port_update_compose_tags.sh" [processBcryptPassword]="config/password/bcrypt/password_process_bcrypt.sh" + [prometheus_install_post_compose]="prometheus/scripts/prometheus_install_hooks.sh" + [prometheus_install_post_start]="prometheus/scripts/prometheus_install_hooks.sh" [readTaskField]="crontab/task/crontab_task_processor.sh" [reconcileConfigFile]="config/core/variables/config_scan_variables.sh" [reconcileContainersTopOwnership]="function/permission/libreportal_folders.sh" @@ -754,6 +747,7 @@ declare -gA LP_FN_MAP=( [run_task_processor]="crontab/task/crontab_task_processor.sh" [scanConfigsForRandomPassword]="config/password/password_update_all.sh" [scanFileForRandomPasswordKeysUsers]="config/password/password_scan_file.sh" + [searxng_install_post_start]="searxng/scripts/searxng_install_hooks.sh" [setupApply]="setup/setup_apply.sh" [setupApplyConfig]="setup/setup_apply.sh" [setupApplyFinalize]="setup/setup_apply.sh" @@ -805,9 +799,13 @@ declare -gA LP_FN_MAP=( [tailscaleInstallToContainer]="headscale/scripts/tailscale_install.sh" [toolArgsGet]="docker/app/functions/function_app_tool.sh" [toolsMenu]="menu/tools/manage_main.sh" + [traefik_install_post_compose]="traefik/scripts/traefik_install_hooks.sh" + [traefik_install_pre]="traefik/scripts/traefik_install_hooks.sh" [traefikSetupLabelsMiddlewares]="network/traefik/traefik_middlewares.sh" [traefikSetupLoginCredentials]="network/traefik/traefik_login_credentials.sh" [traefikUpdateWhitelist]="network/traefik/traefik_whitelist.sh" + [trilium_install_post_start]="trilium/scripts/trilium_install_hooks.sh" + [unbound_install_post_compose]="unbound/scripts/unbound_install_hooks.sh" [uninstallCrowdsec]="crowdsec/crowdsec.sh" [uninstallDockerRootless]="docker/install/rootless/rootless_uninstall.sh" [updateAppConfig]="webui/data/generators/apps/webui_app_config.sh" @@ -887,6 +885,9 @@ declare -gA LP_FN_MAP=( [webuiUpdateSystemConfig]="webui/data/generators/config/webui_update_config.sh" [webuiValidateConfigValue]="webui/data/generators/config/webui_update_config.sh" [whitelistPortUpdater]="docker/whitelist_port_updater.sh" + [wireguard_install_post_compose]="wireguard/scripts/wireguard_install_hooks.sh" + [wireguard_install_post_start]="wireguard/scripts/wireguard_install_hooks.sh" + [wireguard_install_pre]="wireguard/scripts/wireguard_install_hooks.sh" [writeAtomic]="crontab/task/crontab_task_processor.sh" [zipFile]="function/file/zip_file.sh" ) @@ -895,6 +896,8 @@ declare -gA LP_FN_MAP=( # LP_FN_MAP; used by the loader / debugging tools. declare -gA LP_FN_ROOT=( [acquireSingletonLock]="scripts" + [adguard_install_message_data]="containers" + [adguard_install_post_start]="containers" [adoptDockerSubnet]="scripts" [appAdguardApplyDnsUpdater]="containers" [appAdguardResetPassword]="containers" @@ -1017,6 +1020,10 @@ declare -gA LP_FN_ROOT=( [authAdapter_nextcloud_setAdmin]="containers" [authAdapter_nextcloud_setPassword]="containers" [authAdapter_traefik_setPassword]="containers" + [authelia_install_post]="containers" + [authelia_install_post_compose]="containers" + [authelia_install_post_start]="containers" + [authelia_install_pre]="containers" [authPersistCfg]="scripts" [authToolArg]="scripts" [backupAllApps]="scripts" @@ -1066,6 +1073,7 @@ declare -gA LP_FN_ROOT=( [backupSystemConfig]="scripts" [backupVerifySnapshot]="scripts" [_bookstackArtisan]="containers" + [bookstack_install_post_start]="containers" [borgArchiveName]="scripts" [borgBackupAppToLocation]="scripts" [borgBackupSystemToLocation]="scripts" @@ -1306,15 +1314,20 @@ declare -gA LP_FN_ROOT=( [gitCheckGitDetails]="scripts" [gitCleanInstallBackups]="scripts" [_giteaCmd]="containers" + [gitea_install_post_compose]="containers" [gitFolderResetAndBackup]="scripts" [gitPerformUpdate]="scripts" [gitReset]="scripts" [gitUntrackFiles]="scripts" [gitUseExistingBackup]="scripts" + [gluetun_install_post_start]="containers" [gluetunRouteExistingAppsPrompt]="containers" + [grafana_install_post_start]="containers" + [grafana_install_pre]="containers" [hashPassword]="scripts" [headscaleCommands]="containers" [headscaleEditConfig]="containers" + [headscale_install_post_compose]="containers" [healthLogError]="scripts" [healthLogInfo]="scripts" [healthLogSuccess]="scripts" @@ -1331,15 +1344,11 @@ declare -gA LP_FN_ROOT=( [hostSshSetPasswordAuth]="scripts" [hostSshUser]="scripts" [initializeAppVariables]="scripts" - [installAdguard]="containers" [installApp]="scripts" [installArch]="scripts" - [installAuthelia]="containers" - [installBookstack]="containers" [installCrontab]="scripts" [installCrowdsec]="containers" [installCrowdsecHost]="containers" - [installDashy]="containers" [installDebianUbuntu]="scripts" [installDockerNetwork]="scripts" [installDockerRooted]="scripts" @@ -1348,44 +1357,20 @@ declare -gA LP_FN_ROOT=( [installDockerRootless]="scripts" [installDockerRootlessStartSetup]="scripts" [installDockerRootlessUser]="scripts" - [installFocalboard]="containers" - [installGitea]="containers" - [installGluetun]="containers" - [installGrafana]="containers" - [installHeadscale]="containers" - [installInvidious]="containers" - [installIpinfo]="containers" - [installJellyfin]="containers" - [installJitsimeet]="containers" [installLibrePortal]="containers" [installLibrePortalAppWebUI]="scripts" [installLibrePortalImageWebUI]="scripts" [installLibrePortalWebUITaskService]="scripts" - [installMastodon]="containers" - [installMoneyapp]="containers" - [installNextcloud]="containers" - [installOllama]="containers" - [installOnlyoffice]="containers" [installOptionalMetricsApps]="scripts" - [installOwncloud]="containers" - [installPihole]="containers" - [installPrometheus]="containers" [installRecommendedApps]="scripts" [installResticHost]="scripts" [installResticMigrateLegacyPasswords]="scripts" [installRootlessApparmorForPasta]="scripts" - [installSearxng]="containers" - [installSpeedtest]="containers" [installSQLiteDatabase]="scripts" [installSSLCertificate]="scripts" [installSwapfile]="scripts" - [installTraefik]="containers" - [installTrilium]="containers" [installUFW]="scripts" [installUFWDocker]="scripts" - [installUnbound]="containers" - [installVaultwarden]="containers" - [installWireguard]="containers" [_invidiousBcrypt]="containers" [_invidiousPsql]="containers" [invidiousToolsMenu]="scripts" @@ -1409,6 +1394,9 @@ declare -gA LP_FN_ROOT=( [isQuestion]="scripts" [isSetupWizardComplete]="scripts" [isSuccessful]="scripts" + [jitsimeet_install_post_compose]="containers" + [jitsimeet_install_post_setup]="containers" + [jitsimeet_install_post_start]="containers" [kopiaBackupAppToLocation]="scripts" [kopiaBackupSystemToLocation]="scripts" [kopiaCheckLocation]="scripts" @@ -1488,6 +1476,8 @@ declare -gA LP_FN_ROOT=( [migrateRunHook]="scripts" [migrateSystem]="scripts" [migrateUrlRewriteEnabled]="scripts" + [moneyapp_install_post_compose]="containers" + [moneyapp_install_pre]="containers" [monitoringAppEnabled]="scripts" [monitoringInstalledApps]="scripts" [monitoringIsInstalled]="scripts" @@ -1499,7 +1489,9 @@ declare -gA LP_FN_ROOT=( [moveFile]="scripts" [_nextcloudOcc]="containers" [_nextcloudOccWithPass]="containers" + [onlyoffice_install_message_data]="containers" [openFifoReader]="scripts" + [owncloud_install_post_compose]="containers" [passwordValidation]="scripts" [peerAdd]="scripts" [peerCheckAll]="scripts" @@ -1550,6 +1542,8 @@ declare -gA LP_FN_ROOT=( [portStoreMapping]="scripts" [portUpdateComposeTags]="scripts" [processBcryptPassword]="scripts" + [prometheus_install_post_compose]="containers" + [prometheus_install_post_start]="containers" [readTaskField]="scripts" [reconcileConfigFile]="scripts" [reconcileContainersTopOwnership]="scripts" @@ -1637,6 +1631,7 @@ declare -gA LP_FN_ROOT=( [run_task_processor]="scripts" [scanConfigsForRandomPassword]="scripts" [scanFileForRandomPasswordKeysUsers]="scripts" + [searxng_install_post_start]="containers" [setupApply]="scripts" [setupApplyConfig]="scripts" [setupApplyFinalize]="scripts" @@ -1688,9 +1683,13 @@ declare -gA LP_FN_ROOT=( [tailscaleInstallToContainer]="containers" [toolArgsGet]="scripts" [toolsMenu]="scripts" + [traefik_install_post_compose]="containers" + [traefik_install_pre]="containers" [traefikSetupLabelsMiddlewares]="scripts" [traefikSetupLoginCredentials]="scripts" [traefikUpdateWhitelist]="scripts" + [trilium_install_post_start]="containers" + [unbound_install_post_compose]="containers" [uninstallCrowdsec]="containers" [uninstallDockerRootless]="scripts" [updateAppConfig]="scripts" @@ -1770,6 +1769,9 @@ declare -gA LP_FN_ROOT=( [webuiUpdateSystemConfig]="scripts" [webuiValidateConfigValue]="scripts" [whitelistPortUpdater]="scripts" + [wireguard_install_post_compose]="containers" + [wireguard_install_post_start]="containers" + [wireguard_install_pre]="containers" [writeAtomic]="scripts" [zipFile]="scripts" ) @@ -1798,6 +1800,8 @@ LP_EAGER_FILES=( # re-invokes. Sourced inline instead of eval-in-loop because bash # parses one large file faster than it evals snippets at startup. acquireSingletonLock() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; acquireSingletonLock "$@"; } +adguard_install_message_data() { source "${install_containers_dir}adguard/scripts/adguard_install_hooks.sh"; adguard_install_message_data "$@"; } +adguard_install_post_start() { source "${install_containers_dir}adguard/scripts/adguard_install_hooks.sh"; adguard_install_post_start "$@"; } adoptDockerSubnet() { source "${install_scripts_dir}checks/requirements/check_docker_network.sh"; adoptDockerSubnet "$@"; } appAdguardApplyDnsUpdater() { source "${install_containers_dir}adguard/tools/adguard_apply_dns_updater.sh"; appAdguardApplyDnsUpdater "$@"; } appAdguardResetPassword() { source "${install_containers_dir}adguard/tools/adguard_reset_password.sh"; appAdguardResetPassword "$@"; } @@ -1920,6 +1924,10 @@ authAdapter_nextcloud_listUsers() { source "${install_containers_dir}nextcloud/s authAdapter_nextcloud_setAdmin() { source "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; authAdapter_nextcloud_setAdmin "$@"; } authAdapter_nextcloud_setPassword() { source "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; authAdapter_nextcloud_setPassword "$@"; } authAdapter_traefik_setPassword() { source "${install_containers_dir}traefik/scripts/traefik_auth.sh"; authAdapter_traefik_setPassword "$@"; } +authelia_install_post() { source "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_post "$@"; } +authelia_install_post_compose() { source "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_post_compose "$@"; } +authelia_install_post_start() { source "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_post_start "$@"; } +authelia_install_pre() { source "${install_containers_dir}authelia/scripts/authelia_install_hooks.sh"; authelia_install_pre "$@"; } authPersistCfg() { source "${install_scripts_dir}app/auth_adapter.sh"; authPersistCfg "$@"; } authToolArg() { source "${install_scripts_dir}app/auth_adapter.sh"; authToolArg "$@"; } backupAllApps() { source "${install_scripts_dir}backup/app/backup_app_all.sh"; backupAllApps "$@"; } @@ -1969,6 +1977,7 @@ backupSshKeySet() { source "${install_scripts_dir}backup/locations/location_ssh. backupSystemConfig() { source "${install_scripts_dir}backup/system/backup_system.sh"; backupSystemConfig "$@"; } backupVerifySnapshot() { source "${install_scripts_dir}backup/verify/backup_verify.sh"; backupVerifySnapshot "$@"; } _bookstackArtisan() { source "${install_containers_dir}bookstack/scripts/bookstack_auth.sh"; _bookstackArtisan "$@"; } +bookstack_install_post_start() { source "${install_containers_dir}bookstack/scripts/bookstack_install_hooks.sh"; bookstack_install_post_start "$@"; } borgArchiveName() { source "${install_scripts_dir}backup/engine/borg_env.sh"; borgArchiveName "$@"; } borgBackupAppToLocation() { source "${install_scripts_dir}backup/engine/borg_backup.sh"; borgBackupAppToLocation "$@"; } borgBackupSystemToLocation() { source "${install_scripts_dir}backup/engine/borg_backup.sh"; borgBackupSystemToLocation "$@"; } @@ -2209,15 +2218,20 @@ gitCheckForUpdate() { source "${install_scripts_dir}update/git/checks/update_git gitCheckGitDetails() { source "${install_scripts_dir}update/git/check_git_details.sh"; gitCheckGitDetails "$@"; } gitCleanInstallBackups() { source "${install_scripts_dir}update/backup/install_git_backup.sh"; gitCleanInstallBackups "$@"; } _giteaCmd() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; _giteaCmd "$@"; } +gitea_install_post_compose() { source "${install_containers_dir}gitea/scripts/gitea_install_hooks.sh"; gitea_install_post_compose "$@"; } gitFolderResetAndBackup() { source "${install_scripts_dir}update/backup/reset_git_backup.sh"; gitFolderResetAndBackup "$@"; } gitPerformUpdate() { source "${install_scripts_dir}update/backup/reset_git_backup.sh"; gitPerformUpdate "$@"; } gitReset() { source "${install_scripts_dir}update/git/reset_git.sh"; gitReset "$@"; } gitUntrackFiles() { source "${install_scripts_dir}update/git/untrack_files.sh"; gitUntrackFiles "$@"; } gitUseExistingBackup() { source "${install_scripts_dir}update/backup/use_git_backup.sh"; gitUseExistingBackup "$@"; } +gluetun_install_post_start() { source "${install_containers_dir}gluetun/scripts/gluetun_install_hooks.sh"; gluetun_install_post_start "$@"; } gluetunRouteExistingAppsPrompt() { source "${install_containers_dir}gluetun/scripts/gluetun_route_apps.sh"; gluetunRouteExistingAppsPrompt "$@"; } +grafana_install_post_start() { source "${install_containers_dir}grafana/scripts/grafana_install_hooks.sh"; grafana_install_post_start "$@"; } +grafana_install_pre() { source "${install_containers_dir}grafana/scripts/grafana_install_hooks.sh"; grafana_install_pre "$@"; } hashPassword() { source "${install_scripts_dir}config/password/password_hash.sh"; hashPassword "$@"; } headscaleCommands() { source "${install_containers_dir}headscale/scripts/headscale_commands.sh"; headscaleCommands "$@"; } headscaleEditConfig() { source "${install_containers_dir}headscale/scripts/headscale_edit_config.sh"; headscaleEditConfig "$@"; } +headscale_install_post_compose() { source "${install_containers_dir}headscale/scripts/headscale_install_hooks.sh"; headscale_install_post_compose "$@"; } healthLogError() { source "${install_scripts_dir}crontab/task/crontab_check_processor.sh"; healthLogError "$@"; } healthLogInfo() { source "${install_scripts_dir}crontab/task/crontab_check_processor.sh"; healthLogInfo "$@"; } healthLogSuccess() { source "${install_scripts_dir}crontab/task/crontab_check_processor.sh"; healthLogSuccess "$@"; } @@ -2234,15 +2248,11 @@ hostSshRefreshUi() { source "${install_scripts_dir}ssh/host_access.sh"; hostSshR hostSshSetPasswordAuth() { source "${install_scripts_dir}ssh/host_access.sh"; hostSshSetPasswordAuth "$@"; } hostSshUser() { source "${install_scripts_dir}ssh/host_access.sh"; hostSshUser "$@"; } initializeAppVariables() { source "${install_scripts_dir}network/variables/variables_init_app.sh"; initializeAppVariables "$@"; } -installAdguard() { source "${install_containers_dir}adguard/adguard.sh"; installAdguard "$@"; } installApp() { source "${install_scripts_dir}app/install/app_install.sh"; installApp "$@"; } installArch() { source "${install_scripts_dir}os/install/arch.sh"; installArch "$@"; } -installAuthelia() { source "${install_containers_dir}authelia/authelia.sh"; installAuthelia "$@"; } -installBookstack() { source "${install_containers_dir}bookstack/bookstack.sh"; installBookstack "$@"; } installCrontab() { source "${install_scripts_dir}crontab/crontab_install.sh"; installCrontab "$@"; } installCrowdsec() { source "${install_containers_dir}crowdsec/crowdsec.sh"; installCrowdsec "$@"; } installCrowdsecHost() { source "${install_containers_dir}crowdsec/scripts/crowdsec_install_host.sh"; installCrowdsecHost "$@"; } -installDashy() { source "${install_containers_dir}dashy/dashy.sh"; installDashy "$@"; } installDebianUbuntu() { source "${install_scripts_dir}os/install/ubuntu.sh"; installDebianUbuntu "$@"; } installDockerNetwork() { source "${install_scripts_dir}docker/network/network_setup.sh"; installDockerNetwork "$@"; } installDockerRooted() { source "${install_scripts_dir}docker/install/rooted/rooted_docker.sh"; installDockerRooted "$@"; } @@ -2251,44 +2261,20 @@ installDockerRootedCompose() { source "${install_scripts_dir}docker/install/root installDockerRootless() { source "${install_scripts_dir}docker/install/rootless/rootless_docker.sh"; installDockerRootless "$@"; } installDockerRootlessStartSetup() { source "${install_scripts_dir}docker/install/rootless/rootless_start_setup.sh"; installDockerRootlessStartSetup "$@"; } installDockerRootlessUser() { source "${install_scripts_dir}docker/install/rootless/rootless_user.sh"; installDockerRootlessUser "$@"; } -installFocalboard() { source "${install_containers_dir}focalboard/focalboard.sh"; installFocalboard "$@"; } -installGitea() { source "${install_containers_dir}gitea/gitea.sh"; installGitea "$@"; } -installGluetun() { source "${install_containers_dir}gluetun/gluetun.sh"; installGluetun "$@"; } -installGrafana() { source "${install_containers_dir}grafana/grafana.sh"; installGrafana "$@"; } -installHeadscale() { source "${install_containers_dir}headscale/headscale.sh"; installHeadscale "$@"; } -installInvidious() { source "${install_containers_dir}invidious/invidious.sh"; installInvidious "$@"; } -installIpinfo() { source "${install_containers_dir}ipinfo/ipinfo.sh"; installIpinfo "$@"; } -installJellyfin() { source "${install_containers_dir}jellyfin/jellyfin.sh"; installJellyfin "$@"; } -installJitsimeet() { source "${install_containers_dir}jitsimeet/jitsimeet.sh"; installJitsimeet "$@"; } installLibrePortal() { source "${install_containers_dir}libreportal/libreportal.sh"; installLibrePortal "$@"; } installLibrePortalAppWebUI() { source "${install_scripts_dir}webui/webui_install_app.sh"; installLibrePortalAppWebUI "$@"; } installLibrePortalImageWebUI() { source "${install_scripts_dir}webui/webui_install_image.sh"; installLibrePortalImageWebUI "$@"; } installLibrePortalWebUITaskService() { source "${install_scripts_dir}webui/webui_install_systemd.sh"; installLibrePortalWebUITaskService "$@"; } -installMastodon() { source "${install_containers_dir}mastodon/mastodon.sh"; installMastodon "$@"; } -installMoneyapp() { source "${install_containers_dir}moneyapp/moneyapp.sh"; installMoneyapp "$@"; } -installNextcloud() { source "${install_containers_dir}nextcloud/nextcloud.sh"; installNextcloud "$@"; } -installOllama() { source "${install_containers_dir}ollama/ollama.sh"; installOllama "$@"; } -installOnlyoffice() { source "${install_containers_dir}onlyoffice/onlyoffice.sh"; installOnlyoffice "$@"; } installOptionalMetricsApps() { source "${install_scripts_dir}start/start_recommended.sh"; installOptionalMetricsApps "$@"; } -installOwncloud() { source "${install_containers_dir}owncloud/owncloud.sh"; installOwncloud "$@"; } -installPihole() { source "${install_containers_dir}pihole/pihole.sh"; installPihole "$@"; } -installPrometheus() { source "${install_containers_dir}prometheus/prometheus.sh"; installPrometheus "$@"; } installRecommendedApps() { source "${install_scripts_dir}start/start_recommended.sh"; installRecommendedApps "$@"; } installResticHost() { source "${install_scripts_dir}install/install_restic.sh"; installResticHost "$@"; } installResticMigrateLegacyPasswords() { source "${install_scripts_dir}install/install_restic.sh"; installResticMigrateLegacyPasswords "$@"; } installRootlessApparmorForPasta() { source "${install_scripts_dir}docker/install/rootless/rootless_apparmor.sh"; installRootlessApparmorForPasta "$@"; } -installSearxng() { source "${install_containers_dir}searxng/searxng.sh"; installSearxng "$@"; } -installSpeedtest() { source "${install_containers_dir}speedtest/speedtest.sh"; installSpeedtest "$@"; } installSQLiteDatabase() { source "${install_scripts_dir}database/install_sqlite.sh"; installSQLiteDatabase "$@"; } installSSLCertificate() { source "${install_scripts_dir}install/install_certificate.sh"; installSSLCertificate "$@"; } installSwapfile() { source "${install_scripts_dir}install/install_swapfile.sh"; installSwapfile "$@"; } -installTraefik() { source "${install_containers_dir}traefik/traefik.sh"; installTraefik "$@"; } -installTrilium() { source "${install_containers_dir}trilium/trilium.sh"; installTrilium "$@"; } installUFW() { source "${install_scripts_dir}install/install_ufw.sh"; installUFW "$@"; } installUFWDocker() { source "${install_scripts_dir}install/install_ufwd.sh"; installUFWDocker "$@"; } -installUnbound() { source "${install_containers_dir}unbound/unbound.sh"; installUnbound "$@"; } -installVaultwarden() { source "${install_containers_dir}vaultwarden/vaultwarden.sh"; installVaultwarden "$@"; } -installWireguard() { source "${install_containers_dir}wireguard/wireguard.sh"; installWireguard "$@"; } _invidiousBcrypt() { source "${install_containers_dir}invidious/scripts/invidious_auth.sh"; _invidiousBcrypt "$@"; } _invidiousPsql() { source "${install_containers_dir}invidious/scripts/invidious_auth.sh"; _invidiousPsql "$@"; } invidiousToolsMenu() { source "${install_scripts_dir}menu/tools/manage_invidious.sh"; invidiousToolsMenu "$@"; } @@ -2312,6 +2298,9 @@ isOptionMenu() { source "${install_scripts_dir}menu/message/markers.sh"; isOptio isQuestion() { source "${install_scripts_dir}menu/message/markers.sh"; isQuestion "$@"; } isSetupWizardComplete() { source "${install_scripts_dir}setup/setup_lock.sh"; isSetupWizardComplete "$@"; } isSuccessful() { source "${install_scripts_dir}menu/message/markers.sh"; isSuccessful "$@"; } +jitsimeet_install_post_compose() { source "${install_containers_dir}jitsimeet/scripts/jitsimeet_install_hooks.sh"; jitsimeet_install_post_compose "$@"; } +jitsimeet_install_post_setup() { source "${install_containers_dir}jitsimeet/scripts/jitsimeet_install_hooks.sh"; jitsimeet_install_post_setup "$@"; } +jitsimeet_install_post_start() { source "${install_containers_dir}jitsimeet/scripts/jitsimeet_install_hooks.sh"; jitsimeet_install_post_start "$@"; } kopiaBackupAppToLocation() { source "${install_scripts_dir}backup/engine/kopia_backup.sh"; kopiaBackupAppToLocation "$@"; } kopiaBackupSystemToLocation() { source "${install_scripts_dir}backup/engine/kopia_backup.sh"; kopiaBackupSystemToLocation "$@"; } kopiaCheckLocation() { source "${install_scripts_dir}backup/engine/kopia_check.sh"; kopiaCheckLocation "$@"; } @@ -2391,6 +2380,8 @@ _migrateResolveLocation() { source "${install_scripts_dir}migrate/migrate_discov migrateRunHook() { source "${install_scripts_dir}migrate/migrate_hooks.sh"; migrateRunHook "$@"; } migrateSystem() { source "${install_scripts_dir}migrate/migrate_apply.sh"; migrateSystem "$@"; } migrateUrlRewriteEnabled() { source "${install_scripts_dir}migrate/migrate_url_rewrite.sh"; migrateUrlRewriteEnabled "$@"; } +moneyapp_install_post_compose() { source "${install_containers_dir}moneyapp/scripts/moneyapp_install_hooks.sh"; moneyapp_install_post_compose "$@"; } +moneyapp_install_pre() { source "${install_containers_dir}moneyapp/scripts/moneyapp_install_hooks.sh"; moneyapp_install_pre "$@"; } monitoringAppEnabled() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringAppEnabled "$@"; } monitoringInstalledApps() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringInstalledApps "$@"; } monitoringIsInstalled() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringIsInstalled "$@"; } @@ -2402,7 +2393,9 @@ monitoringToggleAppConfig() { source "${install_scripts_dir}network/monitoring/m moveFile() { source "${install_scripts_dir}function/file/move_file.sh"; moveFile "$@"; } _nextcloudOcc() { source "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; _nextcloudOcc "$@"; } _nextcloudOccWithPass() { source "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; _nextcloudOccWithPass "$@"; } +onlyoffice_install_message_data() { source "${install_containers_dir}onlyoffice/scripts/onlyoffice_install_hooks.sh"; onlyoffice_install_message_data "$@"; } openFifoReader() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; openFifoReader "$@"; } +owncloud_install_post_compose() { source "${install_containers_dir}owncloud/scripts/owncloud_install_hooks.sh"; owncloud_install_post_compose "$@"; } passwordValidation() { source "${install_scripts_dir}function/validation/password.sh"; passwordValidation "$@"; } peerAdd() { source "${install_scripts_dir}peer/peer_add.sh"; peerAdd "$@"; } peerCheckAll() { source "${install_scripts_dir}peer/peer_check.sh"; peerCheckAll "$@"; } @@ -2453,6 +2446,8 @@ portsRemoveFromDatabase() { source "${install_scripts_dir}network/ports/core/por portStoreMapping() { source "${install_scripts_dir}network/ports/allocation/port_store_mapping.sh"; portStoreMapping "$@"; } portUpdateComposeTags() { source "${install_scripts_dir}network/ports/allocation/port_update_compose_tags.sh"; portUpdateComposeTags "$@"; } processBcryptPassword() { source "${install_scripts_dir}config/password/bcrypt/password_process_bcrypt.sh"; processBcryptPassword "$@"; } +prometheus_install_post_compose() { source "${install_containers_dir}prometheus/scripts/prometheus_install_hooks.sh"; prometheus_install_post_compose "$@"; } +prometheus_install_post_start() { source "${install_containers_dir}prometheus/scripts/prometheus_install_hooks.sh"; prometheus_install_post_start "$@"; } readTaskField() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; readTaskField "$@"; } reconcileConfigFile() { source "${install_scripts_dir}config/core/variables/config_scan_variables.sh"; reconcileConfigFile "$@"; } reconcileContainersTopOwnership() { source "${install_scripts_dir}function/permission/libreportal_folders.sh"; reconcileContainersTopOwnership "$@"; } @@ -2540,6 +2535,7 @@ runTask() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh run_task_processor() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; run_task_processor "$@"; } scanConfigsForRandomPassword() { source "${install_scripts_dir}config/password/password_update_all.sh"; scanConfigsForRandomPassword "$@"; } scanFileForRandomPasswordKeysUsers() { source "${install_scripts_dir}config/password/password_scan_file.sh"; scanFileForRandomPasswordKeysUsers "$@"; } +searxng_install_post_start() { source "${install_containers_dir}searxng/scripts/searxng_install_hooks.sh"; searxng_install_post_start "$@"; } setupApply() { source "${install_scripts_dir}setup/setup_apply.sh"; setupApply "$@"; } setupApplyConfig() { source "${install_scripts_dir}setup/setup_apply.sh"; setupApplyConfig "$@"; } setupApplyFinalize() { source "${install_scripts_dir}setup/setup_apply.sh"; setupApplyFinalize "$@"; } @@ -2591,9 +2587,13 @@ tagsProcessorTrustedDomains() { source "${install_scripts_dir}config/tags/proces tailscaleInstallToContainer() { source "${install_containers_dir}headscale/scripts/tailscale_install.sh"; tailscaleInstallToContainer "$@"; } toolArgsGet() { source "${install_scripts_dir}docker/app/functions/function_app_tool.sh"; toolArgsGet "$@"; } toolsMenu() { source "${install_scripts_dir}menu/tools/manage_main.sh"; toolsMenu "$@"; } +traefik_install_post_compose() { source "${install_containers_dir}traefik/scripts/traefik_install_hooks.sh"; traefik_install_post_compose "$@"; } +traefik_install_pre() { source "${install_containers_dir}traefik/scripts/traefik_install_hooks.sh"; traefik_install_pre "$@"; } traefikSetupLabelsMiddlewares() { source "${install_scripts_dir}network/traefik/traefik_middlewares.sh"; traefikSetupLabelsMiddlewares "$@"; } traefikSetupLoginCredentials() { source "${install_scripts_dir}network/traefik/traefik_login_credentials.sh"; traefikSetupLoginCredentials "$@"; } traefikUpdateWhitelist() { source "${install_scripts_dir}network/traefik/traefik_whitelist.sh"; traefikUpdateWhitelist "$@"; } +trilium_install_post_start() { source "${install_containers_dir}trilium/scripts/trilium_install_hooks.sh"; trilium_install_post_start "$@"; } +unbound_install_post_compose() { source "${install_containers_dir}unbound/scripts/unbound_install_hooks.sh"; unbound_install_post_compose "$@"; } uninstallCrowdsec() { source "${install_containers_dir}crowdsec/crowdsec.sh"; uninstallCrowdsec "$@"; } uninstallDockerRootless() { source "${install_scripts_dir}docker/install/rootless/rootless_uninstall.sh"; uninstallDockerRootless "$@"; } updateAppConfig() { source "${install_scripts_dir}webui/data/generators/apps/webui_app_config.sh"; updateAppConfig "$@"; } @@ -2673,5 +2673,8 @@ webuiUpdateAppStatus() { source "${install_scripts_dir}webui/data/generators/app webuiUpdateSystemConfig() { source "${install_scripts_dir}webui/data/generators/config/webui_update_config.sh"; webuiUpdateSystemConfig "$@"; } webuiValidateConfigValue() { source "${install_scripts_dir}webui/data/generators/config/webui_update_config.sh"; webuiValidateConfigValue "$@"; } whitelistPortUpdater() { source "${install_scripts_dir}docker/whitelist_port_updater.sh"; whitelistPortUpdater "$@"; } +wireguard_install_post_compose() { source "${install_containers_dir}wireguard/scripts/wireguard_install_hooks.sh"; wireguard_install_post_compose "$@"; } +wireguard_install_post_start() { source "${install_containers_dir}wireguard/scripts/wireguard_install_hooks.sh"; wireguard_install_post_start "$@"; } +wireguard_install_pre() { source "${install_containers_dir}wireguard/scripts/wireguard_install_hooks.sh"; wireguard_install_pre "$@"; } writeAtomic() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; writeAtomic "$@"; } zipFile() { source "${install_scripts_dir}function/file/zip_file.sh"; zipFile "$@"; }