From 49cf5bb221240525eea956cfdbd44de5ea5dd25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Feb 2025 21:26:14 +0100 Subject: [PATCH 001/259] Remove 'reconfigure' option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 2 +- advanced/bash-completion/pihole | 2 +- automated install/basic-install.sh | 52 +++++++++++------------------- pihole | 10 +++--- 4 files changed, 26 insertions(+), 40 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 9ea63b4c..6c6167c0 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -218,7 +218,7 @@ main() { fi if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then - ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \ + ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --repair --unattended || \ echo -e "${basicError}" && exit 1 fi diff --git a/advanced/bash-completion/pihole b/advanced/bash-completion/pihole index 4343cf92..cf99ab73 100644 --- a/advanced/bash-completion/pihole +++ b/advanced/bash-completion/pihole @@ -7,7 +7,7 @@ _pihole() { case "${prev}" in "pihole") - opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query reconfigure regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api" + opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) ;; "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 8b21ccf7..744f9d2c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -142,12 +142,12 @@ EOM ######## Undocumented Flags. Shhh ######## # These are undocumented flags; some of which we can use when repairing an installation # The runUnattended flag is one example of this -reconfigure=false +repair=false runUnattended=false # Check arguments for the undocumented flags for var in "$@"; do case "$var" in - "--reconfigure") reconfigure=true ;; + "--repair") repair=true ;; "--unattended") runUnattended=true ;; esac done @@ -1111,7 +1111,7 @@ setPrivacyLevel() { # A function to display a list of example blocklists for users to select chooseBlocklists() { - # Back up any existing adlist file, on the off chance that it exists. Useful in case of a reconfigure. + # Back up any existing adlist file, on the off chance that it exists. if [[ -f "${adlistFile}" ]]; then mv "${adlistFile}" "${adlistFile}.old" fi @@ -1787,21 +1787,12 @@ displayFinalMessage() { \\n${additional}" "${r}" "${c}" } -update_dialogs() { - # If pihole -r "reconfigure" option was selected, - if [[ "${reconfigure}" = true ]]; then - # set some variables that will be used - opt1a="Repair" - opt1b="This will retain existing settings" - strAdd="You will remain on the same version" - else - # Otherwise, set some variables with different values - opt1a="Update" - opt1b="This will retain existing settings." - strAdd="You will be updated to the latest version." - fi - opt2a="Reconfigure" - opt2b="Resets Pi-hole and allows re-selecting settings." +repair_dialog() { + # pihole -r/--repair option was selected + # set some variables that will be used + opt1a="Repair" + opt1b="This will retain existing settings" + strAdd="You will remain on the same version" # Display the information to the user UpdateCmd=$(dialog --no-shadow --keep-tite --output-fd 1 \ @@ -1810,9 +1801,8 @@ update_dialogs() { --menu "\\n\\nWe have detected an existing install.\ \\n\\nPlease choose from the following options:\ \\n($strAdd)" \ - "${r}" "${c}" 2 \ - "${opt1a}" "${opt1b}" \ - "${opt2a}" "${opt2b}") || result=$? + "${r}" "${c}" 1 \ + "${opt1a}" "${opt1b}") || result=$? case ${result} in "${DIALOG_CANCEL}" | "${DIALOG_ESC}") @@ -1823,16 +1813,11 @@ update_dialogs() { # Set the variable based on if the user chooses case ${UpdateCmd} in - # repair, or + # repair "${opt1a}") printf " %b %s option selected\\n" "${INFO}" "${opt1a}" useUpdateVars=true ;; - # reconfigure, - "${opt2a}") - printf " %b %s option selected\\n" "${INFO}" "${opt2a}" - useUpdateVars=false - ;; esac } @@ -1923,9 +1908,9 @@ checkout_pull_branch() { } clone_or_update_repos() { - # If the user wants to reconfigure, - if [[ "${reconfigure}" == true ]]; then - printf " %b Performing reconfiguration, skipping download of local repos\\n" "${INFO}" + # If the user wants to repair/update, + if [[ "${repair}" == true ]]; then + printf " %b Resetting local repos\\n" "${INFO}" # Reset the Core repo resetRepo ${PI_HOLE_LOCAL_REPO} || { @@ -1938,7 +1923,7 @@ clone_or_update_repos() { printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceDir}" "${COL_NC}" exit 1 } - # Otherwise, a repair is happening + # Otherwise, a fresh installation is happening else # so get git files for Core getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || @@ -2455,8 +2440,9 @@ main() { # also disable debconf-apt-progress dialogs export DEBIAN_FRONTEND="noninteractive" else - # If running attended, show the available options (repair/reconfigure) - update_dialogs + # If running attended, show the available options (repair/cancel) + # if repair is selected useUpdateVars will be 'true' + repair_dialog fi fi diff --git a/pihole b/pihole index 6424c793..39cb3070 100755 --- a/pihole +++ b/pihole @@ -107,11 +107,11 @@ updatePiholeFunc() { fi } -reconfigurePiholeFunc() { +repairPiholeFunc() { if [ -n "${DOCKER_VERSION}" ]; then unsupportedFunc else - /etc/.pihole/automated\ install/basic-install.sh --reconfigure + /etc/.pihole/automated\ install/basic-install.sh --repair exit 0; fi } @@ -476,7 +476,7 @@ Debugging Options: Add '-c' or '--check-database' to include a Pi-hole database integrity check Add '-a' to automatically upload the log to tricorder.pi-hole.net -f, flush Flush the Pi-hole log - -r, reconfigure Reconfigure or Repair Pi-hole subsystems + -r, repair Repair Pi-hole subsystems -t, tail [arg] View the live output of the Pi-hole log. Add an optional argument to filter the log (regular expressions are supported) @@ -533,7 +533,7 @@ case "${1}" in "--allow-wild" | "allow-wild" ) need_root=0;; "-f" | "flush" ) ;; "-up" | "updatePihole" ) ;; - "-r" | "reconfigure" ) ;; + "-r" | "repair" ) ;; "-l" | "logging" ) ;; "uninstall" ) ;; "enable" ) need_root=0;; @@ -576,7 +576,7 @@ case "${1}" in "-d" | "debug" ) debugFunc "$@";; "-f" | "flush" ) flushFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";; - "-r" | "reconfigure" ) reconfigurePiholeFunc;; + "-r" | "repair" ) repairPiholeFunc;; "-g" | "updateGravity" ) updateGravityFunc "$@";; "-l" | "logging" ) piholeLogging "$@";; "uninstall" ) uninstallFunc;; From dfc2b32248bd0d74e68e4879a5f8fa331b77e46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Feb 2025 21:55:08 +0100 Subject: [PATCH 002/259] Use better function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 744f9d2c..05219357 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1907,7 +1907,7 @@ checkout_pull_branch() { return 0 } -clone_or_update_repos() { +clone_or_reset_repos() { # If the user wants to repair/update, if [[ "${repair}" == true ]]; then printf " %b Resetting local repos\\n" "${INFO}" @@ -2469,8 +2469,8 @@ main() { # Setup adlist file if not exists installDefaultBlocklists fi - # Download or update the scripts by updating the appropriate git repos - clone_or_update_repos + # Download or reset the appropriate git repos depending on the 'repair' flag + clone_or_reset_repos # Create the pihole user From 5da5d0d4c16d96f1cae9fb56f85d1e49a104d9d7 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sun, 23 Feb 2025 08:50:08 +0100 Subject: [PATCH 003/259] Use temp_store = FILE to avoid memory exhaustion on build the tree for very large databases Signed-off-by: DL6ER --- gravity.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 0a34599b..18a5c901 100755 --- a/gravity.sh +++ b/gravity.sh @@ -92,7 +92,8 @@ gravity_build_tree() { echo -ne " ${INFO} ${str}..." # The index is intentionally not UNIQUE as poor quality adlists may contain domains more than once - output=$({ pihole-FTL sqlite3 -ni "${gravityTEMPfile}" "CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1) + # We use temp_store = FILE to avoid memory exhaustion on large databases + output=$({ pihole-FTL sqlite3 -ni "${gravityTEMPfile}" "PRAGMA temp_store = FILE; CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1) status="$?" if [[ "${status}" -ne 0 ]]; then From 729a44f82ae1e21b6c8906490e46deb7591613b8 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 23 Feb 2025 15:48:32 +0100 Subject: [PATCH 004/259] Do not hide error messages when dealing with services If service start/stop/restart/enable/disable fails, it help to debug the issue, if STDERR is not hidden, hence the error message can be seen. systemctl furthermore has the `-q` option to suppress non-error output. It works as well for "is-enabled", but until a certain systemd version still throws an error, if the checked service does not exist at all. Once Debian Bullseye support is dropped by Pi-hole, also STDERR form systemctl is-enabled does not need to be suppressed anymore. Signed-off-by: MichaIng --- automated install/basic-install.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 4a1df70c..8b4425bc 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1355,9 +1355,9 @@ stop_service() { local str="Stopping ${1} service" printf " %b %s..." "${INFO}" "${str}" if is_command systemctl; then - systemctl stop "${1}" &>/dev/null || true + systemctl -q stop "${1}" || true else - service "${1}" stop &>/dev/null || true + service "${1}" stop >/dev/null || true fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" } @@ -1370,10 +1370,10 @@ restart_service() { # If systemctl exists, if is_command systemctl; then # use that to restart the service - systemctl restart "${1}" &>/dev/null + systemctl -q restart "${1}" else # Otherwise, fall back to the service command - service "${1}" restart &>/dev/null + service "${1}" restart >/dev/null fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" } @@ -1386,10 +1386,10 @@ enable_service() { # If systemctl exists, if is_command systemctl; then # use that to enable the service - systemctl enable "${1}" &>/dev/null + systemctl -q enable "${1}" else # Otherwise, use update-rc.d to accomplish this - update-rc.d "${1}" defaults &>/dev/null + update-rc.d "${1}" defaults >/dev/null fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" } @@ -1402,10 +1402,10 @@ disable_service() { # If systemctl exists, if is_command systemctl; then # use that to disable the service - systemctl disable "${1}" &>/dev/null + systemctl -q disable "${1}" else # Otherwise, use update-rc.d to accomplish this - update-rc.d "${1}" disable &>/dev/null + update-rc.d "${1}" disable >/dev/null fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" } @@ -1414,7 +1414,7 @@ check_service_active() { # If systemctl exists, if is_command systemctl; then # use that to check the status of the service - systemctl is-enabled "${1}" &>/dev/null + systemctl -q is-enabled "${1}" 2>/dev/null else # Otherwise, fall back to service command service "${1}" status &>/dev/null @@ -1999,7 +1999,7 @@ FTLinstall() { curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true # Stop pihole-FTL service if available - stop_service pihole-FTL &>/dev/null + stop_service pihole-FTL >/dev/null # Install the new version with the correct permissions install -T -m 0755 "${binary}" /usr/bin/pihole-FTL From a0541dd7fbd04bc1e758634a2ab34301cf43be4d Mon Sep 17 00:00:00 2001 From: Jeroen Habets Date: Mon, 24 Feb 2025 10:45:17 +0100 Subject: [PATCH 005/259] Update README.md Fix Text+URL for allowlisting/denylisting. Keep former terms for when people search for them. Signed-off-by: Jeroen Habets --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7eb1fb3a..fddd3d2d 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ The [pihole](https://docs.pi-hole.net/core/pihole-command/) command has all the Some notable features include: -- [Whitelisting, Blacklisting, and Regex](https://docs.pi-hole.net/core/pihole-command/#whitelisting-blacklisting-and-regex) +- [Allowlisting, Denylisting (fka Whitelisting, Blacklisting), and Regex](https://docs.pi-hole.net/core/pihole-command/#allowlisting-denylisting-and-regex) - [Debugging utility](https://docs.pi-hole.net/core/pihole-command/#debugger) - [Viewing the live log file](https://docs.pi-hole.net/core/pihole-command/#tail) - [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity) From e70981d80f3f9d4c42a5bbb74651ae2ed489e6da Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 24 Feb 2025 17:01:17 +0100 Subject: [PATCH 006/259] Do not overwrite TLS cert/key mode FTL correctly creates the cert and especially private key with 0600 mode. But the prestart scripts changes it to 0660. After removing the dedicated webserver from Pi-hole setups, the pihole group has no purpose anymore, and files should not be writable to any other user than pihole itself, and the private TLS key not reasable to anyone else either. Additionally, this commit consolidates the chmod calls, applying 0755 to all directories and 0640 to all files, but the TLS key and cert. Signed-off-by: MichaIng --- advanced/Templates/pihole-FTL-prestart.sh | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) mode change 100755 => 100644 advanced/Templates/pihole-FTL-prestart.sh diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh old mode 100755 new mode 100644 index f0bbe09a..ab449dfe --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -10,22 +10,14 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files -# shellcheck disable=SC2174 -mkdir -pm 0640 /var/log/pihole +mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole /var/log/pihole -chmod -R 0640 /var/log/pihole -chmod -R 0660 /etc/pihole +find /etc/pihole /var/log/pihole -type d -exec chmod 0755 {} + +find /etc/pihole /var/log/pihole -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + +find /etc/pihole /var/log/pihole -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + -# Logrotate config file need to be owned by root and must not be writable by group and others +# Logrotate config file need to be owned by root chown root:root /etc/pihole/logrotate -chmod 0644 /etc/pihole/logrotate - -# allow all users to enter the directories -chmod 0755 /etc/pihole /var/log/pihole - -# allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) -# credits https://stackoverflow.com/a/11512211 -find /etc/pihole/ -type d -exec chmod 0755 {} \; # Touch files to ensure they exist (create if non-existing, preserve if existing) [ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" From 65bcb24d0e461ddc87665b1f5f6a4e99f8446a5b Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 24 Feb 2025 17:28:33 +0100 Subject: [PATCH 007/259] Fix test Do not check whether the pihole user can read /etc/pihole/logrotate. It needs to be readable by root only, which is always true. Signed-off-by: MichaIng --- test/test_any_automated_install.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 73da7eef..c656fe88 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -127,10 +127,6 @@ def test_installPihole_fresh_install_readableFiles(host): check_localversion = test_cmd.format("r", "/etc/pihole/versions", piholeuser) actual_rc = host.run(check_localversion).rc assert exit_status_success == actual_rc - # readable logrotate - check_logrotate = test_cmd.format("r", "/etc/pihole/logrotate", piholeuser) - actual_rc = host.run(check_logrotate).rc - assert exit_status_success == actual_rc # readable macvendor.db check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser) actual_rc = host.run(check_macvendor).rc From 0b380d671d273d529e6a0cece9fca7b7dc6e2e77 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Mon, 24 Feb 2025 17:34:32 +0100 Subject: [PATCH 008/259] Follow symlinks with find Incorporating https://github.com/pi-hole/pi-hole/pull/5997 Signed-off-by: MichaIng --- advanced/Templates/pihole-FTL-prestart.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 advanced/Templates/pihole-FTL-prestart.sh diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh old mode 100644 new mode 100755 index ab449dfe..8855481b --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -12,9 +12,9 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole /var/log/pihole -find /etc/pihole /var/log/pihole -type d -exec chmod 0755 {} + -find /etc/pihole /var/log/pihole -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + -find /etc/pihole /var/log/pihole -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + +find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + +find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + +find /etc/pihole/ /var/log/pihole/ -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + # Logrotate config file need to be owned by root chown root:root /etc/pihole/logrotate From 232d581916aef4828288e5045e65263fc47b3519 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 26 Feb 2025 12:25:51 +0100 Subject: [PATCH 009/259] Re-add comment about execute bit on directory Co-authored-by: Dominik Signed-off-by: MichaIng --- advanced/Templates/pihole-FTL-prestart.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 8855481b..5c6bd909 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -12,6 +12,7 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole /var/log/pihole +# allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + find /etc/pihole/ /var/log/pihole/ -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + From 83a38bb71d3cf849b8e968eb56b9404a42675395 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 26 Feb 2025 12:26:50 +0100 Subject: [PATCH 010/259] Add comment about file permissions Co-authored-by: Dominik Signed-off-by: MichaIng --- advanced/Templates/pihole-FTL-prestart.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 5c6bd909..07b28bbb 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -14,6 +14,7 @@ mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole /var/log/pihole # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + +# Set all files (except TLS-related ones) to u+rw g+r find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + find /etc/pihole/ /var/log/pihole/ -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + From ad6a48b219ea24cb7069eff10e698c16cf80534d Mon Sep 17 00:00:00 2001 From: MichaIng Date: Wed, 26 Feb 2025 20:59:32 +0100 Subject: [PATCH 011/259] Add comment about TLS-related file permissions Co-authored-by: Dominik Signed-off-by: MichaIng --- advanced/Templates/pihole-FTL-prestart.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 07b28bbb..1abafd28 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -16,6 +16,7 @@ chown -R pihole:pihole /etc/pihole /var/log/pihole find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + # Set all files (except TLS-related ones) to u+rw g+r find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + +# Set TLS-related files to a more restrictive u+rw *only* (they may contain private keys) find /etc/pihole/ /var/log/pihole/ -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + # Logrotate config file need to be owned by root From d1b5f95aa7c4ac88c6e9dd26dc0c30351e779800 Mon Sep 17 00:00:00 2001 From: UltChowsk Date: Wed, 26 Feb 2025 20:37:13 -0500 Subject: [PATCH 012/259] Removing kernel check based on discussion in Pi-Hole PR pi-hole#5957. Signed-off-by: UltChowsk --- automated install/basic-install.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 3bf14cc5..76c5765b 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1476,17 +1476,12 @@ notify_package_updates_available() { # Store the list of packages in a variable updatesToInstall=$(eval "${PKG_COUNT}") - if [[ -d "/lib/modules/$(uname -r)" ]]; then if [[ "${updatesToInstall}" -eq 0 ]]; then printf "%b %b %s... up to date!\\n\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s... %s updates available\\n" "${OVER}" "${TICK}" "${str}" "${updatesToInstall}" printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" fi - else - printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " Kernel update detected. If the install fails, please reboot and try again\\n" - fi } install_dependent_packages() { From 869411a51440cb236ff6d076a798cb58032ec02e Mon Sep 17 00:00:00 2001 From: UltChowsk Date: Thu, 27 Feb 2025 06:23:56 -0500 Subject: [PATCH 013/259] Fixing whitespaces after removing lines. Signed-off-by: UltChowsk --- automated install/basic-install.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 76c5765b..96ed17b2 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1476,12 +1476,12 @@ notify_package_updates_available() { # Store the list of packages in a variable updatesToInstall=$(eval "${PKG_COUNT}") - if [[ "${updatesToInstall}" -eq 0 ]]; then - printf "%b %b %s... up to date!\\n\\n" "${OVER}" "${TICK}" "${str}" - else - printf "%b %b %s... %s updates available\\n" "${OVER}" "${TICK}" "${str}" "${updatesToInstall}" - printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" - fi + if [[ "${updatesToInstall}" -eq 0 ]]; then + printf "%b %b %s... up to date!\\n\\n" "${OVER}" "${TICK}" "${str}" + else + printf "%b %b %s... %s updates available\\n" "${OVER}" "${TICK}" "${str}" "${updatesToInstall}" + printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" + fi } install_dependent_packages() { From 7282aada25704631987ed35ffbf5c5bdb7412404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 28 Feb 2025 11:51:09 +0100 Subject: [PATCH 014/259] Don't show a warning before the repair is done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 44 ++---------------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 05219357..1d154cfe 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1787,40 +1787,6 @@ displayFinalMessage() { \\n${additional}" "${r}" "${c}" } -repair_dialog() { - # pihole -r/--repair option was selected - # set some variables that will be used - opt1a="Repair" - opt1b="This will retain existing settings" - strAdd="You will remain on the same version" - - # Display the information to the user - UpdateCmd=$(dialog --no-shadow --keep-tite --output-fd 1 \ - --cancel-label Exit \ - --title "Existing Install Detected!" \ - --menu "\\n\\nWe have detected an existing install.\ -\\n\\nPlease choose from the following options:\ -\\n($strAdd)" \ - "${r}" "${c}" 1 \ - "${opt1a}" "${opt1b}") || result=$? - - case ${result} in - "${DIALOG_CANCEL}" | "${DIALOG_ESC}") - printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" - exit 1 - ;; - esac - - # Set the variable based on if the user chooses - case ${UpdateCmd} in - # repair - "${opt1a}") - printf " %b %s option selected\\n" "${INFO}" "${opt1a}" - useUpdateVars=true - ;; - esac -} - check_download_exists() { # Check if the download exists and we can reach the server local status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) @@ -2430,19 +2396,15 @@ main() { exit 1 fi - # in case of an update (can be a v5 -> v6 or v6 -> v6 update) + # in case of an update (can be a v5 -> v6 or v6 -> v6 update) or repair if [[ -f "${PI_HOLE_V6_CONFIG}" ]] || [[ -f "/etc/pihole/setupVars.conf" ]]; then + # retain settings + useUpdateVars=true # if it's running unattended, if [[ "${runUnattended}" == true ]]; then printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" - # Use the setup variables - useUpdateVars=true # also disable debconf-apt-progress dialogs export DEBIAN_FRONTEND="noninteractive" - else - # If running attended, show the available options (repair/cancel) - # if repair is selected useUpdateVars will be 'true' - repair_dialog fi fi From a9650ae28736aedd62680f4f705525021185d519 Mon Sep 17 00:00:00 2001 From: Karol Kania <44871508+karolkania@users.noreply.github.com> Date: Fri, 28 Feb 2025 12:52:07 +0100 Subject: [PATCH 015/259] Update gravity.sh fix the `if statement` that doesn't seem to work for neither of alpine's ash / bash - applying some workaround with the `stat` command Signed-off-by: Karol Kania <44871508+karolkania@users.noreply.github.com> --- gravity.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gravity.sh b/gravity.sh index 0a34599b..cc8c6ba1 100755 --- a/gravity.sh +++ b/gravity.sh @@ -541,14 +541,18 @@ gravity_DownloadBlocklists() { # it (in case it doesn't exist) # First, check if the directory is writable directory="$(dirname -- "${saveLocation}")" - if [ ! -w "${directory}" ]; then + directory_permissions=$(stat -c %a ${directory}) + # echo "directory_permissions: ${directory_permissions}" + if [ $directory_permissions -lt 700 ]; then echo -e " ${CROSS} Unable to write to ${directory}" echo " Please run pihole -g as root" echo "" continue fi # Then, check if the file is writable (if it exists) - if [ -e "${saveLocation}" ] && [ ! -w "${saveLocation}" ]; then + saveLocation_permissions=$(stat -c %a ${saveLocation}) + # echo "saveLocation_permissions: ${saveLocation_permissions}" + if [ -e "${saveLocation}" ] && [ ${saveLocation_permissions} -lt 600 ]; then echo -e " ${CROSS} Unable to write to ${saveLocation}" echo " Please run pihole -g as root" echo "" From 887475795897b038879fa9a33a888203869462d9 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 28 Feb 2025 21:29:33 +0000 Subject: [PATCH 016/259] Start by renaming useUpdateVars to fresh_install and flipping the logic, the old name is not relevant any more Signed-off-by: Adam Warner --- automated install/basic-install.sh | 13 ++++--------- test/test_any_automated_install.py | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d18d4e88..f78f0c02 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -81,9 +81,7 @@ PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole" PI_HOLE_BIN_DIR="/usr/local/bin" PI_HOLE_V6_CONFIG="${PI_HOLE_CONFIG_DIR}/pihole.toml" -if [ -z "$useUpdateVars" ]; then - useUpdateVars=false -fi +fresh_install=true adlistFile="/etc/pihole/adlists.list" # Pi-hole needs an IP address; to begin, these variables are empty since we don't know what the IP is until this script can run @@ -93,7 +91,6 @@ IPV6_ADDRESS=${IPV6_ADDRESS} QUERY_LOGGING= WEBPORT= PRIVACY_LEVEL= -v5_to_v6_update=false # Where old configs go to if a v6 migration is performed V6_CONF_MIGRATION_DIR="/etc/pihole/migration_backup_v6" @@ -2290,8 +2287,6 @@ migrate_dnsmasq_configs() { # Print a blank line for separation printf "\\n" - - v5_to_v6_update=true } # Check for availability of either the "service" or "systemctl" commands @@ -2384,7 +2379,7 @@ main() { # in case of an update (can be a v5 -> v6 or v6 -> v6 update) or repair if [[ -f "${PI_HOLE_V6_CONFIG}" ]] || [[ -f "/etc/pihole/setupVars.conf" ]]; then # retain settings - useUpdateVars=true + fresh_install=false # if it's running unattended, if [[ "${runUnattended}" == true ]]; then printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" @@ -2393,7 +2388,7 @@ main() { fi fi - if [[ "${useUpdateVars}" == false ]]; then + if [[ "${fresh_install}" == true ]]; then # Display welcome dialogs welcomeDialogs # Create directory for Pi-hole storage (/etc/pihole/) @@ -2512,7 +2507,7 @@ main() { printf " %b This can be changed using 'pihole setpassword'\\n\\n" "${INFO}" fi - if [[ "${useUpdateVars}" == false ]]; then + if [[ "${fresh_install}" == true ]]; then # Get the Web interface port, return only the first port and strip all non-numeric characters WEBPORT=$(getFTLConfigValue webserver.port|cut -d, -f1 | tr -cd '0-9') diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index c656fe88..5fa0f065 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -89,10 +89,10 @@ def test_installPihole_fresh_install_readableFiles(host): export DEBIAN_FRONTEND=noninteractive umask 0027 runUnattended=true - useUpdateVars=true + fresh_install=false source /opt/pihole/basic-install.sh > /dev/null runUnattended=true - useUpdateVars=true + fresh_install=false main /opt/pihole/pihole-FTL-prestart.sh """ From ce73691082b24d5936059365c735d3567ef32fd9 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 28 Feb 2025 22:20:17 +0000 Subject: [PATCH 017/259] Juggle some code around: - Move random password generation block inside final "fresh install" if block, ensure password is ONLY generated on fresh installs. - Add additional check for fresh install around setting of PIHOLE_DNS1/2, QUERY_LOGGING, and PRIVACY_LEVEL - Remove dedicated displayFinalMessage function. Signed-off-by: Adam Warner --- automated install/basic-install.sh | 104 +++++++++++------------------ 1 file changed, 38 insertions(+), 66 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index f78f0c02..d3038901 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -89,7 +89,6 @@ IPV4_ADDRESS=${IPV4_ADDRESS} IPV6_ADDRESS=${IPV6_ADDRESS} # Give settings their default values. These may be changed by prompts later in the script. QUERY_LOGGING= -WEBPORT= PRIVACY_LEVEL= # Where old configs go to if a v6 migration is performed @@ -1754,34 +1753,6 @@ checkSelinux() { fi } -# Installation complete message with instructions for the user -displayFinalMessage() { - # TODO: COME BACK TO THIS, WHAT IS GOING ON? - # If the number of arguments is > 0, - if [[ "${#1}" -gt 0 ]]; then - # set the password to the first argument. - pwstring="$1" - elif [[ -n $(pihole-FTL --config webserver.api.pwhash) ]]; then - # Else if the password exists from previous setup, we'll load it later - pwstring="unchanged" - else - # Else, inform the user that there is no set password. - pwstring="NOT SET" - fi - - # Store a message in a variable and display it - additional="View the web interface at http://pi.hole/admin:${WEBPORT} or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pwstring}" - - # Final completion message to user - dialog --no-shadow --keep-tite \ - --title "Installation Complete!" \ - --msgbox "Configure your devices to use the Pi-hole as their DNS server using:\ -\\n\\nIPv4: ${IPV4_ADDRESS%/*}\ -\\nIPv6: ${IPV6_ADDRESS:-"Not Configured"}\ -\\nIf you have not done so already, the above IP should be set to static.\ -\\n${additional}" "${r}" "${c}" -} - check_download_exists() { # Check if the download exists and we can reach the server local status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) @@ -2414,7 +2385,6 @@ main() { # Download or reset the appropriate git repos depending on the 'repair' flag clone_or_reset_repos - # Create the pihole user create_pihole_user @@ -2443,11 +2413,9 @@ main() { # Copy the temp log file into final log location for storage copy_to_install_log - # Migrate existing install to v6.0 migrate_dnsmasq_configs - # Check for and disable systemd-resolved-DNSStubListener before reloading resolved # DNSStubListener needs to remain in place for installer to download needed files, # so this change needs to be made after installation is complete, @@ -2470,28 +2438,25 @@ main() { restart_service pihole-FTL - # Add password to web UI if there is none - pw="" - # If this is a fresh installation and no password is set, - if [[ ${v5_to_v6_update} = false && -z $(getFTLConfigValue webserver.api.pwhash) ]]; then - # generate a random password - pw=$(tr -dc _A-Z-a-z-0-9 0)); then - # display the password - printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${pw}" "${COL_NC}" - printf " %b This can be changed using 'pihole setpassword'\\n\\n" "${INFO}" - fi - if [[ "${fresh_install}" == true ]]; then + # Get the Web interface port, return only the first port and strip all non-numeric characters WEBPORT=$(getFTLConfigValue webserver.port|cut -d, -f1 | tr -cd '0-9') - # Display the completion dialog - displayFinalMessage "${pw}" - - # If the Web interface was installed, - printf " %b View the web interface at http://pi.hole:${WEBPORT}/admin or http://%s/admin\\n\\n" "${INFO}" "${IPV4_ADDRESS%/*}:${WEBPORT}" + # If this is a fresh install, we will set a random password. + # Users can change this password after installation if they wish + pw=$(tr -dc _A-Z-a-z-0-9 /dev/null # Explain to the user how to use Pi-hole as their DNS server - printf " %b You may now configure your devices to use the Pi-hole as their DNS server\\n" "${INFO}" + printf "\\n %b You may now configure your devices to use the Pi-hole as their DNS server\\n" "${INFO}" [[ -n "${IPV4_ADDRESS%/*}" ]] && printf " %b Pi-hole DNS (IPv4): %s\\n" "${INFO}" "${IPV4_ADDRESS%/*}" [[ -n "${IPV6_ADDRESS}" ]] && printf " %b Pi-hole DNS (IPv6): %s\\n" "${INFO}" "${IPV6_ADDRESS}" printf " %b If you have not done so already, the above IP should be set to static.\\n" "${INFO}" + + printf " %b View the web interface at http://pi.hole:${WEBPORT}/admin or http://%s/admin\\n\\n" "${INFO}" "${IPV4_ADDRESS%/*}:${WEBPORT}" + printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${pw}" "${COL_NC}" + printf " %b This can be changed using 'pihole setpassword'\\n\\n" "${INFO}" + + # Final dialog message to the user + dialog --no-shadow --keep-tite \ + --title "Installation Complete!" \ + --msgbox "Configure your devices to use the Pi-hole as their DNS server using:\ +\\n\\nIPv4: ${IPV4_ADDRESS%/*}\ +\\nIPv6: ${IPV6_ADDRESS:-"Not Configured"}\ +\\nIf you have not done so already, the above IP should be set to static.\ +\\nView the web interface at http://pi.hole/admin:${WEBPORT} or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pw}" "${r}" "${c}" + INSTALL_TYPE="Installation" else INSTALL_TYPE="Update" From 0130f7be74f4f3efc2a6c243359a08fbb13dae54 Mon Sep 17 00:00:00 2001 From: Jack'lul <8418678+jacklul@users.noreply.github.com> Date: Sat, 1 Mar 2025 14:43:36 +0100 Subject: [PATCH 018/259] Fix find command syntax, remove log dir from search Signed-off-by: Jack'lul <8418678+jacklul@users.noreply.github.com> --- advanced/Templates/pihole-FTL-prestart.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 1abafd28..49b0f0d4 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -17,7 +17,7 @@ find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + # Set all files (except TLS-related ones) to u+rw g+r find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} + # Set TLS-related files to a more restrictive u+rw *only* (they may contain private keys) -find /etc/pihole/ /var/log/pihole/ -type f -name '*.pem' -o -name '*.crt' -exec chmod 0600 {} + +find /etc/pihole/ -type f \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0600 {} + # Logrotate config file need to be owned by root chown root:root /etc/pihole/logrotate From 9c7e02f213654da2cbf83727bbaccd5bd1ff9907 Mon Sep 17 00:00:00 2001 From: Karol Kania <44871508+karolkania@users.noreply.github.com> Date: Sun, 2 Mar 2025 12:05:42 +0100 Subject: [PATCH 019/259] Update gravity.sh remove the left-over commented debug code Signed-off-by: Karol Kania <44871508+karolkania@users.noreply.github.com> --- gravity.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/gravity.sh b/gravity.sh index cc8c6ba1..ad94ca54 100755 --- a/gravity.sh +++ b/gravity.sh @@ -542,7 +542,6 @@ gravity_DownloadBlocklists() { # First, check if the directory is writable directory="$(dirname -- "${saveLocation}")" directory_permissions=$(stat -c %a ${directory}) - # echo "directory_permissions: ${directory_permissions}" if [ $directory_permissions -lt 700 ]; then echo -e " ${CROSS} Unable to write to ${directory}" echo " Please run pihole -g as root" @@ -551,7 +550,6 @@ gravity_DownloadBlocklists() { fi # Then, check if the file is writable (if it exists) saveLocation_permissions=$(stat -c %a ${saveLocation}) - # echo "saveLocation_permissions: ${saveLocation_permissions}" if [ -e "${saveLocation}" ] && [ ${saveLocation_permissions} -lt 600 ]; then echo -e " ${CROSS} Unable to write to ${saveLocation}" echo " Please run pihole -g as root" From df814ece91ee1a348d2377890f62e002f5e2bb68 Mon Sep 17 00:00:00 2001 From: Dominik Date: Mon, 3 Mar 2025 09:00:17 +0100 Subject: [PATCH 020/259] Revert "Improve gravity on systems with low memory" --- gravity.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gravity.sh b/gravity.sh index 9814a777..493f2b15 100755 --- a/gravity.sh +++ b/gravity.sh @@ -92,8 +92,7 @@ gravity_build_tree() { echo -ne " ${INFO} ${str}..." # The index is intentionally not UNIQUE as poor quality adlists may contain domains more than once - # We use temp_store = FILE to avoid memory exhaustion on large databases - output=$({ pihole-FTL sqlite3 -ni "${gravityTEMPfile}" "PRAGMA temp_store = FILE; CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1) + output=$({ pihole-FTL sqlite3 -ni "${gravityTEMPfile}" "CREATE INDEX idx_gravity ON gravity (domain, adlist_id);"; } 2>&1) status="$?" if [[ "${status}" -ne 0 ]]; then From bef8227cbdd8a370046b08a29d75abe43361629e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 3 Mar 2025 20:16:07 +0100 Subject: [PATCH 021/259] Use a more general method to determine whether systemd is the init system Signed-off-by: DL6ER --- automated install/basic-install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e69256ff..f419ab6c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1281,8 +1281,7 @@ installConfigs() { fi # Install pihole-FTL systemd or init.d service, based on whether systemd is the init system or not - # Follow debhelper logic, which checks for /run/systemd/system to derive whether systemd is the init system - if [[ -d '/run/systemd/system' ]]; then + if ps -p 1 -o comm= | grep -q systemd; then install -T -m 0644 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.systemd" '/etc/systemd/system/pihole-FTL.service' # Remove init.d service if present From 4df5c0bb9675eda8d00f8e073f428d1434cd18c6 Mon Sep 17 00:00:00 2001 From: Jack'lul <8418678+jacklul@users.noreply.github.com> Date: Wed, 5 Mar 2025 22:25:33 +0100 Subject: [PATCH 022/259] Add webserver log to piholeLogFlush.sh Signed-off-by: Jack'lul <8418678+jacklul@users.noreply.github.com> --- advanced/Scripts/piholeLogFlush.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 34d96318..58c6a41d 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -35,6 +35,10 @@ FTLFILE=$(getFTLConfigValue "files.log.ftl") if [ -z "$FTLFILE" ]; then FTLFILE="/var/log/pihole/FTL.log" fi +WEBFILE=$(getFTLConfigValue "files.log.webserver") +if [ -z "$WEBFILE" ]; then + WEBFILE="/var/log/pihole/webserver.log" +fi if [[ "$*" == *"once"* ]]; then # Nightly logrotation @@ -71,6 +75,17 @@ if [[ "$*" == *"once"* ]]; then if [[ "$*" != *"quiet"* ]]; then echo -e "${OVER} ${TICK} Rotated ${FTLFILE} ..." fi + # Copy webserver.log over to webserver.log.1 + # and empty out webserver.log + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Rotating ${WEBFILE} ..." + fi + cp -p "${WEBFILE}" "${WEBFILE}.1" + echo " " > "${WEBFILE}" + chmod 640 "${WEBFILE}" + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Rotated ${WEBFILE} ..." + fi fi else # Manual flushing @@ -103,6 +118,20 @@ else echo -e "${OVER} ${TICK} Flushed ${FTLFILE} ..." fi + # Flush both webserver.log and webserver.log.1 (if existing) + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Flushing ${WEBFILE} ..." + fi + echo " " > "${WEBFILE}" + chmod 640 "${WEBFILE}" + if [ -f "${WEBFILE}.1" ]; then + echo " " > "${WEBFILE}.1" + chmod 640 "${WEBFILE}.1" + fi + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Flushed ${WEBFILE} ..." + fi + if [[ "$*" != *"quiet"* ]]; then echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." fi From e437e3a805d1a3add6a56f3bacaa8e38434b9333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Mar 2025 09:48:06 +0100 Subject: [PATCH 023/259] Create webserver.log on FTL startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Templates/pihole-FTL-prestart.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 49b0f0d4..5813959d 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -26,4 +26,5 @@ chown root:root /etc/pihole/logrotate [ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" [ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log [ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log +[ -f /var/log/pihole/webserver.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/webserver.log [ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases From d094b197e3a6eb941fc1ca6dc1a4fd06b331171d Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Thu, 6 Mar 2025 15:06:34 +0200 Subject: [PATCH 024/259] README.md: switch to the SVG logo Signed-off-by: XhmikosR --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fddd3d2d..f320f8c5 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,9 @@ #

- - - - Pi-hole website - -
- Network-wide ad blocking via your own Linux hardware + Pi-hole website +
+ Network-wide ad blocking via your own Linux hardware

From 45cb722e5035c70cb49278f8a4f53f799d3d3c6a Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Thu, 6 Mar 2025 21:40:17 +0200 Subject: [PATCH 025/259] version.sh: fix typo in comment Signed-off-by: XhmikosR --- advanced/Scripts/version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh index 2b0883af..540924c2 100755 --- a/advanced/Scripts/version.sh +++ b/advanced/Scripts/version.sh @@ -12,7 +12,7 @@ # shellcheck disable=SC3043 # https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions -# Source the versions file poupulated by updatechecker.sh +# Source the versions file populated by updatechecker.sh cachedVersions="/etc/pihole/versions" if [ -f ${cachedVersions} ]; then From f3dc202e36bbcb3a1ce337f3bdbe89302b819bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 7 Mar 2025 10:16:25 +0100 Subject: [PATCH 026/259] Remove WEB_CALL from COL_TABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/COL_TABLE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/COL_TABLE b/advanced/Scripts/COL_TABLE index 4344c7b8..f9a014fc 100644 --- a/advanced/Scripts/COL_TABLE +++ b/advanced/Scripts/COL_TABLE @@ -1,5 +1,6 @@ +#!/usr/bin/env sh # Determine if terminal is capable of showing colors -if ([ -t 1 ] && [ $(tput colors) -ge 8 ]) || [ "${WEBCALL}" ]; then +if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then # Bold and underline may not show up on all clients # If something MUST be emphasized, use both COL_BOLD='' From 5de9b6ae698fbf7e13985ab78a4b3674b64c37c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 7 Mar 2025 13:43:41 +0100 Subject: [PATCH 027/259] Add 2FA handling to api.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 90 ++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index b8c7fe99..79fc90f4 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -21,7 +21,7 @@ TestAPIAvailability() { # as we are running locally, we can get the port value from FTL directly - local chaos_api_list availabilityResponse + local chaos_api_list authResponse authStatus authData # Query the API URLs from FTL using CHAOS TXT local.api.ftl # The result is a space-separated enumeration of full URLs @@ -49,20 +49,29 @@ TestAPIAvailability() { API_URL="${API_URL#\"}" # Test if the API is available at this URL - availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") + authResponse=$(curl --connect-timeout 2 -skS -w "%{http_code}" "${API_URL}auth") + + # authStatus are the last 3 characters + # not using ${authResponse#"${authResponse%???}"}" here because it's extremely slow on big responses + authStatus=$(printf "%s" "${authResponse}" | tail -c 3) + # data is everything from response without the last 3 characters + authData=$(printf %s "${authResponse%???}") # Test if http status code was 200 (OK) or 401 (authentication required) - if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then + if [ ! "${authStatus}" = 200 ] && [ ! "${authStatus}" = 401 ]; then # API is not available at this port/protocol combination API_PORT="" else # API is available at this URL combination - if [ "${availabilityResponse}" = 200 ]; then + if [ "${authStatus}" = 200 ]; then # API is available without authentication needAuth=false fi + # Check if 2FA is required + needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null) + break fi @@ -108,22 +117,51 @@ LoginAPI() { echo "API Authentication: Trying to use CLI password" fi - # Try to authenticate using the CLI password - Authentication "${1}" - + # If we can read the CLI password, we can skip 2FA even when it's required otherwise + needTOTP=false elif [ "${1}" = "verbose" ]; then echo "API Authentication: CLI password not available" fi + if [ -z "${password}" ]; then + # no password read from CLI file + echo "Please enter your password:" + # secretly read the password + secretRead; printf '\n' + fi + if [ "${needTOTP}" = true ]; then + # 2FA required + echo "Please enter the correct second factor." + echo "(Can be any number if you used the app password)" + read -r totp + fi - # If this did not work, ask the user for the password - while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do + # Try to authenticate using the supplied password (CLI file or user input) and TOTP + Authentication "${1}" + + # Try to login again until the session is valid + while [ ! "${validSession}" = true ] ; do echo "Authentication failed. Please enter your Pi-hole password" + # Print the error message if there is one + if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then + echo "Error: ${sessionError}" + fi + # Print the session message if there is one + if [ ! "${sessionMessage}" = "null" ] && [ "${1}" = "verbose" ]; then + echo "Error: ${sessionMessage}" + fi + # secretly read the password secretRead; printf '\n' + if [ "${needTOTP}" = true ]; then + echo "Please enter the correct second factor:" + echo "(Can be any number if you used the app password)" + read -r totp + fi + # Try to authenticate again Authentication "${1}" done @@ -131,23 +169,27 @@ LoginAPI() { } Authentication() { - sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli " --data "{\"password\":\"${password}\"}" )" + sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}" )" - if [ -z "${sessionResponse}" ]; then - echo "No response from FTL server. Please check connectivity" - exit 1 - fi - # obtain validity and session ID from session response - validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) - SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) - - if [ "${1}" = "verbose" ]; then - if [ "${validSession}" = true ]; then - echo "API Authentication: ${COL_GREEN}Success${COL_NC}" - else - echo "API Authentication: ${COL_RED}Failed${COL_NC}" + if [ -z "${sessionResponse}" ]; then + echo "No response from FTL server. Please check connectivity" + exit 1 + fi + # obtain validity, session ID and sessionMessage from session response + validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) + SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) + sessionMessage=$(echo "${sessionResponse}"| jq --raw-output .session.message 2>/dev/null) + + # obtain the error message from the session response + sessionError=$(echo "${sessionResponse}"| jq --raw-output .error.message 2>/dev/null) + + if [ "${1}" = "verbose" ]; then + if [ "${validSession}" = true ]; then + echo "API Authentication: ${COL_GREEN}Success${COL_NC}" + else + echo "API Authentication: ${COL_RED}Failed${COL_NC}" + fi fi - fi } LogoutAPI() { From 9b4502a7a93e67fd1de0f1de7a06daa2636aaece Mon Sep 17 00:00:00 2001 From: casperklein Date: Fri, 7 Mar 2025 23:00:40 +0100 Subject: [PATCH 028/259] Add trailing / to directories Signed-off-by: casperklein --- advanced/Templates/pihole-FTL-prestart.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 49b0f0d4..70405a0b 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -11,7 +11,7 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole -chown -R pihole:pihole /etc/pihole /var/log/pihole +chown -R pihole:pihole /etc/pihole/ /var/log/pihole/ # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + # Set all files (except TLS-related ones) to u+rw g+r From 27aeed76f0aaa411acb8249c47762e8df3251fbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 10:30:22 +0000 Subject: [PATCH 029/259] Bump tox from 4.24.1 to 4.24.2 in /test Bumps [tox](https://github.com/tox-dev/tox) from 4.24.1 to 4.24.2. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.24.1...4.24.2) --- updated-dependencies: - dependency-name: tox dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 7b7e679f..b1dd923c 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.3.4 pytest-xdist == 3.6.1 pytest-testinfra == 10.1.1 -tox == 4.24.1 +tox == 4.24.2 pytest-clarity == 1.0.1 From 6b873b2d7f06720de7a6808514a1c6fbed9bd88d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 10:46:01 +0000 Subject: [PATCH 030/259] Bump pytest from 8.3.4 to 8.3.5 in /test Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index b1dd923c..46d614e7 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ pyyaml == 6.0.2 -pytest == 8.3.4 +pytest == 8.3.5 pytest-xdist == 3.6.1 pytest-testinfra == 10.1.1 tox == 4.24.2 From 3a592471c69ddfbe68867bc3045b31a1dbc0d6a1 Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Fri, 14 Mar 2025 14:32:29 -0500 Subject: [PATCH 031/259] revert pi-hole/pi-hole/pull/6030 in preparation for pi-hole/docker-pi-hole/pull/1786 Signed-off-by: Michael Woolweaver --- gravity.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gravity.sh b/gravity.sh index 3a7db5ae..493f2b15 100755 --- a/gravity.sh +++ b/gravity.sh @@ -541,16 +541,14 @@ gravity_DownloadBlocklists() { # it (in case it doesn't exist) # First, check if the directory is writable directory="$(dirname -- "${saveLocation}")" - directory_permissions=$(stat -c %a ${directory}) - if [ $directory_permissions -lt 700 ]; then + if [ ! -w "${directory}" ]; then echo -e " ${CROSS} Unable to write to ${directory}" echo " Please run pihole -g as root" echo "" continue fi # Then, check if the file is writable (if it exists) - saveLocation_permissions=$(stat -c %a ${saveLocation}) - if [ -e "${saveLocation}" ] && [ ${saveLocation_permissions} -lt 600 ]; then + if [ -e "${saveLocation}" ] && [ ! -w "${saveLocation}" ]; then echo -e " ${CROSS} Unable to write to ${saveLocation}" echo " Please run pihole -g as root" echo "" From dec670a6d63281862edc127cc9f7520753d6a22f Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 22 Mar 2025 09:18:02 +0100 Subject: [PATCH 032/259] Move list parsing entirely into FTL Signed-off-by: DL6ER --- gravity.sh | 41 +++++------------------------------------ 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/gravity.sh b/gravity.sh index 3a7db5ae..c41972f3 100755 --- a/gravity.sh +++ b/gravity.sh @@ -823,11 +823,11 @@ gravity_DownloadBlocklistFromUrl() { done="true" # Check if $listCurlBuffer is a non-zero length file elif [[ -s "${listCurlBuffer}" ]]; then - # Determine if blocklist is non-standard and parse as appropriate - gravity_ParseFileIntoDomains "${listCurlBuffer}" "${saveLocation}" - # Remove curl buffer file after its use - rm "${listCurlBuffer}" - # Compare lists if are they identical + # Move the downloaded list to the final location + mv "${listCurlBuffer}" "${saveLocation}" + # Ensure the file has the correct permissions + fix_owner_permissions "${saveLocation}" + # Compare lists if they are identical compareLists "${adlistID}" "${saveLocation}" # Add domains to database table file pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" @@ -856,37 +856,6 @@ gravity_DownloadBlocklistFromUrl() { fi } -# Parse source files into domains format -gravity_ParseFileIntoDomains() { - local src="${1}" destination="${2}" - - # Remove comments and print only the domain name - # Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous - # This helps with that and makes it easier to read - # It also helps with debugging so each stage of the script can be researched more in depth - # 1) Convert all characters to lowercase - tr '[:upper:]' '[:lower:]' <"${src}" >"${destination}" - - # 2) Remove carriage returns - # 3) Remove lines starting with ! (ABP Comments) - # 4) Remove lines starting with [ (ABP Header) - # 5) Remove lines containing ABP extended CSS selectors ("##", "#$#", "#@#", "#?#") and Adguard JavaScript (#%#) preceded by a letter - # 6) Remove comments (text starting with "#", include possible spaces before the hash sign) - # 7) Remove leading tabs, spaces, etc. (Also removes leading IP addresses) - # 8) Remove empty lines - - sed -i -r \ - -e 's/\r$//' \ - -e 's/\s*!.*//g' \ - -e 's/\s*\[.*//g' \ - -e '/[a-z]\#[$?@%]{0,3}\#/d' \ - -e 's/\s*#.*//g' \ - -e 's/^.*\s+//g' \ - -e '/^$/d' "${destination}" - - fix_owner_permissions "${destination}" -} - # Report number of entries in a table gravity_Table_Count() { local table="${1}" From 71ec0a0244bd81592e744357a477dcad90f5373a Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 27 Mar 2025 13:05:09 +0100 Subject: [PATCH 033/259] Add ON DELETE CASCADE to FOREIGN KEY REFERENCES in gravity.db Signed-off-by: DL6ER --- advanced/Templates/gravity.db.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/advanced/Templates/gravity.db.sql b/advanced/Templates/gravity.db.sql index 021f6f67..0187e4e6 100644 --- a/advanced/Templates/gravity.db.sql +++ b/advanced/Templates/gravity.db.sql @@ -43,8 +43,8 @@ CREATE TABLE adlist CREATE TABLE adlist_by_group ( - adlist_id INTEGER NOT NULL REFERENCES adlist (id), - group_id INTEGER NOT NULL REFERENCES "group" (id), + adlist_id INTEGER NOT NULL REFERENCES adlist (id) ON DELETE CASCADE, + group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE, PRIMARY KEY (adlist_id, group_id) ); @@ -75,8 +75,8 @@ INSERT INTO "info" VALUES('gravity_restored','false'); CREATE TABLE domainlist_by_group ( - domainlist_id INTEGER NOT NULL REFERENCES domainlist (id), - group_id INTEGER NOT NULL REFERENCES "group" (id), + domainlist_id INTEGER NOT NULL REFERENCES domainlist (id) ON DELETE CASCADE, + group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE, PRIMARY KEY (domainlist_id, group_id) ); @@ -91,8 +91,8 @@ CREATE TABLE client CREATE TABLE client_by_group ( - client_id INTEGER NOT NULL REFERENCES client (id), - group_id INTEGER NOT NULL REFERENCES "group" (id), + client_id INTEGER NOT NULL REFERENCES client (id) ON DELETE CASCADE, + group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE, PRIMARY KEY (client_id, group_id) ); From 315528d74036975816a83fb22b5228fc22ae80fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:25:08 +0000 Subject: [PATCH 034/259] Bump tox from 4.24.2 to 4.25.0 in /test Bumps [tox](https://github.com/tox-dev/tox) from 4.24.2 to 4.25.0. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.24.2...4.25.0) --- updated-dependencies: - dependency-name: tox dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 46d614e7..fa536e25 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.3.5 pytest-xdist == 3.6.1 pytest-testinfra == 10.1.1 -tox == 4.24.2 +tox == 4.25.0 pytest-clarity == 1.0.1 From 49fbdc4c00dc8cae39c04fc7fe4d73b5678e06de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 10:25:36 +0000 Subject: [PATCH 035/259] Bump actions/setup-python from 5.4.0 to 5.5.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.4.0 to 5.5.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5.4.0...v5.5.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e96bf7d5..43cd8ad4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,7 +77,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Python 3.10 - uses: actions/setup-python@v5.4.0 + uses: actions/setup-python@v5.5.0 with: python-version: "3.10" From 0f482396ee63f1f653ea707ec95925a84520dc0b Mon Sep 17 00:00:00 2001 From: James George Date: Sun, 23 Feb 2025 19:52:15 +0800 Subject: [PATCH 036/259] Update update.sh, updatecheck.sh and uninstall.sh to honour pihole.toml settings for webserver.paths.webroot and webserver.paths.webhome When uninstalling, remove web interface parent directory empty check and possible removal. Signed-off-by: James George --- advanced/Scripts/update.sh | 9 +++++++-- advanced/Scripts/updatecheck.sh | 8 +++++--- automated install/uninstall.sh | 15 +++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 9ea63b4c..6fb11a2b 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -12,7 +12,6 @@ # Variables readonly ADMIN_INTERFACE_GIT_URL="https://github.com/pi-hole/web.git" -readonly ADMIN_INTERFACE_DIR="/var/www/html/admin" readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git" readonly PI_HOLE_FILES_DIR="/etc/.pihole" @@ -26,12 +25,18 @@ CHECK_ONLY=false source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # shellcheck disable=SC1091 source "/opt/pihole/COL_TABLE" +# shellcheck disable=SC1091 +source "${PI_HOLE_INSTALL_DIR}/utils.sh" # is_repo() sourced from basic-install.sh # make_repo() sourced from basic-install.sh # update_repo() source from basic-install.sh # getGitFiles() sourced from basic-install.sh # FTLcheckUpdate() sourced from basic-install.sh +# getFTLConfigValue() sourced from utils.sh + +# Honour configured paths for the web application. +readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") GitCheckUpdateAvail() { local directory @@ -209,7 +214,7 @@ main() { echo "" echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo." getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}" - echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'" + echo -e " ${INFO} If you had made any changes in '${ADMIN_INTERFACE_DIR}', they have been stashed using 'git stash'" fi if [[ "${FTL_update}" == true ]]; then diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index b325ee9c..b64917a2 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -42,6 +42,8 @@ function get_remote_hash() { # shellcheck disable=SC1091 . /opt/pihole/utils.sh +readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") + # Remove the below three legacy files if they exist rm -f "/etc/pihole/GitHubVersions" rm -f "/etc/pihole/localbranches" @@ -85,13 +87,13 @@ addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_CORE_HASH" "${GITHUB_CORE_HASH}" # get Web versions -WEB_VERSION="$(get_local_version /var/www/html/admin)" +WEB_VERSION="$(get_local_version "${ADMIN_INTERFACE_DIR}")" addOrEditKeyValPair "${VERSION_FILE}" "WEB_VERSION" "${WEB_VERSION}" -WEB_BRANCH="$(get_local_branch /var/www/html/admin)" +WEB_BRANCH="$(get_local_branch "${ADMIN_INTERFACE_DIR}")" addOrEditKeyValPair "${VERSION_FILE}" "WEB_BRANCH" "${WEB_BRANCH}" -WEB_HASH="$(get_local_hash /var/www/html/admin)" +WEB_HASH="$(get_local_hash "${ADMIN_INTERFACE_DIR}")" addOrEditKeyValPair "${VERSION_FILE}" "WEB_HASH" "${WEB_HASH}" GITHUB_WEB_VERSION="$(get_remote_version web "${WEB_BRANCH}")" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 39c13037..332adbf6 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -9,6 +9,9 @@ # Please see LICENSE file for your rights under this license. source "/opt/pihole/COL_TABLE" +source "/opt/pihole/utils.sh" + +readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") while true; do read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer @@ -53,17 +56,9 @@ removeMetaPackage() { } removePiholeFiles() { - # Only web directories/files that are created by Pi-hole should be removed + # Remove the web interface of Pi-hole echo -ne " ${INFO} Removing Web Interface..." - ${SUDO} rm -rf /var/www/html/admin &> /dev/null - - - # If the web directory is empty after removing these files, then the parent html directory can be removed. - if [ -d "/var/www/html" ]; then - if [[ ! "$(ls -A /var/www/html)" ]]; then - ${SUDO} rm -rf /var/www/html &> /dev/null - fi - fi + ${SUDO} rm -rf "${ADMIN_INTERFACE_DIR}" &> /dev/null echo -e "${OVER} ${TICK} Removed Web Interface" # Attempt to preserve backwards compatibility with older versions From 7886cfc80ba781e90536574d74a1495de8ba1338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 31 Mar 2025 12:13:34 +0200 Subject: [PATCH 037/259] Add CentOS 10 to test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 1 + test/_centos_10.Dockerfile | 20 ++++++++++++++++++++ test/tox.centos_10.ini | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 test/_centos_10.Dockerfile create mode 100644 test/tox.centos_10.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43cd8ad4..ff31b080 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -67,6 +67,7 @@ jobs: ubuntu_22, ubuntu_24, centos_9, + centos_10, fedora_40, fedora_41, ] diff --git a/test/_centos_10.Dockerfile b/test/_centos_10.Dockerfile new file mode 100644 index 00000000..ca439e1b --- /dev/null +++ b/test/_centos_10.Dockerfile @@ -0,0 +1,20 @@ +FROM quay.io/centos/centos:stream10 +# Disable SELinux +RUN echo "SELINUX=disabled" > /etc/selinux/config +RUN yum install -y --allowerasing curl git initscripts + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true +ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/tox.centos_10.ini b/test/tox.centos_10.ini new file mode 100644 index 00000000..1a15c766 --- /dev/null +++ b/test/tox.centos_10.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv:py3] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _centos_10.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py From 3cb6ea503a1b8f17c077041a37976ebc05cc0e5d Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Tue, 1 Apr 2025 23:57:56 -0500 Subject: [PATCH 038/259] build `gravityDBfile_default` like the other variables seems this one was forgotten Signed-off-by: Michael Woolweaver --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 493f2b15..824ba5e1 100755 --- a/gravity.sh +++ b/gravity.sh @@ -58,7 +58,7 @@ fi # Set this only after sourcing pihole-FTL.conf as the gravity database path may # have changed gravityDBfile="${GRAVITYDB}" -gravityDBfile_default="/etc/pihole/gravity.db" +gravityDBfile_default="${piholeDir}/gravity.db" gravityTEMPfile="${GRAVITYDB}_temp" gravityDIR="$(dirname -- "${gravityDBfile}")" gravityOLDfile="${gravityDIR}/gravity_old.db" From 4efe4dfd4ba12be108a24fb97bc8d564989f5d9a Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Wed, 2 Apr 2025 14:21:45 -0500 Subject: [PATCH 039/259] source with source not dot Signed-off-by: Michael Woolweaver --- advanced/Scripts/piholeDebug.sh | 2 +- advanced/Scripts/query.sh | 4 ++-- advanced/Scripts/updatecheck.sh | 2 +- advanced/Scripts/version.sh | 4 ++-- advanced/Templates/pihole-FTL-poststop.sh | 2 +- advanced/Templates/pihole-FTL-prestart.sh | 2 +- advanced/Templates/pihole-FTL.service | 2 +- gravity.sh | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index f4226299..372df27f 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -42,7 +42,7 @@ else fi # shellcheck disable=SC1091 -. /etc/pihole/versions +source /etc/pihole/versions # Read the value of an FTL config key. The value is printed to stdout. get_ftl_conf_value() { diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index 3340bdd2..a65a1f07 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -22,10 +22,10 @@ domain="" # Source color table colfile="/opt/pihole/COL_TABLE" -. "${colfile}" +source "${colfile}" # Source api functions -. "${PI_HOLE_INSTALL_DIR}/api.sh" +source "${PI_HOLE_INSTALL_DIR}/api.sh" Help() { echo "Usage: pihole -q [option] diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index b325ee9c..0124808b 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -40,7 +40,7 @@ function get_remote_hash() { # Source the utils file for addOrEditKeyValPair() # shellcheck disable=SC1091 -. /opt/pihole/utils.sh +source /opt/pihole/utils.sh # Remove the below three legacy files if they exist rm -f "/etc/pihole/GitHubVersions" diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh index 540924c2..9e6fe75a 100755 --- a/advanced/Scripts/version.sh +++ b/advanced/Scripts/version.sh @@ -17,12 +17,12 @@ cachedVersions="/etc/pihole/versions" if [ -f ${cachedVersions} ]; then # shellcheck disable=SC1090 - . "$cachedVersions" + source "$cachedVersions" else echo "Could not find /etc/pihole/versions. Running update now." pihole updatechecker # shellcheck disable=SC1090 - . "$cachedVersions" + source "$cachedVersions" fi main() { diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh index b5ddbc97..38d3cc33 100755 --- a/advanced/Templates/pihole-FTL-poststop.sh +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -4,7 +4,7 @@ PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -. "${utilsfile}" +source "${utilsfile}" # Get file paths FTL_PID_FILE="$(getFTLConfigValue files.pid)" diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 37d750a2..99c47a3f 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -4,7 +4,7 @@ PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -. "${utilsfile}" +source "${utilsfile}" # Get file paths FTL_PID_FILE="$(getFTLConfigValue files.pid)" diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 151d4f90..67f509b5 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -13,7 +13,7 @@ PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -. "${utilsfile}" +source "${utilsfile}" is_running() { diff --git a/gravity.sh b/gravity.sh index 824ba5e1..50180d02 100755 --- a/gravity.sh +++ b/gravity.sh @@ -17,13 +17,13 @@ PI_HOLE_SCRIPT_DIR="/opt/pihole" # Source utils.sh for GetFTLConfigValue utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -. "${utilsfile}" +source "${utilsfile}" coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" # shellcheck disable=SC1090 -. "${coltable}" +source "${coltable}" # shellcheck disable=SC1091 -. "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" +source "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" basename="pihole" PIHOLE_COMMAND="/usr/local/bin/${basename}" From 4108c817dc4b478264f44064b90183d9f784ce6a Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 19:12:57 +0100 Subject: [PATCH 040/259] Revert "source with source not dot (#6137)" This reverts commit 8fd2ebd3d7bc00fe4c36dcdae0932d7bab4a3c3c, reversing changes made to 557bc6f1794244f55b36258a51e3bd494860b439. --- advanced/Scripts/piholeDebug.sh | 2 +- advanced/Scripts/query.sh | 4 ++-- advanced/Scripts/updatecheck.sh | 2 +- advanced/Scripts/version.sh | 4 ++-- advanced/Templates/pihole-FTL-poststop.sh | 2 +- advanced/Templates/pihole-FTL-prestart.sh | 2 +- advanced/Templates/pihole-FTL.service | 2 +- gravity.sh | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 372df27f..f4226299 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -42,7 +42,7 @@ else fi # shellcheck disable=SC1091 -source /etc/pihole/versions +. /etc/pihole/versions # Read the value of an FTL config key. The value is printed to stdout. get_ftl_conf_value() { diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index a65a1f07..3340bdd2 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -22,10 +22,10 @@ domain="" # Source color table colfile="/opt/pihole/COL_TABLE" -source "${colfile}" +. "${colfile}" # Source api functions -source "${PI_HOLE_INSTALL_DIR}/api.sh" +. "${PI_HOLE_INSTALL_DIR}/api.sh" Help() { echo "Usage: pihole -q [option] diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 0124808b..b325ee9c 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -40,7 +40,7 @@ function get_remote_hash() { # Source the utils file for addOrEditKeyValPair() # shellcheck disable=SC1091 -source /opt/pihole/utils.sh +. /opt/pihole/utils.sh # Remove the below three legacy files if they exist rm -f "/etc/pihole/GitHubVersions" diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh index 9e6fe75a..540924c2 100755 --- a/advanced/Scripts/version.sh +++ b/advanced/Scripts/version.sh @@ -17,12 +17,12 @@ cachedVersions="/etc/pihole/versions" if [ -f ${cachedVersions} ]; then # shellcheck disable=SC1090 - source "$cachedVersions" + . "$cachedVersions" else echo "Could not find /etc/pihole/versions. Running update now." pihole updatechecker # shellcheck disable=SC1090 - source "$cachedVersions" + . "$cachedVersions" fi main() { diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh index 38d3cc33..b5ddbc97 100755 --- a/advanced/Templates/pihole-FTL-poststop.sh +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -4,7 +4,7 @@ PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -source "${utilsfile}" +. "${utilsfile}" # Get file paths FTL_PID_FILE="$(getFTLConfigValue files.pid)" diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 99c47a3f..37d750a2 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -4,7 +4,7 @@ PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -source "${utilsfile}" +. "${utilsfile}" # Get file paths FTL_PID_FILE="$(getFTLConfigValue files.pid)" diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 67f509b5..151d4f90 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -13,7 +13,7 @@ PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -source "${utilsfile}" +. "${utilsfile}" is_running() { diff --git a/gravity.sh b/gravity.sh index 50180d02..824ba5e1 100755 --- a/gravity.sh +++ b/gravity.sh @@ -17,13 +17,13 @@ PI_HOLE_SCRIPT_DIR="/opt/pihole" # Source utils.sh for GetFTLConfigValue utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck disable=SC1090 -source "${utilsfile}" +. "${utilsfile}" coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" # shellcheck disable=SC1090 -source "${coltable}" +. "${coltable}" # shellcheck disable=SC1091 -source "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" +. "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" basename="pihole" PIHOLE_COMMAND="/usr/local/bin/${basename}" From e548ed043fd1e80a77ba3cfbbc77219dac6987f8 Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Mon, 31 Mar 2025 22:18:32 -0500 Subject: [PATCH 041/259] ensure gravity_Cleanup() checks the correct directory for list data also glob with * to ensure .etag & .sha1 are removed as well should fix #6075 Co-authored-by: yubiuser Signed-off-by: Michael Woolweaver --- gravity.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gravity.sh b/gravity.sh index 493f2b15..151801ed 100755 --- a/gravity.sh +++ b/gravity.sh @@ -572,7 +572,7 @@ gravity_DownloadBlocklists() { echo "" done - gravity_Blackbody=true + DownloadBlocklists_done=true } compareLists() { @@ -932,13 +932,13 @@ gravity_Cleanup() { # invalid_domains location rm "${GRAVITY_TMPDIR}"/*.ph-non-domains 2>/dev/null - # Ensure this function only runs when gravity_SetDownloadOptions() has completed - if [[ "${gravity_Blackbody:-}" == true ]]; then - # Remove any unused .domains files - for file in "${piholeDir}"/*."${domainsExtension}"; do - # If list is not in active array, then remove it + # Ensure this function only runs when gravity_DownloadBlocklists() has completed + if [[ "${DownloadBlocklists_done:-}" == true ]]; then + # Remove any unused .domains/.etag/.sha files + for file in "${listsCacheDir}"/*."${domainsExtension}"; do + # If list is not in active array, then remove it and all associated files if [[ ! "${activeDomains[*]}" == *"${file}"* ]]; then - rm -f "${file}" 2>/dev/null || + rm -f "${file}"* 2>/dev/null || echo -e " ${CROSS} Failed to remove ${file##*/}" fi done From f98b9520e4508b05ebfbff52fdf4e81f892d33bb Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:19:14 +0100 Subject: [PATCH 042/259] v5 sudoers file that allowed www-data to run pihole command is no longer needed. "Fixes" #6066 Signed-off-by: Adam Warner --- automated install/basic-install.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e69256ff..acd83e31 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2411,6 +2411,15 @@ main() { # Migrate existing install to v6.0 migrate_dnsmasq_configs + # Cleanup old v5 sudoers file if it exists + sudoers_file="/etc/sudoers.d/pihole" + if [[ -f "${sudoers_file}" ]]; then + # only remove the file if it contains the Pi-hole header + if grep -q "Pi-hole: A black hole for Internet advertisements" "${sudoers_file}"; then + rm -f "${sudoers_file}" + fi + fi + # Check for and disable systemd-resolved-DNSStubListener before reloading resolved # DNSStubListener needs to remain in place for installer to download needed files, # so this change needs to be made after installation is complete, From fe2b22c57089f83abae8fa27d1d1975e928852d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Mar 2025 19:19:07 +0100 Subject: [PATCH 043/259] Add recommended fields to the deb package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e69256ff..9e0246f0 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -106,11 +106,13 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion +Section: contrib/metapackages +Priority: optional EOM ) From 07864032de9b0f0f6781cc09db1e39f1f77c3a41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Apr 2025 10:05:08 +0000 Subject: [PATCH 044/259] Bump pytest-testinfra from 10.1.1 to 10.2.2 in /test Bumps [pytest-testinfra](https://github.com/pytest-dev/pytest-testinfra) from 10.1.1 to 10.2.2. - [Release notes](https://github.com/pytest-dev/pytest-testinfra/releases) - [Changelog](https://github.com/pytest-dev/pytest-testinfra/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-testinfra/compare/10.1.1...10.2.2) --- updated-dependencies: - dependency-name: pytest-testinfra dependency-version: 10.2.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index fa536e25..6987ee0c 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,6 +1,6 @@ pyyaml == 6.0.2 pytest == 8.3.5 pytest-xdist == 3.6.1 -pytest-testinfra == 10.1.1 +pytest-testinfra == 10.2.2 tox == 4.25.0 pytest-clarity == 1.0.1 From 6e06a93c31c309c22a21e2bb4c520ad675d141d7 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sat, 5 Apr 2025 00:41:50 +0100 Subject: [PATCH 045/259] functionise log rotation and flushing code to avoid dupliation Signed-off-by: Adam Warner --- advanced/Scripts/piholeLogFlush.sh | 121 ++++++++++------------------- 1 file changed, 43 insertions(+), 78 deletions(-) diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 58c6a41d..f3ecd8ad 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -40,6 +40,42 @@ if [ -z "$WEBFILE" ]; then WEBFILE="/var/log/pihole/webserver.log" fi +# Helper function to handle log rotation for a single file +rotate_log() { + # This function copies x.log over to x.log.1 + # and then empties x.log + # Note that moving the file is not an option, as + # dnsmasq would happily continue writing into the + # moved file (it will have the same file handler) + local logfile="$1" + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Rotating ${logfile} ..." + fi + cp -p "${logfile}" "${logfile}.1" + echo " " > "${logfile}" + chmod 640 "${logfile}" + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Rotated ${logfile} ..." + fi +} + +# Helper function to handle log flushing for a single file +flush_log() { + local logfile="$1" + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Flushing ${logfile} ..." + fi + echo " " > "${logfile}" + chmod 640 "${logfile}" + if [ -f "${logfile}.1" ]; then + echo " " > "${logfile}.1" + chmod 640 "${logfile}.1" + fi + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Flushed ${logfile} ..." + fi +} + if [[ "$*" == *"once"* ]]; then # Nightly logrotation if command -v /usr/sbin/logrotate >/dev/null; then @@ -50,87 +86,16 @@ if [[ "$*" == *"once"* ]]; then fi /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate else - # Copy pihole.log over to pihole.log.1 - # and empty out pihole.log - # Note that moving the file is not an option, as - # dnsmasq would happily continue writing into the - # moved file (it will have the same file handler) - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Rotating ${LOGFILE} ..." - fi - cp -p "${LOGFILE}" "${LOGFILE}.1" - echo " " > "${LOGFILE}" - chmod 640 "${LOGFILE}" - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Rotated ${LOGFILE} ..." - fi - # Copy FTL.log over to FTL.log.1 - # and empty out FTL.log - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Rotating ${FTLFILE} ..." - fi - cp -p "${FTLFILE}" "${FTLFILE}.1" - echo " " > "${FTLFILE}" - chmod 640 "${FTLFILE}" - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Rotated ${FTLFILE} ..." - fi - # Copy webserver.log over to webserver.log.1 - # and empty out webserver.log - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Rotating ${WEBFILE} ..." - fi - cp -p "${WEBFILE}" "${WEBFILE}.1" - echo " " > "${WEBFILE}" - chmod 640 "${WEBFILE}" - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Rotated ${WEBFILE} ..." - fi + # Handle rotation for each log file + rotate_log "${LOGFILE}" + rotate_log "${FTLFILE}" + rotate_log "${WEBFILE}" fi else # Manual flushing - - # Flush both pihole.log and pihole.log.1 (if existing) - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing ${LOGFILE} ..." - fi - echo " " > "${LOGFILE}" - chmod 640 "${LOGFILE}" - if [ -f "${LOGFILE}.1" ]; then - echo " " > "${LOGFILE}.1" - chmod 640 "${LOGFILE}.1" - fi - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Flushed ${LOGFILE} ..." - fi - - # Flush both FTL.log and FTL.log.1 (if existing) - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing ${FTLFILE} ..." - fi - echo " " > "${FTLFILE}" - chmod 640 "${FTLFILE}" - if [ -f "${FTLFILE}.1" ]; then - echo " " > "${FTLFILE}.1" - chmod 640 "${FTLFILE}.1" - fi - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Flushed ${FTLFILE} ..." - fi - - # Flush both webserver.log and webserver.log.1 (if existing) - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing ${WEBFILE} ..." - fi - echo " " > "${WEBFILE}" - chmod 640 "${WEBFILE}" - if [ -f "${WEBFILE}.1" ]; then - echo " " > "${WEBFILE}.1" - chmod 640 "${WEBFILE}.1" - fi - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Flushed ${WEBFILE} ..." - fi + flush_log "${LOGFILE}" + flush_log "${FTLFILE}" + flush_log "${WEBFILE}" if [[ "$*" != *"quiet"* ]]; then echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." From e018a37a8cf59af5c0d81ce54807ee38e49bb55e Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:24:51 +0100 Subject: [PATCH 046/259] First things first - bump severity of shellcheck action from error to warning Signed-off-by: Adam Warner --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ff31b080..0fadb6f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,7 @@ jobs: with: check_together: 'yes' format: tty - severity: error + severity: warning - name: Spell-Checking uses: codespell-project/actions-codespell@master From 39f5115135f71b05b7080b7b49750178978d0cf7 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:39:44 +0100 Subject: [PATCH 047/259] In ./automated install/basic-install.sh line 1753: local status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) ^----^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./automated install/basic-install.sh line 2076: elif [ $? -eq 2 ]; then ^-- SC2319 (warning): This $? refers to a condition, not a command. Assign to a variable to avoid it being overwritten. Signed-off-by: Adam Warner --- automated install/basic-install.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 3af23793..59dbb94b 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1752,7 +1752,8 @@ checkSelinux() { check_download_exists() { # Check if the download exists and we can reach the server - local status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) + local status + status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) # Check the status code if grep -q "200" <<<"$status"; then @@ -2069,13 +2070,13 @@ FTLcheckUpdate() { path="${ftlBranch}/${binary}" # Check whether or not the binary for this FTL branch actually exists. If not, then there is no update! - # shellcheck disable=SC1090 if ! check_download_exists "$path"; then - if [ $? -eq 1 ]; then + local status + status=$? + if [ "${status}" -eq 1 ]; then printf " %b Branch \"%s\" is not available.\\n" "${INFO}" "${ftlBranch}" printf " %b Use %bpihole checkout ftl [branchname]%b to switch to a valid branch.\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" - return 2 - elif [ $? -eq 2 ]; then + elif [ "${status}" -eq 2 ]; then printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}" return 3 else From a624d3be8d99692e4ed6a64dd9c375a8c57bbfe3 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:39:56 +0100 Subject: [PATCH 048/259] In ./advanced/Scripts/utils.sh line 91: if [[ $? -eq 5 ]]; then ^------------^ SC3010 (warning): In POSIX sh, [[ ]] is undefined. Signed-off-by: Adam Warner --- advanced/Scripts/utils.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index 63d51f87..adce8144 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -88,8 +88,8 @@ getFTLConfigValue(){ ####################### setFTLConfigValue(){ pihole-FTL --config "${1}" "${2}" >/dev/null - if [[ $? -eq 5 ]]; then - echo -e " ${CROSS} ${1} set by environment variable. Please unset it to use this function" + if [ $? -eq 5 ]; then + printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}" exit 5 fi } From 59d21772710b200cb38b5051cfe73423dfa789f1 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:41:43 +0100 Subject: [PATCH 049/259] In ./advanced/Scripts/database_migration/gravity-db.sh line 18: piholeDir="${2}" ^-------^ SC2034 (warning): piholeDir appears unused. Verify use (or export if used externally). Turns out it is _actually_ unused, the full path of the gravity database is passed to the function, so we'll tidy this up rather than supressing. Signed-off-by: Adam Warner --- advanced/Scripts/database_migration/gravity-db.sh | 3 +-- gravity.sh | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/database_migration/gravity-db.sh b/advanced/Scripts/database_migration/gravity-db.sh index b0982bcc..d701f2bf 100755 --- a/advanced/Scripts/database_migration/gravity-db.sh +++ b/advanced/Scripts/database_migration/gravity-db.sh @@ -13,9 +13,8 @@ readonly scriptPath="/etc/.pihole/advanced/Scripts/database_migration/gravity" upgrade_gravityDB(){ - local database piholeDir version + local database version database="${1}" - piholeDir="${2}" # Exit early if the database does not exist (e.g. in CI tests) if [[ ! -f "${database}" ]]; then diff --git a/gravity.sh b/gravity.sh index e4f47719..57df0712 100755 --- a/gravity.sh +++ b/gravity.sh @@ -306,7 +306,7 @@ migrate_to_database() { fi # Check if gravity database needs to be updated - upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" + upgrade_gravityDB "${gravityDBfile}" # Migrate list files to new database if [ -e "${adListFile}" ]; then @@ -334,7 +334,7 @@ migrate_to_database() { fi # Check if gravity database needs to be updated - upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" + upgrade_gravityDB "${gravityDBfile}" } # Determine if DNS resolution is available before proceeding @@ -1100,7 +1100,7 @@ for var in "$@"; do "-t" | "--timeit") timed=true ;; "-r" | "--repair") repairSelector "$3" ;; "-u" | "--upgrade") - upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" + upgrade_gravityDB "${gravityDBfile}" exit 0 ;; "-h" | "--help") helpFunc ;; From 63623c43538c5591c12771d06a28dae7f53ce347 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:46:10 +0100 Subject: [PATCH 050/259] In ./advanced/Scripts/piholeCheckout.sh line 112: corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}")) ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting). In ./advanced/Scripts/piholeCheckout.sh line 139: webbranches=($(get_available_branches "${webInterfaceDir}")) ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting). In ./advanced/Scripts/piholeCheckout.sh line 170: ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) ) ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting). In ./advanced/Scripts/piholeCheckout.sh line 218: elif [ $? -eq 2 ]; then ^-- SC2319 (warning): This $? refers to a condition, not a command. Assign to a variable to avoid it being overwritten. Signed-off-by: Adam Warner --- advanced/Scripts/piholeCheckout.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index 84c966df..58d62bc5 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -109,7 +109,7 @@ checkout() { echo -e "${OVER} ${CROSS} $str" exit 1 fi - corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}")) + mapfile -t corebranches < <(get_available_branches "${PI_HOLE_FILES_DIR}") if [[ "${corebranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" @@ -136,7 +136,7 @@ checkout() { echo -e "${OVER} ${CROSS} $str" exit 1 fi - webbranches=($(get_available_branches "${webInterfaceDir}")) + mapfile -t webbranches < <(get_available_branches "${webInterfaceDir}") if [[ "${webbranches[*]}" == *"master"* ]]; then echo -e "${OVER} ${TICK} $str" @@ -167,7 +167,7 @@ checkout() { # Check if requested branch is available echo -e " ${INFO} Checking for availability of branch ${COL_CYAN}${2}${COL_NC} on GitHub" - ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) ) + mapfile -t ftlbranches < <(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) # If returned array is empty -> connectivity issue if [[ ${#ftlbranches[@]} -eq 0 ]]; then echo -e " ${CROSS} Unable to fetch branches from GitHub. Please check your Internet connection and try again later." @@ -209,13 +209,15 @@ checkout() { # Update local and remote versions via updatechecker /opt/pihole/updatecheck.sh else - if [ $? -eq 1 ]; then + local status + status=$? + if [ $status -eq 1 ]; then # Binary for requested branch is not available, may still be # int he process of being built or CI build job failed printf " %b Binary for requested branch is not available, please try again later.\\n" ${CROSS} printf " If the issue persists, please contact Pi-hole Support and ask them to re-generate the binary.\\n" exit 1 - elif [ $? -eq 2 ]; then + elif [ $status -eq 2 ]; then printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}" exit 1 else From f5dc337d1b819dd359b15e26dfb07fa94bcccc79 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:48:12 +0100 Subject: [PATCH 051/259] In ./advanced/Scripts/piholeLogFlush.sh line 12: source ${colfile} ^--------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. In ./advanced/Scripts/piholeLogFlush.sh line 16: source "${utilsfile}" ^------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. Signed-off-by: Adam Warner --- advanced/Scripts/piholeLogFlush.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 58c6a41d..2e67a9ee 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -7,6 +7,7 @@ # # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. +# shellcheck disable=SC1090 colfile="/opt/pihole/COL_TABLE" source ${colfile} From 3a9b9c027efcb53d239fc66b2ba8545c01a0e59e Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:50:51 +0100 Subject: [PATCH 052/259] In ./pihole line 20: source "${colfile}" ^----------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. In ./pihole line 23: source "${utilsfile}" ^------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. In ./pihole line 27: source "${apifile}" ^----------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. In ./pihole line 34: source "${versionsfile}" ^---------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location. In ./pihole line 251: local timer="$(echo "${data}"| jq --raw-output '.timer' )" ^---^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./pihole line 255: local str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}" ^-^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./pihole line 378: local logging_enabled=$(getFTLConfigValue dns.queryLogging) ^-------------^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./pihole line 385: readonly LOGFILE=$(getFTLConfigValue files.log.dnsmasq) ^-----^ SC2155 (warning): Declare and assign separately to avoid masking return values. Signed-off-by: Adam Warner --- pihole | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pihole b/pihole index bf662a82..efba71f0 100755 --- a/pihole +++ b/pihole @@ -9,6 +9,8 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. +# shellcheck disable=SC1090 + readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" # PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout), @@ -247,12 +249,14 @@ Time: data=$(PostFTLData "dns/blocking" "{ \"blocking\": ${1}, \"timer\": ${tt} }") # Check the response - local extra=" forever" - local timer="$(echo "${data}"| jq --raw-output '.timer' )" + local extra timer + extra=" forever" + timer="$(echo "${data}"| jq --raw-output '.timer' )" if [[ "${timer}" != "null" ]]; then extra=" for ${timer}s" fi - local str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}" + local str + str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}" # Logout from the API LogoutAPI @@ -375,14 +379,16 @@ statusFunc() { tailFunc() { # Warn user if Pi-hole's logging is disabled - local logging_enabled=$(getFTLConfigValue dns.queryLogging) + local logging_enabled + logging_enabled=$(getFTLConfigValue dns.queryLogging) if [[ "${logging_enabled}" != "true" ]]; then echo " ${CROSS} Warning: Query logging is disabled" fi echo -e " ${INFO} Press Ctrl-C to exit" # Get logfile path - readonly LOGFILE=$(getFTLConfigValue files.log.dnsmasq) + readonly LOGFILE + LOGFILE=$(getFTLConfigValue files.log.dnsmasq) # Strip date from each line # Color blocklist/denylist/wildcard entries as red From f01e8c70d9333c66929e64978df2d56089e5dfb7 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 4 Apr 2025 23:54:34 +0100 Subject: [PATCH 053/259] Weirldly, GHA missed these minor warnings however have disabled them as they are due to variables either being used in or declared in basic-install,.sh Signed-off-by: Adam Warner --- advanced/Scripts/piholeCheckout.sh | 4 ++++ automated install/uninstall.sh | 1 + 2 files changed, 5 insertions(+) diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index 58d62bc5..be5c9dc5 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -9,6 +9,7 @@ # Please see LICENSE file for your rights under this license. readonly PI_HOLE_FILES_DIR="/etc/.pihole" +# shellcheck disable=SC2034 SKIP_INSTALL="true" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" @@ -59,6 +60,7 @@ checkout() { exit 1; fi + # shellcheck disable=SC2154 if ! is_repo "${webInterfaceDir}" ; then echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!" echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" @@ -103,6 +105,7 @@ checkout() { echo "master" > /etc/pihole/ftlbranch chmod 644 /etc/pihole/ftlbranch elif [[ "${1}" == "core" ]] ; then + # shellcheck disable=SC2154 str="Fetching branches from ${piholeGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then @@ -130,6 +133,7 @@ checkout() { fi checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}" elif [[ "${1}" == "web" ]] ; then + # shellcheck disable=SC2154 str="Fetching branches from ${webInterfaceGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${webInterfaceDir}" ; then diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 332adbf6..28917bca 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -39,6 +39,7 @@ else fi readonly PI_HOLE_FILES_DIR="/etc/.pihole" +# shellcheck disable=SC2034 SKIP_INSTALL="true" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" From 48c59cb6cf66546a7b8f2f7a8ca1ccc0bc51281e Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 6 Apr 2025 14:18:52 +0100 Subject: [PATCH 054/259] In ./automated install/uninstall.sh line 14: readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./advanced/Scripts/update.sh line 39: readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values. In ./advanced/Scripts/updatecheck.sh line 45: readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values. Signed-off-by: Adam Warner --- advanced/Scripts/update.sh | 3 ++- advanced/Scripts/updatecheck.sh | 3 ++- automated install/uninstall.sh | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index ed038db9..d7441105 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -36,7 +36,8 @@ source "${PI_HOLE_INSTALL_DIR}/utils.sh" # getFTLConfigValue() sourced from utils.sh # Honour configured paths for the web application. -readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +readonly ADMIN_INTERFACE_DIR GitCheckUpdateAvail() { local directory diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index b64917a2..6cd485eb 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -42,7 +42,8 @@ function get_remote_hash() { # shellcheck disable=SC1091 . /opt/pihole/utils.sh -readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +readonly ADMIN_INTERFACE_DIR # Remove the below three legacy files if they exist rm -f "/etc/pihole/GitHubVersions" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 28917bca..9020d275 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -11,7 +11,8 @@ source "/opt/pihole/COL_TABLE" source "/opt/pihole/utils.sh" -readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +readonly ADMIN_INTERFACE_DIR while true; do read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer From 2088601148b0ab1180892f4cab7269eb619a4173 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sun, 6 Apr 2025 14:33:34 +0100 Subject: [PATCH 055/259] Add .shellcheckrc to configure shellcheck ignore SC1090-1 globally Signed-off-by: Adam Warner --- .shellcheckrc | 1 + advanced/Scripts/database_migration/gravity-db.sh | 2 +- advanced/Scripts/list.sh | 1 - advanced/Scripts/piholeARPTable.sh | 1 - advanced/Scripts/piholeLogFlush.sh | 1 - advanced/Scripts/query.sh | 2 +- advanced/Scripts/update.sh | 1 - advanced/Scripts/version.sh | 2 -- advanced/Templates/pihole-FTL-poststop.sh | 1 - advanced/Templates/pihole-FTL-prestart.sh | 1 - advanced/Templates/pihole-FTL.service | 1 - automated install/basic-install.sh | 1 - gravity.sh | 3 --- pihole | 2 -- 14 files changed, 3 insertions(+), 17 deletions(-) create mode 100644 .shellcheckrc diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 00000000..37eee86d --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1 @@ +disable=SC1090,SC1091 # Ignore warnings about being unable to follow sourced files diff --git a/advanced/Scripts/database_migration/gravity-db.sh b/advanced/Scripts/database_migration/gravity-db.sh index d701f2bf..41593368 100755 --- a/advanced/Scripts/database_migration/gravity-db.sh +++ b/advanced/Scripts/database_migration/gravity-db.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# shellcheck disable=SC1090 + # Pi-hole: A black hole for Internet advertisements # (c) 2019 Pi-hole, LLC (https://pi-hole.net) diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index 5c57f878..3280ebfa 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1090 # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh index f55b1320..e0565148 100755 --- a/advanced/Scripts/piholeARPTable.sh +++ b/advanced/Scripts/piholeARPTable.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1090 # Pi-hole: A black hole for Internet advertisements # (c) 2019 Pi-hole, LLC (https://pi-hole.net) diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 2e67a9ee..58c6a41d 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -7,7 +7,6 @@ # # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -# shellcheck disable=SC1090 colfile="/opt/pihole/COL_TABLE" source ${colfile} diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index 3340bdd2..43498f17 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -1,5 +1,5 @@ #!/usr/bin/env sh -# shellcheck disable=SC1090 + # Ignore warning about `local` being undefinded in POSIX # shellcheck disable=SC3043 diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index d7441105..e94ef0fd 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -21,7 +21,6 @@ SKIP_INSTALL=true # when --check-only is passed to this script, it will not perform the actual update CHECK_ONLY=false -# shellcheck disable=SC1090 source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # shellcheck disable=SC1091 source "/opt/pihole/COL_TABLE" diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh index 540924c2..54b89498 100755 --- a/advanced/Scripts/version.sh +++ b/advanced/Scripts/version.sh @@ -16,12 +16,10 @@ cachedVersions="/etc/pihole/versions" if [ -f ${cachedVersions} ]; then - # shellcheck disable=SC1090 . "$cachedVersions" else echo "Could not find /etc/pihole/versions. Running update now." pihole updatechecker - # shellcheck disable=SC1090 . "$cachedVersions" fi diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh index b5ddbc97..d196e3da 100755 --- a/advanced/Templates/pihole-FTL-poststop.sh +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -3,7 +3,6 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck disable=SC1090 . "${utilsfile}" # Get file paths diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 37d750a2..5bfd1b17 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -3,7 +3,6 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck disable=SC1090 . "${utilsfile}" # Get file paths diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 151d4f90..6cb3e09a 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -12,7 +12,6 @@ # Source utils.sh for getFTLConfigValue(), getFTLPID() PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck disable=SC1090 . "${utilsfile}" diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 59dbb94b..ef6e02c6 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1090 # Pi-hole: A black hole for Internet advertisements # (c) Pi-hole (https://pi-hole.net) diff --git a/gravity.sh b/gravity.sh index 57df0712..102ec15f 100755 --- a/gravity.sh +++ b/gravity.sh @@ -1,5 +1,4 @@ #!/usr/bin/env bash -# shellcheck disable=SC1090 # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) @@ -16,11 +15,9 @@ export LC_ALL=C PI_HOLE_SCRIPT_DIR="/opt/pihole" # Source utils.sh for GetFTLConfigValue utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck disable=SC1090 . "${utilsfile}" coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" -# shellcheck disable=SC1090 . "${coltable}" # shellcheck disable=SC1091 . "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" diff --git a/pihole b/pihole index efba71f0..c780308d 100755 --- a/pihole +++ b/pihole @@ -9,8 +9,6 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -# shellcheck disable=SC1090 - readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" # PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout), From e579397f51526964e5199ff855937b15567c0f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 24 Feb 2025 20:03:44 +0100 Subject: [PATCH 056/259] Allow all users to read the version file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Templates/pihole-FTL-prestart.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 37d750a2..ed2e6a2e 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -12,6 +12,9 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole/ /var/log/pihole/ +# allow all users read version file +chmod 0664 /etc/pihole/versions + # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + # Set all files (except TLS-related ones) to u+rw g+r From d28e7952668ca0b2b35dce7eaac55eb1768c74b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 25 Feb 2025 21:12:58 +0100 Subject: [PATCH 057/259] Permissions on versions file should be 640 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/updatecheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index b64917a2..b5ae7e46 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -52,7 +52,7 @@ rm -f "/etc/pihole/localversions" # Create new versions file if it does not exist VERSION_FILE="/etc/pihole/versions" touch "${VERSION_FILE}" -chmod 644 "${VERSION_FILE}" +chmod 640 "${VERSION_FILE}" # if /pihole.docker.tag file exists, we will use it's value later in this script DOCKER_TAG=$(cat /pihole.docker.tag 2>/dev/null) From 9f5e18b1cdf65429aeb40c6ad6aa84cf7ec33e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 6 Apr 2025 20:52:02 +0200 Subject: [PATCH 058/259] Make it 644 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/updatecheck.sh | 2 +- advanced/Templates/pihole-FTL-prestart.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index b5ae7e46..b64917a2 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -52,7 +52,7 @@ rm -f "/etc/pihole/localversions" # Create new versions file if it does not exist VERSION_FILE="/etc/pihole/versions" touch "${VERSION_FILE}" -chmod 640 "${VERSION_FILE}" +chmod 644 "${VERSION_FILE}" # if /pihole.docker.tag file exists, we will use it's value later in this script DOCKER_TAG=$(cat /pihole.docker.tag 2>/dev/null) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index ed2e6a2e..7ad1bfe8 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -12,8 +12,9 @@ FTL_PID_FILE="$(getFTLConfigValue files.pid)" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole/ /var/log/pihole/ -# allow all users read version file -chmod 0664 /etc/pihole/versions + +# allow all users read version file (and use pihole -v) +chmod 0644 /etc/pihole/versions # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} + From ca1bab3c1b012533844a8c5c3586886e131bf716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 10:34:42 +0200 Subject: [PATCH 059/259] Fix more shellcheck warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .shellcheckrc | 3 ++- advanced/Scripts/api.sh | 1 - advanced/Scripts/list.sh | 3 +++ advanced/Scripts/piholeARPTable.sh | 2 ++ advanced/Scripts/piholeCheckout.sh | 3 ++- advanced/Scripts/piholeDebug.sh | 10 ++++++---- advanced/Scripts/piholeLogFlush.sh | 2 ++ advanced/Scripts/query.sh | 6 +----- advanced/Scripts/update.sh | 5 +++-- advanced/Scripts/updatecheck.sh | 2 +- advanced/Scripts/utils.sh | 1 - advanced/Scripts/version.sh | 6 ++---- advanced/Templates/pihole-FTL-poststop.sh | 1 + advanced/Templates/pihole-FTL-prestart.sh | 1 + automated install/basic-install.sh | 4 ++-- automated install/uninstall.sh | 3 +++ gravity.sh | 7 ++++--- pihole | 4 ++++ 18 files changed, 39 insertions(+), 25 deletions(-) diff --git a/.shellcheckrc b/.shellcheckrc index 37eee86d..8e0b8387 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -1 +1,2 @@ -disable=SC1090,SC1091 # Ignore warnings about being unable to follow sourced files +external-sources=true # allow shellcheck to read external sources +disable=SC3043 #disable SC3043: In POSIX sh, local is undefined. diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 79fc90f4..65a4eaa5 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -1,5 +1,4 @@ #!/usr/bin/env sh -# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index 3280ebfa..c07b0f2d 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -11,9 +11,11 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./utils.sh" source "${utilsfile}" readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" +# shellcheck source="./api.sh" source "${apifile}" # Determine database location @@ -38,6 +40,7 @@ typeId="" comment="" colfile="/opt/pihole/COL_TABLE" +# shellcheck source="./COL_TABLE" source ${colfile} helpFunc() { diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh index e0565148..8257eb3e 100755 --- a/advanced/Scripts/piholeARPTable.sh +++ b/advanced/Scripts/piholeARPTable.sh @@ -11,11 +11,13 @@ coltable="/opt/pihole/COL_TABLE" if [[ -f ${coltable} ]]; then +# shellcheck source="./COL_TABLE" source ${coltable} fi readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./utils.sh" source "${utilsfile}" # Determine database location diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index be5c9dc5..bde8a355 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -11,6 +11,7 @@ readonly PI_HOLE_FILES_DIR="/etc/.pihole" # shellcheck disable=SC2034 SKIP_INSTALL="true" +# shellcheck source="../../automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # webInterfaceGitUrl set in basic-install.sh @@ -218,7 +219,7 @@ checkout() { if [ $status -eq 1 ]; then # Binary for requested branch is not available, may still be # int he process of being built or CI build job failed - printf " %b Binary for requested branch is not available, please try again later.\\n" ${CROSS} + printf " %b Binary for requested branch is not available, please try again later.\\n" "${CROSS}" printf " If the issue persists, please contact Pi-hole Support and ask them to re-generate the binary.\\n" exit 1 elif [ $status -eq 2 ]; then diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index f4226299..1b196a80 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -8,7 +8,6 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -# shellcheck source=/dev/null # -e option instructs bash to immediately exit if any command [1] has a non-zero exit status # -u a reference to any variable you haven't previously defined @@ -27,6 +26,7 @@ PIHOLE_COLTABLE_FILE="${PIHOLE_SCRIPTS_DIRECTORY}/COL_TABLE" # These provide the colors we need for making the log more readable if [[ -f ${PIHOLE_COLTABLE_FILE} ]]; then +# shellcheck source=./COL_TABLE source ${PIHOLE_COLTABLE_FILE} else COL_NC='\e[0m' # No Color @@ -41,7 +41,7 @@ else #OVER="\r\033[K" fi -# shellcheck disable=SC1091 +# shellcheck source=/dev/null . /etc/pihole/versions # Read the value of an FTL config key. The value is printed to stdout. @@ -213,7 +213,7 @@ compare_local_version_to_git_version() { local local_status local_status=$(git status -s) # echo this information out to the user in a nice format - if [ ${local_version} ]; then + if [ "${local_version}" ]; then log_write "${TICK} Version: ${local_version}" elif [ -n "${DOCKER_VERSION}" ]; then log_write "${TICK} Version: Pi-hole Docker Container ${COL_BOLD}${DOCKER_VERSION}${COL_NC}" @@ -488,7 +488,9 @@ run_and_print_command() { local output output=$(${cmd} 2>&1) # If the command was successful, - if [[ $? -eq 0 ]]; then + local return_code + return_code=$? + if [[ "${return_code}" -eq 0 ]]; then # show the output log_write "${output}" else diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 58c6a41d..ab88fb73 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -9,10 +9,12 @@ # Please see LICENSE file for your rights under this license. colfile="/opt/pihole/COL_TABLE" +# shellcheck source="./COL_TABLE" source ${colfile} readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./utils.sh" source "${utilsfile}" # In case we're running at the same time as a system logrotate, use a diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index 43498f17..aeebba3a 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -1,10 +1,5 @@ #!/usr/bin/env sh - -# Ignore warning about `local` being undefinded in POSIX -# shellcheck disable=SC3043 -# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions - # Pi-hole: A black hole for Internet advertisements # (c) 2023 Pi-hole, LLC (https://pi-hole.net) # Network-wide ad blocking via your own hardware. @@ -22,6 +17,7 @@ domain="" # Source color table colfile="/opt/pihole/COL_TABLE" +# shellcheck source="./COL_TABLE" . "${colfile}" # Source api functions diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index e94ef0fd..7e13054e 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -21,10 +21,11 @@ SKIP_INSTALL=true # when --check-only is passed to this script, it will not perform the actual update CHECK_ONLY=false +# shellcheck source="../../automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" -# shellcheck disable=SC1091 +# shellcheck source=./COL_TABLE source "/opt/pihole/COL_TABLE" -# shellcheck disable=SC1091 +# shellcheck source="./utils.sh" source "${PI_HOLE_INSTALL_DIR}/utils.sh" # is_repo() sourced from basic-install.sh diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 6cd485eb..62bcbcf3 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -39,7 +39,7 @@ function get_remote_hash() { } # Source the utils file for addOrEditKeyValPair() -# shellcheck disable=SC1091 +# shellcheck source="./utils.sh" . /opt/pihole/utils.sh ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index adce8144..d4a6957c 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -1,5 +1,4 @@ #!/usr/bin/env sh -# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions # Pi-hole: A black hole for Internet advertisements # (c) 2017 Pi-hole, LLC (https://pi-hole.net) diff --git a/advanced/Scripts/version.sh b/advanced/Scripts/version.sh index 54b89498..e932fe63 100755 --- a/advanced/Scripts/version.sh +++ b/advanced/Scripts/version.sh @@ -8,18 +8,16 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -# Ignore warning about `local` being undefinded in POSIX -# shellcheck disable=SC3043 -# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions - # Source the versions file populated by updatechecker.sh cachedVersions="/etc/pihole/versions" if [ -f ${cachedVersions} ]; then + # shellcheck source=/dev/null . "$cachedVersions" else echo "Could not find /etc/pihole/versions. Running update now." pihole updatechecker + # shellcheck source=/dev/null . "$cachedVersions" fi diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh index d196e3da..e7db109d 100755 --- a/advanced/Templates/pihole-FTL-poststop.sh +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -3,6 +3,7 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="../Scripts/utils.sh" . "${utilsfile}" # Get file paths diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index aae26cf3..056cb21c 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -3,6 +3,7 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="../Scripts/utils.sh" . "${utilsfile}" # Get file paths diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index ef6e02c6..2d9041a2 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -153,6 +153,7 @@ done # If the color table file exists, if [[ -f "${coltable}" ]]; then # source it + # shellcheck source="../advanced/Scripts/COL_TABLE" source "${coltable}" # Otherwise, else @@ -1871,7 +1872,6 @@ clone_or_reset_repos() { # Download FTL binary to random temp directory and install FTL binary # Disable directive for SC2120 a value _can_ be passed to this function, but it is passed from an external script that sources this one -# shellcheck disable=SC2120 FTLinstall() { # Local, named variables local str="Downloading and Installing FTL" @@ -2400,7 +2400,7 @@ main() { # /opt/pihole/utils.sh should be installed by installScripts now, so we can use it if [ -f "${PI_HOLE_INSTALL_DIR}/utils.sh" ]; then - # shellcheck disable=SC1091 + # shellcheck source="../advanced/Scripts/utils.sh" source "${PI_HOLE_INSTALL_DIR}/utils.sh" else printf " %b Failure: /opt/pihole/utils.sh does not exist .\\n" "${CROSS}" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 9020d275..9b118627 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -8,7 +8,9 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. +# shellcheck source="../advanced/Scripts/COL_TABLE" source "/opt/pihole/COL_TABLE" +# shellcheck source="../advanced/Scripts/utils.sh" source "/opt/pihole/utils.sh" ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") @@ -42,6 +44,7 @@ fi readonly PI_HOLE_FILES_DIR="/etc/.pihole" # shellcheck disable=SC2034 SKIP_INSTALL="true" +# shellcheck source="./basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # package_manager_detect() sourced from basic-install.sh diff --git a/gravity.sh b/gravity.sh index 102ec15f..d7dfadf6 100755 --- a/gravity.sh +++ b/gravity.sh @@ -15,11 +15,13 @@ export LC_ALL=C PI_HOLE_SCRIPT_DIR="/opt/pihole" # Source utils.sh for GetFTLConfigValue utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source=./advanced/Scripts/utils.sh . "${utilsfile}" coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" +# shellcheck source=./advanced/Scripts/COL_TABLE . "${coltable}" -# shellcheck disable=SC1091 +# shellcheck source=./advanced/Scripts/database_migration/gravity-db.sh . "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" basename="pihole" @@ -767,8 +769,7 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - # shellcheck disable=SC2086 - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${modifiedOptions} -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${cmd_ext}" "${modifiedOptions}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) fi case $url in diff --git a/pihole b/pihole index c780308d..7b645030 100755 --- a/pihole +++ b/pihole @@ -17,13 +17,16 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_BIN_DIR="/usr/local/bin" readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" +# shellcheck source=./advanced/Scripts/COL_TABLE.sh source "${colfile}" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source=./advanced/Scripts/utils.sh source "${utilsfile}" # Source api functions readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" +# shellcheck source=./advanced/Scripts/api.sh source "${apifile}" versionsfile="/etc/pihole/versions" @@ -31,6 +34,7 @@ if [ -f "${versionsfile}" ]; then # Only source versionsfile if the file exits # fixes a warning during installation where versionsfile does not exist yet # but gravity calls `pihole -status` and thereby sourcing the file + # shellcheck source=/dev/null source "${versionsfile}" fi From 3732ea736542e6651d7f6fd9adcadf78640b29f2 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 7 Apr 2025 10:24:53 +0100 Subject: [PATCH 060/259] Remove shellcheck directives that no longer serve any purpose Signed-off-by: Adam Warner --- advanced/Scripts/piholeCheckout.sh | 4 ---- advanced/Scripts/piholeDebug.sh | 1 - advanced/Scripts/update.sh | 1 - automated install/basic-install.sh | 1 - automated install/uninstall.sh | 1 - 5 files changed, 8 deletions(-) diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index bde8a355..21e9df9f 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -9,7 +9,6 @@ # Please see LICENSE file for your rights under this license. readonly PI_HOLE_FILES_DIR="/etc/.pihole" -# shellcheck disable=SC2034 SKIP_INSTALL="true" # shellcheck source="../../automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" @@ -61,7 +60,6 @@ checkout() { exit 1; fi - # shellcheck disable=SC2154 if ! is_repo "${webInterfaceDir}" ; then echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!" echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" @@ -106,7 +104,6 @@ checkout() { echo "master" > /etc/pihole/ftlbranch chmod 644 /etc/pihole/ftlbranch elif [[ "${1}" == "core" ]] ; then - # shellcheck disable=SC2154 str="Fetching branches from ${piholeGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${PI_HOLE_FILES_DIR}" ; then @@ -134,7 +131,6 @@ checkout() { fi checkout_pull_branch "${PI_HOLE_FILES_DIR}" "${2}" elif [[ "${1}" == "web" ]] ; then - # shellcheck disable=SC2154 str="Fetching branches from ${webInterfaceGitUrl}" echo -ne " ${INFO} $str" if ! fully_fetch_repo "${webInterfaceDir}" ; then diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 1b196a80..caff6c5e 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -935,7 +935,6 @@ parse_file() { # Get the lines that are in the file(s) and store them in an array for parsing later local file_info if [[ -f "$filename" ]]; then - #shellcheck disable=SC2016 IFS=$'\r\n' command eval 'file_info=( $(cat "${filename}") )' else read -r -a file_info <<< "$filename" diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 7e13054e..bcd1889a 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -15,7 +15,6 @@ readonly ADMIN_INTERFACE_GIT_URL="https://github.com/pi-hole/web.git" readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git" readonly PI_HOLE_FILES_DIR="/etc/.pihole" -# shellcheck disable=SC2034 SKIP_INSTALL=true # when --check-only is passed to this script, it will not perform the actual update diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 2d9041a2..983d75d7 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -769,7 +769,6 @@ chooseInterface() { # All further interfaces are deselected status="OFF" done - # shellcheck disable=SC2086 # Disable check for double quote here as we are passing a string with spaces PIHOLE_INTERFACE=$(dialog --no-shadow --keep-tite --output-fd 1 \ --cancel-label "Exit" --ok-label "Select" \ diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 9b118627..1d365a37 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -42,7 +42,6 @@ else fi readonly PI_HOLE_FILES_DIR="/etc/.pihole" -# shellcheck disable=SC2034 SKIP_INSTALL="true" # shellcheck source="./basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" From 23fc53c618d0b4243644be3f950d0b27829dae40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 11:32:14 +0200 Subject: [PATCH 061/259] Set -x option for shellcheck GHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0fadb6f4..51e48076 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,6 +34,8 @@ jobs: check_together: 'yes' format: tty severity: warning + env: + SHELLCHECK_OPTS: -x # Enable shellcheck -x option (follow external sources) - name: Spell-Checking uses: codespell-project/actions-codespell@master From 135b0cce14db6dd53d35c2cebff2b5118164d00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 11:47:40 +0200 Subject: [PATCH 062/259] Switch to Differential ShellCheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 51e48076..2d8f047c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,9 +16,13 @@ jobs: smoke-tests: if: github.event.pull_request.draft == false runs-on: ubuntu-latest + permissions: + security-events: write # required by Differential ShellCheck steps: - name: Checkout repository uses: actions/checkout@v4.2.2 + with: + fetch-depth: 0 # Differential ShellCheck requires full git history - name: Check scripts in repository are executable run: | @@ -28,14 +32,17 @@ jobs: # If FAIL is 1 then we fail. [[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!" - - name: Run shellcheck - uses: ludeeus/action-shellcheck@master + - name: Differential ShellCheck + uses: redhat-plumbers-in-action/differential-shellcheck@v5 with: - check_together: 'yes' - format: tty - severity: warning - env: - SHELLCHECK_OPTS: -x # Enable shellcheck -x option (follow external sources) + token: ${{ secrets.GITHUB_TOKEN }} + + - if: ${{ runner.debug == '1' && !cancelled() }} + name: Upload artifact with ShellCheck defects in SARIF format + uses: actions/upload-artifact@v4 + with: + name: Differential ShellCheck SARIF + path: ${{ steps.ShellCheck.outputs.sarif }} - name: Spell-Checking uses: codespell-project/actions-codespell@master From 5002ce8ba76b0e5b9dc04412c63e14b3e429113e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 14:01:47 +0200 Subject: [PATCH 063/259] Source files relative to the repos root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/list.sh | 6 +++--- advanced/Scripts/piholeARPTable.sh | 4 ++-- advanced/Scripts/piholeCheckout.sh | 2 +- advanced/Scripts/piholeDebug.sh | 2 +- advanced/Scripts/piholeLogFlush.sh | 4 ++-- advanced/Scripts/query.sh | 3 ++- advanced/Scripts/update.sh | 6 +++--- advanced/Scripts/updatecheck.sh | 2 +- advanced/Templates/pihole-FTL-poststop.sh | 2 +- advanced/Templates/pihole-FTL-prestart.sh | 2 +- automated install/basic-install.sh | 4 ++-- automated install/uninstall.sh | 6 +++--- pihole | 3 ++- 13 files changed, 24 insertions(+), 22 deletions(-) diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index c07b0f2d..fa356f16 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -11,11 +11,11 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source="./utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" -# shellcheck source="./api.sh" +# shellcheck source="./advanced/Scripts/api.sh" source "${apifile}" # Determine database location @@ -40,7 +40,7 @@ typeId="" comment="" colfile="/opt/pihole/COL_TABLE" -# shellcheck source="./COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" source ${colfile} helpFunc() { diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh index 8257eb3e..c62acdbc 100755 --- a/advanced/Scripts/piholeARPTable.sh +++ b/advanced/Scripts/piholeARPTable.sh @@ -11,13 +11,13 @@ coltable="/opt/pihole/COL_TABLE" if [[ -f ${coltable} ]]; then -# shellcheck source="./COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" source ${coltable} fi readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source="./utils.sh" +# shellcheck source=./advanced/Scripts/utils.sh source "${utilsfile}" # Determine database location diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index 21e9df9f..beaac5f1 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -10,7 +10,7 @@ readonly PI_HOLE_FILES_DIR="/etc/.pihole" SKIP_INSTALL="true" -# shellcheck source="../../automated install/basic-install.sh" +# shellcheck source="./automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # webInterfaceGitUrl set in basic-install.sh diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index caff6c5e..70c0ffe2 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -26,7 +26,7 @@ PIHOLE_COLTABLE_FILE="${PIHOLE_SCRIPTS_DIRECTORY}/COL_TABLE" # These provide the colors we need for making the log more readable if [[ -f ${PIHOLE_COLTABLE_FILE} ]]; then -# shellcheck source=./COL_TABLE +# shellcheck source=./advanced/Scripts/COL_TABLE source ${PIHOLE_COLTABLE_FILE} else COL_NC='\e[0m' # No Color diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ab88fb73..84610fda 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -9,12 +9,12 @@ # Please see LICENSE file for your rights under this license. colfile="/opt/pihole/COL_TABLE" -# shellcheck source="./COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" source ${colfile} readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source="./utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" # In case we're running at the same time as a system logrotate, use a diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index aeebba3a..18c018dc 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -17,10 +17,11 @@ domain="" # Source color table colfile="/opt/pihole/COL_TABLE" -# shellcheck source="./COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" . "${colfile}" # Source api functions +# shellcheck source="./advanced/Scripts/api.sh" . "${PI_HOLE_INSTALL_DIR}/api.sh" Help() { diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index bcd1889a..08a50be1 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -20,11 +20,11 @@ SKIP_INSTALL=true # when --check-only is passed to this script, it will not perform the actual update CHECK_ONLY=false -# shellcheck source="../../automated install/basic-install.sh" +# shellcheck source="./automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" -# shellcheck source=./COL_TABLE +# shellcheck source=./advanced/Scripts/COL_TABLE source "/opt/pihole/COL_TABLE" -# shellcheck source="./utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" source "${PI_HOLE_INSTALL_DIR}/utils.sh" # is_repo() sourced from basic-install.sh diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 62bcbcf3..44f21419 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -39,7 +39,7 @@ function get_remote_hash() { } # Source the utils file for addOrEditKeyValPair() -# shellcheck source="./utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" . /opt/pihole/utils.sh ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh index e7db109d..504e2382 100755 --- a/advanced/Templates/pihole-FTL-poststop.sh +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -3,7 +3,7 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source="../Scripts/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" . "${utilsfile}" # Get file paths diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 056cb21c..579309d3 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -3,7 +3,7 @@ # Source utils.sh for getFTLConfigValue() PI_HOLE_SCRIPT_DIR='/opt/pihole' utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source="../Scripts/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" . "${utilsfile}" # Get file paths diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 983d75d7..9d364ffa 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -153,7 +153,7 @@ done # If the color table file exists, if [[ -f "${coltable}" ]]; then # source it - # shellcheck source="../advanced/Scripts/COL_TABLE" + # shellcheck source="./advanced/Scripts/COL_TABLE" source "${coltable}" # Otherwise, else @@ -2399,7 +2399,7 @@ main() { # /opt/pihole/utils.sh should be installed by installScripts now, so we can use it if [ -f "${PI_HOLE_INSTALL_DIR}/utils.sh" ]; then - # shellcheck source="../advanced/Scripts/utils.sh" + # shellcheck source="./advanced/Scripts/utils.sh" source "${PI_HOLE_INSTALL_DIR}/utils.sh" else printf " %b Failure: /opt/pihole/utils.sh does not exist .\\n" "${CROSS}" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 1d365a37..a158e595 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -8,9 +8,9 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -# shellcheck source="../advanced/Scripts/COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" source "/opt/pihole/COL_TABLE" -# shellcheck source="../advanced/Scripts/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" source "/opt/pihole/utils.sh" ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") @@ -43,7 +43,7 @@ fi readonly PI_HOLE_FILES_DIR="/etc/.pihole" SKIP_INSTALL="true" -# shellcheck source="./basic-install.sh" +# shellcheck source="./automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" # package_manager_detect() sourced from basic-install.sh diff --git a/pihole b/pihole index 7b645030..2c3a433b 100755 --- a/pihole +++ b/pihole @@ -17,7 +17,7 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_BIN_DIR="/usr/local/bin" readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" -# shellcheck source=./advanced/Scripts/COL_TABLE.sh +# shellcheck source=./advanced/Scripts/COL_TABLE source "${colfile}" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" @@ -431,6 +431,7 @@ piholeCheckoutFunc() { exit 0 fi + #shellcheck source=./advanced/Scripts/piholeCheckout.sh source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh shift checkout "$@" From b271dbf606560a50c0e18dea60dfdb7f8a129853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 14:11:39 +0200 Subject: [PATCH 064/259] Set shellcheck level to warning, can be lowered later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2d8f047c..ea7f71c3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,6 +35,7 @@ jobs: - name: Differential ShellCheck uses: redhat-plumbers-in-action/differential-shellcheck@v5 with: + severity: warning token: ${{ secrets.GITHUB_TOKEN }} - if: ${{ runner.debug == '1' && !cancelled() }} From bda81cb2f5b1785beead193487cffe596d5faa3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Apr 2025 21:25:29 +0200 Subject: [PATCH 065/259] Remove debug SARIF upload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ea7f71c3..b9f38800 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,13 +38,6 @@ jobs: severity: warning token: ${{ secrets.GITHUB_TOKEN }} - - if: ${{ runner.debug == '1' && !cancelled() }} - name: Upload artifact with ShellCheck defects in SARIF format - uses: actions/upload-artifact@v4 - with: - name: Differential ShellCheck SARIF - path: ${{ steps.ShellCheck.outputs.sarif }} - - name: Spell-Checking uses: codespell-project/actions-codespell@master with: From 0f511ad5744167c4dbe821966734ad2b632fbf30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 8 Apr 2025 17:50:19 +0200 Subject: [PATCH 066/259] Remove token and use sarif-fmt for nicer CLI output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b9f38800..5d73f31b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,8 +16,6 @@ jobs: smoke-tests: if: github.event.pull_request.draft == false runs-on: ubuntu-latest - permissions: - security-events: write # required by Differential ShellCheck steps: - name: Checkout repository uses: actions/checkout@v4.2.2 @@ -36,7 +34,8 @@ jobs: uses: redhat-plumbers-in-action/differential-shellcheck@v5 with: severity: warning - token: ${{ secrets.GITHUB_TOKEN }} + display-engine: sarif-fmt + - name: Spell-Checking uses: codespell-project/actions-codespell@master From 48272f3393638a7d6ffa214adb6f4f10fbec792a Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Wed, 9 Apr 2025 18:00:28 +0100 Subject: [PATCH 067/259] revert a change to gravity.sh that attempted to fix an SC2086 warning from shellcheck. Fixes #6159 Signed-off-by: Adam Warner --- gravity.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index d7dfadf6..e75bb250 100755 --- a/gravity.sh +++ b/gravity.sh @@ -769,7 +769,9 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${cmd_ext}" "${modifiedOptions}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) + # See https://github.com/pi-hole/pi-hole/issues/6159 for justification of the below disable directive + # shellcheck disable=SC2086 + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${modifiedOptions} -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) fi case $url in From 9e62625f83e4686407898c0584bb5557e2e8578f Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Tue, 15 Apr 2025 14:13:43 +1000 Subject: [PATCH 068/259] Install on IPv6-only/DNS64/NAT64 system Alters the test for IPv4 route so the installer doesn't fail instantly on IPv6-only. Gives user a dialog to proceed with IPv6 only installation Switches DNS server options to only contain IPv6 addresses. Signed-off-by: Rob Gill --- automated install/basic-install.sh | 43 ++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e69256ff..8a18a6cd 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -49,7 +49,6 @@ Google (ECS, DNSSEC);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860: OpenDNS (ECS, DNSSEC);208.67.222.222;208.67.220.220;2620:119:35::35;2620:119:53::53 Level3;4.2.2.1;4.2.2.2;; Comodo;8.26.56.26;8.20.247.20;; -DNS.WATCH (DNSSEC);84.200.69.80;84.200.70.40;2001:1608:10:25:0:0:1c04:b12f;2001:1608:10:25:0:0:9249:d69b Quad9 (filtered, DNSSEC);9.9.9.9;149.112.112.112;2620:fe::fe;2620:fe::9 Quad9 (unfiltered, no DNSSEC);9.9.9.10;149.112.112.10;2620:fe::10;2620:fe::fe:10 Quad9 (filtered, ECS, DNSSEC);9.9.9.11;149.112.112.11;2620:fe::11;2620:fe::fe:11 @@ -57,6 +56,17 @@ Cloudflare (DNSSEC);1.1.1.1;1.0.0.1;2606:4700:4700::1111;2606:4700:4700::1001 EOM ) +DNS_SERVERS_IPV6_ONLY=$( + cat < Date: Sat, 19 Apr 2025 20:29:19 +0300 Subject: [PATCH 069/259] Allow alternative cron daemons on Debian Add cron-daemon virtual package as an alternative dependency. This way pihole-meta by default still depends on cron, but allows installation of systemd-cron, which completely replaces cron daemon and package. With systemd-cron functionality of crontab files and /etc/cron.* directories works expected, as systemd-cron generates systemd timers from cron files. Signed-off-by: Ihor Urazov --- automated install/basic-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index af03d93d..496ca07c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -115,11 +115,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion +Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron | cron-daemon,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion Section: contrib/metapackages Priority: optional EOM From 1432568d17f78f533583fca2d4fca29c72f5cdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 20 Apr 2025 20:14:41 +0200 Subject: [PATCH 070/259] Remove duplicated code checking if adlist domain is blocked locally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/gravity.sh b/gravity.sh index e75bb250..514289d0 100755 --- a/gravity.sh +++ b/gravity.sh @@ -646,32 +646,6 @@ gravity_DownloadBlocklistFromUrl() { str="Status:" echo -ne " ${INFO} ${str} Pending..." blocked=false - case $(getFTLConfigValue dns.blocking.mode) in - "IP-NODATA-AAAA" | "IP") - # Get IP address of this domain - ip="$(dig "${domain}" +short)" - # Check if this IP matches any IP of the system - if [[ -n "${ip}" && $(grep -Ec "inet(|6) ${ip}" <<<"$(ip a)") -gt 0 ]]; then - blocked=true - fi - ;; - "NXDOMAIN") - if [[ $(dig "${domain}" | grep "NXDOMAIN" -c) -ge 1 ]]; then - blocked=true - fi - ;; - "NODATA") - if [[ $(dig "${domain}" | grep "NOERROR" -c) -ge 1 ]] && [[ -z $(dig +short "${domain}") ]]; then - blocked=true - fi - ;; - "NULL" | *) - if [[ $(dig "${domain}" +short | grep "0.0.0.0" -c) -ge 1 ]]; then - blocked=true - fi - ;; - esac - # Check if this domain is blocked by Pi-hole but only if the domain is not a # local file or empty if [[ $url != "file"* ]] && [[ -n "${domain}" ]]; then From 8733b429dd908644e4d08e25309270ab0cf4f71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 20 Apr 2025 22:50:55 +0200 Subject: [PATCH 071/259] Treat FTL return data as strings - part II MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 65a4eaa5..006a8d31 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -226,7 +226,7 @@ GetFTLData() { # return only the data if [ "${status}" = 200 ]; then # response OK - echo "${data}" + printf %s "${data}" else # connection lost echo "${status}" From 4a1bcda6f1b0a7f7e56221ad3ac27b7f509e20a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 21 Apr 2025 09:28:19 +0200 Subject: [PATCH 072/259] All gravity related files and dirs should be owned by pihole:pihole MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 514289d0..37a7301b 100755 --- a/gravity.sh +++ b/gravity.sh @@ -126,7 +126,7 @@ gravity_swap_databases() { oldAvail=false if [ "${availableBlocks}" -gt "$((gravityBlocks * 2))" ] && [ -f "${gravityDBfile}" ]; then oldAvail=true - cp "${gravityDBfile}" "${gravityOLDfile}" + cp -p "${gravityDBfile}" "${gravityOLDfile}" fi # Drop the gravity and antigravity tables + subsequent VACUUM the current @@ -140,6 +140,7 @@ gravity_swap_databases() { # Check if the backup directory exists if [ ! -d "${gravityBCKdir}" ]; then mkdir -p "${gravityBCKdir}" + chown pihole:pihole "${gravityBCKdir}" fi # If multiple gravityBCKfile's are present (appended with a number), rotate them @@ -1016,6 +1017,7 @@ migrate_to_listsCache_dir() { local str="Migrating the list's cache directory to new location" echo -ne " ${INFO} ${str}..." mkdir -p "${listsCacheDir}" + chown pihole:pihole "${listsCacheDir}" # Move the old files to the new directory if mv "${piholeDir}"/list.* "${listsCacheDir}/" 2>/dev/null; then From 6fc5bf83f49a637316e4c69a5d0947443426efb5 Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Wed, 9 Apr 2025 12:25:24 -0500 Subject: [PATCH 073/259] don't mute SC2086 Signed-off-by: Michael Woolweaver --- gravity.sh | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/gravity.sh b/gravity.sh index 514289d0..8ccd9a5b 100755 --- a/gravity.sh +++ b/gravity.sh @@ -601,7 +601,7 @@ compareLists() { # Download specified URL and perform checks on HTTP status and file content gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" - local modifiedOptions="" listCurlBuffer str httpCode success="" ip cmd_ext + local modifiedOptions=() listCurlBuffer str httpCode success="" ip cmd_ext local file_path permissions ip_addr port blocked=false download=true # Create temp file to store content on disk instead of RAM @@ -619,14 +619,14 @@ gravity_DownloadBlocklistFromUrl() { # Save HTTP ETag to the specified file. An ETag is a caching related header, # usually returned in a response. If no ETag is sent by the server, an empty # file is created and can later be used consistently. - modifiedOptions="--etag-save ${saveLocation}.etag" + modifiedOptions=("${modifiedOptions[@]}" --etag-save "${saveLocation}".etag) if [[ -f "${saveLocation}.etag" ]]; then # This option makes a conditional HTTP request for the specific ETag read # from the given file by sending a custom If-None-Match header using the # stored ETag. This way, the server will only send the file if it has # changed since the last request. - modifiedOptions="${modifiedOptions} --etag-compare ${saveLocation}.etag" + modifiedOptions=("${modifiedOptions[@]}" --etag-compare "${saveLocation}".etag) fi fi @@ -639,7 +639,7 @@ gravity_DownloadBlocklistFromUrl() { # Interstingly, this option is not supported by raw.githubusercontent.com # URLs, however, it is still supported by many older web servers which may # not support the HTTP ETag method so we keep it as a fallback. - modifiedOptions="${modifiedOptions} -z ${saveLocation}" + modifiedOptions=("${modifiedOptions[@]}" -z "${saveLocation}") fi fi @@ -743,9 +743,7 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - # See https://github.com/pi-hole/pi-hole/issues/6159 for justification of the below disable directive - # shellcheck disable=SC2086 - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${modifiedOptions} -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} "${modifiedOptions[@]}" -w "%{http_code}" ${url} -o ${listCurlBuffer} 2>/dev/null) fi case $url in From 89c4248315700004e249e119ebf851e7e464ee40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 21:57:47 +0200 Subject: [PATCH 074/259] Use quotes for all substitutions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 8ccd9a5b..403b1bd7 100755 --- a/gravity.sh +++ b/gravity.sh @@ -743,7 +743,7 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} "${modifiedOptions[@]}" -w "%{http_code}" ${url} -o ${listCurlBuffer} 2>/dev/null) + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${cmd_ext}" "${modifiedOptions[@]}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) fi case $url in From 774037834b769b9d37477424f5cbc810c7e6cc25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 22:01:21 +0200 Subject: [PATCH 075/259] Rename cmd_ext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gravity.sh b/gravity.sh index 403b1bd7..384ee4ea 100755 --- a/gravity.sh +++ b/gravity.sh @@ -601,7 +601,7 @@ compareLists() { # Download specified URL and perform checks on HTTP status and file content gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" - local modifiedOptions=() listCurlBuffer str httpCode success="" ip cmd_ext + local modifiedOptions=() listCurlBuffer str httpCode success="" ip customUpstreamResolver local file_path permissions ip_addr port blocked=false download=true # Create temp file to store content on disk instead of RAM @@ -705,7 +705,7 @@ gravity_DownloadBlocklistFromUrl() { fi echo -e "${OVER} ${CROSS} ${str} ${domain} is blocked by one of your lists. Using DNS server ${upstream} instead" echo -ne " ${INFO} ${str} Pending..." - cmd_ext="--resolve $domain:$port:$ip" + customUpstreamResolver="--resolve $domain:$port:$ip" fi fi @@ -743,7 +743,7 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${cmd_ext}" "${modifiedOptions[@]}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${customUpstreamResolver}" "${modifiedOptions[@]}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) fi case $url in From 76e41aeefaacf54a7fc23a0581d5ab8293e77a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 22:03:54 +0200 Subject: [PATCH 076/259] Add small note about modifiedOptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 384ee4ea..d91d3166 100755 --- a/gravity.sh +++ b/gravity.sh @@ -601,8 +601,10 @@ compareLists() { # Download specified URL and perform checks on HTTP status and file content gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" - local modifiedOptions=() listCurlBuffer str httpCode success="" ip customUpstreamResolver + local listCurlBuffer str httpCode success="" ip customUpstreamResolver local file_path permissions ip_addr port blocked=false download=true + # modifiedOptions is an array to store all the options used to check if the adlist has been changed upstream + local modifiedOptions=() # Create temp file to store content on disk instead of RAM # We don't use '--suffix' here because not all implementations of mktemp support it, e.g. on Alpine From 13d76abff7212965da856bfcf042675a9a0ee5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 22:38:07 +0200 Subject: [PATCH 077/259] Set customUpstreamResolver empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index d91d3166..4ce532fc 100755 --- a/gravity.sh +++ b/gravity.sh @@ -601,7 +601,7 @@ compareLists() { # Download specified URL and perform checks on HTTP status and file content gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" - local listCurlBuffer str httpCode success="" ip customUpstreamResolver + local listCurlBuffer str httpCode success="" ip customUpstreamResolver="" local file_path permissions ip_addr port blocked=false download=true # modifiedOptions is an array to store all the options used to check if the adlist has been changed upstream local modifiedOptions=() From ce0bdac1bd2eb1809722abe62c205f95a049fd81 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Wed, 23 Apr 2025 06:41:16 +1000 Subject: [PATCH 078/259] Remove reference to telnet and chronometer in README Replace with curl example and commandline example Signed-off-by: Rob Gill --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f320f8c5..622ff202 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,10 @@ Some of the statistics you can integrate include: - Queries cached - Unique clients -Access the API via [`telnet`](https://github.com/pi-hole/FTL), the Web (`admin/api.php`) and Command Line (`pihole -c -j`). You can find out [more details over here](https://discourse.pi-hole.net/t/pi-hole-api/1863). +Access the API using: +- your browser: http://pi.hole/api/docs +- `curl`: `curl --connect-timeout 2 -ks "https://pi.hole/api/stats/summary" -H "Accept: application/json"`; +- the command line - examples: `pihole api config/webserver/port` or `pihole api stats/summary`. ### The Command-Line Interface From 7a641f4c35b29f82e7d706b14e9260734fd8d842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 22:52:33 +0200 Subject: [PATCH 079/259] Use paramteter expansion to prevent adding literal '' if parameter is empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 4ce532fc..19458c16 100755 --- a/gravity.sh +++ b/gravity.sh @@ -745,7 +745,7 @@ gravity_DownloadBlocklistFromUrl() { fi if [[ "${download}" == true ]]; then - httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L "${compression}" "${customUpstreamResolver}" "${modifiedOptions[@]}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) + httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression:+${compression}} ${customUpstreamResolver:+${customUpstreamResolver}} "${modifiedOptions[@]}" -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) fi case $url in From d7b6d6aa339d70b9a2aaeef1245404dcfd370a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 22 Apr 2025 23:06:01 +0200 Subject: [PATCH 080/259] Remove unused $target from gravity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gravity.sh b/gravity.sh index 514289d0..03759963 100755 --- a/gravity.sh +++ b/gravity.sh @@ -417,7 +417,7 @@ gravity_DownloadBlocklists() { echo -e " ${INFO} Storing gravity database in ${COL_BOLD}${gravityDBfile}${COL_NC}" fi - local url domain str target compression adlist_type directory success + local url domain str compression adlist_type directory success echo "" # Prepare new gravity database @@ -566,7 +566,7 @@ gravity_DownloadBlocklists() { if [[ "${check_url}" =~ ${regex} ]]; then echo -e " ${CROSS} Invalid Target" else - timeit gravity_DownloadBlocklistFromUrl "${url}" "${sourceIDs[$i]}" "${saveLocation}" "${target}" "${compression}" "${adlist_type}" "${domain}" + timeit gravity_DownloadBlocklistFromUrl "${url}" "${sourceIDs[$i]}" "${saveLocation}" "${compression}" "${adlist_type}" "${domain}" fi echo "" done @@ -600,7 +600,7 @@ compareLists() { # Download specified URL and perform checks on HTTP status and file content gravity_DownloadBlocklistFromUrl() { - local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" + local url="${1}" adlistID="${2}" saveLocation="${3}" compression="${4}" gravity_type="${5}" domain="${6}" local modifiedOptions="" listCurlBuffer str httpCode success="" ip cmd_ext local file_path permissions ip_addr port blocked=false download=true From 72a52807d1ab42ced45bdf893376cdadee9611c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 25 Apr 2025 21:03:09 +0200 Subject: [PATCH 081/259] Fix gravity waiting forever for DNS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/gravity.sh b/gravity.sh index 514289d0..06396d11 100755 --- a/gravity.sh +++ b/gravity.sh @@ -348,17 +348,24 @@ gravity_CheckDNSResolutionAvailable() { echo -e " ${CROSS} DNS resolution is currently unavailable" fi - str="Waiting until DNS resolution is available..." + str="Waiting 120 seconds if DNS resolution becomes available..." echo -ne " ${INFO} ${str}" - until getent hosts github.com &> /dev/null; do - # Append one dot for each second waiting - str="${str}." - echo -ne " ${OVER} ${INFO} ${str}" - sleep 1 + + for ((i = 0; i < 120; i++)); do + if getent hosts github.com &> /dev/null; then + # If we reach this point, DNS resolution is available + echo -e "${OVER} ${TICK} DNS resolution is available" + break + fi + # Append one dot for each second waiting + str="${str}." + echo -ne " ${OVER} ${INFO} ${str}" + sleep 1 done - # If we reach this point, DNS resolution is available - echo -e "${OVER} ${TICK} DNS resolution is available" + # DNS resolution is still unavailable after 120 seconds + return 1 + } # Function: try_restore_backup @@ -1081,6 +1088,12 @@ for var in "$@"; do esac done +# Check if DNS is available, no need to do any database manipulation if we're not able to download adlists +if ! timeit gravity_CheckDNSResolutionAvailable; then + echo -e " ${CROSS} No DNS resolution available. Please contact support." + exit 1 +fi + # Remove OLD (backup) gravity file, if it exists if [[ -f "${gravityOLDfile}" ]]; then rm "${gravityOLDfile}" @@ -1121,11 +1134,6 @@ if [[ "${forceDelete:-}" == true ]]; then fi # Gravity downloads blocklists next -if ! timeit gravity_CheckDNSResolutionAvailable; then - echo -e " ${CROSS} Can not complete gravity update, no DNS is available. Please contact support." - exit 1 -fi - if ! gravity_DownloadBlocklists; then echo -e " ${CROSS} Unable to create gravity database. Please try again later. If the problem persists, please contact support." exit 1 From 1bea6db50adb3a07ba58808791c7c013bc12a671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 24 Apr 2025 09:00:07 +0200 Subject: [PATCH 082/259] Fix API logic in api.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 006a8d31..7e9d4653 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -20,7 +20,7 @@ TestAPIAvailability() { # as we are running locally, we can get the port value from FTL directly - local chaos_api_list authResponse authStatus authData + local chaos_api_list authResponse authStatus authData apiAvailable # Query the API URLs from FTL using CHAOS TXT local.api.ftl # The result is a space-separated enumeration of full URLs @@ -59,7 +59,7 @@ TestAPIAvailability() { # Test if http status code was 200 (OK) or 401 (authentication required) if [ ! "${authStatus}" = 200 ] && [ ! "${authStatus}" = 401 ]; then # API is not available at this port/protocol combination - API_PORT="" + apiAvailable=false else # API is available at this URL combination @@ -71,6 +71,8 @@ TestAPIAvailability() { # Check if 2FA is required needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null) + apiAvailable=true + break fi @@ -86,9 +88,9 @@ TestAPIAvailability() { fi done - # if API_PORT is empty, no working API port was found - if [ -n "${API_PORT}" ]; then - echo "API not available at: ${API_URL}" + # if apiAvailable is false, no working API was found + if [ "${apiAvailable}" = false ]; then + echo "API not available. Please check FTL.log" echo "Exiting." exit 1 fi From 454f96d0ea2c165ce1587363bb4757cd34bbd01e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Apr 2025 10:25:43 +0000 Subject: [PATCH 083/259] Bump actions/setup-python from 5.5.0 to 5.6.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.5.0 to 5.6.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5.5.0...v5.6.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: 5.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5d73f31b..26435035 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,7 +80,7 @@ jobs: uses: actions/checkout@v4.2.2 - name: Set up Python 3.10 - uses: actions/setup-python@v5.5.0 + uses: actions/setup-python@v5.6.0 with: python-version: "3.10" From 215003899d78dd5aac0b3ac3f5e442fb7f0cd457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 26 Apr 2025 15:03:01 +0200 Subject: [PATCH 084/259] (2+1)*40 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 06396d11..8d881105 100755 --- a/gravity.sh +++ b/gravity.sh @@ -351,7 +351,8 @@ gravity_CheckDNSResolutionAvailable() { str="Waiting 120 seconds if DNS resolution becomes available..." echo -ne " ${INFO} ${str}" - for ((i = 0; i < 120; i++)); do + # Default DNS timeout is two seconds, plus 1 second for each dot > 120 seconds + for ((i = 0; i < 40; i++)); do if getent hosts github.com &> /dev/null; then # If we reach this point, DNS resolution is available echo -e "${OVER} ${TICK} DNS resolution is available" From 4303a5868ffc47f9d8dd1c1298f7aff24e4ebc85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 26 Apr 2025 15:03:42 +0200 Subject: [PATCH 085/259] Only append dot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gravity.sh b/gravity.sh index 8d881105..887f9750 100755 --- a/gravity.sh +++ b/gravity.sh @@ -359,8 +359,7 @@ gravity_CheckDNSResolutionAvailable() { break fi # Append one dot for each second waiting - str="${str}." - echo -ne " ${OVER} ${INFO} ${str}" + echo -ne "." sleep 1 done From 3bd6a41795430f63c2c08262960c6d6f50fe73e9 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Sat, 26 Apr 2025 15:36:22 +0200 Subject: [PATCH 086/259] Improve wording Co-authored-by: Adam Warner Signed-off-by: yubiuser --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 887f9750..5276d180 100755 --- a/gravity.sh +++ b/gravity.sh @@ -348,7 +348,7 @@ gravity_CheckDNSResolutionAvailable() { echo -e " ${CROSS} DNS resolution is currently unavailable" fi - str="Waiting 120 seconds if DNS resolution becomes available..." + str="Waiting up to 120 seconds for DNS resolution..." echo -ne " ${INFO} ${str}" # Default DNS timeout is two seconds, plus 1 second for each dot > 120 seconds From 40da3a40ec649cc8d0c0edb614755eb1a60c2a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 28 Apr 2025 21:03:08 +0200 Subject: [PATCH 087/259] Remove os_check from install script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 172 ----------------------------- 1 file changed, 172 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index af03d93d..fda294b4 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -227,176 +227,6 @@ is_command() { command -v "${check_command}" >/dev/null 2>&1 } -os_check_dig(){ - local protocol="$1" - local domain="$2" - local nameserver="$3" - local response - - response="$(dig -"${protocol}" +short -t txt "${domain}" "${nameserver}" 2>&1 - echo $? - )" - echo "${response}" -} - -os_check_dig_response(){ - # Checks the reply from the dig command to determine if it's a valid response - local digReply="$1" - local response - - # Dig returned 0 (success), so get the actual response, and loop through it to determine if the detected variables above are valid - response="${digReply%%$'\n'*}" - # If the value of ${response} is a single 0, then this is the return code, not an actual response. - if [ "${response}" == 0 ]; then - echo false - else - echo true - fi -} - -os_check() { - if [ "$PIHOLE_SKIP_OS_CHECK" != true ]; then - # This function gets a list of supported OS versions from a TXT record at versions.pi-hole.net - # and determines whether or not the script is running on one of those systems - local remote_os_domain valid_os valid_version valid_response detected_os detected_version display_warning cmdResult digReturnCode response - local piholeNameserver="@ns1.pi-hole.net" - remote_os_domain=${OS_CHECK_DOMAIN_NAME:-"versions.pi-hole.net"} - - detected_os=$(grep '^ID=' /etc/os-release | cut -d '=' -f2 | tr -d '"') - detected_version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f2 | tr -d '"') - - # Test via IPv4 and hardcoded nameserver ns1.pi-hole.net - cmdResult=$(os_check_dig 4 "${remote_os_domain}" "${piholeNameserver}") - - # Gets the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - if [ ! "${digReturnCode}" == "0" ]; then - valid_response=false - else - valid_response=$(os_check_dig_response cmdResult) - fi - - # Try again via IPv6 and hardcoded nameserver ns1.pi-hole.net - if [ "$valid_response" = false ]; then - unset valid_response - unset cmdResult - unset digReturnCode - - cmdResult=$(os_check_dig 6 "${remote_os_domain}" "${piholeNameserver}") - # Gets the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - if [ ! "${digReturnCode}" == "0" ]; then - valid_response=false - else - valid_response=$(os_check_dig_response cmdResult) - fi - fi - - # Try again without hardcoded nameserver - if [ "$valid_response" = false ]; then - unset valid_response - unset cmdResult - unset digReturnCode - - cmdResult=$(os_check_dig 4 "${remote_os_domain}") - # Gets the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - if [ ! "${digReturnCode}" == "0" ]; then - valid_response=false - else - valid_response=$(os_check_dig_response cmdResult) - fi - fi - - if [ "$valid_response" = false ]; then - unset valid_response - unset cmdResult - unset digReturnCode - - cmdResult=$(os_check_dig 6 "${remote_os_domain}") - # Gets the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - if [ ! "${digReturnCode}" == "0" ]; then - valid_response=false - else - valid_response=$(os_check_dig_response cmdResult) - fi - fi - - if [ "$valid_response" = true ]; then - response="${cmdResult%%$'\n'*}" - IFS=" " read -r -a supportedOS < <(echo "${response}" | tr -d '"') - for distro_and_versions in "${supportedOS[@]}"; do - distro_part="${distro_and_versions%%=*}" - versions_part="${distro_and_versions##*=}" - - # If the distro part is a (case-insensitive) substring of the computer OS - if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then - valid_os=true - IFS="," read -r -a supportedVer <<<"${versions_part}" - for version in "${supportedVer[@]}"; do - if [[ "${detected_version}" =~ $version ]]; then - valid_version=true - break - fi - done - break - fi - done - fi - - if [ "$valid_os" = true ] && [ "$valid_version" = true ] && [ "$valid_response" = true ]; then - display_warning=false - fi - - if [ "$display_warning" != false ]; then - if [ "$valid_response" = false ]; then - - if [ "${digReturnCode}" -eq 0 ]; then - errStr="dig succeeded, but response was blank. Please contact support" - else - errStr="dig failed with return code ${digReturnCode}" - fi - printf " %b %bRetrieval of supported OS list failed. %s. %b\\n" "${CROSS}" "${COL_LIGHT_RED}" "${errStr}" "${COL_NC}" - printf " %bUnable to determine if the detected OS (%s %s) is supported%b\\n" "${COL_LIGHT_RED}" "${detected_os^}" "${detected_version}" "${COL_NC}" - printf " Possible causes for this include:\\n" - printf " - Firewall blocking DNS lookups from Pi-hole device to ns1.pi-hole.net\\n" - printf " - DNS resolution issues of the host system\\n" - printf " - Other internet connectivity issues\\n" - else - printf " %b %bUnsupported OS detected: %s %s%b\\n" "${CROSS}" "${COL_LIGHT_RED}" "${detected_os^}" "${detected_version}" "${COL_NC}" - printf " If you are seeing this message and you do have a supported OS, please contact support.\\n" - fi - printf "\\n" - printf " %bhttps://docs.pi-hole.net/main/prerequisites/#supported-operating-systems%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" - printf "\\n" - printf " If you wish to attempt to continue anyway, you can try one of the following commands to skip this check:\\n" - printf "\\n" - printf " e.g: If you are seeing this message on a fresh install, you can run:\\n" - printf " %bcurl -sSL https://install.pi-hole.net | sudo PIHOLE_SKIP_OS_CHECK=true bash%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" - printf "\\n" - printf " If you are seeing this message after having run pihole -up:\\n" - printf " %bsudo PIHOLE_SKIP_OS_CHECK=true pihole -r%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" - printf " (In this case, your previous run of pihole -up will have already updated the local repository)\\n" - printf "\\n" - printf " It is possible that the installation will still fail at this stage due to an unsupported configuration.\\n" - printf " If that is the case, you can feel free to ask the community on Discourse with the %bCommunity Help%b category:\\n" "${COL_LIGHT_RED}" "${COL_NC}" - printf " %bhttps://discourse.pi-hole.net/c/bugs-problems-issues/community-help/%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" - printf "\\n" - exit 1 - - else - printf " %b %bSupported OS detected%b\\n" "${TICK}" "${COL_LIGHT_GREEN}" "${COL_NC}" - fi - else - printf " %b %bPIHOLE_SKIP_OS_CHECK env variable set to true - installer will continue%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" - fi -} - # Compatibility package_manager_detect() { @@ -2369,8 +2199,6 @@ main() { # Install Pi-hole dependencies install_dependent_packages - # Check that the installed OS is officially supported - display warning if not - os_check # Check if there is a usable FTL binary available on this architecture - do # this early on as FTL is a hard dependency for Pi-hole From d9f4ee7aaa4094536fee7b29b497814638395f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 28 Apr 2025 21:04:08 +0200 Subject: [PATCH 088/259] Remove os_check from update script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 08a50be1..51c1b1a1 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -112,8 +112,6 @@ main() { web_update=false FTL_update=false - # Perform an OS check to ensure we're on an appropriate operating system - os_check # Install packages used by this installation script (necessary if users have removed e.g. git from their systems) package_manager_detect From 54c8dd3d77b8460adea76e72999509eca3ac2374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 28 Apr 2025 21:06:05 +0200 Subject: [PATCH 089/259] Remove os_check from tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/_centos_10.Dockerfile | 1 - test/_centos_9.Dockerfile | 1 - test/_debian_11.Dockerfile | 1 - test/_debian_12.Dockerfile | 1 - test/_fedora_40.Dockerfile | 1 - test/_fedora_41.Dockerfile | 1 - test/_ubuntu_20.Dockerfile | 1 - test/_ubuntu_22.Dockerfile | 1 - test/_ubuntu_24.Dockerfile | 1 - test/test_any_automated_install.py | 44 ------------------------------ 10 files changed, 53 deletions(-) diff --git a/test/_centos_10.Dockerfile b/test/_centos_10.Dockerfile index ca439e1b..78a89789 100644 --- a/test/_centos_10.Dockerfile +++ b/test/_centos_10.Dockerfile @@ -15,6 +15,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_centos_9.Dockerfile b/test/_centos_9.Dockerfile index a5e7cf0b..73f53fa5 100644 --- a/test/_centos_9.Dockerfile +++ b/test/_centos_9.Dockerfile @@ -15,6 +15,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_debian_11.Dockerfile b/test/_debian_11.Dockerfile index b8107244..2389063c 100644 --- a/test/_debian_11.Dockerfile +++ b/test/_debian_11.Dockerfile @@ -12,6 +12,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_debian_12.Dockerfile b/test/_debian_12.Dockerfile index 7446711a..a6c5f1ed 100644 --- a/test/_debian_12.Dockerfile +++ b/test/_debian_12.Dockerfile @@ -12,6 +12,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_fedora_40.Dockerfile b/test/_fedora_40.Dockerfile index 20102a10..43913895 100644 --- a/test/_fedora_40.Dockerfile +++ b/test/_fedora_40.Dockerfile @@ -13,6 +13,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_fedora_41.Dockerfile b/test/_fedora_41.Dockerfile index bf5fe5d5..c03371a5 100644 --- a/test/_fedora_41.Dockerfile +++ b/test/_fedora_41.Dockerfile @@ -13,6 +13,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_ubuntu_20.Dockerfile b/test/_ubuntu_20.Dockerfile index 75c12673..5b8deb5d 100644 --- a/test/_ubuntu_20.Dockerfile +++ b/test/_ubuntu_20.Dockerfile @@ -12,6 +12,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_ubuntu_22.Dockerfile b/test/_ubuntu_22.Dockerfile index 9206a46a..c3be89e1 100644 --- a/test/_ubuntu_22.Dockerfile +++ b/test/_ubuntu_22.Dockerfile @@ -13,6 +13,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_ubuntu_24.Dockerfile b/test/_ubuntu_24.Dockerfile index 4cab43de..cf57c2aa 100644 --- a/test/_ubuntu_24.Dockerfile +++ b/test/_ubuntu_24.Dockerfile @@ -13,6 +13,5 @@ RUN true && \ chmod +x $SCRIPTDIR/* ENV SKIP_INSTALL=true -ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 5fa0f065..e72b4779 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -465,50 +465,6 @@ def test_validate_ip(host): test_address("0.0.0.0#00001", False) -def test_os_check_fails(host): - """Confirms install fails on unsupported OS""" - host.run( - """ - source /opt/pihole/basic-install.sh - package_manager_detect - build_dependency_package - install_dependent_packages - cat < /etc/os-release -ID=UnsupportedOS -VERSION_ID="2" -EOT - """ - ) - detectOS = host.run( - """t - source /opt/pihole/basic-install.sh - os_check - """ - ) - expected_stdout = "Unsupported OS detected: UnsupportedOS" - assert expected_stdout in detectOS.stdout - - -def test_os_check_passes(host): - """Confirms OS meets the requirements""" - host.run( - """ - source /opt/pihole/basic-install.sh - package_manager_detect - build_dependency_package - install_dependent_packages - """ - ) - detectOS = host.run( - """ - source /opt/pihole/basic-install.sh - os_check - """ - ) - expected_stdout = "Supported OS detected" - assert expected_stdout in detectOS.stdout - - def test_package_manager_has_pihole_deps(host): """Confirms OS is able to install the required packages for Pi-hole""" mock_command("dialog", {"*": ("", "0")}, host) From 5355e9e08491e6167ecdb40b172780527b340a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 28 Apr 2025 21:10:36 +0200 Subject: [PATCH 090/259] Remove os_check from debug script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeDebug.sh | 94 ++++----------------------------- 1 file changed, 10 insertions(+), 84 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 70c0ffe2..741ff2f4 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -296,91 +296,12 @@ check_component_versions() { check_ftl_version } -os_check() { - # This function gets a list of supported OS versions from a TXT record at versions.pi-hole.net - # and determines whether or not the script is running on one of those systems - local remote_os_domain valid_os valid_version detected_os detected_version cmdResult digReturnCode response - remote_os_domain=${OS_CHECK_DOMAIN_NAME:-"versions.pi-hole.net"} - - detected_os=$(grep "\bID\b" /etc/os-release | cut -d '=' -f2 | tr -d '"') - detected_version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f2 | tr -d '"') - - cmdResult="$(dig -4 +short -t txt "${remote_os_domain}" @ns1.pi-hole.net 2>&1; echo $?)" - #Get the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - # Extract dig response - response="${cmdResult%%$'\n'*}" - - if [ "${digReturnCode}" -ne 0 ]; then - log_write "${INFO} Distro: ${detected_os^}" - log_write "${INFO} Version: ${detected_version}" - log_write "${CROSS} dig IPv4 return code: ${COL_RED}${digReturnCode}${COL_NC}" - log_write "${CROSS} dig response: ${response}" - log_write "${INFO} Retrying via IPv6" - - cmdResult="$(dig -6 +short -t txt "${remote_os_domain}" @ns1.pi-hole.net 2>&1; echo $?)" - #Get the return code of the previous command (last line) - digReturnCode="${cmdResult##*$'\n'}" - - # Extract dig response - response="${cmdResult%%$'\n'*}" - fi - # If also no success via IPv6 - if [ "${digReturnCode}" -ne 0 ]; then - log_write "${CROSS} dig IPv6 return code: ${COL_RED}${digReturnCode}${COL_NC}" - log_write "${CROSS} dig response: ${response}" - log_write "${CROSS} Error: ${COL_RED}dig command failed - Unable to check OS${COL_NC}" - else - IFS=" " read -r -a supportedOS < <(echo "${response}" | tr -d '"') - for distro_and_versions in "${supportedOS[@]}" - do - distro_part="${distro_and_versions%%=*}" - versions_part="${distro_and_versions##*=}" - - if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then - valid_os=true - IFS="," read -r -a supportedVer <<<"${versions_part}" - for version in "${supportedVer[@]}" - do - if [[ "${detected_version}" =~ $version ]]; then - valid_version=true - break - fi - done - break - fi - done - - # If it is a docker container, we can assume the OS is supported - [ -n "${DOCKER_VERSION}" ] && valid_os=true && valid_version=true - - local finalmsg - if [ "$valid_os" = true ]; then - log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}" - - if [ "$valid_version" = true ]; then - log_write "${TICK} Version: ${COL_GREEN}${detected_version}${COL_NC}" - finalmsg="${TICK} ${COL_GREEN}Distro and version supported${COL_NC}" - else - log_write "${CROSS} Version: ${COL_RED}${detected_version}${COL_NC}" - finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is supported but version ${detected_version} is currently unsupported ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}" - fi - else - log_write "${CROSS} Distro: ${COL_RED}${detected_os^}${COL_NC}" - finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is not a supported distro ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}" - fi - - # Print dig response and the final check result - log_write "${TICK} dig return code: ${COL_GREEN}${digReturnCode}${COL_NC}" - log_write "${INFO} dig response: ${response}" - log_write "${finalmsg}" - fi -} - diagnose_operating_system() { # error message in a variable so we can easily modify it later (or reuse it) local error_msg="Distribution unknown -- most likely you are on an unsupported platform and may run into issues." + local detected_os + local detected_version + # Display the current test that is running echo_current_diagnostic "Operating system" @@ -389,8 +310,13 @@ diagnose_operating_system() { # If there is a /etc/*release file, it's probably a supported operating system, so we can if ls /etc/*release 1> /dev/null 2>&1; then - # display the attributes to the user from the function made earlier - os_check + # display the attributes to the user + + detected_os=$(grep "\bID\b" /etc/os-release | cut -d '=' -f2 | tr -d '"') + detected_version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f2 | tr -d '"') + + log_write "${INFO} Distro: ${detected_os^}" + log_write "${INFO} Version: ${detected_version}" else # If it doesn't exist, it's not a system we currently support and link to FAQ log_write "${CROSS} ${COL_RED}${error_msg}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})" From 0c533ec71bece9eb1fcbb764389801d732244c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 3 May 2025 20:06:24 +0200 Subject: [PATCH 091/259] Use CODEOWNERS instead of deprecated dependbot/reviewers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/CODEOWNERS | 5 +++++ .github/dependabot.yml | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..58192bc1 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax + +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +* @pi-hole/core-maintainers diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e140f792..af9b74db 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,8 +8,6 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development - reviewers: - - "pi-hole/core-maintainers" - package-ecosystem: pip directory: "/test" schedule: @@ -18,5 +16,3 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development - reviewers: - - "pi-hole/core-maintainers" From b82487ee6a07486693fb58c0e0ce1653a7c8ffc2 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Sun, 4 May 2025 12:01:09 +0200 Subject: [PATCH 092/259] Add Fedora 42 to tests Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- .github/workflows/test.yml | 1 + test/_fedora_42.Dockerfile | 17 +++++++++++++++++ test/test_any_automated_install.py | 1 + test/tox.fedora_42.ini | 10 ++++++++++ 4 files changed, 29 insertions(+) create mode 100644 test/_fedora_42.Dockerfile create mode 100644 test/tox.fedora_42.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 26435035..ac496406 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,6 +72,7 @@ jobs: centos_10, fedora_40, fedora_41, + fedora_42, ] env: DISTRO: ${{matrix.distro}} diff --git a/test/_fedora_42.Dockerfile b/test/_fedora_42.Dockerfile new file mode 100644 index 00000000..90b17c0b --- /dev/null +++ b/test/_fedora_42.Dockerfile @@ -0,0 +1,17 @@ +FROM fedora:42 +RUN dnf install -y git initscripts + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index e72b4779..0fa0453a 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -245,6 +245,7 @@ def test_FTL_detect_no_errors(host, arch, detected_string, supported): { "-A /bin/sh": ("Tag_CPU_arch: " + arch, "0"), "-A /usr/bin/sh": ("Tag_CPU_arch: " + arch, "0"), + "-A /usr/sbin/sh": ("Tag_CPU_arch: " + arch, "0"), }, host, ) diff --git a/test/tox.fedora_42.ini b/test/tox.fedora_42.ini new file mode 100644 index 00000000..67eb77e4 --- /dev/null +++ b/test/tox.fedora_42.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _fedora_42.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py From 65fd0b099d96bb636c6e431f81981f3d64cb2ab5 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Sun, 4 May 2025 14:21:53 +0200 Subject: [PATCH 093/259] Extend .gitignore Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8016472b..6322fd3e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ __pycache__ .idea/ *.iml .vscode/ +.venv/ +.fleet/ +.cache/ From 96437dc913e12e531d5d1fedab380e6871c7fd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 4 May 2025 19:39:43 +0200 Subject: [PATCH 094/259] Set dns.interface during installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index fda294b4..2e1afe7b 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -99,6 +99,7 @@ IPV6_ADDRESS=${IPV6_ADDRESS} # Give settings their default values. These may be changed by prompts later in the script. QUERY_LOGGING= PRIVACY_LEVEL= +PIHOLE_INTERFACE= # Where old configs go to if a v6 migration is performed V6_CONF_MIGRATION_DIR="/etc/pihole/migration_backup_v6" @@ -2329,6 +2330,10 @@ main() { if [ -n "${PRIVACY_LEVEL}" ]; then setFTLConfigValue "misc.privacylevel" "${PRIVACY_LEVEL}" fi + + if [ -n "${PIHOLE_INTERFACE}" ]; then + setFTLConfigValue "dns.interface" "${PIHOLE_INTERFACE}" + fi fi # Download and compile the aggregated block list From fc103af050c4253ebe616721ba4708163cfa4c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 4 May 2025 21:45:44 +0200 Subject: [PATCH 095/259] Revert response code logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 7e9d4653..97192108 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -57,34 +57,33 @@ TestAPIAvailability() { authData=$(printf %s "${authResponse%???}") # Test if http status code was 200 (OK) or 401 (authentication required) - if [ ! "${authStatus}" = 200 ] && [ ! "${authStatus}" = 401 ]; then - # API is not available at this port/protocol combination - apiAvailable=false - else - # API is available at this URL combination - - if [ "${authStatus}" = 200 ]; then - # API is available without authentication - needAuth=false - fi + if [ "${authStatus}" = 200 ]; then + # API is available without authentication + apiAvailable=true + needAuth=false + break + elif [ "${authStatus}" = 401 ]; then + # API is available with authentication + apiAvailable=true + needAuth=true # Check if 2FA is required needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null) - - apiAvailable=true - break - fi - # Remove the first URL from the list - local last_api_list - last_api_list="${chaos_api_list}" - chaos_api_list="${chaos_api_list#* }" + else + # API is not available at this port/protocol combination + apiAvailable=false + # Remove the first URL from the list + local last_api_list + last_api_list="${chaos_api_list}" + chaos_api_list="${chaos_api_list#* }" - # If the list did not change, we are at the last element - if [ "${last_api_list}" = "${chaos_api_list}" ]; then - # Remove the last element - chaos_api_list="" + # If the list did not change, we are at the last element + if [ "${last_api_list}" = "${chaos_api_list}" ]; then + # Remove the last element + chaos_api_list="" + fi fi done From d45003a8ca4211474ca40a156c39332967ef8e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 5 May 2025 17:27:53 +0200 Subject: [PATCH 096/259] Do not try to upgrade gravity if it does not exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 2e1afe7b..ce240683 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2295,10 +2295,13 @@ main() { # but before starting or resttarting the ftl service disable_resolved_stublistener - # Check if gravity database needs to be upgraded. If so, do it without rebuilding - # gravity altogether. This may be a very long running task needlessly blocking - # the update process. - /opt/pihole/gravity.sh --upgrade + if [[ "${fresh_install}" == false ]]; then + # Check if gravity database needs to be upgraded. If so, do it without rebuilding + # gravity altogether. This may be a very long running task needlessly blocking + # the update process. + # Only do this on updates, not on fresh installs as the database does not exit yet + /opt/pihole/gravity.sh --upgrade + fi printf " %b Restarting services...\\n" "${INFO}" # Start services From 9f3e71b0b6db86330014d8077f42c4ae95a2b30f Mon Sep 17 00:00:00 2001 From: Piotr Tyrakowski Date: Fri, 9 May 2025 17:03:57 +0200 Subject: [PATCH 097/259] Update basic-install.sh I have updated line 708 to use grep -v "loo" instead of "lo" the reason is with "lo" it cannot find "wlo1" interface Signed-off-by: Piotr Tyrakowski --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e69256ff..657b00b7 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -705,7 +705,7 @@ find_IPv4_information() { # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | grep -v "lo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) + availableInterfaces=$(ip --oneline link show up | grep -v "loo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) } # A function for displaying the dialogs the user sees when first running the installer From 189da82614a4d9e3a25e526541fa5719f7047bd5 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Mon, 12 May 2025 08:54:58 +0200 Subject: [PATCH 098/259] && chown Co-authored-by: Dan Schaper Signed-off-by: yubiuser --- gravity.sh | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gravity.sh b/gravity.sh index 37a7301b..f34ac3fb 100755 --- a/gravity.sh +++ b/gravity.sh @@ -139,8 +139,7 @@ gravity_swap_databases() { else # Check if the backup directory exists if [ ! -d "${gravityBCKdir}" ]; then - mkdir -p "${gravityBCKdir}" - chown pihole:pihole "${gravityBCKdir}" + mkdir -p "${gravityBCKdir}" && chown pihole:pihole "${gravityBCKdir}" fi # If multiple gravityBCKfile's are present (appended with a number), rotate them @@ -1016,8 +1015,7 @@ migrate_to_listsCache_dir() { # If not, we need to migrate the old files to the new directory local str="Migrating the list's cache directory to new location" echo -ne " ${INFO} ${str}..." - mkdir -p "${listsCacheDir}" - chown pihole:pihole "${listsCacheDir}" + mkdir -p "${listsCacheDir}" && chown pihole:pihole "${listsCacheDir}" # Move the old files to the new directory if mv "${piholeDir}"/list.* "${listsCacheDir}/" 2>/dev/null; then From 842afc24758e38f29533dc2e9794d7064fcb7dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 21 Apr 2025 09:43:07 +0200 Subject: [PATCH 099/259] Give FTL 60 seconds for graceful shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Templates/pihole-FTL.service | 6 +++++- advanced/Templates/pihole-FTL.systemd | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 6cb3e09a..7c7e9962 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -12,6 +12,7 @@ # Source utils.sh for getFTLConfigValue(), getFTLPID() PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" . "${utilsfile}" @@ -56,13 +57,16 @@ start() { stop() { if is_running; then kill "${FTL_PID}" - for i in 1 2 3 4 5; do + # Give FTL 60 seconds to gracefully stop + i=1 + while [ "${i}" -le 60 ]; do if ! is_running; then break fi printf "." sleep 1 + i=$((i + 1)) done echo diff --git a/advanced/Templates/pihole-FTL.systemd b/advanced/Templates/pihole-FTL.systemd index 0a3d270e..fcbb8d8d 100644 --- a/advanced/Templates/pihole-FTL.systemd +++ b/advanced/Templates/pihole-FTL.systemd @@ -28,7 +28,7 @@ ExecReload=/bin/kill -HUP $MAINPID ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh # Use graceful shutdown with a reasonable timeout -TimeoutStopSec=10s +TimeoutStopSec=60s # Make /usr, /boot, /etc and possibly some more folders read-only... ProtectSystem=full From 190798e57247116c8f8ae2b623719bccaefb3177 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Wed, 19 Mar 2025 19:26:17 -0300 Subject: [PATCH 100/259] Allow simple `pihole api` output, containing only the JSON payload Signed-off-by: RD WebDesign --- advanced/Scripts/api.sh | 32 ++++++++++++++++++++++++-------- pihole | 2 +- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 97192108..fda17458 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -301,14 +301,23 @@ secretRead() { } apiFunc() { - local data response status status_col + local data response status status_col verbose + + # Define if the output will be verbose (default) or silent + verbose="verbose" + if [ "$1" = "silent" ] || [ "$1" = "-s" ]; then + verbose="" + shift + fi # Authenticate with the API - LoginAPI verbose - echo "" + LoginAPI "${verbose}" - echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}" - echo "" + if [ "${verbose}" = "verbose" ]; then + echo "" + echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}" + echo "" + fi # Get the data from the API response=$(GetFTLData "$1" raw) @@ -325,11 +334,18 @@ apiFunc() { else status_col="${COL_RED}" fi - echo "Status: ${status_col}${status}${COL_NC}" + + # Only print the status in verbose mode or if the status is not 200 + if [ "${verbose}" = "verbose" ] || [ "${status}" != 200 ]; then + echo "Status: ${status_col}${status}${COL_NC}" + fi # Output the data. Format it with jq if available and data is actually JSON. # Otherwise just print it - echo "Data:" + if [ "${verbose}" = "verbose" ]; then + echo "Data:" + fi + if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then echo "${data}" | jq . else @@ -337,5 +353,5 @@ apiFunc() { fi # Delete the session - LogoutAPI verbose + LogoutAPI "${verbose}" } diff --git a/pihole b/pihole index 2c3a433b..248e9a7d 100755 --- a/pihole +++ b/pihole @@ -601,6 +601,6 @@ case "${1}" in "updatechecker" ) shift; updateCheckFunc "$@";; "arpflush" ) arpFunc "$@";; "-t" | "tail" ) tailFunc "$2";; - "api" ) apiFunc "$2";; + "api" ) shift; apiFunc "$@";; * ) helpFunc;; esac From e01d49b3ee36fd39679ac20d9e7a92e618f95e94 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 12 May 2025 15:53:12 -0300 Subject: [PATCH 101/259] Change FTLcheckUpdate to use api.github.com and `jq` to retrieve tag_name Signed-off-by: RD WebDesign --- automated install/basic-install.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 74a02395..24fb22d2 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1972,12 +1972,14 @@ FTLcheckUpdate() { # same as the remote one local FTLversion FTLversion=$(/usr/bin/pihole-FTL tag) - local FTLlatesttag # Get the latest version from the GitHub API - if ! FTLlatesttag=$(curl -sI https://github.com/pi-hole/FTL/releases/latest | grep --color=never -i Location: | awk -F / '{print $NF}' | tr -d '[:cntrl:]'); then + local FTLlatesttag + FTLlatesttag=$(curl -s https://api.github.com/repos/pi-hole/FTL/releases/latest | jq -sRr 'fromjson? | .tag_name | values') + + if [ -z "${FTLlatesttag}" ]; then # There was an issue while retrieving the latest version - printf " %b Failed to retrieve latest FTL release metadata" "${CROSS}" + printf " %b Failed to retrieve latest FTL release metadata\\n" "${CROSS}" return 3 fi @@ -1995,6 +1997,7 @@ FTLcheckUpdate() { # Continue further down... fi else + # FTL not installed, then download return 0 fi fi From 13848f2da1b6bde5603d182767bcbfc0345d17d1 Mon Sep 17 00:00:00 2001 From: Piotr Tyrakowski Date: Mon, 12 May 2025 21:13:01 +0200 Subject: [PATCH 102/259] Update automated install/basic-install.sh Co-authored-by: Dan Schaper Signed-off-by: Piotr Tyrakowski --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 657b00b7..9af7fbfd 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -705,7 +705,7 @@ find_IPv4_information() { # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | grep -v "loo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) + availableInterfaces=$(ip --oneline link show up | awk '{print $2}' | grep -v "^lo" | cut -d':' -f1 | cut -d'@' -f1) } # A function for displaying the dialogs the user sees when first running the installer From de31858950a61a5eb90a0a1c59635b32c1dfcdc1 Mon Sep 17 00:00:00 2001 From: Dan Schaper Date: Mon, 12 May 2025 12:01:34 -0700 Subject: [PATCH 103/259] Use shell parameter expansion to split http_code and payload Codespell editorconfig Signed-off-by: Dan Schaper --- advanced/Scripts/api.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 97192108..20ebef5c 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -47,14 +47,15 @@ TestAPIAvailability() { API_URL="${API_URL%\"}" API_URL="${API_URL#\"}" - # Test if the API is available at this URL - authResponse=$(curl --connect-timeout 2 -skS -w "%{http_code}" "${API_URL}auth") + # Test if the API is available at this URL, include delimiter for ease in splitting payload + authResponse=$(curl --connect-timeout 2 -skS -w ">>%{http_code}" "${API_URL}auth") - # authStatus are the last 3 characters - # not using ${authResponse#"${authResponse%???}"}" here because it's extremely slow on big responses - authStatus=$(printf "%s" "${authResponse}" | tail -c 3) - # data is everything from response without the last 3 characters - authData=$(printf %s "${authResponse%???}") + # authStatus is the response http_code, eg. 200, 401. + # Shell parameter expansion, remove everything up to and including the >> delim + authStatus=${authResponse#*>>} + # data is everything from response + # Shell parameter expansion, remove the >> delim and everything after + authData=${authResponse%>>*} # Test if http status code was 200 (OK) or 401 (authentication required) if [ "${authStatus}" = 200 ]; then From dee44cb3da7aa27c2ee853830c944e3565d5e45e Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 11 May 2025 19:51:27 -0300 Subject: [PATCH 104/259] Define "silent" as default option and include "verbose" to the man page Signed-off-by: RD WebDesign --- advanced/Scripts/api.sh | 20 ++++++++++---------- manpages/pihole.8 | 15 ++++++++++++--- pihole | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index fda17458..2a3d361b 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -301,19 +301,19 @@ secretRead() { } apiFunc() { - local data response status status_col verbose + local data response status status_col verbosity - # Define if the output will be verbose (default) or silent - verbose="verbose" - if [ "$1" = "silent" ] || [ "$1" = "-s" ]; then - verbose="" + # Define if the output will be silent (default) or verbose + verbosity="silent" + if [ "$1" = "verbose" ]; then + verbosity="verbose" shift fi # Authenticate with the API - LoginAPI "${verbose}" + LoginAPI "${verbosity}" - if [ "${verbose}" = "verbose" ]; then + if [ "${verbosity}" = "verbose" ]; then echo "" echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}" echo "" @@ -336,13 +336,13 @@ apiFunc() { fi # Only print the status in verbose mode or if the status is not 200 - if [ "${verbose}" = "verbose" ] || [ "${status}" != 200 ]; then + if [ "${verbosity}" = "verbose" ] || [ "${status}" != 200 ]; then echo "Status: ${status_col}${status}${COL_NC}" fi # Output the data. Format it with jq if available and data is actually JSON. # Otherwise just print it - if [ "${verbose}" = "verbose" ]; then + if [ "${verbosity}" = "verbose" ]; then echo "Data:" fi @@ -353,5 +353,5 @@ apiFunc() { fi # Delete the session - LogoutAPI "${verbose}" + LogoutAPI "${verbosity}" } diff --git a/manpages/pihole.8 b/manpages/pihole.8 index 97a6ec68..e0c38828 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -23,7 +23,7 @@ pihole -r .br \fBpihole -g\fR .br -\fBpihole\fR -\fBq\fR [options] +\fBpihole\fR \fB-q\fR [options] .br \fBpihole\fR \fB-l\fR (\fBon|off|off noflush\fR) .br @@ -43,7 +43,7 @@ pihole -r .br \fBpihole\fR \fBcheckout\fR repo [branch] .br -\fBpihole\fR \api\fR endpoint +\fBpihole\fR \fBapi\fR [verbose] endpoint .br \fBpihole\fR \fBhelp\fR .br @@ -234,10 +234,14 @@ Available commands and options: branchname Update subsystems to the specified branchname .br -\fBapi\fR endpoint +\fBapi\fR [verbose] endpoint .br Query the Pi-hole API at .br + + verbose Show authentication and status messages +.br + .SH "EXAMPLE" Some usage examples @@ -323,6 +327,11 @@ Switching Pi-hole subsystem branches Queries FTL for the stats/summary endpoint .br +\fBpihole api verbose stats/summary\fR +.br + Same as above, but shows authentication and status messages +.br + .SH "COLOPHON" Get sucked into the latest news and community activity by entering Pi-hole's orbit. Information about Pi-hole, and the latest version of the software can be found at https://pi-hole.net. diff --git a/pihole b/pihole index 248e9a7d..1d5093c6 100755 --- a/pihole +++ b/pihole @@ -493,6 +493,7 @@ Debugging Options: Add an optional argument to filter the log (regular expressions are supported) api Query the Pi-hole API at + Precede with 'verbose' option to show authentication and status messages Options: From a590b774314b37cde3a297e2bc7869534c169aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 5 Apr 2025 22:33:30 +0200 Subject: [PATCH 105/259] Link to documentation on how to add local user to pihole group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 9e0246f0..b1956449 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2481,6 +2481,8 @@ main() { printf " %b View the web interface at http://pi.hole:${WEBPORT}/admin or http://%s/admin\\n\\n" "${INFO}" "${IPV4_ADDRESS%/*}:${WEBPORT}" printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${pw}" "${COL_NC}" printf " %b This can be changed using 'pihole setpassword'\\n\\n" "${INFO}" + printf " %b To allow your user to use all CLI functions without authentication, refer to\\n" "${INFO}" + printf " our documentation at: https://docs.pi-hole.net/main/post-install/\\n\\n" # Final dialog message to the user dialog --no-shadow --keep-tite \ @@ -2489,7 +2491,11 @@ main() { \\n\\nIPv4: ${IPV4_ADDRESS%/*}\ \\nIPv6: ${IPV6_ADDRESS:-"Not Configured"}\ \\nIf you have not done so already, the above IP should be set to static.\ -\\nView the web interface at http://pi.hole/admin:${WEBPORT} or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pw}" "${r}" "${c}" +\\nView the web interface at http://pi.hole/admin:${WEBPORT} or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pw}\ +\\n +\\n +\\nTo allow your user to use all CLI functions without authentication,\ +\\nrefer to https://docs.pi-hole.net/main/post-install/" "${r}" "${c}" INSTALL_TYPE="Installation" else From f6d477f228e530c28748c39da51997c8a28162e6 Mon Sep 17 00:00:00 2001 From: Dan Schaper Date: Wed, 14 May 2025 09:51:47 -0700 Subject: [PATCH 106/259] =?UTF-8?q?Revert=20"fix(get=5Favailable=5Finterfa?= =?UTF-8?q?ces):=20only=20drop=20the=20loopback=20device=20(=E2=80=98lo?= =?UTF-8?q?=E2=80=99),=20don=E2=80=99t=20filter=20every=20=E2=80=9Clo?= =?UTF-8?q?=E2=80=9D=20substring"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 9af7fbfd..e69256ff 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -705,7 +705,7 @@ find_IPv4_information() { # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | awk '{print $2}' | grep -v "^lo" | cut -d':' -f1 | cut -d'@' -f1) + availableInterfaces=$(ip --oneline link show up | grep -v "lo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) } # A function for displaying the dialogs the user sees when first running the installer From 88934ec81843ebcca64b2fea98bac97212bb1b5f Mon Sep 17 00:00:00 2001 From: Piotr Tyrakowski Date: Wed, 14 May 2025 21:47:34 +0200 Subject: [PATCH 107/259] Update basic-install.sh Signed-off-by: Piotr Tyrakowski --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 24fb22d2..b2bc894f 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -574,7 +574,7 @@ Do you wish to continue with an IPv6-only installation?\\n\\n" \ # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | grep -v "lo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) + availableInterfaces=$(ip --oneline link show up | awk '{print $2}' | grep -v "^lo" | cut -d':' -f1 | cut -d'@' -f1) } # A function for displaying the dialogs the user sees when first running the installer From 86d9ac5f8f27a66f2d1201911238185737af311a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 10:02:13 +0000 Subject: [PATCH 108/259] Bump tox from 4.25.0 to 4.26.0 in /test Bumps [tox](https://github.com/tox-dev/tox) from 4.25.0 to 4.26.0. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.25.0...4.26.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.26.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 6987ee0c..b273c351 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.3.5 pytest-xdist == 3.6.1 pytest-testinfra == 10.2.2 -tox == 4.25.0 +tox == 4.26.0 pytest-clarity == 1.0.1 From 6ba6b0f0157d5ea3ad0dfdb4de30a1086f114512 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Tue, 20 May 2025 19:46:28 -0300 Subject: [PATCH 109/259] Return 1 only if resolution fails Function gravity_CheckDNSResolutionAvailable() should return 0 if DNS resolution is available Signed-off-by: RD WebDesign --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index cf22065a..16e459c6 100755 --- a/gravity.sh +++ b/gravity.sh @@ -356,7 +356,7 @@ gravity_CheckDNSResolutionAvailable() { if getent hosts github.com &> /dev/null; then # If we reach this point, DNS resolution is available echo -e "${OVER} ${TICK} DNS resolution is available" - break + return 0 fi # Append one dot for each second waiting echo -ne "." From 1a3a23a8677a1c063d0855888f6bf22fb7536890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 26 May 2025 21:38:26 +0200 Subject: [PATCH 110/259] Give FTL 120 seconds to shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Templates/pihole-FTL.service | 4 ++-- advanced/Templates/pihole-FTL.systemd | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 7c7e9962..9cdad7a0 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -57,9 +57,9 @@ start() { stop() { if is_running; then kill "${FTL_PID}" - # Give FTL 60 seconds to gracefully stop + # Give FTL 120 seconds to gracefully stop i=1 - while [ "${i}" -le 60 ]; do + while [ "${i}" -le 120 ]; do if ! is_running; then break fi diff --git a/advanced/Templates/pihole-FTL.systemd b/advanced/Templates/pihole-FTL.systemd index fcbb8d8d..0f0e8245 100644 --- a/advanced/Templates/pihole-FTL.systemd +++ b/advanced/Templates/pihole-FTL.systemd @@ -28,7 +28,7 @@ ExecReload=/bin/kill -HUP $MAINPID ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh # Use graceful shutdown with a reasonable timeout -TimeoutStopSec=60s +TimeoutStopSec=120s # Make /usr, /boot, /etc and possibly some more folders read-only... ProtectSystem=full From b707890f1048a188c0182642a5dc01d02661fc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 27 May 2025 20:09:59 +0200 Subject: [PATCH 111/259] Use PID1 to determine which command to use when toggeling services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d84c8750..f4b51c6d 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -228,6 +228,13 @@ is_command() { command -v "${check_command}" >/dev/null 2>&1 } +is_pid1() { + # Checks to see if the given command runs as PID 1 + local is_pid1="$1" + + ps -p 1 -o comm= | grep -q "${is_pid1}" +} + # Compatibility package_manager_detect() { @@ -1152,7 +1159,7 @@ installConfigs() { fi # Install pihole-FTL systemd or init.d service, based on whether systemd is the init system or not - if ps -p 1 -o comm= | grep -q systemd; then + if is_pid1 systemd; then install -T -m 0644 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.systemd" '/etc/systemd/system/pihole-FTL.service' # Remove init.d service if present @@ -1220,9 +1227,12 @@ stop_service() { # Can softfail, as process may not be installed when this is called local str="Stopping ${1} service" printf " %b %s..." "${INFO}" "${str}" - if is_command systemctl; then + # If systemd is PID 1, + if is_pid1 systemd; then + # use that to restart the service systemctl -q stop "${1}" || true else + # Otherwise, fall back to the service command service "${1}" stop >/dev/null || true fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" @@ -1233,8 +1243,8 @@ restart_service() { # Local, named variables local str="Restarting ${1} service" printf " %b %s..." "${INFO}" "${str}" - # If systemctl exists, - if is_command systemctl; then + # If systemd is PID 1, + if is_pid1 systemd; then # use that to restart the service systemctl -q restart "${1}" else @@ -1249,8 +1259,8 @@ enable_service() { # Local, named variables local str="Enabling ${1} service to start on reboot" printf " %b %s..." "${INFO}" "${str}" - # If systemctl exists, - if is_command systemctl; then + # If systemd is PID1, + if is_pid1 systemd; then # use that to enable the service systemctl -q enable "${1}" else @@ -1265,8 +1275,8 @@ disable_service() { # Local, named variables local str="Disabling ${1} service" printf " %b %s..." "${INFO}" "${str}" - # If systemctl exists, - if is_command systemctl; then + # If systemd is PID1, + if is_pid1 systemd; then # use that to disable the service systemctl -q disable "${1}" else @@ -1277,8 +1287,8 @@ disable_service() { } check_service_active() { - # If systemctl exists, - if is_command systemctl; then + # If systemd is PID1, + if is_pid1 systemd; then # use that to check the status of the service systemctl -q is-enabled "${1}" 2>/dev/null else From 137338e6a8445347b97cc04693bdb2801e60fa3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 27 May 2025 21:23:56 +0200 Subject: [PATCH 112/259] Use service wrappers in all scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeARPTable.sh | 11 +++++++++-- advanced/Scripts/piholeLogFlush.sh | 11 +++++++++-- automated install/uninstall.sh | 11 ++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh index c62acdbc..120df5b8 100755 --- a/advanced/Scripts/piholeARPTable.sh +++ b/advanced/Scripts/piholeARPTable.sh @@ -20,6 +20,13 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source=./advanced/Scripts/utils.sh source "${utilsfile}" +readonly PI_HOLE_FILES_DIR="/etc/.pihole" +SKIP_INSTALL="true" +# shellcheck source="./automated install/basic-install.sh" +source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" +# stop_service() is defined in basic-install.sh +# restart_service() is defined in basic-install.sh + # Determine database location DBFILE=$(getFTLConfigValue "files.database") if [ -z "$DBFILE" ]; then @@ -33,7 +40,7 @@ flushARP(){ fi # Stop FTL to prevent database access - if ! output=$(service pihole-FTL stop 2>&1); then + if ! output=$(stop_service pihole-FTL 2>&1); then echo -e "${OVER} ${CROSS} Failed to stop FTL" echo " Output: ${output}" return 1 @@ -65,7 +72,7 @@ flushARP(){ fi # Start FTL again - if ! output=$(service pihole-FTL restart 2>&1); then + if ! output=$(restart_service pihole-FTL 2>&1); then echo -e "${OVER} ${CROSS} Failed to restart FTL" echo " Output: ${output}" return 1 diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ca70f31b..ac0c196f 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -17,6 +17,12 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" +SKIP_INSTALL="true" +# shellcheck source="./automated install/basic-install.sh" +source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" +# stop_service() is defined in basic-install.sh +# restart_service() is defined in basic-install.sh + # In case we're running at the same time as a system logrotate, use a # separate logrotate state file to prevent stepping on each other's # toes. @@ -104,13 +110,14 @@ else fi # Stop FTL to make sure it doesn't write to the database while we're deleting data - service pihole-FTL stop + stop_service pihole-FTL >/dev/null + # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") # Restart FTL - service pihole-FTL restart + restart_service pihole-FTL >/dev/null if [[ "$*" != *"quiet"* ]]; then echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" fi diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index a158e595..eb1e9e29 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -13,6 +13,11 @@ source "/opt/pihole/COL_TABLE" # shellcheck source="./advanced/Scripts/utils.sh" source "/opt/pihole/utils.sh" +SKIP_INSTALL="true" +# shellcheck source="./automated install/basic-install.sh" +source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" +# stop_service() is defined in basic-install.sh + ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") readonly ADMIN_INTERFACE_DIR @@ -102,11 +107,7 @@ removePiholeFiles() { # Remove FTL if command -v pihole-FTL &> /dev/null; then echo -ne " ${INFO} Removing pihole-FTL..." - if [[ -x "$(command -v systemctl)" ]]; then - systemctl stop pihole-FTL - else - service pihole-FTL stop - fi + stop_service pihole-FTL ${SUDO} rm -f /etc/systemd/system/pihole-FTL.service if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then read -rp " ${QST} FTL service override directory /etc/systemd/system/pihole-FTL.service.d detected. Do you wish to remove this from your system? [y/N] " answer From f3166d7a785b43efd97d96a15977105359da33c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 27 May 2025 23:51:04 +0200 Subject: [PATCH 113/259] Adjust test to mock PID1 to be systemd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/_centos_10.Dockerfile | 2 +- test/_centos_9.Dockerfile | 2 +- test/_fedora_40.Dockerfile | 2 +- test/_fedora_41.Dockerfile | 2 +- test/_fedora_42.Dockerfile | 2 +- test/test_any_automated_install.py | 16 +++++++++------- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/test/_centos_10.Dockerfile b/test/_centos_10.Dockerfile index 78a89789..c6b2ca75 100644 --- a/test/_centos_10.Dockerfile +++ b/test/_centos_10.Dockerfile @@ -1,7 +1,7 @@ FROM quay.io/centos/centos:stream10 # Disable SELinux RUN echo "SELINUX=disabled" > /etc/selinux/config -RUN yum install -y --allowerasing curl git initscripts +RUN yum install -y --allowerasing curl git ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_centos_9.Dockerfile b/test/_centos_9.Dockerfile index 73f53fa5..0e12edab 100644 --- a/test/_centos_9.Dockerfile +++ b/test/_centos_9.Dockerfile @@ -1,7 +1,7 @@ FROM quay.io/centos/centos:stream9 # Disable SELinux RUN echo "SELINUX=disabled" > /etc/selinux/config -RUN yum install -y --allowerasing curl git initscripts +RUN yum install -y --allowerasing curl git ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_40.Dockerfile b/test/_fedora_40.Dockerfile index 43913895..56be9d84 100644 --- a/test/_fedora_40.Dockerfile +++ b/test/_fedora_40.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:40 -RUN dnf install -y git initscripts +RUN dnf install -y git ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_41.Dockerfile b/test/_fedora_41.Dockerfile index c03371a5..2a9ecf70 100644 --- a/test/_fedora_41.Dockerfile +++ b/test/_fedora_41.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:41 -RUN dnf install -y git initscripts +RUN dnf install -y git ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_42.Dockerfile b/test/_fedora_42.Dockerfile index 90b17c0b..34c7ef5d 100644 --- a/test/_fedora_42.Dockerfile +++ b/test/_fedora_42.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:42 -RUN dnf install -y git initscripts +RUN dnf install -y git ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 0fa0453a..f10d2576 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -66,6 +66,14 @@ def test_installPihole_fresh_install_readableFiles(host): mock_command("dialog", {"*": ("", "0")}, host) # mock git pull mock_command_passthrough("git", {"pull": ("", "0")}, host) + # mock PID 1 to pretend to be systemd + mock_command_2( + "ps", + { + "-p 1": ("systemd", "0"), + }, + host, + ) # mock systemctl to not start FTL mock_command_2( "systemctl", @@ -73,6 +81,7 @@ def test_installPihole_fresh_install_readableFiles(host): "enable pihole-FTL": ("", "0"), "restart pihole-FTL": ("", "0"), "start pihole-FTL": ("", "0"), + "stop pihole-FTL": ("", "0"), "*": ('echo "systemctl call with $@"', "0"), }, host, @@ -131,13 +140,6 @@ def test_installPihole_fresh_install_readableFiles(host): check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser) actual_rc = host.run(check_macvendor).rc assert exit_status_success == actual_rc - # check readable and executable /etc/init.d/pihole-FTL - check_init = test_cmd.format("x", "/etc/init.d/pihole-FTL", piholeuser) - actual_rc = host.run(check_init).rc - assert exit_status_success == actual_rc - check_init = test_cmd.format("r", "/etc/init.d/pihole-FTL", piholeuser) - actual_rc = host.run(check_init).rc - assert exit_status_success == actual_rc # check readable and executable manpages if maninstalled is True: check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser) From 69473a7b54869233ea40a8d16bf17030ac835656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 28 May 2025 19:25:35 +0200 Subject: [PATCH 114/259] Add awk to meta package dependencie (is missing on Fedora 42 by default) and order dependencies alphabetically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index f4b51c6d..94ef8002 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -116,11 +116,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron | cron-daemon,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion +Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,netcat-openbsd,procps,psmisc,sudo,unzip Section: contrib/metapackages Priority: optional EOM @@ -130,12 +130,12 @@ EOM PIHOLE_META_PACKAGE_CONTROL_RPM=$( cat < Date: Wed, 28 May 2025 20:47:55 +0200 Subject: [PATCH 115/259] Add gwak to Fedorea 42 test image as other tests also rely on awk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/_fedora_42.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/_fedora_42.Dockerfile b/test/_fedora_42.Dockerfile index 34c7ef5d..0d235e2d 100644 --- a/test/_fedora_42.Dockerfile +++ b/test/_fedora_42.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:42 -RUN dnf install -y git +RUN dnf install -y git gawk ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole From d177c4c776be2f9e7adf044660827f3405ec1905 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 30 May 2025 19:03:12 +0200 Subject: [PATCH 116/259] Add useful comment Co-authored-by: Dan Schaper Signed-off-by: yubiuser --- automated install/basic-install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 94ef8002..6cc69008 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -235,7 +235,9 @@ is_pid1() { # Checks to see if the given command runs as PID 1 local is_pid1="$1" - ps -p 1 -o comm= | grep -q "${is_pid1}" + # select PID 1, format output to show only CMD column without header + # quietly grep for a match on the function passed parameter + ps --pid 1 --format comm= | grep -q "${is_pid1}" } # Compatibility From fd40fa6f396273c8d6b95d123ecbc8590b47bf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 30 May 2025 20:52:37 +0200 Subject: [PATCH 117/259] Test need adjustment to long arument syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/test_any_automated_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index f10d2576..64d8c28a 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -70,7 +70,7 @@ def test_installPihole_fresh_install_readableFiles(host): mock_command_2( "ps", { - "-p 1": ("systemd", "0"), + "--pid 1": ("systemd", "0"), }, host, ) From 6f429d82b429531e24b8e41e7859f01871ab4992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 30 May 2025 21:05:08 +0200 Subject: [PATCH 118/259] Allow to get API URL from local.api.ftl even if DNS port has changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 6969b45f..613a8d86 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -19,13 +19,19 @@ TestAPIAvailability() { + local chaos_api_list authResponse authStatus authData apiAvailable DNSport + # as we are running locally, we can get the port value from FTL directly - local chaos_api_list authResponse authStatus authData apiAvailable + readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" + # shellcheck source=./advanced/Scripts/utils.sh + . "${utilsfile}" + + DNSport=$(getFTLConfigValue dns.port) # Query the API URLs from FTL using CHAOS TXT local.api.ftl # The result is a space-separated enumeration of full URLs # e.g., "http://localhost:80/api/" "https://localhost:443/api/" - chaos_api_list="$(dig +short chaos txt local.api.ftl @127.0.0.1)" + chaos_api_list="$(dig +short -p "${DNSport}" chaos txt local.api.ftl @127.0.0.1)" # If the query was not successful, the variable is empty if [ -z "${chaos_api_list}" ]; then From 89c4976da485fe506726d2c28db54e7eeab42afe Mon Sep 17 00:00:00 2001 From: Dan Schaper Date: Sat, 31 May 2025 08:23:24 -0700 Subject: [PATCH 119/259] Make LOGFILE readonly after assignment Signed-off-by: Dan Schaper --- pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pihole b/pihole index 2c3a433b..1a5cdf9e 100755 --- a/pihole +++ b/pihole @@ -389,8 +389,8 @@ tailFunc() { echo -e " ${INFO} Press Ctrl-C to exit" # Get logfile path - readonly LOGFILE LOGFILE=$(getFTLConfigValue files.log.dnsmasq) + readonly LOGFILE # Strip date from each line # Color blocklist/denylist/wildcard entries as red From e1b05028a766c4287e75e5d7d3455010f00467ac Mon Sep 17 00:00:00 2001 From: Dan Schaper Date: Sat, 31 May 2025 09:14:08 -0700 Subject: [PATCH 120/259] Revert "Use PID1 to determine which command to use when toggeling services" --- advanced/Scripts/piholeARPTable.sh | 11 ++------ advanced/Scripts/piholeLogFlush.sh | 11 ++------ automated install/basic-install.sh | 43 ++++++++++-------------------- automated install/uninstall.sh | 11 ++++---- test/_centos_10.Dockerfile | 2 +- test/_centos_9.Dockerfile | 2 +- test/_fedora_40.Dockerfile | 2 +- test/_fedora_41.Dockerfile | 2 +- test/_fedora_42.Dockerfile | 2 +- test/test_any_automated_install.py | 16 +++++------ 10 files changed, 35 insertions(+), 67 deletions(-) diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh index 120df5b8..c62acdbc 100755 --- a/advanced/Scripts/piholeARPTable.sh +++ b/advanced/Scripts/piholeARPTable.sh @@ -20,13 +20,6 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source=./advanced/Scripts/utils.sh source "${utilsfile}" -readonly PI_HOLE_FILES_DIR="/etc/.pihole" -SKIP_INSTALL="true" -# shellcheck source="./automated install/basic-install.sh" -source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" -# stop_service() is defined in basic-install.sh -# restart_service() is defined in basic-install.sh - # Determine database location DBFILE=$(getFTLConfigValue "files.database") if [ -z "$DBFILE" ]; then @@ -40,7 +33,7 @@ flushARP(){ fi # Stop FTL to prevent database access - if ! output=$(stop_service pihole-FTL 2>&1); then + if ! output=$(service pihole-FTL stop 2>&1); then echo -e "${OVER} ${CROSS} Failed to stop FTL" echo " Output: ${output}" return 1 @@ -72,7 +65,7 @@ flushARP(){ fi # Start FTL again - if ! output=$(restart_service pihole-FTL 2>&1); then + if ! output=$(service pihole-FTL restart 2>&1); then echo -e "${OVER} ${CROSS} Failed to restart FTL" echo " Output: ${output}" return 1 diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ac0c196f..ca70f31b 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -17,12 +17,6 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" -SKIP_INSTALL="true" -# shellcheck source="./automated install/basic-install.sh" -source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" -# stop_service() is defined in basic-install.sh -# restart_service() is defined in basic-install.sh - # In case we're running at the same time as a system logrotate, use a # separate logrotate state file to prevent stepping on each other's # toes. @@ -110,14 +104,13 @@ else fi # Stop FTL to make sure it doesn't write to the database while we're deleting data - stop_service pihole-FTL >/dev/null - + service pihole-FTL stop # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") # Restart FTL - restart_service pihole-FTL >/dev/null + service pihole-FTL restart if [[ "$*" != *"quiet"* ]]; then echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" fi diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 6cc69008..d84c8750 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -116,11 +116,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,netcat-openbsd,procps,psmisc,sudo,unzip +Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron | cron-daemon,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion Section: contrib/metapackages Priority: optional EOM @@ -130,12 +130,12 @@ EOM PIHOLE_META_PACKAGE_CONTROL_RPM=$( cat </dev/null 2>&1 } -is_pid1() { - # Checks to see if the given command runs as PID 1 - local is_pid1="$1" - - # select PID 1, format output to show only CMD column without header - # quietly grep for a match on the function passed parameter - ps --pid 1 --format comm= | grep -q "${is_pid1}" -} - # Compatibility package_manager_detect() { @@ -1164,7 +1152,7 @@ installConfigs() { fi # Install pihole-FTL systemd or init.d service, based on whether systemd is the init system or not - if is_pid1 systemd; then + if ps -p 1 -o comm= | grep -q systemd; then install -T -m 0644 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.systemd" '/etc/systemd/system/pihole-FTL.service' # Remove init.d service if present @@ -1232,12 +1220,9 @@ stop_service() { # Can softfail, as process may not be installed when this is called local str="Stopping ${1} service" printf " %b %s..." "${INFO}" "${str}" - # If systemd is PID 1, - if is_pid1 systemd; then - # use that to restart the service + if is_command systemctl; then systemctl -q stop "${1}" || true else - # Otherwise, fall back to the service command service "${1}" stop >/dev/null || true fi printf "%b %b %s...\\n" "${OVER}" "${TICK}" "${str}" @@ -1248,8 +1233,8 @@ restart_service() { # Local, named variables local str="Restarting ${1} service" printf " %b %s..." "${INFO}" "${str}" - # If systemd is PID 1, - if is_pid1 systemd; then + # If systemctl exists, + if is_command systemctl; then # use that to restart the service systemctl -q restart "${1}" else @@ -1264,8 +1249,8 @@ enable_service() { # Local, named variables local str="Enabling ${1} service to start on reboot" printf " %b %s..." "${INFO}" "${str}" - # If systemd is PID1, - if is_pid1 systemd; then + # If systemctl exists, + if is_command systemctl; then # use that to enable the service systemctl -q enable "${1}" else @@ -1280,8 +1265,8 @@ disable_service() { # Local, named variables local str="Disabling ${1} service" printf " %b %s..." "${INFO}" "${str}" - # If systemd is PID1, - if is_pid1 systemd; then + # If systemctl exists, + if is_command systemctl; then # use that to disable the service systemctl -q disable "${1}" else @@ -1292,8 +1277,8 @@ disable_service() { } check_service_active() { - # If systemd is PID1, - if is_pid1 systemd; then + # If systemctl exists, + if is_command systemctl; then # use that to check the status of the service systemctl -q is-enabled "${1}" 2>/dev/null else diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index eb1e9e29..a158e595 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -13,11 +13,6 @@ source "/opt/pihole/COL_TABLE" # shellcheck source="./advanced/Scripts/utils.sh" source "/opt/pihole/utils.sh" -SKIP_INSTALL="true" -# shellcheck source="./automated install/basic-install.sh" -source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" -# stop_service() is defined in basic-install.sh - ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") readonly ADMIN_INTERFACE_DIR @@ -107,7 +102,11 @@ removePiholeFiles() { # Remove FTL if command -v pihole-FTL &> /dev/null; then echo -ne " ${INFO} Removing pihole-FTL..." - stop_service pihole-FTL + if [[ -x "$(command -v systemctl)" ]]; then + systemctl stop pihole-FTL + else + service pihole-FTL stop + fi ${SUDO} rm -f /etc/systemd/system/pihole-FTL.service if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then read -rp " ${QST} FTL service override directory /etc/systemd/system/pihole-FTL.service.d detected. Do you wish to remove this from your system? [y/N] " answer diff --git a/test/_centos_10.Dockerfile b/test/_centos_10.Dockerfile index c6b2ca75..78a89789 100644 --- a/test/_centos_10.Dockerfile +++ b/test/_centos_10.Dockerfile @@ -1,7 +1,7 @@ FROM quay.io/centos/centos:stream10 # Disable SELinux RUN echo "SELINUX=disabled" > /etc/selinux/config -RUN yum install -y --allowerasing curl git +RUN yum install -y --allowerasing curl git initscripts ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_centos_9.Dockerfile b/test/_centos_9.Dockerfile index 0e12edab..73f53fa5 100644 --- a/test/_centos_9.Dockerfile +++ b/test/_centos_9.Dockerfile @@ -1,7 +1,7 @@ FROM quay.io/centos/centos:stream9 # Disable SELinux RUN echo "SELINUX=disabled" > /etc/selinux/config -RUN yum install -y --allowerasing curl git +RUN yum install -y --allowerasing curl git initscripts ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_40.Dockerfile b/test/_fedora_40.Dockerfile index 56be9d84..43913895 100644 --- a/test/_fedora_40.Dockerfile +++ b/test/_fedora_40.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:40 -RUN dnf install -y git +RUN dnf install -y git initscripts ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_41.Dockerfile b/test/_fedora_41.Dockerfile index 2a9ecf70..c03371a5 100644 --- a/test/_fedora_41.Dockerfile +++ b/test/_fedora_41.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:41 -RUN dnf install -y git +RUN dnf install -y git initscripts ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/_fedora_42.Dockerfile b/test/_fedora_42.Dockerfile index 0d235e2d..90b17c0b 100644 --- a/test/_fedora_42.Dockerfile +++ b/test/_fedora_42.Dockerfile @@ -1,5 +1,5 @@ FROM fedora:42 -RUN dnf install -y git gawk +RUN dnf install -y git initscripts ENV GITDIR=/etc/.pihole ENV SCRIPTDIR=/opt/pihole diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 64d8c28a..0fa0453a 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -66,14 +66,6 @@ def test_installPihole_fresh_install_readableFiles(host): mock_command("dialog", {"*": ("", "0")}, host) # mock git pull mock_command_passthrough("git", {"pull": ("", "0")}, host) - # mock PID 1 to pretend to be systemd - mock_command_2( - "ps", - { - "--pid 1": ("systemd", "0"), - }, - host, - ) # mock systemctl to not start FTL mock_command_2( "systemctl", @@ -81,7 +73,6 @@ def test_installPihole_fresh_install_readableFiles(host): "enable pihole-FTL": ("", "0"), "restart pihole-FTL": ("", "0"), "start pihole-FTL": ("", "0"), - "stop pihole-FTL": ("", "0"), "*": ('echo "systemctl call with $@"', "0"), }, host, @@ -140,6 +131,13 @@ def test_installPihole_fresh_install_readableFiles(host): check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser) actual_rc = host.run(check_macvendor).rc assert exit_status_success == actual_rc + # check readable and executable /etc/init.d/pihole-FTL + check_init = test_cmd.format("x", "/etc/init.d/pihole-FTL", piholeuser) + actual_rc = host.run(check_init).rc + assert exit_status_success == actual_rc + check_init = test_cmd.format("r", "/etc/init.d/pihole-FTL", piholeuser) + actual_rc = host.run(check_init).rc + assert exit_status_success == actual_rc # check readable and executable manpages if maninstalled is True: check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser) From 8c8133500498cf5c1912c3a35fcc3acac131d97d Mon Sep 17 00:00:00 2001 From: Dan Schaper Date: Sat, 31 May 2025 11:39:13 -0700 Subject: [PATCH 121/259] Don't revert the package metadata Signed-off-by: Dan Schaper --- automated install/basic-install.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d84c8750..279dc1d1 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -116,11 +116,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: grep,dnsutils,binutils,git,iproute2,dialog,ca-certificates,cron | cron-daemon,curl,iputils-ping,psmisc,sudo,unzip,libcap2-bin,dns-root-data,libcap2,netcat-openbsd,procps,jq,lshw,bash-completion +Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,netcat-openbsd,procps,psmisc,sudo,unzip Section: contrib/metapackages Priority: optional EOM @@ -130,12 +130,12 @@ EOM PIHOLE_META_PACKAGE_CONTROL_RPM=$( cat < Date: Mon, 2 Jun 2025 03:59:36 +0200 Subject: [PATCH 122/259] basic-install.sh listing interfaces Following up on below one: https://github.com/pi-hole/pi-hole/pull/6236 And below poor attempt: https://github.com/pi-hole/pi-hole/pull/6256 Signed-off-by: deHakkelaar --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 279dc1d1..dfecda9c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -577,7 +577,7 @@ Do you wish to continue with an IPv6-only installation?\\n\\n" \ # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | awk '{print $2}' | grep -v "^lo" | cut -d':' -f1 | cut -d'@' -f1) + availableInterfaces=$(ip --oneline link show up | awk -F ': |@' '!/<.*LOOPBACK.*>/ {print $2}') } # A function for displaying the dialogs the user sees when first running the installer From ea61755881b9c3b4c7776ab265079f3695c9cd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 5 Jun 2025 12:50:10 +0200 Subject: [PATCH 123/259] Only update the package cache on fresh installations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 1 + automated install/basic-install.sh | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 51c1b1a1..d9412f8a 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -114,6 +114,7 @@ main() { # Install packages used by this installation script (necessary if users have removed e.g. git from their systems) + check_fresh_install package_manager_detect build_dependency_package install_dependent_packages diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 279dc1d1..cbad9eac 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -231,6 +231,13 @@ is_command() { command -v "${check_command}" >/dev/null 2>&1 } +check_fresh_install() { + # in case of an update (can be a v5 -> v6 or v6 -> v6 update) or repair + if [[ -f "${PI_HOLE_V6_CONFIG}" ]] || [[ -f "/etc/pihole/setupVars.conf" ]]; then + fresh_install=false + fi +} + # Compatibility package_manager_detect() { @@ -247,8 +254,10 @@ package_manager_detect() { PKG_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true" # The command we will use to remove packages (used in the uninstaller) PKG_REMOVE="${PKG_MANAGER} -y remove --purge" - # Update package cache - update_package_cache || exit 1 + # Update package cache only on fresh installs + if [[ "${fresh_install}" == true ]]; then + update_package_cache || exit 1 + fi # If apt-get is not found, check for rpm. elif is_command rpm; then @@ -2193,6 +2202,9 @@ main() { # Check for availability of either the "service" or "systemctl" commands check_service_command + # Check if this is a fresh install or an update/repair + check_fresh_install + # Check for supported package managers so that we may install dependencies package_manager_detect @@ -2216,10 +2228,7 @@ main() { exit 1 fi - # in case of an update (can be a v5 -> v6 or v6 -> v6 update) or repair - if [[ -f "${PI_HOLE_V6_CONFIG}" ]] || [[ -f "/etc/pihole/setupVars.conf" ]]; then - # retain settings - fresh_install=false + if [[ "${fresh_install}" == false ]]; then # if it's running unattended, if [[ "${runUnattended}" == true ]]; then printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" From 93ecfb9504c7f353ebf8dd83b23a8c89c9bbdc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 5 Jun 2025 13:09:03 +0200 Subject: [PATCH 124/259] We test a fresh installaton, so don't pretend this is not a fresh installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/test_any_automated_install.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 0fa0453a..eb1f72e4 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -89,10 +89,8 @@ def test_installPihole_fresh_install_readableFiles(host): export DEBIAN_FRONTEND=noninteractive umask 0027 runUnattended=true - fresh_install=false source /opt/pihole/basic-install.sh > /dev/null runUnattended=true - fresh_install=false main /opt/pihole/pihole-FTL-prestart.sh """ From 5ff4f000d5e8e9c853bd18b96ae1237868243978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 5 Jun 2025 14:16:27 +0200 Subject: [PATCH 125/259] Add 'never-stale' to the exempt issue labels of the stale workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index a0dd9a31..34ffb64e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,7 +24,7 @@ jobs: days-before-close: 5 stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.' stale-issue-label: '${{ env.stale_label }}' - exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed' + exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed, never-stale' exempt-all-issue-assignees: true operations-per-run: 300 close-issue-reason: 'not_planned' From d16c049768463a978137340812d782a0120acb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 5 Jun 2025 14:43:38 +0200 Subject: [PATCH 126/259] Set PI_HOLE_SCRIPT_DIR in api.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 613a8d86..e5eacd41 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -22,7 +22,8 @@ TestAPIAvailability() { local chaos_api_list authResponse authStatus authData apiAvailable DNSport # as we are running locally, we can get the port value from FTL directly - readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" + PI_HOLE_SCRIPT_DIR="/opt/pihole" + utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source=./advanced/Scripts/utils.sh . "${utilsfile}" From 082d74eeb1f6eaee9edcda6f79695e714451c077 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 6 Jun 2025 06:44:17 +0200 Subject: [PATCH 127/259] Install ARMv7 binary even when we detect a 64bit (aarch64) CPU but the operating system is 32bit. See FTL#2494 for reference Signed-off-by: DL6ER --- automated install/basic-install.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 279dc1d1..fcacf96d 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1849,9 +1849,18 @@ get_binary_name() { # If the machine is aarch64 (armv8) if [[ "${machine}" == "aarch64" ]]; then - # If AArch64 is found (e.g., BCM2711 in Raspberry Pi 4) - printf "%b %b Detected AArch64 (64 Bit ARM) architecture\\n" "${OVER}" "${TICK}" - l_binary="pihole-FTL-arm64" + if [[ "$(getconf LONG_BIT)" == "64" ]]; then + # If the OS is 64 bit, we use the arm64 binary + printf "%b %b Detected AArch64 (64 Bit ARM) architecture\\n" "${OVER}" "${TICK}" + l_binary="pihole-FTL-arm64" + else + # If the OS is 32 bit, we use the armv7 binary (aarch64 is actually armv8) + # Even though the machine is 64 bit capable, this makes debugging + # very hard as 32bit tools like gdb, etc. cannot analyze the 64 bit + # binary. See FTL issue #2494 for such an example. + printf "%b %b Detected AArch64 (64 Bit ARM) architecture with 32 bit OS\\n" "${OVER}" "${TICK}" + l_binary="pihole-FTL-armv7" + fi elif [[ "${machine}" == "arm"* ]]; then # ARM 32 bit # Get supported processor from other binaries installed on the system From 3933cb0575f1004ed585bcf090e4c2f52dc78936 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 10:01:39 +0000 Subject: [PATCH 128/259] Bump pytest from 8.3.5 to 8.4.0 in /test Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.5 to 8.4.0. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.3.5...8.4.0) --- updated-dependencies: - dependency-name: pytest dependency-version: 8.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index b273c351..8e45a6d0 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ pyyaml == 6.0.2 -pytest == 8.3.5 +pytest == 8.4.0 pytest-xdist == 3.6.1 pytest-testinfra == 10.2.2 tox == 4.26.0 From 2c1032090d7afff4effe1661981ba8947250c890 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 10:07:56 +0000 Subject: [PATCH 129/259] Bump pytest-xdist from 3.6.1 to 3.7.0 in /test Bumps [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) from 3.6.1 to 3.7.0. - [Release notes](https://github.com/pytest-dev/pytest-xdist/releases) - [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.6.1...v3.7.0) --- updated-dependencies: - dependency-name: pytest-xdist dependency-version: 3.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 8e45a6d0..d2e4344a 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,6 +1,6 @@ pyyaml == 6.0.2 pytest == 8.4.0 -pytest-xdist == 3.6.1 +pytest-xdist == 3.7.0 pytest-testinfra == 10.2.2 tox == 4.26.0 pytest-clarity == 1.0.1 From b39c9956e844d82a17ac2ba51c421977d443901a Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Sat, 7 Jun 2025 18:27:46 +0300 Subject: [PATCH 130/259] Dependabot: group updates Signed-off-by: XhmikosR --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index af9b74db..4ecfe617 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,6 +8,11 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development + versioning-strategy: increase + groups: + github-actions: + patterns: + - "*" - package-ecosystem: pip directory: "/test" schedule: @@ -16,3 +21,8 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development + versioning-strategy: increase + groups: + github-actions: + patterns: + - "*" From 5777497f52c3c87da870e9282bf21e30ffcf5133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 8 Jun 2025 21:25:43 +0200 Subject: [PATCH 131/259] Separate package manager detection and cache update functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 1 - automated install/basic-install.sh | 9 +++++---- test/test_any_automated_install.py | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index d9412f8a..51c1b1a1 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -114,7 +114,6 @@ main() { # Install packages used by this installation script (necessary if users have removed e.g. git from their systems) - check_fresh_install package_manager_detect build_dependency_package install_dependent_packages diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index cbad9eac..99b11d5c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -254,10 +254,6 @@ package_manager_detect() { PKG_COUNT="${PKG_MANAGER} -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true" # The command we will use to remove packages (used in the uninstaller) PKG_REMOVE="${PKG_MANAGER} -y remove --purge" - # Update package cache only on fresh installs - if [[ "${fresh_install}" == true ]]; then - update_package_cache || exit 1 - fi # If apt-get is not found, check for rpm. elif is_command rpm; then @@ -2208,6 +2204,11 @@ main() { # Check for supported package managers so that we may install dependencies package_manager_detect + # Update package cache only on fresh installs and apt based systems + if [[ "${fresh_install}" == true ]] && is_command apt-get; then + update_package_cache || exit 1 + fi + # Notify user of package availability notify_package_updates_available diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index eb1f72e4..cf4b454d 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -471,6 +471,7 @@ def test_package_manager_has_pihole_deps(host): """ source /opt/pihole/basic-install.sh package_manager_detect + update_package_cache build_dependency_package install_dependent_packages """ @@ -487,6 +488,7 @@ def test_meta_package_uninstall(host): """ source /opt/pihole/basic-install.sh package_manager_detect + update_package_cache build_dependency_package install_dependent_packages """ From 7a16024020d975b3e0490621e4cc6832b4151111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 8 Jun 2025 21:31:56 +0200 Subject: [PATCH 132/259] Run package update everytime before building the meta package when invoking from the install script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 99b11d5c..c18e6c0d 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2204,8 +2204,8 @@ main() { # Check for supported package managers so that we may install dependencies package_manager_detect - # Update package cache only on fresh installs and apt based systems - if [[ "${fresh_install}" == true ]] && is_command apt-get; then + # Update package cache only on apt based systems + if is_command apt-get; then update_package_cache || exit 1 fi From c19e907c0c5c26604b30dbd7d56752e26a407476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 9 Jun 2025 19:06:15 +0200 Subject: [PATCH 133/259] Fix dependabot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/dependabot.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4ecfe617..7a5d2064 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,9 +8,8 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development - versioning-strategy: increase groups: - github-actions: + github-actions-dependencies: patterns: - "*" - package-ecosystem: pip @@ -21,8 +20,7 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development - versioning-strategy: increase groups: - github-actions: + python-dependencies: patterns: - "*" From 04d9d32444d57ee29388d21b63a276d88e1f31c1 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Tue, 17 Jun 2025 20:19:13 -0300 Subject: [PATCH 134/259] Remove test for port 4711 Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 741ff2f4..2f82186f 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -388,14 +388,6 @@ check_firewalld() { else log_write "${CROSS} ${COL_RED} Local Interface Not Detected${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" fi - # check FTL custom zone port: 4711 - local firewalld_ftl_zone_ports - firewalld_ftl_zone_ports=$(firewall-cmd --zone=ftl --list-ports) - if [[ "${firewalld_ftl_zone_ports}" =~ "4711/tcp" ]]; then - log_write "${TICK} ${COL_GREEN} FTL Port 4711/tcp Detected${COL_NC}"; - else - log_write "${CROSS} ${COL_RED} FTL Port 4711/tcp Not Detected${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" - fi else log_write "${CROSS} ${COL_RED}FTL Custom Zone Not Detected${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" fi From 405053692a8ae62c18fde18baa7b19211cb86036 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Tue, 17 Jun 2025 21:32:49 -0300 Subject: [PATCH 135/259] Add HTTPS and NTP services to firewalld test Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 2f82186f..7f12a2ab 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -367,7 +367,7 @@ check_firewalld() { # test common required service ports local firewalld_enabled_services firewalld_enabled_services=$(firewall-cmd --list-services) - local firewalld_expected_services=("http" "dns" "dhcp" "dhcpv6") + local firewalld_expected_services=("http" "https" "dns" "dhcp" "dhcpv6" "ntp") for i in "${firewalld_expected_services[@]}"; do if [[ "${firewalld_enabled_services}" =~ ${i} ]]; then log_write "${TICK} ${COL_GREEN} Allow Service: ${i}${COL_NC}"; From 700c892dff37b9dab8d20b9c4965367eed513285 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Jun 2025 10:10:43 +0000 Subject: [PATCH 136/259] Bump tox from 4.26.0 to 4.27.0 in /test Bumps [tox](https://github.com/tox-dev/tox) from 4.26.0 to 4.27.0. - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.26.0...4.27.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.27.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index d2e4344a..821e505e 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.4.0 pytest-xdist == 3.7.0 pytest-testinfra == 10.2.2 -tox == 4.26.0 +tox == 4.27.0 pytest-clarity == 1.0.1 From 0bc06ed204cb4fc6b831c060b608b59acbbb4d82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Jun 2025 10:10:47 +0000 Subject: [PATCH 137/259] Bump pytest from 8.4.0 to 8.4.1 in /test Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.4.0 to 8.4.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.4.0...8.4.1) --- updated-dependencies: - dependency-name: pytest dependency-version: 8.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index d2e4344a..43b1af15 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ pyyaml == 6.0.2 -pytest == 8.4.0 +pytest == 8.4.1 pytest-xdist == 3.7.0 pytest-testinfra == 10.2.2 tox == 4.26.0 From 830c4bc049bcd7e81727dec8d2d91303e1f9d705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 21 Jun 2025 22:40:43 +0200 Subject: [PATCH 138/259] Do not skipp root check for pihole user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- pihole | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pihole b/pihole index 1dfab754..1dee25e5 100755 --- a/pihole +++ b/pihole @@ -570,9 +570,9 @@ if [[ -z ${USER} ]]; then USER=$(whoami) fi -# Check if the current user is neither root nor pihole and if the command +# Check if the current user is not root and if the command # requires root. If so, exit with an error message. -if [[ $EUID -ne 0 && ${USER} != "pihole" && need_root -eq 1 ]];then +if [[ $EUID -ne 0 && need_root -eq 1 ]];then echo -e " ${CROSS} The Pi-hole command requires root privileges, try:" echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}" exit 1 From a48665c7bba428e3e204c9f1bed5d2b8c244336c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 24 Jun 2025 18:51:01 +0200 Subject: [PATCH 139/259] Remove deprecated and unused colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/COL_TABLE | 20 +------- advanced/Scripts/piholeCheckout.sh | 10 ++-- advanced/Scripts/update.sh | 26 +++++----- automated install/basic-install.sh | 82 +++++++++++++++--------------- automated install/uninstall.sh | 10 ++-- gravity.sh | 8 +-- pihole | 4 +- 7 files changed, 71 insertions(+), 89 deletions(-) diff --git a/advanced/Scripts/COL_TABLE b/advanced/Scripts/COL_TABLE index f9a014fc..0c6981c1 100644 --- a/advanced/Scripts/COL_TABLE +++ b/advanced/Scripts/COL_TABLE @@ -1,11 +1,11 @@ #!/usr/bin/env sh +# shellcheck disable=SC2034 # Disable warning about unused variables + # Determine if terminal is capable of showing colors if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then # Bold and underline may not show up on all clients # If something MUST be emphasized, use both COL_BOLD='' - COL_ULINE='' - COL_NC='' COL_GRAY='' COL_RED='' @@ -17,8 +17,6 @@ if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then else # Provide empty variables for `set -u` COL_BOLD="" - COL_ULINE="" - COL_NC="" COL_GRAY="" COL_RED="" @@ -29,22 +27,8 @@ else COL_CYAN="" fi -# Deprecated variables -COL_WHITE="${COL_BOLD}" -COL_BLACK="${COL_NC}" -COL_LIGHT_BLUE="${COL_BLUE}" -COL_LIGHT_GREEN="${COL_GREEN}" -COL_LIGHT_CYAN="${COL_CYAN}" -COL_LIGHT_RED="${COL_RED}" -COL_URG_RED="${COL_RED}${COL_BOLD}${COL_ULINE}" -COL_LIGHT_PURPLE="${COL_PURPLE}" -COL_BROWN="${COL_YELLOW}" -COL_LIGHT_GRAY="${COL_GRAY}" -COL_DARK_GRAY="${COL_GRAY}" - TICK="[${COL_GREEN}✓${COL_NC}]" CROSS="[${COL_RED}✗${COL_NC}]" INFO="[i]" QST="[?]" -DONE="${COL_GREEN} done!${COL_NC}" OVER="\\r" diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index beaac5f1..a6df46f2 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -26,7 +26,7 @@ source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" warning1() { echo " Please note that changing branches severely alters your Pi-hole subsystems" echo " Features that work on the master branch, may not on a development branch" - echo -e " ${COL_LIGHT_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}" + echo -e " ${COL_RED}This feature is NOT supported unless a Pi-hole developer explicitly asks!${COL_NC}" read -r -p " Have you read and understood this? [y/N] " response case "${response}" in [yY][eE][sS]|[yY]) @@ -55,19 +55,19 @@ checkout() { # This is unlikely if ! is_repo "${PI_HOLE_FILES_DIR}" ; then - echo -e " ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!" + echo -e " ${COL_RED}Error: Core Pi-hole repo is missing from system!" echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" exit 1; fi if ! is_repo "${webInterfaceDir}" ; then - echo -e " ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!" + echo -e " ${COL_RED}Error: Web Admin repo is missing from system!" echo -e " Please re-run install script from https://github.com/pi-hole/pi-hole${COL_NC}" exit 1; fi if [[ -z "${1}" ]]; then - echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC}" + echo -e " ${COL_RED}Invalid option${COL_NC}" echo -e " Try 'pihole checkout --help' for more information." exit 1 fi @@ -238,7 +238,7 @@ checkout() { if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then exit 0 else - echo -e " ${COL_LIGHT_RED} Error: Unable to complete update, please contact support${COL_NC}" + echo -e " ${COL_RED} Error: Unable to complete update, please contact support${COL_NC}" exit 1 fi fi diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 51c1b1a1..5fb7de18 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -47,7 +47,7 @@ GitCheckUpdateAvail() { # Fetch latest changes in this repo if ! git fetch --quiet origin ; then - echo -e "\\n ${COL_LIGHT_RED}Error: Unable to update local repository. Contact Pi-hole Support.${COL_NC}" + echo -e "\\n ${COL_RED}Error: Unable to update local repository. Contact Pi-hole Support.${COL_NC}" exit 1 fi @@ -76,13 +76,13 @@ GitCheckUpdateAvail() { if [[ "${#LOCAL}" == 0 ]]; then - echo -e "\\n ${COL_LIGHT_RED}Error: Local revision could not be obtained, please contact Pi-hole Support" + echo -e "\\n ${COL_RED}Error: Local revision could not be obtained, please contact Pi-hole Support" echo -e " Additional debugging output:${COL_NC}" git status exit 1 fi if [[ "${#REMOTE}" == 0 ]]; then - echo -e "\\n ${COL_LIGHT_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support" + echo -e "\\n ${COL_RED}Error: Remote revision could not be obtained, please contact Pi-hole Support" echo -e " Additional debugging output:${COL_NC}" git status exit 1 @@ -103,7 +103,7 @@ GitCheckUpdateAvail() { } main() { - local basicError="\\n ${COL_LIGHT_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}" + local basicError="\\n ${COL_RED}Unable to complete update, please contact Pi-hole Support${COL_NC}" local core_update local web_update local FTL_update @@ -120,7 +120,7 @@ main() { # This is unlikely if ! is_repo "${PI_HOLE_FILES_DIR}" ; then - echo -e "\\n ${COL_LIGHT_RED}Error: Core Pi-hole repo is missing from system!" + echo -e "\\n ${COL_RED}Error: Core Pi-hole repo is missing from system!" echo -e " Please re-run install script from https://pi-hole.net${COL_NC}" exit 1; fi @@ -132,11 +132,11 @@ main() { echo -e " ${INFO} Pi-hole Core:\\t${COL_YELLOW}update available${COL_NC}" else core_update=false - echo -e " ${INFO} Pi-hole Core:\\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} Pi-hole Core:\\t${COL_GREEN}up to date${COL_NC}" fi if ! is_repo "${ADMIN_INTERFACE_DIR}" ; then - echo -e "\\n ${COL_LIGHT_RED}Error: Web Admin repo is missing from system!" + echo -e "\\n ${COL_RED}Error: Web Admin repo is missing from system!" echo -e " Please re-run install script from https://pi-hole.net${COL_NC}" exit 1; fi @@ -146,7 +146,7 @@ main() { echo -e " ${INFO} Web Interface:\\t${COL_YELLOW}update available${COL_NC}" else web_update=false - echo -e " ${INFO} Web Interface:\\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} Web Interface:\\t${COL_GREEN}up to date${COL_NC}" fi local funcOutput @@ -160,17 +160,17 @@ main() { else case $? in 1) - echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_GREEN}up to date${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_GREEN}up to date${COL_NC}" ;; 2) - echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_LIGHT_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch." + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch." ;; 3) - echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, cannot reach download server${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, cannot reach download server${COL_NC}" exit 1 ;; *) - echo -e " ${INFO} FTL:\\t\\t${COL_LIGHT_RED}Something has gone wrong, contact support${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, contact support${COL_NC}" exit 1 esac FTL_update=false @@ -187,7 +187,7 @@ main() { if [[ ! "${ftlBranch}" == "master" && ! "${ftlBranch}" == "development" ]]; then # Notify user that they are on a custom branch which might mean they they are lost # behind if a branch was merged to development and got abandoned - printf " %b %bWarning:%b You are using FTL from a custom branch (%s) and might be missing future releases.\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}" "${ftlBranch}" + printf " %b %bWarning:%b You are using FTL from a custom branch (%s) and might be missing future releases.\\n" "${INFO}" "${COL_RED}" "${COL_NC}" "${ftlBranch}" fi if [[ "${core_update}" == false && "${web_update}" == false && "${FTL_update}" == false ]]; then diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index fca77f99..46bfffb9 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -173,13 +173,11 @@ if [[ -f "${coltable}" ]]; then else # Set these values so the installer can still run in color COL_NC='\e[0m' # No Color - COL_LIGHT_GREEN='\e[1;32m' - COL_LIGHT_RED='\e[1;31m' - TICK="[${COL_LIGHT_GREEN}✓${COL_NC}]" - CROSS="[${COL_LIGHT_RED}✗${COL_NC}]" + COL_GREEN='\e[1;32m' + COL_RED='\e[1;31m' + TICK="[${COL_GREEN}✓${COL_NC}]" + CROSS="[${COL_RED}✗${COL_NC}]" INFO="[i]" - # shellcheck disable=SC2034 - DONE="${COL_LIGHT_GREEN} done!${COL_NC}" OVER="\\r\\033[K" fi @@ -187,13 +185,13 @@ fi # This lets users know that it is a Pi-hole, LLC product show_ascii_berry() { echo -e " - ${COL_LIGHT_GREEN}.;;,. + ${COL_GREEN}.;;,. .ccccc:,. :cccclll:. ..,, :ccccclll. ;ooodc 'ccll:;ll .oooodc .;cll.;;looo:. - ${COL_LIGHT_RED}.. ','. + ${COL_RED}.. ','. .',,,,,,'. .',,,,,,,,,,. .',,,,,,,,,,,,.... @@ -215,7 +213,7 @@ abort() { # remove any leftover build directory that may exist rm -rf /tmp/pihole-meta_* - echo -e "\\n\\n ${COL_LIGHT_RED}Installation was interrupted${COL_NC}\\n" + echo -e "\\n\\n ${COL_RED}Installation was interrupted${COL_NC}\\n" echo -e "Pi-hole's dependencies might be already installed. If you want to remove them you can try to\\n" echo -e "a) run 'pihole uninstall' \\n" echo -e "b) Remove the meta-package 'pihole-meta' manually \\n" @@ -308,7 +306,7 @@ build_dependency_package(){ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf "%b Error: Building pihole-meta.deb failed. %b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf "%b Error: Building pihole-meta.deb failed. %b\\n" "${COL_RED}" "${COL_NC}" return 1 fi @@ -341,7 +339,7 @@ build_dependency_package(){ printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf "%b Error: Building pihole-meta.rpm failed. %b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf "%b Error: Building pihole-meta.rpm failed. %b\\n" "${COL_RED}" "${COL_NC}" return 1 fi @@ -483,7 +481,7 @@ getGitFiles() { printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Update the repo, returning an error message on failure update_repo "${directory}" || { - printf "\\n %b: Could not update local repository. Contact support.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf "\\n %b: Could not update local repository. Contact support.%b\\n" "${COL_RED}" "${COL_NC}" exit 1 } # If it's not a .git repo, @@ -492,7 +490,7 @@ getGitFiles() { printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" # Attempt to make the repository, showing an error on failure make_repo "${directory}" "${remoteRepo}" || { - printf "\\n %bError: Could not update local repository. Contact support.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf "\\n %bError: Could not update local repository. Contact support.%b\\n" "${COL_RED}" "${COL_NC}" exit 1 } fi @@ -807,7 +805,7 @@ setDNS() { result=$? case ${result} in "${DIALOG_CANCEL}" | "${DIALOG_ESC}") - printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -844,7 +842,7 @@ If you want to specify a port other than 53, separate it with a hash.\ result=$? case ${result} in "${DIALOG_CANCEL}" | "${DIALOG_ESC}") - printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -898,7 +896,7 @@ If you want to specify a port other than 53, separate it with a hash.\ DNSSettingsCorrect=False ;; "${DIALOG_ESC}") - printf " %b Escape pressed, exiting installer at DNS Settings%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Escape pressed, exiting installer at DNS Settings%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -949,7 +947,7 @@ setLogging() { ;; "${DIALOG_ESC}") # User pressed - printf " %b Escape pressed, exiting installer at Query Logging choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Escape pressed, exiting installer at Query Logging choice.%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -974,7 +972,7 @@ setPrivacyLevel() { printf " %b Using privacy level: %s\\n" "${INFO}" "${PRIVACY_LEVEL}" ;; "${DIALOG_CANCEL}" | "${DIALOG_ESC}") - printf " %b Cancelled privacy level selection.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Cancelled privacy level selection.%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -1008,7 +1006,7 @@ chooseBlocklists() { ;; "${DIALOG_ESC}") # User pressed - printf " %b Escape pressed, exiting installer at blocklist choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b Escape pressed, exiting installer at blocklist choice.%b\\n" "${COL_RED}" "${COL_NC}" exit 1 ;; esac @@ -1134,7 +1132,7 @@ installScripts() { else # Otherwise, show an error and exit printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf "\\t\\t%bError: Local repo %s not found, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" + printf "\\t\\t%bError: Local repo %s not found, exiting installer%b\\n" "${COL_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" return 1 fi } @@ -1149,7 +1147,7 @@ installConfigs() { # Install empty custom.list file if it does not exist if [[ ! -r "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" ]]; then if ! install -D -T -o pihole -g pihole -m 660 /dev/null "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" &>/dev/null; then - printf " %b Error: Unable to initialize configuration file %s/custom.list\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}/hosts" + printf " %b Error: Unable to initialize configuration file %s/custom.list\\n" "${COL_RED}" "${PI_HOLE_CONFIG_DIR}/hosts" return 1 fi fi @@ -1328,7 +1326,7 @@ update_package_cache() { UPDATE_PKG_CACHE="apt update" fi printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %b Error: Unable to update package cache. Please try \"%s\"%b\\n" "${COL_LIGHT_RED}" "sudo ${UPDATE_PKG_CACHE}" "${COL_NC}" + printf " %b Error: Unable to update package cache. Please try \"%s\"%b\\n" "${COL_RED}" "sudo ${UPDATE_PKG_CACHE}" "${COL_NC}" return 1 fi } @@ -1346,7 +1344,7 @@ notify_package_updates_available() { printf "%b %b %s... up to date!\\n\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s... %s updates available\\n" "${OVER}" "${TICK}" "${str}" "${updatesToInstall}" - printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" + printf " %b %bIt is recommended to update your OS after installing the Pi-hole!%b\\n\\n" "${INFO}" "${COL_GREEN}" "${COL_NC}" fi } @@ -1363,11 +1361,11 @@ install_dependent_packages() { rm /tmp/pihole-meta.deb else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %b Error: Unable to install Pi-hole dependency package.\\n" "${COL_LIGHT_RED}" + printf " %b Error: Unable to install Pi-hole dependency package.\\n" "${COL_RED}" return 1 fi else - printf " %b Error: Unable to find Pi-hole dependency package.\\n" "${COL_LIGHT_RED}" + printf " %b Error: Unable to find Pi-hole dependency package.\\n" "${COL_RED}" return 1 fi # Install Fedora/CentOS packages @@ -1378,11 +1376,11 @@ install_dependent_packages() { rm /tmp/pihole-meta.rpm else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %b Error: Unable to install Pi-hole dependency package.\\n" "${COL_LIGHT_RED}" + printf " %b Error: Unable to install Pi-hole dependency package.\\n" "${COL_RED}" return 1 fi else - printf " %b Error: Unable to find Pi-hole dependency package.\\n" "${COL_LIGHT_RED}" + printf " %b Error: Unable to find Pi-hole dependency package.\\n" "${COL_RED}" return 1 fi @@ -1611,13 +1609,13 @@ checkSelinux() { if [[ "${SELINUX_ENFORCING}" -eq 1 ]] && [[ -z "${PIHOLE_SELINUX}" ]]; then printf " Pi-hole does not provide an SELinux policy as the required changes modify the security of your system.\\n" printf " Please refer to https://wiki.centos.org/HowTos/SELinux if SELinux is required for your deployment.\\n" - printf " This check can be skipped by setting the environment variable %bPIHOLE_SELINUX%b to %btrue%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" "${COL_LIGHT_RED}" "${COL_NC}" + printf " This check can be skipped by setting the environment variable %bPIHOLE_SELINUX%b to %btrue%b\\n" "${COL_RED}" "${COL_NC}" "${COL_RED}" "${COL_NC}" printf " e.g: export PIHOLE_SELINUX=true\\n" printf " By setting this variable to true you acknowledge there may be issues with Pi-hole during or after the install\\n" - printf "\\n %bSELinux Enforcing detected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + printf "\\n %bSELinux Enforcing detected, exiting installer%b\\n" "${COL_RED}" "${COL_NC}" exit 1 elif [[ "${SELINUX_ENFORCING}" -eq 1 ]] && [[ -n "${PIHOLE_SELINUX}" ]]; then - printf " %b %bSELinux Enforcing detected%b. PIHOLE_SELINUX env variable set - installer will continue\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b %bSELinux Enforcing detected%b. PIHOLE_SELINUX env variable set - installer will continue\\n" "${INFO}" "${COL_RED}" "${COL_NC}" fi } @@ -1715,13 +1713,13 @@ clone_or_reset_repos() { # Reset the Core repo resetRepo ${PI_HOLE_LOCAL_REPO} || { - printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" + printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" exit 1 } # Reset the Web repo resetRepo ${webInterfaceDir} || { - printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceDir}" "${COL_NC}" + printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_RED}" "${webInterfaceDir}" "${COL_NC}" exit 1 } # Otherwise, a fresh installation is happening @@ -1729,13 +1727,13 @@ clone_or_reset_repos() { # so get git files for Core getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || { - printf " %b Unable to clone %s into %s, unable to continue%b\\n" "${COL_LIGHT_RED}" "${piholeGitUrl}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" + printf " %b Unable to clone %s into %s, unable to continue%b\\n" "${COL_RED}" "${piholeGitUrl}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}" exit 1 } # get the Web git files getGitFiles ${webInterfaceDir} ${webInterfaceGitUrl} || { - printf " %b Unable to clone %s into ${webInterfaceDir}, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceGitUrl}" "${COL_NC}" + printf " %b Unable to clone %s into ${webInterfaceDir}, exiting installer%b\\n" "${COL_RED}" "${webInterfaceGitUrl}" "${COL_NC}" exit 1 } fi @@ -1811,7 +1809,7 @@ FTLinstall() { return 1 } printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %b Error: Download of %s/%s failed (checksum error)%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" + printf " %b Error: Download of %s/%s failed (checksum error)%b\\n" "${COL_RED}" "${url}" "${binary}" "${COL_NC}" # Remove temp dir remove_dir "${tempdir}" @@ -1825,7 +1823,7 @@ FTLinstall() { } printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" # The URL could not be found - printf " %b Error: URL %s/%s not found%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" + printf " %b Error: URL %s/%s not found%b\\n" "${COL_RED}" "${url}" "${binary}" "${COL_NC}" # Remove temp dir remove_dir "${tempdir}" @@ -1902,7 +1900,7 @@ get_binary_name() { # Something else - we try to use 32bit executable and warn the user if [[ ! "${machine}" == "i686" ]]; then printf "%b %b %s...\\n" "${OVER}" "${CROSS}" "${str}" - printf " %b %bNot able to detect architecture (unknown: %s), trying x86 (32bit) executable%b\\n" "${INFO}" "${COL_LIGHT_RED}" "${machine}" "${COL_NC}" + printf " %b %bNot able to detect architecture (unknown: %s), trying x86 (32bit) executable%b\\n" "${INFO}" "${COL_RED}" "${machine}" "${COL_NC}" printf " %b Contact Pi-hole Support if you experience issues (e.g: FTL not running)\\n" "${INFO}" else printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}" @@ -1945,7 +1943,7 @@ FTLcheckUpdate() { status=$? if [ "${status}" -eq 1 ]; then printf " %b Branch \"%s\" is not available.\\n" "${INFO}" "${ftlBranch}" - printf " %b Use %bpihole checkout ftl [branchname]%b to switch to a valid branch.\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" + printf " %b Use %bpihole checkout ftl [branchname]%b to switch to a valid branch.\\n" "${INFO}" "${COL_GREEN}" "${COL_NC}" elif [ "${status}" -eq 2 ]; then printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}" return 3 @@ -2158,7 +2156,7 @@ main() { else # Otherwise, they do not have enough privileges, so let the user know printf " %b %s\\n" "${INFO}" "${str}" - printf " %b %bScript called with non-root privileges%b\\n" "${INFO}" "${COL_LIGHT_RED}" "${COL_NC}" + printf " %b %bScript called with non-root privileges%b\\n" "${INFO}" "${COL_RED}" "${COL_NC}" printf " The Pi-hole requires elevated privileges to install and run\\n" printf " Please check the installer for any concerns regarding this requirement\\n" printf " Make sure to download this script from a trusted source\\n\\n" @@ -2182,7 +2180,7 @@ main() { # Otherwise, tell the user they need to run the script as root, and bail printf "%b %b Sudo utility check\\n" "${OVER}" "${CROSS}" printf " %b Sudo is needed for the Web Interface to run pihole commands\\n\\n" "${INFO}" - printf " %b %bPlease re-run this installer as root${COL_NC}\\n" "${INFO}" "${COL_LIGHT_RED}" + printf " %b %bPlease re-run this installer as root${COL_NC}\\n" "${INFO}" "${COL_RED}" exit 1 fi fi @@ -2367,7 +2365,7 @@ main() { printf " %b If you have not done so already, the above IP should be set to static.\\n" "${INFO}" printf " %b View the web interface at http://pi.hole:${WEBPORT}/admin or http://%s/admin\\n\\n" "${INFO}" "${IPV4_ADDRESS%/*}:${WEBPORT}" - printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${pw}" "${COL_NC}" + printf " %b Web Interface password: %b%s%b\\n" "${INFO}" "${COL_GREEN}" "${pw}" "${COL_NC}" printf " %b This can be changed using 'pihole setpassword'\\n\\n" "${INFO}" printf " %b To allow your user to use all CLI functions without authentication, refer to\\n" "${INFO}" printf " our documentation at: https://docs.pi-hole.net/main/post-install/\\n\\n" @@ -2392,7 +2390,7 @@ main() { # Display where the log file is printf "\\n %b The install log is located at: %s\\n" "${INFO}" "${installLogLoc}" - printf " %b %b%s complete! %b\\n" "${TICK}" "${COL_LIGHT_GREEN}" "${INSTALL_TYPE}" "${COL_NC}" + printf " %b %b%s complete! %b\\n" "${TICK}" "${COL_GREEN}" "${INSTALL_TYPE}" "${COL_NC}" if [[ "${INSTALL_TYPE}" == "Update" ]]; then printf "\\n" diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index a158e595..e8dec36a 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -17,10 +17,10 @@ ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfig readonly ADMIN_INTERFACE_DIR while true; do - read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer + read -rp " ${QST} Are you sure you would like to remove ${COL_BOLD}Pi-hole${COL_NC}? [y/N] " answer case ${answer} in [Yy]* ) break;; - * ) echo -e "${OVER} ${COL_LIGHT_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;; + * ) echo -e "${OVER} ${COL_GREEN}Uninstall has been canceled${COL_NC}"; exit 0;; esac done @@ -150,11 +150,11 @@ removePiholeFiles() { echo -e "\\n We're sorry to see you go, but thanks for checking out Pi-hole! If you need help, reach out to us on GitHub, Discourse, Reddit or Twitter - Reinstall at any time: ${COL_WHITE}curl -sSL https://install.pi-hole.net | bash${COL_NC} + Reinstall at any time: ${COL_BOLD}curl -sSL https://install.pi-hole.net | bash${COL_NC} - ${COL_LIGHT_RED}Please reset the DNS on your router/clients to restore internet connectivity${COL_NC} + ${COL_RED}Please reset the DNS on your router/clients to restore internet connectivity${COL_NC} ${INFO} Pi-hole's meta package has been removed, use the 'autoremove' function from your package manager to remove unused dependencies${COL_NC} - ${COL_LIGHT_GREEN}Uninstallation Complete! ${COL_NC}" + ${COL_GREEN}Uninstallation Complete! ${COL_NC}" } ######### SCRIPT ########### diff --git a/gravity.sh b/gravity.sh index 16e459c6..fcbce46b 100755 --- a/gravity.sh +++ b/gravity.sh @@ -50,7 +50,7 @@ etag_support=false # Check gravity temp directory if [ ! -d "${GRAVITY_TMPDIR}" ] || [ ! -w "${GRAVITY_TMPDIR}" ]; then - echo -e " ${COL_LIGHT_RED}Gravity temporary directory does not exist or is not a writeable directory, falling back to /tmp. ${COL_NC}" + echo -e " ${COL_RED}Gravity temporary directory does not exist or is not a writeable directory, falling back to /tmp. ${COL_NC}" GRAVITY_TMPDIR="/tmp" fi @@ -821,13 +821,13 @@ gravity_DownloadBlocklistFromUrl() { if [[ "${done}" != "true" ]]; then # Determine if cached list has read permission if [[ -r "${saveLocation}" ]]; then - echo -e " ${CROSS} List download failed: ${COL_LIGHT_GREEN}using previously cached list${COL_NC}" + echo -e " ${CROSS} List download failed: ${COL_GREEN}using previously cached list${COL_NC}" # Set list status to "download-failed/cached" database_adlist_status "${adlistID}" "3" # Add domains to database table file pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" else - echo -e " ${CROSS} List download failed: ${COL_LIGHT_RED}no cached list available${COL_NC}" + echo -e " ${CROSS} List download failed: ${COL_RED}no cached list available${COL_NC}" # Manually reset these two numbers because we do not call parseList here database_adlist_number "${adlistID}" 0 0 database_adlist_status "${adlistID}" "4" @@ -864,7 +864,7 @@ gravity_ShowCount() { # Trap Ctrl-C gravity_Trap() { - trap '{ echo -e "\\n\\n ${INFO} ${COL_LIGHT_RED}User-abort detected${COL_NC}"; gravity_Cleanup "error"; }' INT + trap '{ echo -e "\\n\\n ${INFO} ${COL_RED}User-abort detected${COL_NC}"; gravity_Cleanup "error"; }' INT } # Clean up after Gravity upon exit or cancellation diff --git a/pihole b/pihole index 1dfab754..fde9ae82 100755 --- a/pihole +++ b/pihole @@ -238,7 +238,7 @@ Time: fi if [[ ${error} == true ]];then - echo -e " ${COL_LIGHT_RED}Unknown format for blocking timer!${COL_NC}" + echo -e " ${COL_RED}Unknown format for blocking timer!${COL_NC}" echo -e " Try 'pihole disable --help' for more information." exit 1 fi @@ -293,7 +293,7 @@ Options: echo -e " ${INFO} Enabling logging..." local str="Logging has been enabled!" else - echo -e " ${COL_LIGHT_RED}Invalid option${COL_NC} + echo -e " ${COL_RED}Invalid option${COL_NC} Try 'pihole logging --help' for more information." exit 1 fi From daec6f8c02ef8871a84f8e1926d4f6cb9b19a525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 24 Jun 2025 19:03:24 +0200 Subject: [PATCH 140/259] Set color codes when FORCE_COLOR is true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/COL_TABLE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/COL_TABLE b/advanced/Scripts/COL_TABLE index 0c6981c1..7d339c0e 100644 --- a/advanced/Scripts/COL_TABLE +++ b/advanced/Scripts/COL_TABLE @@ -2,7 +2,8 @@ # shellcheck disable=SC2034 # Disable warning about unused variables # Determine if terminal is capable of showing colors -if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then +# When COL_TABLE is sourced via gravity invoked by FTL, FORCE_COLOR is set to true +if { [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; } || [ "${FORCE_COLOR}" ]; then # Bold and underline may not show up on all clients # If something MUST be emphasized, use both COL_BOLD='' From 19d59434408f0d3ce2f86a0cb4c824468c16d3c6 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Wed, 25 Jun 2025 05:10:12 +1000 Subject: [PATCH 141/259] piholeDebug - Get default route robustly Determine address and interface of default route by preceeding 'via' and 'dev' fields in json output instead of plain text field position. Log if unable to determine default gateway Signed-off-by: Rob Gill --- advanced/Scripts/piholeDebug.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 741ff2f4..e4bd1191 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -497,16 +497,25 @@ ping_gateway() { ping_ipv4_or_ipv6 "${protocol}" # Check if we are using IPv4 or IPv6 # Find the default gateways using IPv4 or IPv6 - local gateway gateway_addr gateway_iface + local gateway gateway_addr gateway_iface default_route log_write "${INFO} Default IPv${protocol} gateway(s):" - while IFS= read -r gateway; do - log_write " $(cut -d ' ' -f 3 <<< "${gateway}")%$(cut -d ' ' -f 5 <<< "${gateway}")" - done < <(ip -"${protocol}" route | grep default) + while IFS= read -r default_route; do + gateway_addr=$(jq -r '.gateway' <<< "${default_route}") + gateway_iface=$(jq -r '.dev' <<< "${default_route}") + log_write " ${gateway_addr}%${gateway_iface}" + done < <(ip -j -"${protocol}" route | jq -c '.[] | select(.dst == "default")') + + # Find the first default route + default_route=$(ip -j -"${protocol}" route show default) + if echo "$default_route" | grep 'gateway' | grep -q 'dev'; then + gateway_addr=$(echo "$default_route" | jq -r -c '.[0].gateway') + gateway_iface=$(echo "$default_route" | jq -r -c '.[0].dev') + else + log_write " Unable to determine gateway address for IPv${protocol}" + fi - gateway_addr=$(ip -"${protocol}" route | grep default | cut -d ' ' -f 3 | head -n 1) - gateway_iface=$(ip -"${protocol}" route | grep default | cut -d ' ' -f 5 | head -n 1) # If there was at least one gateway if [ -n "${gateway_addr}" ]; then # Append the interface to the gateway address if it is a link-local address From 3a35e589f2ead2aa85c146c17f7246401248b602 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 26 Jun 2025 00:40:37 +0200 Subject: [PATCH 142/259] installer: exit if FTL update check fails The return code of `FTLdetect()` is used in the installer to know whether FTL has been installed or not. The function however returns an error only, if the download of FTL fails, not if checking for a latest version/update of FTL fails. This way, installs and rapairs can continue without or with ourdated FTL until `pihole-FTL migrate v6`, which hangs endlessly, if it is a v5 FTL. This commit handles the return code in `FTLdetect()`, and lets it return true only if FTL download succeeded, or if the update check succeeded and FTL is up-to-date. Else, it could neither be repaired, nor installed, and the error message should give a hint what went wrong, hence exit. `FTLdetect()` is not called by any other script, hence this change has no surprising effect elsewhere. Additionally, a syntax error in the `FTLcheckUpdate()` function itself is fixed, which masks the `check_download_exists()` return code, hence always leads to error code 4, if the FTL branch is not `master`. Signed-off-by: MichaIng --- automated install/basic-install.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 279dc1d1..afb9dc50 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1940,8 +1940,8 @@ FTLcheckUpdate() { path="${ftlBranch}/${binary}" # Check whether or not the binary for this FTL branch actually exists. If not, then there is no update! + local status if ! check_download_exists "$path"; then - local status status=$? if [ "${status}" -eq 1 ]; then printf " %b Branch \"%s\" is not available.\\n" "${INFO}" "${ftlBranch}" @@ -2031,6 +2031,11 @@ FTLdetect() { if FTLcheckUpdate "${1}"; then FTLinstall "${1}" || return 1 + else + case $? in + 1) :;; # FTL is up-to-date + *) exit 1;; # 404 (2), other HTTP or curl error (3), unknown (4) + esac fi } From f24fc9573a9a77fb18b389262e70c92364b13781 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sun, 29 Jun 2025 06:45:02 +1000 Subject: [PATCH 143/259] taillog Prevent grep interpeting search term as an option Adds '--' indicating end of options before the user provided search pattern. Signed-off-by: Rob Gill --- pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pihole b/pihole index fde9ae82..7df4aefc 100755 --- a/pihole +++ b/pihole @@ -396,7 +396,7 @@ tailFunc() { # Color blocklist/denylist/wildcard entries as red # Color A/AAAA/DHCP strings as white # Color everything else as gray - tail -f $LOGFILE | grep --line-buffered "${1}" | sed -E \ + tail -f $LOGFILE | grep --line-buffered -- "${1}" | sed -E \ -e "s,($(date +'%b %d ')| dnsmasq\[[0-9]*\]),,g" \ -e "s,(.*(denied |gravity blocked ).*),${COL_RED}&${COL_NC}," \ -e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \ From 2f9fa80d7a9dc9d7452c0177b2a897ba0c11d455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 1 Jul 2025 13:34:55 +0200 Subject: [PATCH 144/259] Update python version used in test to 3.13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac496406..c2e8f951 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,10 +80,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v4.2.2 - - name: Set up Python 3.10 + - name: Set up Python uses: actions/setup-python@v5.6.0 with: - python-version: "3.10" + python-version: "3.13" - name: Install wheel run: pip install wheel From c5c5116e530c2a61aadfc34d7b81d3adf0efe03d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 10:28:30 +0000 Subject: [PATCH 145/259] Bump pytest-xdist from 3.7.0 to 3.8.0 in /test Bumps [pytest-xdist](https://github.com/pytest-dev/pytest-xdist) from 3.7.0 to 3.8.0. - [Release notes](https://github.com/pytest-dev/pytest-xdist/releases) - [Changelog](https://github.com/pytest-dev/pytest-xdist/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-xdist/compare/v3.7.0...v3.8.0) --- updated-dependencies: - dependency-name: pytest-xdist dependency-version: 3.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 6553def2..92f78840 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,6 +1,6 @@ pyyaml == 6.0.2 pytest == 8.4.1 -pytest-xdist == 3.7.0 +pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 tox == 4.27.0 pytest-clarity == 1.0.1 From 6db6c68a4e95d63e92f79b4e3093384c8b2ef4f6 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Thu, 10 Jul 2025 21:34:35 +0200 Subject: [PATCH 146/259] update: abort if FTL branch does not exist Currently, if the FTL update check returns 404, hence the FTL branch does not seem to exist, an error message is printed, but the update continues, only the FTL update is skipped. This can lead to setups with v5 FTL and v6 core/web, failing at config migration, where FTL is invoked with a v6-only command. With this change, the update aborts immediately if the FTL branch is invalid, like it does in case of other FTL update check errors (other HTTP error codes than 404 or other curl errors). Hence it continues only if FTL is up-to-date already, or a new version from the given branch has been found. Signed-off-by: MichaIng --- advanced/Scripts/update.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 5fb7de18..4e0d973e 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -164,6 +164,7 @@ main() { ;; 2) echo -e " ${INFO} FTL:\\t\\t${COL_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch." + exit 1 ;; 3) echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, cannot reach download server${COL_NC}" From 3f7f6f02948eb37751dcd7b29eca953ff2bc2804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 27 Feb 2025 12:00:25 +0100 Subject: [PATCH 147/259] Allow uses to skip binary check and installing FTL in case the use a self-compiled binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 34 ++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 86e74730..8a81deac 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -156,6 +156,7 @@ EOM # The runUnattended flag is one example of this repair=false runUnattended=false +PIHOLE_SKIP_FTL_CHECK=false # Check arguments for the undocumented flags for var in "$@"; do case "$var" in @@ -2224,12 +2225,16 @@ main() { # Check if there is a usable FTL binary available on this architecture - do # this early on as FTL is a hard dependency for Pi-hole - local funcOutput - funcOutput=$(get_binary_name) #Store output of get_binary_name here - # Abort early if this processor is not supported (get_binary_name returns empty string) - if [[ "${funcOutput}" == "" ]]; then - printf " %b Upgrade/install aborted\\n" "${CROSS}" "${DISTRO_NAME}" - exit 1 + # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture + if [ ! "${PIHOLE_SKIP_FTL_CHECK}" = true ]; then + # Get the binary name for the current architecture + local funcOutput + funcOutput=$(get_binary_name) #Store output of get_binary_name here + # Abort early if this processor is not supported (get_binary_name returns empty string) + if [[ "${funcOutput}" == "" ]]; then + printf " %b Upgrade/install aborted\\n" "${CROSS}" "${DISTRO_NAME}" + exit 1 + fi fi if [[ "${fresh_install}" == false ]]; then @@ -2271,13 +2276,16 @@ main() { create_pihole_user # Download and install FTL - local binary - binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) - local theRest - theRest="${funcOutput%pihole-FTL*}" # Print the rest of get_binary_name's output to display (cut out from first instance of "pihole-FTL") - if ! FTLdetect "${binary}" "${theRest}"; then - printf " %b FTL Engine not installed\\n" "${CROSS}" - exit 1 + # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture + if [ ! "${PIHOLE_SKIP_FTL_CHECK}" = true ]; then + local binary + binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) + local theRest + theRest="${funcOutput%pihole-FTL*}" # Print the rest of get_binary_name's output to display (cut out from first instance of "pihole-FTL") + if ! FTLdetect "${binary}" "${theRest}"; then + printf " %b FTL Engine not installed\\n" "${CROSS}" + exit 1 + fi fi # Install and log everything to a file From f67a8e51108e2c83019230688bfb141009524747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 3 Mar 2025 22:02:25 +0100 Subject: [PATCH 148/259] Only set PIHOLE_SKIP_FTL_CHECK if not already set by env variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 8a81deac..50123739 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -156,7 +156,9 @@ EOM # The runUnattended flag is one example of this repair=false runUnattended=false -PIHOLE_SKIP_FTL_CHECK=false +if [ -z "$PIHOLE_SKIP_FTL_CHECK" ]; then + PIHOLE_SKIP_FTL_CHECK=false +fi # Check arguments for the undocumented flags for var in "$@"; do case "$var" in From f3e04117f6fc1cb01a23adc1933cfde17df6c708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 3 Mar 2025 22:19:32 +0100 Subject: [PATCH 149/259] Let users know we skipped the FTL checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: davygravy Signed-off-by: Christian König --- automated install/basic-install.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 50123739..4d475399 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2228,7 +2228,7 @@ main() { # Check if there is a usable FTL binary available on this architecture - do # this early on as FTL is a hard dependency for Pi-hole # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture - if [ ! "${PIHOLE_SKIP_FTL_CHECK}" = true ]; then + if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then # Get the binary name for the current architecture local funcOutput funcOutput=$(get_binary_name) #Store output of get_binary_name here @@ -2237,6 +2237,8 @@ main() { printf " %b Upgrade/install aborted\\n" "${CROSS}" "${DISTRO_NAME}" exit 1 fi + else + printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping architecture check%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" fi if [[ "${fresh_install}" == false ]]; then @@ -2279,7 +2281,7 @@ main() { # Download and install FTL # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture - if [ ! "${PIHOLE_SKIP_FTL_CHECK}" = true ]; then + if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then local binary binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) local theRest @@ -2288,6 +2290,8 @@ main() { printf " %b FTL Engine not installed\\n" "${CROSS}" exit 1 fi + else + printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping FTL binary installation%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" fi # Install and log everything to a file From 463086ef23e7e4c0fd1d7b182e15a913565a1700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 8 Mar 2025 14:38:00 +0100 Subject: [PATCH 150/259] Skip FTL update check if $PIHOLE_SKIP_FTL_CHECK is set to true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 52 +++++++++++++++++------------- automated install/basic-install.sh | 4 +-- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index 4e0d973e..eb9e7829 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -149,31 +149,37 @@ main() { echo -e " ${INFO} Web Interface:\\t${COL_GREEN}up to date${COL_NC}" fi - local funcOutput - funcOutput=$(get_binary_name) #Store output of get_binary_name here - local binary - binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) + # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture + if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then + local funcOutput + funcOutput=$(get_binary_name) #Store output of get_binary_name here + local binary + binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) - if FTLcheckUpdate "${binary}" &>/dev/null; then - FTL_update=true - echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}" + if FTLcheckUpdate "${binary}" &>/dev/null; then + FTL_update=true + echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}update available${COL_NC}" + else + case $? in + 1) + echo -e " ${INFO} FTL:\\t\\t${COL_GREEN}up to date${COL_NC}" + ;; + 2) + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch." + exit 1 + ;; + 3) + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, cannot reach download server${COL_NC}" + exit 1 + ;; + *) + echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, contact support${COL_NC}" + exit 1 + esac + FTL_update=false + fi else - case $? in - 1) - echo -e " ${INFO} FTL:\\t\\t${COL_GREEN}up to date${COL_NC}" - ;; - 2) - echo -e " ${INFO} FTL:\\t\\t${COL_RED}Branch is not available.${COL_NC}\\n\\t\\t\\tUse ${COL_GREEN}pihole checkout ftl [branchname]${COL_NC} to switch to a valid branch." - exit 1 - ;; - 3) - echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, cannot reach download server${COL_NC}" - exit 1 - ;; - *) - echo -e " ${INFO} FTL:\\t\\t${COL_RED}Something has gone wrong, contact support${COL_NC}" - exit 1 - esac + echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}PIHOLE_SKIP_FTL_CHECK env variable set to true - update check skipped${COL_NC}" FTL_update=false fi diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 4d475399..0ab163ae 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2238,7 +2238,7 @@ main() { exit 1 fi else - printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping architecture check%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" + printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping architecture check%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" fi if [[ "${fresh_install}" == false ]]; then @@ -2291,7 +2291,7 @@ main() { exit 1 fi else - printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping FTL binary installation%b\\n" "${INFO}" "${COL_LIGHT_GREEN}" "${COL_NC}" + printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping FTL binary installation%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" fi # Install and log everything to a file From 3977a312f01687bcc649365297c6a0a3ba402317 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 11 Jul 2025 21:01:01 +0100 Subject: [PATCH 151/259] Update release.yml Signed-off-by: Adam Warner --- .github/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/release.yml b/.github/release.yml index 2e8776e9..e12a3ff7 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -2,6 +2,7 @@ changelog: exclude: labels: - internal + - dependencies authors: - dependabot - github-actions From ea8272d7d4a59bb43373ff75e7a640e54b2cd134 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 12 Jul 2025 14:25:17 +1000 Subject: [PATCH 152/259] speed up pihole --query Count list and gravity matches using jq in a single step. Use jq's map to simplify list processing, eliminating intermediate jsons. Eliminate while loop for each lists's final output and formatting. Signed-off-by: Rob Gill --- advanced/Scripts/query.sh | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index 18c018dc..fe018060 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -37,19 +37,16 @@ Options: } GenerateOutput() { - local data gravity_data lists_data num_gravity num_lists search_type_str - local gravity_data_csv lists_data_csv line current_domain url type color + local counts data num_gravity num_lists search_type_str + local gravity_data_csv lists_data_csv line url type color data="${1}" - # construct a new json for the list results where each object contains the domain and the related type - lists_data=$(printf %s "${data}" | jq '.search.domains | [.[] | {domain: .domain, type: .type}]') - - # construct a new json for the gravity results where each object contains the adlist URL and the related domains - gravity_data=$(printf %s "${data}" | jq '.search.gravity | group_by(.address,.type) | map({ address: (.[0].address), type: (.[0].type), domains: [.[] | .domain] })') - - # number of objects in each json - num_gravity=$(printf %s "${gravity_data}" | jq length) - num_lists=$(printf %s "${lists_data}" | jq length) + # Get count of list and gravity matches + # Use JQ to count number of entries in lists and gravity + # (output is number of list matches then number of gravity matches) + counts=$(printf %s "${data}" | jq --raw-output '(.search.domains | length), (.search.gravity | group_by(.address,.type) | length)') + num_lists=$(echo "$counts" | sed -n '1p') + num_gravity=$(echo "$counts" | sed -n '2p') if [ "${partial}" = true ]; then search_type_str="partially" @@ -62,7 +59,7 @@ GenerateOutput() { if [ "${num_lists}" -gt 0 ]; then # Convert the data to a csv, each line is a "domain,type" string # not using jq's @csv here as it quotes each value individually - lists_data_csv=$(printf %s "${lists_data}" | jq --raw-output '.[] | [.domain, .type] | join(",")') + lists_data_csv=$(printf %s "${data}" | jq --raw-output '.search.domains | map([.domain, .type] | join(",")) | join("\n")') # Generate output for each csv line, separating line in a domain and type substring at the ',' echo "${lists_data_csv}" | while read -r line; do @@ -73,9 +70,9 @@ GenerateOutput() { # Results from gravity printf "%s\n\n" "Found ${num_gravity} adlists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'." if [ "${num_gravity}" -gt 0 ]; then - # Convert the data to a csv, each line is a "URL,domain,domain,...." string + # Convert the data to a csv, each line is a "URL,type,domain,domain,...." string # not using jq's @csv here as it quotes each value individually - gravity_data_csv=$(printf %s "${gravity_data}" | jq --raw-output '.[] | [.address, .type, .domains[]] | join(",")') + gravity_data_csv=$(printf %s "${data}" | jq --raw-output '.search.gravity | group_by(.address,.type) | map([.[0].address, .[0].type, (.[] | .domain)] | join(",")) | join("\n")') # Generate line-by-line output for each csv line echo "${gravity_data_csv}" | while read -r line; do @@ -97,15 +94,8 @@ GenerateOutput() { # cut off type, leaving "domain,domain,...." line=${line#*,} - # print each domain and remove it from the string until nothing is left - while [ ${#line} -gt 0 ]; do - current_domain=${line%%,*} - printf ' - %s\n' "${COL_GREEN}${current_domain}${COL_NC}" - # we need to remove the current_domain and the comma in two steps because - # the last domain won't have a trailing comma and the while loop wouldn't exit - line=${line#"${current_domain}"} - line=${line#,} - done + # Replace commas with newlines and format output + echo "${line}" | sed 's/,/\n/g' | sed "s/^/ - ${COL_GREEN}/" | sed "s/$/${COL_NC}/" printf "\n\n" done fi From 05ad3d71556f209d86c68430e3c343839b5f50d0 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 12 Jul 2025 22:25:22 +0000 Subject: [PATCH 153/259] Update advanced/Scripts/query.sh Co-authored-by: yubiuser Signed-off-by: Rob Gill --- advanced/Scripts/query.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/query.sh b/advanced/Scripts/query.sh index fe018060..d0dfd6e9 100755 --- a/advanced/Scripts/query.sh +++ b/advanced/Scripts/query.sh @@ -68,7 +68,7 @@ GenerateOutput() { fi # Results from gravity - printf "%s\n\n" "Found ${num_gravity} adlists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'." + printf "%s\n\n" "Found ${num_gravity} lists ${search_type_str} matching '${COL_BLUE}${domain}${COL_NC}'." if [ "${num_gravity}" -gt 0 ]; then # Convert the data to a csv, each line is a "URL,type,domain,domain,...." string # not using jq's @csv here as it quotes each value individually From 86bdae0076edf3a96a41ade11bc0675fa988e45a Mon Sep 17 00:00:00 2001 From: deHakkelaar Date: Sun, 13 Jul 2025 11:05:58 +0200 Subject: [PATCH 154/259] Update basic-install.sh Added comments --- automated install/basic-install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index dfecda9c..3932fb59 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -577,6 +577,9 @@ Do you wish to continue with an IPv6-only installation?\\n\\n" \ # Get available interfaces that are UP get_available_interfaces() { # There may be more than one so it's all stored in a variable + # The ip command list all interfaces that are in the up state + # The awk command filters out any interfaces that have the LOOPBACK flag set + # while using the characters ": " or "@" as a field separator for awk availableInterfaces=$(ip --oneline link show up | awk -F ': |@' '!/<.*LOOPBACK.*>/ {print $2}') } From 0187087da0624e5e1dbbe8805b7802a4304a9ea0 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Mon, 14 Jul 2025 05:44:46 +1000 Subject: [PATCH 155/259] Speed up pihole --api Get session authentication information via single jq operation, setting defaults if no data returned. Simplify jq test for valid JSON data Signed-off-by: Rob Gill --- advanced/Scripts/api.sh | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index e5eacd41..7ce79db1 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -183,13 +183,20 @@ Authentication() { echo "No response from FTL server. Please check connectivity" exit 1 fi - # obtain validity, session ID and sessionMessage from session response - validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) - SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 2>/dev/null) - sessionMessage=$(echo "${sessionResponse}"| jq --raw-output .session.message 2>/dev/null) - # obtain the error message from the session response - sessionError=$(echo "${sessionResponse}"| jq --raw-output .error.message 2>/dev/null) + # obtain validity, session ID, sessionMessage and error message from + # session response, apply default values if none returned + result=$(echo "${sessionResponse}" | jq -r ' + (.session.valid // false), + (.session.sid // null), + (.session.message // null), + (.error.message // null) + ' 2>/dev/null) + + validSession=$(echo "${result}" | sed -n '1p') + SID=$(echo "${result}" | sed -n '2p') + sessionMessage=$(echo "${result}" | sed -n '3p') + sessionError=$(echo "${result}" | sed -n '4p') if [ "${1}" = "verbose" ]; then if [ "${validSession}" = true ]; then @@ -353,12 +360,9 @@ apiFunc() { if [ "${verbosity}" = "verbose" ]; then echo "Data:" fi - - if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then - echo "${data}" | jq . - else - echo "${data}" - fi + # Attempt to print the data with jq, if it is not valid JSON, or not installed + # then print the plain text. + echo "${data}" | jq . 2>/dev/null || echo "${data}" # Delete the session LogoutAPI "${verbosity}" From 71501e15e50041d441f49852b3b06304efae971a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 13 Jul 2025 22:16:40 +0200 Subject: [PATCH 156/259] Re-order authentication errors in verbose mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/api.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index e5eacd41..d946b559 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -150,7 +150,6 @@ LoginAPI() { # Try to login again until the session is valid while [ ! "${validSession}" = true ] ; do - echo "Authentication failed. Please enter your Pi-hole password" # Print the error message if there is one if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then @@ -161,6 +160,14 @@ LoginAPI() { echo "Error: ${sessionMessage}" fi + if [ "${1}" = "verbose" ]; then + # If we are not in verbose mode, no need to print the error message again + echo "Please enter your Pi-hole password" + else + + echo "Authentication failed. Please enter your Pi-hole password" + fi + # secretly read the password secretRead; printf '\n' From e231107e811e31a013a870826b3231683d150f42 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:15:19 +0200 Subject: [PATCH 157/259] Remove netcat from the list of dependencies Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- automated install/basic-install.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index ac467dda..5c4a84c0 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -116,11 +116,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,netcat-openbsd,procps,psmisc,sudo,unzip +Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,procps,psmisc,sudo,unzip Section: contrib/metapackages Priority: optional EOM @@ -130,12 +130,12 @@ EOM PIHOLE_META_PACKAGE_CONTROL_RPM=$( cat < Date: Mon, 14 Jul 2025 21:38:59 +0100 Subject: [PATCH 158/259] Allow non-root access for updateGravity command Signed-off-by: Adam Warner --- pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pihole b/pihole index c1566ed7..ba4fa19d 100755 --- a/pihole +++ b/pihole @@ -552,7 +552,7 @@ case "${1}" in "enable" ) need_root=0;; "disable" ) need_root=0;; "-d" | "debug" ) ;; - "-g" | "updateGravity" ) ;; + "-g" | "updateGravity" ) need_root=0;; "reloaddns" ) ;; "reloadlists" ) ;; "setpassword" ) ;; From 1bef0415dbb76c0db6e4ec1dd324392cac230077 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 14 Jul 2025 22:02:02 +0100 Subject: [PATCH 159/259] bare minimum first past fix for `pihoe api` command not working due to attempting to re-set readony variabes PI_HOE_SCRIPT_DIR and utisfie. Can't compain about them being readony if they're.. not. Signed-off-by: Adam Warner --- pihole | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pihole b/pihole index c1566ed7..9688e9e9 100755 --- a/pihole +++ b/pihole @@ -9,7 +9,7 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" +PI_HOLE_SCRIPT_DIR="/opt/pihole" # PI_HOLE_BIN_DIR is not readonly here because in some functions (checkout), # they might get set again when the installer is sourced. This causes an @@ -20,7 +20,7 @@ readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" # shellcheck source=./advanced/Scripts/COL_TABLE source "${colfile}" -readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source=./advanced/Scripts/utils.sh source "${utilsfile}" From dad27f8d0686923b8ca5aeb256fe471f8eeb3518 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 14 Jul 2025 21:20:39 -0300 Subject: [PATCH 160/259] Remove `readonly` from list.sh to avoid errors Signed-off-by: RD WebDesign --- advanced/Scripts/list.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index fa356f16..c5a80ad2 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -9,12 +9,12 @@ # This file is copyright under the latest version of the EUPL. # Please see LICENSE file for your rights under this license. -readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" -readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +PI_HOLE_SCRIPT_DIR="/opt/pihole" +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" -readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" +apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" # shellcheck source="./advanced/Scripts/api.sh" source "${apifile}" From 3c52ce98d477ecd1dc6f229af6264c1b934fc38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Jul 2025 13:50:37 +0200 Subject: [PATCH 161/259] Revert https://github.com/pi-hole/pi-hole/pull/6312 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- pihole | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pihole b/pihole index 7b5e3eb8..1231e993 100755 --- a/pihole +++ b/pihole @@ -572,7 +572,8 @@ fi # Check if the current user is not root and if the command # requires root. If so, exit with an error message. -if [[ $EUID -ne 0 && need_root -eq 1 ]];then +# Add an exception for the user "pihole" to allow the webserver running gravity +if [[ $EUID -ne 0 && ${USER} != "pihole" && need_root -eq 1 ]];then echo -e " ${CROSS} The Pi-hole command requires root privileges, try:" echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}" exit 1 From 95021fce5866003015e63ce9f2b529a18e0aedf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Jul 2025 21:00:05 +0200 Subject: [PATCH 162/259] Fix permission for *.etag files after gravity run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gravity.sh b/gravity.sh index fd5d45de..da5aecfa 100755 --- a/gravity.sh +++ b/gravity.sh @@ -808,6 +808,10 @@ gravity_DownloadBlocklistFromUrl() { fix_owner_permissions "${saveLocation}" # Compare lists if they are identical compareLists "${adlistID}" "${saveLocation}" + # Set permissions for the *.etag file + if [[ -f "${saveLocation}.etag" ]]; then + fix_owner_permissions "${saveLocation}.etag" + fi # Add domains to database table file pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" done="true" From da85a7a2a76726f784eded726eb483ff43d27da0 Mon Sep 17 00:00:00 2001 From: Jack'lul Date: Fri, 18 Jul 2025 10:34:02 +0200 Subject: [PATCH 163/259] Use RTMIN value provided by FTL when possible Signed-off-by: Jack'lul --- pihole | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pihole b/pihole index 7b5e3eb8..61aeca84 100755 --- a/pihole +++ b/pihole @@ -150,7 +150,7 @@ versionFunc() { } reloadDNS() { - local svcOption svc str output status pid icon FTL_PID_FILE + local svcOption svc str output status pid icon FTL_PID_FILE sigrtmin svcOption="${1:-reload}" # get the current path to the pihole-FTL.pid @@ -169,7 +169,10 @@ reloadDNS() { str="FTL is not running" icon="${INFO}" else - svc="kill -RTMIN ${pid}" + sigrtmin="$(pihole-FTL sigrtmin 2>/dev/null)" + # Make sure sigrtmin is a number, otherwise fallback to RTMIN + [[ "${sigrtmin}" =~ ^[0-9]+$ ]] || unset sigrtmin + svc="kill -${sigrtmin:-RTMIN} ${pid}" str="Reloading DNS lists" icon="${TICK}" fi From a8db4def9a42e564b61591f3e04e05cbb30edd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 21 Jul 2025 11:54:12 +0200 Subject: [PATCH 164/259] Use flag --skipFTL instead of env var PIHOLE_SKIP_FTL_CHECK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/update.sh | 26 ++++++++++++++++++++------ automated install/basic-install.sh | 13 ++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/advanced/Scripts/update.sh b/advanced/Scripts/update.sh index eb9e7829..67ac9693 100755 --- a/advanced/Scripts/update.sh +++ b/advanced/Scripts/update.sh @@ -150,7 +150,7 @@ main() { fi # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture - if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then + if [ "${skipFTL}" != true ]; then local funcOutput funcOutput=$(get_binary_name) #Store output of get_binary_name here local binary @@ -179,7 +179,7 @@ main() { FTL_update=false fi else - echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}PIHOLE_SKIP_FTL_CHECK env variable set to true - update check skipped${COL_NC}" + echo -e " ${INFO} FTL:\\t\\t${COL_YELLOW}--skipFTL set - update check skipped${COL_NC}" FTL_update=false fi @@ -228,7 +228,14 @@ main() { fi if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then - ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --repair --unattended || \ + local addionalFlag + + if [[ ${skipFTL} == true ]]; then + addionalFlag="--skipFTL" + else + addionalFlag="" + fi + ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --repair --unattended ${addionalFlag} || \ echo -e "${basicError}" && exit 1 fi @@ -248,8 +255,15 @@ main() { exit 0 } -if [[ "$1" == "--check-only" ]]; then - CHECK_ONLY=true -fi +CHECK_ONLY=false +skipFTL=false + +# Check arguments +for var in "$@"; do + case "$var" in + "--check-only") CHECK_ONLY=true ;; + "--skipFTL") skipFTL=true ;; + esac +done main diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 0ab163ae..296730b0 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -156,14 +156,13 @@ EOM # The runUnattended flag is one example of this repair=false runUnattended=false -if [ -z "$PIHOLE_SKIP_FTL_CHECK" ]; then - PIHOLE_SKIP_FTL_CHECK=false -fi +skipFTL=false # Check arguments for the undocumented flags for var in "$@"; do case "$var" in "--repair") repair=true ;; "--unattended") runUnattended=true ;; + "--skipFTL") skipFTL=true ;; esac done @@ -2228,7 +2227,7 @@ main() { # Check if there is a usable FTL binary available on this architecture - do # this early on as FTL is a hard dependency for Pi-hole # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture - if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then + if [ "${skipFTL}" != true ]; then # Get the binary name for the current architecture local funcOutput funcOutput=$(get_binary_name) #Store output of get_binary_name here @@ -2238,7 +2237,7 @@ main() { exit 1 fi else - printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping architecture check%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" + printf " %b %b--skipFTL set - skipping architecture check%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" fi if [[ "${fresh_install}" == false ]]; then @@ -2281,7 +2280,7 @@ main() { # Download and install FTL # Allow the user to skip this check if they are using a self-compiled FTL binary from an unsupported architecture - if [ "${PIHOLE_SKIP_FTL_CHECK}" != true ]; then + if [ "${skipFTL}" != true ]; then local binary binary="pihole-FTL${funcOutput##*pihole-FTL}" #binary name will be the last line of the output of get_binary_name (it always begins with pihole-FTL) local theRest @@ -2291,7 +2290,7 @@ main() { exit 1 fi else - printf " %b %bPIHOLE_SKIP_FTL_CHECK env variable set to true - skipping FTL binary installation%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" + printf " %b %b--skipFTL set - skipping FTL binary installation%b\\n" "${INFO}" "${COL_YELLOW}" "${COL_NC}" fi # Install and log everything to a file From a9e3d3b72841a63bef3e3f6df08d57b91807d4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 21 Jul 2025 12:07:33 +0200 Subject: [PATCH 165/259] Use --skipFTL flag also for pihole repair and checkout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeCheckout.sh | 18 +++++++++++++++++- pihole | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/piholeCheckout.sh b/advanced/Scripts/piholeCheckout.sh index a6df46f2..deb07172 100755 --- a/advanced/Scripts/piholeCheckout.sh +++ b/advanced/Scripts/piholeCheckout.sh @@ -41,6 +41,22 @@ warning1() { } checkout() { + + local skipFTL additionalFlag + skipFTL=false + # Check arguments + for var in "$@"; do + case "$var" in + "--skipFTL") skipFTL=true ;; + esac + done + + if [ "${skipFTL}" == true ]; then + additionalFlag="--skipFTL" + else + additionalFlag="" + fi + local corebranches local webbranches @@ -235,7 +251,7 @@ checkout() { # Force updating everything if [[ ! "${1}" == "web" && ! "${1}" == "ftl" ]]; then echo -e " ${INFO} Running installer to upgrade your installation" - if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended; then + if "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" --unattended ${additionalFlag}; then exit 0 else echo -e " ${COL_RED} Error: Unable to complete update, please contact support${COL_NC}" diff --git a/pihole b/pihole index c1566ed7..5c3377d3 100755 --- a/pihole +++ b/pihole @@ -115,7 +115,22 @@ repairPiholeFunc() { if [ -n "${DOCKER_VERSION}" ]; then unsupportedFunc else - /etc/.pihole/automated\ install/basic-install.sh --repair + local skipFTL additionalFlag + skipFTL=false + # Check arguments + for var in "$@"; do + case "$var" in + "--skipFTL") skipFTL=true ;; + esac + done + + if [ "${skipFTL}" == true ]; then + additionalFlag="--skipFTL" + else + additionalFlag="" + fi + + /etc/.pihole/automated\ install/basic-install.sh --repair ${additionalFlag} exit 0; fi } @@ -589,7 +604,7 @@ case "${1}" in "-d" | "debug" ) debugFunc "$@";; "-f" | "flush" ) flushFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";; - "-r" | "repair" ) repairPiholeFunc;; + "-r" | "repair" ) repairPiholeFunc "$@";; "-g" | "updateGravity" ) updateGravityFunc "$@";; "-l" | "logging" ) piholeLogging "$@";; "uninstall" ) uninstallFunc;; From 22e6ff2cdfca407d841eb8959c37ca3e3ff48f61 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 21 Jul 2025 16:15:25 -0300 Subject: [PATCH 166/259] Update man page - remove "reconfigure" option Signed-off-by: RD WebDesign --- manpages/pihole.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manpages/pihole.8 b/manpages/pihole.8 index e0c38828..8390ffeb 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -105,9 +105,9 @@ Available commands and options: Flush the Pi-hole log .br -\fB-r, reconfigure\fR +\fB-r, repair\fR .br - Reconfigure or Repair Pi-hole subsystems + Repair Pi-hole subsystems .br \fB-t, tail\fR [arg] From 285b3c37f96b2640d6ab58b6c61bcaaf51272ca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 29 Jun 2025 22:31:26 +0200 Subject: [PATCH 167/259] Tweak fluash ARP function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeARPTable.sh | 83 ------------------------- advanced/Scripts/piholeNetworkFlush.sh | 84 ++++++++++++++++++++++++++ advanced/bash-completion/pihole | 12 ++-- manpages/pihole.8 | 5 +- pihole | 21 +++++-- 5 files changed, 112 insertions(+), 93 deletions(-) delete mode 100755 advanced/Scripts/piholeARPTable.sh create mode 100755 advanced/Scripts/piholeNetworkFlush.sh diff --git a/advanced/Scripts/piholeARPTable.sh b/advanced/Scripts/piholeARPTable.sh deleted file mode 100755 index c62acdbc..00000000 --- a/advanced/Scripts/piholeARPTable.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -# Pi-hole: A black hole for Internet advertisements -# (c) 2019 Pi-hole, LLC (https://pi-hole.net) -# Network-wide ad blocking via your own hardware. -# -# ARP table interaction -# -# This file is copyright under the latest version of the EUPL. -# Please see LICENSE file for your rights under this license. - -coltable="/opt/pihole/COL_TABLE" -if [[ -f ${coltable} ]]; then -# shellcheck source="./advanced/Scripts/COL_TABLE" - source ${coltable} -fi - -readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" -utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" -# shellcheck source=./advanced/Scripts/utils.sh -source "${utilsfile}" - -# Determine database location -DBFILE=$(getFTLConfigValue "files.database") -if [ -z "$DBFILE" ]; then - DBFILE="/etc/pihole/pihole-FTL.db" -fi - -flushARP(){ - local output - if [[ "${args[1]}" != "quiet" ]]; then - echo -ne " ${INFO} Flushing network table ..." - fi - - # Stop FTL to prevent database access - if ! output=$(service pihole-FTL stop 2>&1); then - echo -e "${OVER} ${CROSS} Failed to stop FTL" - echo " Output: ${output}" - return 1 - fi - - # Truncate network_addresses table in pihole-FTL.db - # This needs to be done before we can truncate the network table due to - # foreign key constraints - if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network_addresses" 2>&1); then - echo -e "${OVER} ${CROSS} Failed to truncate network_addresses table" - echo " Database location: ${DBFILE}" - echo " Output: ${output}" - return 1 - fi - - # Truncate network table in pihole-FTL.db - if ! output=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM network" 2>&1); then - echo -e "${OVER} ${CROSS} Failed to truncate network table" - echo " Database location: ${DBFILE}" - echo " Output: ${output}" - return 1 - fi - - # Flush ARP cache of the host - if ! output=$(ip -s -s neigh flush all 2>&1); then - echo -e "${OVER} ${CROSS} Failed to flush ARP cache" - echo " Output: ${output}" - return 1 - fi - - # Start FTL again - if ! output=$(service pihole-FTL restart 2>&1); then - echo -e "${OVER} ${CROSS} Failed to restart FTL" - echo " Output: ${output}" - return 1 - fi - - if [[ "${args[1]}" != "quiet" ]]; then - echo -e "${OVER} ${TICK} Flushed network table" - fi -} - -args=("$@") - -case "${args[0]}" in - "arpflush" ) flushARP;; -esac diff --git a/advanced/Scripts/piholeNetworkFlush.sh b/advanced/Scripts/piholeNetworkFlush.sh new file mode 100755 index 00000000..a8721476 --- /dev/null +++ b/advanced/Scripts/piholeNetworkFlush.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# Pi-hole: A black hole for Internet advertisements +# (c) 2019 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. +# +# Network table flush +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. + +coltable="/opt/pihole/COL_TABLE" +if [[ -f ${coltable} ]]; then +# shellcheck source="./advanced/Scripts/COL_TABLE" + source ${coltable} +fi + +readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source=./advanced/Scripts/utils.sh +source "${utilsfile}" + +# Source api functions +# shellcheck source="./advanced/Scripts/api.sh" +. "${PI_HOLE_SCRIPT_DIR}/api.sh" + +flushNetwork(){ + local output + + echo -ne " ${INFO} Flushing network table ..." + + local data status error + # Authenticate with FTL + LoginAPI + + # send query again + data=$(PostFTLData "action/flush/network" "" "status") + + # Separate the status from the data + status=$(printf %s "${data#"${data%???}"}") + data=$(printf %s "${data%???}") + + # If there is an .error object in the returned data, display it + local error + error=$(jq --compact-output <<< "${data}" '.error') + if [[ $error != "null" && $error != "" ]]; then + echo -e "${OVER} ${CROSS} Failed to flush the network table:" + echo -e " $(jq <<< "${data}" '.error')" + LogoutAPI + exit 1 + elif [[ "${status}" == "200" ]]; then + echo -e "${OVER} ${TICK} Flushed network table" + fi + + # Delete session + LogoutAPI +} + +flushArp(){ + # Flush ARP cache of the host + if ! output=$(ip -s -s neigh flush all 2>&1); then + echo -e "${OVER} ${CROSS} Failed to flush ARP cache" + echo " Output: ${output}" + return 1 + fi +} + +# Process all options (if present) +while [ "$#" -gt 0 ]; do + case "$1" in + "--arp" ) doARP=true ;; + esac + shift +done + +flushNetwork + +if [[ "${doARP}" == true ]]; then + echo -ne " ${INFO} Flushing ARP cache" + if flushArp; then + echo -e "${OVER} ${TICK} Flushed ARP cache" + fi +fi + diff --git a/advanced/bash-completion/pihole b/advanced/bash-completion/pihole index cf99ab73..e0f9017b 100644 --- a/advanced/bash-completion/pihole +++ b/advanced/bash-completion/pihole @@ -1,5 +1,5 @@ _pihole() { - local cur prev opts opts_checkout opts_debug opts_logging opts_query opts_update opts_version + local cur prev opts opts_lists opts_checkout opts_debug opts_logging opts_query opts_update opts_networkflush COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" @@ -7,7 +7,7 @@ _pihole() { case "${prev}" in "pihole") - opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api" + opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard networkflush api" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) ;; "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") @@ -34,9 +34,13 @@ _pihole() { opts_update="--check-only" COMPREPLY=( $(compgen -W "${opts_update}" -- ${cur}) ) ;; - "core"|"admin"|"ftl") + "networkflush") + opts_networkflush="--arp" + COMPREPLY=( $(compgen -W "${opts_networkflush}" -- ${cur}) ) + ;; + "core"|"web"|"ftl") if [[ "$prev2" == "checkout" ]]; then - opts_checkout="master dev" + opts_checkout="master development" COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) ) else return 1 diff --git a/manpages/pihole.8 b/manpages/pihole.8 index e0c38828..66b0dd17 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -317,9 +317,10 @@ Switching Pi-hole subsystem branches Switch to core development branch .br -\fBpihole arpflush\fR +\fBpihole networkflush\fR .br - Flush information stored in Pi-hole's network tables + Flush information stored in Pi-hole's network table + Add '--arp' to additionally flush the ARP table .br \fBpihole api stats/summary\fR diff --git a/pihole b/pihole index 7df4aefc..efbabc38 100755 --- a/pihole +++ b/pihole @@ -96,8 +96,18 @@ flushFunc() { exit 0 } +# Deprecated function, should be removed in the future +# use networkFlush instead arpFunc() { - "${PI_HOLE_SCRIPT_DIR}"/piholeARPTable.sh "$@" + shift + echo -e " ${INFO} The 'arpflush' command is deprecated, use 'networkflush' instead" + "${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@" + exit 0 +} + +networkFlush() { + shift + "${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@" exit 0 } @@ -519,7 +529,8 @@ Options: reloadlists Update the lists WITHOUT flushing the cache or restarting the DNS server checkout Switch Pi-hole subsystems to a different GitHub branch Add '-h' for more info on checkout usage - arpflush Flush information stored in Pi-hole's network tables"; + networkflush Flush information stored in Pi-hole's network tables + Add '--arp' to additionally flush the ARP table "; exit 0 } @@ -558,7 +569,8 @@ case "${1}" in "setpassword" ) ;; "checkout" ) ;; "updatechecker" ) ;; - "arpflush" ) ;; + "arpflush" ) ;; # Deprecated, use networkflush instead + "networkflush" ) ;; "-t" | "tail" ) ;; "api" ) need_root=0;; * ) helpFunc;; @@ -600,7 +612,8 @@ case "${1}" in "setpassword" ) SetWebPassword "$@";; "checkout" ) piholeCheckoutFunc "$@";; "updatechecker" ) shift; updateCheckFunc "$@";; - "arpflush" ) arpFunc "$@";; + "arpflush" ) arpFunc "$@";; # Deprecated, use networkflush instead + "networkflush" ) networkFlush "$@";; "-t" | "tail" ) tailFunc "$2";; "api" ) shift; apiFunc "$@";; * ) helpFunc;; From 70e317f3735cfdf62fc84cbc1637225b2dd62f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Jul 2025 13:57:10 +0200 Subject: [PATCH 168/259] Revert https://github.com/pi-hole/pi-hole/pull/6345 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pihole b/pihole index 1231e993..665c11f5 100755 --- a/pihole +++ b/pihole @@ -552,7 +552,7 @@ case "${1}" in "enable" ) need_root=0;; "disable" ) need_root=0;; "-d" | "debug" ) ;; - "-g" | "updateGravity" ) need_root=0;; + "-g" | "updateGravity" ) ;; "reloaddns" ) ;; "reloadlists" ) ;; "setpassword" ) ;; From 9580dc6560d4e476da58f4567ff0e39ae2e70b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Jul 2025 13:54:53 +0200 Subject: [PATCH 169/259] Improve setFTLConfigValue function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/utils.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index d4a6957c..f5dc89fb 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -86,9 +86,17 @@ getFTLConfigValue(){ # setFTLConfigValue dns.upstreams '[ "8.8.8.8" , "8.8.4.4" ]' ####################### setFTLConfigValue(){ - pihole-FTL --config "${1}" "${2}" >/dev/null - if [ $? -eq 5 ]; then - printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}" - exit 5 - fi + local err + { pihole-FTL --config "${1}" "${2}" >/dev/null; err="$?"; } || true + + case $err in + 0) ;; + 5) + # FTL returns 5 if the value was set by an environment variable and is therefore read-only + printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}"; + exit 5;; + *) + printf " %s Failed to set %s. Try with sudo power\n" "${CROSS}" "${1}" + exit 1 + esac } From 310f0711fac439dcc09481492c4d11533b4039ee Mon Sep 17 00:00:00 2001 From: yubiuser Date: Mon, 21 Jul 2025 13:41:53 +0200 Subject: [PATCH 170/259] Group evaluations Co-authored-by: Dan Schaper Signed-off-by: yubiuser --- pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pihole b/pihole index 665c11f5..dabaad5a 100755 --- a/pihole +++ b/pihole @@ -573,7 +573,7 @@ fi # Check if the current user is not root and if the command # requires root. If so, exit with an error message. # Add an exception for the user "pihole" to allow the webserver running gravity -if [[ $EUID -ne 0 && ${USER} != "pihole" && need_root -eq 1 ]];then +if [[ ( $EUID -ne 0 && ${USER} != "pihole" ) && need_root -eq 1 ]]; then echo -e " ${CROSS} The Pi-hole command requires root privileges, try:" echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}" exit 1 From 05f4ae77190fc8ff3fabc43a065e0e45679fcf29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Jul 2025 08:52:25 +0200 Subject: [PATCH 171/259] Invert need_root logic and check if set/unset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Co-authored-by: Dan Schaper --- pihole | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/pihole b/pihole index c68575a9..5e4465ea 100755 --- a/pihole +++ b/pihole @@ -542,7 +542,7 @@ if [[ $# = 0 ]]; then fi # functions that do not require sudo power -need_root=1 +need_root= case "${1}" in "-h" | "help" | "--help" ) helpFunc;; "-v" | "version" ) versionFunc;; @@ -552,30 +552,30 @@ case "${1}" in "tricorder" ) tricorderFunc;; # we need to add all arguments that require sudo power to not trigger the * argument - "allow" | "allowlist" ) need_root=0;; - "deny" | "denylist" ) need_root=0;; - "--wild" | "wildcard" ) need_root=0;; - "--regex" | "regex" ) need_root=0;; - "--allow-regex" | "allow-regex" ) need_root=0;; - "--allow-wild" | "allow-wild" ) need_root=0;; - "-f" | "flush" ) ;; - "-up" | "updatePihole" ) ;; - "-r" | "repair" ) ;; - "-l" | "logging" ) ;; - "uninstall" ) ;; - "enable" ) need_root=0;; - "disable" ) need_root=0;; - "-d" | "debug" ) ;; - "-g" | "updateGravity" ) ;; - "reloaddns" ) ;; - "reloadlists" ) ;; - "setpassword" ) ;; - "checkout" ) ;; - "updatechecker" ) ;; - "arpflush" ) ;; # Deprecated, use networkflush instead - "networkflush" ) ;; - "-t" | "tail" ) ;; - "api" ) need_root=0;; + "allow" | "allowlist" ) ;; + "deny" | "denylist" ) ;; + "--wild" | "wildcard" ) ;; + "--regex" | "regex" ) ;; + "--allow-regex" | "allow-regex" ) ;; + "--allow-wild" | "allow-wild" ) ;; + "-f" | "flush" ) need_root=true;; + "-up" | "updatePihole" ) need_root=true;; + "-r" | "repair" ) need_root=true;; + "-l" | "logging" ) need_root=true;; + "uninstall" ) need_root=true;; + "enable" ) ;; + "disable" ) ;; + "-d" | "debug" ) need_root=true;; + "-g" | "updateGravity" ) need_root=true;; + "reloaddns" ) need_root=true;; + "reloadlists" ) need_root=true;; + "setpassword" ) need_root=true;; + "checkout" ) need_root=true;; + "updatechecker" ) need_root=true;; + "arpflush" ) need_root=true;; # Deprecated, use networkflush instead + "networkflush" ) need_root=true;; + "-t" | "tail" ) need_root=true;; + "api" ) ;; * ) helpFunc;; esac @@ -588,8 +588,8 @@ fi # Check if the current user is not root and if the command # requires root. If so, exit with an error message. # Add an exception for the user "pihole" to allow the webserver running gravity -if [[ ( $EUID -ne 0 && ${USER} != "pihole" ) && need_root -eq 1 ]]; then - echo -e " ${CROSS} The Pi-hole command requires root privileges, try:" +if [[ ( $EUID -ne 0 && ${USER} != "pihole" ) && -n "${need_root}" ]]; then + echo -e " ${CROSS} This Pi-hole command requires root privileges, try:" echo -e " ${COL_GREEN}sudo pihole $*${COL_NC}" exit 1 fi From 7aa57e154e26e4cb0a598ccc82b24cac1a59d86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 23 Jul 2025 08:18:47 +0200 Subject: [PATCH 172/259] Group functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- pihole | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/pihole b/pihole index 5e4465ea..5af46fa6 100755 --- a/pihole +++ b/pihole @@ -157,6 +157,7 @@ uninstallFunc() { versionFunc() { exec "${PI_HOLE_SCRIPT_DIR}"/version.sh + exit 0 } reloadDNS() { @@ -277,6 +278,7 @@ Time: LogoutAPI echo -e "${OVER} ${TICK} ${str}" + exit 0 } piholeLogging() { @@ -550,21 +552,22 @@ case "${1}" in "-q" | "query" ) queryFunc "$@";; "status" ) statusFunc "$2";; "tricorder" ) tricorderFunc;; + "allow" | "allowlist" ) listFunc "$@";; + "deny" | "denylist" ) listFunc "$@";; + "--wild" | "wildcard" ) listFunc "$@";; + "--regex" | "regex" ) listFunc "$@";; + "--allow-regex" | "allow-regex" ) listFunc "$@";; + "--allow-wild" | "allow-wild" ) listFunc "$@";; + "enable" ) piholeEnable true "$2";; + "disable" ) piholeEnable false "$2";; + "api" ) shift; apiFunc "$@"; exit 0;; # we need to add all arguments that require sudo power to not trigger the * argument - "allow" | "allowlist" ) ;; - "deny" | "denylist" ) ;; - "--wild" | "wildcard" ) ;; - "--regex" | "regex" ) ;; - "--allow-regex" | "allow-regex" ) ;; - "--allow-wild" | "allow-wild" ) ;; "-f" | "flush" ) need_root=true;; "-up" | "updatePihole" ) need_root=true;; "-r" | "repair" ) need_root=true;; "-l" | "logging" ) need_root=true;; "uninstall" ) need_root=true;; - "enable" ) ;; - "disable" ) ;; "-d" | "debug" ) need_root=true;; "-g" | "updateGravity" ) need_root=true;; "reloaddns" ) need_root=true;; @@ -575,7 +578,6 @@ case "${1}" in "arpflush" ) need_root=true;; # Deprecated, use networkflush instead "networkflush" ) need_root=true;; "-t" | "tail" ) need_root=true;; - "api" ) ;; * ) helpFunc;; esac @@ -596,12 +598,6 @@ fi # Handle redirecting to specific functions based on arguments case "${1}" in - "allow" | "allowlist" ) listFunc "$@";; - "deny" | "denylist" ) listFunc "$@";; - "--wild" | "wildcard" ) listFunc "$@";; - "--regex" | "regex" ) listFunc "$@";; - "--allow-regex" | "allow-regex" ) listFunc "$@";; - "--allow-wild" | "allow-wild" ) listFunc "$@";; "-d" | "debug" ) debugFunc "$@";; "-f" | "flush" ) flushFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";; @@ -609,8 +605,6 @@ case "${1}" in "-g" | "updateGravity" ) updateGravityFunc "$@";; "-l" | "logging" ) piholeLogging "$@";; "uninstall" ) uninstallFunc;; - "enable" ) piholeEnable true "$2";; - "disable" ) piholeEnable false "$2";; "reloaddns" ) reloadDNS "reload";; "reloadlists" ) reloadDNS "reload-lists";; "setpassword" ) SetWebPassword "$@";; @@ -619,6 +613,5 @@ case "${1}" in "arpflush" ) arpFunc "$@";; # Deprecated, use networkflush instead "networkflush" ) networkFlush "$@";; "-t" | "tail" ) tailFunc "$2";; - "api" ) shift; apiFunc "$@";; * ) helpFunc;; esac From 5b4a7b8b74983877c653e4b1e046c06062171140 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 26 Jul 2025 18:48:32 +1000 Subject: [PATCH 173/259] pihole api - use keepalive for curl queries Adds the keepalive header to all curl requests This reduces session establishment time across the multiple requests necessary to authenticate, obtain response and log out Signed-off-by: Rob Gill --- advanced/Scripts/api.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 7589d3ff..53dabebb 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -55,7 +55,7 @@ TestAPIAvailability() { API_URL="${API_URL#\"}" # Test if the API is available at this URL, include delimiter for ease in splitting payload - authResponse=$(curl --connect-timeout 2 -skS -w ">>%{http_code}" "${API_URL}auth") + authResponse=$(curl --connect-timeout 2 -skS -H "Connection: keep-alive" -w ">>%{http_code}" "${API_URL}auth") # authStatus is the response http_code, eg. 200, 401. # Shell parameter expansion, remove everything up to and including the >> delim @@ -184,7 +184,7 @@ LoginAPI() { } Authentication() { - sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}" )" + sessionResponse=$(curl --connect-timeout 2 -skS -H "Connection: keep-alive" -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}") if [ -z "${sessionResponse}" ]; then echo "No response from FTL server. Please check connectivity" @@ -219,7 +219,7 @@ LogoutAPI() { # SID is not null (successful Authentication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delete the session. Omit the output, but get the http status code - deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}") + deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") case "${deleteResponse}" in "401") echo "Logout attempt without a valid session. Unauthorized!";; @@ -233,7 +233,7 @@ LogoutAPI() { GetFTLData() { local data response status # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") if [ "${2}" = "raw" ]; then # return the raw response @@ -260,7 +260,7 @@ GetFTLData() { PostFTLData() { local data response status # send the data to the API - response=$(curl -skS -w "%{http_code}" -X POST "${API_URL}$1" --data-raw "$2" -H "Accept: application/json" -H "sid: ${SID}" ) + response=$(curl -skS -w "%{http_code}" -X POST "${API_URL}$1" --data-raw "$2" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") # data is everything from response without the last 3 characters if [ "${3}" = "status" ]; then # Keep the status code appended if requested From 9252e90bd625edab6fdbcaa9e1225610331f86a1 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Fri, 25 Jul 2025 21:54:54 +0100 Subject: [PATCH 174/259] Check for the existence of the FTL binary before stopping the service This prevents errors on fresh installs where the FTL binary does not exist yet. Signed-off-by: Adam Warner --- automated install/basic-install.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 5c4a84c0..e85b4ff1 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1794,8 +1794,12 @@ FTLinstall() { # Before stopping FTL, we download the macvendor database curl -sSL "https://ftl.pi-hole.net/macvendor.db" -o "${PI_HOLE_CONFIG_DIR}/macvendor.db" || true - # Stop pihole-FTL service if available - stop_service pihole-FTL >/dev/null + + # If the binary already exists in /usr/bin, then we need to stop the service + # If the binary does not exist, then we can skip this step. + if [[ -f /usr/bin/pihole-FTL ]]; then + stop_service pihole-FTL >/dev/null + fi # Install the new version with the correct permissions install -T -m 0755 "${binary}" /usr/bin/pihole-FTL From 364ba99b1f37cad83e34f3b009038df4493be9c6 Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sat, 26 Jul 2025 10:56:21 +0100 Subject: [PATCH 175/259] Update automated install/basic-install.sh Co-authored-by: yubiuser Signed-off-by: Adam Warner --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index e85b4ff1..daacb9a3 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1796,7 +1796,7 @@ FTLinstall() { # If the binary already exists in /usr/bin, then we need to stop the service - # If the binary does not exist, then we can skip this step. + # If the binary does not exist (fresh installs), then we can skip this step. if [[ -f /usr/bin/pihole-FTL ]]; then stop_service pihole-FTL >/dev/null fi From 37ec67e9a3241834359451a38f20b06d6b6382be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 26 Jul 2025 10:36:36 +0000 Subject: [PATCH 176/259] Bump tox from 4.27.0 to 4.28.3 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.27.0 to 4.28.3 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.27.0...4.28.3) --- updated-dependencies: - dependency-name: tox dependency-version: 4.28.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 92f78840..6496bf2f 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.4.1 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.27.0 +tox == 4.28.3 pytest-clarity == 1.0.1 From 24d8754033ed00bdda509f6bcdfee5d8d787b80c Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sat, 26 Jul 2025 12:35:02 +0100 Subject: [PATCH 177/259] Revert "pihole api - use keepalive for curl queries" --- advanced/Scripts/api.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh index 53dabebb..7589d3ff 100755 --- a/advanced/Scripts/api.sh +++ b/advanced/Scripts/api.sh @@ -55,7 +55,7 @@ TestAPIAvailability() { API_URL="${API_URL#\"}" # Test if the API is available at this URL, include delimiter for ease in splitting payload - authResponse=$(curl --connect-timeout 2 -skS -H "Connection: keep-alive" -w ">>%{http_code}" "${API_URL}auth") + authResponse=$(curl --connect-timeout 2 -skS -w ">>%{http_code}" "${API_URL}auth") # authStatus is the response http_code, eg. 200, 401. # Shell parameter expansion, remove everything up to and including the >> delim @@ -184,7 +184,7 @@ LoginAPI() { } Authentication() { - sessionResponse=$(curl --connect-timeout 2 -skS -H "Connection: keep-alive" -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}") + sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}" )" if [ -z "${sessionResponse}" ]; then echo "No response from FTL server. Please check connectivity" @@ -219,7 +219,7 @@ LogoutAPI() { # SID is not null (successful Authentication only), delete the session if [ "${validSession}" = true ] && [ ! "${SID}" = null ]; then # Try to delete the session. Omit the output, but get the http status code - deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") + deleteResponse=$(curl -skS -o /dev/null -w "%{http_code}" -X DELETE "${API_URL}auth" -H "Accept: application/json" -H "sid: ${SID}") case "${deleteResponse}" in "401") echo "Logout attempt without a valid session. Unauthorized!";; @@ -233,7 +233,7 @@ LogoutAPI() { GetFTLData() { local data response status # get the data from querying the API as well as the http status code - response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") + response=$(curl -skS -w "%{http_code}" -X GET "${API_URL}$1" -H "Accept: application/json" -H "sid: ${SID}" ) if [ "${2}" = "raw" ]; then # return the raw response @@ -260,7 +260,7 @@ GetFTLData() { PostFTLData() { local data response status # send the data to the API - response=$(curl -skS -w "%{http_code}" -X POST "${API_URL}$1" --data-raw "$2" -H "Accept: application/json" -H "sid: ${SID}" -H "Connection: keep-alive") + response=$(curl -skS -w "%{http_code}" -X POST "${API_URL}$1" --data-raw "$2" -H "Accept: application/json" -H "sid: ${SID}" ) # data is everything from response without the last 3 characters if [ "${3}" = "status" ]; then # Keep the status code appended if requested From 5cb601200c09729cbbcf6d094edc5a4420272bd9 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Sat, 26 Jul 2025 19:40:05 +0200 Subject: [PATCH 178/259] Use non-interactive shell in utils.sh:getFTLConfigValue to avoid colored output Signed-off-by: DL6ER --- advanced/Scripts/utils.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index f5dc89fb..d000a6db 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -73,7 +73,9 @@ getFTLPID() { # Example getFTLConfigValue dns.piholePTR ####################### getFTLConfigValue(){ - pihole-FTL --config -q "${1}" + # Pipe to cat to avoid pihole-FTL assuming this is an interactive command + # returning colored output. + pihole-FTL --config -q "${1}" | cat } ####################### From d4562a1debacac39414fe0176624ec49a03c9d09 Mon Sep 17 00:00:00 2001 From: deHakkelaar Date: Thu, 31 Jul 2025 18:03:43 +0200 Subject: [PATCH 179/259] Add "setpassword" to pihole Bash completion Its missing. After: ``` $ sudo pihole allow arpflush disable logging reloadlists tail version allow-regex checkout enable query repair uninstall wildcard allow-wild debug flush regex setpassword updateGravity api deny help reloaddns status updatePihole ``` Signed-off-by: deHakkelaar --- advanced/bash-completion/pihole | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/bash-completion/pihole b/advanced/bash-completion/pihole index e0f9017b..acc5b71a 100644 --- a/advanced/bash-completion/pihole +++ b/advanced/bash-completion/pihole @@ -7,7 +7,7 @@ _pihole() { case "${prev}" in "pihole") - opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard networkflush api" + opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists setpassword status tail uninstall updateGravity updatePihole version wildcard networkflush api" COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) ;; "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") From 9bc17a1f2bfbf4221d76dfda070751d22932c9d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 10:52:42 +0000 Subject: [PATCH 180/259] Bump tox from 4.28.3 to 4.28.4 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.28.3 to 4.28.4 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.28.3...4.28.4) --- updated-dependencies: - dependency-name: tox dependency-version: 4.28.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 6496bf2f..7e329dcf 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.2 pytest == 8.4.1 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.28.3 +tox == 4.28.4 pytest-clarity == 1.0.1 From 7baa9c5de05e72ebcbf9147a9a304fa7d75d80e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 4 Aug 2025 20:38:27 +0200 Subject: [PATCH 181/259] Adjust .shellcheckrc to 0.11 and enable some optional checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .shellcheckrc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.shellcheckrc b/.shellcheckrc index 8e0b8387..c4711a8f 100644 --- a/.shellcheckrc +++ b/.shellcheckrc @@ -1,2 +1,6 @@ external-sources=true # allow shellcheck to read external sources disable=SC3043 #disable SC3043: In POSIX sh, local is undefined. +enable=useless-use-of-cat # disabled by default as of shellcheck 0.11.0 +enable=avoid-negated-conditions # avoid-negated-conditions is optional as of shellcheck 0.11.0 +enable=require-variable-braces +enable=deprecate-which From 340ffbe5e8bde3b94b18870db7de542db8493a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 6 Aug 2025 12:51:08 +0200 Subject: [PATCH 182/259] Add pihole-FTL bash completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/bash-completion/pihole-ftl.bash | 53 ++++++++++++++++++++++++ automated install/basic-install.sh | 1 + automated install/uninstall.sh | 1 + 3 files changed, 55 insertions(+) create mode 100644 advanced/bash-completion/pihole-ftl.bash diff --git a/advanced/bash-completion/pihole-ftl.bash b/advanced/bash-completion/pihole-ftl.bash new file mode 100644 index 00000000..f83ed16e --- /dev/null +++ b/advanced/bash-completion/pihole-ftl.bash @@ -0,0 +1,53 @@ +#!/bin/bash +# +# Bash completion script for pihole-FTL +# +# This completion script provides tab completion for some pihole-FTL CLI flags and commands. +_pihole_ftl_completion() { + local cur prev opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + # Selected commands and flags + opts="version tag branch help dnsmasq-test regex-test lua sqlite3 --config --teleporter --gen-x509 --read-x509 gravity ntp gzip dhcp-discover arp-scan idn2 sha256sum verify --default-gateway" + + # Handle subcommands for specific commands + case "${prev}" in + # Gravity subcommands + gravity) + mapfile -t COMPREPLY < <(compgen -W "checkList" -- "${cur}") + return 0 + ;; + + # SQLite3 special modes + sqlite3) + mapfile -t COMPREPLY < <(compgen -W "-h -ni" -- "${cur}") + return 0 + ;; + + # ARP scan options + arp-scan) + mapfile -t COMPREPLY < <(compgen -W "-a -x" -- "${cur}") + return 0 + ;; + + # IDN2 options + idn2) + mapfile -t COMPREPLY < <(compgen -W "--decode" -- "${cur}") + return 0 + ;; + + # NTP options + ntp) + mapfile -t COMPREPLY < <(compgen -W "--update" -- "${cur}") + return 0 + ;; + + esac + # Default completion + mapfile -t COMPREPLY < <(compgen -W "${opts}" -- "${cur}") +} + +# Register the completion function for pihole-FTL +complete -F _pihole_ftl_completion pihole-FTL diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index daacb9a3..4e823ec4 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1138,6 +1138,7 @@ installScripts() { install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./advanced/Scripts/COL_TABLE install -o "${USER}" -Dm755 -t "${PI_HOLE_BIN_DIR}" pihole install -Dm644 ./advanced/bash-completion/pihole /etc/bash_completion.d/pihole + install -Dm644 ./advanced/bash-completion/pihole-ftl.bash /etc/bash_completion.d/pihole-FTL printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index e8dec36a..dfe0871e 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -89,6 +89,7 @@ removePiholeFiles() { ${SUDO} rm -rf /opt/pihole/ &> /dev/null ${SUDO} rm -f /usr/local/bin/pihole &> /dev/null ${SUDO} rm -f /etc/bash_completion.d/pihole &> /dev/null + ${SUDO} rm -f /etc/bash_completion.d/pihole-FTL &> /dev/null ${SUDO} rm -f /etc/sudoers.d/pihole &> /dev/null echo -e " ${TICK} Removed config files" From 5d1ef6279f6b9d26b4a106709ddb292a06fbd830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 6 Aug 2025 12:57:36 +0200 Subject: [PATCH 183/259] Fix shellcheck warnings for pihole bash completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .../bash-completion/{pihole => pihole.bash} | 22 +++++++++++-------- automated install/basic-install.sh | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) rename advanced/bash-completion/{pihole => pihole.bash} (65%) diff --git a/advanced/bash-completion/pihole b/advanced/bash-completion/pihole.bash similarity index 65% rename from advanced/bash-completion/pihole rename to advanced/bash-completion/pihole.bash index acc5b71a..736a75d9 100644 --- a/advanced/bash-completion/pihole +++ b/advanced/bash-completion/pihole.bash @@ -1,3 +1,7 @@ +#!/bin/bash +# +# Bash completion script for pihole +# _pihole() { local cur prev opts opts_lists opts_checkout opts_debug opts_logging opts_query opts_update opts_networkflush COMPREPLY=() @@ -8,40 +12,40 @@ _pihole() { case "${prev}" in "pihole") opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists setpassword status tail uninstall updateGravity updatePihole version wildcard networkflush api" - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts}" -- "${cur}") ;; "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") opts_lists="\not \--delmode \--quiet \--list \--help" - COMPREPLY=( $(compgen -W "${opts_lists}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_lists}" -- "${cur}") ;; "checkout") opts_checkout="core ftl web master dev" - COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_checkout}" -- "${cur}") ;; "debug") opts_debug="-a" - COMPREPLY=( $(compgen -W "${opts_debug}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_debug}" -- "${cur}") ;; "logging") opts_logging="on off 'off noflush'" - COMPREPLY=( $(compgen -W "${opts_logging}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_logging}" -- "${cur}") ;; "query") opts_query="--partial --all" - COMPREPLY=( $(compgen -W "${opts_query}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_query}" -- "${cur}") ;; "updatePihole"|"-up") opts_update="--check-only" - COMPREPLY=( $(compgen -W "${opts_update}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_update}" -- "${cur}") ;; "networkflush") opts_networkflush="--arp" - COMPREPLY=( $(compgen -W "${opts_networkflush}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_networkflush}" -- "${cur}") ;; "core"|"web"|"ftl") if [[ "$prev2" == "checkout" ]]; then opts_checkout="master development" - COMPREPLY=( $(compgen -W "${opts_checkout}" -- ${cur}) ) + mapfile -t COMPREPLY < <(compgen -W "${opts_checkout}" -- "${cur}") else return 1 fi diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 4e823ec4..9d3bd2b3 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1137,7 +1137,7 @@ installScripts() { install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./automated\ install/uninstall.sh install -o "${USER}" -Dm755 -t "${PI_HOLE_INSTALL_DIR}" ./advanced/Scripts/COL_TABLE install -o "${USER}" -Dm755 -t "${PI_HOLE_BIN_DIR}" pihole - install -Dm644 ./advanced/bash-completion/pihole /etc/bash_completion.d/pihole + install -Dm644 ./advanced/bash-completion/pihole.bash /etc/bash_completion.d/pihole install -Dm644 ./advanced/bash-completion/pihole-ftl.bash /etc/bash_completion.d/pihole-FTL printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" From 4511daf5607f55244b3476f813ef0cec9dd693e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 6 Aug 2025 21:01:37 +0200 Subject: [PATCH 184/259] Use pihole-FTL --complete to generate autocomplete suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/bash-completion/pihole-ftl.bash | 52 ++---------------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/advanced/bash-completion/pihole-ftl.bash b/advanced/bash-completion/pihole-ftl.bash index f83ed16e..d652f007 100644 --- a/advanced/bash-completion/pihole-ftl.bash +++ b/advanced/bash-completion/pihole-ftl.bash @@ -2,52 +2,8 @@ # # Bash completion script for pihole-FTL # -# This completion script provides tab completion for some pihole-FTL CLI flags and commands. -_pihole_ftl_completion() { - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" +# This completion script provides tab completion for pihole-FTL CLI flags and commands. +# It uses the `pihole-FTL --complete` command to generate the completion options. +_complete_FTL() { mapfile -t COMPREPLY < <(pihole-FTL --complete "${COMP_WORDS[@]}"); } - # Selected commands and flags - opts="version tag branch help dnsmasq-test regex-test lua sqlite3 --config --teleporter --gen-x509 --read-x509 gravity ntp gzip dhcp-discover arp-scan idn2 sha256sum verify --default-gateway" - - # Handle subcommands for specific commands - case "${prev}" in - # Gravity subcommands - gravity) - mapfile -t COMPREPLY < <(compgen -W "checkList" -- "${cur}") - return 0 - ;; - - # SQLite3 special modes - sqlite3) - mapfile -t COMPREPLY < <(compgen -W "-h -ni" -- "${cur}") - return 0 - ;; - - # ARP scan options - arp-scan) - mapfile -t COMPREPLY < <(compgen -W "-a -x" -- "${cur}") - return 0 - ;; - - # IDN2 options - idn2) - mapfile -t COMPREPLY < <(compgen -W "--decode" -- "${cur}") - return 0 - ;; - - # NTP options - ntp) - mapfile -t COMPREPLY < <(compgen -W "--update" -- "${cur}") - return 0 - ;; - - esac - # Default completion - mapfile -t COMPREPLY < <(compgen -W "${opts}" -- "${cur}") -} - -# Register the completion function for pihole-FTL -complete -F _pihole_ftl_completion pihole-FTL +complete -F _complete_FTL pihole-FTL From 94bbf5f42977661aa1f3d2f5132a4969c78f494a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 7 Aug 2025 19:44:26 +0200 Subject: [PATCH 185/259] Fix shellcheck warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index daacb9a3..7ad651af 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -94,8 +94,8 @@ fresh_install=true adlistFile="/etc/pihole/adlists.list" # Pi-hole needs an IP address; to begin, these variables are empty since we don't know what the IP is until this script can run -IPV4_ADDRESS=${IPV4_ADDRESS} -IPV6_ADDRESS=${IPV6_ADDRESS} +IPV4_ADDRESS= +IPV6_ADDRESS= # Give settings their default values. These may be changed by prompts later in the script. QUERY_LOGGING= PRIVACY_LEVEL= @@ -161,7 +161,7 @@ repair=false runUnattended=false # Check arguments for the undocumented flags for var in "$@"; do - case "$var" in + case "${var}" in "--repair") repair=true ;; "--unattended") runUnattended=true ;; esac @@ -576,7 +576,7 @@ Do you wish to continue with an IPv6-only installation?\\n\\n" \ ;; esac - DNS_SERVERS="$DNS_SERVERS_IPV6_ONLY" + DNS_SERVERS="${DNS_SERVERS_IPV6_ONLY}" printf " %b Proceeding with IPv6 only installation.\\n" "${INFO}" } @@ -652,7 +652,7 @@ chooseInterface() { PIHOLE_INTERFACE=$(dialog --no-shadow --keep-tite --output-fd 1 \ --cancel-label "Exit" --ok-label "Select" \ --radiolist "Choose An Interface (press space to toggle selection)" \ - ${r} ${c} "${interfaceCount}" ${interfacesList}) + ${r} ${c} "${interfaceCount}" "${interfacesList}") result=$? case ${result} in @@ -674,9 +674,9 @@ testIPv6() { # first will contain fda2 (ULA) printf -v first "%s" "${1%%:*}" # value1 will contain 253 which is the decimal value corresponding to 0xFD - value1=$(((0x$first) / 256)) + value1=$(((0x${first}) / 256)) # value2 will contain 162 which is the decimal value corresponding to 0xA2 - value2=$(((0x$first) % 256)) + value2=$(((0x${first}) % 256)) # the ULA test is testing for fc00::/7 according to RFC 4193 if (((value1 & 254) == 252)); then # echoing result to calling function as return value @@ -701,7 +701,7 @@ find_IPv6_information() { # For each address in the array above, determine the type of IPv6 address it is for i in "${IPV6_ADDRESSES[@]}"; do # Check if it's ULA, GUA, or LL by using the function created earlier - result=$(testIPv6 "$i") + result=$(testIPv6 "${i}") # If it's a ULA address, use it and store it as a global variable [[ "${result}" == "ULA" ]] && ULA_ADDRESS="${i%/*}" # If it's a GUA address, use it and store it as a global variable @@ -736,7 +736,7 @@ collect_v4andv6_information() { printf " %b IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}" find_IPv6_information printf " %b IPv6 address: %s\\n" "${INFO}" "${IPV6_ADDRESS}" - if [ "$IPV4_ADDRESS" == "" ] && [ "$IPV6_ADDRESS" != "" ]; then + if [ "${IPV4_ADDRESS}" == "" ] && [ "${IPV6_ADDRESS}" != "" ]; then confirm_ipv6_only fi } @@ -756,7 +756,7 @@ valid_ip() { local regex="^${ipv4elem}\\.${ipv4elem}\\.${ipv4elem}\\.${ipv4elem}${portelem}$" # Evaluate the regex, and return the result - [[ $ip =~ ${regex} ]] + [[ ${ip} =~ ${regex} ]] stat=$? return "${stat}" @@ -791,7 +791,7 @@ setDNS() { DNSChooseOptions=() local DNSServerCount=0 # Save the old Internal Field Separator in a variable, - OIFS=$IFS + OIFS=${IFS} # and set the new one to newline IFS=$'\n' # Put the DNS Servers into an array @@ -859,7 +859,7 @@ If you want to specify a port other than 53, separate it with a hash.\ esac # Clean user input and replace whitespace with comma. - piholeDNS=$(sed 's/[, \t]\+/,/g' <<<"${piholeDNS}") + piholeDNS="${piholeDNS//[[:blank:]]/,}" # Separate the user input into the two DNS values (separated by a comma) printf -v PIHOLE_DNS_1 "%s" "${piholeDNS%%,*}" @@ -915,7 +915,7 @@ If you want to specify a port other than 53, separate it with a hash.\ done else # Save the old Internal Field Separator in a variable, - OIFS=$IFS + OIFS=${IFS} # and set the new one to newline IFS=$'\n' for DNSServer in ${DNS_SERVERS}; do @@ -1636,9 +1636,9 @@ check_download_exists() { status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1) # Check the status code - if grep -q "200" <<<"$status"; then + if grep -q "200" <<<"${status}"; then return 0 - elif grep -q "404" <<<"$status"; then + elif grep -q "404" <<<"${status}"; then return 1 fi @@ -1671,7 +1671,7 @@ get_available_branches() { # Get reachable remote branches, but store STDERR as STDOUT variable output=$({ git ls-remote --heads --quiet | cut -d'/' -f3- -; } 2>&1) # echo status for calling function to capture - echo "$output" + echo "${output}" return } @@ -1704,9 +1704,9 @@ checkout_pull_branch() { oldbranch="$(git symbolic-ref HEAD)" str="Switching to branch: '${branch}' from '${oldbranch}'" - printf " %b %s" "${INFO}" "$str" + printf " %b %s" "${INFO}" "${str}" git checkout "${branch}" --quiet || return 1 - printf "%b %b %s\\n" "${OVER}" "${TICK}" "$str" + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" # Data in the repositories is public anyway so we can make it readable by everyone (+r to keep executable permission if already set by git) chmod -R a+rX "${directory}" @@ -1913,7 +1913,7 @@ get_binary_name() { l_binary="pihole-FTL-riscv64" else # Something else - we try to use 32bit executable and warn the user - if [[ ! "${machine}" == "i686" ]]; then + if [[ "${machine}" != "i686" ]]; then printf "%b %b %s...\\n" "${OVER}" "${CROSS}" "${str}" printf " %b %bNot able to detect architecture (unknown: %s), trying x86 (32bit) executable%b\\n" "${INFO}" "${COL_RED}" "${machine}" "${COL_NC}" printf " %b Contact Pi-hole Support if you experience issues (e.g: FTL not running)\\n" "${INFO}" @@ -1947,14 +1947,14 @@ FTLcheckUpdate() { local remoteSha1 local localSha1 - if [[ ! "${ftlBranch}" == "master" ]]; then + if [[ "${ftlBranch}" != "master" ]]; then # This is not the master branch local path path="${ftlBranch}/${binary}" # Check whether or not the binary for this FTL branch actually exists. If not, then there is no update! local status - if ! check_download_exists "$path"; then + if ! check_download_exists "${path}"; then status=$? if [ "${status}" -eq 1 ]; then printf " %b Branch \"%s\" is not available.\\n" "${INFO}" "${ftlBranch}" @@ -2057,11 +2057,11 @@ make_temporary_log() { TEMPLOG=$(mktemp /tmp/pihole_temp.XXXXXX) # Open handle 3 for templog # https://stackoverflow.com/questions/18460186/writing-outputs-to-log-file-and-console - exec 3>"$TEMPLOG" + exec 3>"${TEMPLOG}" # Delete templog, but allow for addressing via file handle # This lets us write to the log without having a temporary file on the drive, which # is meant to be a security measure so there is not a lingering file on the drive during the install process - rm "$TEMPLOG" + rm "${TEMPLOG}" } copy_to_install_log() { @@ -2351,7 +2351,7 @@ main() { if [ -n "${PIHOLE_DNS_1}" ]; then local string="\"${PIHOLE_DNS_1}\"" [ -n "${PIHOLE_DNS_2}" ] && string+=", \"${PIHOLE_DNS_2}\"" - setFTLConfigValue "dns.upstreams" "[ $string ]" + setFTLConfigValue "dns.upstreams" "[ ${string} ]" fi if [ -n "${QUERY_LOGGING}" ]; then From 5ed52554d741061a6bb81cea477e4b9dbd340a5f Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Mon, 11 Aug 2025 14:51:59 +0100 Subject: [PATCH 186/259] Move unattended check to the top of the script - exit early if `/etc/pihole/pihole.toml` file is not found, Signed-off-by: Adam Warner --- automated install/basic-install.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index daacb9a3..35975844 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -167,6 +167,17 @@ for var in "$@"; do esac done +if [[ "${runUnattended}" == true ]]; then + # In order to run an unattended setup, a pre-seeded /etc/pihole/pihole.toml must exist + if [[ ! -f "${PI_HOLE_CONFIG_DIR}/pihole.toml" ]]; then + printf " %b Error: \"%s\" not found. Cannot run unattended setup\\n" "${CROSS}" "${PI_HOLE_CONFIG_DIR}/pihole.toml" + exit 1 + fi + printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" + # also disable debconf-apt-progress dialogs + export DEBIAN_FRONTEND="noninteractive" +fi + # If the color table file exists, if [[ -f "${coltable}" ]]; then # source it @@ -2242,15 +2253,6 @@ main() { exit 1 fi - if [[ "${fresh_install}" == false ]]; then - # if it's running unattended, - if [[ "${runUnattended}" == true ]]; then - printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" - # also disable debconf-apt-progress dialogs - export DEBIAN_FRONTEND="noninteractive" - fi - fi - if [[ "${fresh_install}" == true ]]; then # Display welcome dialogs welcomeDialogs From ea274073b4ffed226256485175e680c0beeb6b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 13 Aug 2025 06:27:19 +0200 Subject: [PATCH 187/259] Add Debian 13 Trixie to the test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 1 + test/_debian_13.Dockerfile | 16 ++++++++++++++++ test/tox.debian_13.ini | 10 ++++++++++ 3 files changed, 27 insertions(+) create mode 100644 test/_debian_13.Dockerfile create mode 100644 test/tox.debian_13.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c2e8f951..e3037854 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -65,6 +65,7 @@ jobs: [ debian_11, debian_12, + debian_13, ubuntu_20, ubuntu_22, ubuntu_24, diff --git a/test/_debian_13.Dockerfile b/test/_debian_13.Dockerfile new file mode 100644 index 00000000..cfff2235 --- /dev/null +++ b/test/_debian_13.Dockerfile @@ -0,0 +1,16 @@ +FROM buildpack-deps:trixie-scm + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/tox.debian_13.ini b/test/tox.debian_13.ini new file mode 100644 index 00000000..dcfbf816 --- /dev/null +++ b/test/tox.debian_13.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv:py3] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _debian_13.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py From 9e258e70058fa86c947ee53e30c934d66547c224 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 15 Aug 2025 19:39:21 +0200 Subject: [PATCH 188/259] Rename views, upgrade gravity database and bump gravity databae version Signed-off-by: DL6ER --- .../Scripts/database_migration/gravity-db.sh | 6 +++ .../database_migration/gravity/19_to_20.sql | 43 +++++++++++++++++++ advanced/Scripts/piholeDebug.sh | 4 +- advanced/Templates/gravity.db.sql | 10 ++--- gravity.sh | 2 +- manpages/pihole.8 | 2 +- 6 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 advanced/Scripts/database_migration/gravity/19_to_20.sql diff --git a/advanced/Scripts/database_migration/gravity-db.sh b/advanced/Scripts/database_migration/gravity-db.sh index 41593368..5cf4cc34 100755 --- a/advanced/Scripts/database_migration/gravity-db.sh +++ b/advanced/Scripts/database_migration/gravity-db.sh @@ -150,4 +150,10 @@ upgrade_gravityDB(){ pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/18_to_19.sql" version=19 fi + if [[ "$version" == "19" ]]; then + # Update views to use new allowlist/denylist names + echo -e " ${INFO} Upgrading gravity database from version 19 to 20" + pihole-FTL sqlite3 -ni "${database}" < "${scriptPath}/19_to_20.sql" + version=20 + fi } diff --git a/advanced/Scripts/database_migration/gravity/19_to_20.sql b/advanced/Scripts/database_migration/gravity/19_to_20.sql new file mode 100644 index 00000000..1867615d --- /dev/null +++ b/advanced/Scripts/database_migration/gravity/19_to_20.sql @@ -0,0 +1,43 @@ +.timeout 30000 + +BEGIN TRANSACTION; + +DROP VIEW vw_whitelist; +CREATE VIEW vw_allowlist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id + FROM domainlist + LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id + LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id + WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1) + AND domainlist.type = 0 + ORDER BY domainlist.id; + +DROP VIEW vw_blacklist; +CREATE VIEW vw_denylist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id + FROM domainlist + LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id + LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id + WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1) + AND domainlist.type = 1 + ORDER BY domainlist.id; + +DROP VIEW vw_regex_whitelist; +CREATE VIEW vw_regex_allowlist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id + FROM domainlist + LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id + LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id + WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1) + AND domainlist.type = 2 + ORDER BY domainlist.id; + +DROP VIEW vw_regex_blacklist; +CREATE VIEW vw_regex_denylist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id + FROM domainlist + LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id + LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id + WHERE domainlist.enabled = 1 AND (domainlist_by_group.group_id IS NULL OR "group".enabled = 1) + AND domainlist.type = 3 + ORDER BY domainlist.id; + +UPDATE info SET value = 20 WHERE property = 'version'; + +COMMIT; diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 2b903e50..c0254cd2 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -672,7 +672,7 @@ dig_at() { local record_type="A" fi - # Find a random blocked url that has not been whitelisted and is not ABP style. + # Find a random blocked url that has not been allowlisted and is not ABP style. # This helps emulate queries to different domains that a user might query # It will also give extra assurance that Pi-hole is correctly resolving and blocking domains local random_url @@ -1088,7 +1088,7 @@ show_adlists() { } show_domainlist() { - show_db_entries "Domainlist (0/1 = exact white-/blacklist, 2/3 = regex white-/blacklist)" "SELECT id,CASE type WHEN '0' THEN '0 ' WHEN '1' THEN ' 1 ' WHEN '2' THEN ' 2 ' WHEN '3' THEN ' 3' ELSE type END type,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 4 7 12 100 19 19 50" + show_db_entries "Domainlist (0/1 = exact allow-/denylist, 2/3 = regex allow-/denylist)" "SELECT id,CASE type WHEN '0' THEN '0 ' WHEN '1' THEN ' 1 ' WHEN '2' THEN ' 2 ' WHEN '3' THEN ' 3' ELSE type END type,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 4 7 12 100 19 19 50" } show_clients() { diff --git a/advanced/Templates/gravity.db.sql b/advanced/Templates/gravity.db.sql index 0187e4e6..9aad6113 100644 --- a/advanced/Templates/gravity.db.sql +++ b/advanced/Templates/gravity.db.sql @@ -66,7 +66,7 @@ CREATE TABLE info value TEXT NOT NULL ); -INSERT INTO "info" VALUES('version','19'); +INSERT INTO "info" VALUES('version','20'); /* This is a flag to indicate if gravity was restored from a backup false = not restored, failed = restoration failed due to no backup @@ -111,7 +111,7 @@ CREATE TRIGGER tr_domainlist_update AFTER UPDATE ON domainlist UPDATE domainlist SET date_modified = (cast(strftime('%s', 'now') as int)) WHERE domain = NEW.domain; END; -CREATE VIEW vw_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id +CREATE VIEW vw_allowlist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id FROM domainlist LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id @@ -119,7 +119,7 @@ CREATE VIEW vw_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_gr AND domainlist.type = 0 ORDER BY domainlist.id; -CREATE VIEW vw_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id +CREATE VIEW vw_denylist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id FROM domainlist LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id @@ -127,7 +127,7 @@ CREATE VIEW vw_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_gr AND domainlist.type = 1 ORDER BY domainlist.id; -CREATE VIEW vw_regex_whitelist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id +CREATE VIEW vw_regex_allowlist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id FROM domainlist LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id @@ -135,7 +135,7 @@ CREATE VIEW vw_regex_whitelist AS SELECT domain, domainlist.id AS id, domainlist AND domainlist.type = 2 ORDER BY domainlist.id; -CREATE VIEW vw_regex_blacklist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id +CREATE VIEW vw_regex_denylist AS SELECT domain, domainlist.id AS id, domainlist_by_group.group_id AS group_id FROM domainlist LEFT JOIN domainlist_by_group ON domainlist_by_group.domainlist_id = domainlist.id LEFT JOIN "group" ON "group".id = domainlist_by_group.group_id diff --git a/gravity.sh b/gravity.sh index fd5d45de..5e64238d 100755 --- a/gravity.sh +++ b/gravity.sh @@ -851,7 +851,7 @@ gravity_Table_Count() { fi } -# Output count of blacklisted domains and regex filters +# Output count of denied and allowed domains and regex filters gravity_ShowCount() { # Here we use the table "gravity" instead of the view "vw_gravity" for speed. # It's safe to replace it here, because right after a gravity run both will show the exactly same number of domains. diff --git a/manpages/pihole.8 b/manpages/pihole.8 index 7843f9ce..ac3146ba 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -268,7 +268,7 @@ Allow-/denylist manipulation \fBpihole --regex "ad.*\\.example\\.com$"\fR .br - Adds "ad.*\\.example\\.com$" to the regex blacklist. + Adds "ad.*\\.example\\.com$" to the regex denylist. Would block all subdomains of example.com which start with "ad" .br From 6e9e961d3c1381079380fb2d3d2f80633299c318 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 10:23:35 +0000 Subject: [PATCH 189/259] Bump actions/checkout in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.2 to 5.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.2...v5.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/test.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 77aacbec..b41b7b11 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 34ffb64e..557c749f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 7df1a32d..856fe4ea 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -33,7 +33,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c2e8f951..ee61c30a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 with: fetch-depth: 0 # Differential ShellCheck requires full git history @@ -78,7 +78,7 @@ jobs: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@v5.0.0 - name: Set up Python uses: actions/setup-python@v5.6.0 From 0db48383ae9a5c8ffb0da44a79ec86d16bb36d18 Mon Sep 17 00:00:00 2001 From: "Michael Ziminsky (Z)" Date: Mon, 2 Jun 2025 18:23:15 -0700 Subject: [PATCH 190/259] Add support for alpine Signed-off-by: Michael Ziminsky (Z) --- advanced/Templates/pihole-FTL.openrc | 40 +++++++++++++++++ automated install/basic-install.sh | 66 +++++++++++++++++++++++++--- gravity.sh | 7 ++- 3 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 advanced/Templates/pihole-FTL.openrc diff --git a/advanced/Templates/pihole-FTL.openrc b/advanced/Templates/pihole-FTL.openrc new file mode 100644 index 00000000..34a30a0b --- /dev/null +++ b/advanced/Templates/pihole-FTL.openrc @@ -0,0 +1,40 @@ +#!/sbin/openrc-run +# shellcheck shell=sh disable=SC2034 + +: "${PI_HOLE_SCRIPT_DIR:=/opt/pihole}" + +command="/usr/bin/pihole-FTL" +command_user="pihole:pihole" +supervisor=supervise-daemon +command_args_foreground="-f" +command_background=true +pidfile="/run/${RC_SVCNAME}_openrc.pid" +extra_started_commands="reload" + +respawn_max=5 +respawn_period=60 +capabilities="^CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN,CAP_SYS_TIME" + +depend() { + want net + provide dns +} + +checkconfig() { + $command -f test +} + +start_pre() { + sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-prestart.sh" +} + +stop_post() { + sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-poststop.sh" +} + +reload() { + checkconfig || return $? + ebegin "Reloading ${RC_SVCNAME}" + start-stop-daemon --signal HUP --pidfile "${pidfile}" + eend $? +} diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 9d3bd2b3..d5720df6 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -154,6 +154,34 @@ Pi-hole dependency meta package EOM ) +# List of required packages on APK based systems +PIHOLE_META_VERSION_APK=0.1 +PIHOLE_META_DEPS_APK=( + bash + bash-completion + bind-tools + binutils + coreutils + cronie + curl + dialog + git + grep + iproute2-ss + jq + libcap + logrotate + ncurses + nmap-ncat + procps-ng + psmisc + shadow + sudo + tzdata + unzip + wget +) + ######## Undocumented Flags. Shhh ######## # These are undocumented flags; some of which we can use when repairing an installation # The runUnattended flag is one example of this @@ -271,7 +299,15 @@ package_manager_detect() { PKG_COUNT="${PKG_MANAGER} check-update | grep -E '(.i686|.x86|.noarch|.arm|.src|.riscv64)' | wc -l || true" # The command we will use to remove packages (used in the uninstaller) PKG_REMOVE="${PKG_MANAGER} remove -y" - # If neither apt-get or yum/dnf package managers were found + + # If neither apt-get or yum/dnf package managers were found, check for apk. + elif is_command apk; then + PKG_MANAGER="apk" + UPDATE_PKG_CACHE="${PKG_MANAGER} update" + PKG_INSTALL="${PKG_MANAGER} add" + PKG_COUNT="${PKG_MANAGER} list --upgradable -q | wc -l" + PKG_REMOVE="${PKG_MANAGER} del" + else # we cannot install required packages printf " %b No supported package manager found\\n" "${CROSS}" @@ -282,13 +318,20 @@ package_manager_detect() { build_dependency_package(){ # This function will build a package that contains all the dependencies needed for Pi-hole + if is_command apk ; then + local str="APK based system detected. Dependencies will be installed using a virtual package named pihole-meta" + printf " %b %s...\\n" "${INFO}" "${str}" + return 0 + fi # remove any leftover build directory that may exist rm -rf /tmp/pihole-meta_* # Create a fresh build directory with random name + # Busybox Compat: `mktemp` long flags unsupported + # -d flag is short form of --directory local tempdir - tempdir="$(mktemp --directory /tmp/pihole-meta_XXXXX)" + tempdir="$(mktemp -d /tmp/pihole-meta_XXXXX)" chmod 0755 "${tempdir}" if is_command apt-get; then @@ -1177,7 +1220,12 @@ installConfigs() { # Load final service systemctl daemon-reload else - install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" '/etc/init.d/pihole-FTL' + local INIT="service" + if is_command openrc; then + INIT="openrc" + fi + + install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.${INIT}" '/etc/init.d/pihole-FTL' fi install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-prestart.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-prestart.sh" install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-poststop.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-poststop.sh" @@ -1266,6 +1314,8 @@ enable_service() { if is_command systemctl; then # use that to enable the service systemctl -q enable "${1}" + elif is_command openrc; then + rc-update add "${1}" "${2:-default}" &> /dev/null else # Otherwise, use update-rc.d to accomplish this update-rc.d "${1}" defaults >/dev/null @@ -1282,6 +1332,8 @@ disable_service() { if is_command systemctl; then # use that to disable the service systemctl -q disable "${1}" + elif is_command openrc; then + rc-update del "${1}" "${2:-default}" &> /dev/null else # Otherwise, use update-rc.d to accomplish this update-rc.d "${1}" disable >/dev/null @@ -1294,6 +1346,8 @@ check_service_active() { if is_command systemctl; then # use that to check the status of the service systemctl -q is-enabled "${1}" 2>/dev/null + elif is_command openrc; then + rc-status default boot | grep -q "${1}" else # Otherwise, fall back to service command service "${1}" status &>/dev/null @@ -1395,8 +1449,10 @@ install_dependent_packages() { printf " %b Error: Unable to find Pi-hole dependency package.\\n" "${COL_RED}" return 1 fi - - # If neither apt-get or yum/dnf package managers were found + # Install Alpine packages + elif is_command apk; then + ${PKG_INSTALL} -q -t "pihole-meta=${PIHOLE_META_VERSION_APK}" "${PIHOLE_META_DEPS_APK[@]}" &> /dev/null && + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else # we cannot install the dependency package printf " %b No supported package manager found\\n" "${CROSS}" diff --git a/gravity.sh b/gravity.sh index fd5d45de..a3b44279 100755 --- a/gravity.sh +++ b/gravity.sh @@ -118,9 +118,12 @@ gravity_swap_databases() { # Swap databases and remove or conditionally rename old database # Number of available blocks on disk - availableBlocks=$(stat -f --format "%a" "${gravityDIR}") + # Busybox Compat: `stat` long flags unsupported + # -f flag is short form of --file-system. + # -c flag is short form of --format. + availableBlocks=$(stat -f -c "%a" "${gravityDIR}") # Number of blocks, used by gravity.db - gravityBlocks=$(stat --format "%b" "${gravityDBfile}") + gravityBlocks=$(stat -c "%b" "${gravityDBfile}") # Only keep the old database if available disk space is at least twice the size of the existing gravity.db. # Better be safe than sorry... oldAvail=false From d75dae788d04679161d99cbe52ca6327ecb52469 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Tue, 15 Apr 2025 16:18:46 +1000 Subject: [PATCH 191/259] Alpine Linux tests Add Dockerfile and corresponding tox file to add alpine linux 3.21 & 3.22 to the test suite Add apk as another package manager in the automated install tests Use short switches for su command as busybox's su does not accept long switches here Add Alpine test to github workflow Signed-off-by: Michael Ziminsky (Z) --- .github/workflows/test.yml | 2 ++ test/_alpine_3_21.Dockerfile | 18 ++++++++++++++++++ test/_alpine_3_22.Dockerfile | 18 ++++++++++++++++++ test/test_any_automated_install.py | 14 +++++++++++++- test/tox.alpine_3_21.ini | 10 ++++++++++ test/tox.alpine_3_22.ini | 10 ++++++++++ 6 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 test/_alpine_3_21.Dockerfile create mode 100644 test/_alpine_3_22.Dockerfile create mode 100644 test/tox.alpine_3_21.ini create mode 100644 test/tox.alpine_3_22.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee61c30a..492e131b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -73,6 +73,8 @@ jobs: fedora_40, fedora_41, fedora_42, + alpine_3_21, + alpine_3_22, ] env: DISTRO: ${{matrix.distro}} diff --git a/test/_alpine_3_21.Dockerfile b/test/_alpine_3_21.Dockerfile new file mode 100644 index 00000000..d7b88f20 --- /dev/null +++ b/test/_alpine_3_21.Dockerfile @@ -0,0 +1,18 @@ +FROM alpine:3.21 + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole +RUN sed -i 's/#\(.*\/community\)/\1/' /etc/apk/repositories +RUN apk --no-cache add bash coreutils curl git jq openrc shadow + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/_alpine_3_22.Dockerfile b/test/_alpine_3_22.Dockerfile new file mode 100644 index 00000000..25beb4e0 --- /dev/null +++ b/test/_alpine_3_22.Dockerfile @@ -0,0 +1,18 @@ +FROM alpine:3.22 + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole +RUN sed -i 's/#\(.*\/community\)/\1/' /etc/apk/repositories +RUN apk --no-cache add bash coreutils curl git jq openrc shadow + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index cf4b454d..0a561b36 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -22,6 +22,7 @@ def test_supported_package_manager(host): # break supported package managers host.run("rm -rf /usr/bin/apt-get") host.run("rm -rf /usr/bin/rpm") + host.run("rm -rf /sbin/apk") package_manager_detect = host.run( """ source /opt/pihole/basic-install.sh @@ -77,10 +78,21 @@ def test_installPihole_fresh_install_readableFiles(host): }, host, ) + mock_command_2( + "rc-service", + { + "rc-service pihole-FTL enable": ("", "0"), + "rc-service pihole-FTL restart": ("", "0"), + "rc-service pihole-FTL start": ("", "0"), + "*": ('echo "rc-service call with $@"', "0"), + }, + host, + ) # try to install man host.run("command -v apt-get > /dev/null && apt-get install -qq man") host.run("command -v dnf > /dev/null && dnf install -y man") host.run("command -v yum > /dev/null && yum install -y man") + host.run("command -v apk > /dev/null && apk add mandoc man-pages") # Workaround to get FTLv6 installed until it reaches master branch host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch') install = host.run( @@ -103,7 +115,7 @@ def test_installPihole_fresh_install_readableFiles(host): maninstalled = False piholeuser = "pihole" exit_status_success = 0 - test_cmd = 'su --shell /bin/bash --command "test -{0} {1}" -p {2}' + test_cmd = 'su -s /bin/bash -c "test -{0} {1}" -p {2}' # check files in /etc/pihole for read, write and execute permission check_etc = test_cmd.format("r", "/etc/pihole", piholeuser) actual_rc = host.run(check_etc).rc diff --git a/test/tox.alpine_3_21.ini b/test/tox.alpine_3_21.ini new file mode 100644 index 00000000..b0465f6c --- /dev/null +++ b/test/tox.alpine_3_21.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv:py3] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _alpine_3_21.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py diff --git a/test/tox.alpine_3_22.ini b/test/tox.alpine_3_22.ini new file mode 100644 index 00000000..38f66c4f --- /dev/null +++ b/test/tox.alpine_3_22.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv:py3] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _alpine_3_22.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py From 4bf67a3c7923baf112a030a8ae1097ef86c117c5 Mon Sep 17 00:00:00 2001 From: "Michael Ziminsky (Z)" Date: Thu, 26 Jun 2025 22:53:55 -0700 Subject: [PATCH 192/259] Alpine: Add some additional dependencies and minor script fixes Signed-off-by: Michael Ziminsky (Z) --- advanced/Scripts/piholeDebug.sh | 2 +- advanced/Scripts/piholeLogFlush.sh | 2 +- automated install/basic-install.sh | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 2b903e50..a478b845 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -778,7 +778,7 @@ process_status(){ : else # non-Docker system - if service "${i}" status | grep -E 'is\srunning' &> /dev/null; then + if service "${i}" status | grep -q -E 'is\srunning|started'; then status_of_process="active" else status_of_process="inactive" diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ca70f31b..ac28aed9 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -86,6 +86,7 @@ if [[ "$*" == *"once"* ]]; then if [[ "$*" != *"quiet"* ]]; then echo -ne " ${INFO} Running logrotate ..." fi + mkdir -p "${STATEFILE%/*}" /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate else # Handle rotation for each log file @@ -115,4 +116,3 @@ else echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" fi fi - diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d5720df6..601183e7 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -167,12 +167,14 @@ PIHOLE_META_DEPS_APK=( dialog git grep - iproute2-ss + iproute2-minimal # piholeARPTable.sh + iproute2-ss # piholeDebug.sh jq libcap logrotate + lscpu # piholeDebug.sh + lshw # piholeDebug.sh ncurses - nmap-ncat procps-ng psmisc shadow From 44f95a4f576f40f21a80d91534af1239caec4e8a Mon Sep 17 00:00:00 2001 From: "Michael Ziminsky (Z)" Date: Wed, 9 Jul 2025 15:28:51 -0700 Subject: [PATCH 193/259] Alpine: Ensure community repo is enabled and handle dependency install errors Signed-off-by: Michael Ziminsky (Z) --- automated install/basic-install.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 601183e7..aaf10cd7 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1453,8 +1453,25 @@ install_dependent_packages() { fi # Install Alpine packages elif is_command apk; then - ${PKG_INSTALL} -q -t "pihole-meta=${PIHOLE_META_VERSION_APK}" "${PIHOLE_META_DEPS_APK[@]}" &> /dev/null && + local repo_str="Ensuring alpine 'community' repo is enabled." + printf "%b %b %s" "${OVER}" "${INFO}" "${repo_str}" + + local pattern='^\s*#(.*/community/?)\s*$' + sed -Ei "s:${pattern}:\1:" /etc/apk/repositories + if grep -Eq "${pattern}" /etc/apk/repositories; then + # Repo still commented out = Failure + printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${repo_str}" + else + printf "%b %b %s\\n" "${OVER}" "${TICK}" "${repo_str}" + fi + printf " %b %s..." "${INFO}" "${str}" + if { ${PKG_INSTALL} -q -t "pihole-meta=${PIHOLE_META_VERSION_APK}" "${PIHOLE_META_DEPS_APK[@]}" &>/dev/null; }; then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" + else + printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" + printf " %b Error: Unable to install Pi-hole dependency package.\\n" "${COL_RED}" + return 1 + fi else # we cannot install the dependency package printf " %b No supported package manager found\\n" "${CROSS}" From 3908be911c30ceb8d728f332d92009ce2535b84d Mon Sep 17 00:00:00 2001 From: "Michael Ziminsky (Z)" Date: Mon, 14 Jul 2025 09:29:51 -0700 Subject: [PATCH 194/259] Alpine: Switch cron service from busybox to cronie during install Signed-off-by: Michael Ziminsky (Z) --- automated install/basic-install.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index aaf10cd7..5daf2622 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1496,6 +1496,15 @@ installCron() { # Randomize update checker time sed -i "s/59 17/$((1 + RANDOM % 58)) $((12 + RANDOM % 8))/" /etc/cron.d/pihole printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" + + # Switch off of busybox cron on alpine + if is_command openrc; then + printf " %b Switching from busybox crond to cronie...\\n" "${INFO}" + stop_service crond + disable_service crond + enable_service cronie + restart_service cronie + fi } # Gravity is a very important script as it aggregates all of the domains into a single HOSTS formatted list, From f50a4c1c89fabbd87cf5922e830188e5f166d20c Mon Sep 17 00:00:00 2001 From: "Michael Ziminsky (Z)" Date: Wed, 30 Jul 2025 12:32:39 -0700 Subject: [PATCH 195/259] Don't use hard-coded path for pihole user `nologin` shell Signed-off-by: Michael Ziminsky (Z) --- automated install/basic-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 5daf2622..d2871ec8 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1554,7 +1554,7 @@ create_pihole_user() { # then create and add her to the pihole group local str="Creating user 'pihole'" printf "%b %b %s..." "${OVER}" "${INFO}" "${str}" - if useradd -r --no-user-group -g pihole -s /usr/sbin/nologin pihole; then + if useradd -r --no-user-group -g pihole -s "$(command -v nologin)" pihole; then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" @@ -1569,7 +1569,7 @@ create_pihole_user() { # create and add pihole user to the pihole group local str="Creating user 'pihole'" printf "%b %b %s..." "${OVER}" "${INFO}" "${str}" - if useradd -r --no-user-group -g pihole -s /usr/sbin/nologin pihole; then + if useradd -r --no-user-group -g pihole -s "$(command -v nologin)" pihole; then printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}" else printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" From 7140953500e07052279a180d9f325544505d1ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 20 Aug 2025 18:43:22 +0200 Subject: [PATCH 196/259] Use SHA to pin github actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/merge-conflict.yml | 2 +- .github/workflows/stale.yml | 4 ++-- .github/workflows/stale_pr.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/test.yml | 14 +++++++------- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b41b7b11..2c01ef1b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 diff --git a/.github/workflows/merge-conflict.yml b/.github/workflows/merge-conflict.yml index f169ab6f..5dca98ba 100644 --- a/.github/workflows/merge-conflict.yml +++ b/.github/workflows/merge-conflict.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check if PRs are have merge conflicts - uses: eps1lon/actions-label-merge-conflict@v3.0.3 + uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 #v3.0.3 with: dirtyLabel: "PR: Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 557c749f..42ea2537 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: issues: write steps: - - uses: actions/stale@v9.1.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/stale_pr.yml index 6952dcab..3e5729ce 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/stale_pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v9.1.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Do not automatically mark PR/issue as stale diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 856fe4ea..b8546b64 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -33,7 +33,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ee61c30a..4c95d362 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 with: fetch-depth: 0 # Differential ShellCheck requires full git history @@ -31,25 +31,25 @@ jobs: [[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!" - name: Differential ShellCheck - uses: redhat-plumbers-in-action/differential-shellcheck@v5 + uses: redhat-plumbers-in-action/differential-shellcheck@0d9e5b29625f871e6a4215380486d6f1a7cb6cdd #v5.5.5 with: severity: warning display-engine: sarif-fmt - name: Spell-Checking - uses: codespell-project/actions-codespell@master + uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 #v2.1 with: ignore_words_file: .codespellignore - name: Get editorconfig-checker - uses: editorconfig-checker/action-editorconfig-checker@main # tag v1.0.0 is really out of date + uses: editorconfig-checker/action-editorconfig-checker@main # tag v2. is really out of date - name: Run editorconfig-checker run: editorconfig-checker - name: Check python code formatting with black - uses: psf/black@stable + uses: psf/black@8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b #25.1.0 with: src: "./test" options: "--check --diff --color" @@ -78,10 +78,10 @@ jobs: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 - name: Set up Python - uses: actions/setup-python@v5.6.0 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 #v5.6.0 with: python-version: "3.13" From 87f307f1d8088962a4bcc1a0fd2b9da9405a9f7d Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Fri, 29 Aug 2025 08:47:00 +1000 Subject: [PATCH 197/259] Uninstall refactor Split removePiholeFiles into functions for each category. Reorder execution so that: Pihole-FTL is stopped and removed before shutdown scripts are removed. User and group are removed before needed commands are removed. Remove database and log files in user-specified non-default locations, and use local directories from basic install.sh, falling back to defaults. Remove use of sudo as the script already checks that it is called as root. Advise user of location of crontab backup if is created Make use of service control functions, command detection and default directories from basic_install.sh Align variable names with current basic-install.sh Disable pihole-FTL service immediately, if systemctl is available Call systemd daemon-reload after removing service files (on systemd systems) Signed-off-by: Rob Gill --- automated install/basic-install.sh | 3 +- automated install/uninstall.sh | 209 +++++++++++++++++++---------- 2 files changed, 138 insertions(+), 74 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d2871ec8..318107c1 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1333,9 +1333,10 @@ disable_service() { # If systemctl exists, if is_command systemctl; then # use that to disable the service - systemctl -q disable "${1}" + systemctl -q disable --now "${1}" elif is_command openrc; then rc-update del "${1}" "${2:-default}" &> /dev/null + else # Otherwise, use update-rc.d to accomplish this update-rc.d "${1}" disable >/dev/null diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index dfe0871e..6d307de4 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -12,9 +12,7 @@ source "/opt/pihole/COL_TABLE" # shellcheck source="./advanced/Scripts/utils.sh" source "/opt/pihole/utils.sh" - -ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") -readonly ADMIN_INTERFACE_DIR +# getFTLConfigValue() from utils.sh while true; do read -rp " ${QST} Are you sure you would like to remove ${COL_BOLD}Pi-hole${COL_NC}? [y/N] " answer @@ -29,126 +27,179 @@ str="Root user check" if [[ ${EUID} -eq 0 ]]; then echo -e " ${TICK} ${str}" else - # Check if sudo is actually installed - # If it isn't, exit because the uninstall can not complete - if [ -x "$(command -v sudo)" ]; then - export SUDO="sudo" - else - echo -e " ${CROSS} ${str} - Script called with non-root privileges - The Pi-hole requires elevated privileges to uninstall" - exit 1 - fi + echo -e " ${CROSS} ${str} + Script called with non-root privileges + The Pi-hole requires elevated privileges to uninstall" + exit 1 fi -readonly PI_HOLE_FILES_DIR="/etc/.pihole" +# Get paths for admin interface, log files and database files, +# to allow deletion where user has specified a non-default location +ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") +FTL_LOG=$(getFTLConfigValue "files.log.ftl") +DNSMASQ_LOG=$(getFTLConfigValue "files.log.dnsmasq") +WEBSERVER_LOG=$(getFTLConfigValue "files.log.webserver") +PIHOLE_DB=$(getFTLConfigValue "files.database") +GRAVITY_DB=$(getFTLConfigValue "files.gravity") +MACVENDOR_DB=$(getFTLConfigValue "files.macvendor") + +PI_HOLE_LOCAL_REPO="/etc/.pihole" +# Setting SKIP_INSTALL="true" to source the installer functions without running them SKIP_INSTALL="true" # shellcheck source="./automated install/basic-install.sh" -source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" - -# package_manager_detect() sourced from basic-install.sh -package_manager_detect - +source "${PI_HOLE_LOCAL_REPO}/automated install/basic-install.sh" +# Functions and Variables sources from basic-install: +# package_manager_detect(), disable_service(), stop_service(), +# restart service() and is_command() +# PI_HOLE_CONFIG_DIR PI_HOLE_INSTALL_DIR PI_HOLE_LOCAL_REPO removeMetaPackage() { # Purge Pi-hole meta package echo "" echo -ne " ${INFO} Removing Pi-hole meta package..."; - eval "${SUDO}" "${PKG_REMOVE}" "pihole-meta" &> /dev/null; + eval "${PKG_REMOVE}" "pihole-meta" &> /dev/null; echo -e "${OVER} ${INFO} Removed Pi-hole meta package"; - } -removePiholeFiles() { +removeWebInterface() { # Remove the web interface of Pi-hole echo -ne " ${INFO} Removing Web Interface..." - ${SUDO} rm -rf "${ADMIN_INTERFACE_DIR}" &> /dev/null + rm -rf "${ADMIN_INTERFACE_DIR:-/var/www/html/admin/}" &> /dev/null echo -e "${OVER} ${TICK} Removed Web Interface" +} - # Attempt to preserve backwards compatibility with older versions - # to guarantee no additional changes were made to /etc/crontab after - # the installation of pihole, /etc/crontab.pihole should be permanently - # preserved. - if [[ -f /etc/crontab.orig ]]; then - ${SUDO} mv /etc/crontab /etc/crontab.pihole - ${SUDO} mv /etc/crontab.orig /etc/crontab - ${SUDO} service cron restart - echo -e " ${TICK} Restored the default system cron" - fi +removeFTL() { + # Remove FTL and stop any running FTL service + if is_command "pihole-FTL"; then + # service stop & disable from basic_install.sh + stop_service pihole-FTL + disable_service pihole-FTL - # Attempt to preserve backwards compatibility with older versions - if [[ -f /etc/cron.d/pihole ]];then - ${SUDO} rm -f /etc/cron.d/pihole &> /dev/null - echo -e " ${TICK} Removed /etc/cron.d/pihole" - fi - - ${SUDO} rm -rf /var/log/*pihole* &> /dev/null - ${SUDO} rm -rf /var/log/pihole/*pihole* &> /dev/null - ${SUDO} rm -rf /etc/pihole/ &> /dev/null - ${SUDO} rm -rf /etc/.pihole/ &> /dev/null - ${SUDO} rm -rf /opt/pihole/ &> /dev/null - ${SUDO} rm -f /usr/local/bin/pihole &> /dev/null - ${SUDO} rm -f /etc/bash_completion.d/pihole &> /dev/null - ${SUDO} rm -f /etc/bash_completion.d/pihole-FTL &> /dev/null - ${SUDO} rm -f /etc/sudoers.d/pihole &> /dev/null - echo -e " ${TICK} Removed config files" - - # Restore Resolved - if [[ -e /etc/systemd/resolved.conf.orig ]] || [[ -e /etc/systemd/resolved.conf.d/90-pi-hole-disable-stub-listener.conf ]]; then - ${SUDO} cp -p /etc/systemd/resolved.conf.orig /etc/systemd/resolved.conf &> /dev/null || true - ${SUDO} rm -f /etc/systemd/resolved.conf.d/90-pi-hole-disable-stub-listener.conf - systemctl reload-or-restart systemd-resolved - fi - - # Remove FTL - if command -v pihole-FTL &> /dev/null; then echo -ne " ${INFO} Removing pihole-FTL..." - if [[ -x "$(command -v systemctl)" ]]; then - systemctl stop pihole-FTL - else - service pihole-FTL stop - fi - ${SUDO} rm -f /etc/systemd/system/pihole-FTL.service + rm -f /etc/systemd/system/pihole-FTL.service &> /dev/null if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then read -rp " ${QST} FTL service override directory /etc/systemd/system/pihole-FTL.service.d detected. Do you wish to remove this from your system? [y/N] " answer case $answer in [yY]*) echo -ne " ${INFO} Removing /etc/systemd/system/pihole-FTL.service.d..." - ${SUDO} rm -R /etc/systemd/system/pihole-FTL.service.d + rm -R /etc/systemd/system/pihole-FTL.service.d &> /dev/null echo -e "${OVER} ${INFO} Removed /etc/systemd/system/pihole-FTL.service.d" ;; *) echo -e " ${INFO} Leaving /etc/systemd/system/pihole-FTL.service.d in place.";; esac fi - ${SUDO} rm -f /etc/init.d/pihole-FTL - ${SUDO} rm -f /usr/bin/pihole-FTL + rm -f /etc/init.d/pihole-FTL &> /dev/null + rm -f /usr/bin/pihole-FTL &> /dev/null echo -e "${OVER} ${TICK} Removed pihole-FTL" + + # Force systemd reload after service files are removed + if is_command "systemctl"; then + echo -ne " ${INFO} Restarting systemd..." + systemctl daemon-reload + echo -e "${OVER} ${TICK} Restarted systemd..." + fi + fi +} + +removeCronFiles() { + # Attempt to preserve backwards compatibility with older versions + # to guarantee no additional changes were made to /etc/crontab after + # the installation of pihole, /etc/crontab.pihole should be permanently + # preserved. + if [[ -f /etc/crontab.orig ]]; then + mv /etc/crontab /etc/crontab.pihole + mv /etc/crontab.orig /etc/crontab + restart_service cron + echo -e " ${TICK} Restored the default system cron" + echo -e " ${INFO} A backup of the most recent crontab is saved at /etc/crontab.pihole" fi - # If the pihole manpage exists, then delete and rebuild man-db + # Attempt to preserve backwards compatibility with older versions + if [[ -f /etc/cron.d/pihole ]];then + rm -f /etc/cron.d/pihole &> /dev/null + echo -e " ${TICK} Removed /etc/cron.d/pihole" + fi +} + +removePiholeFiles() { + # Remove databases (including user specified non-default paths) + rm -f "${PIHOLE_DB:-/etc/pihole/pihole-FTL.db}" &> /dev/null + rm -f "${GRAVITY_DB:-/etc/pihole/gravity.db}" &> /dev/null + rm -f "${MACVENDOR_DB:-/etc/pihole/macvendor.db}" &> /dev/null + + # Remove pihole config, repo and local files + rm -rf "${PI_HOLE_CONFIG_DIR:-/etc/pihole}" &> /dev/null + rm -rf "${PI_HOLE_LOCAL_REPO:-/etc/.pihole}" &> /dev/null + rm -rf "${PI_HOLE_INSTALL_DIR:-/opt/pihole}" &> /dev/null + + # Remove log files (including user specified non-default paths) + # and rotated logs + # Explicitly escape spaces, in case of trailing space in path before wildcard + rm -f "$(printf '%q' "${FTL_LOG:-/var/log/pihole/FTL.log}")*" &> /dev/null + rm -f "$(printf '%q' "${DNSMASQ_LOG:-/var/log/pihole/pihole.log}")*" &> /dev/null + rm -f "$(printf '%q' "${WEBSERVER_LOG:-/var/log/pihole/webserver.log}")*" &> /dev/null + + # remove any remnant log-files from old versions + rm -rf /var/log/*pihole* &> /dev/null + + # remove log directory + rm -rf /var/log/pihole &> /dev/null + + # remove the pihole command + rm -f /usr/local/bin/pihole &> /dev/null + + # remove Pi-hole's bash completion + rm -f /etc/bash_completion.d/pihole &> /dev/null + rm -f /etc/bash_completion.d/pihole-FTL &> /dev/null + + # Remove pihole from sudoers for compatibility with old versions + rm -f /etc/sudoers.d/pihole &> /dev/null + + echo -e " ${TICK} Removed config files" +} + +removeManPage() { + # If the pihole manpage exists, then delete if [[ -f /usr/local/share/man/man8/pihole.8 ]]; then - ${SUDO} rm -f /usr/local/share/man/man8/pihole.8 /usr/local/share/man/man8/pihole-FTL.8 /usr/local/share/man/man5/pihole-FTL.conf.5 - ${SUDO} mandb -q &>/dev/null + rm -f /usr/local/share/man/man8/pihole.8 /usr/local/share/man/man8/pihole-FTL.8 /usr/local/share/man/man5/pihole-FTL.conf.5 + # Rebuild man-db if present + if is_command "mandb"; then + mandb -q &>/dev/null + fi echo -e " ${TICK} Removed pihole man page" fi +} +removeUser() { # If the pihole user exists, then remove if id "pihole" &> /dev/null; then - if ${SUDO} userdel -r pihole 2> /dev/null; then + if userdel -r pihole 2> /dev/null; then echo -e " ${TICK} Removed 'pihole' user" else echo -e " ${CROSS} Unable to remove 'pihole' user" fi fi + # If the pihole group exists, then remove if getent group "pihole" &> /dev/null; then - if ${SUDO} groupdel pihole 2> /dev/null; then + if groupdel pihole 2> /dev/null; then echo -e " ${TICK} Removed 'pihole' group" else echo -e " ${CROSS} Unable to remove 'pihole' group" fi fi +} +restoreResolved() { + # Restore Resolved from saved configuration, if present + if [[ -e /etc/systemd/resolved.conf.orig ]] || [[ -e /etc/systemd/resolved.conf.d/90-pi-hole-disable-stub-listener.conf ]]; then + cp -p /etc/systemd/resolved.conf.orig /etc/systemd/resolved.conf &> /dev/null || true + rm -f /etc/systemd/resolved.conf.d/90-pi-hole-disable-stub-listener.conf &> /dev/null + systemctl reload-or-restart systemd-resolved + fi +} + +completionMessage() { echo -e "\\n We're sorry to see you go, but thanks for checking out Pi-hole! If you need help, reach out to us on GitHub, Discourse, Reddit or Twitter Reinstall at any time: ${COL_BOLD}curl -sSL https://install.pi-hole.net | bash${COL_NC} @@ -159,5 +210,17 @@ removePiholeFiles() { } ######### SCRIPT ########### +# The ordering here allows clean uninstallation with nothing +# removed before anything that depends upon it. +# eg removeFTL relies on scripts removed by removePiholeFiles +# removeUser relies on commands removed by removeMetaPackage +package_manager_detect +removeWebInterface +removeCronFiles +restoreResolved +removeManPage +removeFTL +removeUser removeMetaPackage removePiholeFiles +completionMessage From 59ccfd6d139275d8198826937eb0bab47982972d Mon Sep 17 00:00:00 2001 From: Jon Herron Date: Tue, 23 Sep 2025 20:11:17 -0400 Subject: [PATCH 198/259] Fix typo found during install Signed-off-by: Jon Herron --- automated install/basic-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 318107c1..f843a972 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2488,7 +2488,7 @@ main() { \\n\\nIPv4: ${IPV4_ADDRESS%/*}\ \\nIPv6: ${IPV6_ADDRESS:-"Not Configured"}\ \\nIf you have not done so already, the above IP should be set to static.\ -\\nView the web interface at http://pi.hole/admin:${WEBPORT} or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pw}\ +\\nView the web interface at http://pi.hole:${WEBPORT}/admin or http://${IPV4_ADDRESS%/*}:${WEBPORT}/admin\\n\\nYour Admin Webpage login password is ${pw}\ \\n \\n \\nTo allow your user to use all CLI functions without authentication,\ From f5ce7b29e074d15fe1baa9710713dd8870350f12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Oct 2025 10:02:17 +0000 Subject: [PATCH 199/259] Bump the python-dependencies group across 1 directory with 3 updates Bumps the python-dependencies group with 3 updates in the /test directory: [pyyaml](https://github.com/yaml/pyyaml), [pytest](https://github.com/pytest-dev/pytest) and [tox](https://github.com/tox-dev/tox). Updates `pyyaml` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/yaml/pyyaml/releases) - [Changelog](https://github.com/yaml/pyyaml/blob/6.0.3/CHANGES) - [Commits](https://github.com/yaml/pyyaml/compare/6.0.2...6.0.3) Updates `pytest` from 8.4.1 to 8.4.2 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.4.1...8.4.2) Updates `tox` from 4.28.4 to 4.30.2 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.28.4...4.30.2) --- updated-dependencies: - dependency-name: pyyaml dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-dependencies - dependency-name: pytest dependency-version: 8.4.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-dependencies - dependency-name: tox dependency-version: 4.30.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/requirements.txt b/test/requirements.txt index 7e329dcf..f1c71084 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,6 +1,6 @@ -pyyaml == 6.0.2 -pytest == 8.4.1 +pyyaml == 6.0.3 +pytest == 8.4.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.28.4 +tox == 4.30.3 pytest-clarity == 1.0.1 From f8d14c398ee5cb310b6d2bc007b13c5c8b8f5b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 4 Oct 2025 21:15:12 +0200 Subject: [PATCH 200/259] Use sha also fpr editor-config-checker without adding a specific tag commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4c95d362..f6f0ee3c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: ignore_words_file: .codespellignore - name: Get editorconfig-checker - uses: editorconfig-checker/action-editorconfig-checker@main # tag v2. is really out of date + uses: editorconfig-checker/action-editorconfig-checker@f40bac9e7d9e7d298fbe36b83e1eff8f0de13fb8 # tag v2. is really out of date - name: Run editorconfig-checker run: editorconfig-checker From 37fc86410f31af10f98a481c1dc9603dcfc5d382 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Oct 2025 19:26:34 +0000 Subject: [PATCH 201/259] Bump the github-actions-dependencies group across 1 directory with 4 updates Bumps the github-actions-dependencies group with 4 updates in the / directory: [github/codeql-action](https://github.com/github/codeql-action), [actions/stale](https://github.com/actions/stale), [psf/black](https://github.com/psf/black) and [actions/setup-python](https://github.com/actions/setup-python). Updates `github/codeql-action` from 3.29.10 to 3.30.6 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/96f518a34f7a870018057716cc4d7a5c014bd61c...64d10c13136e1c5bce3e5fbde8d4906eeaafc885) Updates `actions/stale` from 9.1.0 to 10.1.0 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/5bef64f19d7facfb25b37b414482c7164d639639...5f858e3efba33a5ca4407a664cc011ad407f2008) Updates `psf/black` from 25.1.0 to 25.9.0 - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b...af0ba72a73598c76189d6dd1b21d8532255d5942) Updates `actions/setup-python` from 5.6.0 to 6.0.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/a26af69be951a213d495a4c3e4e4022e16d87065...e797f83bcb11b83ae66e0230d6156d7c80228e7c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.6 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies - dependency-name: actions/stale dependency-version: 10.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies - dependency-name: psf/black dependency-version: 25.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies - dependency-name: actions/setup-python dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/stale.yml | 2 +- .github/workflows/stale_pr.yml | 2 +- .github/workflows/test.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2c01ef1b..bf53b688 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 + uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 + uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@96f518a34f7a870018057716cc4d7a5c014bd61c #v3.29.10 + uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 42ea2537..2fdf9291 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: issues: write steps: - - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 #v10.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/stale_pr.yml index 3e5729ce..7d68df6a 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/stale_pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 #v10.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Do not automatically mark PR/issue as stale diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dfba9044..9c04ecad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: run: editorconfig-checker - name: Check python code formatting with black - uses: psf/black@8a737e727ac5ab2f1d4cf5876720ed276dc8dc4b #25.1.0 + uses: psf/black@af0ba72a73598c76189d6dd1b21d8532255d5942 #25.9.0 with: src: "./test" options: "--check --diff --color" @@ -84,7 +84,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 #v5.6.0 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c #v6.0.0 with: python-version: "3.13" From 08ce6499fc91ec5800c32e907abae5c3bb9520a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 10:01:39 +0000 Subject: [PATCH 202/259] Bump the github-actions-dependencies group with 2 updates Bumps the github-actions-dependencies group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [editorconfig-checker/action-editorconfig-checker](https://github.com/editorconfig-checker/action-editorconfig-checker). Updates `github/codeql-action` from 3.30.6 to 4.30.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/64d10c13136e1c5bce3e5fbde8d4906eeaafc885...f443b600d91635bebf5b0d9ebc620189c0d6fba5) Updates `editorconfig-checker/action-editorconfig-checker` from f40bac9e7d9e7d298fbe36b83e1eff8f0de13fb8 to 1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4 - [Release notes](https://github.com/editorconfig-checker/action-editorconfig-checker/releases) - [Commits](https://github.com/editorconfig-checker/action-editorconfig-checker/compare/f40bac9e7d9e7d298fbe36b83e1eff8f0de13fb8...1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.8 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies - dependency-name: editorconfig-checker/action-editorconfig-checker dependency-version: 1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4 dependency-type: direct:production dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index bf53b688..820ee16e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 + uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 + uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 #v3.30.6 + uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9c04ecad..674e9aef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: ignore_words_file: .codespellignore - name: Get editorconfig-checker - uses: editorconfig-checker/action-editorconfig-checker@f40bac9e7d9e7d298fbe36b83e1eff8f0de13fb8 # tag v2. is really out of date + uses: editorconfig-checker/action-editorconfig-checker@1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4 # tag v2. is really out of date - name: Run editorconfig-checker run: editorconfig-checker From 71dbf2715acbc125ddd0b988639385bfe6a69b12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 10:01:51 +0000 Subject: [PATCH 203/259] Bump tox from 4.30.3 to 4.31.0 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.30.3 to 4.31.0 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.30.3...4.31.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.31.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index f1c71084..889a9be3 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.3 pytest == 8.4.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.30.3 +tox == 4.31.0 pytest-clarity == 1.0.1 From 9e8e36059139c518d81f6db11327f2574d6d3e94 Mon Sep 17 00:00:00 2001 From: casperklein Date: Wed, 15 Oct 2025 04:37:19 +0200 Subject: [PATCH 204/259] add missing local variable Signed-off-by: casperklein --- advanced/bash-completion/pihole.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/bash-completion/pihole.bash b/advanced/bash-completion/pihole.bash index 736a75d9..7f6c7ab4 100644 --- a/advanced/bash-completion/pihole.bash +++ b/advanced/bash-completion/pihole.bash @@ -3,7 +3,7 @@ # Bash completion script for pihole # _pihole() { - local cur prev opts opts_lists opts_checkout opts_debug opts_logging opts_query opts_update opts_networkflush + local cur prev prev2 opts opts_lists opts_checkout opts_debug opts_logging opts_query opts_update opts_networkflush COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" From 190b89483c2d7b41cdc7bbb207784e85b9086c10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 Oct 2025 10:01:21 +0000 Subject: [PATCH 205/259] Bump the github-actions-dependencies group with 2 updates Bumps the github-actions-dependencies group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [editorconfig-checker/action-editorconfig-checker](https://github.com/editorconfig-checker/action-editorconfig-checker). Updates `github/codeql-action` from 4.30.8 to 4.30.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f443b600d91635bebf5b0d9ebc620189c0d6fba5...16140ae1a102900babc80a33c44059580f687047) Updates `editorconfig-checker/action-editorconfig-checker` from 1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4 to 5ecdd656fe347c26f76b1b435b90e1d74fb5e787 - [Release notes](https://github.com/editorconfig-checker/action-editorconfig-checker/releases) - [Commits](https://github.com/editorconfig-checker/action-editorconfig-checker/compare/1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4...5ecdd656fe347c26f76b1b435b90e1d74fb5e787) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: editorconfig-checker/action-editorconfig-checker dependency-version: 5ecdd656fe347c26f76b1b435b90e1d74fb5e787 dependency-type: direct:production dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 820ee16e..cf17767c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 + uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 + uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 #v4.30.8 + uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 674e9aef..085a3cc7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: ignore_words_file: .codespellignore - name: Get editorconfig-checker - uses: editorconfig-checker/action-editorconfig-checker@1a41284d59c6fe7f1b21ddc4a2b36400a33dc1b4 # tag v2. is really out of date + uses: editorconfig-checker/action-editorconfig-checker@5ecdd656fe347c26f76b1b435b90e1d74fb5e787 # tag v2. is really out of date - name: Run editorconfig-checker run: editorconfig-checker From 31cf4ed06d7449896f26aa9d3c1116ac68ad9def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sat, 18 Oct 2025 13:12:23 +0200 Subject: [PATCH 206/259] Fix gravity indention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index f84d05f9..1cd422e1 100755 --- a/gravity.sh +++ b/gravity.sh @@ -750,7 +750,7 @@ gravity_DownloadBlocklistFromUrl() { # Check for allowed protocols if [[ $url != "http"* && $url != "https"* && $url != "file"* && $url != "ftp"* && $url != "ftps"* && $url != "sftp"* ]]; then echo -e "${OVER} ${CROSS} ${str} Invalid protocol specified. Ignoring list." - echo -e "Ensure your URL starts with a valid protocol like http:// , https:// or file:// ." + echo -e " Ensure your URL starts with a valid protocol like http:// , https:// or file:// ." download=false fi From bfc263ac964570a8b1811f536cd4d32247cc395d Mon Sep 17 00:00:00 2001 From: yubiuser Date: Mon, 20 Oct 2025 09:22:21 +0200 Subject: [PATCH 207/259] Apply suggestion from @rdwebdesign Co-authored-by: RD WebDesign Signed-off-by: yubiuser --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 1cd422e1..5720ca41 100755 --- a/gravity.sh +++ b/gravity.sh @@ -1130,7 +1130,7 @@ fi if [[ "${forceDelete:-}" == true ]]; then str="Deleting existing list cache" - echo -ne "${INFO} ${str}..." + echo -ne " ${INFO} ${str}..." rm "${listsCacheDir}/list.*" 2>/dev/null || true echo -e "${OVER} ${TICK} ${str}" From a734733a87c731eb3ef77b3bd66336e087daaef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 18 Aug 2025 20:09:04 +0200 Subject: [PATCH 208/259] Disable log flush on docker container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- pihole | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pihole b/pihole index 5af46fa6..e6257b64 100755 --- a/pihole +++ b/pihole @@ -92,8 +92,12 @@ debugFunc() { } flushFunc() { - "${PI_HOLE_SCRIPT_DIR}"/piholeLogFlush.sh "$@" - exit 0 + if [ -n "${DOCKER_VERSION}" ]; then + unsupportedFunc + else + "${PI_HOLE_SCRIPT_DIR}"/piholeLogFlush.sh "$@" + exit 0 + fi } # Deprecated function, should be removed in the future From 12342682b425a9181d153673cc1d8c073efb91f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 21 Oct 2025 20:29:19 +0200 Subject: [PATCH 209/259] Separate log flush from log rotate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/piholeLogFlush.sh | 78 +++++++---------------------- advanced/Scripts/piholeLogRotate.sh | 72 ++++++++++++++++++++++++++ advanced/Templates/pihole.cron | 2 +- automated install/basic-install.sh | 2 +- manpages/pihole.8 | 15 +++++- pihole | 15 +++++- 6 files changed, 118 insertions(+), 66 deletions(-) create mode 100755 advanced/Scripts/piholeLogRotate.sh diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index ac28aed9..10b4f320 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -17,11 +17,6 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # shellcheck source="./advanced/Scripts/utils.sh" source "${utilsfile}" -# In case we're running at the same time as a system logrotate, use a -# separate logrotate state file to prevent stepping on each other's -# toes. -STATEFILE="/var/lib/logrotate/pihole" - # Determine database location DBFILE=$(getFTLConfigValue "files.database") if [ -z "$DBFILE" ]; then @@ -42,25 +37,6 @@ if [ -z "$WEBFILE" ]; then WEBFILE="/var/log/pihole/webserver.log" fi -# Helper function to handle log rotation for a single file -rotate_log() { - # This function copies x.log over to x.log.1 - # and then empties x.log - # Note that moving the file is not an option, as - # dnsmasq would happily continue writing into the - # moved file (it will have the same file handler) - local logfile="$1" - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Rotating ${logfile} ..." - fi - cp -p "${logfile}" "${logfile}.1" - echo " " > "${logfile}" - chmod 640 "${logfile}" - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Rotated ${logfile} ..." - fi -} - # Helper function to handle log flushing for a single file flush_log() { local logfile="$1" @@ -78,41 +54,23 @@ flush_log() { fi } -if [[ "$*" == *"once"* ]]; then - # Nightly logrotation - if command -v /usr/sbin/logrotate >/dev/null; then - # Logrotate once +# Manual flushing +flush_log "${LOGFILE}" +flush_log "${FTLFILE}" +flush_log "${WEBFILE}" - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Running logrotate ..." - fi - mkdir -p "${STATEFILE%/*}" - /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate - else - # Handle rotation for each log file - rotate_log "${LOGFILE}" - rotate_log "${FTLFILE}" - rotate_log "${WEBFILE}" - fi -else - # Manual flushing - flush_log "${LOGFILE}" - flush_log "${FTLFILE}" - flush_log "${WEBFILE}" - - if [[ "$*" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." - fi - - # Stop FTL to make sure it doesn't write to the database while we're deleting data - service pihole-FTL stop - - # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) - deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") - - # Restart FTL - service pihole-FTL restart - if [[ "$*" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" - fi +if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." +fi + +# Stop FTL to make sure it doesn't write to the database while we're deleting data +service pihole-FTL stop + +# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) +deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") + +# Restart FTL +service pihole-FTL restart +if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" fi diff --git a/advanced/Scripts/piholeLogRotate.sh b/advanced/Scripts/piholeLogRotate.sh new file mode 100755 index 00000000..b7de90ee --- /dev/null +++ b/advanced/Scripts/piholeLogRotate.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Pi-hole: A black hole for Internet advertisements +# (c) 2025 Pi-hole, LLC (https://pi-hole.net) +# Network-wide ad blocking via your own hardware. +# +# Rotate Pi-hole's log file +# +# This file is copyright under the latest version of the EUPL. +# Please see LICENSE file for your rights under this license. + +colfile="/opt/pihole/COL_TABLE" +# shellcheck source="./advanced/Scripts/COL_TABLE" +source ${colfile} + +readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck source="./advanced/Scripts/utils.sh" +source "${utilsfile}" + +# In case we're running at the same time as a system logrotate, use a +# separate logrotate state file to prevent stepping on each other's +# toes. +STATEFILE="/var/lib/logrotate/pihole" + + +# Determine log file location +LOGFILE=$(getFTLConfigValue "files.log.dnsmasq") +if [ -z "$LOGFILE" ]; then + LOGFILE="/var/log/pihole/pihole.log" +fi +FTLFILE=$(getFTLConfigValue "files.log.ftl") +if [ -z "$FTLFILE" ]; then + FTLFILE="/var/log/pihole/FTL.log" +fi +WEBFILE=$(getFTLConfigValue "files.log.webserver") +if [ -z "$WEBFILE" ]; then + WEBFILE="/var/log/pihole/webserver.log" +fi + +# Helper function to handle log rotation for a single file +rotate_log() { + # This function copies x.log over to x.log.1 + # and then empties x.log + # Note that moving the file is not an option, as + # dnsmasq would happily continue writing into the + # moved file (it will have the same file handler) + local logfile="$1" + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Rotating ${logfile} ..." + fi + cp -p "${logfile}" "${logfile}.1" + echo " " > "${logfile}" + chmod 640 "${logfile}" + if [[ "$*" != *"quiet"* ]]; then + echo -e "${OVER} ${TICK} Rotated ${logfile} ..." + fi +} + +# Nightly logrotation +if command -v /usr/sbin/logrotate >/dev/null; then + # Logrotate once + if [[ "$*" != *"quiet"* ]]; then + echo -ne " ${INFO} Running logrotate ..." + fi + mkdir -p "${STATEFILE%/*}" + /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate +else + # Handle rotation for each log file + rotate_log "${LOGFILE}" + rotate_log "${FTLFILE}" + rotate_log "${WEBFILE}" +fi diff --git a/advanced/Templates/pihole.cron b/advanced/Templates/pihole.cron index c62d31ab..3b71cbff 100644 --- a/advanced/Templates/pihole.cron +++ b/advanced/Templates/pihole.cron @@ -24,7 +24,7 @@ # The flush script will use logrotate if available # parameter "once": logrotate only once (default is twice) # parameter "quiet": don't print messages -00 00 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole flush once quiet +00 00 * * * root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole logrotate quiet @reboot root /usr/sbin/logrotate --state /var/lib/logrotate/pihole /etc/pihole/logrotate diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index a4c04158..65464b9e 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -84,7 +84,7 @@ webInterfaceDir="${webroot}/admin" piholeGitUrl="https://github.com/pi-hole/pi-hole.git" PI_HOLE_LOCAL_REPO="/etc/.pihole" # List of pihole scripts, stored in an array -PI_HOLE_FILES=(list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage) +PI_HOLE_FILES=(list piholeDebug piholeLogFlush piholeLogRotate setupLCD update version gravity uninstall webpage) # This directory is where the Pi-hole scripts will be installed PI_HOLE_INSTALL_DIR="/opt/pihole" PI_HOLE_CONFIG_DIR="/etc/pihole" diff --git a/manpages/pihole.8 b/manpages/pihole.8 index ac3146ba..191691ee 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -100,9 +100,12 @@ Available commands and options: -c Include a Pi-hole database integrity check .br -\fB-f, flush\fR +\fB-f, flush\fR [quite] .br - Flush the Pi-hole log + Flush the Pi-hole log and last 24h from the query database +.br + + quite Suppress output .br \fB-r, repair\fR @@ -242,6 +245,14 @@ Available commands and options: verbose Show authentication and status messages .br +\fBlogrotate\fR [quite] +.br + Rotate Pi-hole's log files +.br + + quite Suppress output +.br + .SH "EXAMPLE" Some usage examples diff --git a/pihole b/pihole index e6257b64..4fe09418 100755 --- a/pihole +++ b/pihole @@ -92,6 +92,7 @@ debugFunc() { } flushFunc() { + # unsupported in docker because it requires restarting FTL if [ -n "${DOCKER_VERSION}" ]; then unsupportedFunc else @@ -109,6 +110,11 @@ arpFunc() { exit 0 } +logrotateFunc() { + "${PI_HOLE_SCRIPT_DIR}"/piholeLogRotate.sh "$@" + exit 0 +} + networkFlush() { shift "${PI_HOLE_SCRIPT_DIR}"/piholeNetworkFlush.sh "$@" @@ -506,7 +512,8 @@ Debugging Options: -d, debug Start a debugging session Add '-c' or '--check-database' to include a Pi-hole database integrity check Add '-a' to automatically upload the log to tricorder.pi-hole.net - -f, flush Flush the Pi-hole log + -f, flush Flush the Pi-hole logs and last 24h from the query database + Add 'quiet' to suppress output messages -r, repair Repair Pi-hole subsystems -t, tail [arg] View the live output of the Pi-hole log. Add an optional argument to filter the log @@ -539,7 +546,9 @@ Options: checkout Switch Pi-hole subsystems to a different GitHub branch Add '-h' for more info on checkout usage networkflush Flush information stored in Pi-hole's network tables - Add '--arp' to additionally flush the ARP table "; + Add '--arp' to additionally flush the ARP table + logrotate Rotate Pi-hole's log files + Add 'quiet' to suppress output messages"; exit 0 } @@ -582,6 +591,7 @@ case "${1}" in "arpflush" ) need_root=true;; # Deprecated, use networkflush instead "networkflush" ) need_root=true;; "-t" | "tail" ) need_root=true;; + "logrotate" ) need_root=true;; * ) helpFunc;; esac @@ -617,5 +627,6 @@ case "${1}" in "arpflush" ) arpFunc "$@";; # Deprecated, use networkflush instead "networkflush" ) networkFlush "$@";; "-t" | "tail" ) tailFunc "$2";; + "logrotate" ) logrotateFunc "$@";; * ) helpFunc;; esac From b2e56662c0d4cf4393fff58f181b8c3167745155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 22 Oct 2025 20:25:42 +0200 Subject: [PATCH 210/259] Loose requirements for local file access for gravity Signed-off-by: yubiuser --- gravity.sh | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/gravity.sh b/gravity.sh index 5720ca41..1e394811 100755 --- a/gravity.sh +++ b/gravity.sh @@ -612,7 +612,7 @@ compareLists() { gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" compression="${4}" gravity_type="${5}" domain="${6}" local listCurlBuffer str httpCode success="" ip customUpstreamResolver="" - local file_path permissions ip_addr port blocked=false download=true + local file_path ip_addr port blocked=false download=true # modifiedOptions is an array to store all the options used to check if the adlist has been changed upstream local modifiedOptions=() @@ -721,29 +721,40 @@ gravity_DownloadBlocklistFromUrl() { fi fi - # If we are going to "download" a local file, we first check if the target - # file has a+r permission. We explicitly check for all+read because we want - # to make sure that the file is readable by everyone and not just the user - # running the script. - if [[ $url == "file://"* ]]; then + # If we "download" a local file (file://), verify read access before using it. + # When running as root (e.g., via pihole -g), check that the 'pihole' user can read the file + # to match the effective runtime user of FTL; otherwise, check the current user's read access + # (e.g., in Docker or when invoked by a non-root user). The target must + # resolve to a regular file and be readable by the evaluated user. + if [[ "${url}" == "file://"* ]]; then # Get the file path - file_path=$(echo "$url" | cut -d'/' -f3-) + file_path=$(echo "${url}" | cut -d'/' -f3-) # Check if the file exists and is a regular file (i.e. not a socket, fifo, tty, block). Might still be a symlink. - if [[ ! -f $file_path ]]; then - # Output that the file does not exist - echo -e "${OVER} ${CROSS} ${file_path} does not exist" - download=false - else - # Check if the file or a file referenced by the symlink has a+r permissions - permissions=$(stat -L -c "%a" "$file_path") - if [[ $permissions == *4 || $permissions == *5 || $permissions == *6 || $permissions == *7 ]]; then - # Output that we are using the local file - echo -e "${OVER} ${INFO} Using local file ${file_path}" - else - # Output that the file does not have the correct permissions - echo -e "${OVER} ${CROSS} Cannot read file (file needs to have a+r permission)" + if [[ ! -f ${file_path} ]]; then + # Output that the file does not exist + echo -e "${OVER} ${CROSS} ${file_path} does not exist" download=false - fi + else + if [ "$(id -un)" == "root" ]; then + # If we are root, we need to check if the pihole user has read permission + # otherwise, we might read files that the pihole user should not be able to read + if sudo -u pihole test -r "${file_path}"; then + echo -e "${OVER} ${INFO} Using local file ${file_path}" + else + echo -e "${OVER} ${CROSS} Cannot read file (user 'pihole' lacks read permission)" + download=false + fi + else + # If we are not root, we just check if the current user has read permission + if [[ -r "${file_path}" ]]; then + # Output that we are using the local file + echo -e "${OVER} ${INFO} Using local file ${file_path}" + else + # Output that the file is not readable by the current user + echo -e "${OVER} ${CROSS} Cannot read file (current user '$(id -un)' lacks read permission)" + download=false + fi + fi fi fi From 11344c39f5bbc960bb343f7e95a45d0d0090c7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 23 Oct 2025 22:09:55 +0200 Subject: [PATCH 211/259] Prevent URLs like file:/./ to circumvent permission check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 1e394811..8f1005a0 100755 --- a/gravity.sh +++ b/gravity.sh @@ -726,7 +726,7 @@ gravity_DownloadBlocklistFromUrl() { # to match the effective runtime user of FTL; otherwise, check the current user's read access # (e.g., in Docker or when invoked by a non-root user). The target must # resolve to a regular file and be readable by the evaluated user. - if [[ "${url}" == "file://"* ]]; then + if [[ "${url}" == "file:/"* ]]; then # Get the file path file_path=$(echo "${url}" | cut -d'/' -f3-) # Check if the file exists and is a regular file (i.e. not a socket, fifo, tty, block). Might still be a symlink. From 527895a377b60877d21b9d3ef3d1a4e3738e3c82 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 24 Oct 2025 21:07:12 +0200 Subject: [PATCH 212/259] Fix indentation Co-authored-by: RD WebDesign Signed-off-by: yubiuser --- gravity.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gravity.sh b/gravity.sh index 8f1005a0..28fa5ead 100755 --- a/gravity.sh +++ b/gravity.sh @@ -736,9 +736,9 @@ gravity_DownloadBlocklistFromUrl() { download=false else if [ "$(id -un)" == "root" ]; then - # If we are root, we need to check if the pihole user has read permission - # otherwise, we might read files that the pihole user should not be able to read - if sudo -u pihole test -r "${file_path}"; then + # If we are root, we need to check if the pihole user has read permission + # otherwise, we might read files that the pihole user should not be able to read + if sudo -u pihole test -r "${file_path}"; then echo -e "${OVER} ${INFO} Using local file ${file_path}" else echo -e "${OVER} ${CROSS} Cannot read file (user 'pihole' lacks read permission)" From 77dd566a4fc3d6c39ae09225e2065f65720c072a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:01:46 +0000 Subject: [PATCH 213/259] Bump tox from 4.31.0 to 4.32.0 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.31.0 to 4.32.0 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.31.0...4.32.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 889a9be3..cfbd4915 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.3 pytest == 8.4.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.31.0 +tox == 4.32.0 pytest-clarity == 1.0.1 From 1ca693866cf6c373c606541c0f65a4c43f27bc7c Mon Sep 17 00:00:00 2001 From: Adam Warner Date: Sat, 25 Oct 2025 11:28:14 +0100 Subject: [PATCH 214/259] Fix formatting in chooseInterface function to ensure proper variable expansion - with quotes, the dialog command throws the error: Expected at least 20 tokens for --radi, have 5. Use --help to list options. Signed-off-by: Adam Warner --- automated install/basic-install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index a4c04158..5f7bc89e 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -694,10 +694,11 @@ chooseInterface() { status="OFF" done # Disable check for double quote here as we are passing a string with spaces + # shellcheck disable=SC2086 PIHOLE_INTERFACE=$(dialog --no-shadow --keep-tite --output-fd 1 \ --cancel-label "Exit" --ok-label "Select" \ --radiolist "Choose An Interface (press space to toggle selection)" \ - ${r} ${c} "${interfaceCount}" "${interfacesList}") + ${r} ${c} "${interfaceCount}" ${interfacesList}) result=$? case ${result} in From 1818e7e59eb322c3e8d9304a3c5421c1a2fc0c05 Mon Sep 17 00:00:00 2001 From: casperklein Date: Sun, 26 Oct 2025 12:05:13 +0100 Subject: [PATCH 215/259] Ensure 'versions' file exist on first start Signed-off-by: casperklein --- advanced/Templates/pihole-FTL-prestart.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 579309d3..9fa79889 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -14,6 +14,7 @@ mkdir -p /var/log/pihole chown -R pihole:pihole /etc/pihole/ /var/log/pihole/ # allow all users read version file (and use pihole -v) +touch /etc/pihole/versions chmod 0644 /etc/pihole/versions # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) From 72e369926502732dc4cc2d58afe4eee9de872aa8 Mon Sep 17 00:00:00 2001 From: Yannick7777 Date: Sun, 26 Oct 2025 12:55:43 +0100 Subject: [PATCH 216/259] Add log file path variables and ensure log files are created if missing Signed-off-by: Yannick7777 --- advanced/Templates/pihole-FTL-prestart.sh | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh index 579309d3..2761c599 100755 --- a/advanced/Templates/pihole-FTL-prestart.sh +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -8,6 +8,13 @@ utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" # Get file paths FTL_PID_FILE="$(getFTLConfigValue files.pid)" +FTL_LOG_FILE="$(getFTLConfigValue files.log.ftl)" +PIHOLE_LOG_FILE="$(getFTLConfigValue files.log.dnsmasq)" +WEBSERVER_LOG_FILE="$(getFTLConfigValue files.log.webserver)" +FTL_PID_FILE="${FTL_PID_FILE:-/run/pihole-FTL.pid}" +FTL_LOG_FILE="${FTL_LOG_FILE:-/var/log/pihole/FTL.log}" +PIHOLE_LOG_FILE="${PIHOLE_LOG_FILE:-/var/log/pihole/pihole.log}" +WEBSERVER_LOG_FILE="${WEBSERVER_LOG_FILE:-/var/log/pihole/webserver.log}" # Ensure that permissions are set so that pihole-FTL can edit all necessary files mkdir -p /var/log/pihole @@ -28,7 +35,7 @@ chown root:root /etc/pihole/logrotate # Touch files to ensure they exist (create if non-existing, preserve if existing) [ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" -[ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log -[ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log -[ -f /var/log/pihole/webserver.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/webserver.log +[ -f "${FTL_LOG_FILE}" ] || install -m 640 -o pihole -g pihole /dev/null "${FTL_LOG_FILE}" +[ -f "${PIHOLE_LOG_FILE}" ] || install -m 640 -o pihole -g pihole /dev/null "${PIHOLE_LOG_FILE}" +[ -f "${WEBSERVER_LOG_FILE}" ] || install -m 640 -o pihole -g pihole /dev/null "${WEBSERVER_LOG_FILE}" [ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases From 49099d017ae985fecc5061d4a2a7868759d32883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 26 Oct 2025 20:30:34 +0100 Subject: [PATCH 217/259] Start using commented tags for editorconfig-checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 085a3cc7..a4ed2a7d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: ignore_words_file: .codespellignore - name: Get editorconfig-checker - uses: editorconfig-checker/action-editorconfig-checker@5ecdd656fe347c26f76b1b435b90e1d74fb5e787 # tag v2. is really out of date + uses: editorconfig-checker/action-editorconfig-checker@4b6cd6190d435e7e084fb35e36a096e98506f7b9 #v2.1.0 - name: Run editorconfig-checker run: editorconfig-checker From fc4c10dbe2e71ee016c719c6392d8f5f1d6a4c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Sun, 26 Oct 2025 21:06:22 +0100 Subject: [PATCH 218/259] Add bind9-dnsutils as dependency for APT based systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 5f7bc89e..0b186472 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -116,11 +116,11 @@ c=70 PIHOLE_META_PACKAGE_CONTROL_APT=$( cat < Architecture: all Description: Pi-hole dependency meta package -Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,procps,psmisc,sudo,unzip +Depends: awk,bash-completion,binutils,ca-certificates,cron|cron-daemon,curl,dialog,bind9-dnsutils|dnsutils,dns-root-data,git,grep,iproute2,iputils-ping,jq,libcap2,libcap2-bin,lshw,procps,psmisc,sudo,unzip Section: contrib/metapackages Priority: optional EOM From 4247a6056bb5307314462b9bd808f92ed050115e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 13:43:44 +0000 Subject: [PATCH 219/259] Bump github/codeql-action Bumps the github-actions-dependencies group with 1 update in the / directory: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.30.9 to 4.31.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/16140ae1a102900babc80a33c44059580f687047...4e94bd11f71e507f7f87df81788dff88d1dacbfb) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cf17767c..9fad5cc6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 + uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 + uses: github/codeql-action/autobuild@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 #v4.30.9 + uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 From 558f0c4bf720b2edca315ed986c685e48bbad497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 31 Oct 2025 18:53:18 +0100 Subject: [PATCH 220/259] Add Fedora 43 to test suite Signed-off-by: yubiuser --- .github/workflows/test.yml | 1 + test/_fedora_43.Dockerfile | 17 +++++++++++++++++ test/tox.fedora_43.ini | 10 ++++++++++ 3 files changed, 28 insertions(+) create mode 100644 test/_fedora_43.Dockerfile create mode 100644 test/tox.fedora_43.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a4ed2a7d..dbb0f656 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,6 +74,7 @@ jobs: fedora_40, fedora_41, fedora_42, + fedora_43, alpine_3_21, alpine_3_22, ] diff --git a/test/_fedora_43.Dockerfile b/test/_fedora_43.Dockerfile new file mode 100644 index 00000000..85f06ff8 --- /dev/null +++ b/test/_fedora_43.Dockerfile @@ -0,0 +1,17 @@ +FROM fedora:43 +RUN dnf install -y git initscripts + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/tox.fedora_43.ini b/test/tox.fedora_43.ini new file mode 100644 index 00000000..efbb0471 --- /dev/null +++ b/test/tox.fedora_43.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _fedora_43.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py From 766e61c52a9f162edcbe53720a966807fd5b6769 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:01:18 +0000 Subject: [PATCH 221/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.31.0 to 4.31.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e94bd11f71e507f7f87df81788dff88d1dacbfb...0499de31b99561a6d14a36a5f662c2a54f91beee) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9fad5cc6..4e905e66 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 + uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb #v4.31.0 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 From 4ff250edac40b91bafc9b53dab0bca5455c077ba Mon Sep 17 00:00:00 2001 From: Sparronator9999 <86388887+Sparronator9999@users.noreply.github.com> Date: Sun, 2 Nov 2025 07:25:52 +1100 Subject: [PATCH 222/259] Fix libcap capabilities not being granted on OpenRC distros Created on behalf of @mgziminsky - see this issue comment: https://github.com/pi-hole/pi-hole/issues/6454#issuecomment-3476576177 Signed-off-by: Sparronator9999 <86388887+Sparronator9999@users.noreply.github.com> --- advanced/Templates/pihole-FTL.openrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Templates/pihole-FTL.openrc b/advanced/Templates/pihole-FTL.openrc index 34a30a0b..2207273e 100644 --- a/advanced/Templates/pihole-FTL.openrc +++ b/advanced/Templates/pihole-FTL.openrc @@ -13,7 +13,7 @@ extra_started_commands="reload" respawn_max=5 respawn_period=60 -capabilities="^CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN,CAP_SYS_TIME" +capabilities="^CAP_NET_BIND_SERVICE,^CAP_NET_RAW,^CAP_NET_ADMIN,^CAP_SYS_NICE,^CAP_IPC_LOCK,^CAP_CHOWN,^CAP_SYS_TIME" depend() { want net From 40aa986af120b674340cd690cb632fba323562a6 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 3 Nov 2025 17:18:50 -0300 Subject: [PATCH 223/259] Add list "type" (block/allow) to the debug log table Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 7cc31e29..4630aa97 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -1084,7 +1084,7 @@ show_groups() { } show_adlists() { - show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids,address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 100 19 19 50" + show_db_entries "Adlists (type: 0 = blocklist, 1 = allowlist)" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN '0' WHEN '1' THEN ' 1' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 4 100 19 19 50" } show_domainlist() { From 7df117876faebeb38353cdd859513ce9a6e60798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 3 Nov 2025 22:23:12 +0100 Subject: [PATCH 224/259] Replace sudo with doas on alpine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- automated install/basic-install.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 0b186472..8dc4ae96 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -155,7 +155,7 @@ EOM ) # List of required packages on APK based systems -PIHOLE_META_VERSION_APK=0.1 +PIHOLE_META_VERSION_APK=0.2 PIHOLE_META_DEPS_APK=( bash bash-completion @@ -165,6 +165,8 @@ PIHOLE_META_DEPS_APK=( cronie curl dialog + doas # sudo replacement + doas-sudo-shim git grep iproute2-minimal # piholeARPTable.sh @@ -178,7 +180,6 @@ PIHOLE_META_DEPS_APK=( procps-ng psmisc shadow - sudo tzdata unzip wget From 7452c950802e9da78fa48cb9bb180a5f646a3efa Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 8 Nov 2025 15:35:10 +1000 Subject: [PATCH 225/259] systemd service - don't use deprecated PermissionsStartOnly - elevate Prestart and Poststop script permissions using "+" prefix instead, as per https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#Command%20lines ( PermissionsStartOnly was deprecated in systemd 241 and no longer appears in documentation since 2018 https://github.com/systemd/systemd/pull/10802 ) Signed-off-by: Rob Gill --- advanced/Templates/pihole-FTL.systemd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/advanced/Templates/pihole-FTL.systemd b/advanced/Templates/pihole-FTL.systemd index fcbb8d8d..29470c5a 100644 --- a/advanced/Templates/pihole-FTL.systemd +++ b/advanced/Templates/pihole-FTL.systemd @@ -17,15 +17,15 @@ StartLimitIntervalSec=60s [Service] User=pihole -PermissionsStartOnly=true AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_NICE CAP_IPC_LOCK CAP_CHOWN CAP_SYS_TIME -ExecStartPre=/opt/pihole/pihole-FTL-prestart.sh +# Run prestart with elevated permissions +ExecStartPre=+/opt/pihole/pihole-FTL-prestart.sh ExecStart=/usr/bin/pihole-FTL -f Restart=on-failure RestartSec=5s ExecReload=/bin/kill -HUP $MAINPID -ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh +ExecStopPost=+/opt/pihole/pihole-FTL-poststop.sh # Use graceful shutdown with a reasonable timeout TimeoutStopSec=60s From 83f7b4089a952b37e40c82eb25ebab6d66fe7dbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:01:11 +0000 Subject: [PATCH 226/259] Bump codespell-project/actions-codespell Bumps the github-actions-dependencies group with 1 update: [codespell-project/actions-codespell](https://github.com/codespell-project/actions-codespell). Updates `codespell-project/actions-codespell` from 2.1 to 2.2 - [Release notes](https://github.com/codespell-project/actions-codespell/releases) - [Commits](https://github.com/codespell-project/actions-codespell/compare/406322ec52dd7b488e48c1c4b82e2a8b3a1bf630...8f01853be192eb0f849a5c7d721450e7a467c579) --- updated-dependencies: - dependency-name: codespell-project/actions-codespell dependency-version: '2.2' dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbb0f656..04638d4e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: - name: Spell-Checking - uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 #v2.1 + uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 #v2.2 with: ignore_words_file: .codespellignore From bf41c3dded6e8dcef6ef8654823e059b2092baae Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Mon, 10 Nov 2025 14:33:07 +1000 Subject: [PATCH 227/259] debug - speed up processing and display of file contents and services Use bash-internal globs and parameter expasion in preference to assignment from output of ls or basename per file/directory. When displaying file contents, call sed once and preprocesses the entire file (eg pihole.toml), rather than spawning a new sed process for every line of the file. When checking services, call awk once to extract all data for each ip:port pair, rather than three times. Signed-off-by: Rob Gill --- advanced/Scripts/piholeDebug.sh | 95 +++++++++++++++------------------ 1 file changed, 42 insertions(+), 53 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 7cc31e29..cff4d373 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -593,18 +593,21 @@ check_required_ports() { # Add port 53 ports_configured+=("53") + local protocol_type port_number service_name # Now that we have the values stored, for i in "${!ports_in_use[@]}"; do # loop through them and assign some local variables - local service_name - service_name=$(echo "${ports_in_use[$i]}" | awk '{gsub(/users:\(\("/,"",$7);gsub(/".*/,"",$7);print $7}') - local protocol_type - protocol_type=$(echo "${ports_in_use[$i]}" | awk '{print $1}') - local port_number - port_number="$(echo "${ports_in_use[$i]}" | awk '{print $5}')" # | awk '{gsub(/^.*:/,"",$5);print $5}') + read -r protocol_type port_number service_name <<< "$( + awk '{ + p=$1; n=$5; s=$7 + gsub(/users:\(\("/,"",s) + gsub(/".*/,"",s) + print p, n, s + }' <<< "${ports_in_use[$i]}" + )" # Check if the right services are using the right ports - if [[ ${ports_configured[*]} =~ $(echo "${port_number}" | rev | cut -d: -f1 | rev) ]]; then + if [[ ${ports_configured[*]} =~ ${port_number##*:} ]]; then compare_port_to_service_assigned "${ftl}" "${service_name}" "${protocol_type}:${port_number}" else # If it's not a default port that Pi-hole needs, just print it out for the user to see @@ -816,42 +819,27 @@ ftl_full_status(){ make_array_from_file() { local filename="${1}" + + # If the file is a directory do nothing since it cannot be parsed + [[ -d "${filename}" ]] && return + # The second argument can put a limit on how many line should be read from the file # Since some of the files are so large, this is helpful to limit the output local limit=${2} # A local iterator for testing if we are at the limit above local i=0 - # If the file is a directory - if [[ -d "${filename}" ]]; then - # do nothing since it cannot be parsed - : - else - # Otherwise, read the file line by line - while IFS= read -r line;do - # Otherwise, strip out comments and blank lines - new_line=$(echo "${line}" | sed -e 's/^\s*#.*$//' -e '/^$/d') - # If the line still has content (a non-zero value) - if [[ -n "${new_line}" ]]; then - # If the string contains "### CHANGED", highlight this part in red - if [[ "${new_line}" == *"### CHANGED"* ]]; then - new_line="${new_line//### CHANGED/${COL_RED}### CHANGED${COL_NC}}" - fi + # Process the file, strip out comments and blank lines + local processed + processed=$(sed -e 's/^\s*#.*$//' -e '/^$/d' "${filename}") - # Finally, write this line to the log - log_write " ${new_line}" - fi - # Increment the iterator +1 - i=$((i+1)) - # but if the limit of lines we want to see is exceeded - if [[ -z ${limit} ]]; then - # do nothing - : - elif [[ $i -eq ${limit} ]]; then - break - fi - done < "${filename}" - fi + while IFS= read -r line; do + # If the string contains "### CHANGED", highlight this part in red + log_write " ${line//### CHANGED/${COL_RED}### CHANGED${COL_NC}}" + ((i++)) + # if the limit of lines we want to see is exceeded do nothing + [[ -n ${limit} && $i -eq ${limit} ]] && break + done <<< "$processed" } parse_file() { @@ -924,38 +912,38 @@ list_files_in_dir() { fi # Store the files found in an array - mapfile -t files_found < <(ls "${dir_to_parse}") + local files_found=("${dir_to_parse}"/*) # For each file in the array, for each_file in "${files_found[@]}"; do - if [[ -d "${dir_to_parse}/${each_file}" ]]; then + if [[ -d "${each_file}" ]]; then # If it's a directory, do nothing : - elif [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_DEBUG_LOG}" ]] || \ - [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_RAW_BLOCKLIST_FILES}" ]] || \ - [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_INSTALL_LOG_FILE}" ]] || \ - [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_LOG}" ]] || \ - [[ "${dir_to_parse}/${each_file}" == "${PIHOLE_LOG_GZIPS}" ]]; then + elif [[ "${each_file}" == "${PIHOLE_DEBUG_LOG}" ]] || \ + [[ "${each_file}" == "${PIHOLE_RAW_BLOCKLIST_FILES}" ]] || \ + [[ "${each_file}" == "${PIHOLE_INSTALL_LOG_FILE}" ]] || \ + [[ "${each_file}" == "${PIHOLE_LOG}" ]] || \ + [[ "${each_file}" == "${PIHOLE_LOG_GZIPS}" ]]; then : elif [[ "${dir_to_parse}" == "${DNSMASQ_D_DIRECTORY}" ]]; then # in case of the dnsmasq directory include all files in the debug output - log_write "\\n${COL_GREEN}$(ls -lhd "${dir_to_parse}"/"${each_file}")${COL_NC}" - make_array_from_file "${dir_to_parse}/${each_file}" + log_write "\\n${COL_GREEN}$(ls -lhd "${each_file}")${COL_NC}" + make_array_from_file "${each_file}" else # Then, parse the file's content into an array so each line can be analyzed if need be for i in "${!REQUIRED_FILES[@]}"; do - if [[ "${dir_to_parse}/${each_file}" == "${REQUIRED_FILES[$i]}" ]]; then + if [[ "${each_file}" == "${REQUIRED_FILES[$i]}" ]]; then # display the filename - log_write "\\n${COL_GREEN}$(ls -lhd "${dir_to_parse}"/"${each_file}")${COL_NC}" + log_write "\\n${COL_GREEN}$(ls -lhd "${each_file}")${COL_NC}" # Check if the file we want to view has a limit (because sometimes we just need a little bit of info from the file, not the entire thing) - case "${dir_to_parse}/${each_file}" in + case "${each_file}" in # If it's Web server log, give the first and last 25 lines - "${PIHOLE_WEBSERVER_LOG}") head_tail_log "${dir_to_parse}/${each_file}" 25 + "${PIHOLE_WEBSERVER_LOG}") head_tail_log "${each_file}" 25 ;; # Same for the FTL log - "${PIHOLE_FTL_LOG}") head_tail_log "${dir_to_parse}/${each_file}" 35 + "${PIHOLE_FTL_LOG}") head_tail_log "${each_file}" 35 ;; # parse the file into an array in case we ever need to analyze it line-by-line - *) make_array_from_file "${dir_to_parse}/${each_file}"; + *) make_array_from_file "${each_file}"; esac else # Otherwise, do nothing since it's not a file needed for Pi-hole so we don't care about it @@ -991,6 +979,7 @@ head_tail_log() { local filename="${1}" # The number of lines to use for head and tail local qty="${2}" + local filebasename="${filename##*/}" local head_line local tail_line # Put the current Internal Field Separator into another variable so it can be restored later @@ -999,14 +988,14 @@ head_tail_log() { IFS=$'\r\n' local log_head=() mapfile -t log_head < <(head -n "${qty}" "${filename}") - log_write " ${COL_CYAN}-----head of $(basename "${filename}")------${COL_NC}" + log_write " ${COL_CYAN}-----head of ${filebasename}------${COL_NC}" for head_line in "${log_head[@]}"; do log_write " ${head_line}" done log_write "" local log_tail=() mapfile -t log_tail < <(tail -n "${qty}" "${filename}") - log_write " ${COL_CYAN}-----tail of $(basename "${filename}")------${COL_NC}" + log_write " ${COL_CYAN}-----tail of ${filebasename}------${COL_NC}" for tail_line in "${log_tail[@]}"; do log_write " ${tail_line}" done From 03fd486921bdf7bd13330ec861fabca8adac605a Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Tue, 11 Nov 2025 07:28:21 +1000 Subject: [PATCH 228/259] use configured value for web repo when updating or repairing Instead of hardcoded web repo location, get the currently configured location. Imports utils.sh to facilitate this Signed-off-by: Rob Gill --- automated install/basic-install.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 0b186472..e42cabb8 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1808,6 +1808,12 @@ clone_or_reset_repos() { # If the user wants to repair/update, if [[ "${repair}" == true ]]; then printf " %b Resetting local repos\\n" "${INFO}" + + # import getFTLConfigValue from utils.sh + source "/opt/pihole/utils.sh" + # Use the configured Web repo location on repair/update + webInterfaceDir=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome") + # Reset the Core repo resetRepo ${PI_HOLE_LOCAL_REPO} || { From 5f977eb35ff117eeb288908356c8f6060eacd217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 10:01:21 +0000 Subject: [PATCH 229/259] Bump the github-actions-dependencies group with 2 updates Bumps the github-actions-dependencies group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [psf/black](https://github.com/psf/black). Updates `github/codeql-action` from 4.31.2 to 4.31.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db) Updates `psf/black` from 25.9.0 to 25.11.0 - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/af0ba72a73598c76189d6dd1b21d8532255d5942...05f0a8ce1f71fbb36e1e032d3b518c7b945089a2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: psf/black dependency-version: 25.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4e905e66..c412b06f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 + uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 + uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee #v4.31.2 + uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 04638d4e..a7914407 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: run: editorconfig-checker - name: Check python code formatting with black - uses: psf/black@af0ba72a73598c76189d6dd1b21d8532255d5942 #25.9.0 + uses: psf/black@05f0a8ce1f71fbb36e1e032d3b518c7b945089a2 #25.11.0 with: src: "./test" options: "--check --diff --color" From 17dd5b97f3986a3bde617726057ccadc458a0ff2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Nov 2025 10:02:08 +0000 Subject: [PATCH 230/259] Bump pytest in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [pytest](https://github.com/pytest-dev/pytest). Updates `pytest` from 8.4.2 to 9.0.1 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.4.2...9.0.1) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index cfbd4915..d00f8fbe 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ pyyaml == 6.0.3 -pytest == 8.4.2 +pytest == 9.0.1 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 tox == 4.32.0 From 1dc8bfc9503278e67384f464bd3c92eaea853978 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:30:59 +0100 Subject: [PATCH 231/259] Use port from dns.port in piholeDebug.sh Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- advanced/Scripts/piholeDebug.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index cff4d373..e906a0de 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -725,7 +725,7 @@ dig_at() { fi # Check if Pi-hole can use itself to block a domain - if local_dig="$(dig +tries=1 +time=2 -"${protocol}" "${random_url}" @"${local_address}" "${record_type}")"; then + if local_dig="$(dig +tries=1 +time=2 -"${protocol}" "${random_url}" @"${local_address}" "${record_type}" -p "$(get_ftl_conf_value "dns.port")")"; then # If it can, show success if [[ "${local_dig}" == *"status: NOERROR"* ]]; then local_dig="NOERROR" From 987a59f7e58e3dba4ea0c27b1b7396357b7dbac8 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Wed, 19 Nov 2025 16:35:39 -0300 Subject: [PATCH 232/259] Show "Block" and "Allow" instead of 0 and 1 Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 4630aa97..f298b2f3 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -1084,7 +1084,7 @@ show_groups() { } show_adlists() { - show_db_entries "Adlists (type: 0 = blocklist, 1 = allowlist)" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN '0' WHEN '1' THEN ' 1' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 4 100 19 19 50" + show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN 'Block' WHEN '1' THEN 'Allow' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 5 100 19 19 50" } show_domainlist() { From 8c6bb3f8da4340e3818c67060885c2f7ed31d63d Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Thu, 20 Nov 2025 16:46:38 -0300 Subject: [PATCH 233/259] Use text colums instead of number codes on gravity tables - Domains table ("type" column): replace 0, 1, 2 and 3 with "exact-allow", "exact-deny", "regex-allow" and "regex-deny" - All tables: use yes/no for "enabled" columns Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index f298b2f3..9e5ea64b 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -1080,15 +1080,15 @@ check_dhcp_servers() { } show_groups() { - show_db_entries "Groups" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,name,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,description FROM \"group\"" "4 7 50 19 19 50" + show_db_entries "Groups" "SELECT id,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,name,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,description FROM \"group\"" "4 7 50 19 19 50" } show_adlists() { - show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN 'Block' WHEN '1' THEN 'Allow' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 5 100 19 19 50" + show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN 'Block' WHEN '1' THEN 'Allow' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 5 100 19 19 50" } show_domainlist() { - show_db_entries "Domainlist (0/1 = exact allow-/denylist, 2/3 = regex allow-/denylist)" "SELECT id,CASE type WHEN '0' THEN '0 ' WHEN '1' THEN ' 1 ' WHEN '2' THEN ' 2 ' WHEN '3' THEN ' 3' ELSE type END type,CASE enabled WHEN '0' THEN ' 0' WHEN '1' THEN ' 1' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 4 7 12 100 19 19 50" + show_db_entries "Domainlist" "SELECT id,CASE type WHEN '0' THEN 'exact-allow' WHEN '1' THEN 'exact-deny' WHEN '2' THEN 'regex-allow' WHEN '3' THEN 'regex-deny' ELSE type END type,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 11 7 12 100 19 19 50" } show_clients() { From 4b824f931fe5a1a1f6cf37709e1aa22f0975f100 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 10:01:26 +0000 Subject: [PATCH 234/259] Bump the github-actions-dependencies group with 2 updates Bumps the github-actions-dependencies group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [github/codeql-action](https://github.com/github/codeql-action). Updates `actions/checkout` from 5.0.0 to 6.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/08c6903cd8c0fde910a37f88322edcfb5dd907a8...1af3b93b6815bc44a9784bd300feb67ff0d1eeb3) Updates `github/codeql-action` from 4.31.3 to 4.31.4 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/014f16e7ab1402f30e7c3329d33797e7948572db...e12f0178983d466f2f6028f5cc7a6d786fd97f4b) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies - dependency-name: github/codeql-action dependency-version: 4.31.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/test.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c412b06f..d33b9791 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 + uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 + uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db #v4.31.3 + uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 2fdf9291..9b65fec4 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index b8546b64..1a21c34f 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -33,7 +33,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7914407..27d9466f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 with: fetch-depth: 0 # Differential ShellCheck requires full git history @@ -82,7 +82,7 @@ jobs: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 - name: Set up Python uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c #v6.0.0 From 247b0c506b07d1dce2d7f7eb4c9c41f740338528 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Wed, 26 Nov 2025 23:46:43 -0300 Subject: [PATCH 235/259] Remove custom FTL FirewallD zone checks from debug log Removed checks for custom FTL FirewallD zone in piholeDebug.sh. Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index d13f2fbf..dd55e2c8 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -375,22 +375,6 @@ check_firewalld() { log_write "${CROSS} ${COL_RED} Allow Service: ${i}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" fi done - # check for custom FTL FirewallD zone - local firewalld_zones - firewalld_zones=$(firewall-cmd --get-zones) - if [[ "${firewalld_zones}" =~ "ftl" ]]; then - log_write "${TICK} ${COL_GREEN}FTL Custom Zone Detected${COL_NC}"; - # check FTL custom zone interface: lo - local firewalld_ftl_zone_interfaces - firewalld_ftl_zone_interfaces=$(firewall-cmd --zone=ftl --list-interfaces) - if [[ "${firewalld_ftl_zone_interfaces}" =~ "lo" ]]; then - log_write "${TICK} ${COL_GREEN} Local Interface Detected${COL_NC}"; - else - log_write "${CROSS} ${COL_RED} Local Interface Not Detected${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" - fi - else - log_write "${CROSS} ${COL_RED}FTL Custom Zone Not Detected${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS_FIREWALLD})" - fi fi else log_write "${TICK} ${COL_GREEN}Firewalld service not detected${COL_NC}"; From d77179a412c4d6fafaf1c985b0ec8b5baa31220d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:01:27 +0000 Subject: [PATCH 236/259] Bump the github-actions-dependencies group with 2 updates Bumps the github-actions-dependencies group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [actions/setup-python](https://github.com/actions/setup-python). Updates `github/codeql-action` from 4.31.4 to 4.31.5 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e12f0178983d466f2f6028f5cc7a6d786fd97f4b...fdbfb4d2750291e159f0156def62b853c2798ca2) Updates `actions/setup-python` from 6.0.0 to 6.1.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/e797f83bcb11b83ae66e0230d6156d7c80228e7c...83679a892e2d95755f2dac6acb0bfd1e9ac5d548) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: actions/setup-python dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/test.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d33b9791..61ef30d5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 + uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 + uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b #v4.31.4 + uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 27d9466f..ab5ac940 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,7 +85,7 @@ jobs: uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 - name: Set up Python - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c #v6.0.0 + uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 #v6.1.0 with: python-version: "3.13" From 353105ec0f1f2ad3c047917d063e2dad6d57ec92 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Sun, 30 Nov 2025 19:00:15 +0100 Subject: [PATCH 237/259] remove wget from alpine dependencies Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- automated install/basic-install.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 0b186472..a0b37a9c 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -155,7 +155,7 @@ EOM ) # List of required packages on APK based systems -PIHOLE_META_VERSION_APK=0.1 +PIHOLE_META_VERSION_APK=0.2 PIHOLE_META_DEPS_APK=( bash bash-completion @@ -181,7 +181,6 @@ PIHOLE_META_DEPS_APK=( sudo tzdata unzip - wget ) ######## Undocumented Flags. Shhh ######## From 95ae51bbdbb028625b541466c2f1caabfeb2301c Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 30 Nov 2025 18:42:02 -0300 Subject: [PATCH 238/259] Use more specific strings on the tables to match only desired text - use `--no---` and `--yes---` to make sure the strings won't match user comments or parts of domains - also use `-ALLOW-` and `-BLOCK-` Also reduce the domain column to 90 characters Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index d13f2fbf..74cdce2f 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -1069,15 +1069,15 @@ check_dhcp_servers() { } show_groups() { - show_db_entries "Groups" "SELECT id,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,name,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,description FROM \"group\"" "4 7 50 19 19 50" + show_db_entries "Groups" "SELECT id,CASE enabled WHEN '0' THEN '--no---' WHEN '1' THEN '--yes--' ELSE enabled END enabled,name,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,description FROM \"group\"" "4 7 50 19 19 50" } show_adlists() { - show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN 'Block' WHEN '1' THEN 'Allow' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 5 100 19 19 50" + show_db_entries "Adlists" "SELECT id,CASE enabled WHEN '0' THEN '--no---' WHEN '1' THEN '--yes--' ELSE enabled END enabled,GROUP_CONCAT(adlist_by_group.group_id) group_ids, CASE type WHEN '0' THEN '-BLOCK-' WHEN '1' THEN '-ALLOW-' ELSE type END type, address,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM adlist LEFT JOIN adlist_by_group ON adlist.id = adlist_by_group.adlist_id GROUP BY id;" "5 7 12 7 100 19 19 50" } show_domainlist() { - show_db_entries "Domainlist" "SELECT id,CASE type WHEN '0' THEN 'exact-allow' WHEN '1' THEN 'exact-deny' WHEN '2' THEN 'regex-allow' WHEN '3' THEN 'regex-deny' ELSE type END type,CASE enabled WHEN '0' THEN ' no' WHEN '1' THEN ' yes' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 11 7 12 100 19 19 50" + show_db_entries "Domainlist" "SELECT id,CASE type WHEN '0' THEN 'exact-allow' WHEN '1' THEN 'exact-deny' WHEN '2' THEN 'regex-allow' WHEN '3' THEN 'regex-deny' ELSE type END type,CASE enabled WHEN '0' THEN '--no---' WHEN '1' THEN '--yes--' ELSE enabled END enabled,GROUP_CONCAT(domainlist_by_group.group_id) group_ids,domain,datetime(date_added,'unixepoch','localtime') date_added,datetime(date_modified,'unixepoch','localtime') date_modified,comment FROM domainlist LEFT JOIN domainlist_by_group ON domainlist.id = domainlist_by_group.domainlist_id GROUP BY id;" "5 11 7 12 90 19 19 50" } show_clients() { From 1f4ed9b518f19583047a7005f237ddde03267a24 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Sun, 30 Nov 2025 18:43:40 -0300 Subject: [PATCH 239/259] Replace some strings with their colored equivalents Signed-off-by: RD WebDesign --- advanced/Scripts/piholeDebug.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 74cdce2f..9d443c60 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -1022,6 +1022,24 @@ show_db_entries() { ) for line in "${entries[@]}"; do + # Use gray color for "no". Normal color for "yes" + line=${line//--no---/${COL_GRAY} no ${COL_NC}} + line=${line//--yes--/ yes } + + # Use red for "deny" and green for "allow" + if [ "$title" = "Domainlist" ]; then + line=${line//regex-deny/${COL_RED}regex-deny${COL_NC}} + line=${line//regex-allow/${COL_GREEN}regex-allow${COL_NC}} + line=${line//exact-deny/${COL_RED}exact-deny${COL_NC}} + line=${line//exact-allow/${COL_GREEN}exact-allow${COL_NC}} + fi + + # Use red for "block" and green for "allow" + if [ "$title" = "Adlists" ]; then + line=${line//-BLOCK-/${COL_RED} Block ${COL_NC}} + line=${line//-ALLOW-/${COL_GREEN} Allow ${COL_NC}} + fi + log_write " ${line}" done From f5f74066fc8615c42182e7550f9a06ca44996868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 3 Dec 2025 23:37:04 +0100 Subject: [PATCH 240/259] Add Alpine 3.23 to test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- .github/workflows/test.yml | 1 + test/_alpine_3_23.Dockerfile | 18 ++++++++++++++++++ test/tox.alpine_3_23.ini | 10 ++++++++++ 3 files changed, 29 insertions(+) create mode 100644 test/_alpine_3_23.Dockerfile create mode 100644 test/tox.alpine_3_23.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab5ac940..12213fab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,6 +77,7 @@ jobs: fedora_43, alpine_3_21, alpine_3_22, + alpine_3_23, ] env: DISTRO: ${{matrix.distro}} diff --git a/test/_alpine_3_23.Dockerfile b/test/_alpine_3_23.Dockerfile new file mode 100644 index 00000000..2cb34137 --- /dev/null +++ b/test/_alpine_3_23.Dockerfile @@ -0,0 +1,18 @@ +FROM alpine:3.23 + +ENV GITDIR=/etc/.pihole +ENV SCRIPTDIR=/opt/pihole +RUN sed -i 's/#\(.*\/community\)/\1/' /etc/apk/repositories +RUN apk --no-cache add bash coreutils curl git jq openrc shadow + +RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole +ADD . $GITDIR +RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ +ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR + +RUN true && \ + chmod +x $SCRIPTDIR/* + +ENV SKIP_INSTALL=true + +#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ diff --git a/test/tox.alpine_3_23.ini b/test/tox.alpine_3_23.ini new file mode 100644 index 00000000..d7208064 --- /dev/null +++ b/test/tox.alpine_3_23.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py3 + +[testenv:py3] +allowlist_externals = docker +deps = -rrequirements.txt +setenv = + COLUMNS=120 +commands = docker buildx build --load --progress plain -f _alpine_3_23.Dockerfile -t pytest_pihole:test_container ../ + pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py From a5c6c2c12c889677ce4a56d041a97e71fe067435 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 10:01:25 +0000 Subject: [PATCH 241/259] Bump the github-actions-dependencies group with 3 updates Bumps the github-actions-dependencies group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action](https://github.com/github/codeql-action) and [actions/stale](https://github.com/actions/stale). Updates `actions/checkout` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8) Updates `github/codeql-action` from 4.31.5 to 4.31.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/fdbfb4d2750291e159f0156def62b853c2798ca2...cf1bb45a277cb3c205638b2cd5c984db1c46a412) Updates `actions/stale` from 10.1.0 to 10.1.1 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/5f858e3efba33a5ca4407a664cc011ad407f2008...997185467fa4f803885201cee163a9f38240193d) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: github/codeql-action dependency-version: 4.31.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: actions/stale dependency-version: 10.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/stale.yml | 4 ++-- .github/workflows/stale_pr.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/test.yml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 61ef30d5..728c789e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 + uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 + uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 #v4.31.5 + uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 9b65fec4..deeaa675 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: issues: write steps: - - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 #v10.1.0 + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d #v10.1.1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/stale_pr.yml b/.github/workflows/stale_pr.yml index 7d68df6a..6dfcbe99 100644 --- a/.github/workflows/stale_pr.yml +++ b/.github/workflows/stale_pr.yml @@ -17,7 +17,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 #v10.1.0 + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d #v10.1.1 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Do not automatically mark PR/issue as stale diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 1a21c34f..4901f359 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -33,7 +33,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 12213fab..88f88785 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 with: fetch-depth: 0 # Differential ShellCheck requires full git history @@ -83,7 +83,7 @@ jobs: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 #v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 #v6.1.0 From 9f07e74eb8f079da302eeef48273e3799c00cc6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Dec 2025 10:01:35 +0000 Subject: [PATCH 242/259] Bump the github-actions-dependencies group with 3 updates Bumps the github-actions-dependencies group with 3 updates: [github/codeql-action](https://github.com/github/codeql-action), [redhat-plumbers-in-action/differential-shellcheck](https://github.com/redhat-plumbers-in-action/differential-shellcheck) and [psf/black](https://github.com/psf/black). Updates `github/codeql-action` from 4.31.7 to 4.31.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cf1bb45a277cb3c205638b2cd5c984db1c46a412...1b168cd39490f61582a9beae412bb7057a6b2c4e) Updates `redhat-plumbers-in-action/differential-shellcheck` from 5.5.5 to 5.5.6 - [Release notes](https://github.com/redhat-plumbers-in-action/differential-shellcheck/releases) - [Changelog](https://github.com/redhat-plumbers-in-action/differential-shellcheck/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/redhat-plumbers-in-action/differential-shellcheck/compare/0d9e5b29625f871e6a4215380486d6f1a7cb6cdd...d965e66ec0b3b2f821f75c8eff9b12442d9a7d1e) Updates `psf/black` from 25.11.0 to 25.12.0 - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/05f0a8ce1f71fbb36e1e032d3b518c7b945089a2...782e5605c86aab56be6f905da10dcd3e463fd9c2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: redhat-plumbers-in-action/differential-shellcheck dependency-version: 5.5.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: psf/black dependency-version: 25.12.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/test.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 728c789e..7c5a104c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 + uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 + uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 #v4.31.7 + uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 88f88785..0bfae55c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: [[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!" - name: Differential ShellCheck - uses: redhat-plumbers-in-action/differential-shellcheck@0d9e5b29625f871e6a4215380486d6f1a7cb6cdd #v5.5.5 + uses: redhat-plumbers-in-action/differential-shellcheck@d965e66ec0b3b2f821f75c8eff9b12442d9a7d1e #v5.5.6 with: severity: warning display-engine: sarif-fmt @@ -49,7 +49,7 @@ jobs: run: editorconfig-checker - name: Check python code formatting with black - uses: psf/black@05f0a8ce1f71fbb36e1e032d3b518c7b945089a2 #25.11.0 + uses: psf/black@782e5605c86aab56be6f905da10dcd3e463fd9c2 #25.12.0 with: src: "./test" options: "--check --diff --color" From 3ddf4014aff586c43398d57f6ad42e9c6002a5fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Dec 2025 10:02:04 +0000 Subject: [PATCH 243/259] Bump pytest in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [pytest](https://github.com/pytest-dev/pytest). Updates `pytest` from 9.0.1 to 9.0.2 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/9.0.1...9.0.2) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index d00f8fbe..d6058566 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -1,5 +1,5 @@ pyyaml == 6.0.3 -pytest == 9.0.1 +pytest == 9.0.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 tox == 4.32.0 From dd1e60b505bdc30970ce813b31f1df642afa8fc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Dec 2025 10:01:25 +0000 Subject: [PATCH 244/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.31.8 to 4.31.9 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/1b168cd39490f61582a9beae412bb7057a6b2c4e...5d4e8d1aca955e8d8589aabd499c5cae939e33c7) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7c5a104c..47b92b0f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 + uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e #v4.31.8 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 From 102bc6043d6e79dfb0d6e76b0c17d71602e907d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Jan 2026 10:01:40 +0000 Subject: [PATCH 245/259] Bump tox from 4.32.0 to 4.33.0 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.32.0 to 4.33.0 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.32.0...4.33.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.33.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index d6058566..b6991f2e 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.3 pytest == 9.0.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.32.0 +tox == 4.33.0 pytest-clarity == 1.0.1 From d0433cdb48ce410f0f7f12ab166a678c458ec652 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Wed, 7 Jan 2026 00:28:09 -0300 Subject: [PATCH 246/259] Add missing `-g` to the message in gravity recovery command Signed-off-by: RD WebDesign --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 5720ca41..22e6c742 100755 --- a/gravity.sh +++ b/gravity.sh @@ -947,7 +947,7 @@ database_recovery() { else echo -e "${OVER} ${CROSS} ${str} - the following errors happened:" while IFS= read -r line; do echo " - $line"; done <<<"$result" - echo -e " ${CROSS} Recovery failed. Try \"pihole -r recreate\" instead." + echo -e " ${CROSS} Recovery failed. Try \"pihole -g -r recreate\" instead." exit 1 fi echo "" From ec6d3e2f83ef2bb2faf3f4802fd630fbe5680e9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 10 Jan 2026 10:01:07 +0000 Subject: [PATCH 247/259] Bump tox from 4.33.0 to 4.34.1 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.33.0 to 4.34.1 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.33.0...4.34.1) --- updated-dependencies: - dependency-name: tox dependency-version: 4.34.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index b6991f2e..5baac071 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.3 pytest == 9.0.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.33.0 +tox == 4.34.1 pytest-clarity == 1.0.1 From 887255f518456155e000a74516e01786881af23e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 10:02:42 +0000 Subject: [PATCH 248/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.31.9 to 4.31.10 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5d4e8d1aca955e8d8589aabd499c5cae939e33c7...cdefb33c0f6224e58673d9004f47f7cb3e328b89) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.10 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 47b92b0f..3aa26016 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 + uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v4.31.9 + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 From f0bc92038455f1c9026aa4463af9b001a49d5fe9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Jan 2026 10:02:49 +0000 Subject: [PATCH 249/259] Bump the github-actions-dependencies group with 4 updates Bumps the github-actions-dependencies group with 4 updates: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action](https://github.com/github/codeql-action), [psf/black](https://github.com/psf/black) and [actions/setup-python](https://github.com/actions/setup-python). Updates `actions/checkout` from 6.0.1 to 6.0.2 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd) Updates `github/codeql-action` from 4.31.10 to 4.31.11 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/cdefb33c0f6224e58673d9004f47f7cb3e328b89...19b2f06db2b6f5108140aeb04014ef02b648f789) Updates `psf/black` from 25.12.0 to 26.1.0 - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/782e5605c86aab56be6f905da10dcd3e463fd9c2...6305bf1ae645ab7541be4f5028a86239316178eb) Updates `actions/setup-python` from 6.1.0 to 6.2.0 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/83679a892e2d95755f2dac6acb0bfd1e9ac5d548...a309ff8b426b58ec0e2a45f0f869d46889d02405) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: github/codeql-action dependency-version: 4.31.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies - dependency-name: psf/black dependency-version: 26.1.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions-dependencies - dependency-name: actions/setup-python dependency-version: 6.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/stale.yml | 2 +- .github/workflows/sync-back-to-dev.yml | 2 +- .github/workflows/test.yml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3aa26016..e4634816 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 + uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 + uses: github/codeql-action/autobuild@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 #v4.31.10 + uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index deeaa675..1e044ec9 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 - name: Remove 'stale' label run: gh issue edit ${{ github.event.issue.number }} --remove-label ${{ env.stale_label }} env: diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 4901f359..058bbcab 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -33,7 +33,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 - name: Opening pull request run: gh pr create -B development -H master --title 'Sync master back into development' --body 'Created by Github action' --label 'internal' env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0bfae55c..6482e242 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 with: fetch-depth: 0 # Differential ShellCheck requires full git history @@ -49,7 +49,7 @@ jobs: run: editorconfig-checker - name: Check python code formatting with black - uses: psf/black@782e5605c86aab56be6f905da10dcd3e463fd9c2 #25.12.0 + uses: psf/black@6305bf1ae645ab7541be4f5028a86239316178eb #26.1.0 with: src: "./test" options: "--check --diff --color" @@ -83,10 +83,10 @@ jobs: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 #v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 #v6.2.0 with: python-version: "3.13" From 03ee5b514d86030d34b4501996c44f044e87687c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 27 Jan 2026 20:19:46 +0100 Subject: [PATCH 250/259] Fix black formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- test/conftest.py | 96 ++++++-------------- test/test_any_automated_install.py | 106 +++++++--------------- test/test_any_utils.py | 30 ++---- test/test_centos_fedora_common_support.py | 26 ++---- 4 files changed, 78 insertions(+), 180 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index dcf49790..d4c763e7 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -51,29 +51,19 @@ def mock_command(script, args, container): in unit tests """ full_script_path = "/usr/local/bin/{}".format(script) - mock_script = dedent( - r"""\ + mock_script = dedent(r"""\ #!/bin/bash -e echo "\$0 \$@" >> /var/log/{script} - case "\$1" in""".format( - script=script - ) - ) + case "\$1" in""".format(script=script)) for k, v in args.items(): - case = dedent( - """ + case = dedent(""" {arg}) echo {res} exit {retcode} - ;;""".format( - arg=k, res=v[0], retcode=v[1] - ) - ) + ;;""".format(arg=k, res=v[0], retcode=v[1])) mock_script += case - mock_script += dedent( - """ - esac""" - ) + mock_script += dedent(""" + esac""") container.run( """ cat < {script}\n{content}\nEOF @@ -94,37 +84,23 @@ def mock_command_passthrough(script, args, container): """ orig_script_path = container.check_output("command -v {}".format(script)) full_script_path = "/usr/local/bin/{}".format(script) - mock_script = dedent( - r"""\ + mock_script = dedent(r"""\ #!/bin/bash -e echo "\$0 \$@" >> /var/log/{script} - case "\$1" in""".format( - script=script - ) - ) + case "\$1" in""".format(script=script)) for k, v in args.items(): - case = dedent( - """ + case = dedent(""" {arg}) echo {res} exit {retcode} - ;;""".format( - arg=k, res=v[0], retcode=v[1] - ) - ) + ;;""".format(arg=k, res=v[0], retcode=v[1])) mock_script += case - mock_script += dedent( - r""" + mock_script += dedent(r""" *) {orig_script_path} "\$@" - ;;""".format( - orig_script_path=orig_script_path - ) - ) - mock_script += dedent( - """ - esac""" - ) + ;;""".format(orig_script_path=orig_script_path)) + mock_script += dedent(""" + esac""") container.run( """ cat < {script}\n{content}\nEOF @@ -141,29 +117,19 @@ def mock_command_run(script, args, container): in unit tests """ full_script_path = "/usr/local/bin/{}".format(script) - mock_script = dedent( - r"""\ + mock_script = dedent(r"""\ #!/bin/bash -e echo "\$0 \$@" >> /var/log/{script} - case "\$1 \$2" in""".format( - script=script - ) - ) + case "\$1 \$2" in""".format(script=script)) for k, v in args.items(): - case = dedent( - """ + case = dedent(""" \"{arg}\") echo {res} exit {retcode} - ;;""".format( - arg=k, res=v[0], retcode=v[1] - ) - ) + ;;""".format(arg=k, res=v[0], retcode=v[1])) mock_script += case - mock_script += dedent( - """ - esac""" - ) + mock_script += dedent(r""" + esac""") container.run( """ cat < {script}\n{content}\nEOF @@ -180,29 +146,19 @@ def mock_command_2(script, args, container): in unit tests """ full_script_path = "/usr/local/bin/{}".format(script) - mock_script = dedent( - r"""\ + mock_script = dedent(r"""\ #!/bin/bash -e echo "\$0 \$@" >> /var/log/{script} - case "\$1 \$2" in""".format( - script=script - ) - ) + case "\$1 \$2" in""".format(script=script)) for k, v in args.items(): - case = dedent( - """ + case = dedent(""" \"{arg}\") echo \"{res}\" exit {retcode} - ;;""".format( - arg=k, res=v[0], retcode=v[1] - ) - ) + ;;""".format(arg=k, res=v[0], retcode=v[1])) mock_script += case - mock_script += dedent( - """ - esac""" - ) + mock_script += dedent(r""" + esac""") container.run( """ cat < {script}\n{content}\nEOF diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 0a561b36..edbbd8ab 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -6,10 +6,8 @@ from .conftest import ( info_box, cross_box, mock_command, - mock_command_run, mock_command_2, mock_command_passthrough, - run_script, ) FTL_BRANCH = "development" @@ -23,12 +21,10 @@ def test_supported_package_manager(host): host.run("rm -rf /usr/bin/apt-get") host.run("rm -rf /usr/bin/rpm") host.run("rm -rf /sbin/apk") - package_manager_detect = host.run( - """ + package_manager_detect = host.run(""" source /opt/pihole/basic-install.sh package_manager_detect - """ - ) + """) expected_stdout = cross_box + " No supported package manager found" assert expected_stdout in package_manager_detect.stdout # assert package_manager_detect.rc == 1 @@ -38,13 +34,11 @@ def test_selinux_not_detected(host): """ confirms installer continues when SELinux configuration file does not exist """ - check_selinux = host.run( - """ + check_selinux = host.run(""" rm -f /etc/selinux/config source /opt/pihole/basic-install.sh checkSelinux - """ - ) + """) expected_stdout = info_box + " SELinux not detected" assert expected_stdout in check_selinux.stdout assert check_selinux.rc == 0 @@ -95,8 +89,7 @@ def test_installPihole_fresh_install_readableFiles(host): host.run("command -v apk > /dev/null && apk add mandoc man-pages") # Workaround to get FTLv6 installed until it reaches master branch host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch') - install = host.run( - """ + install = host.run(""" export TERM=xterm export DEBIAN_FRONTEND=noninteractive umask 0027 @@ -105,8 +98,7 @@ def test_installPihole_fresh_install_readableFiles(host): runUnattended=true main /opt/pihole/pihole-FTL-prestart.sh - """ - ) + """) assert 0 == install.rc maninstalled = True if (info_box + " man not installed") in install.stdout: @@ -201,13 +193,11 @@ def test_update_package_cache_success_no_errors(host): """ confirms package cache was updated without any errors """ - updateCache = host.run( - """ + updateCache = host.run(""" source /opt/pihole/basic-install.sh package_manager_detect update_package_cache - """ - ) + """) expected_stdout = tick_box + " Update local cache of available packages" assert expected_stdout in updateCache.stdout assert "error" not in updateCache.stdout.lower() @@ -218,13 +208,11 @@ def test_update_package_cache_failure_no_errors(host): confirms package cache was not updated """ mock_command("apt-get", {"update": ("", "1")}, host) - updateCache = host.run( - """ + updateCache = host.run(""" source /opt/pihole/basic-install.sh package_manager_detect update_package_cache - """ - ) + """) expected_stdout = cross_box + " Update local cache of available packages" assert expected_stdout in updateCache.stdout assert "Error: Unable to update package cache." in updateCache.stdout @@ -260,16 +248,14 @@ def test_FTL_detect_no_errors(host, arch, detected_string, supported): host, ) host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch') - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh create_pihole_user funcOutput=$(get_binary_name) binary="pihole-FTL${funcOutput##*pihole-FTL}" theRest="${funcOutput%pihole-FTL*}" FTLdetect "${binary}" "${theRest}" - """ - ) + """) if supported: expected_stdout = info_box + " FTL Checks..." assert expected_stdout in detectPlatform.stdout @@ -289,22 +275,18 @@ def test_FTL_development_binary_installed_and_responsive_no_errors(host): confirms FTL development binary is copied and functional in installed location """ host.run('echo "' + FTL_BRANCH + '" > /etc/pihole/ftlbranch') - host.run( - """ + host.run(""" source /opt/pihole/basic-install.sh create_pihole_user funcOutput=$(get_binary_name) binary="pihole-FTL${funcOutput##*pihole-FTL}" theRest="${funcOutput%pihole-FTL*}" FTLdetect "${binary}" "${theRest}" - """ - ) - version_check = host.run( - """ + """) + version_check = host.run(""" VERSION=$(pihole-FTL version) echo ${VERSION:0:1} - """ - ) + """) expected_stdout = "v" assert expected_stdout in version_check.stdout @@ -319,12 +301,10 @@ def test_IPv6_only_link_local(host): {"-6 address": ("inet6 fe80::d210:52fa:fe00:7ad7/64 scope link", "0")}, host, ) - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh find_IPv6_information - """ - ) + """) expected_stdout = "Unable to find IPv6 ULA/GUA address" assert expected_stdout in detectPlatform.stdout @@ -344,12 +324,10 @@ def test_IPv6_only_ULA(host): }, host, ) - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh find_IPv6_information - """ - ) + """) expected_stdout = "Found IPv6 ULA address" assert expected_stdout in detectPlatform.stdout @@ -369,12 +347,10 @@ def test_IPv6_only_GUA(host): }, host, ) - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh find_IPv6_information - """ - ) + """) expected_stdout = "Found IPv6 GUA address" assert expected_stdout in detectPlatform.stdout @@ -395,12 +371,10 @@ def test_IPv6_GUA_ULA_test(host): }, host, ) - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh find_IPv6_information - """ - ) + """) expected_stdout = "Found IPv6 ULA address" assert expected_stdout in detectPlatform.stdout @@ -421,12 +395,10 @@ def test_IPv6_ULA_GUA_test(host): }, host, ) - detectPlatform = host.run( - """ + detectPlatform = host.run(""" source /opt/pihole/basic-install.sh find_IPv6_information - """ - ) + """) expected_stdout = "Found IPv6 ULA address" assert expected_stdout in detectPlatform.stdout @@ -437,14 +409,10 @@ def test_validate_ip(host): """ def test_address(addr, success=True): - output = host.run( - """ + output = host.run(""" source /opt/pihole/basic-install.sh valid_ip "{addr}" - """.format( - addr=addr - ) - ) + """.format(addr=addr)) assert output.rc == 0 if success else 1 @@ -479,15 +447,13 @@ def test_validate_ip(host): def test_package_manager_has_pihole_deps(host): """Confirms OS is able to install the required packages for Pi-hole""" mock_command("dialog", {"*": ("", "0")}, host) - output = host.run( - """ + output = host.run(""" source /opt/pihole/basic-install.sh package_manager_detect update_package_cache build_dependency_package install_dependent_packages - """ - ) + """) assert "No package" not in output.stdout assert output.rc == 0 @@ -496,21 +462,17 @@ def test_package_manager_has_pihole_deps(host): def test_meta_package_uninstall(host): """Confirms OS is able to install and uninstall the Pi-hole meta package""" mock_command("dialog", {"*": ("", "0")}, host) - install = host.run( - """ + install = host.run(""" source /opt/pihole/basic-install.sh package_manager_detect update_package_cache build_dependency_package install_dependent_packages - """ - ) + """) assert install.rc == 0 - uninstall = host.run( - """ + uninstall = host.run(""" source /opt/pihole/uninstall.sh removeMetaPackage - """ - ) + """) assert uninstall.rc == 0 diff --git a/test/test_any_utils.py b/test/test_any_utils.py index 0f9ae6d2..43e637f3 100644 --- a/test/test_any_utils.py +++ b/test/test_any_utils.py @@ -1,31 +1,25 @@ def test_key_val_replacement_works(host): """Confirms addOrEditKeyValPair either adds or replaces a key value pair in a given file""" - host.run( - """ + host.run(""" source /opt/pihole/utils.sh addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1" addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2" addOrEditKeyValPair "./testoutput" "KEY_ONE" "value3" addOrEditKeyValPair "./testoutput" "KEY_FOUR" "value4" - """ - ) - output = host.run( - """ + """) + output = host.run(""" cat ./testoutput - """ - ) + """) expected_stdout = "KEY_ONE=value3\nKEY_TWO=value2\nKEY_FOUR=value4\n" assert expected_stdout == output.stdout def test_getFTLPID_default(host): """Confirms getFTLPID returns the default value if FTL is not running""" - output = host.run( - """ + output = host.run(""" source /opt/pihole/utils.sh getFTLPID - """ - ) + """) expected_stdout = "-1\n" assert expected_stdout == output.stdout @@ -36,8 +30,7 @@ def test_setFTLConfigValue_getFTLConfigValue(host): Requires FTL to be installed, so we do that first (taken from test_FTL_development_binary_installed_and_responsive_no_errors) """ - host.run( - """ + host.run(""" source /opt/pihole/basic-install.sh create_pihole_user funcOutput=$(get_binary_name) @@ -45,15 +38,12 @@ def test_setFTLConfigValue_getFTLConfigValue(host): binary="pihole-FTL${funcOutput##*pihole-FTL}" theRest="${funcOutput%pihole-FTL*}" FTLdetect "${binary}" "${theRest}" - """ - ) + """) - output = host.run( - """ + output = host.run(""" source /opt/pihole/utils.sh setFTLConfigValue "dns.upstreams" '["9.9.9.9"]' > /dev/null getFTLConfigValue "dns.upstreams" - """ - ) + """) assert "[ 9.9.9.9 ]" in output.stdout diff --git a/test/test_centos_fedora_common_support.py b/test/test_centos_fedora_common_support.py index 7e0bae4e..a892db87 100644 --- a/test/test_centos_fedora_common_support.py +++ b/test/test_centos_fedora_common_support.py @@ -15,14 +15,10 @@ def mock_selinux_config(state, host): # getenforce returns the running state of SELinux mock_command("getenforce", {"*": (state.capitalize(), "0")}, host) # create mock configuration with desired content - host.run( - """ + host.run(""" mkdir /etc/selinux echo "SELINUX={state}" > /etc/selinux/config - """.format( - state=state.lower() - ) - ) + """.format(state=state.lower())) def test_selinux_enforcing_exit(host): @@ -30,12 +26,10 @@ def test_selinux_enforcing_exit(host): confirms installer prompts to exit when SELinux is Enforcing by default """ mock_selinux_config("enforcing", host) - check_selinux = host.run( - """ + check_selinux = host.run(""" source /opt/pihole/basic-install.sh checkSelinux - """ - ) + """) expected_stdout = cross_box + " Current SELinux: enforcing" assert expected_stdout in check_selinux.stdout expected_stdout = "SELinux Enforcing detected, exiting installer" @@ -48,12 +42,10 @@ def test_selinux_permissive(host): confirms installer continues when SELinux is Permissive """ mock_selinux_config("permissive", host) - check_selinux = host.run( - """ + check_selinux = host.run(""" source /opt/pihole/basic-install.sh checkSelinux - """ - ) + """) expected_stdout = tick_box + " Current SELinux: permissive" assert expected_stdout in check_selinux.stdout assert check_selinux.rc == 0 @@ -64,12 +56,10 @@ def test_selinux_disabled(host): confirms installer continues when SELinux is Disabled """ mock_selinux_config("disabled", host) - check_selinux = host.run( - """ + check_selinux = host.run(""" source /opt/pihole/basic-install.sh checkSelinux - """ - ) + """) expected_stdout = tick_box + " Current SELinux: disabled" assert expected_stdout in check_selinux.stdout assert check_selinux.rc == 0 From 19f80a1aa713615a29517926b9551d060d1a71fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 31 Jan 2026 10:02:46 +0000 Subject: [PATCH 251/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.31.11 to 4.32.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/19b2f06db2b6f5108140aeb04014ef02b648f789...b20883b0cd1f46c72ae0ba6d1090936928f9fa30) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e4634816..5415dded 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 + uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 #v4.31.11 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 From 8c4778025a484fb0e3796759c364f55b6dcf05ef Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Thu, 5 Feb 2026 18:44:42 +0100 Subject: [PATCH 252/259] Don't install unused /usr/local/share/man/man5 Last used before `pihole-FTL.conf.5` was removed with https://github.com/pi-hole/pi-hole/pull/4489 Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- automated install/basic-install.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 3aa2c4bf..9a8a87ad 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1251,10 +1251,6 @@ install_manpage() { # if not present, create man8 directory install -d -m 755 /usr/local/share/man/man8 fi - if [[ ! -d "/usr/local/share/man/man5" ]]; then - # if not present, create man5 directory - install -d -m 755 /usr/local/share/man/man5 - fi # Testing complete, copy the files & update the man db install -D -m 644 -T ${PI_HOLE_LOCAL_REPO}/manpages/pihole.8 /usr/local/share/man/man8/pihole.8 From 3d5c832dbe7b8c76a579e1dcfa133bac4ca869e4 Mon Sep 17 00:00:00 2001 From: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> Date: Fri, 6 Feb 2026 16:49:13 +0100 Subject: [PATCH 253/259] Remove /usr/local/share/man/man5 from tests Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com> --- test/test_any_automated_install.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index edbbd8ab..aa48fd32 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -154,12 +154,6 @@ def test_installPihole_fresh_install_readableFiles(host): check_man = test_cmd.format("r", "/usr/local/share/man/man8", piholeuser) actual_rc = host.run(check_man).rc assert exit_status_success == actual_rc - check_man = test_cmd.format("x", "/usr/local/share/man/man5", piholeuser) - actual_rc = host.run(check_man).rc - assert exit_status_success == actual_rc - check_man = test_cmd.format("r", "/usr/local/share/man/man5", piholeuser) - actual_rc = host.run(check_man).rc - assert exit_status_success == actual_rc check_man = test_cmd.format( "r", "/usr/local/share/man/man8/pihole.8", piholeuser ) From a90df8072ce93814fbfa21dd7a25671b28ee1a59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 10:02:40 +0000 Subject: [PATCH 254/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.32.0 to 4.32.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b20883b0cd1f46c72ae0ba6d1090936928f9fa30...45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.32.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5415dded..5d2b30bf 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 + uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 + uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 #v4.32.0 + uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 From 0b0cbdf7d07182b9b99791d1cd676f7a0c51acf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 10:02:34 +0000 Subject: [PATCH 255/259] Bump tox from 4.34.1 to 4.35.0 in /test in the python-dependencies group Bumps the python-dependencies group in /test with 1 update: [tox](https://github.com/tox-dev/tox). Updates `tox` from 4.34.1 to 4.35.0 - [Release notes](https://github.com/tox-dev/tox/releases) - [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst) - [Commits](https://github.com/tox-dev/tox/compare/4.34.1...4.35.0) --- updated-dependencies: - dependency-name: tox dependency-version: 4.35.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-dependencies ... Signed-off-by: dependabot[bot] --- test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/requirements.txt b/test/requirements.txt index 5baac071..61f18c4e 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -2,5 +2,5 @@ pyyaml == 6.0.3 pytest == 9.0.2 pytest-xdist == 3.8.0 pytest-testinfra == 10.2.2 -tox == 4.34.1 +tox == 4.35.0 pytest-clarity == 1.0.1 From 75af6dc9686579c4ad25ce60a450d6834870f8db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 10:02:35 +0000 Subject: [PATCH 256/259] Bump github/codeql-action in the github-actions-dependencies group Bumps the github-actions-dependencies group with 1 update: [github/codeql-action](https://github.com/github/codeql-action). Updates `github/codeql-action` from 4.32.2 to 4.32.3 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2...9e907b5e64f6b83e7804b09294d44122997950d6) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.32.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-dependencies ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5d2b30bf..ee923724 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,12 +29,12 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 #v4.32.3 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 + uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 #v4.32.3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 #v4.32.2 + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 #v4.32.3 From d765ce768f0769b2d21e6ee80201c322020c720a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 16 Feb 2026 20:09:58 +0100 Subject: [PATCH 257/259] Wipe version file before creating a new one Signed-off-by: yubiuser --- advanced/Scripts/updatecheck.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index 44f21419..a54e5c9e 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -50,8 +50,12 @@ rm -f "/etc/pihole/GitHubVersions" rm -f "/etc/pihole/localbranches" rm -f "/etc/pihole/localversions" -# Create new versions file if it does not exist VERSION_FILE="/etc/pihole/versions" + +# Remove the version file if it exists +rm -f "${VERSION_FILE}" + +# Create new versions file touch "${VERSION_FILE}" chmod 644 "${VERSION_FILE}" From ac370146286b39a8d09ffa40a93a66c5942cae94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 18 Feb 2026 09:22:11 +0100 Subject: [PATCH 258/259] Truncate version file instead of removing and creating freshly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/updatecheck.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/advanced/Scripts/updatecheck.sh b/advanced/Scripts/updatecheck.sh index a54e5c9e..23abf7a6 100755 --- a/advanced/Scripts/updatecheck.sh +++ b/advanced/Scripts/updatecheck.sh @@ -52,11 +52,8 @@ rm -f "/etc/pihole/localversions" VERSION_FILE="/etc/pihole/versions" -# Remove the version file if it exists -rm -f "${VERSION_FILE}" - -# Create new versions file -touch "${VERSION_FILE}" +# Truncates the file to zero length if it exists to clear it up, otherwise creates an empty file. +truncate -s 0 "${VERSION_FILE}" chmod 644 "${VERSION_FILE}" # if /pihole.docker.tag file exists, we will use it's value later in this script From 4125bcccdcf3de01a59157ff5a8aef59d4765161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 18 Feb 2026 09:25:10 +0100 Subject: [PATCH 259/259] Files should be created before calling addOrEditKeyValPair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- advanced/Scripts/utils.sh | 3 --- test/test_any_utils.py | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index d000a6db..51f5db36 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -30,9 +30,6 @@ addOrEditKeyValPair() { local key="${2}" local value="${3}" - # touch file to prevent grep error if file does not exist yet - touch "${file}" - if grep -q "^${key}=" "${file}"; then # Key already exists in file, modify the value sed -i "/^${key}=/c\\${key}=${value}" "${file}" diff --git a/test/test_any_utils.py b/test/test_any_utils.py index 43e637f3..e4646572 100644 --- a/test/test_any_utils.py +++ b/test/test_any_utils.py @@ -2,6 +2,7 @@ def test_key_val_replacement_works(host): """Confirms addOrEditKeyValPair either adds or replaces a key value pair in a given file""" host.run(""" source /opt/pihole/utils.sh + touch ./testoutput addOrEditKeyValPair "./testoutput" "KEY_ONE" "value1" addOrEditKeyValPair "./testoutput" "KEY_TWO" "value2" addOrEditKeyValPair "./testoutput" "KEY_ONE" "value3"