Compare commits

...

113 Commits

Author SHA1 Message Date
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
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
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
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
15 changed files with 444 additions and 235 deletions

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

@@ -77,7 +77,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.4.0
with: with:
python-version: "3.10" python-version: "3.10"

View File

@@ -165,15 +165,17 @@ 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
@@ -264,7 +266,8 @@ apiFunc() {
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%???}"

View File

@@ -44,6 +44,14 @@ fi
# shellcheck disable=SC1091 # shellcheck disable=SC1091
. /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)
@@ -346,6 +352,9 @@ os_check() {
fi fi
done done
# If it is a docker container, we can assume the OS is supported
[ -n "${DOCKER_VERSION}" ] && valid_os=true && valid_version=true
local finalmsg local finalmsg
if [ "$valid_os" = true ]; then if [ "$valid_os" = true ]; then
log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}" log_write "${TICK} Distro: ${COL_GREEN}${detected_os^}${COL_NC}"
@@ -489,13 +498,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 +829,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 +856,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 +878,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
@@ -1112,7 +1137,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 +1221,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 +1342,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 +1371,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

@@ -107,6 +107,9 @@ main() {
web_update=false web_update=false
FTL_update=false FTL_update=false
# Perform an OS check to ensure we're on an appropriate operating system
os_check
# Install packages used by this installation script (necessary if users have removed e.g. git from their systems) # 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

View File

@@ -67,6 +67,11 @@ 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
( (

View File

@@ -93,6 +93,7 @@ IPV6_ADDRESS=${IPV6_ADDRESS}
QUERY_LOGGING= QUERY_LOGGING=
WEBPORT= WEBPORT=
PRIVACY_LEVEL= PRIVACY_LEVEL=
v5_to_v6_update=false
# Where old configs go to if a v6 migration is performed # Where old configs go to if a v6 migration is performed
V6_CONF_MIGRATION_DIR="/etc/pihole/migration_backup_v6" V6_CONF_MIGRATION_DIR="/etc/pihole/migration_backup_v6"
@@ -388,28 +389,6 @@ os_check() {
fi fi
} }
# This function waits for dpkg to unlock, which signals that the previous apt-get command has finished.
test_dpkg_lock() {
i=0
printf " %b Waiting for package manager to finish (up to 30 seconds)\\n" "${INFO}"
# fuser is a program to show which processes use the named files, sockets, or filesystems
# So while the lock is held,
while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do
# we wait half a second,
sleep 0.5
# increase the iterator,
((i = i + 1))
# exit if waiting for more then 30 seconds
if [[ $i -gt 60 ]]; then
printf " %b %bError: Could not verify package manager finished and released lock. %b\\n" "${CROSS}" "${COL_LIGHT_RED}" "${COL_NC}"
printf " Attempt to install packages manually and retry.\\n"
exit 1
fi
done
# and then report success once dpkg is unlocked.
return 0
}
# Compatibility # Compatibility
package_manager_detect() { package_manager_detect() {
@@ -1182,27 +1161,23 @@ installDefaultBlocklists() {
echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >>"${adlistFile}" echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >>"${adlistFile}"
} }
remove_old_dnsmasq_ftl_configs() { move_old_dnsmasq_ftl_configs() {
# Local, named variables # Create migration directory /etc/pihole/migration_backup_v6
# and make it owned by pihole:pihole
mkdir -p "${V6_CONF_MIGRATION_DIR}"
chown pihole:pihole "${V6_CONF_MIGRATION_DIR}"
# Move all conf files originally created by Pi-hole into this directory
# - 01-pihole.conf
# - 02-pihole-dhcp.conf
# - 04-pihole-static-dhcp.conf
# - 05-pihole-custom-cname.conf
# - 06-rfc6761.conf
mv /etc/dnsmasq.d/0{1,2,4,5}-pihole*.conf "${V6_CONF_MIGRATION_DIR}/" 2>/dev/null || true
mv /etc/dnsmasq.d/06-rfc6761.conf "${V6_CONF_MIGRATION_DIR}/" 2>/dev/null || true
# If the dnsmasq main config file exists
local dnsmasq_conf="/etc/dnsmasq.conf" local dnsmasq_conf="/etc/dnsmasq.conf"
local pihole_01="/etc/dnsmasq.d/01-pihole.conf"
local rfc6761_06="/etc/dnsmasq.d/06-rfc6761.conf"
local pihole_dhcp_02="/etc/dnsmasq.d/02-pihole-dhcp.conf"
# pihole-FTL does some fancy stuff with config these days, and so we can remove some old config files
if [[ -f "${pihole_01}" ]]; then
rm "${pihole_01}"
fi
if [[ -f "${rfc6761_06}" ]]; then
rm "${rfc6761_06}"
fi
if [[ -f "${pihole_dhcp_02}" ]]; then
rm "${pihole_dhcp_02}"
fi
# If the dnsmasq config file exists
if [[ -f "${dnsmasq_conf}" ]]; then if [[ -f "${dnsmasq_conf}" ]]; then
# There should not be anything custom in here for Pi-hole users # There should not be anything custom in here for Pi-hole users
# It is no longer needed, but we'll back it up instead of deleting it just in case # It is no longer needed, but we'll back it up instead of deleting it just in case
@@ -1233,12 +1208,12 @@ remove_old_pihole_lighttpd_configs() {
lighty-disable-mod pihole-admin >/dev/null || true lighty-disable-mod pihole-admin >/dev/null || true
fi fi
if [[ -f "${confavailable}" ]]; then if [[ -f "${confenabled}" || -L "${confenabled}" ]]; then
rm "${confavailable}" rm "${confenabled}"
fi fi
if [[ -f "${confenabled}" ]]; then if [[ -f "${confavailable}" ]]; then
rm "${confenabled}" rm "${confavailable}"
fi fi
} }
@@ -1301,13 +1276,6 @@ installConfigs() {
# Ensure that permissions are correctly set # Ensure that permissions are correctly set
chown -R pihole:pihole /etc/pihole chown -R pihole:pihole /etc/pihole
# Install list of DNS servers
# Format: Name;Primary IPv4;Secondary IPv4;Primary IPv6;Secondary IPv6
# Some values may be empty (for example: DNS servers without IPv6 support)
echo "${DNS_SERVERS}" >"${PI_HOLE_CONFIG_DIR}/dns-servers.conf"
chmod 644 "${PI_HOLE_CONFIG_DIR}/dns-servers.conf"
chown pihole:pihole "${PI_HOLE_CONFIG_DIR}/dns-servers.conf"
# Install empty custom.list file if it does not exist # Install empty custom.list file if it does not exist
if [[ ! -r "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" ]]; then if [[ ! -r "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" ]]; then
if ! install -D -T -o pihole -g pihole -m 660 /dev/null "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" &>/dev/null; then if ! install -D -T -o pihole -g pihole -m 660 /dev/null "${PI_HOLE_CONFIG_DIR}/hosts/custom.list" &>/dev/null; then
@@ -1458,20 +1426,15 @@ disable_resolved_stublistener() {
printf " %b Testing if systemd-resolved is enabled\\n" "${INFO}" printf " %b Testing if systemd-resolved is enabled\\n" "${INFO}"
# Check if Systemd-resolved's DNSStubListener is enabled and active on port 53 # Check if Systemd-resolved's DNSStubListener is enabled and active on port 53
if check_service_active "systemd-resolved"; then if check_service_active "systemd-resolved"; then
# Check if DNSStubListener is enabled # Disable the DNSStubListener to unbind it from port 53
printf " %b %b Testing if systemd-resolved DNSStub-Listener is active" "${OVER}" "${INFO}" # Note that this breaks dns functionality on host until FTL is up and running
if (grep -E '#?DNSStubListener=yes' /etc/systemd/resolved.conf &>/dev/null); then printf "%b %b Disabling systemd-resolved DNSStubListener\\n" "${OVER}" "${TICK}"
# Disable the DNSStubListener to unbind it from port 53 mkdir -p /etc/systemd/resolved.conf.d
# Note that this breaks dns functionality on host until ftl are up and running cat > /etc/systemd/resolved.conf.d/90-pi-hole-disable-stub-listener.conf << EOF
printf "%b %b Disabling systemd-resolved DNSStubListener" "${OVER}" "${TICK}" [Resolve]
# Make a backup of the original /etc/systemd/resolved.conf DNSStubListener=no
# (This will need to be restored on uninstallation) EOF
sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf systemctl reload-or-restart systemd-resolved
printf " and restarting systemd-resolved\\n"
systemctl reload-or-restart systemd-resolved
else
printf "%b %b Systemd-resolved does not need to be restarted\\n" "${OVER}" "${INFO}"
fi
else else
printf "%b %b Systemd-resolved is not enabled\\n" "${OVER}" "${INFO}" printf "%b %b Systemd-resolved is not enabled\\n" "${OVER}" "${INFO}"
fi fi
@@ -1728,7 +1691,8 @@ installPihole() {
exit 1 exit 1
fi fi
remove_old_dnsmasq_ftl_configs # Move old dnsmasq files to $V6_CONF_MIGRATION_DIR for later migration via migrate_dnsmasq_configs()
move_old_dnsmasq_ftl_configs
remove_old_pihole_lighttpd_configs remove_old_pihole_lighttpd_configs
# Install config files # Install config files
@@ -1800,7 +1764,7 @@ displayFinalMessage() {
if [[ "${#1}" -gt 0 ]]; then if [[ "${#1}" -gt 0 ]]; then
# set the password to the first argument. # set the password to the first argument.
pwstring="$1" pwstring="$1"
elif [[ $(pihole-FTL --config webserver.api.pwhash) == '""' ]]; then elif [[ -n $(pihole-FTL --config webserver.api.pwhash) ]]; then
# Else if the password exists from previous setup, we'll load it later # Else if the password exists from previous setup, we'll load it later
pwstring="unchanged" pwstring="unchanged"
else else
@@ -2156,7 +2120,7 @@ get_binary_name() {
else else
printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}" printf "%b %b Detected 32bit (i686) architecture\\n" "${OVER}" "${TICK}"
fi fi
l_binary="pihole-FTL-linux-386" l_binary="pihole-FTL-386"
fi fi
# Returning a string value via echo # Returning a string value via echo
@@ -2300,6 +2264,44 @@ copy_to_install_log() {
chown pihole:pihole "${installLogLoc}" chown pihole:pihole "${installLogLoc}"
} }
disableLighttpd() {
# Return early when lighttpd is not active
if ! check_service_active lighttpd; then
return
fi
local response
# Detect if the terminal is interactive
if [[ -t 0 ]]; then
# The terminal is interactive
dialog --no-shadow --keep-tite \
--title "Pi-hole v6.0 no longer uses lighttpd" \
--yesno "\\n\\nPi-hole v6.0 has its own embedded web server so lighttpd is no longer needed *unless* you have custom configurations.\\n\\nIn this case, you can opt-out of disabling lighttpd and pihole-FTL will try to bind to an alternative port such as 8080.\\n\\nDo you want to disable lighttpd (recommended)?" "${r}" "${c}" && response=0 || response="$?"
else
# The terminal is non-interactive, assume yes. Lighttpd will be stopped
# but keeps being installed and can easily be re-enabled by the user
response=0
fi
# If the user does not want to disable lighttpd, return early
if [[ "${response}" -ne 0 ]]; then
return
fi
# Lighttpd is not needed anymore, so disable it
# We keep all the configuration files in place, so the user can re-enable it
# if needed
# Check if lighttpd is installed
if is_command lighttpd; then
# Stop the lighttpd service
stop_service lighttpd
# Disable the lighttpd service
disable_service lighttpd
fi
}
migrate_dnsmasq_configs() { migrate_dnsmasq_configs() {
# Previously, Pi-hole created a number of files in /etc/dnsmasq.d # Previously, Pi-hole created a number of files in /etc/dnsmasq.d
# During migration, their content is copied into the new single source of # During migration, their content is copied into the new single source of
@@ -2307,25 +2309,49 @@ migrate_dnsmasq_configs() {
# avoid conflicts with other services on this system # avoid conflicts with other services on this system
# Exit early if this is already Pi-hole v6.0 # Exit early if this is already Pi-hole v6.0
# We decide this on the presence of the file /etc/pihole/pihole.toml # We decide this on the non-existence of the file /etc/pihole/setupVars.conf (either moved by previous migration or fresh install)
if [[ -f "${PI_HOLE_V6_CONFIG}" ]]; then if [[ ! -f "/etc/pihole/setupVars.conf" ]]; then
return 0 return 0
fi fi
# Create target directory /etc/pihole/migration_backup_v6 # Disable lighttpd server during v6 migration
# and make it owned by pihole:pihole disableLighttpd
mkdir -p "${V6_CONF_MIGRATION_DIR}"
chown pihole:pihole "${V6_CONF_MIGRATION_DIR}"
# Move all conf files originally created by Pi-hole into this directory # move_old_dnsmasq_ftl_configs() moved everything is in place,
# - 01-pihole.conf # so we can create the new config file /etc/pihole/pihole.toml
# - 02-pihole-dhcp.conf # This file will be created with the default settings unless the user has
# - 04-pihole-static-dhcp.conf # changed settings via setupVars.conf or the other dnsmasq files moved before
# - 05-pihole-custom-cname.conf # During migration, setupVars.conf is moved to /etc/pihole/migration_backup_v6
# - 06-rfc6761.conf str="Migrating Pi-hole configuration to version 6"
printf " %b %s..." "${INFO}" "${str}"
local FTLoutput FTLstatus
FTLoutput=$(pihole-FTL migrate v6)
FTLstatus=$?
if [[ "${FTLstatus}" -eq 0 ]]; then
printf "%b %b %s\\n" "${OVER}" "${TICK}" "${str}"
else
printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}"
fi
mv /etc/dnsmasq.d/0{1,2,4,5}-pihole*.conf "${V6_CONF_MIGRATION_DIR}/" 2>/dev/null || true # Print the output of the FTL migration prefacing every line with four
mv /etc/dnsmasq.d/06-rfc6761.conf "${V6_CONF_MIGRATION_DIR}/" 2>/dev/null || true # spaces for alignment
printf "%b" "${FTLoutput}" | sed 's/^/ /'
# Print a blank line for separation
printf "\\n"
v5_to_v6_update=true
}
# Check for availability of either the "service" or "systemctl" commands
check_service_command() {
# Check for the availability of the "service" command
if ! is_command service && ! is_command systemctl; then
# If neither the "service" nor the "systemctl" command is available, inform the user
printf " %b Neither the service nor the systemctl commands are available\\n" "${CROSS}"
printf " on this machine. This Pi-hole installer cannot continue.\\n"
exit 1
fi
} }
main() { main() {
@@ -2376,6 +2402,9 @@ main() {
# Check if SELinux is Enforcing and exit before doing anything else # Check if SELinux is Enforcing and exit before doing anything else
checkSelinux checkSelinux
# Check for availability of either the "service" or "systemctl" commands
check_service_command
# Check for supported package managers so that we may install dependencies # Check for supported package managers so that we may install dependencies
package_manager_detect package_manager_detect
@@ -2471,18 +2500,11 @@ main() {
# Copy the temp log file into final log location for storage # Copy the temp log file into final log location for storage
copy_to_install_log copy_to_install_log
# Add password to web UI if there is none
pw=""
# If no password is set,
if [[ $(pihole-FTL --config webserver.api.pwhash) == '""' ]]; then
# generate a random password
pw=$(tr -dc _A-Z-a-z-0-9 </dev/urandom | head -c 8)
pihole setpassword "${pw}"
fi
# Migrate existing install to v6.0 # Migrate existing install to v6.0
migrate_dnsmasq_configs migrate_dnsmasq_configs
# Check for and disable systemd-resolved-DNSStubListener before reloading resolved # Check for and disable systemd-resolved-DNSStubListener before reloading resolved
# DNSStubListener needs to remain in place for installer to download needed files, # DNSStubListener needs to remain in place for installer to download needed files,
# so this change needs to be made after installation is complete, # so this change needs to be made after installation is complete,
@@ -2505,9 +2527,23 @@ main() {
restart_service pihole-FTL restart_service pihole-FTL
# write privacy level and logging to pihole.toml # Add password to web UI if there is none
pw=""
# If this is a fresh installation and no password is set,
if [[ ${v5_to_v6_update} = false && -z $(getFTLConfigValue webserver.api.pwhash) ]]; then
# generate a random password
pw=$(tr -dc _A-Z-a-z-0-9 </dev/urandom | head -c 8)
pihole setpassword "${pw}"
fi
# apply settings to pihole.toml
# needs to be done after FTL service has been started, otherwise pihole.toml does not exist # needs to be done after FTL service has been started, otherwise pihole.toml does not exist
# set on fresh installations by setPrivacyLevel() and setLogging( # set on fresh installations by setDNS() and setPrivacyLevel() and setLogging()
if [ -n "${PIHOLE_DNS_1}" ]; then
local string="\"${PIHOLE_DNS_1}\""
[ -n "${PIHOLE_DNS_2}" ] && string+=", \"${PIHOLE_DNS_2}\""
setFTLConfigValue "dns.upstreams" "[ $string ]"
fi
if [ -n "${QUERY_LOGGING}" ]; then if [ -n "${QUERY_LOGGING}" ]; then
setFTLConfigValue "dns.queryLogging" "${QUERY_LOGGING}" setFTLConfigValue "dns.queryLogging" "${QUERY_LOGGING}"
fi fi

View File

@@ -94,8 +94,9 @@ 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

View File

@@ -30,6 +30,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 +47,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
@@ -58,6 +62,8 @@ gravityDBfile_default="/etc/pihole/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 +97,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 +127,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 "${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}"
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}"
@@ -324,6 +362,54 @@ gravity_CheckDNSResolutionAvailable() {
echo -e "${OVER} ${TICK} DNS resolution is available" echo -e "${OVER} ${TICK} DNS resolution is available"
} }
# 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
gravity_DownloadBlocklists() { gravity_DownloadBlocklists() {
echo -e " ${INFO} ${COL_BOLD}Neutrino emissions detected${COL_NC}..." echo -e " ${INFO} ${COL_BOLD}Neutrino emissions detected${COL_NC}..."
@@ -332,33 +418,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 target 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 +450,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 +509,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 +534,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)
@@ -488,7 +602,7 @@ 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}" target="${4}" compression="${5}" gravity_type="${6}" domain="${7}"
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,12 +611,37 @@ 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:"
@@ -632,7 +771,7 @@ gravity_DownloadBlocklistFromUrl() {
if [[ "${download}" == true ]]; then if [[ "${download}" == true ]]; then
# 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,9 +814,10 @@ 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
@@ -685,10 +825,10 @@ gravity_DownloadBlocklistFromUrl() {
gravity_ParseFileIntoDomains "${listCurlBuffer}" "${saveLocation}" gravity_ParseFileIntoDomains "${listCurlBuffer}" "${saveLocation}"
# Remove curl buffer file after its use # Remove curl buffer file after its use
rm "${listCurlBuffer}" rm "${listCurlBuffer}"
# Compare lists if are they 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 +841,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
@@ -764,11 +905,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
@@ -917,11 +1058,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}"
# 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
}
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
@@ -997,6 +1160,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,7 +1173,7 @@ 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

9
pihole
View File

@@ -73,19 +73,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
} }
@@ -400,7 +398,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

View File

@@ -1,18 +0,0 @@
FROM buildpack-deps:lunar-scm
ENV GITDIR=/etc/.pihole
ENV SCRIPTDIR=/opt/pihole
RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole
ADD . $GITDIR
RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $GITDIR/advanced/Scripts/COL_TABLE $SCRIPTDIR/
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR
ENV DEBIAN_FRONTEND=noninteractive
RUN true && \
chmod +x $SCRIPTDIR/*
ENV SKIP_INSTALL=true
ENV OS_CHECK_DOMAIN_NAME=dev-supportedos.pi-hole.net
#sed '/# Start the installer/Q' /opt/pihole/basic-install.sh > /opt/pihole/stub_basic-install.sh && \

View File

@@ -2,5 +2,5 @@ pyyaml == 6.0.2
pytest == 8.3.4 pytest == 8.3.4
pytest-xdist == 3.6.1 pytest-xdist == 3.6.1
pytest-testinfra == 10.1.1 pytest-testinfra == 10.1.1
tox == 4.23.2 tox == 4.24.1
pytest-clarity == 1.0.1 pytest-clarity == 1.0.1

View File

@@ -119,11 +119,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