Compare commits

...

301 Commits

Author SHA1 Message Date
Adam Warner
4fed49c5e5 Pi-hole Core v6.1 (#6221) 2025-05-30 22:56:55 +01:00
yubiuser
cad0d0bf1f Allow to get API URL from local.api.ftl even if DNS port has changed (#6252) 2025-05-30 21:57:23 +02:00
Dan Schaper
42aba32ceb Use PID1 to determine which command to use when toggeling services (#6245) 2025-05-30 12:24:09 -07:00
Christian König
6f429d82b4 Allow to get API URL from local.api.ftl even if DNS port has changed
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-30 21:05:08 +02:00
Christian König
fd40fa6f39 Test need adjustment to long arument syntax
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-30 20:52:37 +02:00
yubiuser
d177c4c776 Add useful comment
Co-authored-by: Dan Schaper <dan.schaper@pi-hole.net>
Signed-off-by: yubiuser <github@yubiuser.dev>
2025-05-30 19:03:12 +02:00
Christian König
888556278e Add gwak to Fedorea 42 test image as other tests also rely on awk
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-28 20:47:55 +02:00
Christian König
69473a7b54 Add awk to meta package dependencie (is missing on Fedora 42 by default) and order dependencies alphabetically
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-28 19:54:44 +02:00
Christian König
f3166d7a78 Adjust test to mock PID1 to be systemd
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-27 23:52:46 +02:00
Christian König
137338e6a8 Use service wrappers in all scripts
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-27 21:23:56 +02:00
Christian König
b707890f10 Use PID1 to determine which command to use when toggeling services
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-27 20:09:59 +02:00
Dominik
822e677c5c Use a more general method to determine whether systemd is the init system (#6043) 2025-05-27 19:33:57 +02:00
yubiuser
5aadc5f475 Function gravity_CheckDNSResolutionAvailable() should return 0 if DNS resolution is available (#6240) 2025-05-21 07:44:04 +02:00
RD WebDesign
6ba6b0f015 Return 1 only if resolution fails
Function gravity_CheckDNSResolutionAvailable() should return 0 if DNS resolution is available

Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-05-20 19:46:28 -03:00
yubiuser
5f60860a17 Bump tox from 4.25.0 to 4.26.0 in /test (#6237) 2025-05-17 13:13:30 +02:00
dependabot[bot]
86d9ac5f8f Bump tox from 4.25.0 to 4.26.0 in /test
Bumps [tox](https://github.com/tox-dev/tox) from 4.25.0 to 4.26.0.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.25.0...4.26.0)

---
updated-dependencies:
- dependency-name: tox
  dependency-version: 4.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-17 10:02:13 +00:00
Dan Schaper
a04ed13d0a Allow simple pihole api output, containing only the JSON payload (#6096) 2025-05-16 13:57:04 -07:00
Dan Schaper
04e52daaf3 Update get_available_interfaces() to correctly filter loopback device (lo) (#6236) 2025-05-15 08:43:12 -07:00
Piotr Tyrakowski
88934ec818 Update basic-install.sh
Signed-off-by: Piotr Tyrakowski <verscup@gmail.com>
2025-05-14 21:47:34 +02:00
Dan Schaper
9aa005ad4c Revert "fix(get_available_interfaces): only drop the loopback device (‘lo’), don’t filter every “lo” substring" (#6235) 2025-05-14 09:53:07 -07:00
Dan Schaper
f6d477f228 Revert "fix(get_available_interfaces): only drop the loopback device (‘lo’), don’t filter every “lo” substring" 2025-05-14 09:51:47 -07:00
Dan Schaper
3c1d8690fa fix(get_available_interfaces): only drop the loopback device (‘lo’), don’t filter every “lo” substring (#6224) 2025-05-14 09:05:21 -07:00
Dan Schaper
3314887e65 Change FTLcheckUpdate to use api.github.com and jq to retrieve tag_name (#6229) 2025-05-14 08:32:42 -07:00
Dan Schaper
c1a5b902fb Use shell parameter expansion to split http_code and payload for api.sh (#6230) 2025-05-14 08:31:13 -07:00
RD WebDesign
dee44cb3da Define "silent" as default option and include "verbose" to the man page
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-05-13 14:22:41 -03:00
Dan Schaper
de31858950 Use shell parameter expansion to split http_code and payload
Codespell

editorconfig

Signed-off-by: Dan Schaper <dan.schaper@pi-hole.net>
2025-05-12 12:26:56 -07:00
Piotr Tyrakowski
13848f2da1 Update automated install/basic-install.sh
Co-authored-by: Dan Schaper <dan.schaper@pi-hole.net>
Signed-off-by: Piotr Tyrakowski <verscup@gmail.com>
2025-05-12 21:13:01 +02:00
RD WebDesign
e01d49b3ee Change FTLcheckUpdate to use api.github.com and jq to retrieve tag_name
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-05-12 15:53:12 -03:00
RD WebDesign
190798e572 Allow simple pihole api output, containing only the JSON payload
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-05-12 14:23:15 -03:00
Dan Schaper
1bdbc26a07 Give FTL 60 seconds for graceful shutdown (#6187) 2025-05-12 10:13:29 -07:00
Christian König
842afc2475 Give FTL 60 seconds for graceful shutdown
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-12 19:02:29 +02:00
Dan Schaper
398405c303 All gravity related files and dirs should be owned by pihole:pihole (#6186) 2025-05-12 08:48:27 -07:00
yubiuser
189da82614 && chown
Co-authored-by: Dan Schaper <dan.schaper@pi-hole.net>
Signed-off-by: yubiuser <github@yubiuser.dev>
2025-05-12 08:54:58 +02:00
Dan Schaper
99d00e0ed0 Do not try to upgrade gravity if it does not exist (#6218) 2025-05-11 08:47:46 -07:00
Dan Schaper
3c6c3d3a15 Fix API logic in api.sh (#6193) 2025-05-11 08:43:12 -07:00
Dan Schaper
3c0ff57660 Allow alternative cron daemons on Debian (#6180) 2025-05-11 08:12:29 -07:00
Piotr Tyrakowski
9f3e71b0b6 Update basic-install.sh
I have updated line 708
to use grep -v "loo" 
instead of "lo" 
the reason is with "lo" it cannot find "wlo1" interface

Signed-off-by: Piotr Tyrakowski <verscup@gmail.com>
2025-05-09 17:03:57 +02:00
Christian König
d45003a8ca Do not try to upgrade gravity if it does not exist
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-05 17:27:53 +02:00
yubiuser
7aaaa49cf0 Set dns.interface during installation (#6216) 2025-05-05 08:39:23 +02:00
Christian König
fc103af050 Revert response code logic
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-04 21:45:44 +02:00
yubiuser
46fbd931b5 Use CODEOWNERS instead of deprecated dependbot/reviewers (#6213) 2025-05-04 20:56:09 +02:00
Christian König
96437dc913 Set dns.interface during installation
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-04 19:39:43 +02:00
yubiuser
cae558d5d4 Extend .gitignore (#6215) 2025-05-04 14:32:40 +02:00
darkexplosiveqwx
65fd0b099d Extend .gitignore
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
2025-05-04 14:22:02 +02:00
yubiuser
744ac6ad88 Add Fedora 42 to tests (#6177) 2025-05-04 13:28:03 +02:00
darkexplosiveqwx
b82487ee6a Add Fedora 42 to tests
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
2025-05-04 12:02:15 +02:00
Dan Schaper
0a72e517b6 Remove reference to telnet and chronometer in README (#6188) 2025-05-03 13:38:29 -07:00
Dan Schaper
09368a77b4 Remove unused $target from gravity (#6192) 2025-05-03 13:37:45 -07:00
Dan Schaper
0e6439c6c0 Remove check for supported OS (#6206) 2025-05-03 13:17:56 -07:00
Christian König
0c533ec71b Use CODEOWNERS instead of deprecated dependbot/reviewers
Signed-off-by: Christian König <github@yubiuser.dev>
2025-05-03 20:06:24 +02:00
Christian König
5355e9e084 Remove os_check from debug script
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-28 21:10:36 +02:00
Christian König
54c8dd3d77 Remove os_check from tests
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-28 21:06:05 +02:00
Christian König
d9f4ee7aaa Remove os_check from update script
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-28 21:04:08 +02:00
Christian König
40da3a40ec Remove os_check from install script
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-28 21:03:08 +02:00
yubiuser
3cbaee7b76 Fix gravity waiting forever for DNS (#6196) 2025-04-26 16:48:24 +02:00
yubiuser
3bd6a41795 Improve wording
Co-authored-by: Adam Warner <me@adamwarner.co.uk>
Signed-off-by: yubiuser <github@yubiuser.dev>
2025-04-26 15:36:22 +02:00
Christian König
4303a5868f Only append dot
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-26 15:03:42 +02:00
Christian König
215003899d (2+1)*40
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-26 15:03:01 +02:00
yubiuser
cf3b7d0d8e Bump actions/setup-python from 5.5.0 to 5.6.0 (#6199) 2025-04-26 12:56:31 +02:00
dependabot[bot]
454f96d0ea Bump actions/setup-python from 5.5.0 to 5.6.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.5.0 to 5.6.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.5.0...v5.6.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 5.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-26 10:25:43 +00:00
Christian König
1bea6db50a Fix API logic in api.sh
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-25 21:16:52 +02:00
Christian König
72a52807d1 Fix gravity waiting forever for DNS
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-25 21:03:09 +02:00
Christian König
d7b6d6aa33 Remove unused $target from gravity
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-22 23:06:01 +02:00
Rob Gill
ce0bdac1bd Remove reference to telnet and chronometer in README
Replace with curl example and commandline example

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-04-23 06:41:16 +10:00
Christian König
4a1bcda6f1 All gravity related files and dirs should be owned by pihole:pihole
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-21 09:30:36 +02:00
yubiuser
60485fdc51 Remove duplicated code checking if adlist domain is blocked locally (#6183) 2025-04-21 09:17:39 +02:00
yubiuser
6fe77ebeed Treat FTL return data as strings - part II (#6184) 2025-04-21 09:16:58 +02:00
Christian König
8733b429dd Treat FTL return data as strings - part II
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-20 22:50:55 +02:00
Christian König
1432568d17 Remove duplicated code checking if adlist domain is blocked locally
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-20 20:14:41 +02:00
Ihor Urazov
cff7f40739 Allow alternative cron daemons on Debian
Add cron-daemon virtual package as an alternative dependency. This way
pihole-meta by default still depends on cron, but allows installation of
systemd-cron, which completely replaces cron daemon and package. With
systemd-cron functionality of crontab files and /etc/cron.* directories
works expected, as systemd-cron generates systemd timers from cron
files.

Signed-off-by: Ihor Urazov <iurazov@healthjoy.com>
2025-04-19 20:33:19 +03:00
yubiuser
248d25b8d0 Install on IPv6-only/DNS64/NAT64 system (#6144) 2025-04-15 17:33:09 +02:00
Dominik
95c1b1a542 Add ON DELETE CASCADE to FOREIGN KEY REFERENCES in gravity.db (#6113) 2025-04-15 06:24:52 +02:00
Rob Gill
9e62625f83 Install on IPv6-only/DNS64/NAT64 system
Alters the test for IPv4 route so the installer doesn't fail instantly on IPv6-only.

Gives user a dialog to proceed with IPv6 only installation

Switches DNS server options to only contain IPv6 addresses.

Signed-off-by: Rob Gill <rrobgill@protonmail.com>
2025-04-15 14:13:43 +10:00
Dan Schaper
faeba69090 revert a change to gravity.sh that attempted to fix an SC2086 warning… (#6162) 2025-04-09 10:07:10 -07:00
Adam Warner
48272f3393 revert a change to gravity.sh that attempted to fix an SC2086 warning from shellcheck.
Fixes #6159

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-09 18:02:40 +01:00
Adam Warner
195e65855d Fix more shellcheck warnings (#6155) 2025-04-08 17:27:07 +01:00
Christian König
0f511ad574 Remove token and use sarif-fmt for nicer CLI output
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-08 17:50:19 +02:00
Adam Warner
323dbbe5d9 Reduce code duplication in piholeLogFlush (#6148) 2025-04-08 12:44:30 +01:00
Christian König
bda81cb2f5 Remove debug SARIF upload
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 21:25:29 +02:00
Christian König
b271dbf606 Set shellcheck level to warning, can be lowered later
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 14:11:39 +02:00
Christian König
5002ce8ba7 Source files relative to the repos root
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 14:10:01 +02:00
Christian König
135b0cce14 Switch to Differential ShellCheck
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 11:54:35 +02:00
Christian König
23fc53c618 Set -x option for shellcheck GHA
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 11:32:14 +02:00
Adam Warner
3732ea7365 Remove shellcheck directives that no longer serve any purpose
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-07 10:24:53 +01:00
Christian König
ca1bab3c1b Fix more shellcheck warnings
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-07 10:52:57 +02:00
yubiuser
36e6c9921e Shellcheck Tweaks (#6147) 2025-04-07 10:08:25 +02:00
Dan Schaper
6c5bc1de39 versions file should readable by others (make pihole -v work for non-root users) (#6002) 2025-04-06 12:58:16 -07:00
Christian König
9f5e18b1cd Make it 644
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-06 21:13:47 +02:00
Christian König
d28e795266 Permissions on versions file should be 640
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-06 21:12:58 +02:00
Christian König
e579397f51 Allow all users to read the version file
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-06 20:52:57 +02:00
Adam Warner
2088601148 Add .shellcheckrc to configure shellcheck ignore SC1090-1 globally
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 18:46:47 +01:00
Adam Warner
48c59cb6cf In ./automated install/uninstall.sh line 14:
readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
         ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./advanced/Scripts/update.sh line 39:
readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
         ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./advanced/Scripts/updatecheck.sh line 45:
readonly ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
         ^-----------------^ SC2155 (warning): Declare and assign separately to avoid masking return values.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:20:51 +01:00
Adam Warner
f01e8c70d9 Weirldly, GHA missed these minor warnings however have disabled them as they are due to variables either being used in or declared in basic-install,.sh
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
3a9b9c027e In ./pihole line 20:
source "${colfile}"
       ^----------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

In ./pihole line 23:
source "${utilsfile}"
       ^------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

In ./pihole line 27:
source "${apifile}"
       ^----------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

In ./pihole line 34:
    source "${versionsfile}"
           ^---------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

In ./pihole line 251:
  local timer="$(echo "${data}"| jq --raw-output '.timer' )"
        ^---^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./pihole line 255:
  local str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}"
        ^-^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./pihole line 378:
  local logging_enabled=$(getFTLConfigValue dns.queryLogging)
        ^-------------^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./pihole line 385:
  readonly LOGFILE=$(getFTLConfigValue files.log.dnsmasq)
           ^-----^ SC2155 (warning): Declare and assign separately to avoid masking return values.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
f5dc337d1b In ./advanced/Scripts/piholeLogFlush.sh line 12:
source ${colfile}
       ^--------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

In ./advanced/Scripts/piholeLogFlush.sh line 16:
source "${utilsfile}"
       ^------------^ SC1090 (warning): ShellCheck can't follow non-constant source. Use a directive to specify location.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
63623c4353 In ./advanced/Scripts/piholeCheckout.sh line 112:
corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}"))
                      ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting).

In ./advanced/Scripts/piholeCheckout.sh line 139:
        webbranches=($(get_available_branches "${webInterfaceDir}"))
                     ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting).

In ./advanced/Scripts/piholeCheckout.sh line 170:
        ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) )
                      ^-- SC2207 (warning): Prefer mapfile or read -a to split command output (or quote to avoid splitting).

In ./advanced/Scripts/piholeCheckout.sh line 218:
            elif [ $? -eq 2 ]; then
                   ^-- SC2319 (warning): This $? refers to a condition, not a command. Assign to a variable to avoid it being overwritten.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
59d2177271 In ./advanced/Scripts/database_migration/gravity-db.sh line 18:
piholeDir="${2}"
    ^-------^ SC2034 (warning): piholeDir appears unused. Verify use (or export if used externally).

Turns out it is _actually_ unused, the full path of the gravity database is passed to the function, so we'll tidy this up rather than supressing.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
a624d3be8d In ./advanced/Scripts/utils.sh line 91:
if [[ $? -eq 5 ]]; then
     ^------------^ SC3010 (warning): In POSIX sh, [[ ]] is undefined.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
39f5115135 In ./automated install/basic-install.sh line 1753:
local status=$(curl --head --silent "https://ftl.pi-hole.net/${1}" | head -n 1)
          ^----^ SC2155 (warning): Declare and assign separately to avoid masking return values.

In ./automated install/basic-install.sh line 2076:
            elif [ $? -eq 2 ]; then
                   ^-- SC2319 (warning): This $? refers to a condition, not a command. Assign to a variable to avoid it being overwritten.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
e018a37a8c First things first - bump severity of shellcheck action from error to warning
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 14:11:40 +01:00
Adam Warner
6e06a93c31 functionise log rotation and flushing code to avoid dupliation
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-06 13:57:07 +01:00
Adam Warner
7e5d9db6b7 Remove no-longer-needed pihole sudoers file (#6143) 2025-04-06 13:52:37 +01:00
Dominik
5afab5e96c Move list parsing entirely into FTL (#6105) 2025-04-05 20:15:16 +02:00
yubiuser
ab8b8da9c3 Bump pytest-testinfra from 10.1.1 to 10.2.2 in /test (#6151) 2025-04-05 12:11:16 +02:00
dependabot[bot]
07864032de Bump pytest-testinfra from 10.1.1 to 10.2.2 in /test
Bumps [pytest-testinfra](https://github.com/pytest-dev/pytest-testinfra) from 10.1.1 to 10.2.2.
- [Release notes](https://github.com/pytest-dev/pytest-testinfra/releases)
- [Changelog](https://github.com/pytest-dev/pytest-testinfra/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-testinfra/compare/10.1.1...10.2.2)

---
updated-dependencies:
- dependency-name: pytest-testinfra
  dependency-version: 10.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-05 10:05:08 +00:00
Adam Warner
bdcb6fc88c Update update.sh, updatecheck.sh and uninstall.sh to honour pihole.to… (#5981) 2025-04-05 01:18:49 +01:00
Adam Warner
f403468450 Add webserver log to piholeLogFlush.sh (#6049) 2025-04-05 00:33:18 +01:00
Adam Warner
097ac8336e Add recommended fields to the deb package (#6054) 2025-04-05 00:31:26 +01:00
Christian König
fe2b22c570 Add recommended fields to the deb package
Signed-off-by: Christian König <github@yubiuser.dev>
2025-04-05 00:29:13 +01:00
Adam Warner
2477d6b184 Revert #6137 (#6146) 2025-04-04 23:28:51 +01:00
Adam Warner
f98b9520e4 v5 sudoers file that allowed www-data to run pihole command is no longer needed. "Fixes" #6066
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-04-04 23:19:14 +01:00
yubiuser
65b42c1c8f Ensure gravity_Cleanup() checks the correct directory (#6131) 2025-04-04 22:50:19 +02:00
Michael Woolweaver
e548ed043f ensure gravity_Cleanup() checks the correct directory for list data
also glob with * to ensure .etag & .sha1 are removed as well
should fix #6075

Co-authored-by: yubiuser <github@yubiuser.dev>
Signed-off-by: Michael Woolweaver <michael@woolweaver.bid>
2025-04-04 15:15:51 -05:00
Adam Warner
4108c817dc Revert "source with source not dot (#6137)"
This reverts commit 8fd2ebd3d7, reversing
changes made to 557bc6f179.
2025-04-04 19:12:57 +01:00
Dan Schaper
8fd2ebd3d7 source with source not dot (#6137) 2025-04-02 12:36:48 -07:00
Michael Woolweaver
4efe4dfd4b source with source not dot
Signed-off-by: Michael Woolweaver <michael@woolweaver.bid>
2025-04-02 14:21:45 -05:00
Adam Warner
557bc6f179 Add CentOS 10 to test suite (#6126) 2025-04-02 18:24:36 +01:00
Adam Warner
8fce8f6149 build gravityDBfile_default like the other variables (#6133) 2025-04-02 17:12:21 +01:00
Michael Woolweaver
3cb6ea503a build gravityDBfile_default like the other variables
seems this one was forgotten

Signed-off-by: Michael Woolweaver <michael@woolweaver.bid>
2025-04-01 23:57:56 -05:00
Christian König
7886cfc80b Add CentOS 10 to test suite
Signed-off-by: Christian König <github@yubiuser.dev>
2025-03-31 12:13:34 +02:00
Adam Warner
8797a0df05 Sync master back into development (#6122) 2025-03-30 18:31:02 +01:00
Adam Warner
0f7803b775 Pi-hole Core v6.0.6 (#6118) 2025-03-30 17:54:55 +01:00
James George
0f482396ee Update update.sh, updatecheck.sh and uninstall.sh to honour pihole.toml settings for webserver.paths.webroot and webserver.paths.webhome
When uninstalling, remove web interface parent directory empty check and possible removal.

Signed-off-by: James George <james.george@vigilantvoid.com>
2025-03-30 13:11:21 +08:00
yubiuser
73074f1557 Bump tox from 4.24.2 to 4.25.0 in /test (#6116) 2025-03-29 21:46:47 +01:00
yubiuser
bc23303788 Bump actions/setup-python from 5.4.0 to 5.5.0 (#6117) 2025-03-29 21:43:58 +01:00
dependabot[bot]
49fbdc4c00 Bump actions/setup-python from 5.4.0 to 5.5.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.4.0...v5.5.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-29 10:25:36 +00:00
dependabot[bot]
315528d740 Bump tox from 4.24.2 to 4.25.0 in /test
Bumps [tox](https://github.com/tox-dev/tox) from 4.24.2 to 4.25.0.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.24.2...4.25.0)

---
updated-dependencies:
- dependency-name: tox
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-29 10:25:08 +00:00
DL6ER
71ec0a0244 Add ON DELETE CASCADE to FOREIGN KEY REFERENCES in gravity.db
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-03-27 13:10:53 +01:00
Adam Warner
e5cb0efd61 revert #6030 in preparation for docker-pi-hole #1794 (#6086) 2025-03-25 17:06:01 +00:00
DL6ER
dec670a6d6 Move list parsing entirely into FTL
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-03-22 09:18:02 +01:00
Michael Woolweaver
3a592471c6 revert pi-hole/pi-hole/pull/6030
in preparation for pi-hole/docker-pi-hole/pull/1786

Signed-off-by: Michael Woolweaver <michael@woolweaver.bid>
2025-03-14 14:32:29 -05:00
yubiuser
3f5c00919b Remove WEB_CALL from COL_TABLE (#6062) 2025-03-10 06:14:47 +01:00
yubiuser
349544b24a Create webserver.log on FTL startup (#6051) 2025-03-10 06:14:22 +01:00
yubiuser
387ec3a3c2 Bump pytest from 8.3.4 to 8.3.5 in /test (#6068) 2025-03-08 11:50:40 +01:00
dependabot[bot]
6b873b2d7f Bump pytest from 8.3.4 to 8.3.5 in /test
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-08 10:46:01 +00:00
yubiuser
46e5b3b02e Bump tox from 4.24.1 to 4.24.2 in /test (#6067) 2025-03-08 11:44:54 +01:00
dependabot[bot]
27aeed76f0 Bump tox from 4.24.1 to 4.24.2 in /test
Bumps [tox](https://github.com/tox-dev/tox) from 4.24.1 to 4.24.2.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.24.1...4.24.2)

---
updated-dependencies:
- dependency-name: tox
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-08 10:30:22 +00:00
yubiuser
80d63eca93 Add 2FA handling to api.sh (#6065) 2025-03-08 10:46:54 +01:00
yubiuser
72404c983d Add trailing / when changing ownership of /etc/pihole (#6057) 2025-03-07 23:08:04 +01:00
casperklein
9b4502a7a9 Add trailing / to directories
Signed-off-by: casperklein <casperklein@users.noreply.github.com>
2025-03-07 23:00:40 +01:00
Christian König
5de9b6ae69 Add 2FA handling to api.sh
Signed-off-by: Christian König <github@yubiuser.dev>
2025-03-07 13:43:41 +01:00
Christian König
f3dc202e36 Remove WEB_CALL from COL_TABLE
Signed-off-by: Christian König <github@yubiuser.dev>
2025-03-07 10:16:25 +01:00
yubiuser
9050e47049 version.sh: fix typo in comment (#6056) 2025-03-06 20:49:20 +01:00
XhmikosR
45cb722e50 version.sh: fix typo in comment
Signed-off-by: XhmikosR <xhmikosr@gmail.com>
2025-03-06 21:40:17 +02:00
yubiuser
98b17edfd7 README.md: switch to the SVG logo (#6052) 2025-03-06 14:27:58 +01:00
XhmikosR
d094b197e3 README.md: switch to the SVG logo
Signed-off-by: XhmikosR <xhmikosr@gmail.com>
2025-03-06 15:06:34 +02:00
Christian König
e437e3a805 Create webserver.log on FTL startup
Signed-off-by: Christian König <github@yubiuser.dev>
2025-03-06 09:48:06 +01:00
Jack'lul
4df5c0bb96 Add webserver log to piholeLogFlush.sh
Signed-off-by: Jack'lul <8418678+jacklul@users.noreply.github.com>
2025-03-05 22:25:33 +01:00
Adam Warner
411b9fcb6d Sync master back into development (#6046) 2025-03-04 19:46:03 +00:00
Adam Warner
9fe687bd62 Pi-hole Core v6.0.5 (#6042) 2025-03-04 17:21:05 +00:00
DL6ER
bef8227cbd Use a more general method to determine whether systemd is the init system
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-03-03 20:16:07 +01:00
Adam Warner
edf336067a Fix gravity.sh -- Alpine / Docker specific issue (#6030) 2025-03-03 17:44:45 +00:00
Adam Warner
196a84721f Fix find command syntax, remove log dir from search (#6035) 2025-03-03 17:40:12 +00:00
Adam Warner
978694f262 Improve update/fresh install detection (#6034) 2025-03-03 12:23:29 +00:00
Dominik
7eef780fbc Revert "Improve gravity on systems with low memory" (#6039) 2025-03-03 11:01:45 +01:00
Dominik
df814ece91 Revert "Improve gravity on systems with low memory" 2025-03-03 09:00:17 +01:00
Karol Kania
9c7e02f213 Update gravity.sh
remove the left-over commented debug code 

Signed-off-by: Karol Kania <44871508+karolkania@users.noreply.github.com>
2025-03-02 12:05:42 +01:00
Jack'lul
0130f7be74 Fix find command syntax, remove log dir from search
Signed-off-by: Jack'lul <8418678+jacklul@users.noreply.github.com>
2025-03-01 14:43:36 +01:00
Dan Schaper
f207385269 Removing kernel check based on discussion in Pi-Hole PR pi-hole#5957. (#6020) 2025-02-28 20:00:00 -08:00
Adam Warner
ce73691082 Juggle some code around:
- Move random password generation block inside final "fresh install" if block, ensure password is ONLY generated on fresh installs.
 - Add additional check for fresh install around setting of PIHOLE_DNS1/2, QUERY_LOGGING, and PRIVACY_LEVEL
 - Remove dedicated displayFinalMessage function.

Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-02-28 23:06:52 +00:00
Adam Warner
8874757958 Start by renaming useUpdateVars to fresh_install and flipping the logic, the old name is not relevant any more
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-02-28 21:29:33 +00:00
Adam Warner
821c953216 Remove 'reconfigure' option (#5887) 2025-02-28 21:14:18 +00:00
Dominik
53e241f057 Improve gravity on systems with low memory (#5977) 2025-02-28 17:02:56 +01:00
Karol Kania
a9650ae287 Update gravity.sh
fix the `if statement` that doesn't seem to work for neither of alpine's ash / bash - applying some workaround with the `stat` command

Signed-off-by: Karol Kania <44871508+karolkania@users.noreply.github.com>
2025-02-28 12:52:07 +01:00
Christian König
7282aada25 Don't show a warning before the repair is done
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-28 11:51:09 +01:00
Dominik
c5d66c2162 Do not overwrite TLS cert/key mode (#5998) 2025-02-27 19:45:32 +01:00
UltChowsk
869411a514 Fixing whitespaces after removing lines.
Signed-off-by: UltChowsk <ult@chowsk.net>
2025-02-27 06:24:13 -05:00
UltChowsk
d1b5f95aa7 Removing kernel check based on discussion in Pi-Hole PR pi-hole#5957.
Signed-off-by: UltChowsk <ult@chowsk.net>
2025-02-26 20:37:20 -05:00
MichaIng
ad6a48b219 Add comment about TLS-related file permissions
Co-authored-by: Dominik <DL6ER@users.noreply.github.com>
Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-26 20:59:32 +01:00
MichaIng
83a38bb71d Add comment about file permissions
Co-authored-by: Dominik <DL6ER@users.noreply.github.com>
Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-26 12:26:50 +01:00
MichaIng
232d581916 Re-add comment about execute bit on directory
Co-authored-by: Dominik <DL6ER@users.noreply.github.com>
Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-26 12:25:51 +01:00
Dan Schaper
002536ae09 Do not hide error messages when dealing with services (#5983) 2025-02-25 12:30:39 -08:00
yubiuser
8a788ad755 Update README.md - Fix Text+URL for allowlisting/denylisting (#5993) 2025-02-25 20:57:57 +01:00
MichaIng
0b380d671d Follow symlinks with find
Incorporating https://github.com/pi-hole/pi-hole/pull/5997

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-24 17:37:01 +01:00
MichaIng
65bcb24d0e Fix test
Do not check whether the pihole user can read /etc/pihole/logrotate. It needs to be readable by root only, which is always true.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-24 17:29:59 +01:00
MichaIng
e70981d80f Do not overwrite TLS cert/key mode
FTL correctly creates the cert and especially private key with 0600 mode. But the prestart scripts changes it to 0660.

After removing the dedicated webserver from Pi-hole setups, the pihole group has no purpose anymore, and files should not be writable to any other user than pihole itself, and the private TLS key not reasable to anyone else either.

Additionally, this commit consolidates the chmod calls, applying 0755 to all directories and 0640 to all files, but the TLS key and cert.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-24 17:29:58 +01:00
yubiuser
9840b42847 Add missing trailing / when setting permissions of /etc/pihole (#5997) 2025-02-24 17:24:10 +01:00
Christian König
b59ab5852a Add missing trailing / when setting permissions of /etc/pihole
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-24 15:59:11 +01:00
Jeroen Habets
a0541dd7fb Update README.md
Fix Text+URL for allowlisting/denylisting. Keep former terms for when people search for them.

Signed-off-by: Jeroen Habets <jeroenhabets@users.noreply.github.com>
2025-02-24 10:45:17 +01:00
Dominik
48c4efd7b0 Improve dig error handlin in api.sh (#5965) 2025-02-23 20:15:31 +01:00
MichaIng
729a44f82a Do not hide error messages when dealing with services
If service start/stop/restart/enable/disable fails, it help to debug the issue, if STDERR is not hidden, hence the error message can be seen. systemctl furthermore has the `-q` option to suppress non-error output. It works as well for "is-enabled", but until a certain systemd version still throws an error, if the checked service does not exist at all. Once Debian Bullseye support is dropped by Pi-hole, also STDERR form systemctl is-enabled does not need to be suppressed anymore.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-23 15:48:32 +01:00
Dominik
9c995962a5 If there are no files to change, don't print an error (#5953) 2025-02-23 09:04:16 +01:00
DL6ER
5da5d0d4c1 Use temp_store = FILE to avoid memory exhaustion on build the tree for very large databases
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-23 08:50:08 +01:00
Adam Warner
a7e414aca4 Sync master back into development (#5976) 2025-02-22 23:17:53 +00:00
Adam Warner
567bb724b1 Pi-hole Core v6.0.4 (#5975) 2025-02-22 23:14:13 +00:00
Adam Warner
bc3c78f4fa Print a more helpful message on pihole checkout in docker containers (#5963) 2025-02-22 22:49:51 +00:00
yubiuser
ce18de3d6d Assure that Lighttpd conf-enabled symlink is removed (#5974) 2025-02-22 23:31:47 +01:00
MichaIng
8e706e4a16 Assure that Lighttpd conf-enabled symlink is removed
`/etc/lighttpd/conf-enabled` usually contains symlinks to the actual files in `/etc/lighttpd/conf-available`, at least `lighty-enable-mod` does exactly this. If `/etc/lighttpd/conf-available/15-pihole-admin.conf` is removed first, `/etc/lighttpd/conf-enabled/15-pihole-admin.conf` hence points to nowhere, which makes the `-f` check return false. The orphaned symlink is hence not removed, if `lighty-disable-mod` is not available.

This PR changes the order, to remove the symlink first, and to be failsafe also if it is orphaned already, and the actual config afterwards.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-22 23:27:05 +01:00
Adam Warner
667a25574a Fix dnsmasq v5 to v6 config migration (#5968) 2025-02-22 21:33:02 +00:00
MichaIng
8f5296536e Fix dnsmasq v5 to v6 config migration
The dnsmasq config files were removed in `remove_old_dnsmasq_ftl_configs()`, before they were tried to be migrated via `migrate_dnsmasq_configs()`, and hence most settings were lost during v5 to v6 update.

This commit renames and adjussts `remove_old_dnsmasq_ftl_configs()` to move dnsmasq config files into the migration directory instead, to be picked up by `migrate_dnsmasq_configs()` later.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-22 21:43:49 +01:00
Adam Warner
da4048ba5d Only run migration code if setupVars.conf exists. (#5969) 2025-02-22 20:30:46 +00:00
Adam Warner
1764f99333 decide migration based on existence of setupVars rather than pihole.toml
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2025-02-22 15:35:05 +00:00
Christian König
cadee26dba Improve dig error handlin in api.sh
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-22 13:48:55 +01:00
DL6ER
b64a54bba1 Print a more helpful message on pihole checkout in docker containers
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-22 11:53:16 +01:00
yubiuser
5d5bddc979 Don't set a random password on v5 -> v6 updates (#5960) 2025-02-22 11:21:17 +01:00
Christian König
bd3a0f4891 Don't set a random password on v5 -> v6 updates
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-22 07:16:28 +01:00
Christian König
cd269cbca1 If there are no files to change, don't print an error
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-21 22:02:03 +01:00
Adam Warner
8290e414ce Sync master back into development (#5944) 2025-02-20 23:23:31 +00:00
Adam Warner
0e6d9e74d9 Pi-hole Core v6.0.2 (#5939) 2025-02-20 23:07:13 +00:00
Adam Warner
f38332409f Fix empty password detection (#5935) 2025-02-20 22:43:52 +00:00
MichaIng
cd4efc3141 Fix empty password detection
The CLI skips double quotes in config output, hence the output is completely empty, if no password was applied yet, e.g. on a fresh install. This leads to an unprotected web interface. The check is corrected, to have a random password applied as intended.

Additionally, the logic to show an unchanged or unset password on the completion dialog is inverted to correctly show "unchanged" resp. "NOT SET" if the password has not been changed resp. is empty.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-20 19:12:59 +01:00
Adam Warner
99bd142dd5 Apply chosen upstream DNS on fresh install (#5938) 2025-02-20 17:59:37 +00:00
MichaIng
49bb6dc0da Apply chosen upstream DNS on fresh install
While the dialog is shown to choose or enter an upstream DNS for Pi-hole, it is never applied. Hence fresh Pi-hole installs have no upstream DNS and cannot resolve queries.

It is now checked for the two generated variables PIHOLE_DNS_1 and PIHOLE_DNS_2, a TOML array generated and applied via pihole-FTL CLI.

Signed-off-by: MichaIng <micha@dietpi.com>
2025-02-20 18:28:38 +01:00
Dominik
6f82ec5121 Sync master back into development (#5913) 2025-02-19 17:30:40 +01:00
Dominik
9de976cbbd Pi-hole Core 6.0.1 (#5912) 2025-02-19 17:17:57 +01:00
yubiuser
0890f67322 Fix i386 fallback download (#5903) 2025-02-19 10:12:29 +01:00
DL6ER
f7403e2ee6 Fix binary name in 32 bit x86 fallback case
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-19 08:42:32 +01:00
Dominik
51a9412c4b Sync master back into development (#5892) 2025-02-18 19:22:47 +01:00
Adam Warner
2d81552f9f Pi-hole core v6.0.0 (#5842) 2025-02-18 17:19:41 +00:00
yubiuser
2faad0b60a Fix database integrity check in debug log (#5889) 2025-02-14 07:41:07 +01:00
Christian König
c9e58adc48 DHCP discover timeout was reduced by FTL
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-10 20:41:18 +01:00
Christian König
d1639740d9 Fix database integrity check in debug log
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-10 20:29:05 +01:00
Dominik
abb94cafe4 Amend warning on gravity tree build failure (#5888) 2025-02-09 19:07:57 +01:00
DL6ER
1bebeff720 Add further info message that building the tree may have failed because of too little RAM baing available. We have see this a few times, either with way too many domains on devices like a Pi Zero or, e.g., only 256 MB RAM being allocated to VMs
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-09 10:06:24 +01:00
Christian König
dfc2b32248 Use better function name
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-06 21:57:17 +01:00
Christian König
49cf5bb221 Remove 'reconfigure' option
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-06 21:57:05 +01:00
yubiuser
9d53ad7668 installer: use a drop-in to disable systemd-resolved stub listener (#5885) 2025-02-06 18:47:49 +01:00
Nick Rosbrook
8fb3ccc147 installer: use a drop-in to disable systemd-resolved stub listener
systemd-resolved supports drop-in config snippets, e.g. by placing .conf
files in /etc/systemd/resolved.conf.d. During install, use a drop-in
config to set DNSStubListener=no, instead of modifying the main config.

This is generally better practice, and also prevents conflicts when
distribution packages are upgraded, which may include new versions of
/etc/systemd/resolved.conf.

Signed-off-by: Nick Rosbrook <enr0n@ubuntu.com>
2025-02-04 16:18:04 -05:00
Dominik
9212a4a514 Decide if the content was changed *before* passing over to FTL (#5872) 2025-02-04 18:57:01 +01:00
Adam Warner
2ae78e02bd Add call to os_check in the update script (#5845) 2025-02-04 17:35:15 +00:00
yubiuser
330698878a Remove outdated dns-servers.conf (#5883) 2025-02-04 06:19:07 +01:00
Dominik
8e298df1e8 Show only enabled domains/regex in the final gravity message (#5884) 2025-02-03 20:37:49 +01:00
Dominik
894a9e157f Move gravity list cache into dedicated directory (#5869) 2025-02-03 20:35:38 +01:00
DL6ER
88cfda7210 Show only enabled domains/regex in the final gravity message
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-03 19:16:24 +01:00
Christian König
0da97e762f Remove outdated dns-servers.conf
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-03 08:31:33 +01:00
Christian König
94e772378e Merge branch 'development' into new/listsCacheDir
Signed-off-by: Christian König <github@yubiuser.dev>
2025-02-03 08:09:37 +01:00
Dominik
7dbf408c26 Gravity: Use ETags (#5867) 2025-02-03 06:30:11 +01:00
Dominik
ec805f9543 Fix counting of domains in the gravity summary (#5881) 2025-02-02 21:07:52 +01:00
DL6ER
7162be18e2 Remove curl -V temp variable
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-02 20:57:13 +01:00
yubiuser
9cd32bf2b7 Bump actions/setup-python from 5.3.0 to 5.4.0 (#5878) 2025-02-02 13:34:16 +01:00
DL6ER
9da1e9ab88 Fix counting of domains at the end of pihole -g. The existing schme used the SQL VIEWs for simplicitly, however, they have the unintended side-effect of - when being queried without a GROUP BY clause - returning entries multiple times if they are assigned to several groups
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-01 19:42:25 +01:00
DL6ER
37718c65e9 Simplify cURL etag feature detection following discussion in #5873
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-02-01 19:36:56 +01:00
dependabot[bot]
aadea31e52 Bump actions/setup-python from 5.3.0 to 5.4.0
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5.3.0...v5.4.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 10:14:46 +00:00
DL6ER
9faef22061 Decide if the content was changed *before* passing over to FTL
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-31 16:46:12 +01:00
DL6ER
bf899fa57f Migrate list's files (lists themselves, their SHA1 sum and, later, their ETags) into a dedicated directory /etc/pihole/listsCache in an attempt to clean up /etc/pihole
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-30 06:12:49 +01:00
DL6ER
68b03e114c Merge branch 'development' into new/etags
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 19:24:31 +01:00
Dominik
e682f69a1d Use a different method to identify if a gravity restore succeeded (#5868) 2025-01-29 19:23:40 +01:00
DL6ER
f50c696253 Use temp variable for curl -V output
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 19:19:01 +01:00
DL6ER
6e0b16ed1a Rename heisenbergCompensator -> modifiedOptions
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 19:17:04 +01:00
DL6ER
4322299c39 Drive-by fixing of errors reported by shellcheck for gravity.sh
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 17:53:33 +01:00
DL6ER
cee021c358 Use HTTP ETags in addition to the If-Modified-Since header if supported by curl to avoid downloading from servers not using the latter method (raw.githubcontent.com)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 17:53:33 +01:00
DL6ER
c381109dcd Use a different method to identify if a gravity restore succeeded
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-29 17:52:39 +01:00
Dominik
9a3fcf2a85 Gravity database resilience (#5818) 2025-01-27 01:29:37 +01:00
DL6ER
6d4d35e848 Merge branch 'development' into tweak/gravity_backup 2025-01-26 19:53:06 +01:00
DL6ER
69bfb3ff3b Store timestamp of the backup creation instead of the filename on restoring gravity.db
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-26 19:52:46 +01:00
yubiuser
f7727f98bd Bump actions/stale from 9.0.0 to 9.1.0 (#5863) 2025-01-26 08:44:57 +01:00
yubiuser
05f8bb128c Bump tox from 4.23.2 to 4.24.1 in /test (#5864) 2025-01-26 06:28:22 +01:00
dependabot[bot]
66757de3fb Bump tox from 4.23.2 to 4.24.1 in /test
Bumps [tox](https://github.com/tox-dev/tox) from 4.23.2 to 4.24.1.
- [Release notes](https://github.com/tox-dev/tox/releases)
- [Changelog](https://github.com/tox-dev/tox/blob/main/docs/changelog.rst)
- [Commits](https://github.com/tox-dev/tox/compare/4.23.2...4.24.1)

---
updated-dependencies:
- dependency-name: tox
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-25 10:34:03 +00:00
dependabot[bot]
08e3257f37 Bump actions/stale from 9.0.0 to 9.1.0
Bumps [actions/stale](https://github.com/actions/stale) from 9.0.0 to 9.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/v9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-25 10:08:17 +00:00
Adam Warner
0f318027fc Remove unused code from debug log and skip some tests inside containers (#5854) 2025-01-16 17:13:41 +00:00
RD WebDesign
254b67bca3 Using more user-friendly messages on git describe failure
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-13 20:11:41 -03:00
RD WebDesign
0ae50eab87 Suppress error message on git describe failure
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-12 20:25:32 -03:00
DL6ER
cc25ee940e Fix unreachable code
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-12 13:42:51 +01:00
DL6ER
12927f8a3d Put gravity backup files into dedicated directory for cleaness
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-12 13:41:27 +01:00
yubiuser
efaa0f4287 Bump eps1lon/actions-label-merge-conflict from 3.0.2 to 3.0.3 (#5856) 2025-01-11 15:04:52 +01:00
dependabot[bot]
83d464e85f Bump eps1lon/actions-label-merge-conflict from 3.0.2 to 3.0.3
Bumps [eps1lon/actions-label-merge-conflict](https://github.com/eps1lon/actions-label-merge-conflict) from 3.0.2 to 3.0.3.
- [Release notes](https://github.com/eps1lon/actions-label-merge-conflict/releases)
- [Changelog](https://github.com/eps1lon/actions-label-merge-conflict/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eps1lon/actions-label-merge-conflict/compare/v3.0.2...v3.0.3)

---
updated-dependencies:
- dependency-name: eps1lon/actions-label-merge-conflict
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-11 10:54:32 +00:00
RD WebDesign
27fb2bbe3a Replace some hardcoded paths with pihole.toml values
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-09 19:11:22 -03:00
RD WebDesign
c78be8a89d No systemctl or service inside containers
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-09 19:11:22 -03:00
RD WebDesign
0590bbba2d Skip some checks in docker container
These commands always fail in containers with "command not found" (as expected).

Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-09 19:11:21 -03:00
RD WebDesign
733dce1c4c If it's a docker container, consider the OS is supported
Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-09 19:11:15 -03:00
RD WebDesign
bd9cc7cbb7 Clean up unused WEBCALL code
Debug Log is no longer available via web interface

Signed-off-by: RD WebDesign <github@rdwebdesign.com.br>
2025-01-09 17:15:12 -03:00
Dominik
4902c70063 Explicitly migrate from v5 to v6 (#5830) 2025-01-09 19:39:27 +01:00
Dominik
4be130971e Update automated install/basic-install.sh
Co-authored-by: yubiuser <github@yubiuser.dev>
Signed-off-by: Dominik <DL6ER@users.noreply.github.com>
2025-01-09 18:32:04 +01:00
Dominik
211a881888 Apply suggestions from code review
Co-authored-by: yubiuser <github@yubiuser.dev>
Signed-off-by: Dominik <DL6ER@users.noreply.github.com>
2025-01-08 19:28:15 +01:00
DL6ER
4d23187f86 Add missing newline
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-07 17:49:57 +01:00
Christian König
b544b74f7a Merge branch 'development' into fix/migration 2025-01-06 16:43:18 +01:00
Dominik
6e633e4cfd Improve lighttpd disabling (#5849) 2025-01-02 15:05:00 +01:00
DL6ER
364281354c Check if service is currently enabled when checking if lighttpd may need to be disabled
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-02 13:43:32 +01:00
yubiuser
4c5285e469 Remove now unused function test_dpkg_lock() (#5848) 2025-01-01 18:56:19 +01:00
DL6ER
79087fb252 SHow lighttpd disable dialog only once during v6 migration and when lighttpd is actually installed
Signed-off-by: DL6ER <dl6er@dl6er.de>
2025-01-01 18:55:49 +01:00
DL6ER
fab1ca3a40 Merge branch 'development' into tweak/gravity_backup 2025-01-01 18:46:33 +01:00
Christian König
4fd77f57fa Remove now unused function test_dpkg_lock()
Signed-off-by: Christian König <github@yubiuser.dev>
2025-01-01 12:20:50 +01:00
Adam Warner
bd9cb00574 Perform os_check during update, in case the user has updated to an unsupported OS between Pi-hole updates.
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2024-12-31 15:31:04 +00:00
Dominik
b0e0bdc436 Disable lighttpd if found (#5835) 2024-12-30 17:01:04 +01:00
DL6ER
1835827371 Ensure Yes to keeping lighttpd doesn't trigger set -e during the upgrade
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-30 15:35:41 +01:00
Adam Warner
cb32a7f81c Merge branch 'master' into development 2024-12-29 14:06:24 +00:00
Adam Warner
2cf046d559 Fix v5 for Fedora 41 (#5839) 2024-12-29 13:53:35 +00:00
Adam Warner
a1ccee6694 use rpm -q to check if packages are already installed, this is due to a change in the behaviour of dnf in Fedora 41
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2024-12-29 13:32:07 +00:00
Adam Warner
dff0c0105d remove EOL OS from test suite
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2024-12-29 12:43:08 +00:00
Adam Warner
d972ffa53a while v6 is still not released, update tests in master to NOT use development branch of FTL
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2024-12-29 12:35:32 +00:00
Adam Warner
22b6dc7dae Add test scripts for fed 41 for v5
Signed-off-by: Adam Warner <me@adamwarner.co.uk>
2024-12-29 12:23:37 +00:00
Dominik
3406915917 Exit early when neither service nor systemctl commands are available (#5834) 2024-12-26 07:19:22 +01:00
Dominik
50645c2924 Apply suggestions from code review
Co-authored-by: Adam Warner <me@adamwarner.co.uk>
Co-authored-by: RD WebDesign <github@rdwebdesign.com.br>
Signed-off-by: Dominik <DL6ER@users.noreply.github.com>
2024-12-24 02:19:37 +01:00
DL6ER
d14273f958 Add comment where setupVars.conf goes when v6 migration is done
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-24 02:17:50 +01:00
DL6ER
47d5a08565 Ask the user if they want to disable lighttpd
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 19:12:47 +01:00
DL6ER
e08f65d1c4 Disable lighttpd if found
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 09:30:37 +01:00
yubiuser
b964657b62 Speedup api response handling (#5833) 2024-12-23 09:14:47 +01:00
DL6ER
a2a22c4e13 Exit early when neither service nor systemctl commands are available
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 09:13:34 +01:00
DL6ER
8faa28d8a0 Explicitly log migration process
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-23 08:57:34 +01:00
Dominik
a9948304db Fix v5 -> v6 update (#5832) 2024-12-23 08:54:26 +01:00
Christian König
3011d48b6f Use tail instead of parameter expansion
Signed-off-by: Christian König <github@yubiuser.dev>
2024-12-22 23:44:31 +01:00
Christian König
c777152c04 Only separat data and status when needed
Signed-off-by: Christian König <github@yubiuser.dev>
2024-12-22 21:57:47 +01:00
DL6ER
4f268ed193 Explicitly migrate from v5 to v6
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-12-21 07:10:46 +01:00
DL6ER
579dc07046 Merge branch 'development' into tweak/gravity_backup
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-26 21:08:09 +01:00
DL6ER
633c971a44 Store failed gravity restoration status in message table
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-23 09:44:39 +01:00
Dominik
9a9af719f0 Update gravity.sh
Co-authored-by: RD WebDesign <github@rdwebdesign.com.br>
Signed-off-by: Dominik <DL6ER@users.noreply.github.com>
2024-11-17 17:05:26 +01:00
DL6ER
fdf44355d2 Keep up to 10 database backups
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-16 12:08:27 +01:00
DL6ER
a5cb07c76e Attempt to restore from all possibly available gravity.db backups
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-16 11:52:31 +01:00
DL6ER
59e9bac794 Only try to obtain sources after possible database restore following a corruption
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-16 11:49:11 +01:00
DL6ER
b2ad878f4a Try to restore from gravity backup on database preparation error (if backup is available)
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-16 10:18:00 +01:00
DL6ER
6ff30f7294 Backup a stripped-down version of gravity.db after each pihole -g run
Signed-off-by: DL6ER <dl6er@dl6er.de>
2024-11-16 10:09:44 +01:00
47 changed files with 1047 additions and 1029 deletions

5
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,5 @@
# see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
* @pi-hole/core-maintainers

View File

@@ -8,8 +8,6 @@ updates:
time: "10:00" time: "10:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
target-branch: development target-branch: development
reviewers:
- "pi-hole/core-maintainers"
- package-ecosystem: pip - package-ecosystem: pip
directory: "/test" directory: "/test"
schedule: schedule:
@@ -18,5 +16,3 @@ updates:
time: "10:00" time: "10:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
target-branch: development target-branch: development
reviewers:
- "pi-hole/core-maintainers"

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check if PRs are have merge conflicts - name: Check if PRs are have merge conflicts
uses: eps1lon/actions-label-merge-conflict@v3.0.2 uses: eps1lon/actions-label-merge-conflict@v3.0.3
with: with:
dirtyLabel: "PR: Merge Conflict" dirtyLabel: "PR: Merge Conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}" repoToken: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -17,7 +17,7 @@ jobs:
issues: write issues: write
steps: steps:
- uses: actions/stale@v9.0.0 - uses: actions/stale@v9.1.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30 days-before-stale: 30

View File

@@ -17,7 +17,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@v9.0.0 - uses: actions/stale@v9.1.0
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
# Do not automatically mark PR/issue as stale # Do not automatically mark PR/issue as stale

View File

@@ -19,6 +19,8 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4.2.2 uses: actions/checkout@v4.2.2
with:
fetch-depth: 0 # Differential ShellCheck requires full git history
- name: Check scripts in repository are executable - name: Check scripts in repository are executable
run: | run: |
@@ -28,12 +30,12 @@ jobs:
# If FAIL is 1 then we fail. # If FAIL is 1 then we fail.
[[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!" [[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!"
- name: Run shellcheck - name: Differential ShellCheck
uses: ludeeus/action-shellcheck@master uses: redhat-plumbers-in-action/differential-shellcheck@v5
with: with:
check_together: 'yes' severity: warning
format: tty display-engine: sarif-fmt
severity: error
- name: Spell-Checking - name: Spell-Checking
uses: codespell-project/actions-codespell@master uses: codespell-project/actions-codespell@master
@@ -67,8 +69,10 @@ jobs:
ubuntu_22, ubuntu_22,
ubuntu_24, ubuntu_24,
centos_9, centos_9,
centos_10,
fedora_40, fedora_40,
fedora_41, fedora_41,
fedora_42,
] ]
env: env:
DISTRO: ${{matrix.distro}} DISTRO: ${{matrix.distro}}
@@ -77,7 +81,7 @@ jobs:
uses: actions/checkout@v4.2.2 uses: actions/checkout@v4.2.2
- name: Set up Python 3.10 - name: Set up Python 3.10
uses: actions/setup-python@v5.3.0 uses: actions/setup-python@v5.6.0
with: with:
python-version: "3.10" python-version: "3.10"

3
.gitignore vendored
View File

@@ -10,3 +10,6 @@ __pycache__
.idea/ .idea/
*.iml *.iml
.vscode/ .vscode/
.venv/
.fleet/
.cache/

2
.shellcheckrc Normal file
View File

@@ -0,0 +1,2 @@
external-sources=true # allow shellcheck to read external sources
disable=SC3043 #disable SC3043: In POSIX sh, local is undefined.

View File

@@ -3,13 +3,9 @@
# #
<p align="center"> <p align="center">
<picture> <img src="https://raw.githubusercontent.com/pi-hole/graphics/refs/heads/master/Vortex/vortex_with_text.svg" alt="Pi-hole website" width="168" height="270">
<source media="(prefers-color-scheme: dark)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_darkmode.png"> <br>
<source media="(prefers-color-scheme: light)" srcset="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png"> <strong>Network-wide ad blocking via your own Linux hardware</strong>
<img src="https://pi-hole.github.io/graphics/Vortex/Vortex_Vertical_wordmark_lightmode.png" width="168" height="270" alt="Pi-hole website">
</picture>
<br>
<strong>Network-wide ad blocking via your own Linux hardware</strong>
</p> </p>
<!-- markdownlint-enable MD033 --> <!-- markdownlint-enable MD033 -->
@@ -132,7 +128,10 @@ Some of the statistics you can integrate include:
- Queries cached - Queries cached
- Unique clients - Unique clients
Access the API via [`telnet`](https://github.com/pi-hole/FTL), the Web (`admin/api.php`) and Command Line (`pihole -c -j`). You can find out [more details over here](https://discourse.pi-hole.net/t/pi-hole-api/1863). Access the API using:
- your browser: http://pi.hole/api/docs
- `curl`: `curl --connect-timeout 2 -ks "https://pi.hole/api/stats/summary" -H "Accept: application/json"`;
- the command line - examples: `pihole api config/webserver/port` or `pihole api stats/summary`.
### The Command-Line Interface ### The Command-Line Interface
@@ -140,7 +139,7 @@ The [pihole](https://docs.pi-hole.net/core/pihole-command/) command has all the
Some notable features include: Some notable features include:
- [Whitelisting, Blacklisting, and Regex](https://docs.pi-hole.net/core/pihole-command/#whitelisting-blacklisting-and-regex) - [Allowlisting, Denylisting (fka Whitelisting, Blacklisting), and Regex](https://docs.pi-hole.net/core/pihole-command/#allowlisting-denylisting-and-regex)
- [Debugging utility](https://docs.pi-hole.net/core/pihole-command/#debugger) - [Debugging utility](https://docs.pi-hole.net/core/pihole-command/#debugger)
- [Viewing the live log file](https://docs.pi-hole.net/core/pihole-command/#tail) - [Viewing the live log file](https://docs.pi-hole.net/core/pihole-command/#tail)
- [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity) - [Updating Ad Lists](https://docs.pi-hole.net/core/pihole-command/#gravity)

View File

@@ -1,5 +1,6 @@
#!/usr/bin/env sh
# Determine if terminal is capable of showing colors # Determine if terminal is capable of showing colors
if ([ -t 1 ] && [ $(tput colors) -ge 8 ]) || [ "${WEBCALL}" ]; then if [ -t 1 ] && [ "$(tput colors)" -ge 8 ]; then
# Bold and underline may not show up on all clients # Bold and underline may not show up on all clients
# If something MUST be emphasized, use both # If something MUST be emphasized, use both
COL_BOLD='' COL_BOLD=''

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
@@ -20,13 +19,19 @@
TestAPIAvailability() { TestAPIAvailability() {
local chaos_api_list authResponse authStatus authData apiAvailable DNSport
# as we are running locally, we can get the port value from FTL directly # as we are running locally, we can get the port value from FTL directly
local chaos_api_list availabilityResponse readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh
. "${utilsfile}"
DNSport=$(getFTLConfigValue dns.port)
# Query the API URLs from FTL using CHAOS TXT local.api.ftl # Query the API URLs from FTL using CHAOS TXT local.api.ftl
# The result is a space-separated enumeration of full URLs # The result is a space-separated enumeration of full URLs
# e.g., "http://localhost:80/api/" "https://localhost:443/api/" # e.g., "http://localhost:80/api/" "https://localhost:443/api/"
chaos_api_list="$(dig +short chaos txt local.api.ftl @127.0.0.1)" chaos_api_list="$(dig +short -p "${DNSport}" chaos txt local.api.ftl @127.0.0.1)"
# If the query was not successful, the variable is empty # If the query was not successful, the variable is empty
if [ -z "${chaos_api_list}" ]; then if [ -z "${chaos_api_list}" ]; then
@@ -34,6 +39,12 @@ TestAPIAvailability() {
exit 1 exit 1
fi fi
# If an error occurred, the variable starts with ;;
if [ "${chaos_api_list#;;}" != "${chaos_api_list}" ]; then
echo "Communication error. Is FTL running?"
exit 1
fi
# Iterate over space-separated list of URLs # Iterate over space-separated list of URLs
while [ -n "${chaos_api_list}" ]; do while [ -n "${chaos_api_list}" ]; do
# Get the first URL # Get the first URL
@@ -42,39 +53,50 @@ TestAPIAvailability() {
API_URL="${API_URL%\"}" API_URL="${API_URL%\"}"
API_URL="${API_URL#\"}" API_URL="${API_URL#\"}"
# Test if the API is available at this URL # Test if the API is available at this URL, include delimiter for ease in splitting payload
availabilityResponse=$(curl -skS -o /dev/null -w "%{http_code}" "${API_URL}auth") authResponse=$(curl --connect-timeout 2 -skS -w ">>%{http_code}" "${API_URL}auth")
# authStatus is the response http_code, eg. 200, 401.
# Shell parameter expansion, remove everything up to and including the >> delim
authStatus=${authResponse#*>>}
# data is everything from response
# Shell parameter expansion, remove the >> delim and everything after
authData=${authResponse%>>*}
# Test if http status code was 200 (OK) or 401 (authentication required) # Test if http status code was 200 (OK) or 401 (authentication required)
if [ ! "${availabilityResponse}" = 200 ] && [ ! "${availabilityResponse}" = 401 ]; then if [ "${authStatus}" = 200 ]; then
# API is not available at this port/protocol combination # API is available without authentication
API_PORT="" apiAvailable=true
else needAuth=false
# API is available at this URL combination
if [ "${availabilityResponse}" = 200 ]; then
# API is available without authentication
needAuth=false
fi
break break
fi
# Remove the first URL from the list elif [ "${authStatus}" = 401 ]; then
local last_api_list # API is available with authentication
last_api_list="${chaos_api_list}" apiAvailable=true
chaos_api_list="${chaos_api_list#* }" needAuth=true
# Check if 2FA is required
needTOTP=$(echo "${authData}"| jq --raw-output .session.totp 2>/dev/null)
break
# If the list did not change, we are at the last element else
if [ "${last_api_list}" = "${chaos_api_list}" ]; then # API is not available at this port/protocol combination
# Remove the last element apiAvailable=false
chaos_api_list="" # Remove the first URL from the list
local last_api_list
last_api_list="${chaos_api_list}"
chaos_api_list="${chaos_api_list#* }"
# If the list did not change, we are at the last element
if [ "${last_api_list}" = "${chaos_api_list}" ]; then
# Remove the last element
chaos_api_list=""
fi
fi fi
done done
# if API_PORT is empty, no working API port was found # if apiAvailable is false, no working API was found
if [ -n "${API_PORT}" ]; then if [ "${apiAvailable}" = false ]; then
echo "API not available at: ${API_URL}" echo "API not available. Please check FTL.log"
echo "Exiting." echo "Exiting."
exit 1 exit 1
fi fi
@@ -102,22 +124,51 @@ LoginAPI() {
echo "API Authentication: Trying to use CLI password" echo "API Authentication: Trying to use CLI password"
fi fi
# Try to authenticate using the CLI password # If we can read the CLI password, we can skip 2FA even when it's required otherwise
Authentication "${1}" needTOTP=false
elif [ "${1}" = "verbose" ]; then elif [ "${1}" = "verbose" ]; then
echo "API Authentication: CLI password not available" echo "API Authentication: CLI password not available"
fi fi
if [ -z "${password}" ]; then
# no password read from CLI file
echo "Please enter your password:"
# secretly read the password
secretRead; printf '\n'
fi
if [ "${needTOTP}" = true ]; then
# 2FA required
echo "Please enter the correct second factor."
echo "(Can be any number if you used the app password)"
read -r totp
fi
# If this did not work, ask the user for the password # Try to authenticate using the supplied password (CLI file or user input) and TOTP
while [ "${validSession}" = false ] || [ -z "${validSession}" ] ; do Authentication "${1}"
# Try to login again until the session is valid
while [ ! "${validSession}" = true ] ; do
echo "Authentication failed. Please enter your Pi-hole password" echo "Authentication failed. Please enter your Pi-hole password"
# Print the error message if there is one
if [ ! "${sessionError}" = "null" ] && [ "${1}" = "verbose" ]; then
echo "Error: ${sessionError}"
fi
# Print the session message if there is one
if [ ! "${sessionMessage}" = "null" ] && [ "${1}" = "verbose" ]; then
echo "Error: ${sessionMessage}"
fi
# secretly read the password # secretly read the password
secretRead; printf '\n' secretRead; printf '\n'
if [ "${needTOTP}" = true ]; then
echo "Please enter the correct second factor:"
echo "(Can be any number if you used the app password)"
read -r totp
fi
# Try to authenticate again # Try to authenticate again
Authentication "${1}" Authentication "${1}"
done done
@@ -125,23 +176,27 @@ LoginAPI() {
} }
Authentication() { Authentication() {
sessionResponse="$(curl -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli " --data "{\"password\":\"${password}\"}" )" sessionResponse="$(curl --connect-timeout 2 -skS -X POST "${API_URL}auth" --user-agent "Pi-hole cli" --data "{\"password\":\"${password}\", \"totp\":${totp:-null}}" )"
if [ -z "${sessionResponse}" ]; then if [ -z "${sessionResponse}" ]; then
echo "No response from FTL server. Please check connectivity" echo "No response from FTL server. Please check connectivity"
exit 1 exit 1
fi fi
# obtain validity and session ID from session response # obtain validity, session ID and sessionMessage from session response
validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null) validSession=$(echo "${sessionResponse}"| jq .session.valid 2>/dev/null)
SID=$(echo "${sessionResponse}"| jq --raw-output .session.sid 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)
if [ "${1}" = "verbose" ]; then
if [ "${validSession}" = true ]; then # obtain the error message from the session response
echo "API Authentication: ${COL_GREEN}Success${COL_NC}" sessionError=$(echo "${sessionResponse}"| jq --raw-output .error.message 2>/dev/null)
else
echo "API Authentication: ${COL_RED}Failed${COL_NC}" if [ "${1}" = "verbose" ]; then
if [ "${validSession}" = true ]; then
echo "API Authentication: ${COL_GREEN}Success${COL_NC}"
else
echo "API Authentication: ${COL_RED}Failed${COL_NC}"
fi
fi fi
fi
} }
LogoutAPI() { LogoutAPI() {
@@ -165,19 +220,21 @@ GetFTLData() {
# get the data from querying the API as well as the http status code # 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}" )
# status are the last 3 characters
status="${response#"${response%???}"}"
# data is everything from response without the last 3 characters
data="${response%???}"
if [ "${2}" = "raw" ]; then if [ "${2}" = "raw" ]; then
# return the raw response # return the raw response
echo "${response}" echo "${response}"
else else
# status are the last 3 characters
# not using ${response#"${response%???}"}" here because it's extremely slow on big responses
status=$(printf "%s" "${response}" | tail -c 3)
# data is everything from response without the last 3 characters
data="${response%???}"
# return only the data # return only the data
if [ "${status}" = 200 ]; then if [ "${status}" = 200 ]; then
# response OK # response OK
echo "${data}" printf %s "${data}"
else else
# connection lost # connection lost
echo "${status}" echo "${status}"
@@ -251,20 +308,30 @@ secretRead() {
} }
apiFunc() { apiFunc() {
local data response status status_col local data response status status_col verbosity
# Define if the output will be silent (default) or verbose
verbosity="silent"
if [ "$1" = "verbose" ]; then
verbosity="verbose"
shift
fi
# Authenticate with the API # Authenticate with the API
LoginAPI verbose LoginAPI "${verbosity}"
echo ""
echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}" if [ "${verbosity}" = "verbose" ]; then
echo "" echo ""
echo "Requesting: ${COL_PURPLE}GET ${COL_CYAN}${API_URL}${COL_YELLOW}$1${COL_NC}"
echo ""
fi
# Get the data from the API # Get the data from the API
response=$(GetFTLData "$1" raw) response=$(GetFTLData "$1" raw)
# status are the last 3 characters # status are the last 3 characters
status="${response#"${response%???}"}" # not using ${response#"${response%???}"}" here because it's extremely slow on big responses
status=$(printf "%s" "${response}" | tail -c 3)
# data is everything from response without the last 3 characters # data is everything from response without the last 3 characters
data="${response%???}" data="${response%???}"
@@ -274,11 +341,18 @@ apiFunc() {
else else
status_col="${COL_RED}" status_col="${COL_RED}"
fi fi
echo "Status: ${status_col}${status}${COL_NC}"
# Only print the status in verbose mode or if the status is not 200
if [ "${verbosity}" = "verbose" ] || [ "${status}" != 200 ]; then
echo "Status: ${status_col}${status}${COL_NC}"
fi
# Output the data. Format it with jq if available and data is actually JSON. # Output the data. Format it with jq if available and data is actually JSON.
# Otherwise just print it # Otherwise just print it
echo "Data:" if [ "${verbosity}" = "verbose" ]; then
echo "Data:"
fi
if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then if command -v jq >/dev/null && echo "${data}" | jq . >/dev/null 2>&1; then
echo "${data}" | jq . echo "${data}" | jq .
else else
@@ -286,5 +360,5 @@ apiFunc() {
fi fi
# Delete the session # Delete the session
LogoutAPI verbose LogoutAPI "${verbosity}"
} }

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2019 Pi-hole, LLC (https://pi-hole.net) # (c) 2019 Pi-hole, LLC (https://pi-hole.net)
@@ -13,9 +13,8 @@
readonly scriptPath="/etc/.pihole/advanced/Scripts/database_migration/gravity" readonly scriptPath="/etc/.pihole/advanced/Scripts/database_migration/gravity"
upgrade_gravityDB(){ upgrade_gravityDB(){
local database piholeDir version local database version
database="${1}" database="${1}"
piholeDir="${2}"
# Exit early if the database does not exist (e.g. in CI tests) # Exit early if the database does not exist (e.g. in CI tests)
if [[ ! -f "${database}" ]]; then if [[ ! -f "${database}" ]]; then

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
@@ -12,9 +11,11 @@
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source="./advanced/Scripts/utils.sh"
source "${utilsfile}" source "${utilsfile}"
readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh"
# shellcheck source="./advanced/Scripts/api.sh"
source "${apifile}" source "${apifile}"
# Determine database location # Determine database location
@@ -39,6 +40,7 @@ typeId=""
comment="" comment=""
colfile="/opt/pihole/COL_TABLE" colfile="/opt/pihole/COL_TABLE"
# shellcheck source="./advanced/Scripts/COL_TABLE"
source ${colfile} source ${colfile}
helpFunc() { helpFunc() {

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2019 Pi-hole, LLC (https://pi-hole.net) # (c) 2019 Pi-hole, LLC (https://pi-hole.net)
@@ -12,13 +11,22 @@
coltable="/opt/pihole/COL_TABLE" coltable="/opt/pihole/COL_TABLE"
if [[ -f ${coltable} ]]; then if [[ -f ${coltable} ]]; then
# shellcheck source="./advanced/Scripts/COL_TABLE"
source ${coltable} source ${coltable}
fi fi
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh
source "${utilsfile}" source "${utilsfile}"
readonly PI_HOLE_FILES_DIR="/etc/.pihole"
SKIP_INSTALL="true"
# shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# stop_service() is defined in basic-install.sh
# restart_service() is defined in basic-install.sh
# Determine database location # Determine database location
DBFILE=$(getFTLConfigValue "files.database") DBFILE=$(getFTLConfigValue "files.database")
if [ -z "$DBFILE" ]; then if [ -z "$DBFILE" ]; then
@@ -32,7 +40,7 @@ flushARP(){
fi fi
# Stop FTL to prevent database access # Stop FTL to prevent database access
if ! output=$(service pihole-FTL stop 2>&1); then if ! output=$(stop_service pihole-FTL 2>&1); then
echo -e "${OVER} ${CROSS} Failed to stop FTL" echo -e "${OVER} ${CROSS} Failed to stop FTL"
echo " Output: ${output}" echo " Output: ${output}"
return 1 return 1
@@ -64,7 +72,7 @@ flushARP(){
fi fi
# Start FTL again # Start FTL again
if ! output=$(service pihole-FTL restart 2>&1); then if ! output=$(restart_service pihole-FTL 2>&1); then
echo -e "${OVER} ${CROSS} Failed to restart FTL" echo -e "${OVER} ${CROSS} Failed to restart FTL"
echo " Output: ${output}" echo " Output: ${output}"
return 1 return 1

View File

@@ -10,6 +10,7 @@
readonly PI_HOLE_FILES_DIR="/etc/.pihole" readonly PI_HOLE_FILES_DIR="/etc/.pihole"
SKIP_INSTALL="true" SKIP_INSTALL="true"
# shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# webInterfaceGitUrl set in basic-install.sh # webInterfaceGitUrl set in basic-install.sh
@@ -109,7 +110,7 @@ checkout() {
echo -e "${OVER} ${CROSS} $str" echo -e "${OVER} ${CROSS} $str"
exit 1 exit 1
fi fi
corebranches=($(get_available_branches "${PI_HOLE_FILES_DIR}")) mapfile -t corebranches < <(get_available_branches "${PI_HOLE_FILES_DIR}")
if [[ "${corebranches[*]}" == *"master"* ]]; then if [[ "${corebranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str" echo -e "${OVER} ${TICK} $str"
@@ -136,7 +137,7 @@ checkout() {
echo -e "${OVER} ${CROSS} $str" echo -e "${OVER} ${CROSS} $str"
exit 1 exit 1
fi fi
webbranches=($(get_available_branches "${webInterfaceDir}")) mapfile -t webbranches < <(get_available_branches "${webInterfaceDir}")
if [[ "${webbranches[*]}" == *"master"* ]]; then if [[ "${webbranches[*]}" == *"master"* ]]; then
echo -e "${OVER} ${TICK} $str" echo -e "${OVER} ${TICK} $str"
@@ -167,7 +168,7 @@ checkout() {
# Check if requested branch is available # Check if requested branch is available
echo -e " ${INFO} Checking for availability of branch ${COL_CYAN}${2}${COL_NC} on GitHub" echo -e " ${INFO} Checking for availability of branch ${COL_CYAN}${2}${COL_NC} on GitHub"
ftlbranches=( $(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -) ) mapfile -t ftlbranches < <(git ls-remote https://github.com/pi-hole/ftl | grep "refs/heads" | cut -d'/' -f3- -)
# If returned array is empty -> connectivity issue # If returned array is empty -> connectivity issue
if [[ ${#ftlbranches[@]} -eq 0 ]]; then if [[ ${#ftlbranches[@]} -eq 0 ]]; then
echo -e " ${CROSS} Unable to fetch branches from GitHub. Please check your Internet connection and try again later." echo -e " ${CROSS} Unable to fetch branches from GitHub. Please check your Internet connection and try again later."
@@ -209,13 +210,15 @@ checkout() {
# Update local and remote versions via updatechecker # Update local and remote versions via updatechecker
/opt/pihole/updatecheck.sh /opt/pihole/updatecheck.sh
else else
if [ $? -eq 1 ]; then local status
status=$?
if [ $status -eq 1 ]; then
# Binary for requested branch is not available, may still be # Binary for requested branch is not available, may still be
# int he process of being built or CI build job failed # int he process of being built or CI build job failed
printf " %b Binary for requested branch is not available, please try again later.\\n" ${CROSS} printf " %b Binary for requested branch is not available, please try again later.\\n" "${CROSS}"
printf " If the issue persists, please contact Pi-hole Support and ask them to re-generate the binary.\\n" printf " If the issue persists, please contact Pi-hole Support and ask them to re-generate the binary.\\n"
exit 1 exit 1
elif [ $? -eq 2 ]; then elif [ $status -eq 2 ]; then
printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}" printf " %b Unable to download from ftl.pi-hole.net. Please check your Internet connection and try again later.\\n" "${CROSS}"
exit 1 exit 1
else else

View File

@@ -8,7 +8,6 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
# shellcheck source=/dev/null
# -e option instructs bash to immediately exit if any command [1] has a non-zero exit status # -e option instructs bash to immediately exit if any command [1] has a non-zero exit status
# -u a reference to any variable you haven't previously defined # -u a reference to any variable you haven't previously defined
@@ -27,6 +26,7 @@ PIHOLE_COLTABLE_FILE="${PIHOLE_SCRIPTS_DIRECTORY}/COL_TABLE"
# These provide the colors we need for making the log more readable # These provide the colors we need for making the log more readable
if [[ -f ${PIHOLE_COLTABLE_FILE} ]]; then if [[ -f ${PIHOLE_COLTABLE_FILE} ]]; then
# shellcheck source=./advanced/Scripts/COL_TABLE
source ${PIHOLE_COLTABLE_FILE} source ${PIHOLE_COLTABLE_FILE}
else else
COL_NC='\e[0m' # No Color COL_NC='\e[0m' # No Color
@@ -41,9 +41,17 @@ else
#OVER="\r\033[K" #OVER="\r\033[K"
fi fi
# shellcheck disable=SC1091 # shellcheck source=/dev/null
. /etc/pihole/versions . /etc/pihole/versions
# Read the value of an FTL config key. The value is printed to stdout.
get_ftl_conf_value() {
local key=$1
# Obtain setting from FTL directly
pihole-FTL --config "${key}"
}
# FAQ URLs for use in showing the debug log # FAQ URLs for use in showing the debug log
FAQ_HARDWARE_REQUIREMENTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/${COL_NC}" FAQ_HARDWARE_REQUIREMENTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/${COL_NC}"
FAQ_HARDWARE_REQUIREMENTS_PORTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#ports${COL_NC}" FAQ_HARDWARE_REQUIREMENTS_PORTS="${COL_CYAN}https://docs.pi-hole.net/main/prerequisites/#ports${COL_NC}"
@@ -61,10 +69,10 @@ DNSMASQ_D_DIRECTORY="/etc/dnsmasq.d"
PIHOLE_DIRECTORY="/etc/pihole" PIHOLE_DIRECTORY="/etc/pihole"
PIHOLE_SCRIPTS_DIRECTORY="/opt/pihole" PIHOLE_SCRIPTS_DIRECTORY="/opt/pihole"
BIN_DIRECTORY="/usr/local/bin" BIN_DIRECTORY="/usr/local/bin"
RUN_DIRECTORY="/run"
LOG_DIRECTORY="/var/log/pihole" LOG_DIRECTORY="/var/log/pihole"
HTML_DIRECTORY="/var/www/html" HTML_DIRECTORY="$(get_ftl_conf_value "webserver.paths.webroot")"
WEB_GIT_DIRECTORY="${HTML_DIRECTORY}/admin" WEBHOME_PATH="$(get_ftl_conf_value "webserver.paths.webhome")"
WEB_GIT_DIRECTORY="${HTML_DIRECTORY}${WEBHOME_PATH}"
SHM_DIRECTORY="/dev/shm" SHM_DIRECTORY="/dev/shm"
ETC="/etc" ETC="/etc"
@@ -79,14 +87,6 @@ PIHOLE_FTL_CONF_FILE="${PIHOLE_DIRECTORY}/pihole.toml"
PIHOLE_DNSMASQ_CONF_FILE="${PIHOLE_DIRECTORY}/dnsmasq.conf" PIHOLE_DNSMASQ_CONF_FILE="${PIHOLE_DIRECTORY}/dnsmasq.conf"
PIHOLE_VERSIONS_FILE="${PIHOLE_DIRECTORY}/versions" PIHOLE_VERSIONS_FILE="${PIHOLE_DIRECTORY}/versions"
# Read the value of an FTL config key. The value is printed to stdout.
get_ftl_conf_value() {
local key=$1
# Obtain setting from FTL directly
pihole-FTL --config "${key}"
}
PIHOLE_GRAVITY_DB_FILE="$(get_ftl_conf_value "files.gravity")" PIHOLE_GRAVITY_DB_FILE="$(get_ftl_conf_value "files.gravity")"
PIHOLE_FTL_DB_FILE="$(get_ftl_conf_value "files.database")" PIHOLE_FTL_DB_FILE="$(get_ftl_conf_value "files.database")"
@@ -94,7 +94,7 @@ PIHOLE_FTL_DB_FILE="$(get_ftl_conf_value "files.database")"
PIHOLE_COMMAND="${BIN_DIRECTORY}/pihole" PIHOLE_COMMAND="${BIN_DIRECTORY}/pihole"
PIHOLE_COLTABLE_FILE="${BIN_DIRECTORY}/COL_TABLE" PIHOLE_COLTABLE_FILE="${BIN_DIRECTORY}/COL_TABLE"
FTL_PID="${RUN_DIRECTORY}/pihole-FTL.pid" FTL_PID="$(get_ftl_conf_value "files.pid")"
PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log" PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log"
PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*" PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*"
@@ -202,7 +202,7 @@ compare_local_version_to_git_version() {
if git status &> /dev/null; then if git status &> /dev/null; then
# The current version the user is on # The current version the user is on
local local_version local local_version
local_version=$(git describe --tags --abbrev=0); local_version=$(git describe --tags --abbrev=0 2> /dev/null);
# What branch they are on # What branch they are on
local local_branch local local_branch
local_branch=$(git rev-parse --abbrev-ref HEAD); local_branch=$(git rev-parse --abbrev-ref HEAD);
@@ -213,7 +213,13 @@ compare_local_version_to_git_version() {
local local_status local local_status
local_status=$(git status -s) local_status=$(git status -s)
# echo this information out to the user in a nice format # echo this information out to the user in a nice format
log_write "${TICK} Version: ${local_version}" if [ "${local_version}" ]; then
log_write "${TICK} Version: ${local_version}"
elif [ -n "${DOCKER_VERSION}" ]; then
log_write "${TICK} Version: Pi-hole Docker Container ${COL_BOLD}${DOCKER_VERSION}${COL_NC}"
else
log_write "${CROSS} Version: not detected"
fi
# Print the repo upstreams # Print the repo upstreams
remotes=$(git remote -v) remotes=$(git remote -v)
@@ -290,88 +296,12 @@ check_component_versions() {
check_ftl_version check_ftl_version
} }
os_check() {
# This function gets a list of supported OS versions from a TXT record at versions.pi-hole.net
# and determines whether or not the script is running on one of those systems
local remote_os_domain valid_os valid_version detected_os detected_version cmdResult digReturnCode response
remote_os_domain=${OS_CHECK_DOMAIN_NAME:-"versions.pi-hole.net"}
detected_os=$(grep "\bID\b" /etc/os-release | cut -d '=' -f2 | tr -d '"')
detected_version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f2 | tr -d '"')
cmdResult="$(dig -4 +short -t txt "${remote_os_domain}" @ns1.pi-hole.net 2>&1; echo $?)"
#Get the return code of the previous command (last line)
digReturnCode="${cmdResult##*$'\n'}"
# Extract dig response
response="${cmdResult%%$'\n'*}"
if [ "${digReturnCode}" -ne 0 ]; then
log_write "${INFO} Distro: ${detected_os^}"
log_write "${INFO} Version: ${detected_version}"
log_write "${CROSS} dig IPv4 return code: ${COL_RED}${digReturnCode}${COL_NC}"
log_write "${CROSS} dig response: ${response}"
log_write "${INFO} Retrying via IPv6"
cmdResult="$(dig -6 +short -t txt "${remote_os_domain}" @ns1.pi-hole.net 2>&1; echo $?)"
#Get the return code of the previous command (last line)
digReturnCode="${cmdResult##*$'\n'}"
# Extract dig response
response="${cmdResult%%$'\n'*}"
fi
# If also no success via IPv6
if [ "${digReturnCode}" -ne 0 ]; then
log_write "${CROSS} dig IPv6 return code: ${COL_RED}${digReturnCode}${COL_NC}"
log_write "${CROSS} dig response: ${response}"
log_write "${CROSS} Error: ${COL_RED}dig command failed - Unable to check OS${COL_NC}"
else
IFS=" " read -r -a supportedOS < <(echo "${response}" | tr -d '"')
for distro_and_versions in "${supportedOS[@]}"
do
distro_part="${distro_and_versions%%=*}"
versions_part="${distro_and_versions##*=}"
if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then
valid_os=true
IFS="," read -r -a supportedVer <<<"${versions_part}"
for version in "${supportedVer[@]}"
do
if [[ "${detected_version}" =~ $version ]]; then
valid_version=true
break
fi
done
break
fi
done
local finalmsg
if [ "$valid_os" = true ]; then
log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}"
if [ "$valid_version" = true ]; then
log_write "${TICK} Version: ${COL_GREEN}${detected_version}${COL_NC}"
finalmsg="${TICK} ${COL_GREEN}Distro and version supported${COL_NC}"
else
log_write "${CROSS} Version: ${COL_RED}${detected_version}${COL_NC}"
finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is supported but version ${detected_version} is currently unsupported ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}"
fi
else
log_write "${CROSS} Distro: ${COL_RED}${detected_os^}${COL_NC}"
finalmsg="${CROSS} Error: ${COL_RED}${detected_os^} is not a supported distro ${COL_NC}(${FAQ_HARDWARE_REQUIREMENTS})${COL_NC}"
fi
# Print dig response and the final check result
log_write "${TICK} dig return code: ${COL_GREEN}${digReturnCode}${COL_NC}"
log_write "${INFO} dig response: ${response}"
log_write "${finalmsg}"
fi
}
diagnose_operating_system() { diagnose_operating_system() {
# error message in a variable so we can easily modify it later (or reuse it) # error message in a variable so we can easily modify it later (or reuse it)
local error_msg="Distribution unknown -- most likely you are on an unsupported platform and may run into issues." local error_msg="Distribution unknown -- most likely you are on an unsupported platform and may run into issues."
local detected_os
local detected_version
# Display the current test that is running # Display the current test that is running
echo_current_diagnostic "Operating system" echo_current_diagnostic "Operating system"
@@ -380,8 +310,13 @@ diagnose_operating_system() {
# If there is a /etc/*release file, it's probably a supported operating system, so we can # If there is a /etc/*release file, it's probably a supported operating system, so we can
if ls /etc/*release 1> /dev/null 2>&1; then if ls /etc/*release 1> /dev/null 2>&1; then
# display the attributes to the user from the function made earlier # display the attributes to the user
os_check
detected_os=$(grep "\bID\b" /etc/os-release | cut -d '=' -f2 | tr -d '"')
detected_version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f2 | tr -d '"')
log_write "${INFO} Distro: ${detected_os^}"
log_write "${INFO} Version: ${detected_version}"
else else
# If it doesn't exist, it's not a system we currently support and link to FAQ # If it doesn't exist, it's not a system we currently support and link to FAQ
log_write "${CROSS} ${COL_RED}${error_msg}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})" log_write "${CROSS} ${COL_RED}${error_msg}${COL_NC} (${FAQ_HARDWARE_REQUIREMENTS})"
@@ -479,7 +414,9 @@ run_and_print_command() {
local output local output
output=$(${cmd} 2>&1) output=$(${cmd} 2>&1)
# If the command was successful, # If the command was successful,
if [[ $? -eq 0 ]]; then local return_code
return_code=$?
if [[ "${return_code}" -eq 0 ]]; then
# show the output # show the output
log_write "${output}" log_write "${output}"
else else
@@ -489,13 +426,25 @@ run_and_print_command() {
} }
hardware_check() { hardware_check() {
# Note: the checks are skipped if Pi-hole is running in a docker container
local skip_msg="${INFO} Not enough permissions inside Docker container ${COL_YELLOW}(skipped)${COL_NC}"
echo_current_diagnostic "System hardware configuration" echo_current_diagnostic "System hardware configuration"
# Store the output of the command in a variable if [ -n "${DOCKER_VERSION}" ]; then
run_and_print_command "lshw -short" log_write "${skip_msg}"
else
# Store the output of the command in a variable
run_and_print_command "lshw -short"
fi
echo_current_diagnostic "Processor details" echo_current_diagnostic "Processor details"
# Store the output of the command in a variable if [ -n "${DOCKER_VERSION}" ]; then
run_and_print_command "lscpu" log_write "${skip_msg}"
else
# Store the output of the command in a variable
run_and_print_command "lscpu"
fi
} }
disk_usage() { disk_usage() {
@@ -808,26 +757,24 @@ dig_at() {
process_status(){ process_status(){
# Check to make sure Pi-hole's services are running and active # Check to make sure Pi-hole's services are running and active
echo_current_diagnostic "Pi-hole processes" echo_current_diagnostic "Pi-hole processes"
# Local iterator # Local iterator
local i local i
# For each process, # For each process,
for i in "${PIHOLE_PROCESSES[@]}"; do for i in "${PIHOLE_PROCESSES[@]}"; do
local status_of_process
# If systemd # If systemd
if command -v systemctl &> /dev/null; then if command -v systemctl &> /dev/null; then
# get its status via systemctl # get its status via systemctl
local status_of_process
status_of_process=$(systemctl is-active "${i}") status_of_process=$(systemctl is-active "${i}")
else else
# Otherwise, use the service command and mock the output of `systemctl is-active` # Otherwise, use the service command and mock the output of `systemctl is-active`
local status_of_process
# If DOCKER_VERSION is set, the output is slightly different (s6 init system on Docker) # If it is a docker container, there is no systemctl or service. Do nothing.
if [ -n "${DOCKER_VERSION}" ]; then if [ -n "${DOCKER_VERSION}" ]; then
if service "${i}" status | grep -E '^up' &> /dev/null; then :
status_of_process="active"
else
status_of_process="inactive"
fi
else else
# non-Docker system # non-Docker system
if service "${i}" status | grep -E 'is\srunning' &> /dev/null; then if service "${i}" status | grep -E 'is\srunning' &> /dev/null; then
@@ -837,8 +784,12 @@ process_status(){
fi fi
fi fi
fi fi
# and print it out to the user # and print it out to the user
if [[ "${status_of_process}" == "active" ]]; then if [ -n "${DOCKER_VERSION}" ]; then
# If it's a Docker container, the test was skipped
log_write "${INFO} systemctl/service not installed inside docker container ${COL_YELLOW}(skipped)${COL_NC}"
elif [[ "${status_of_process}" == "active" ]]; then
# If it's active, show it in green # If it's active, show it in green
log_write "${TICK} ${COL_GREEN}${i}${COL_NC} daemon is ${COL_GREEN}${status_of_process}${COL_NC}" log_write "${TICK} ${COL_GREEN}${i}${COL_NC} daemon is ${COL_GREEN}${status_of_process}${COL_NC}"
else else
@@ -855,6 +806,8 @@ ftl_full_status(){
if command -v systemctl &> /dev/null; then if command -v systemctl &> /dev/null; then
FTL_status=$(systemctl status --full --no-pager pihole-FTL.service) FTL_status=$(systemctl status --full --no-pager pihole-FTL.service)
log_write " ${FTL_status}" log_write " ${FTL_status}"
elif [ -n "${DOCKER_VERSION}" ]; then
log_write "${INFO} systemctl/service not installed inside docker container ${COL_YELLOW}(skipped)${COL_NC}"
else else
log_write "${INFO} systemctl: command not found" log_write "${INFO} systemctl: command not found"
fi fi
@@ -908,7 +861,6 @@ parse_file() {
# Get the lines that are in the file(s) and store them in an array for parsing later # Get the lines that are in the file(s) and store them in an array for parsing later
local file_info local file_info
if [[ -f "$filename" ]]; then if [[ -f "$filename" ]]; then
#shellcheck disable=SC2016
IFS=$'\r\n' command eval 'file_info=( $(cat "${filename}") )' IFS=$'\r\n' command eval 'file_info=( $(cat "${filename}") )'
else else
read -r -a file_info <<< "$filename" read -r -a file_info <<< "$filename"
@@ -1112,7 +1064,7 @@ show_FTL_db_entries() {
} }
check_dhcp_servers() { check_dhcp_servers() {
echo_current_diagnostic "Discovering active DHCP servers (takes 10 seconds)" echo_current_diagnostic "Discovering active DHCP servers (takes 6 seconds)"
OLD_IFS="$IFS" OLD_IFS="$IFS"
IFS=$'\n' IFS=$'\n'
@@ -1196,7 +1148,7 @@ database_integrity_check(){
local database="${1}" local database="${1}"
log_write "${INFO} Checking integrity of ${database} ... (this can take several minutes)" log_write "${INFO} Checking integrity of ${database} ... (this can take several minutes)"
result="$(pihole-FTL "${database}" "PRAGMA integrity_check" 2>&1 & spinner)" result="$(pihole-FTL sqlite3 -ni "${database}" "PRAGMA integrity_check" 2>&1 & spinner)"
if [[ ${result} = "ok" ]]; then if [[ ${result} = "ok" ]]; then
log_write "${TICK} Integrity of ${database} intact" log_write "${TICK} Integrity of ${database} intact"
@@ -1317,19 +1269,16 @@ upload_to_tricorder() {
curl_to_tricorder curl_to_tricorder
# If we're not running in automated mode, # If we're not running in automated mode,
else else
# if not being called from the web interface echo ""
if [[ ! "${WEBCALL}" ]]; then # give the user a choice of uploading it or not
echo "" # Users can review the log file locally (or the output of the script since they are the same) and try to self-diagnose their problem
# give the user a choice of uploading it or not read -r -p "[?] Would you like to upload the log? [y/N] " response
# Users can review the log file locally (or the output of the script since they are the same) and try to self-diagnose their problem case ${response} in
read -r -p "[?] Would you like to upload the log? [y/N] " response # If they say yes, run our function for uploading the log
case ${response} in [yY][eE][sS]|[yY]) curl_to_tricorder;;
# If they say yes, run our function for uploading the log # If they choose no, just exit out of the script
[yY][eE][sS]|[yY]) curl_to_tricorder;; *) log_write " * Log will ${COL_GREEN}NOT${COL_NC} be uploaded to tricorder.\\n * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG}${COL_NC}\\n";exit;
# If they choose no, just exit out of the script esac
*) log_write " * Log will ${COL_GREEN}NOT${COL_NC} be uploaded to tricorder.\\n * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG}${COL_NC}\\n";exit;
esac
fi
fi fi
# Check if tricorder.pi-hole.net is reachable and provide token # Check if tricorder.pi-hole.net is reachable and provide token
# along with some additional useful information # along with some additional useful information
@@ -1349,13 +1298,8 @@ upload_to_tricorder() {
# If no token was generated # If no token was generated
else else
# Show an error and some help instructions # Show an error and some help instructions
# Skip this if being called from web interface and automatic mode was not chosen (users opt-out to upload) log_write "${CROSS} ${COL_RED}There was an error uploading your debug log.${COL_NC}"
if [[ "${WEBCALL}" ]] && [[ ! "${AUTOMATED}" ]]; then log_write " * Please try again or contact the Pi-hole team for assistance."
:
else
log_write "${CROSS} ${COL_RED}There was an error uploading your debug log.${COL_NC}"
log_write " * Please try again or contact the Pi-hole team for assistance."
fi
fi fi
# Finally, show where the log file is no matter the outcome of the function so users can look at it # Finally, show where the log file is no matter the outcome of the function so users can look at it
log_write " * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG}${COL_NC}\\n" log_write " * A local copy of the debug log can be found at: ${COL_CYAN}${PIHOLE_DEBUG_LOG}${COL_NC}\\n"

View File

@@ -9,12 +9,20 @@
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
colfile="/opt/pihole/COL_TABLE" colfile="/opt/pihole/COL_TABLE"
# shellcheck source="./advanced/Scripts/COL_TABLE"
source ${colfile} source ${colfile}
readonly PI_HOLE_SCRIPT_DIR="/opt/pihole" readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source="./advanced/Scripts/utils.sh"
source "${utilsfile}" source "${utilsfile}"
SKIP_INSTALL="true"
# shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# stop_service() is defined in basic-install.sh
# restart_service() is defined in basic-install.sh
# In case we're running at the same time as a system logrotate, use a # In case we're running at the same time as a system logrotate, use a
# separate logrotate state file to prevent stepping on each other's # separate logrotate state file to prevent stepping on each other's
# toes. # toes.
@@ -35,6 +43,46 @@ FTLFILE=$(getFTLConfigValue "files.log.ftl")
if [ -z "$FTLFILE" ]; then if [ -z "$FTLFILE" ]; then
FTLFILE="/var/log/pihole/FTL.log" FTLFILE="/var/log/pihole/FTL.log"
fi fi
WEBFILE=$(getFTLConfigValue "files.log.webserver")
if [ -z "$WEBFILE" ]; then
WEBFILE="/var/log/pihole/webserver.log"
fi
# Helper function to handle log rotation for a single file
rotate_log() {
# This function copies x.log over to x.log.1
# and then empties x.log
# Note that moving the file is not an option, as
# dnsmasq would happily continue writing into the
# moved file (it will have the same file handler)
local logfile="$1"
if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Rotating ${logfile} ..."
fi
cp -p "${logfile}" "${logfile}.1"
echo " " > "${logfile}"
chmod 640 "${logfile}"
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Rotated ${logfile} ..."
fi
}
# Helper function to handle log flushing for a single file
flush_log() {
local logfile="$1"
if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Flushing ${logfile} ..."
fi
echo " " > "${logfile}"
chmod 640 "${logfile}"
if [ -f "${logfile}.1" ]; then
echo " " > "${logfile}.1"
chmod 640 "${logfile}.1"
fi
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Flushed ${logfile} ..."
fi
}
if [[ "$*" == *"once"* ]]; then if [[ "$*" == *"once"* ]]; then
# Nightly logrotation # Nightly logrotation
@@ -46,75 +94,30 @@ if [[ "$*" == *"once"* ]]; then
fi fi
/usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate
else else
# Copy pihole.log over to pihole.log.1 # Handle rotation for each log file
# and empty out pihole.log rotate_log "${LOGFILE}"
# Note that moving the file is not an option, as rotate_log "${FTLFILE}"
# dnsmasq would happily continue writing into the rotate_log "${WEBFILE}"
# moved file (it will have the same file handler)
if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Rotating ${LOGFILE} ..."
fi
cp -p "${LOGFILE}" "${LOGFILE}.1"
echo " " > "${LOGFILE}"
chmod 640 "${LOGFILE}"
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Rotated ${LOGFILE} ..."
fi
# Copy FTL.log over to FTL.log.1
# and empty out FTL.log
if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Rotating ${FTLFILE} ..."
fi
cp -p "${FTLFILE}" "${FTLFILE}.1"
echo " " > "${FTLFILE}"
chmod 640 "${FTLFILE}"
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Rotated ${FTLFILE} ..."
fi
fi fi
else else
# Manual flushing # Manual flushing
flush_log "${LOGFILE}"
# Flush both pihole.log and pihole.log.1 (if existing) flush_log "${FTLFILE}"
if [[ "$*" != *"quiet"* ]]; then flush_log "${WEBFILE}"
echo -ne " ${INFO} Flushing ${LOGFILE} ..."
fi
echo " " > "${LOGFILE}"
chmod 640 "${LOGFILE}"
if [ -f "${LOGFILE}.1" ]; then
echo " " > "${LOGFILE}.1"
chmod 640 "${LOGFILE}.1"
fi
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Flushed ${LOGFILE} ..."
fi
# Flush both FTL.log and FTL.log.1 (if existing)
if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Flushing ${FTLFILE} ..."
fi
echo " " > "${FTLFILE}"
chmod 640 "${FTLFILE}"
if [ -f "${FTLFILE}.1" ]; then
echo " " > "${FTLFILE}.1"
chmod 640 "${FTLFILE}.1"
fi
if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Flushed ${FTLFILE} ..."
fi
if [[ "$*" != *"quiet"* ]]; then if [[ "$*" != *"quiet"* ]]; then
echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..." echo -ne " ${INFO} Flushing database, DNS resolution temporarily unavailable ..."
fi fi
# Stop FTL to make sure it doesn't write to the database while we're deleting data # Stop FTL to make sure it doesn't write to the database while we're deleting data
service pihole-FTL stop stop_service pihole-FTL >/dev/null
# Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history)
deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1") deleted=$(pihole-FTL sqlite3 -ni "${DBFILE}" "DELETE FROM query_storage WHERE timestamp >= strftime('%s','now')-86400; select changes() from query_storage limit 1")
# Restart FTL # Restart FTL
service pihole-FTL restart restart_service pihole-FTL >/dev/null
if [[ "$*" != *"quiet"* ]]; then if [[ "$*" != *"quiet"* ]]; then
echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database" echo -e "${OVER} ${TICK} Deleted ${deleted} queries from long-term query database"
fi fi

View File

@@ -1,9 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC1090
# Ignore warning about `local` being undefinded in POSIX
# shellcheck disable=SC3043
# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2023 Pi-hole, LLC (https://pi-hole.net) # (c) 2023 Pi-hole, LLC (https://pi-hole.net)
@@ -22,9 +17,11 @@ domain=""
# Source color table # Source color table
colfile="/opt/pihole/COL_TABLE" colfile="/opt/pihole/COL_TABLE"
# shellcheck source="./advanced/Scripts/COL_TABLE"
. "${colfile}" . "${colfile}"
# Source api functions # Source api functions
# shellcheck source="./advanced/Scripts/api.sh"
. "${PI_HOLE_INSTALL_DIR}/api.sh" . "${PI_HOLE_INSTALL_DIR}/api.sh"
Help() { Help() {

View File

@@ -12,26 +12,31 @@
# Variables # Variables
readonly ADMIN_INTERFACE_GIT_URL="https://github.com/pi-hole/web.git" readonly ADMIN_INTERFACE_GIT_URL="https://github.com/pi-hole/web.git"
readonly ADMIN_INTERFACE_DIR="/var/www/html/admin"
readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git" readonly PI_HOLE_GIT_URL="https://github.com/pi-hole/pi-hole.git"
readonly PI_HOLE_FILES_DIR="/etc/.pihole" readonly PI_HOLE_FILES_DIR="/etc/.pihole"
# shellcheck disable=SC2034
SKIP_INSTALL=true SKIP_INSTALL=true
# when --check-only is passed to this script, it will not perform the actual update # when --check-only is passed to this script, it will not perform the actual update
CHECK_ONLY=false CHECK_ONLY=false
# shellcheck disable=SC1090 # shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh" source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# shellcheck disable=SC1091 # shellcheck source=./advanced/Scripts/COL_TABLE
source "/opt/pihole/COL_TABLE" source "/opt/pihole/COL_TABLE"
# shellcheck source="./advanced/Scripts/utils.sh"
source "${PI_HOLE_INSTALL_DIR}/utils.sh"
# is_repo() sourced from basic-install.sh # is_repo() sourced from basic-install.sh
# make_repo() sourced from basic-install.sh # make_repo() sourced from basic-install.sh
# update_repo() source from basic-install.sh # update_repo() source from basic-install.sh
# getGitFiles() sourced from basic-install.sh # getGitFiles() sourced from basic-install.sh
# FTLcheckUpdate() sourced from basic-install.sh # FTLcheckUpdate() sourced from basic-install.sh
# getFTLConfigValue() sourced from utils.sh
# Honour configured paths for the web application.
ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
readonly ADMIN_INTERFACE_DIR
GitCheckUpdateAvail() { GitCheckUpdateAvail() {
local directory local directory
@@ -107,6 +112,7 @@ main() {
web_update=false web_update=false
FTL_update=false FTL_update=false
# Install packages used by this installation script (necessary if users have removed e.g. git from their systems) # Install packages used by this installation script (necessary if users have removed e.g. git from their systems)
package_manager_detect package_manager_detect
build_dependency_package build_dependency_package
@@ -206,7 +212,7 @@ main() {
echo "" echo ""
echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo." echo -e " ${INFO} Pi-hole Web Admin files out of date, updating local repo."
getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}" getGitFiles "${ADMIN_INTERFACE_DIR}" "${ADMIN_INTERFACE_GIT_URL}"
echo -e " ${INFO} If you had made any changes in '/var/www/html/admin/', they have been stashed using 'git stash'" echo -e " ${INFO} If you had made any changes in '${ADMIN_INTERFACE_DIR}', they have been stashed using 'git stash'"
fi fi
if [[ "${FTL_update}" == true ]]; then if [[ "${FTL_update}" == true ]]; then
@@ -215,7 +221,7 @@ main() {
fi fi
if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then if [[ "${FTL_update}" == true || "${core_update}" == true ]]; then
${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --reconfigure --unattended || \ ${PI_HOLE_FILES_DIR}/automated\ install/basic-install.sh --repair --unattended || \
echo -e "${basicError}" && exit 1 echo -e "${basicError}" && exit 1
fi fi

View File

@@ -39,9 +39,12 @@ function get_remote_hash() {
} }
# Source the utils file for addOrEditKeyValPair() # Source the utils file for addOrEditKeyValPair()
# shellcheck disable=SC1091 # shellcheck source="./advanced/Scripts/utils.sh"
. /opt/pihole/utils.sh . /opt/pihole/utils.sh
ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
readonly ADMIN_INTERFACE_DIR
# Remove the below three legacy files if they exist # Remove the below three legacy files if they exist
rm -f "/etc/pihole/GitHubVersions" rm -f "/etc/pihole/GitHubVersions"
rm -f "/etc/pihole/localbranches" rm -f "/etc/pihole/localbranches"
@@ -85,13 +88,13 @@ addOrEditKeyValPair "${VERSION_FILE}" "GITHUB_CORE_HASH" "${GITHUB_CORE_HASH}"
# get Web versions # get Web versions
WEB_VERSION="$(get_local_version /var/www/html/admin)" WEB_VERSION="$(get_local_version "${ADMIN_INTERFACE_DIR}")"
addOrEditKeyValPair "${VERSION_FILE}" "WEB_VERSION" "${WEB_VERSION}" addOrEditKeyValPair "${VERSION_FILE}" "WEB_VERSION" "${WEB_VERSION}"
WEB_BRANCH="$(get_local_branch /var/www/html/admin)" WEB_BRANCH="$(get_local_branch "${ADMIN_INTERFACE_DIR}")"
addOrEditKeyValPair "${VERSION_FILE}" "WEB_BRANCH" "${WEB_BRANCH}" addOrEditKeyValPair "${VERSION_FILE}" "WEB_BRANCH" "${WEB_BRANCH}"
WEB_HASH="$(get_local_hash /var/www/html/admin)" WEB_HASH="$(get_local_hash "${ADMIN_INTERFACE_DIR}")"
addOrEditKeyValPair "${VERSION_FILE}" "WEB_HASH" "${WEB_HASH}" addOrEditKeyValPair "${VERSION_FILE}" "WEB_HASH" "${WEB_HASH}"
GITHUB_WEB_VERSION="$(get_remote_version web "${WEB_BRANCH}")" GITHUB_WEB_VERSION="$(get_remote_version web "${WEB_BRANCH}")"

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env sh
# shellcheck disable=SC3043 #https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
@@ -88,8 +87,8 @@ getFTLConfigValue(){
####################### #######################
setFTLConfigValue(){ setFTLConfigValue(){
pihole-FTL --config "${1}" "${2}" >/dev/null pihole-FTL --config "${1}" "${2}" >/dev/null
if [[ $? -eq 5 ]]; then if [ $? -eq 5 ]; then
echo -e " ${CROSS} ${1} set by environment variable. Please unset it to use this function" printf " %s %s set by environment variable. Please unset it to use this function\n" "${CROSS}" "${1}"
exit 5 exit 5
fi fi
} }

View File

@@ -8,20 +8,16 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
# Ignore warning about `local` being undefinded in POSIX # Source the versions file populated by updatechecker.sh
# shellcheck disable=SC3043
# https://github.com/koalaman/shellcheck/wiki/SC3043#exceptions
# Source the versions file poupulated by updatechecker.sh
cachedVersions="/etc/pihole/versions" cachedVersions="/etc/pihole/versions"
if [ -f ${cachedVersions} ]; then if [ -f ${cachedVersions} ]; then
# shellcheck disable=SC1090 # shellcheck source=/dev/null
. "$cachedVersions" . "$cachedVersions"
else else
echo "Could not find /etc/pihole/versions. Running update now." echo "Could not find /etc/pihole/versions. Running update now."
pihole updatechecker pihole updatechecker
# shellcheck disable=SC1090 # shellcheck source=/dev/null
. "$cachedVersions" . "$cachedVersions"
fi fi

View File

@@ -43,8 +43,8 @@ CREATE TABLE adlist
CREATE TABLE adlist_by_group CREATE TABLE adlist_by_group
( (
adlist_id INTEGER NOT NULL REFERENCES adlist (id), adlist_id INTEGER NOT NULL REFERENCES adlist (id) ON DELETE CASCADE,
group_id INTEGER NOT NULL REFERENCES "group" (id), group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE,
PRIMARY KEY (adlist_id, group_id) PRIMARY KEY (adlist_id, group_id)
); );
@@ -67,11 +67,16 @@ CREATE TABLE info
); );
INSERT INTO "info" VALUES('version','19'); INSERT INTO "info" VALUES('version','19');
/* This is a flag to indicate if gravity was restored from a backup
false = not restored,
failed = restoration failed due to no backup
other string = restoration successful with the string being the backup file used */
INSERT INTO "info" VALUES('gravity_restored','false');
CREATE TABLE domainlist_by_group CREATE TABLE domainlist_by_group
( (
domainlist_id INTEGER NOT NULL REFERENCES domainlist (id), domainlist_id INTEGER NOT NULL REFERENCES domainlist (id) ON DELETE CASCADE,
group_id INTEGER NOT NULL REFERENCES "group" (id), group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE,
PRIMARY KEY (domainlist_id, group_id) PRIMARY KEY (domainlist_id, group_id)
); );
@@ -86,8 +91,8 @@ CREATE TABLE client
CREATE TABLE client_by_group CREATE TABLE client_by_group
( (
client_id INTEGER NOT NULL REFERENCES client (id), client_id INTEGER NOT NULL REFERENCES client (id) ON DELETE CASCADE,
group_id INTEGER NOT NULL REFERENCES "group" (id), group_id INTEGER NOT NULL REFERENCES "group" (id) ON DELETE CASCADE,
PRIMARY KEY (client_id, group_id) PRIMARY KEY (client_id, group_id)
); );

View File

@@ -3,7 +3,7 @@
# Source utils.sh for getFTLConfigValue() # Source utils.sh for getFTLConfigValue()
PI_HOLE_SCRIPT_DIR='/opt/pihole' PI_HOLE_SCRIPT_DIR='/opt/pihole'
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090 # shellcheck source="./advanced/Scripts/utils.sh"
. "${utilsfile}" . "${utilsfile}"
# Get file paths # Get file paths

View File

@@ -3,32 +3,32 @@
# Source utils.sh for getFTLConfigValue() # Source utils.sh for getFTLConfigValue()
PI_HOLE_SCRIPT_DIR='/opt/pihole' PI_HOLE_SCRIPT_DIR='/opt/pihole'
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090 # shellcheck source="./advanced/Scripts/utils.sh"
. "${utilsfile}" . "${utilsfile}"
# Get file paths # Get file paths
FTL_PID_FILE="$(getFTLConfigValue files.pid)" FTL_PID_FILE="$(getFTLConfigValue files.pid)"
# Ensure that permissions are set so that pihole-FTL can edit all necessary files # Ensure that permissions are set so that pihole-FTL can edit all necessary files
# shellcheck disable=SC2174 mkdir -p /var/log/pihole
mkdir -pm 0640 /var/log/pihole chown -R pihole:pihole /etc/pihole/ /var/log/pihole/
chown -R pihole:pihole /etc/pihole /var/log/pihole
chmod -R 0640 /var/log/pihole
chmod -R 0660 /etc/pihole
# Logrotate config file need to be owned by root and must not be writable by group and others # allow all users read version file (and use pihole -v)
chown root:root /etc/pihole/logrotate chmod 0644 /etc/pihole/versions
chmod 0644 /etc/pihole/logrotate
# allow all users to enter the directories
chmod 0755 /etc/pihole /var/log/pihole
# allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs) # allow pihole to access subdirs in /etc/pihole (sets execution bit on dirs)
# credits https://stackoverflow.com/a/11512211 find /etc/pihole/ /var/log/pihole/ -type d -exec chmod 0755 {} +
find /etc/pihole -type d -exec chmod 0755 {} \; # Set all files (except TLS-related ones) to u+rw g+r
find /etc/pihole/ /var/log/pihole/ -type f ! \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0640 {} +
# Set TLS-related files to a more restrictive u+rw *only* (they may contain private keys)
find /etc/pihole/ -type f \( -name '*.pem' -o -name '*.crt' \) -exec chmod 0600 {} +
# Logrotate config file need to be owned by root
chown root:root /etc/pihole/logrotate
# Touch files to ensure they exist (create if non-existing, preserve if existing) # Touch files to ensure they exist (create if non-existing, preserve if existing)
[ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" [ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}"
[ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log [ -f /var/log/pihole/FTL.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log
[ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log [ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log
[ -f /var/log/pihole/webserver.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/webserver.log
[ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases [ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases

View File

@@ -12,7 +12,7 @@
# Source utils.sh for getFTLConfigValue(), getFTLPID() # Source utils.sh for getFTLConfigValue(), getFTLPID()
PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_SCRIPT_DIR="/opt/pihole"
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090 # shellcheck source="./advanced/Scripts/utils.sh"
. "${utilsfile}" . "${utilsfile}"
@@ -57,13 +57,16 @@ start() {
stop() { stop() {
if is_running; then if is_running; then
kill "${FTL_PID}" kill "${FTL_PID}"
for i in 1 2 3 4 5; do # Give FTL 60 seconds to gracefully stop
i=1
while [ "${i}" -le 60 ]; do
if ! is_running; then if ! is_running; then
break break
fi fi
printf "." printf "."
sleep 1 sleep 1
i=$((i + 1))
done done
echo echo

View File

@@ -28,7 +28,7 @@ ExecReload=/bin/kill -HUP $MAINPID
ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh
# Use graceful shutdown with a reasonable timeout # Use graceful shutdown with a reasonable timeout
TimeoutStopSec=10s TimeoutStopSec=60s
# Make /usr, /boot, /etc and possibly some more folders read-only... # Make /usr, /boot, /etc and possibly some more folders read-only...
ProtectSystem=full ProtectSystem=full

View File

@@ -7,7 +7,7 @@ _pihole() {
case "${prev}" in case "${prev}" in
"pihole") "pihole")
opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query reconfigure regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api" opts="allow allow-regex allow-wild deny checkout debug disable enable flush help logging query repair regex reloaddns reloadlists status tail uninstall updateGravity updatePihole version wildcard arpflush api"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
;; ;;
"allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild") "allow"|"deny"|"wildcard"|"regex"|"allow-regex"|"allow-wild")

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,18 @@
# This file is copyright under the latest version of the EUPL. # This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license. # Please see LICENSE file for your rights under this license.
# shellcheck source="./advanced/Scripts/COL_TABLE"
source "/opt/pihole/COL_TABLE" source "/opt/pihole/COL_TABLE"
# shellcheck source="./advanced/Scripts/utils.sh"
source "/opt/pihole/utils.sh"
SKIP_INSTALL="true"
# shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/automated install/basic-install.sh"
# stop_service() is defined in basic-install.sh
ADMIN_INTERFACE_DIR=$(getFTLConfigValue "webserver.paths.webroot")$(getFTLConfigValue "webserver.paths.webhome")
readonly ADMIN_INTERFACE_DIR
while true; do while true; do
read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer read -rp " ${QST} Are you sure you would like to remove ${COL_WHITE}Pi-hole${COL_NC}? [y/N] " answer
@@ -37,6 +48,7 @@ fi
readonly PI_HOLE_FILES_DIR="/etc/.pihole" readonly PI_HOLE_FILES_DIR="/etc/.pihole"
SKIP_INSTALL="true" SKIP_INSTALL="true"
# shellcheck source="./automated install/basic-install.sh"
source "${PI_HOLE_FILES_DIR}/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() sourced from basic-install.sh
@@ -53,17 +65,9 @@ removeMetaPackage() {
} }
removePiholeFiles() { removePiholeFiles() {
# Only web directories/files that are created by Pi-hole should be removed # Remove the web interface of Pi-hole
echo -ne " ${INFO} Removing Web Interface..." echo -ne " ${INFO} Removing Web Interface..."
${SUDO} rm -rf /var/www/html/admin &> /dev/null ${SUDO} rm -rf "${ADMIN_INTERFACE_DIR}" &> /dev/null
# If the web directory is empty after removing these files, then the parent html directory can be removed.
if [ -d "/var/www/html" ]; then
if [[ ! "$(ls -A /var/www/html)" ]]; then
${SUDO} rm -rf /var/www/html &> /dev/null
fi
fi
echo -e "${OVER} ${TICK} Removed Web Interface" echo -e "${OVER} ${TICK} Removed Web Interface"
# Attempt to preserve backwards compatibility with older versions # Attempt to preserve backwards compatibility with older versions
@@ -94,19 +98,16 @@ removePiholeFiles() {
echo -e " ${TICK} Removed config files" echo -e " ${TICK} Removed config files"
# Restore Resolved # Restore Resolved
if [[ -e /etc/systemd/resolved.conf.orig ]]; then 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 ${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 systemctl reload-or-restart systemd-resolved
fi fi
# Remove FTL # Remove FTL
if command -v pihole-FTL &> /dev/null; then if command -v pihole-FTL &> /dev/null; then
echo -ne " ${INFO} Removing pihole-FTL..." echo -ne " ${INFO} Removing pihole-FTL..."
if [[ -x "$(command -v systemctl)" ]]; then stop_service pihole-FTL
systemctl stop pihole-FTL
else
service pihole-FTL stop
fi
${SUDO} rm -f /etc/systemd/system/pihole-FTL.service ${SUDO} rm -f /etc/systemd/system/pihole-FTL.service
if [[ -d '/etc/systemd/system/pihole-FTL.service.d' ]]; then 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 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

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC1090
# Pi-hole: A black hole for Internet advertisements # Pi-hole: A black hole for Internet advertisements
# (c) 2017 Pi-hole, LLC (https://pi-hole.net) # (c) 2017 Pi-hole, LLC (https://pi-hole.net)
@@ -16,13 +15,13 @@ export LC_ALL=C
PI_HOLE_SCRIPT_DIR="/opt/pihole" PI_HOLE_SCRIPT_DIR="/opt/pihole"
# Source utils.sh for GetFTLConfigValue # Source utils.sh for GetFTLConfigValue
utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck disable=SC1090 # shellcheck source=./advanced/Scripts/utils.sh
. "${utilsfile}" . "${utilsfile}"
coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" coltable="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
# shellcheck disable=SC1090 # shellcheck source=./advanced/Scripts/COL_TABLE
. "${coltable}" . "${coltable}"
# shellcheck disable=SC1091 # shellcheck source=./advanced/Scripts/database_migration/gravity-db.sh
. "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh" . "/etc/.pihole/advanced/Scripts/database_migration/gravity-db.sh"
basename="pihole" basename="pihole"
@@ -30,6 +29,9 @@ PIHOLE_COMMAND="/usr/local/bin/${basename}"
piholeDir="/etc/${basename}" piholeDir="/etc/${basename}"
# Gravity aux files directory
listsCacheDir="${piholeDir}/listsCache"
# Legacy (pre v5.0) list file locations # Legacy (pre v5.0) list file locations
whitelistFile="${piholeDir}/whitelist.txt" whitelistFile="${piholeDir}/whitelist.txt"
blacklistFile="${piholeDir}/blacklist.txt" blacklistFile="${piholeDir}/blacklist.txt"
@@ -44,6 +46,7 @@ gravityDBcopy="${piholeGitDir}/advanced/Templates/gravity_copy.sql"
domainsExtension="domains" domainsExtension="domains"
curl_connect_timeout=10 curl_connect_timeout=10
etag_support=false
# Check gravity temp directory # Check gravity temp directory
if [ ! -d "${GRAVITY_TMPDIR}" ] || [ ! -w "${GRAVITY_TMPDIR}" ]; then if [ ! -d "${GRAVITY_TMPDIR}" ] || [ ! -w "${GRAVITY_TMPDIR}" ]; then
@@ -54,10 +57,12 @@ fi
# Set this only after sourcing pihole-FTL.conf as the gravity database path may # Set this only after sourcing pihole-FTL.conf as the gravity database path may
# have changed # have changed
gravityDBfile="${GRAVITYDB}" gravityDBfile="${GRAVITYDB}"
gravityDBfile_default="/etc/pihole/gravity.db" gravityDBfile_default="${piholeDir}/gravity.db"
gravityTEMPfile="${GRAVITYDB}_temp" gravityTEMPfile="${GRAVITYDB}_temp"
gravityDIR="$(dirname -- "${gravityDBfile}")" gravityDIR="$(dirname -- "${gravityDBfile}")"
gravityOLDfile="${gravityDIR}/gravity_old.db" gravityOLDfile="${gravityDIR}/gravity_old.db"
gravityBCKdir="${gravityDIR}/gravity_backups"
gravityBCKfile="${gravityBCKdir}/gravity.db"
fix_owner_permissions() { fix_owner_permissions() {
# Fix ownership and permissions for the specified file # Fix ownership and permissions for the specified file
@@ -91,11 +96,21 @@ gravity_build_tree() {
if [[ "${status}" -ne 0 ]]; then if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to build gravity tree in ${gravityTEMPfile}\\n ${output}" echo -e "\\n ${CROSS} Unable to build gravity tree in ${gravityTEMPfile}\\n ${output}"
echo -e " ${INFO} If you have a large amount of domains, make sure your Pi-hole has enough RAM available\\n"
return 1 return 1
fi fi
echo -e "${OVER} ${TICK} ${str}" echo -e "${OVER} ${TICK} ${str}"
} }
# Rotate gravity backup files
rotate_gravity_backup() {
for i in {9..1}; do
if [ -f "${gravityBCKfile}.${i}" ]; then
mv "${gravityBCKfile}.${i}" "${gravityBCKfile}.$((i + 1))"
fi
done
}
# Copy data from old to new database file and swap them # Copy data from old to new database file and swap them
gravity_swap_databases() { gravity_swap_databases() {
str="Swapping databases" str="Swapping databases"
@@ -111,10 +126,32 @@ gravity_swap_databases() {
oldAvail=false oldAvail=false
if [ "${availableBlocks}" -gt "$((gravityBlocks * 2))" ] && [ -f "${gravityDBfile}" ]; then if [ "${availableBlocks}" -gt "$((gravityBlocks * 2))" ] && [ -f "${gravityDBfile}" ]; then
oldAvail=true oldAvail=true
mv "${gravityDBfile}" "${gravityOLDfile}" cp -p "${gravityDBfile}" "${gravityOLDfile}"
else
rm "${gravityDBfile}"
fi fi
# Drop the gravity and antigravity tables + subsequent VACUUM the current
# database for compaction
output=$({ printf ".timeout 30000\\nDROP TABLE IF EXISTS gravity;\\nDROP TABLE IF EXISTS antigravity;\\nVACUUM;\\n" | pihole-FTL sqlite3 -ni "${gravityDBfile}"; } 2>&1)
status="$?"
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to clean current database for backup\\n ${output}"
else
# Check if the backup directory exists
if [ ! -d "${gravityBCKdir}" ]; then
mkdir -p "${gravityBCKdir}" && chown pihole:pihole "${gravityBCKdir}"
fi
# If multiple gravityBCKfile's are present (appended with a number), rotate them
# We keep at most 10 backups
rotate_gravity_backup
# Move the old database to the backup location
mv "${gravityDBfile}" "${gravityBCKfile}.1"
fi
# Move the new database to the correct location
mv "${gravityTEMPfile}" "${gravityDBfile}" mv "${gravityTEMPfile}" "${gravityDBfile}"
echo -e "${OVER} ${TICK} ${str}" echo -e "${OVER} ${TICK} ${str}"
@@ -268,7 +305,7 @@ migrate_to_database() {
fi fi
# Check if gravity database needs to be updated # Check if gravity database needs to be updated
upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" upgrade_gravityDB "${gravityDBfile}"
# Migrate list files to new database # Migrate list files to new database
if [ -e "${adListFile}" ]; then if [ -e "${adListFile}" ]; then
@@ -296,7 +333,7 @@ migrate_to_database() {
fi fi
# Check if gravity database needs to be updated # Check if gravity database needs to be updated
upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" upgrade_gravityDB "${gravityDBfile}"
} }
# Determine if DNS resolution is available before proceeding # Determine if DNS resolution is available before proceeding
@@ -311,17 +348,72 @@ gravity_CheckDNSResolutionAvailable() {
echo -e " ${CROSS} DNS resolution is currently unavailable" echo -e " ${CROSS} DNS resolution is currently unavailable"
fi fi
str="Waiting until DNS resolution is available..." str="Waiting up to 120 seconds for DNS resolution..."
echo -ne " ${INFO} ${str}" echo -ne " ${INFO} ${str}"
until getent hosts github.com &> /dev/null; do
# Append one dot for each second waiting # Default DNS timeout is two seconds, plus 1 second for each dot > 120 seconds
str="${str}." for ((i = 0; i < 40; i++)); do
echo -ne " ${OVER} ${INFO} ${str}" if getent hosts github.com &> /dev/null; then
sleep 1 # If we reach this point, DNS resolution is available
echo -e "${OVER} ${TICK} DNS resolution is available"
return 0
fi
# Append one dot for each second waiting
echo -ne "."
sleep 1
done done
# If we reach this point, DNS resolution is available # DNS resolution is still unavailable after 120 seconds
echo -e "${OVER} ${TICK} DNS resolution is available" return 1
}
# Function: try_restore_backup
# Description: Attempts to restore the previous Pi-hole gravity database from a
# backup file. If a backup exists, it copies the backup to the
# gravity database file and prepares a new gravity database. If the
# restoration is successful, it returns 0. Otherwise, it returns 1.
# Returns:
# 0 - If the backup is successfully restored.
# 1 - If no backup is available or if the restoration fails.
try_restore_backup () {
local num filename timestamp
num=$1
filename="${gravityBCKfile}.${num}"
# Check if a backup exists
if [ -f "${filename}" ]; then
echo -e " ${INFO} Attempting to restore previous database from backup no. ${num}"
cp "${filename}" "${gravityDBfile}"
# If the backup was successfully copied, prepare a new gravity database from
# it
if [ -f "${gravityDBfile}" ]; then
output=$({ pihole-FTL sqlite3 -ni "${gravityTEMPfile}" <<<"${copyGravity}"; } 2>&1)
status="$?"
# Error checking
if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
gravity_Cleanup "error"
fi
# Get the timestamp of the backup file in a human-readable format
# Note that this timestamp will be in the server timezone, this may be
# GMT, e.g., on a Raspberry Pi where the default timezone has never been
# changed
timestamp=$(date -r "${filename}" "+%Y-%m-%d %H:%M:%S %Z")
# Add a record to the info table to indicate that the gravity database was restored
pihole-FTL sqlite3 "${gravityTEMPfile}" "INSERT OR REPLACE INTO info (property,value) values ('gravity_restored','${timestamp}');"
echo -e " ${TICK} Successfully restored from backup (${gravityBCKfile}.${num} at ${timestamp})"
return 0
else
echo -e " ${CROSS} Unable to restore backup no. ${num}"
fi
fi
echo -e " ${CROSS} Backup no. ${num} not available"
return 1
} }
# Retrieve blocklist URLs and parse domains from adlist.list # Retrieve blocklist URLs and parse domains from adlist.list
@@ -332,33 +424,7 @@ gravity_DownloadBlocklists() {
echo -e " ${INFO} Storing gravity database in ${COL_BOLD}${gravityDBfile}${COL_NC}" echo -e " ${INFO} Storing gravity database in ${COL_BOLD}${gravityDBfile}${COL_NC}"
fi fi
# Retrieve source URLs from gravity database local url domain str compression adlist_type directory success
# We source only enabled adlists, SQLite3 stores boolean values as 0 (false) or 1 (true)
mapfile -t sources <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2>/dev/null)"
mapfile -t sourceIDs <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT id FROM vw_adlist;" 2>/dev/null)"
mapfile -t sourceTypes <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT type FROM vw_adlist;" 2>/dev/null)"
# Parse source domains from $sources
mapfile -t sourceDomains <<<"$(
# Logic: Split by folder/port
awk -F '[/:]' '{
# Remove URL protocol & optional username:password@
gsub(/(.*:\/\/|.*:.*@)/, "", $0)
if(length($1)>0){print $1}
else {print "local"}
}' <<<"$(printf '%s\n' "${sources[@]}")" 2>/dev/null
)"
local str="Pulling blocklist source list into range"
echo -e "${OVER} ${TICK} ${str}"
if [[ -z "${sources[*]}" ]] || [[ -z "${sourceDomains[*]}" ]]; then
echo -e " ${INFO} No source list found, or it is empty"
echo ""
unset sources
fi
local url domain str target compression adlist_type directory
echo "" echo ""
# Prepare new gravity database # Prepare new gravity database
@@ -390,10 +456,55 @@ gravity_DownloadBlocklists() {
if [[ "${status}" -ne 0 ]]; then if [[ "${status}" -ne 0 ]]; then
echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}" echo -e "\\n ${CROSS} Unable to copy data from ${gravityDBfile} to ${gravityTEMPfile}\\n ${output}"
return 1
# Try to attempt a backup restore
success=false
if [[ -d "${gravityBCKdir}" ]]; then
for i in {1..10}; do
if try_restore_backup "${i}"; then
success=true
break
fi
done
fi
# If none of the attempts worked, return 1
if [[ "${success}" == false ]]; then
pihole-FTL sqlite3 "${gravityTEMPfile}" "INSERT OR REPLACE INTO info (property,value) values ('gravity_restored','failed');"
return 1
fi
echo -e " ${TICK} ${str}"
else
echo -e "${OVER} ${TICK} ${str}"
fi fi
# Retrieve source URLs from gravity database
# We source only enabled adlists, SQLite3 stores boolean values as 0 (false) or 1 (true)
mapfile -t sources <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT address FROM vw_adlist;" 2>/dev/null)"
mapfile -t sourceIDs <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT id FROM vw_adlist;" 2>/dev/null)"
mapfile -t sourceTypes <<<"$(pihole-FTL sqlite3 -ni "${gravityDBfile}" "SELECT type FROM vw_adlist;" 2>/dev/null)"
# Parse source domains from $sources
mapfile -t sourceDomains <<<"$(
# Logic: Split by folder/port
awk -F '[/:]' '{
# Remove URL protocol & optional username:password@
gsub(/(.*:\/\/|.*:.*@)/, "", $0)
if(length($1)>0){print $1}
else {print "local"}
}' <<<"$(printf '%s\n' "${sources[@]}")" 2>/dev/null
)"
local str="Pulling blocklist source list into range"
echo -e "${OVER} ${TICK} ${str}" echo -e "${OVER} ${TICK} ${str}"
if [[ -z "${sources[*]}" ]] || [[ -z "${sourceDomains[*]}" ]]; then
echo -e " ${INFO} No source list found, or it is empty"
echo ""
unset sources
fi
# Use compression to reduce the amount of data that is transferred # Use compression to reduce the amount of data that is transferred
# between the Pi-hole and the ad list provider. Use this feature # between the Pi-hole and the ad list provider. Use this feature
# only if it is supported by the locally available version of curl # only if it is supported by the locally available version of curl
@@ -404,6 +515,15 @@ gravity_DownloadBlocklists() {
compression="" compression=""
echo -e " ${INFO} Libz compression not available\n" echo -e " ${INFO} Libz compression not available\n"
fi fi
# Check if etag is supported by the locally available version of curl
# (available as of curl 7.68.0, released Jan 2020)
# https://github.com/curl/curl/pull/4543 +
# https://github.com/curl/curl/pull/4678
if curl --help all | grep -q "etag-save"; then
etag_support=true
fi
# Loop through $sources and download each one # Loop through $sources and download each one
for ((i = 0; i < "${#sources[@]}"; i++)); do for ((i = 0; i < "${#sources[@]}"; i++)); do
url="${sources[$i]}" url="${sources[$i]}"
@@ -420,8 +540,8 @@ gravity_DownloadBlocklists() {
fi fi
# Save the file as list.#.domain # Save the file as list.#.domain
saveLocation="${piholeDir}/list.${id}.${domain}.${domainsExtension}" saveLocation="${listsCacheDir}/list.${id}.${domain}.${domainsExtension}"
activeDomains[$i]="${saveLocation}" activeDomains[i]="${saveLocation}"
# Check if we can write to the save location file without actually creating # Check if we can write to the save location file without actually creating
# it (in case it doesn't exist) # it (in case it doesn't exist)
@@ -453,12 +573,12 @@ gravity_DownloadBlocklists() {
if [[ "${check_url}" =~ ${regex} ]]; then if [[ "${check_url}" =~ ${regex} ]]; then
echo -e " ${CROSS} Invalid Target" echo -e " ${CROSS} Invalid Target"
else else
timeit gravity_DownloadBlocklistFromUrl "${url}" "${sourceIDs[$i]}" "${saveLocation}" "${target}" "${compression}" "${adlist_type}" "${domain}" timeit gravity_DownloadBlocklistFromUrl "${url}" "${sourceIDs[$i]}" "${saveLocation}" "${compression}" "${adlist_type}" "${domain}"
fi fi
echo "" echo ""
done done
gravity_Blackbody=true DownloadBlocklists_done=true
} }
compareLists() { compareLists() {
@@ -487,8 +607,8 @@ compareLists() {
# Download specified URL and perform checks on HTTP status and file content # Download specified URL and perform checks on HTTP status and file content
gravity_DownloadBlocklistFromUrl() { gravity_DownloadBlocklistFromUrl() {
local url="${1}" adlistID="${2}" saveLocation="${3}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}" local url="${1}" adlistID="${2}" saveLocation="${3}" compression="${4}" gravity_type="${5}" domain="${6}"
local heisenbergCompensator="" listCurlBuffer str httpCode success="" ip cmd_ext local modifiedOptions="" listCurlBuffer str httpCode success="" ip cmd_ext
local file_path permissions ip_addr port blocked=false download=true local file_path permissions ip_addr port blocked=false download=true
# Create temp file to store content on disk instead of RAM # Create temp file to store content on disk instead of RAM
@@ -497,43 +617,42 @@ gravity_DownloadBlocklistFromUrl() {
mv "${listCurlBuffer}" "${listCurlBuffer%.*}.phgpb" mv "${listCurlBuffer}" "${listCurlBuffer%.*}.phgpb"
listCurlBuffer="${listCurlBuffer%.*}.phgpb" listCurlBuffer="${listCurlBuffer%.*}.phgpb"
# Determine if $saveLocation has read permission # For all remote files, we try to determine if the file has changed to skip
if [[ -r "${saveLocation}" && $url != "file"* ]]; then # downloading them whenever possible.
# Have curl determine if a remote file has been modified since last retrieval if [[ $url != "file"* ]]; then
# Uses "Last-Modified" header, which certain web servers do not provide (e.g: raw github urls) # Use the HTTP ETag header to determine if the file has changed if supported
# Note: Don't do this for local files, always download them # by curl. Using ETags is supported by raw.githubusercontent.com URLs.
heisenbergCompensator="-z ${saveLocation}" if [[ "${etag_support}" == true ]]; then
# Save HTTP ETag to the specified file. An ETag is a caching related header,
# usually returned in a response. If no ETag is sent by the server, an empty
# file is created and can later be used consistently.
modifiedOptions="--etag-save ${saveLocation}.etag"
if [[ -f "${saveLocation}.etag" ]]; then
# This option makes a conditional HTTP request for the specific ETag read
# from the given file by sending a custom If-None-Match header using the
# stored ETag. This way, the server will only send the file if it has
# changed since the last request.
modifiedOptions="${modifiedOptions} --etag-compare ${saveLocation}.etag"
fi
fi
# Add If-Modified-Since header to the request if we did already download the
# file once
if [[ -f "${saveLocation}" ]]; then
# Request a file that has been modified later than the given time and
# date. We provide a file here which makes curl use the modification
# timestamp (mtime) of this file.
# Interstingly, this option is not supported by raw.githubusercontent.com
# URLs, however, it is still supported by many older web servers which may
# not support the HTTP ETag method so we keep it as a fallback.
modifiedOptions="${modifiedOptions} -z ${saveLocation}"
fi
fi fi
str="Status:" str="Status:"
echo -ne " ${INFO} ${str} Pending..." echo -ne " ${INFO} ${str} Pending..."
blocked=false blocked=false
case $(getFTLConfigValue dns.blocking.mode) in
"IP-NODATA-AAAA" | "IP")
# Get IP address of this domain
ip="$(dig "${domain}" +short)"
# Check if this IP matches any IP of the system
if [[ -n "${ip}" && $(grep -Ec "inet(|6) ${ip}" <<<"$(ip a)") -gt 0 ]]; then
blocked=true
fi
;;
"NXDOMAIN")
if [[ $(dig "${domain}" | grep "NXDOMAIN" -c) -ge 1 ]]; then
blocked=true
fi
;;
"NODATA")
if [[ $(dig "${domain}" | grep "NOERROR" -c) -ge 1 ]] && [[ -z $(dig +short "${domain}") ]]; then
blocked=true
fi
;;
"NULL" | *)
if [[ $(dig "${domain}" +short | grep "0.0.0.0" -c) -ge 1 ]]; then
blocked=true
fi
;;
esac
# Check if this domain is blocked by Pi-hole but only if the domain is not a # Check if this domain is blocked by Pi-hole but only if the domain is not a
# local file or empty # local file or empty
if [[ $url != "file"* ]] && [[ -n "${domain}" ]]; then if [[ $url != "file"* ]] && [[ -n "${domain}" ]]; then
@@ -631,8 +750,9 @@ gravity_DownloadBlocklistFromUrl() {
fi fi
if [[ "${download}" == true ]]; then if [[ "${download}" == true ]]; then
# See https://github.com/pi-hole/pi-hole/issues/6159 for justification of the below disable directive
# shellcheck disable=SC2086 # shellcheck disable=SC2086
httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${heisenbergCompensator} -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null) httpCode=$(curl --connect-timeout ${curl_connect_timeout} -s -L ${compression} ${cmd_ext} ${modifiedOptions} -w "%{http_code}" "${url}" -o "${listCurlBuffer}" 2>/dev/null)
fi fi
case $url in case $url in
@@ -675,20 +795,21 @@ gravity_DownloadBlocklistFromUrl() {
# Determine if the blocklist was downloaded and saved correctly # Determine if the blocklist was downloaded and saved correctly
if [[ "${success}" == true ]]; then if [[ "${success}" == true ]]; then
if [[ "${httpCode}" == "304" ]]; then if [[ "${httpCode}" == "304" ]]; then
# Set list status to "unchanged/cached"
database_adlist_status "${adlistID}" "2"
# Add domains to database table file # Add domains to database table file
pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
database_adlist_status "${adlistID}" "2"
done="true" done="true"
# Check if $listCurlBuffer is a non-zero length file # Check if $listCurlBuffer is a non-zero length file
elif [[ -s "${listCurlBuffer}" ]]; then elif [[ -s "${listCurlBuffer}" ]]; then
# Determine if blocklist is non-standard and parse as appropriate # Move the downloaded list to the final location
gravity_ParseFileIntoDomains "${listCurlBuffer}" "${saveLocation}" mv "${listCurlBuffer}" "${saveLocation}"
# Remove curl buffer file after its use # Ensure the file has the correct permissions
rm "${listCurlBuffer}" fix_owner_permissions "${saveLocation}"
# Compare lists if they are identical
compareLists "${adlistID}" "${saveLocation}"
# Add domains to database table file # Add domains to database table file
pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
# Compare lists, are they identical?
compareLists "${adlistID}" "${saveLocation}"
done="true" done="true"
else else
# Fall back to previously cached list if $listCurlBuffer is empty # Fall back to previously cached list if $listCurlBuffer is empty
@@ -701,9 +822,10 @@ gravity_DownloadBlocklistFromUrl() {
# Determine if cached list has read permission # Determine if cached list has read permission
if [[ -r "${saveLocation}" ]]; then if [[ -r "${saveLocation}" ]]; then
echo -e " ${CROSS} List download failed: ${COL_LIGHT_GREEN}using previously cached list${COL_NC}" echo -e " ${CROSS} List download failed: ${COL_LIGHT_GREEN}using previously cached list${COL_NC}"
# Set list status to "download-failed/cached"
database_adlist_status "${adlistID}" "3"
# Add domains to database table file # Add domains to database table file
pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}" pihole-FTL "${gravity_type}" parseList "${saveLocation}" "${gravityTEMPfile}" "${adlistID}"
database_adlist_status "${adlistID}" "3"
else else
echo -e " ${CROSS} List download failed: ${COL_LIGHT_RED}no cached list available${COL_NC}" echo -e " ${CROSS} List download failed: ${COL_LIGHT_RED}no cached list available${COL_NC}"
# Manually reset these two numbers because we do not call parseList here # Manually reset these two numbers because we do not call parseList here
@@ -713,37 +835,6 @@ gravity_DownloadBlocklistFromUrl() {
fi fi
} }
# Parse source files into domains format
gravity_ParseFileIntoDomains() {
local src="${1}" destination="${2}"
# Remove comments and print only the domain name
# Most of the lists downloaded are already in hosts file format but the spacing/formatting is not contiguous
# This helps with that and makes it easier to read
# It also helps with debugging so each stage of the script can be researched more in depth
# 1) Convert all characters to lowercase
tr '[:upper:]' '[:lower:]' <"${src}" >"${destination}"
# 2) Remove carriage returns
# 3) Remove lines starting with ! (ABP Comments)
# 4) Remove lines starting with [ (ABP Header)
# 5) Remove lines containing ABP extended CSS selectors ("##", "#$#", "#@#", "#?#") and Adguard JavaScript (#%#) preceded by a letter
# 6) Remove comments (text starting with "#", include possible spaces before the hash sign)
# 7) Remove leading tabs, spaces, etc. (Also removes leading IP addresses)
# 8) Remove empty lines
sed -i -r \
-e 's/\r$//' \
-e 's/\s*!.*//g' \
-e 's/\s*\[.*//g' \
-e '/[a-z]\#[$?@%]{0,3}\#/d' \
-e 's/\s*#.*//g' \
-e 's/^.*\s+//g' \
-e '/^$/d' "${destination}"
fix_owner_permissions "${destination}"
}
# Report number of entries in a table # Report number of entries in a table
gravity_Table_Count() { gravity_Table_Count() {
local table="${1}" local table="${1}"
@@ -764,11 +855,11 @@ gravity_Table_Count() {
gravity_ShowCount() { gravity_ShowCount() {
# Here we use the table "gravity" instead of the view "vw_gravity" for speed. # 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. # It's safe to replace it here, because right after a gravity run both will show the exactly same number of domains.
gravity_Table_Count "gravity" "gravity domains" "" gravity_Table_Count "gravity" "gravity domains"
gravity_Table_Count "vw_blacklist" "exact denied domains" gravity_Table_Count "domainlist WHERE type = 1 AND enabled = 1" "exact denied domains"
gravity_Table_Count "vw_regex_blacklist" "regex denied filters" gravity_Table_Count "domainlist WHERE type = 3 AND enabled = 1" "regex denied filters"
gravity_Table_Count "vw_whitelist" "exact allowed domains" gravity_Table_Count "domainlist WHERE type = 0 AND enabled = 1" "exact allowed domains"
gravity_Table_Count "vw_regex_whitelist" "regex allowed filters" gravity_Table_Count "domainlist WHERE type = 2 AND enabled = 1" "regex allowed filters"
} }
# Trap Ctrl-C # Trap Ctrl-C
@@ -791,13 +882,13 @@ gravity_Cleanup() {
# invalid_domains location # invalid_domains location
rm "${GRAVITY_TMPDIR}"/*.ph-non-domains 2>/dev/null rm "${GRAVITY_TMPDIR}"/*.ph-non-domains 2>/dev/null
# Ensure this function only runs when gravity_SetDownloadOptions() has completed # Ensure this function only runs when gravity_DownloadBlocklists() has completed
if [[ "${gravity_Blackbody:-}" == true ]]; then if [[ "${DownloadBlocklists_done:-}" == true ]]; then
# Remove any unused .domains files # Remove any unused .domains/.etag/.sha files
for file in "${piholeDir}"/*."${domainsExtension}"; do for file in "${listsCacheDir}"/*."${domainsExtension}"; do
# If list is not in active array, then remove it # If list is not in active array, then remove it and all associated files
if [[ ! "${activeDomains[*]}" == *"${file}"* ]]; then if [[ ! "${activeDomains[*]}" == *"${file}"* ]]; then
rm -f "${file}" 2>/dev/null || rm -f "${file}"* 2>/dev/null ||
echo -e " ${CROSS} Failed to remove ${file##*/}" echo -e " ${CROSS} Failed to remove ${file##*/}"
fi fi
done done
@@ -917,11 +1008,33 @@ timeit(){
elapsed_time=$((end_time - start_time)) elapsed_time=$((end_time - start_time))
# Display the elapsed time # Display the elapsed time
printf " %b--> took %d.%03d seconds%b\n" ${COL_BLUE} $((elapsed_time / 1000)) $((elapsed_time % 1000)) ${COL_NC} printf " %b--> took %d.%03d seconds%b\n" "${COL_BLUE}" $((elapsed_time / 1000)) $((elapsed_time % 1000)) "${COL_NC}"
return $ret return $ret
} }
migrate_to_listsCache_dir() {
# If the ${listsCacheDir} directory already exists, this has been done before
if [[ -d "${listsCacheDir}" ]]; then
return
fi
# If not, we need to migrate the old files to the new directory
local str="Migrating the list's cache directory to new location"
echo -ne " ${INFO} ${str}..."
mkdir -p "${listsCacheDir}" && chown pihole:pihole "${listsCacheDir}"
# Move the old files to the new directory
if mv "${piholeDir}"/list.* "${listsCacheDir}/" 2>/dev/null; then
echo -e "${OVER} ${TICK} ${str}"
else
echo -e "${OVER} ${CROSS} ${str}"
fi
# Update the list's paths in the corresponding .sha1 files to the new location
sed -i "s|${piholeDir}/|${listsCacheDir}/|g" "${listsCacheDir}"/*.sha1 2>/dev/null
}
helpFunc() { helpFunc() {
echo "Usage: pihole -g echo "Usage: pihole -g
Update domains from blocklists specified in adlists.list Update domains from blocklists specified in adlists.list
@@ -968,13 +1081,19 @@ for var in "$@"; do
"-t" | "--timeit") timed=true ;; "-t" | "--timeit") timed=true ;;
"-r" | "--repair") repairSelector "$3" ;; "-r" | "--repair") repairSelector "$3" ;;
"-u" | "--upgrade") "-u" | "--upgrade")
upgrade_gravityDB "${gravityDBfile}" "${piholeDir}" upgrade_gravityDB "${gravityDBfile}"
exit 0 exit 0
;; ;;
"-h" | "--help") helpFunc ;; "-h" | "--help") helpFunc ;;
esac esac
done done
# Check if DNS is available, no need to do any database manipulation if we're not able to download adlists
if ! timeit gravity_CheckDNSResolutionAvailable; then
echo -e " ${CROSS} No DNS resolution available. Please contact support."
exit 1
fi
# Remove OLD (backup) gravity file, if it exists # Remove OLD (backup) gravity file, if it exists
if [[ -f "${gravityOLDfile}" ]]; then if [[ -f "${gravityOLDfile}" ]]; then
rm "${gravityOLDfile}" rm "${gravityOLDfile}"
@@ -997,6 +1116,9 @@ if [[ "${recover_database:-}" == true ]]; then
timeit database_recovery "$4" timeit database_recovery "$4"
fi fi
# Migrate scattered list files to the new cache directory
migrate_to_listsCache_dir
# Move possibly existing legacy files to the gravity database # Move possibly existing legacy files to the gravity database
if ! timeit migrate_to_database; then if ! timeit migrate_to_database; then
echo -e " ${CROSS} Unable to migrate to database. Please contact support." echo -e " ${CROSS} Unable to migrate to database. Please contact support."
@@ -1007,16 +1129,11 @@ if [[ "${forceDelete:-}" == true ]]; then
str="Deleting existing list cache" str="Deleting existing list cache"
echo -ne "${INFO} ${str}..." echo -ne "${INFO} ${str}..."
rm /etc/pihole/list.* 2>/dev/null || true rm "${listsCacheDir}/list.*" 2>/dev/null || true
echo -e "${OVER} ${TICK} ${str}" echo -e "${OVER} ${TICK} ${str}"
fi fi
# Gravity downloads blocklists next # Gravity downloads blocklists next
if ! timeit gravity_CheckDNSResolutionAvailable; then
echo -e " ${CROSS} Can not complete gravity update, no DNS is available. Please contact support."
exit 1
fi
if ! gravity_DownloadBlocklists; then if ! gravity_DownloadBlocklists; then
echo -e " ${CROSS} Unable to create gravity database. Please try again later. If the problem persists, please contact support." echo -e " ${CROSS} Unable to create gravity database. Please try again later. If the problem persists, please contact support."
exit 1 exit 1

View File

@@ -23,7 +23,7 @@ pihole -r
.br .br
\fBpihole -g\fR \fBpihole -g\fR
.br .br
\fBpihole\fR -\fBq\fR [options] \fBpihole\fR \fB-q\fR [options]
.br .br
\fBpihole\fR \fB-l\fR (\fBon|off|off noflush\fR) \fBpihole\fR \fB-l\fR (\fBon|off|off noflush\fR)
.br .br
@@ -43,7 +43,7 @@ pihole -r
.br .br
\fBpihole\fR \fBcheckout\fR repo [branch] \fBpihole\fR \fBcheckout\fR repo [branch]
.br .br
\fBpihole\fR \api\fR endpoint \fBpihole\fR \fBapi\fR [verbose] endpoint
.br .br
\fBpihole\fR \fBhelp\fR \fBpihole\fR \fBhelp\fR
.br .br
@@ -234,10 +234,14 @@ Available commands and options:
branchname Update subsystems to the specified branchname branchname Update subsystems to the specified branchname
.br .br
\fBapi\fR endpoint \fBapi\fR [verbose] endpoint
.br .br
Query the Pi-hole API at <endpoint> Query the Pi-hole API at <endpoint>
.br .br
verbose Show authentication and status messages
.br
.SH "EXAMPLE" .SH "EXAMPLE"
Some usage examples Some usage examples
@@ -323,6 +327,11 @@ Switching Pi-hole subsystem branches
Queries FTL for the stats/summary endpoint Queries FTL for the stats/summary endpoint
.br .br
\fBpihole api verbose stats/summary\fR
.br
Same as above, but shows authentication and status messages
.br
.SH "COLOPHON" .SH "COLOPHON"
Get sucked into the latest news and community activity by entering Pi-hole's orbit. Information about Pi-hole, and the latest version of the software can be found at https://pi-hole.net. Get sucked into the latest news and community activity by entering Pi-hole's orbit. Information about Pi-hole, and the latest version of the software can be found at https://pi-hole.net.

41
pihole
View File

@@ -17,13 +17,16 @@ readonly PI_HOLE_SCRIPT_DIR="/opt/pihole"
PI_HOLE_BIN_DIR="/usr/local/bin" PI_HOLE_BIN_DIR="/usr/local/bin"
readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE" readonly colfile="${PI_HOLE_SCRIPT_DIR}/COL_TABLE"
# shellcheck source=./advanced/Scripts/COL_TABLE
source "${colfile}" source "${colfile}"
readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" readonly utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh"
# shellcheck source=./advanced/Scripts/utils.sh
source "${utilsfile}" source "${utilsfile}"
# Source api functions # Source api functions
readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh" readonly apifile="${PI_HOLE_SCRIPT_DIR}/api.sh"
# shellcheck source=./advanced/Scripts/api.sh
source "${apifile}" source "${apifile}"
versionsfile="/etc/pihole/versions" versionsfile="/etc/pihole/versions"
@@ -31,6 +34,7 @@ if [ -f "${versionsfile}" ]; then
# Only source versionsfile if the file exits # Only source versionsfile if the file exits
# fixes a warning during installation where versionsfile does not exist yet # fixes a warning during installation where versionsfile does not exist yet
# but gravity calls `pihole -status` and thereby sourcing the file # but gravity calls `pihole -status` and thereby sourcing the file
# shellcheck source=/dev/null
source "${versionsfile}" source "${versionsfile}"
fi fi
@@ -73,19 +77,17 @@ listFunc() {
debugFunc() { debugFunc() {
local automated local automated
local web
local check_database_integrity local check_database_integrity
# Pull off the `debug` leaving passed call augmentation flags in $1 # Pull off the `debug` leaving passed call augmentation flags in $1
shift shift
for value in "$@"; do for value in "$@"; do
[[ "$value" == *"-a"* ]] && automated="true" [[ "$value" == *"-a"* ]] && automated="true"
[[ "$value" == *"-w"* ]] && web="true"
[[ "$value" == *"-c"* ]] && check_database_integrity="true" [[ "$value" == *"-c"* ]] && check_database_integrity="true"
[[ "$value" == *"--check_database"* ]] && check_database_integrity="true" [[ "$value" == *"--check_database"* ]] && check_database_integrity="true"
done done
AUTOMATED=${automated:-} WEBCALL=${web:-} CHECK_DATABASE=${check_database_integrity:-} "${PI_HOLE_SCRIPT_DIR}"/piholeDebug.sh AUTOMATED=${automated:-} CHECK_DATABASE=${check_database_integrity:-} "${PI_HOLE_SCRIPT_DIR}"/piholeDebug.sh
exit 0 exit 0
} }
@@ -109,11 +111,11 @@ updatePiholeFunc() {
fi fi
} }
reconfigurePiholeFunc() { repairPiholeFunc() {
if [ -n "${DOCKER_VERSION}" ]; then if [ -n "${DOCKER_VERSION}" ]; then
unsupportedFunc unsupportedFunc
else else
/etc/.pihole/automated\ install/basic-install.sh --reconfigure /etc/.pihole/automated\ install/basic-install.sh --repair
exit 0; exit 0;
fi fi
} }
@@ -249,12 +251,14 @@ Time:
data=$(PostFTLData "dns/blocking" "{ \"blocking\": ${1}, \"timer\": ${tt} }") data=$(PostFTLData "dns/blocking" "{ \"blocking\": ${1}, \"timer\": ${tt} }")
# Check the response # Check the response
local extra=" forever" local extra timer
local timer="$(echo "${data}"| jq --raw-output '.timer' )" extra=" forever"
timer="$(echo "${data}"| jq --raw-output '.timer' )"
if [[ "${timer}" != "null" ]]; then if [[ "${timer}" != "null" ]]; then
extra=" for ${timer}s" extra=" for ${timer}s"
fi fi
local str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}" local str
str="Pi-hole $(echo "${data}" | jq --raw-output '.blocking')${extra}"
# Logout from the API # Logout from the API
LogoutAPI LogoutAPI
@@ -377,14 +381,16 @@ statusFunc() {
tailFunc() { tailFunc() {
# Warn user if Pi-hole's logging is disabled # Warn user if Pi-hole's logging is disabled
local logging_enabled=$(getFTLConfigValue dns.queryLogging) local logging_enabled
logging_enabled=$(getFTLConfigValue dns.queryLogging)
if [[ "${logging_enabled}" != "true" ]]; then if [[ "${logging_enabled}" != "true" ]]; then
echo " ${CROSS} Warning: Query logging is disabled" echo " ${CROSS} Warning: Query logging is disabled"
fi fi
echo -e " ${INFO} Press Ctrl-C to exit" echo -e " ${INFO} Press Ctrl-C to exit"
# Get logfile path # Get logfile path
readonly LOGFILE=$(getFTLConfigValue files.log.dnsmasq) readonly LOGFILE
LOGFILE=$(getFTLConfigValue files.log.dnsmasq)
# Strip date from each line # Strip date from each line
# Color blocklist/denylist/wildcard entries as red # Color blocklist/denylist/wildcard entries as red
@@ -400,7 +406,10 @@ tailFunc() {
piholeCheckoutFunc() { piholeCheckoutFunc() {
if [ -n "${DOCKER_VERSION}" ]; then if [ -n "${DOCKER_VERSION}" ]; then
unsupportedFunc echo -e "${CROSS} Function not supported in Docker images"
echo "Please build a custom image following the steps at"
echo "https://github.com/pi-hole/docker-pi-hole?tab=readme-ov-file#building-the-image-locally"
exit 0
else else
if [[ "$2" == "-h" ]] || [[ "$2" == "--help" ]]; then if [[ "$2" == "-h" ]] || [[ "$2" == "--help" ]]; then
echo "Switch Pi-hole subsystems to a different GitHub branch echo "Switch Pi-hole subsystems to a different GitHub branch
@@ -422,6 +431,7 @@ piholeCheckoutFunc() {
exit 0 exit 0
fi fi
#shellcheck source=./advanced/Scripts/piholeCheckout.sh
source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh source "${PI_HOLE_SCRIPT_DIR}"/piholeCheckout.sh
shift shift
checkout "$@" checkout "$@"
@@ -478,11 +488,12 @@ Debugging Options:
Add '-c' or '--check-database' to include a Pi-hole database integrity check Add '-c' or '--check-database' to include a Pi-hole database integrity check
Add '-a' to automatically upload the log to tricorder.pi-hole.net Add '-a' to automatically upload the log to tricorder.pi-hole.net
-f, flush Flush the Pi-hole log -f, flush Flush the Pi-hole log
-r, reconfigure Reconfigure or Repair Pi-hole subsystems -r, repair Repair Pi-hole subsystems
-t, tail [arg] View the live output of the Pi-hole log. -t, tail [arg] View the live output of the Pi-hole log.
Add an optional argument to filter the log Add an optional argument to filter the log
(regular expressions are supported) (regular expressions are supported)
api <endpoint> Query the Pi-hole API at <endpoint> api <endpoint> Query the Pi-hole API at <endpoint>
Precede <endpoint> with 'verbose' option to show authentication and status messages
Options: Options:
@@ -535,7 +546,7 @@ case "${1}" in
"--allow-wild" | "allow-wild" ) need_root=0;; "--allow-wild" | "allow-wild" ) need_root=0;;
"-f" | "flush" ) ;; "-f" | "flush" ) ;;
"-up" | "updatePihole" ) ;; "-up" | "updatePihole" ) ;;
"-r" | "reconfigure" ) ;; "-r" | "repair" ) ;;
"-l" | "logging" ) ;; "-l" | "logging" ) ;;
"uninstall" ) ;; "uninstall" ) ;;
"enable" ) need_root=0;; "enable" ) need_root=0;;
@@ -578,7 +589,7 @@ case "${1}" in
"-d" | "debug" ) debugFunc "$@";; "-d" | "debug" ) debugFunc "$@";;
"-f" | "flush" ) flushFunc "$@";; "-f" | "flush" ) flushFunc "$@";;
"-up" | "updatePihole" ) updatePiholeFunc "$@";; "-up" | "updatePihole" ) updatePiholeFunc "$@";;
"-r" | "reconfigure" ) reconfigurePiholeFunc;; "-r" | "repair" ) repairPiholeFunc;;
"-g" | "updateGravity" ) updateGravityFunc "$@";; "-g" | "updateGravity" ) updateGravityFunc "$@";;
"-l" | "logging" ) piholeLogging "$@";; "-l" | "logging" ) piholeLogging "$@";;
"uninstall" ) uninstallFunc;; "uninstall" ) uninstallFunc;;
@@ -591,6 +602,6 @@ case "${1}" in
"updatechecker" ) shift; updateCheckFunc "$@";; "updatechecker" ) shift; updateCheckFunc "$@";;
"arpflush" ) arpFunc "$@";; "arpflush" ) arpFunc "$@";;
"-t" | "tail" ) tailFunc "$2";; "-t" | "tail" ) tailFunc "$2";;
"api" ) apiFunc "$2";; "api" ) shift; apiFunc "$@";;
* ) helpFunc;; * ) helpFunc;;
esac esac

View File

@@ -0,0 +1,19 @@
FROM quay.io/centos/centos:stream10
# Disable SELinux
RUN echo "SELINUX=disabled" > /etc/selinux/config
RUN yum install -y --allowerasing curl git
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 && \

View File

@@ -1,7 +1,7 @@
FROM quay.io/centos/centos:stream9 FROM quay.io/centos/centos:stream9
# Disable SELinux # Disable SELinux
RUN echo "SELINUX=disabled" > /etc/selinux/config RUN echo "SELINUX=disabled" > /etc/selinux/config
RUN yum install -y --allowerasing curl git initscripts RUN yum install -y --allowerasing curl git
ENV GITDIR=/etc/.pihole ENV GITDIR=/etc/.pihole
ENV SCRIPTDIR=/opt/pihole ENV SCRIPTDIR=/opt/pihole
@@ -15,6 +15,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -12,6 +12,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -12,6 +12,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -1,5 +1,5 @@
FROM fedora:40 FROM fedora:40
RUN dnf install -y git initscripts RUN dnf install -y git
ENV GITDIR=/etc/.pihole ENV GITDIR=/etc/.pihole
ENV SCRIPTDIR=/opt/pihole ENV SCRIPTDIR=/opt/pihole
@@ -13,6 +13,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -1,5 +1,5 @@
FROM fedora:41 FROM fedora:41
RUN dnf install -y git initscripts RUN dnf install -y git
ENV GITDIR=/etc/.pihole ENV GITDIR=/etc/.pihole
ENV SCRIPTDIR=/opt/pihole ENV SCRIPTDIR=/opt/pihole
@@ -13,6 +13,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -1,4 +1,5 @@
FROM buildpack-deps:lunar-scm FROM fedora:42
RUN dnf install -y git gawk
ENV GITDIR=/etc/.pihole ENV GITDIR=/etc/.pihole
ENV SCRIPTDIR=/opt/pihole ENV SCRIPTDIR=/opt/pihole
@@ -7,12 +8,10 @@ RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
ADD . $GITDIR ADD . $GITDIR
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/ 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 ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
ENV DEBIAN_FRONTEND=noninteractive
RUN true && \ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -12,6 +12,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -13,6 +13,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -13,6 +13,5 @@ RUN true && \
chmod +x $SCRIPTDIR/* chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \ #sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -1,6 +1,6 @@
pyyaml == 6.0.2 pyyaml == 6.0.2
pytest == 8.3.4 pytest == 8.3.5
pytest-xdist == 3.6.1 pytest-xdist == 3.6.1
pytest-testinfra == 10.1.1 pytest-testinfra == 10.2.2
tox == 4.23.2 tox == 4.26.0
pytest-clarity == 1.0.1 pytest-clarity == 1.0.1

View File

@@ -66,6 +66,14 @@ def test_installPihole_fresh_install_readableFiles(host):
mock_command("dialog", {"*": ("", "0")}, host) mock_command("dialog", {"*": ("", "0")}, host)
# mock git pull # mock git pull
mock_command_passthrough("git", {"pull": ("", "0")}, host) mock_command_passthrough("git", {"pull": ("", "0")}, host)
# mock PID 1 to pretend to be systemd
mock_command_2(
"ps",
{
"--pid 1": ("systemd", "0"),
},
host,
)
# mock systemctl to not start FTL # mock systemctl to not start FTL
mock_command_2( mock_command_2(
"systemctl", "systemctl",
@@ -73,6 +81,7 @@ def test_installPihole_fresh_install_readableFiles(host):
"enable pihole-FTL": ("", "0"), "enable pihole-FTL": ("", "0"),
"restart pihole-FTL": ("", "0"), "restart pihole-FTL": ("", "0"),
"start pihole-FTL": ("", "0"), "start pihole-FTL": ("", "0"),
"stop pihole-FTL": ("", "0"),
"*": ('echo "systemctl call with $@"', "0"), "*": ('echo "systemctl call with $@"', "0"),
}, },
host, host,
@@ -89,10 +98,10 @@ def test_installPihole_fresh_install_readableFiles(host):
export DEBIAN_FRONTEND=noninteractive export DEBIAN_FRONTEND=noninteractive
umask 0027 umask 0027
runUnattended=true runUnattended=true
useUpdateVars=true fresh_install=false
source /opt/pihole/basic-install.sh > /dev/null source /opt/pihole/basic-install.sh > /dev/null
runUnattended=true runUnattended=true
useUpdateVars=true fresh_install=false
main main
/opt/pihole/pihole-FTL-prestart.sh /opt/pihole/pihole-FTL-prestart.sh
""" """
@@ -119,11 +128,6 @@ def test_installPihole_fresh_install_readableFiles(host):
assert exit_status_success == actual_rc assert exit_status_success == actual_rc
check_leases = test_cmd.format("w", "/etc/pihole/dhcp.leases", piholeuser) check_leases = test_cmd.format("w", "/etc/pihole/dhcp.leases", piholeuser)
actual_rc = host.run(check_leases).rc actual_rc = host.run(check_leases).rc
# readable dns-servers.conf
assert exit_status_success == actual_rc
check_servers = test_cmd.format("r", "/etc/pihole/dns-servers.conf", piholeuser)
actual_rc = host.run(check_servers).rc
assert exit_status_success == actual_rc
# readable install.log # readable install.log
check_install = test_cmd.format("r", "/etc/pihole/install.log", piholeuser) check_install = test_cmd.format("r", "/etc/pihole/install.log", piholeuser)
actual_rc = host.run(check_install).rc actual_rc = host.run(check_install).rc
@@ -132,21 +136,10 @@ def test_installPihole_fresh_install_readableFiles(host):
check_localversion = test_cmd.format("r", "/etc/pihole/versions", piholeuser) check_localversion = test_cmd.format("r", "/etc/pihole/versions", piholeuser)
actual_rc = host.run(check_localversion).rc actual_rc = host.run(check_localversion).rc
assert exit_status_success == actual_rc assert exit_status_success == actual_rc
# readable logrotate
check_logrotate = test_cmd.format("r", "/etc/pihole/logrotate", piholeuser)
actual_rc = host.run(check_logrotate).rc
assert exit_status_success == actual_rc
# readable macvendor.db # readable macvendor.db
check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser) check_macvendor = test_cmd.format("r", "/etc/pihole/macvendor.db", piholeuser)
actual_rc = host.run(check_macvendor).rc actual_rc = host.run(check_macvendor).rc
assert exit_status_success == actual_rc assert exit_status_success == actual_rc
# check readable and executable /etc/init.d/pihole-FTL
check_init = test_cmd.format("x", "/etc/init.d/pihole-FTL", piholeuser)
actual_rc = host.run(check_init).rc
assert exit_status_success == actual_rc
check_init = test_cmd.format("r", "/etc/init.d/pihole-FTL", piholeuser)
actual_rc = host.run(check_init).rc
assert exit_status_success == actual_rc
# check readable and executable manpages # check readable and executable manpages
if maninstalled is True: if maninstalled is True:
check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser) check_man = test_cmd.format("x", "/usr/local/share/man", piholeuser)
@@ -254,6 +247,7 @@ def test_FTL_detect_no_errors(host, arch, detected_string, supported):
{ {
"-A /bin/sh": ("Tag_CPU_arch: " + arch, "0"), "-A /bin/sh": ("Tag_CPU_arch: " + arch, "0"),
"-A /usr/bin/sh": ("Tag_CPU_arch: " + arch, "0"), "-A /usr/bin/sh": ("Tag_CPU_arch: " + arch, "0"),
"-A /usr/sbin/sh": ("Tag_CPU_arch: " + arch, "0"),
}, },
host, host,
) )
@@ -474,50 +468,6 @@ def test_validate_ip(host):
test_address("0.0.0.0#00001", False) test_address("0.0.0.0#00001", False)
def test_os_check_fails(host):
"""Confirms install fails on unsupported OS"""
host.run(
"""
source /opt/pihole/basic-install.sh
package_manager_detect
build_dependency_package
install_dependent_packages
cat <<EOT > /etc/os-release
ID=UnsupportedOS
VERSION_ID="2"
EOT
"""
)
detectOS = host.run(
"""t
source /opt/pihole/basic-install.sh
os_check
"""
)
expected_stdout = "Unsupported OS detected: UnsupportedOS"
assert expected_stdout in detectOS.stdout
def test_os_check_passes(host):
"""Confirms OS meets the requirements"""
host.run(
"""
source /opt/pihole/basic-install.sh
package_manager_detect
build_dependency_package
install_dependent_packages
"""
)
detectOS = host.run(
"""
source /opt/pihole/basic-install.sh
os_check
"""
)
expected_stdout = "Supported OS detected"
assert expected_stdout in detectOS.stdout
def test_package_manager_has_pihole_deps(host): def test_package_manager_has_pihole_deps(host):
"""Confirms OS is able to install the required packages for Pi-hole""" """Confirms OS is able to install the required packages for Pi-hole"""
mock_command("dialog", {"*": ("", "0")}, host) mock_command("dialog", {"*": ("", "0")}, host)

10
test/tox.centos_10.ini Normal file
View File

@@ -0,0 +1,10 @@
[tox]
envlist = py3
[testenv:py3]
allowlist_externals = docker
deps = -rrequirements.txt
setenv =
COLUMNS=120
commands = docker buildx build --load --progress plain -f _centos_10.Dockerfile -t pytest_pihole:test_container ../
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py

10
test/tox.fedora_42.ini Normal file
View File

@@ -0,0 +1,10 @@
[tox]
envlist = py3
[testenv]
allowlist_externals = docker
deps = -rrequirements.txt
setenv =
COLUMNS=120
commands = docker buildx build --load --progress plain -f _fedora_42.Dockerfile -t pytest_pihole:test_container ../
pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py ./test_centos_fedora_common_support.py