diff --git a/pkgs/by-name/pi/pihole/0001-Remove-sudo.patch b/pkgs/by-name/pi/pihole/0001-Remove-sudo.patch new file mode 100644 index 000000000000..f037d2953bea --- /dev/null +++ b/pkgs/by-name/pi/pihole/0001-Remove-sudo.patch @@ -0,0 +1,32 @@ +From a2b3aa45d6e073272608506b1d27e4f43f2b0032 Mon Sep 17 00:00:00 2001 +From: williamvds +Date: Sun, 6 Apr 2025 23:00:41 +0100 +Subject: [PATCH 1/3] Remove sudo + +Rely on polkit and sensible permissions +--- + pihole | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/pihole b/pihole +index 1d5093c..6afc48a 100755 +--- a/pihole ++++ b/pihole +@@ -570,14 +570,6 @@ if [[ -z ${USER} ]]; then + USER=$(whoami) + fi + +-# Check if the current user is neither root nor pihole and if the command +-# requires root. If so, exit with an error message. +-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 +-fi +- + # Handle redirecting to specific functions based on arguments + case "${1}" in + "allow" | "allowlist" ) listFunc "$@";; +-- +2.48.1 + diff --git a/pkgs/by-name/pi/pihole/0002-Remove-unsupported-commands.patch b/pkgs/by-name/pi/pihole/0002-Remove-unsupported-commands.patch new file mode 100644 index 000000000000..541d9b487764 --- /dev/null +++ b/pkgs/by-name/pi/pihole/0002-Remove-unsupported-commands.patch @@ -0,0 +1,67 @@ +From ab0650484cdd89afb5b60a0a046509ec5ae14375 Mon Sep 17 00:00:00 2001 +From: williamvds +Date: Sun, 6 Apr 2025 23:01:30 +0100 +Subject: [PATCH 2/3] Remove unsupported commands + +Remove some unsupported maintenance commands, particularly the ones which +reinstall, update, and uninstall pihole. This is managed by NixOS, after all. +--- + pihole | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/pihole b/pihole +index 6afc48a..cce7c97 100755 +--- a/pihole ++++ b/pihole +@@ -92,6 +92,7 @@ debugFunc() { + } + + flushFunc() { ++ unsupportedFunc + "${PI_HOLE_SCRIPT_DIR}"/piholeLogFlush.sh "$@" + exit 0 + } +@@ -102,6 +103,7 @@ arpFunc() { + } + + updatePiholeFunc() { ++ unsupportedFunc + if [ -n "${DOCKER_VERSION}" ]; then + unsupportedFunc + else +@@ -137,6 +139,7 @@ chronometerFunc() { + + + uninstallFunc() { ++ unsupportedFunc + if [ -n "${DOCKER_VERSION}" ]; then + unsupportedFunc + else +@@ -405,6 +408,7 @@ tailFunc() { + } + + piholeCheckoutFunc() { ++ unsupportedFunc + if [ -n "${DOCKER_VERSION}" ]; then + echo -e "${CROSS} Function not supported in Docker images" + echo "Please build a custom image following the steps at" +@@ -460,13 +464,14 @@ tricorderFunc() { + } + + updateCheckFunc() { ++ unsupportedFunc + "${PI_HOLE_SCRIPT_DIR}"/updatecheck.sh "$@" + exit 0 + } + + unsupportedFunc(){ +- echo "Function not supported in Docker images" +- exit 0 ++ echo "Function not supported in NixOS" ++ exit 1 + } + + helpFunc() { +-- +2.48.1 + diff --git a/pkgs/by-name/pi/pihole/0003-Fix-redefinition-of-readonly-variable-utilsfile.patch b/pkgs/by-name/pi/pihole/0003-Fix-redefinition-of-readonly-variable-utilsfile.patch new file mode 100644 index 000000000000..62c67c026ded --- /dev/null +++ b/pkgs/by-name/pi/pihole/0003-Fix-redefinition-of-readonly-variable-utilsfile.patch @@ -0,0 +1,52 @@ +From cca2f6437e3ba09019b8fcb1986b4558d7c6db4e Mon Sep 17 00:00:00 2001 +From: williamvds +Date: Sat, 31 May 2025 13:43:42 +0100 +Subject: [PATCH 3/3] Fix redefinition of readonly variable utilsfile + +--- + advanced/Scripts/api.sh | 2 +- + pihole | 10 +++------- + 2 files changed, 4 insertions(+), 8 deletions(-) + +diff --git a/advanced/Scripts/api.sh b/advanced/Scripts/api.sh +index 613a8d8..8720043 100755 +--- a/advanced/Scripts/api.sh ++++ b/advanced/Scripts/api.sh +@@ -19,7 +19,7 @@ + + TestAPIAvailability() { + +- local chaos_api_list authResponse authStatus authData apiAvailable DNSport ++ local chaos_api_list authResponse authStatus authData apiAvailable DNSport utilsfile + + # as we are running locally, we can get the port value from FTL directly + readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +diff --git a/pihole b/pihole +index cce7c97..d63d064 100755 +--- a/pihole ++++ b/pihole +@@ -16,18 +16,14 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" + # error due to modifying a readonly variable. + PI_HOLE_BIN_DIR="/usr/local/bin" + +-readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" + # shellcheck source=./advanced/Scripts/COL_TABLE +-source "${colfile}" ++source "${PI_HOLE_SCRIPT_DIR}/COL_TABLE" + +-readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" + # shellcheck source=./advanced/Scripts/utils.sh +-source "${utilsfile}" ++source "${PI_HOLE_SCRIPT_DIR}/utils.sh" + +-# Source api functions +-readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" + # shellcheck source=./advanced/Scripts/api.sh +-source "${apifile}" ++source "${PI_HOLE_SCRIPT_DIR}/api.sh" + + versionsfile="/etc/pihole/versions" + if [ -f "${versionsfile}" ]; then +-- +2.48.1 + diff --git a/pkgs/by-name/pi/pihole/package.nix b/pkgs/by-name/pi/pihole/package.nix new file mode 100644 index 000000000000..d1c6f575b053 --- /dev/null +++ b/pkgs/by-name/pi/pihole/package.nix @@ -0,0 +1,257 @@ +{ + lib, + fetchFromGitHub, + makeBinaryWrapper, + installShellFiles, + bash, + coreutils, + curl, + dig, + gawk, + getent, + glibc, + gnugrep, + gnused, + iproute2, + jq, + killall, + libidn2, + locale, + ncurses, + netcat, + nettools, + pihole-ftl, + procps, + resholve, + sqlite, + systemd, + util-linux, + stateDir ? "/etc/pihole", + ... +}: + +(resholve.mkDerivation rec { + pname = "pihole"; + version = "6.1"; + + src = fetchFromGitHub { + owner = "pi-hole"; + repo = "pi-hole"; + tag = "v${version}"; + hash = "sha256-aEnv8Lhb5vf0yDyuriVTaUY1wcdVmTdqoK+KDHvT/Lw="; + }; + + patches = [ + # Remove use of sudo in the original script, prefer to use a wrapper + ./0001-Remove-sudo.patch + # Disable unsupported subcommands, particularly those for imperatively installing/upgrading Pi-hole + ./0002-Remove-unsupported-commands.patch + # Fix a readonly variable error caused by defining a shadowing local variable + ./0003-Fix-redefinition-of-readonly-variable-utilsfile.patch + ]; + + nativeBuildInputs = [ + makeBinaryWrapper + installShellFiles + ]; + + installPhase = '' + runHook preInstall + + readonly scriptsDir=$out/usr/share/pihole + + install -Dm 555 -t $out/bin pihole + install -Dm 555 -t $scriptsDir/advanced/Scripts gravity.sh + + # The installation script is sourced by advanced/Scripts/piholeARPTable.sh etc + cp --parents -r -t $scriptsDir/ 'automated install/' advanced/{Scripts,Templates}/ + + installShellCompletion --bash --name pihole.bash \ + advanced/bash-completion/pihole + + runHook postInstall + ''; + + solutions.default = + let + out = builtins.placeholder "out"; + scriptsDir = "${out}/usr/share/pihole/advanced/Scripts"; + in + { + scripts = + let + relativeScripts = "usr/share/pihole/advanced/Scripts"; + in + [ + "bin/pihole" + "${relativeScripts}/api.sh" + "${relativeScripts}/database_migration/gravity-db.sh" + "${relativeScripts}/gravity.sh" + "${relativeScripts}/list.sh" + "${relativeScripts}/piholeARPTable.sh" + "${relativeScripts}/piholeCheckout.sh" + "${relativeScripts}/piholeDebug.sh" + "${relativeScripts}/piholeLogFlush.sh" + "${relativeScripts}/query.sh" + "${relativeScripts}/update.sh" + "${relativeScripts}/updatecheck.sh" + "${relativeScripts}/utils.sh" + "${relativeScripts}/version.sh" + ]; + interpreter = lib.getExe bash; + inputs = [ + # TODO: see if these inputs can help resholving + "bin" + "usr/share/pihole/advanced/Scripts" + + bash + coreutils + curl + dig + gawk + getent + gnugrep + gnused + iproute2 + jq + killall + libidn2 + locale + ncurses + netcat + nettools + pihole-ftl + procps + sqlite + systemd + util-linux + ]; + fake = { + source = [ + "/etc/os-release" + "/etc/pihole/versions" + "/etc/pihole/setupVars.conf" + ]; + external = [ + # Used by chronometer.sh to get GPU information on Raspberry Pis + "sudo" + "vcgencmd" + # used by the checkout and update scripts, which are patched out + "git" + "getenforce" + "firewall-cmd" + # Conditionally used in Docker builds + "service" + "lighttpd" + # Used in piholeLogFlush.sh + "/usr/sbin/logrotate" + # Used by teleporter in webpage.sh + "php" + ]; + }; + fix = { + "$PI_HOLE_BIN_DIR" = [ "${out}/bin" ]; + "$PI_HOLE_FILES_DIR" = [ "${out}/usr/share/pihole" ]; + "$PI_HOLE_INSTALL_DIR" = [ scriptsDir ]; + "$PI_HOLE_LOCAL_REPO" = [ "${out}/usr/share/pihole" ]; + "$PI_HOLE_SCRIPT_DIR" = [ scriptsDir ]; + "$colfile" = [ "${scriptsDir}/COL_TABLE" ]; + "$coltable" = [ "${scriptsDir}/COL_TABLE" ]; + "$PIHOLE_COLTABLE_FILE" = [ "${scriptsDir}/COL_TABLE" ]; + "$utilsfile" = [ "${scriptsDir}/utils.sh" ]; + "$apifile" = [ "${scriptsDir}/api.sh" ]; + "$piholeGitDir" = [ "${out}/usr/share/pihole" ]; + "$PIHOLE_COMMAND" = [ "pihole" ]; + }; + keep = { + source = [ + "$pihole_FTL" # Global config file + "$setupVars" # Global config file + "$PIHOLE_SETUP_VARS_FILE" + "$versionsfile" # configuration file, doesn't exist on NixOS + "${out}/usr/share/pihole/automated install/basic-install.sh" + "${scriptsDir}/COL_TABLE" + "${scriptsDir}/database_migration/gravity-db.sh" + "${scriptsDir}/gravity.sh" + "${scriptsDir}/piholeCheckout.sh" + "${scriptsDir}/utils.sh" + "${scriptsDir}/api.sh" + "/etc/os-release" + "/etc/pihole/versions" + "/etc/pihole/setupVars.conf" + "$cachedVersions" + ]; + + "$PIHOLE_SETUP_VARS_FILE" = true; + "$PKG_INSTALL" = true; # System package manager, patched out + "$PKG_MANAGER" = true; # System package manager, patched out + "$cmd" = true; # ping or ping6 + "$program_name" = true; # alias for $1 + "$svc" = true; # dynamic restart command + "${out}/bin/pihole" = true; + "${scriptsDir}/api.sh" = true; + "${scriptsDir}/gravity.sh" = true; + "${scriptsDir}/list.sh" = true; + "${scriptsDir}/piholeARPTable.sh" = true; + "${scriptsDir}/piholeDebug.sh" = true; + "${scriptsDir}/piholeLogFlush.sh" = true; + "${scriptsDir}/query.sh" = true; + "${scriptsDir}/uninstall.sh" = true; + "${scriptsDir}/update.sh" = true; + "${scriptsDir}/updatecheck.sh" = true; + "${scriptsDir}/version.sh" = true; + + # boolean variables + "$addmode" = true; + "$noReloadRequested" = true; + "$oldAvail" = true; + "$verbose" = true; + "$web" = true; + "$wildcard" = true; + + # Note that this path needs to be quoted due to the whitespace. + # TODO: raise upstream resholve issue. pihole scripts specify this path + # both quoted and escaped. Resholve apparently requires matching the + # literal path, so we need to provide a version with and without the + # backslash. + "'${out}/usr/share/pihole/automated\\ install/basic-install.sh'" = true; + "'${out}/usr/share/pihole/automated install/basic-install.sh'" = true; + + "/etc/.pihole" = true; # Patched with an override + "/etc/os-release" = true; + "/etc/pihole/versions" = true; + "/etc/pihole/setupVars.conf" = true; + }; + execer = [ + "cannot:${pihole-ftl}/bin/pihole-FTL" + "cannot:${iproute2}/bin/ip" + "cannot:${systemd}/bin/systemctl" + "cannot:${glibc.bin}/bin/ldd" + "cannot:${out}/bin/pihole" + ]; + }; + + meta = { + description = "A black hole for Internet advertisements"; + license = lib.licenses.eupl12; + maintainers = with lib.maintainers; [ williamvds ]; + platforms = lib.platforms.linux; + mainProgram = "pihole"; + }; + + passthru = { + stateDir = stateDir; + }; +}).overrideAttrs + (old: { + # Resholve can't fix the hardcoded absolute paths, so substitute them before resholving + preFixup = + '' + scriptsDir=$out/usr/share/pihole + + substituteInPlace $out/bin/pihole $scriptsDir/advanced/Scripts/*.sh \ + --replace-quiet /etc/.pihole $scriptsDir \ + --replace-quiet /opt/pihole $scriptsDir/advanced/Scripts + '' + + old.preFixup; + })