From ea8272d7d4a59bb43373ff75e7a640e54b2cd134 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Sat, 12 Jul 2025 14:25:17 +1000 Subject: [PATCH 01/49] 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 02/49] 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 0187087da0624e5e1dbbe8805b7802a4304a9ea0 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Mon, 14 Jul 2025 05:44:46 +1000 Subject: [PATCH 03/49] 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 04/49] 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 05/49] 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:20:39 -0300 Subject: [PATCH 06/49] 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 07/49] 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 da85a7a2a76726f784eded726eb483ff43d27da0 Mon Sep 17 00:00:00 2001 From: Jack'lul Date: Fri, 18 Jul 2025 10:34:02 +0200 Subject: [PATCH 08/49] 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 22e6ff2cdfca407d841eb8959c37ca3e3ff48f61 Mon Sep 17 00:00:00 2001 From: RD WebDesign Date: Mon, 21 Jul 2025 16:15:25 -0300 Subject: [PATCH 09/49] 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 10/49] 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 11/49] 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 12/49] 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 13/49] 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 14/49] 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 15/49] 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 16/49] 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 17/49] 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 18/49] 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 19/49] 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 20/49] 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 21/49] 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 22/49] 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 23/49] 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 24/49] 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 25/49] 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 26/49] 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 27/49] 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 28/49] 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 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 29/49] 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 30/49] 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 31/49] 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 32/49] 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 33/49] 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 34/49] 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 35/49] 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 36/49] 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 37/49] 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 38/49] 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 39/49] 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 40/49] 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 41/49] 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 42/49] 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 43/49] 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 44/49] 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 45/49] 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 46/49] 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 47/49] 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 48/49] 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 49/49] 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}"