From bef8227cbdd8a370046b08a29d75abe43361629e Mon Sep 17 00:00:00 2001 From: DL6ER Date: Mon, 3 Mar 2025 20:16:07 +0100 Subject: [PATCH 001/157] 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 6fc5bf83f49a637316e4c69a5d0947443426efb5 Mon Sep 17 00:00:00 2001 From: Michael Woolweaver Date: Wed, 9 Apr 2025 12:25:24 -0500 Subject: [PATCH 002/157] 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 003/157] 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 004/157] 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 005/157] 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 006/157] 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 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 007/157] 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 9f3e71b0b6db86330014d8077f42c4ae95a2b30f Mon Sep 17 00:00:00 2001 From: Piotr Tyrakowski Date: Fri, 9 May 2025 17:03:57 +0200 Subject: [PATCH 008/157] 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 13848f2da1b6bde5603d182767bcbfc0345d17d1 Mon Sep 17 00:00:00 2001 From: Piotr Tyrakowski Date: Mon, 12 May 2025 21:13:01 +0200 Subject: [PATCH 009/157] 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 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 010/157] 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 011/157] =?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 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 012/157] 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 013/157] 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 014/157] 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 015/157] 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 016/157] 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 017/157] 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 018/157] 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 019/157] 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 020/157] 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 021/157] 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 022/157] 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 023/157] 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 024/157] 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 025/157] 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 026/157] 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 027/157] 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 028/157] 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 029/157] 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 030/157] 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 031/157] 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 032/157] 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 033/157] 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 034/157] 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 035/157] 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 036/157] 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 037/157] 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 038/157] 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 039/157] 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 040/157] 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 041/157] 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 042/157] 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 043/157] 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 044/157] 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 045/157] 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 046/157] 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 047/157] 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 048/157] 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 049/157] 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 050/157] 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 051/157] 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 052/157] 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 053/157] 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 054/157] 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 055/157] 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 056/157] 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 057/157] 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 058/157] 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 059/157] 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 060/157] 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 061/157] 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 062/157] 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 063/157] 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 064/157] 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 065/157] 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 066/157] 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 067/157] 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 068/157] 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 069/157] 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 070/157] 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 071/157] 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 072/157] 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 073/157] 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 074/157] 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 075/157] 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 076/157] 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 077/157] 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 078/157] 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 079/157] 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 080/157] 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 081/157] 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 082/157] 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 083/157] 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 084/157] 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 085/157] 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 086/157] 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 087/157] 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 088/157] 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 089/157] 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 090/157] 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 091/157] 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 092/157] 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 093/157] 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 094/157] 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 095/157] 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 096/157] 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 097/157] 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 098/157] 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 099/157] 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 100/157] 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 101/157] 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 102/157] 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 103/157] 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 104/157] 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 105/157] 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 106/157] 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 107/157] 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 108/157] 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 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 109/157] 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 110/157] 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 111/157] 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 112/157] 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 113/157] 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 114/157] 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 115/157] 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 116/157] 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 117/157] 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 118/157] 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 119/157] 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 120/157] 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 121/157] 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 122/157] 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 7452c950802e9da78fa48cb9bb180a5f646a3efa Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 8 Nov 2025 15:35:10 +1000 Subject: [PATCH 123/157] 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 124/157] 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 125/157] 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 126/157] 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 127/157] 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 128/157] 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 129/157] 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 130/157] 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 131/157] 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 132/157] 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 133/157] 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 134/157] 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 135/157] 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 136/157] 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 137/157] 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 138/157] 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 139/157] 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 140/157] 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 141/157] 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 142/157] 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 143/157] 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 144/157] 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 145/157] 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 146/157] 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 147/157] 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 148/157] 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 149/157] 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 150/157] 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 151/157] 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 152/157] 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 153/157] 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 154/157] 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 155/157] 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 156/157] 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 157/157] 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"