diff --git a/.codespellignore b/.codespellignore new file mode 100644 index 00000000..501a3d67 --- /dev/null +++ b/.codespellignore @@ -0,0 +1,3 @@ +doubleclick +wan +nwe diff --git a/.editorconfig b/.editorconfig index a50f2f70..714ed210 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,26 +13,8 @@ tab_width = 4 charset = utf-8 trim_trailing_whitespace = true -# Matches multiple files with brace expansion notation -# Set default charset -[*.{js,py}] -charset = utf-8 +[*.yml] +tab_width = 2 -# 4 space indentation -[*.py] -indent_style = space -indent_size = 4 - -# Tab indentation (no size specified) -[Makefile] -indent_style = tab - -# Indentation override for all JS under lib directory -[scripts/**.js] -indent_style = space -indent_size = 2 - -# Matches the exact files either package.json or .travis.yml -[{package.json,.travis.yml}] -indent_style = space -indent_size = 2 +[*.md] +tab_width = 2 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index be18a8f3..f91a9b82 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: time: "10:00" open-pull-requests-limit: 10 target-branch: development + reviewers: + - "pi-hole/core-maintainers" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a4f67b81..6e5a0886 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,16 +25,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: 'python' - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ccac6511..cd3c6ff6 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,7 @@ name: Mark stale issues on: schedule: - - cron: '0 * * * *' + - cron: '0 8 * * *' workflow_dispatch: jobs: @@ -13,14 +13,14 @@ jobs: issues: write steps: - - uses: actions/stale@v4 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - days-before-stale: 30 - days-before-close: 5 - stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.' - stale-issue-label: 'stale' - exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed' - exempt-all-issue-assignees: true - operations-per-run: 300 - stale-issue-reason: 'not_planned' + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 30 + days-before-close: 5 + stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.' + stale-issue-label: 'stale' + exempt-issue-labels: 'Internal, Fixed in next release, Bug: Confirmed, Documentation Needed' + exempt-all-issue-assignees: true + operations-per-run: 300 + close-issue-reason: 'not_planned' diff --git a/.github/workflows/sync-back-to-dev.yml b/.github/workflows/sync-back-to-dev.yml index 5b9fa570..f79b69f2 100644 --- a/.github/workflows/sync-back-to-dev.yml +++ b/.github/workflows/sync-back-to-dev.yml @@ -11,7 +11,7 @@ jobs: name: Syncing branches steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Opening pull request id: pull uses: tretuna/sync-branches@1.4.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d39852dc..308997d7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,39 +8,50 @@ permissions: contents: read jobs: - smoke-test: + smoke-tests: if: github.event.pull_request.draft == false runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - name: Run Smoke Tests + name: Check scripts in repository are executable run: | - # Ensure scripts in repository are executable IFS=$'\n'; for f in $(find . -name '*.sh'); do if [[ ! -x $f ]]; then echo "$f is not executable" && FAIL=1; fi ;done unset IFS; # If FAIL is 1 then we fail. - [[ $FAIL == 1 ]] && exit 1 || echo "Smoke Tests Passed" + [[ $FAIL == 1 ]] && exit 1 || echo "Scripts are executable!" + - + name: Spell-Checking + uses: codespell-project/actions-codespell@master + with: + ignore_words_file: .codespellignore + - + name: Get editorconfig-checker + uses: editorconfig-checker/action-editorconfig-checker@main + - + name: Run editorconfig-checker + run: editorconfig-checker + distro-test: if: github.event.pull_request.draft == false runs-on: ubuntu-latest - needs: smoke-test + needs: smoke-tests strategy: matrix: - distro: [debian_9, debian_10, debian_11, ubuntu_16, ubuntu_18, ubuntu_20, ubuntu_21, centos_7, centos_8, fedora_33, fedora_34] + distro: [debian_10, debian_11, ubuntu_18, ubuntu_20, ubuntu_21, ubuntu_22, centos_7, centos_8, fedora_34] env: DISTRO: ${{matrix.distro}} steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Python 3.8 - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.8 - diff --git a/.stickler.yml b/.stickler.yml index 8a2a1ce9..5fdbbf1e 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -1,6 +1,10 @@ +--- linters: shellcheck: shell: bash phpcs: flake8: max-line-length: 120 + yamllint: + config: ./.yamllint.conf + remarklint: diff --git a/.yamllint.conf b/.yamllint.conf new file mode 100644 index 00000000..d1b0953b --- /dev/null +++ b/.yamllint.conf @@ -0,0 +1,3 @@ +rules: + line-length: disable + document-start: disable diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 018b8c5f..1ea98df2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,5 +3,3 @@ Please read and understand the contribution guide before creating an issue or pull request. The guide can be found here: [https://docs.pi-hole.net/guides/github/contributing/](https://docs.pi-hole.net/guides/github/contributing/) - - diff --git a/advanced/01-pihole.conf b/advanced/01-pihole.conf index 02bc93bf..1fb34905 100644 --- a/advanced/01-pihole.conf +++ b/advanced/01-pihole.conf @@ -37,6 +37,6 @@ interface=@INT@ cache-size=@CACHE_SIZE@ log-queries -log-facility=/var/log/pihole.log +log-facility=/var/log/pihole/pihole.log log-async diff --git a/advanced/Scripts/database_migration/gravity/11_to_12.sql b/advanced/Scripts/database_migration/gravity/11_to_12.sql index 45fbc845..d480d46e 100644 --- a/advanced/Scripts/database_migration/gravity/11_to_12.sql +++ b/advanced/Scripts/database_migration/gravity/11_to_12.sql @@ -16,4 +16,4 @@ CREATE TRIGGER tr_group_zero AFTER DELETE ON "group" UPDATE info SET value = 12 WHERE property = 'version'; -COMMIT; \ No newline at end of file +COMMIT; diff --git a/advanced/Scripts/database_migration/gravity/12_to_13.sql b/advanced/Scripts/database_migration/gravity/12_to_13.sql index d16791d6..7d85cb05 100644 --- a/advanced/Scripts/database_migration/gravity/12_to_13.sql +++ b/advanced/Scripts/database_migration/gravity/12_to_13.sql @@ -15,4 +15,4 @@ CREATE TRIGGER tr_adlist_update AFTER UPDATE OF address,enabled,comment ON adlis UPDATE info SET value = 13 WHERE property = 'version'; -COMMIT; \ No newline at end of file +COMMIT; diff --git a/advanced/Scripts/database_migration/gravity/3_to_4.sql b/advanced/Scripts/database_migration/gravity/3_to_4.sql index 352b1baa..05231f72 100644 --- a/advanced/Scripts/database_migration/gravity/3_to_4.sql +++ b/advanced/Scripts/database_migration/gravity/3_to_4.sql @@ -93,4 +93,4 @@ CREATE VIEW vw_regex_blacklist AS SELECT domain, domainlist.id AS id, domainlist UPDATE info SET value = 4 WHERE property = 'version'; -COMMIT; \ No newline at end of file +COMMIT; diff --git a/advanced/Scripts/database_migration/gravity/4_to_5.sql b/advanced/Scripts/database_migration/gravity/4_to_5.sql index 2ad906fc..4ae9f980 100644 --- a/advanced/Scripts/database_migration/gravity/4_to_5.sql +++ b/advanced/Scripts/database_migration/gravity/4_to_5.sql @@ -35,4 +35,4 @@ CREATE TABLE client_by_group UPDATE info SET value = 5 WHERE property = 'version'; -COMMIT; \ No newline at end of file +COMMIT; diff --git a/advanced/Scripts/list.sh b/advanced/Scripts/list.sh index f3f97da2..b76a7ef7 100755 --- a/advanced/Scripts/list.sh +++ b/advanced/Scripts/list.sh @@ -100,21 +100,29 @@ Options: ValidateDomain() { # Convert to lowercase domain="${1,,}" + local str validDomain # Check validity of domain (don't check for regex entries) - if [[ "${#domain}" -le 253 ]]; then - if [[ ( "${typeId}" == "${regex_blacklist}" || "${typeId}" == "${regex_whitelist}" ) && "${wildcard}" == false ]]; then - validDomain="${domain}" - else + if [[ ( "${typeId}" == "${regex_blacklist}" || "${typeId}" == "${regex_whitelist}" ) && "${wildcard}" == false ]]; then + validDomain="${domain}" + else + # Check max length + if [[ "${#domain}" -le 253 ]]; then validDomain=$(grep -P "^((-|_)*[a-z\\d]((-|_)*[a-z\\d])*(-|_)*)(\\.(-|_)*([a-z\\d]((-|_)*[a-z\\d])*))*$" <<< "${domain}") # Valid chars check validDomain=$(grep -P "^[^\\.]{1,63}(\\.[^\\.]{1,63})*$" <<< "${validDomain}") # Length of each label + # set error string + str="is not a valid argument or domain name!" + else + validDomain= + str="is too long!" + fi fi if [[ -n "${validDomain}" ]]; then domList=("${domList[@]}" "${validDomain}") else - echo -e " ${CROSS} ${domain} is not a valid argument or domain name!" + echo -e " ${CROSS} ${domain} ${str}" fi domaincount=$((domaincount+1)) diff --git a/advanced/Scripts/piholeDebug.sh b/advanced/Scripts/piholeDebug.sh index 844cbd23..e71263d3 100755 --- a/advanced/Scripts/piholeDebug.sh +++ b/advanced/Scripts/piholeDebug.sh @@ -66,8 +66,8 @@ PIHOLE_DIRECTORY="/etc/pihole" PIHOLE_SCRIPTS_DIRECTORY="/opt/pihole" BIN_DIRECTORY="/usr/local/bin" RUN_DIRECTORY="/run" -LOG_DIRECTORY="/var/log" -WEB_SERVER_LOG_DIRECTORY="${LOG_DIRECTORY}/lighttpd" +LOG_DIRECTORY="/var/log/pihole" +WEB_SERVER_LOG_DIRECTORY="/var/log/lighttpd" WEB_SERVER_CONFIG_DIRECTORY="/etc/lighttpd" HTML_DIRECTORY="/var/www/html" WEB_GIT_DIRECTORY="${HTML_DIRECTORY}/admin" @@ -129,36 +129,17 @@ FTL_PORT="${RUN_DIRECTORY}/pihole-FTL.port" PIHOLE_LOG="${LOG_DIRECTORY}/pihole.log" PIHOLE_LOG_GZIPS="${LOG_DIRECTORY}/pihole.log.[0-9].*" PIHOLE_DEBUG_LOG="${LOG_DIRECTORY}/pihole_debug.log" -PIHOLE_FTL_LOG="$(get_ftl_conf_value "LOGFILE" "${LOG_DIRECTORY}/pihole-FTL.log")" +PIHOLE_FTL_LOG="$(get_ftl_conf_value "LOGFILE" "${LOG_DIRECTORY}/FTL.log")" -PIHOLE_WEB_SERVER_ACCESS_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/access.log" -PIHOLE_WEB_SERVER_ERROR_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/error.log" +PIHOLE_WEB_SERVER_ACCESS_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/access-pihole.log" +PIHOLE_WEB_SERVER_ERROR_LOG_FILE="${WEB_SERVER_LOG_DIRECTORY}/error-pihole.log" RESOLVCONF="${ETC}/resolv.conf" DNSMASQ_CONF="${ETC}/dnsmasq.conf" -# An array of operating system "pretty names" that we officially support -# We can loop through the array at any time to see if it matches a value -#SUPPORTED_OS=("Raspbian" "Ubuntu" "Fedora" "Debian" "CentOS") - # Store Pi-hole's processes in an array for easy use and parsing PIHOLE_PROCESSES=( "lighttpd" "pihole-FTL" ) -# Store the required directories in an array so it can be parsed through -#REQUIRED_DIRECTORIES=("${CORE_GIT_DIRECTORY}" -#"${CRON_D_DIRECTORY}" -#"${DNSMASQ_D_DIRECTORY}" -#"${PIHOLE_DIRECTORY}" -#"${PIHOLE_SCRIPTS_DIRECTORY}" -#"${BIN_DIRECTORY}" -#"${RUN_DIRECTORY}" -#"${LOG_DIRECTORY}" -#"${WEB_SERVER_LOG_DIRECTORY}" -#"${WEB_SERVER_CONFIG_DIRECTORY}" -#"${HTML_DIRECTORY}" -#"${WEB_GIT_DIRECTORY}" -#"${BLOCK_PAGE_DIRECTORY}") - # Store the required directories in an array so it can be parsed through REQUIRED_FILES=("${PIHOLE_CRON_FILE}" "${WEB_SERVER_CONFIG_FILE}" @@ -603,7 +584,7 @@ disk_usage() { # Additinal keywords can be added, separated by "|" hide="curlftpfs" - # only show those lines not containg a sensitive phrase + # only show those lines not containing a sensitive phrase for line in "${file_system[@]}"; do if [[ ! $line =~ $hide ]]; then log_write " ${line}" @@ -1394,7 +1375,7 @@ curl_to_tricorder() { upload_to_tricorder() { local username="pihole" # Set the permissions and owner - chmod 644 ${PIHOLE_DEBUG_LOG} + chmod 640 ${PIHOLE_DEBUG_LOG} chown "$USER":"${username}" ${PIHOLE_DEBUG_LOG} # Let the user know debugging is complete with something strikingly visual diff --git a/advanced/Scripts/piholeLogFlush.sh b/advanced/Scripts/piholeLogFlush.sh index 57f901f5..3473fad5 100755 --- a/advanced/Scripts/piholeLogFlush.sh +++ b/advanced/Scripts/piholeLogFlush.sh @@ -31,7 +31,7 @@ if [ -z "$DBFILE" ]; then fi if [[ "$@" != *"quiet"* ]]; then - echo -ne " ${INFO} Flushing /var/log/pihole.log ..." + echo -ne " ${INFO} Flushing /var/log/pihole/pihole.log ..." fi if [[ "$@" == *"once"* ]]; then # Nightly logrotation @@ -44,9 +44,9 @@ if [[ "$@" == *"once"* ]]; then # 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) - cp -p /var/log/pihole.log /var/log/pihole.log.1 - echo " " > /var/log/pihole.log - chmod 644 /var/log/pihole.log + cp -p /var/log/pihole/pihole.log /var/log/pihole/pihole.log.1 + echo " " > /var/log/pihole/pihole.log + chmod 640 /var/log/pihole/pihole.log fi else # Manual flushing @@ -56,10 +56,10 @@ else /usr/sbin/logrotate --force --state "${STATEFILE}" /etc/pihole/logrotate else # Flush both pihole.log and pihole.log.1 (if existing) - echo " " > /var/log/pihole.log - if [ -f /var/log/pihole.log.1 ]; then - echo " " > /var/log/pihole.log.1 - chmod 644 /var/log/pihole.log.1 + echo " " > /var/log/pihole/pihole.log + if [ -f /var/log/pihole/pihole.log.1 ]; then + echo " " > /var/log/pihole/pihole.log.1 + chmod 640 /var/log/pihole/pihole.log.1 fi fi # Delete most recent 24 hours from FTL's database, leave even older data intact (don't wipe out all history) @@ -70,6 +70,6 @@ else fi if [[ "$@" != *"quiet"* ]]; then - echo -e "${OVER} ${TICK} Flushed /var/log/pihole.log" + echo -e "${OVER} ${TICK} Flushed /var/log/pihole/pihole.log" echo -e " ${TICK} Deleted ${deleted} queries from database" fi diff --git a/advanced/Scripts/utils.sh b/advanced/Scripts/utils.sh index f0a7cc37..cf24c098 100755 --- a/advanced/Scripts/utils.sh +++ b/advanced/Scripts/utils.sh @@ -12,7 +12,7 @@ # Basic Housekeeping rules # - Functions must be self contained -# - Functions must be added in alphabetical order +# - Functions should be grouped with other similar functions # - Functions must be documented # - New functions must have a test added for them in test/test_any_utils.py @@ -89,7 +89,7 @@ getFTLAPIPort(){ # -s: FILE exists and has a size greater than zero ftl_api_port=$(cat "${PORTFILE}") # Exploit prevention: unset the variable if there is malicious content - # Verify that the value read from the file is numeric + # Verify that the value read from the file is numeric expr "$ftl_api_port" : "[^[:digit:]]" > /dev/null && unset ftl_api_port fi diff --git a/advanced/Scripts/webpage.sh b/advanced/Scripts/webpage.sh index de06d60c..279de9e9 100755 --- a/advanced/Scripts/webpage.sh +++ b/advanced/Scripts/webpage.sh @@ -296,7 +296,7 @@ trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC68345710423 # changes in the non-FQDN forwarding. This cannot be done in 01-pihole.conf # as we don't want to delete all local=/.../ lines so it's much safer to # simply rewrite the entire corresponding config file (which is what the - # DHCP settings subroutie is doing) + # DHCP settings subroutine is doing) ProcessDHCPSettings } @@ -440,8 +440,8 @@ dhcp-leasefile=/etc/pihole/dhcp.leases echo "#quiet-dhcp6 #enable-ra dhcp-option=option6:dns-server,[::] -dhcp-range=::100,::1ff,constructor:${interface},ra-names,slaac,64,3600 -ra-param=*,0,0 +dhcp-range=::,constructor:${interface},ra-names,ra-stateless,64 + " >> "${dhcpconfig}" fi @@ -650,7 +650,8 @@ Teleporter() { host="${host//./_}" filename="pi-hole-${host:-noname}-teleporter_${datetimestamp}.tar.gz" fi - php /var/www/html/admin/scripts/pi-hole/php/teleporter.php > "${filename}" + # webroot is sourced from basic-install above + php "${webroot}/admin/scripts/pi-hole/php/teleporter.php" > "${filename}" } checkDomain() diff --git a/advanced/Templates/logrotate b/advanced/Templates/logrotate index ffed910b..9a56b552 100644 --- a/advanced/Templates/logrotate +++ b/advanced/Templates/logrotate @@ -1,4 +1,4 @@ -/var/log/pihole.log { +/var/log/pihole/pihole.log { # su # daily copytruncate @@ -9,7 +9,7 @@ nomail } -/var/log/pihole-FTL.log { +/var/log/pihole/FTL.log { # su # weekly copytruncate diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index 41ab8018..f5abfcea 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -9,8 +9,55 @@ # Description: Enable service provided by pihole-FTL daemon ### END INIT INFO +# Global variables +FTLCONFFILE="/etc/pihole/pihole-FTL.conf" +DEFAULT_PID_FILE="/run/pihole-FTL.pid" +DEFAULT_PORT_FILE="/run/pihole-FTL.port" +FTL_PID='' + +# Get the file path of the pihole-FTL.pid file +getFTLPIDFile() { + if [ -s "${FTLCONFFILE}" ]; then + # if PIDFILE is not set in pihole-FTL.conf, use the default path + FTL_PID_FILE="$({ grep '^PIDFILE=' "${FTLCONFFILE}" || echo "${DEFAULT_PID_FILE}"; } | cut -d'=' -f2-)" + else + # if there is no pihole-FTL.conf, use the default path + FTL_PID_FILE="${DEFAULT_PID_FILE}" + fi +} + +# Get the PID of the FTL process based on the content of the pihole-FTL.pid file +getFTLPID() { + if [ -s "${FTL_PID_FILE}" ]; then + # -s: FILE exists and has a size greater than zero + FTL_PID="$(cat "${FTL_PID_FILE}")" + # Exploit prevention: unset the variable if there is malicious content + # Verify that the value read from the file is numeric + expr "${FTL_PID}" : "[^[:digit:]]" > /dev/null && unset FTL_PID + fi + + # If FTL is not running, or the PID file contains malicious stuff, substitute + # negative PID to signal this + FTL_PID=${FTL_PID:=-1} +} + +# Get the file path of the pihole-FTL.port file +getFTLPortFile() { + if [ -s "${FTLCONFFILE}" ]; then + # if PORTFILE is not set in pihole-FTL.conf, use the default path + FTL_PORT_FILE="$({ grep '^PORTFILE=' "${FTLCONFFILE}" || echo "${DEFAULT_PORT_FILE}"; } | cut -d'=' -f2-)" + else + # if there is no pihole-FTL.conf, use the default path + FTL_PORT_FILE="${DEFAULT_PORT_FILE}" +fi +} + + is_running() { - pgrep -xo "pihole-FTL" > /dev/null + if [ -d "/proc/${FTL_PID}" ]; then + return 0 + fi + return 1 } @@ -20,20 +67,34 @@ start() { echo "pihole-FTL is already running" else # Touch files to ensure they exist (create if non-existing, preserve if existing) - mkdir -pm 0755 /run/pihole - [ ! -f /run/pihole-FTL.pid ] && install -m 644 -o pihole -g pihole /dev/null /run/pihole-FTL.pid - [ ! -f /run/pihole-FTL.port ] && install -m 644 -o pihole -g pihole /dev/null /run/pihole-FTL.port - [ ! -f /var/log/pihole-FTL.log ] && install -m 644 -o pihole -g pihole /dev/null /var/log/pihole-FTL.log - [ ! -f /var/log/pihole.log ] && install -m 644 -o pihole -g pihole /dev/null /var/log/pihole.log + mkdir -pm 0755 /run/pihole /var/log/pihole + [ ! -f "${FTL_PID_FILE}" ] && install -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" + [ ! -f "${FTL_PORT_FILE}" ] && install -m 644 -o pihole -g pihole /dev/null "${FTL_PORT_FILE}" + [ ! -f /var/log/pihole/FTL.log ] && install -m 644 -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 /etc/pihole/dhcp.leases ] && install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit all necessary files - chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole.log /var/log/pihole.log /etc/pihole/dhcp.leases + chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases # Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist - chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole-FTL.log /var/log/pihole.log + chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log + chmod -f 0640 /var/log/pihole/pihole.log # Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db # Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist chmod -f 0664 /etc/pihole/pihole-FTL.db + + # Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole/ + # Should be removed with Pi-hole v6.0 + if [ ! -f /var/log/pihole.log ]; then + ln -s /var/log/pihole/pihole.log /var/log/pihole.log + chown -h pihole:pihole /var/log/pihole.log + + fi + if [ ! -f /var/log/pihole-FTL.log ]; then + ln -s /var/log/pihole/FTL.log /var/log/pihole-FTL.log + chown -h pihole:pihole /var/log/pihole-FTL.log + fi + if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole else @@ -47,7 +108,7 @@ start() { # Stop the service stop() { if is_running; then - pkill -xo "pihole-FTL" + kill "${FTL_PID}" for i in 1 2 3 4 5; do if ! is_running; then break @@ -60,8 +121,7 @@ stop() { if is_running; then echo "Not stopped; may still be shutting down or shutdown may have failed, killing now" - pkill -xo -9 "pihole-FTL" - exit 1 + kill -9 "${FTL_PID}" else echo "Stopped" fi @@ -69,7 +129,7 @@ stop() { echo "Not running" fi # Cleanup - rm -f /run/pihole/FTL.sock /dev/shm/FTL-* + rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}" "${FTL_PORT_FILE}" echo } @@ -86,6 +146,14 @@ status() { ### main logic ### + +# Get file paths +getFTLPIDFile +getFTLPortFile + +# Get FTL's current PID +getFTLPID + case "$1" in stop) stop diff --git a/advanced/Templates/pihole.cron b/advanced/Templates/pihole.cron index 37724d2e..46640fbb 100644 --- a/advanced/Templates/pihole.cron +++ b/advanced/Templates/pihole.cron @@ -18,7 +18,7 @@ # early morning. Download any updates from the adlists # Squash output to log, then splat the log to stdout on error to allow for # standard crontab job error handling. -59 1 * * 7 root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole_updateGravity.log || cat /var/log/pihole_updateGravity.log +59 1 * * 7 root PATH="$PATH:/usr/sbin:/usr/local/bin/" pihole updateGravity >/var/log/pihole/pihole_updateGravity.log || cat /var/log/pihole/pihole_updateGravity.log # Pi-hole: Flush the log daily at 00:00 # The flush script will use logrotate if available diff --git a/advanced/dnsmasq.conf.original b/advanced/dnsmasq.conf.original index 6758f0b8..4aa5a8bf 100644 --- a/advanced/dnsmasq.conf.original +++ b/advanced/dnsmasq.conf.original @@ -507,7 +507,7 @@ # (using /etc/hosts) then that name can be specified as the # tftp_servername (the third option to dhcp-boot) and in that # case dnsmasq resolves this name and returns the resultant IP -# addresses in round robin fasion. This facility can be used to +# addresses in round robin fashion. This facility can be used to # load balance the tftp load among a set of servers. #dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name diff --git a/advanced/lighttpd.conf.debian b/advanced/lighttpd.conf.debian index b8656a24..4231a0c9 100644 --- a/advanced/lighttpd.conf.debian +++ b/advanced/lighttpd.conf.debian @@ -28,12 +28,12 @@ server.modules = ( server.document-root = "/var/www/html" server.error-handler-404 = "/pihole/index.php" server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) -server.errorlog = "/var/log/lighttpd/error.log" +server.errorlog = "/var/log/lighttpd/error-pihole.log" server.pid-file = "/run/lighttpd.pid" server.username = "www-data" server.groupname = "www-data" server.port = 80 -accesslog.filename = "/var/log/lighttpd/access.log" +accesslog.filename = "/var/log/lighttpd/access-pihole.log" accesslog.format = "%{%s}t|%V|%r|%s|%b" # Allow streaming response diff --git a/advanced/lighttpd.conf.fedora b/advanced/lighttpd.conf.fedora index 79d5f3b2..c3c94986 100644 --- a/advanced/lighttpd.conf.fedora +++ b/advanced/lighttpd.conf.fedora @@ -29,12 +29,12 @@ server.modules = ( server.document-root = "/var/www/html" server.error-handler-404 = "/pihole/index.php" server.upload-dirs = ( "/var/cache/lighttpd/uploads" ) -server.errorlog = "/var/log/lighttpd/error.log" +server.errorlog = "/var/log/lighttpd/error-pihole.log" server.pid-file = "/run/lighttpd.pid" server.username = "lighttpd" server.groupname = "lighttpd" server.port = 80 -accesslog.filename = "/var/log/lighttpd/access.log" +accesslog.filename = "/var/log/lighttpd/access-pihole.log" accesslog.format = "%{%s}t|%V|%r|%s|%b" # Allow streaming response diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index 835f0efc..9680e9f9 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -2,7 +2,7 @@ # shellcheck disable=SC1090 # Pi-hole: A black hole for Internet advertisements -# (c) 2017-2021 Pi-hole, LLC (https://pi-hole.net) +# (c) Pi-hole (https://pi-hole.net) # Network-wide ad blocking via your own hardware. # # Installs and Updates Pi-hole @@ -32,6 +32,14 @@ export PATH+=':/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' # Local variables will be in lowercase and will exist only within functions # It's still a work in progress, so you may see some variance in this guideline until it is complete +# Dialog result codes +# dialog code values can be set by environment variables, we only override if +# the env var is not set or empty. +: "${DIALOG_OK:=0}" +: "${DIALOG_CANCEL:=1}" +: "${DIALOG_ESC:=255}" + + # List of supported DNS servers DNS_SERVERS=$(cat << EOM Google (ECS, DNSSEC);8.8.8.8;8.8.4.4;2001:4860:4860:0:0:0:0:8888;2001:4860:4860:0:0:0:0:8844 @@ -93,7 +101,7 @@ if [ -z "${USER}" ]; then USER="$(id -un)" fi -# whiptail dialog dimensions: 20 rows and 70 chars width assures to fit on small screens and is known to hold all content. +# dialog dimensions: Let dialog handle appropriate sizing. r=20 c=70 @@ -195,7 +203,7 @@ os_check() { distro_part="${distro_and_versions%%=*}" versions_part="${distro_and_versions##*=}" - # If the distro part is a (case-insensistive) substring of the computer OS + # If the distro part is a (case-insensitive) substring of the computer OS if [[ "${detected_os^^}" =~ ${distro_part^^} ]]; then valid_os=true IFS="," read -r -a supportedVer <<<"${versions_part}" @@ -234,7 +242,7 @@ os_check() { printf " If you are seeing this message and you do have a supported OS, please contact support.\\n" fi printf "\\n" - printf " %bhttps://docs.pi-hole.net/main/prerequesites/#supported-operating-systems%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" + printf " %bhttps://docs.pi-hole.net/main/prerequisites/#supported-operating-systems%b\\n" "${COL_LIGHT_GREEN}" "${COL_NC}" printf "\\n" printf " If you wish to attempt to continue anyway, you can try one of the following commands to skip this check:\\n" printf "\\n" @@ -284,6 +292,9 @@ test_dpkg_lock() { # Compatibility package_manager_detect() { + # TODO - pull common packages for both distributions out into a common variable, then add + # the distro-specific ones below. + # First check to see if apt-get is installed. if is_command apt-get ; then # Set some global variables here @@ -300,15 +311,24 @@ package_manager_detect() { # Check for and determine version number (major and minor) of current php install local phpVer="php" if is_command php ; then - printf " %b Existing PHP installation detected : PHP version %s\\n" "${INFO}" "$(php <<< "")" - printf -v phpInsMajor "%d" "$(php <<< "")" - printf -v phpInsMinor "%d" "$(php <<< "")" - phpVer="php$phpInsMajor.$phpInsMinor" + phpVer="$(php <<< "")" + # Check if the first character of the string is numeric + if [[ ${phpVer:0:1} =~ [1-9] ]]; then + printf " %b Existing PHP installation detected : PHP version %s\\n" "${INFO}" "${phpVer}" + printf -v phpInsMajor "%d" "$(php <<< "")" + printf -v phpInsMinor "%d" "$(php <<< "")" + phpVer="php$phpInsMajor.$phpInsMinor" + else + printf " %b No valid PHP installation detected!\\n" "${CROSS}" + printf " %b PHP version : %s\\n" "${INFO}" "${phpVer}" + printf " %b Aborting installation.\\n" "${CROSS}" + exit 1 + fi fi - # Packages required to perfom the os_check (stored as an array) + # Packages required to perform the os_check (stored as an array) OS_CHECK_DEPS=(grep dnsutils) # Packages required to run this install script (stored as an array) - INSTALLER_DEPS=(git iproute2 whiptail ca-certificates) + INSTALLER_DEPS=(git iproute2 dialog ca-certificates) # Packages required to run Pi-hole (stored as an array) PIHOLE_DEPS=(cron curl iputils-ping psmisc sudo unzip idn2 libcap2-bin dns-root-data libcap2 netcat-openbsd procps) # Packages required for the Web admin interface (stored as an array) @@ -336,9 +356,10 @@ package_manager_detect() { # These variable names match the ones for apt-get. See above for an explanation of what they are for. PKG_INSTALL=("${PKG_MANAGER}" install -y) - PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l" + # CentOS package manager returns 100 when there are packages to update so we need to || true to prevent the script from exiting. + PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l || true" OS_CHECK_DEPS=(grep bind-utils) - INSTALLER_DEPS=(git iproute newt procps-ng which chkconfig ca-certificates) + INSTALLER_DEPS=(git dialog iproute newt procps-ng which chkconfig ca-certificates) PIHOLE_DEPS=(cronie curl findutils sudo unzip libidn2 psmisc libcap nmap-ncat) PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php-common php-cli php-pdo php-xml php-json php-intl) LIGHTTPD_USER="lighttpd" @@ -387,38 +408,58 @@ select_rpm_php(){ PIHOLE_WEB_DEPS=("${CENTOS7_PIHOLE_WEB_DEPS[@]}") unset CENTOS7_PIHOLE_WEB_DEPS fi - # CentOS requires the EPEL repository to gain access to Fedora packages - EPEL_PKG="epel-release" - rpm -q ${EPEL_PKG} &> /dev/null || rc=$? - if [[ $rc -ne 0 ]]; then + + if rpm -qa | grep -qi 'epel'; then + printf " %b EPEL repository already installed\\n" "${TICK}" + else + # CentOS requires the EPEL repository to gain access to Fedora packages + if [[ CURRENT_CENTOS_VERSION -eq 7 ]]; then + EPEL_PKG="https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm" + elif [[ CURRENT_CENTOS_VERSION -eq 8 ]]; then + EPEL_PKG="https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm" + fi printf " %b Enabling EPEL package repository (https://fedoraproject.org/wiki/EPEL)\\n" "${INFO}" - "${PKG_INSTALL[@]}" ${EPEL_PKG} &> /dev/null + "${PKG_INSTALL[@]}" ${EPEL_PKG} printf " %b Installed %s\\n" "${TICK}" "${EPEL_PKG}" fi + # The default php on CentOS 7.x is 5.4 which is EOL # Check if the version of PHP available via installed repositories is >= to PHP 7 AVAILABLE_PHP_VERSION=$("${PKG_MANAGER}" info php | grep -i version | grep -o '[0-9]\+' | head -1) if [[ $AVAILABLE_PHP_VERSION -ge $SUPPORTED_CENTOS_PHP_VERSION ]]; then # Since PHP 7 is available by default, install via default PHP package names : # do nothing as PHP is current + printf "PHP 7 is installed" else REMI_PKG="remi-release" REMI_REPO="remi-php72" - rpm -q ${REMI_PKG} &> /dev/null || rc=$? - if [[ $rc -ne 0 ]]; then - # The PHP version available via default repositories is older than version 7 - if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" "${r}" "${c}"; then - # User decided to NOT update PHP from REMI, attempt to install the default available PHP version - printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}" - : # continue with unsupported php version - else - printf " %b Enabling Remi's RPM repository (https://rpms.remirepo.net)\\n" "${INFO}" - "${PKG_INSTALL[@]}" "https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" &> /dev/null - # enable the PHP 7 repository via yum-config-manager (provided by yum-utils) + REMI_REPO_URL="https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" + + # The PHP version available via default repositories is older than version 7 + dialog --no-shadow --keep-tite \ + --title "PHP 7 Update (recommended)" \ + --defaultno \ + --yesno "PHP 7.x is recommended for both security and language features.\ +\\n\\nWould you like to install PHP7 via Remi's RPM repository?\ +\\n\\nSee: https://rpms.remirepo.net for more information"\ + "${r}" "${c}" && result=0 || result=$? + + case ${result} in + "${DIALOG_OK}" ) + printf " %b Installing PHP 7 via Remi's RPM repository\\n" "${INFO}" "${PKG_INSTALL[@]}" "yum-utils" &> /dev/null - yum-config-manager --enable ${REMI_REPO} &> /dev/null - printf " %b Remi's RPM repository has been enabled for PHP7\\n" "${TICK}" + if rpm -q ${REMI_PKG} &> /dev/null; then + printf " %b Remi's RPM repository is already installed\\n" "${TICK}" + else + printf " %b Enabling Remi's RPM repository (https://rpms.remirepo.net)\\n" "${INFO}" + yum -y install "${REMI_REPO_URL}" + printf " %b Installed %s from %s\\n" "${TICK}" "${REMI_PKG}" "${REMI_REPO_URL}" + printf " %b Remi's RPM repository has been enabled for PHP7\\n" "${TICK}" + fi + yum-config-manager --disable 'remi-php*' + yum-config-manager --enable "${REMI_REPO}" + # trigger an install/update of PHP to ensure previous version of PHP is updated from REMI if "${PKG_INSTALL[@]}" "php-cli" &> /dev/null; then printf " %b PHP7 installed/updated via Remi's RPM repository\\n" "${TICK}" @@ -426,15 +467,49 @@ select_rpm_php(){ printf " %b There was a problem updating to PHP7 via Remi's RPM repository\\n" "${CROSS}" exit 1 fi - fi - fi # Warn user of unsupported version of Fedora or CentOS - if ! whiptail --defaultno --title "Unsupported RPM based distribution" --yesno "Would you like to continue installation on an unsupported RPM based distribution?\\n\\nPlease ensure the following packages have been installed manually:\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+" "${r}" "${c}"; then - printf " %b Aborting installation due to unsupported RPM based distribution\\n" "${CROSS}" - exit - else - printf " %b Continuing installation with unsupported RPM based distribution\\n" "${INFO}" + ;; + + # User chose not to install PHP 7 via Remi's RPM repository + "${DIALOG_CANCEL}") + # User decided to NOT update PHP from REMI, attempt to install the default available PHP version + printf " %b User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use.\\n" "${INFO}" + ;; + + # User closed the dialog window + "${DIALOG_ESC}") + printf " %b Escape pressed, exiting installer at Remi dialog window\\n" "${CROSS}" + exit 1 + ;; + esac fi - fi + + else + # Warn user of unsupported version of Fedora or CentOS + dialog --no-shadow --keep-tite \ + --title "Unsupported RPM based distribution" \ + --defaultno \ + --no-button "Exit" \ + --yes-button "Continue" \ + --yesno "Would you like to continue installation on an unsupported RPM based distribution?\ +\\n\\nPlease ensure the following packages have been installed manually:\ +\\n\\n- lighttpd\\n- lighttpd-fastcgi\\n- PHP version 7+"\ + "${r}" "${c}" && result=0 || result=$? + + case ${result} in + # User chose to continue installation on an unsupported RPM based distribution + "${DIALOG_OK}") + printf " %b User opted to continue installation on an unsupported RPM based distribution.\\n" "${INFO}" + ;; + # User chose not to continue installation on an unsupported RPM based distribution + "${DIALOG_CANCEL}") + printf " %b User opted not to continue installation on an unsupported RPM based distribution.\\n" "${INFO}" + exit 1 + ;; + "${DIALOG_ESC}") + printf " %b Escape pressed, exiting installer at unsupported RPM based distribution dialog window\\n" "${CROSS}" + exit 1 + ;; + esac fi } @@ -625,40 +700,45 @@ get_available_interfaces() { # A function for displaying the dialogs the user sees when first running the installer welcomeDialogs() { # Display the welcome dialog using an appropriately sized window via the calculation conducted earlier in the script - whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" "${r}" "${c}" + dialog --no-shadow --clear --keep-tite \ + --backtitle "Welcome" \ + --title "Pi-hole Automated Installer" \ + --msgbox "\\n\\nThis installer will transform your device into a network-wide ad blocker!" \ + "${r}" "${c}" \ + --and-widget --clear \ + --backtitle "Support Pi-hole" \ + --title "Open Source Software" \ + --msgbox "\\n\\nThe Pi-hole is free, but powered by your donations: https://pi-hole.net/donate/" \ + "${r}" "${c}" \ + --and-widget --clear \ + --colors \ + --backtitle "Initiating network interface" \ + --title "Static IP Needed" \ + --no-button "Exit" --yes-button "Continue" \ + --defaultno \ + --yesno "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly.\\n\\n\ +\\Zb\\Z1IMPORTANT:\\Zn If you have not already done so, you must ensure that this device has a static IP.\\n\\n\ +Depending on your operating system, there are many ways to achieve this, through DHCP reservation, or by manually assigning one.\\n\\n\ +Please continue when the static addressing has been configured."\ + "${r}" "${c}" && result=0 || result="$?" - # Request that users donate if they enjoy the software since we all work on it in our free time - whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: https://pi-hole.net/donate/" "${r}" "${c}" - - # Explain the need for a static address - if whiptail --defaultno --backtitle "Initiating network interface" --title "Static IP Needed" --yesno "\\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly. - -IMPORTANT: If you have not already done so, you must ensure that this device has a static IP. Either through DHCP reservation, or by manually assigning one. Depending on your operating system, there are many ways to achieve this. - -Choose yes to indicate that you have understood this message, and wish to continue" "${r}" "${c}"; then - #Nothing to do, continue - echo - else - printf " %b Installer exited at static IP message.\\n" "${INFO}" - exit 1 - fi + case "${result}" in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Installer exited at static IP message.\\n" "${INFO}" + exit 1 + ;; + esac } # A function that lets the user pick an interface to use with Pi-hole chooseInterface() { - # Turn the available interfaces into an array so it can be used with a whiptail dialog - local interfacesArray=() + # Turn the available interfaces into a string so it can be used with dialog + local interfacesList # Number of available interfaces local interfaceCount - # Whiptail variable storage - local chooseInterfaceCmd - # Temporary Whiptail options storage - local chooseInterfaceOptions - # Loop sentinel variable - local firstLoop=1 - # Find out how many interfaces are available to choose from - interfaceCount=$(wc -l <<< "${availableInterfaces}") + # POSIX compliant way to get the number of elements in an array + interfaceCount=$(printf "%s\n" "${availableInterfaces}" | wc -l) # If there is one interface, if [[ "${interfaceCount}" -eq 1 ]]; then @@ -666,33 +746,33 @@ chooseInterface() { PIHOLE_INTERFACE="${availableInterfaces}" # Otherwise, else + # Set status for the first entry to be selected + status="ON" + # While reading through the available interfaces - while read -r line; do - # Use a variable to set the option as OFF to begin with - mode="OFF" - # If it's the first loop, - if [[ "${firstLoop}" -eq 1 ]]; then - # set this as the interface to use (ON) - firstLoop=0 - mode="ON" - fi - # Put all these interfaces into an array - interfacesArray+=("${line}" "available" "${mode}") - # Feed the available interfaces into this while loop - done <<< "${availableInterfaces}" - # The whiptail command that will be run, stored in a variable - chooseInterfaceCmd=(whiptail --separate-output --radiolist "Choose An Interface (press space to toggle selection)" "${r}" "${c}" 6) - # Now run the command using the interfaces saved into the array - chooseInterfaceOptions=$("${chooseInterfaceCmd[@]}" "${interfacesArray[@]}" 2>&1 >/dev/tty) || \ - # If the user chooses Cancel, exit - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } - # For each interface - for desiredInterface in ${chooseInterfaceOptions}; do - # Set the one the user selected as the interface to use - PIHOLE_INTERFACE=${desiredInterface} - # and show this information to the user - printf " %b Using interface: %s\\n" "${INFO}" "${PIHOLE_INTERFACE}" + for interface in ${availableInterfaces}; do + # Put all these interfaces into a string + interfacesList="${interfacesList}${interface} available ${status} " + # All further interfaces are deselected + status="OFF" done + # shellcheck disable=SC2086 + # Disable check for double quote here as we are passing a string with spaces + PIHOLE_INTERFACE=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label "Exit" --ok-label "Select" \ + --radiolist "Choose An Interface (press space to toggle selection)" \ + ${r} ${c} "${interfaceCount}" ${interfacesList}) + + result=$? + case ${result} in + "${DIALOG_CANCEL}"|"${DIALOG_ESC}") + # Show an error message and exit + printf " %b %s\\n" "${CROSS}" "No interface selected, exiting installer" + exit 1 + ;; + esac + + printf " %b Using interface: %s\\n" "${INFO}" "${PIHOLE_INTERFACE}" fi } @@ -778,57 +858,94 @@ getStaticIPv4Settings() { local ipSettingsCorrect local DHCPChoice # Ask if the user wants to use DHCP settings as their static IP - # This is useful for users that are using DHCP reservations; then we can just use the information gathered via our functions - DHCPChoice=$(whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --menu --separate-output "Do you want to use your current network settings as a static address? \\n - IP address: ${IPV4_ADDRESS} \\n - Gateway: ${IPv4gw} \\n" "${r}" "${c}" 3\ - "Yes" "Set static IP using current values" \ - "No" "Set static IP using custom values" \ - "Skip" "I will set a static IP later, or have already done so" 3>&2 2>&1 1>&3) || \ - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } + # This is useful for users that are using DHCP reservations; we can use the information gathered + DHCPChoice=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label "Exit" --ok-label "Continue" \ + --backtitle "Calibrating network interface" \ + --title "Static IP Address" \ + --menu "Do you want to use your current network settings as a static address?\\n \ + IP address: ${IPV4_ADDRESS}\\n \ + Gateway: ${IPv4gw}\\n" \ + "${r}" "${c}" 3 \ + "Yes" "Set static IP using current values" \ + "No" "Set static IP using custom values" \ + "Skip" "I will set a static IP later, or have already done so") - case ${DHCPChoice} in - "Yes") - # If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict. - whiptail --msgbox --backtitle "IP information" --title "FYI: IP Conflict" "It is possible your router could still try to assign this IP to a device, which would cause a conflict. But in most cases the router is smart enough to not do that. - If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want. - It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address." "${r}" "${c}" - # Nothing else to do since the variables are already set above - setDHCPCD - ;; + result=$? + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac - "No") - # Otherwise, we need to ask the user to input their desired settings. - # Start by getting the IPv4 address (pre-filling it with info gathered from DHCP) - # Start a loop to let the user enter their information with the chance to go back and edit it if necessary - until [[ "${ipSettingsCorrect}" = True ]]; do + case ${DHCPChoice} in + "Skip") + return + ;; + "Yes") + # If they choose yes, let the user know that the IP address will not be available via DHCP and may cause a conflict. + dialog --no-shadow --keep-tite \ + --cancel-label "Exit" \ + --backtitle "IP information" \ + --title "FYI: IP Conflict" \ + --msgbox "\\nIt is possible your router could still try to assign this IP to a device, which would cause a conflict\ +But in most cases the router is smart enough to not do that.\ +If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want.\ +It is also possible to use a DHCP reservation, but if you are going to do that, you might as well set a static address."\ + "${r}" "${c}" && result=0 || result=$? - # Ask for the IPv4 address - IPV4_ADDRESS=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 address" --inputbox "Enter your desired IPv4 address" "${r}" "${c}" "${IPV4_ADDRESS}" 3>&1 1>&2 2>&3) || \ - # Canceling IPv4 settings window - { ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; } - printf " %b Your static IPv4 address: %s\\n" "${INFO}" "${IPV4_ADDRESS}" + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac + ;; - # Ask for the gateway - IPv4gw=$(whiptail --backtitle "Calibrating network interface" --title "IPv4 gateway (router)" --inputbox "Enter your desired IPv4 default gateway" "${r}" "${c}" "${IPv4gw}" 3>&1 1>&2 2>&3) || \ - # Canceling gateway settings window - { ipSettingsCorrect=False; echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}"; exit 1; } - printf " %b Your static IPv4 gateway: %s\\n" "${INFO}" "${IPv4gw}" + "No") + # Otherwise, we need to ask the user to input their desired settings. + # Start by getting the IPv4 address (pre-filling it with info gathered from DHCP) + # Start a loop to let the user enter their information with the chance to go back and edit it if necessary + ipSettingsCorrect=false + until [[ "${ipSettingsCorrect}" = True ]]; do - # Give the user a chance to review their settings before moving on - if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno "Are these settings correct? - IP address: ${IPV4_ADDRESS} - Gateway: ${IPv4gw}" "${r}" "${c}"; then - # After that's done, the loop ends and we move on - ipSettingsCorrect=True - else - # If the settings are wrong, the loop continues - ipSettingsCorrect=False - fi + # Ask for the IPv4 address + _staticIPv4Temp=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancer-label "Exit" \ + --ok-label "Continue" \ + --backtitle "Calibrating network interface" \ + --title "IPv4 Address" \ + --form "\\nEnter your desired IPv4 address" \ + "${r}" "${c}" 0 \ + "IPv4 Address:" 1 1 "${IPV4_ADDRESS}" 1 15 19 0 \ + "IPv4 Gateway:" 2 1 "${IPv4gw}" 2 15 19 0) + + result=$? + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac + + IPV4_ADDRESS=${_staticIPv4Temp%$'\n'*} + IPv4gw=${_staticIPv4Temp#*$'\n'} + + # Give the user a chance to review their settings before moving on + dialog --no-shadow --keep-tite \ + --no-label "Edit IP" \ + --backtitle "Calibrating network interface" \ + --title "Static IP Address" \ + --defaultno \ + --yesno "Are these settings correct? + IP address: ${IPV4_ADDRESS} + Gateway: ${IPv4gw}" \ + "${r}" "${c}" && ipSettingsCorrect=True done - setDHCPCD - ;; - esac + ;; + esac + setDHCPCD } # Configure networking via dhcpcd @@ -918,11 +1035,19 @@ setDNS() { DNSChooseOptions[DNSServerCount]="" # Restore the IFS to what it was IFS=${OIFS} - # In a whiptail dialog, show the options - DNSchoices=$(whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." "${r}" "${c}" 7 \ - "${DNSChooseOptions[@]}" 2>&1 >/dev/tty) || \ - # Exit if the user selects "Cancel" - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } + # In a dialog, show the options + DNSchoices=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label "Exit" \ + --menu "Select Upstream DNS Provider. To use your own, select Custom." "${r}" "${c}" 7 \ + "${DNSChooseOptions[@]}") + + result=$? + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac # Depending on the user's choice, set the GLOBAL variables to the IP of the respective provider if [[ "${DNSchoices}" == "Custom" ]] @@ -936,7 +1061,7 @@ setDNS() { # If the first and second upstream servers do not exist, do not prepopulate an IP address prePopulate="" else - # Otherwise, prepopulate the whiptail dialogue with the appropriate DNS value(s) + # Otherwise, prepopulate the dialogue with the appropriate DNS value(s) prePopulate=", ${PIHOLE_DNS_2}" fi elif [[ "${PIHOLE_DNS_1}" ]] && [[ ! "${PIHOLE_DNS_2}" ]]; then @@ -946,8 +1071,22 @@ setDNS() { fi # Prompt the user to enter custom upstream servers - piholeDNS=$(whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" "${r}" "${c}" "${prePopulate}" 3>&1 1>&2 2>&3) || \ - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } + piholeDNS=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label "Exit" \ + --backtitle "Specify Upstream DNS Provider(s)" \ + --inputbox "Enter your desired upstream DNS provider(s), separated by a comma.\ +If you want to specify a port other than 53, separate it with a hash.\ +\\n\\nFor example '8.8.8.8, 8.8.4.4' or '127.0.0.1#5335'"\ + "${r}" "${c}" "${prePopulate}") + + result=$? + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac + # Clean user input and replace whitespace with comma. piholeDNS=$(sed 's/[, \t]\+/,/g' <<< "${piholeDNS}") @@ -966,7 +1105,13 @@ setDNS() { # If either of the DNS servers are invalid, if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]] || [[ "${PIHOLE_DNS_2}" == "${strInvalid}" ]]; then # explain this to the user, - whiptail --msgbox --backtitle "Invalid IP" --title "Invalid IP" "One or both entered IP addresses were invalid. Please try again.\\n\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" ${r} ${c} + dialog --no-shadow --keep-tite \ + --title "Invalid IP Address(es)" \ + --backtitle "Invalid IP" \ + --msgbox "\\nOne or both of the entered IP addresses were invalid. Please try again.\ +\\n\\nInvalid IPs: ${PIHOLE_DNS_1}, ${PIHOLE_DNS_2}" \ + "${r}" "${c}" + # set the variables back to nothing, if [[ "${PIHOLE_DNS_1}" == "${strInvalid}" ]]; then PIHOLE_DNS_1="" @@ -977,12 +1122,24 @@ setDNS() { # and continue the loop. DNSSettingsCorrect=False else - # Otherwise, show the DNS setting to the user, and break the loop if they confirm them. - if (whiptail --backtitle "Specify Upstream DNS Provider(s)" --title "Upstream DNS Provider(s)" --yesno "Are these settings correct?\\n DNS Server 1: $PIHOLE_DNS_1\\n DNS Server 2: ${PIHOLE_DNS_2}" "${r}" "${c}"); then - DNSSettingsCorrect=True - else - DNSSettingsCorrect=False - fi + dialog --no-shadow --keep-tite \ + --backtitle "Specify Upstream DNS Provider(s)" \ + --title "Upstream DNS Provider(s)" \ + --yesno "Are these settings correct?\\n\\tDNS Server 1:\\t${PIHOLE_DNS_1}\\n\\tDNS Server 2:\\t${PIHOLE_DNS_2}" \ + "${r}" "${c}" && result=0 || result=$? + + case ${result} in + "${DIALOG_OK}") + DNSSettingsCorrect=True + ;; + "${DIALOG_CANCEL}") + DNSSettingsCorrect=False + ;; + "${DIALOG_ESC}") + printf " %b Escape pressed, exiting installer at DNS Settings%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac fi done else @@ -1012,106 +1169,121 @@ setDNS() { # Allow the user to enable/disable logging setLogging() { - # Local, named variables - local LogToggleCommand - local LogChooseOptions - local LogChoices + # Ask the user if they want to enable logging + dialog --no-shadow --keep-tite \ + --backtitle "Pihole Installation" \ + --title "Enable Logging" \ + --yesno "\\n\\nWould you like to enable query logging?" \ + "${r}" "${c}" && result=0 || result=$? - # Ask if the user wants to log queries - LogToggleCommand=(whiptail --separate-output --radiolist "Do you want to log queries?" "${r}" "${c}" 6) - # The default selection is on - LogChooseOptions=("On (Recommended)" "" on - Off "" off) - # Get the user's choice - LogChoices=$("${LogToggleCommand[@]}" "${LogChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) - case ${LogChoices} in - # If it's on, - "On (Recommended)") - printf " %b Logging On.\\n" "${INFO}" - # set the GLOBAL variable setting to true + case ${result} in + "${DIALOG_OK}") + # If they chose yes, + printf " %b Query Logging on.\\n" "${INFO}" QUERY_LOGGING=true ;; - # Otherwise, it's off, - Off) - printf " %b Logging Off.\\n" "${INFO}" - # set the GLOBAL variable setting to false + "${DIALOG_CANCEL}") + # If they chose no, + printf " %b Query Logging off.\\n" "${INFO}" QUERY_LOGGING=false ;; + "${DIALOG_ESC}") + # User pressed + printf " %b Escape pressed, exiting installer at Query Logging choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; esac } # Allow the user to set their FTL privacy level setPrivacyLevel() { - local LevelCommand - local LevelOptions - - LevelCommand=(whiptail --separate-output --radiolist "Select a privacy mode for FTL. https://docs.pi-hole.net/ftldns/privacylevels/" "${r}" "${c}" 6) - # The default selection is level 0 - LevelOptions=( - "0" "Show everything" on - "1" "Hide domains" off - "2" "Hide domains and clients" off - "3" "Anonymous mode" off - ) + PRIVACY_LEVEL=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label "Exit" \ + --ok-label "Continue" \ + --radiolist "Select a privacy mode for FTL. https://docs.pi-hole.net/ftldns/privacylevels/" \ + "${r}" "${c}" 6 \ + "0" "Show everything" on \ + "1" "Hide domains" off \ + "2" "Hide domains and clients" off \ + "3" "Anonymous mode" off) - # Get the user's choice - PRIVACY_LEVEL=$("${LevelCommand[@]}" "${LevelOptions[@]}" 2>&1 >/dev/tty) || (echo -e " ${COL_LIGHT_RED}Cancel was selected, exiting installer${COL_NC}" && exit 1) - - printf " %b Privacy level %d" "${INFO}" "${PRIVACY_LEVEL}" + result=$? + case ${result} in + "${DIALOG_OK}") + printf " %b Using privacy level: %s\\n" "${INFO}" "${PRIVACY_LEVEL}" + ;; + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancelled privacy level selection.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac } # Function to ask the user if they want to install the dashboard setAdminFlag() { - # Local, named variables - local WebToggleCommand - local WebChooseOptions - local WebChoices - # Similar to the logging function, ask what the user wants - WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web admin interface?" "${r}" "${c}" 6) - # with the default being enabled - WebChooseOptions=("On (Recommended)" "" on - Off "" off) - WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) - # Depending on their choice - case ${WebChoices} in - "On (Recommended)") - printf " %b Web Interface On\\n" "${INFO}" - # Set it to true + dialog --no-shadow --keep-tite \ + --backtitle "Pihole Installation" \ + --title "Admin Web Interface" \ + --yesno "\\n\\nDo you want to install the Admin Web Interface?" \ + "${r}" "${c}" && result=0 || result=$? + + case ${result} in + "${DIALOG_OK}") + # If they chose yes, + printf " %b Installing Admin Web Interface\\n" "${INFO}" + # Set the flag to install the web interface INSTALL_WEB_INTERFACE=true ;; - Off) - printf " %b Web Interface Off\\n" "${INFO}" - # or false + "${DIALOG_CANCEL}") + # If they chose no, + printf " %b Not installing Admin Web Interface\\n" "${INFO}" + # Set the flag to not install the web interface INSTALL_WEB_INTERFACE=false - # Deselect the web server as well, since it is obsolete then INSTALL_WEB_SERVER=false ;; + "${DIALOG_ESC}") + # User pressed + printf " %b Escape pressed, exiting installer at Admin Web Interface choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; esac # If the user wants to install the Web admin interface (i.e. it has not been deselected above) - if [[ "${INSTALL_WEB_SERVER}" == true ]]; then + if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then # Get list of required PHP modules, excluding base package (common) and handler (cgi) local i php_modules for i in "${PIHOLE_WEB_DEPS[@]}"; do [[ $i == 'php'* && $i != *'-common' && $i != *'-cgi' ]] && php_modules+=" ${i#*-}"; done - WebToggleCommand=(whiptail --separate-output --radiolist "Do you wish to install the web server (lighttpd) and required PHP modules?\\n\\nNB: If you disable this, and, do not have an existing web server and required PHP modules (${php_modules# }) installed, the web interface will not function. Additionally the web server user needs to be member of the \"pihole\" group for full functionality." "${r}" "${c}" 6) - # Enable as default and recommended option - WebChooseOptions=("On (Recommended)" "" on - Off "" off) - WebChoices=$("${WebToggleCommand[@]}" "${WebChooseOptions[@]}" 2>&1 >/dev/tty) || (printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" && exit 1) - # Depending on their choice - case ${WebChoices} in - "On (Recommended)") - printf " %b Web Server On\\n" "${INFO}" - # set it to true, as clearly seen below. + dialog --no-shadow --keep-tite \ + --backtitle "Pi-hole Installation" \ + --title "Web Server" \ + --yesno "\\n\\nA web server is required for the Admin Web Interface.\ +\\n\\nDo you want to install lighttpd and the required PHP modules?\ +\\n\\nNB: If you disable this, and, do not have an existing web server \ +and required PHP modules (${php_modules# }) installed, the web interface \ +will not function. Additionally the web server user needs to be member of \ +the \"pihole\" group for full functionality." \ + "${r}" "${c}" && result=0 || result=$? + + case ${result} in + "${DIALOG_OK}") + # If they chose yes, + printf " %b Installing lighttpd\\n" "${INFO}" + # Set the flag to install the web server INSTALL_WEB_SERVER=true ;; - Off) - printf " %b Web Server Off\\n" "${INFO}" - # or false + "${DIALOG_CANCEL}") + # If they chose no, + printf " %b Not installing lighttpd\\n" "${INFO}" + # Set the flag to not install the web server INSTALL_WEB_SERVER=false ;; + "${DIALOG_ESC}") + # User pressed + printf " %b Escape pressed, exiting installer at web server choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; esac fi } @@ -1122,18 +1294,32 @@ chooseBlocklists() { if [[ -f "${adlistFile}" ]]; then mv "${adlistFile}" "${adlistFile}.old" fi - # Let user select (or not) blocklists via a checklist - cmd=(whiptail --separate-output --checklist "Pi-hole relies on third party lists in order to block ads.\\n\\nYou can use the suggestion below, and/or add your own after installation\\n\\nTo deselect the suggested list, use spacebar" "${r}" "${c}" 5) - # In an array, show the options available (all off by default): - options=(StevenBlack "StevenBlack's Unified Hosts List" on) + # Let user select (or not) blocklists + dialog --no-shadow --keep-tite \ + --backtitle "Pi-hole Installation" \ + --title "Blocklists" \ + --yesno "\\nPi-hole relies on third party lists in order to block ads.\ +\\n\\nYou can use the suggestion below, and/or add your own after installation.\ +\\n\\nSelect 'Yes' to include:\ +\\n\\nStevenBlack's Unified Hosts List" \ + "${r}" "${c}" && result=0 || result=$? - # In a variable, show the choices available; exit if Cancel is selected - choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty) || { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; rm "${adlistFile}" ;exit 1; } - # Add all selected choices to the lists file - for choice in ${choices} - do - appendToListsFile "${choice}" - done + case ${result} in + "${DIALOG_OK}") + # If they chose yes, + printf " %b Installing StevenBlack's Unified Hosts List\\n" "${INFO}" + echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}" + ;; + "${DIALOG_CANCEL}") + # If they chose no, + printf " %b Not installing StevenBlack's Unified Hosts List\\n" "${INFO}" + ;; + "${DIALOG_ESC}") + # User pressed + printf " %b Escape pressed, exiting installer at blocklist choice.%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac # Create an empty adList file with appropriate permissions. if [ ! -f "${adlistFile}" ]; then install -m 644 /dev/null "${adlistFile}" @@ -1142,14 +1328,6 @@ chooseBlocklists() { fi } -# Accept a string parameter, it must be one of the default lists -# This function saves duplication between chooseBlocklists and installDefaultBlocklists -appendToListsFile() { - case $1 in - StevenBlack ) echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}";; - esac -} - # Used only in unattended setup # If there is already the adListFile, we keep it, else we create it using all default lists installDefaultBlocklists() { @@ -1158,7 +1336,7 @@ installDefaultBlocklists() { if [[ -f "${adlistFile}" ]]; then return; fi - appendToListsFile StevenBlack + echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> "${adlistFile}" } # Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory @@ -1313,7 +1491,7 @@ installConfigs() { if [[ ! -r "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" ]]; then install -d -m 0755 ${PI_HOLE_CONFIG_DIR} if ! install -T -o pihole -m 664 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.conf" "${PI_HOLE_CONFIG_DIR}/pihole-FTL.conf" &>/dev/null; then - printf " %bError: Unable to initialize configuration file %s/pihole-FTL.conf\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}" + printf " %b Error: Unable to initialize configuration file %s/pihole-FTL.conf\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}" return 1 fi fi @@ -1321,11 +1499,14 @@ installConfigs() { # Install empty custom.list file if it does not exist if [[ ! -r "${PI_HOLE_CONFIG_DIR}/custom.list" ]]; then if ! install -o root -m 644 /dev/null "${PI_HOLE_CONFIG_DIR}/custom.list" &>/dev/null; then - printf " %bError: Unable to initialize configuration file %s/custom.list\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}" + printf " %b Error: Unable to initialize configuration file %s/custom.list\\n" "${COL_LIGHT_RED}" "${PI_HOLE_CONFIG_DIR}" return 1 fi fi + # Install pihole-FTL.service + install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" "/etc/init.d/pihole-FTL" + # If the user chose to install the dashboard, if [[ "${INSTALL_WEB_SERVER}" == true ]]; then # and if the Web server conf directory does not exist, @@ -1478,7 +1659,7 @@ disable_resolved_stublistener() { # Check if Systemd-resolved's DNSStubListener is enabled and active on port 53 if check_service_active "systemd-resolved"; then # Check if DNSStubListener is enabled - printf " %b %b Testing if systemd-resolved DNSStub-Listener is active" "${OVER}" "${INFO}" + printf " %b %b Testing if systemd-resolved DNSStub-Listener is active" "${OVER}" "${INFO}" if ( grep -E '#?DNSStubListener=yes' /etc/systemd/resolved.conf &> /dev/null ); then # Disable the DNSStubListener to unbind it from port 53 # Note that this breaks dns functionality on host until dnsmasq/ftl are up and running @@ -1515,7 +1696,7 @@ update_package_cache() { UPDATE_PKG_CACHE="apt update" fi printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %bError: Unable to update package cache. Please try \"%s\"%b\\n" "${COL_LIGHT_RED}" "sudo ${UPDATE_PKG_CACHE}" "${COL_NC}" + printf " %b Error: Unable to update package cache. Please try \"%s\"%b\\n" "${COL_LIGHT_RED}" "sudo ${UPDATE_PKG_CACHE}" "${COL_NC}" return 1 fi } @@ -1731,29 +1912,14 @@ create_pihole_user() { # This function saves any changes to the setup variables into the setupvars.conf file for future runs finalExports() { - # If the Web interface is not set to be installed, - if [[ "${INSTALL_WEB_INTERFACE}" == false ]]; then - # and if there is not an IPv4 address, - if [[ "${IPV4_ADDRESS}" ]]; then - # there is no block page, so set IPv4 to 0.0.0.0 (all IP addresses) - IPV4_ADDRESS="0.0.0.0" - fi - if [[ "${IPV6_ADDRESS}" ]]; then - # and IPv6 to ::/0 - IPV6_ADDRESS="::/0" - fi - fi - # If the setup variable file exists, if [[ -e "${setupVars}" ]]; then # update the variables in the file - sed -i.update.bak '/PIHOLE_INTERFACE/d;/IPV4_ADDRESS/d;/IPV6_ADDRESS/d;/PIHOLE_DNS_1\b/d;/PIHOLE_DNS_2\b/d;/QUERY_LOGGING/d;/INSTALL_WEB_SERVER/d;/INSTALL_WEB_INTERFACE/d;/LIGHTTPD_ENABLED/d;/CACHE_SIZE/d;/DNS_FQDN_REQUIRED/d;/DNS_BOGUS_PRIV/d;/DNSMASQ_LISTENING/d;' "${setupVars}" + sed -i.update.bak '/PIHOLE_INTERFACE/d;/PIHOLE_DNS_1\b/d;/PIHOLE_DNS_2\b/d;/QUERY_LOGGING/d;/INSTALL_WEB_SERVER/d;/INSTALL_WEB_INTERFACE/d;/LIGHTTPD_ENABLED/d;/CACHE_SIZE/d;/DNS_FQDN_REQUIRED/d;/DNS_BOGUS_PRIV/d;/DNSMASQ_LISTENING/d;' "${setupVars}" fi # echo the information to the user { echo "PIHOLE_INTERFACE=${PIHOLE_INTERFACE}" - echo "IPV4_ADDRESS=${IPV4_ADDRESS}" - echo "IPV6_ADDRESS=${IPV6_ADDRESS}" echo "PIHOLE_DNS_1=${PIHOLE_DNS_1}" echo "PIHOLE_DNS_2=${PIHOLE_DNS_2}" echo "QUERY_LOGGING=${QUERY_LOGGING}" @@ -1935,20 +2101,17 @@ displayFinalMessage() { # If the user wants to install the dashboard, if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then # Store a message in a variable and display it - additional="View the web interface at http://pi.hole/admin or http://${IPV4_ADDRESS%/*}/admin - -Your Admin Webpage login password is ${pwstring}" + additional="View the web interface at http://pi.hole/admin or http://${IPV4_ADDRESS%/*}/admin\\n\\nYour Admin Webpage login password is ${pwstring}" fi # Final completion message to user - whiptail --msgbox --backtitle "Make it so." --title "Installation Complete!" "Configure your devices to use the Pi-hole as their DNS server using: - -IPv4: ${IPV4_ADDRESS%/*} -IPv6: ${IPV6_ADDRESS:-"Not Configured"} - -If you have not done so already, the above IP should be set to static. - -${additional}" "${r}" "${c}" + dialog --no-shadow --keep-tite \ + --title "Installation Complete!" \ + --msgbox "Configure your devices to use the Pi-hole as their DNS server using:\ +\\n\\nIPv4: ${IPV4_ADDRESS%/*}\ +\\nIPv6: ${IPV6_ADDRESS:-"Not Configured"}\ +\\nIf you have not done so already, the above IP should be set to static.\ +\\n${additional}" "${r}" "${c}" } update_dialogs() { @@ -1968,20 +2131,33 @@ update_dialogs() { opt2b="Resets Pi-hole and allows re-selecting settings." # Display the information to the user - UpdateCmd=$(whiptail --title "Existing Install Detected!" --menu "\\n\\nWe have detected an existing install.\\n\\nPlease choose from the following options: \\n($strAdd)" "${r}" "${c}" 2 \ + UpdateCmd=$(dialog --no-shadow --keep-tite --output-fd 1 \ + --cancel-label Exit \ + --title "Existing Install Detected!" \ + --menu "\\n\\nWe have detected an existing install.\ +\\n\\nPlease choose from the following options:\ +\\n($strAdd)"\ + "${r}" "${c}" 2 \ "${opt1a}" "${opt1b}" \ - "${opt2a}" "${opt2b}" 3>&2 2>&1 1>&3) || \ - { printf " %bCancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}"; exit 1; } + "${opt2a}" "${opt2b}" || true) + + result=$? + case ${result} in + "${DIALOG_CANCEL}" | "${DIALOG_ESC}") + printf " %b Cancel was selected, exiting installer%b\\n" "${COL_LIGHT_RED}" "${COL_NC}" + exit 1 + ;; + esac # Set the variable based on if the user chooses case ${UpdateCmd} in # repair, or - ${opt1a}) + "${opt1a}") printf " %b %s option selected\\n" "${INFO}" "${opt1a}" useUpdateVars=true ;; # reconfigure, - ${opt2a}) + "${opt2a}") printf " %b %s option selected\\n" "${INFO}" "${opt2a}" useUpdateVars=false ;; @@ -2077,14 +2253,14 @@ clone_or_update_repos() { printf " %b Performing reconfiguration, skipping download of local repos\\n" "${INFO}" # Reset the Core repo resetRepo ${PI_HOLE_LOCAL_REPO} || \ - { printf " %bUnable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \ + { printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \ exit 1; \ } # If the Web interface was installed, if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then # reset it's repo resetRepo ${webInterfaceDir} || \ - { printf " %bUnable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceDir}" "${COL_NC}"; \ + { printf " %b Unable to reset %s, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceDir}" "${COL_NC}"; \ exit 1; \ } fi @@ -2092,14 +2268,14 @@ clone_or_update_repos() { else # so get git files for Core getGitFiles ${PI_HOLE_LOCAL_REPO} ${piholeGitUrl} || \ - { printf " %bUnable to clone %s into %s, unable to continue%b\\n" "${COL_LIGHT_RED}" "${piholeGitUrl}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \ + { printf " %b Unable to clone %s into %s, unable to continue%b\\n" "${COL_LIGHT_RED}" "${piholeGitUrl}" "${PI_HOLE_LOCAL_REPO}" "${COL_NC}"; \ exit 1; \ } # If the Web interface was installed, if [[ "${INSTALL_WEB_INTERFACE}" == true ]]; then # get the Web git files getGitFiles ${webInterfaceDir} ${webInterfaceGitUrl} || \ - { printf " %bUnable to clone %s into ${webInterfaceDir}, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceGitUrl}" "${COL_NC}"; \ + { printf " %b Unable to clone %s into ${webInterfaceDir}, exiting installer%b\\n" "${COL_LIGHT_RED}" "${webInterfaceGitUrl}" "${COL_NC}"; \ exit 1; \ } fi @@ -2117,9 +2293,6 @@ FTLinstall() { # Move into the temp ftl directory pushd "$(mktemp -d)" > /dev/null || { printf "Unable to make temporary directory for FTL binary download\\n"; return 1; } - # Always replace pihole-FTL.service - install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" "/etc/init.d/pihole-FTL" - local ftlBranch local url @@ -2166,7 +2339,7 @@ FTLinstall() { # Otherwise, the hash download failed, so print and exit. popd > /dev/null || { printf "Unable to return to original directory after FTL binary download.\\n"; return 1; } printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" - printf " %bError: Download of %s/%s failed (checksum error)%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" + printf " %b Error: Download of %s/%s failed (checksum error)%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" return 1 fi else @@ -2174,7 +2347,7 @@ FTLinstall() { popd > /dev/null || { printf "Unable to return to original directory after FTL binary download.\\n"; return 1; } printf "%b %b %s\\n" "${OVER}" "${CROSS}" "${str}" # The URL could not be found - printf " %bError: URL %s/%s not found%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" + printf " %b Error: URL %s/%s not found%b\\n" "${COL_LIGHT_RED}" "${url}" "${binary}" "${COL_NC}" return 1 fi } @@ -2453,6 +2626,9 @@ main() { fi fi + # Check if SELinux is Enforcing and exit before doing anything else + checkSelinux + # Check for supported package managers so that we may install dependencies package_manager_detect @@ -2475,14 +2651,12 @@ main() { select_rpm_php fi - # Check if SELinux is Enforcing - checkSelinux # If the setup variable file exists, if [[ -f "${setupVars}" ]]; then # if it's running unattended, if [[ "${runUnattended}" == true ]]; then - printf " %b Performing unattended setup, no whiptail dialogs will be displayed\\n" "${INFO}" + printf " %b Performing unattended setup, no dialogs will be displayed\\n" "${INFO}" # Use the setup variables useUpdateVars=true # also disable debconf-apt-progress dialogs @@ -2613,6 +2787,31 @@ main() { # Fixes a problem reported on Ubuntu 18.04 where trying to start # the service before enabling causes installer to exit enable_service pihole-FTL + + # If this is an update from a previous Pi-hole installation + # we need to move any existing `pihole*` logs from `/var/log` to `/var/log/pihole` + # if /var/log/pihole.log is not a symlink (set during FTL startup) move the files + # can be removed with Pi-hole v6.0 + # To be sure FTL is not running when we move the files we explicitly stop it here + + stop_service pihole-FTL &> /dev/null + + # Special handling for pihole-FTL.log -> pihole/FTL.log + if [ -f /var/log/pihole-FTL.log ] && [ ! -L /var/log/pihole-FTL.log ]; then + # /var/log/pihole-FTL.log -> /var/log/pihole/FTL.log + # /var/log/pihole-FTL.log.1 -> /var/log/pihole/FTL.log.1 + # /var/log/pihole-FTL.log.2.gz -> /var/log/pihole/FTL.log.2.gz + # /var/log/pihole-FTL.log.3.gz -> /var/log/pihole/FTL.log.3.gz + # /var/log/pihole-FTL.log.4.gz -> /var/log/pihole/FTL.log.4.gz + # /var/log/pihole-FTL.log.5.gz -> /var/log/pihole/FTL.log.5.gz + for f in /var/log/pihole-FTL.log*; do mv "$f" "$( sed "s/pihole-/pihole\//" <<< "$f")"; done + fi + + # Remaining log files + if [ -f /var/log/pihole.log ] && [ ! -L /var/log/pihole.log ]; then + mv /var/log/pihole*.* /var/log/pihole/ 2>/dev/null + fi + restart_service pihole-FTL # Download and compile the aggregated block list diff --git a/automated install/uninstall.sh b/automated install/uninstall.sh index 9d3fca31..a0bb2e5b 100755 --- a/automated install/uninstall.sh +++ b/automated install/uninstall.sh @@ -146,6 +146,7 @@ removeNoPurge() { ${SUDO} rm -f /etc/dnsmasq.d/01-pihole.conf &> /dev/null ${SUDO} rm -f /etc/dnsmasq.d/06-rfc6761.conf &> /dev/null ${SUDO} rm -rf /var/log/*pihole* &> /dev/null + ${SUDO} rm -rf /var/log/pihole/*pihole* &> /dev/null ${SUDO} rm -rf /etc/pihole/ &> /dev/null ${SUDO} rm -rf /etc/.pihole/ &> /dev/null ${SUDO} rm -rf /opt/pihole/ &> /dev/null diff --git a/gravity.sh b/gravity.sh index c5e9e414..77974694 100755 --- a/gravity.sh +++ b/gravity.sh @@ -540,7 +540,7 @@ parseList() { num_target_lines_new="$(grep -c "^" "${target}")" # Number of new correctly added lines num_correct_lines="$(( num_target_lines_new-num_target_lines ))" - # Upate number of lines in target file + # Update number of lines in target file num_target_lines="$num_target_lines_new" num_invalid="$(( num_source_lines-num_correct_lines ))" if [[ "${num_invalid}" -eq 0 ]]; then diff --git a/manpages/pihole.8 b/manpages/pihole.8 index aaaa8d7e..4b1e5154 100644 --- a/manpages/pihole.8 +++ b/manpages/pihole.8 @@ -187,12 +187,12 @@ Available commands and options: (Logging options): .br - on Enable the Pi-hole log at /var/log/pihole.log + on Enable the Pi-hole log at /var/log/pihole/pihole.log .br off Disable and flush the Pi-hole log at - /var/log/pihole.log + /var/log/pihole/pihole.log .br - off noflush Disable the Pi-hole log at /var/log/pihole.log + off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log .br \fB-up, updatePihole\fR [--check-only] diff --git a/pihole b/pihole index f51fd956..c54a3192 100755 --- a/pihole +++ b/pihole @@ -254,9 +254,9 @@ Example: 'pihole logging on' Specify whether the Pi-hole log should be used Options: - on Enable the Pi-hole log at /var/log/pihole.log - off Disable and flush the Pi-hole log at /var/log/pihole.log - off noflush Disable the Pi-hole log at /var/log/pihole.log" + on Enable the Pi-hole log at /var/log/pihole/pihole.log + off Disable and flush the Pi-hole log at /var/log/pihole/pihole.log + off noflush Disable the Pi-hole log at /var/log/pihole/pihole.log" exit 0 elif [[ "${1}" == "off" ]]; then # Disable logging @@ -382,7 +382,7 @@ tailFunc() { # Color blocklist/blacklist/wildcard entries as red # Color A/AAAA/DHCP strings as white # Color everything else as gray - tail -f /var/log/pihole.log | grep --line-buffered "${1}" | sed -E \ + tail -f /var/log/pihole/pihole.log | grep --line-buffered "${1}" | sed -E \ -e "s,($(date +'%b %d ')| dnsmasq\[[0-9]*\]),,g" \ -e "s,(.*(blacklisted |gravity blocked ).*),${COL_RED}&${COL_NC}," \ -e "s,.*(query\\[A|DHCP).*,${COL_NC}&${COL_NC}," \ @@ -503,7 +503,7 @@ case "${1}" in "-c" | "chronometer" ) chronometerFunc "$@";; "-q" | "query" ) queryFunc "$@";; "status" ) statusFunc "$2";; - "-t" | "tail" ) tailFunc "$2";; + "tricorder" ) tricorderFunc;; # we need to add all arguments that require sudo power to not trigger the * argument @@ -527,6 +527,7 @@ case "${1}" in "checkout" ) ;; "updatechecker" ) ;; "arpflush" ) ;; + "-t" | "tail" ) ;; * ) helpFunc;; esac @@ -563,4 +564,5 @@ case "${1}" in "checkout" ) piholeCheckoutFunc "$@";; "updatechecker" ) updateCheckFunc "$@";; "arpflush" ) arpFunc "$@";; + "-t" | "tail" ) tailFunc "$2";; esac diff --git a/test/_centos_7.Dockerfile b/test/_centos_7.Dockerfile index 355f4fdb..ccffc00d 100644 --- a/test/_centos_7.Dockerfile +++ b/test/_centos_7.Dockerfile @@ -1,5 +1,5 @@ FROM centos:7 -RUN yum install -y git +RUN yum install -y dialog git python3 ENV GITDIR /etc/.pihole ENV SCRIPTDIR /opt/pihole @@ -9,6 +9,7 @@ ADD . $GITDIR RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $SCRIPTDIR/ ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR +ADD test/centos7.epel.override /etc/yum/pluginconf.d/fastestmirror.conf RUN true && \ chmod +x $SCRIPTDIR/* diff --git a/test/_fedora_33.Dockerfile b/test/_fedora_33.Dockerfile deleted file mode 100644 index 5cdd66ee..00000000 --- a/test/_fedora_33.Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM fedora:33 -RUN dnf install -y 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 $SCRIPTDIR/ -ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR - -RUN true && \ - chmod +x $SCRIPTDIR/* - -ENV PH_TEST 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 && \ diff --git a/test/_ubuntu_16.Dockerfile b/test/_ubuntu_16.Dockerfile deleted file mode 100644 index e572efd1..00000000 --- a/test/_ubuntu_16.Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM buildpack-deps:xenial-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 $SCRIPTDIR/ -ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$SCRIPTDIR - -RUN true && \ - chmod +x $SCRIPTDIR/* - -ENV PH_TEST 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 && \ \ No newline at end of file diff --git a/test/_debian_9.Dockerfile b/test/_ubuntu_22.Dockerfile similarity index 88% rename from test/_debian_9.Dockerfile rename to test/_ubuntu_22.Dockerfile index c590a657..f9876d50 100644 --- a/test/_debian_9.Dockerfile +++ b/test/_ubuntu_22.Dockerfile @@ -1,4 +1,4 @@ -FROM buildpack-deps:stretch-scm +FROM buildpack-deps:jammy-scm ENV GITDIR /etc/.pihole ENV SCRIPTDIR /opt/pihole @@ -7,6 +7,7 @@ RUN mkdir -p $GITDIR $SCRIPTDIR /etc/pihole ADD . $GITDIR RUN cp $GITDIR/advanced/Scripts/*.sh $GITDIR/gravity.sh $GITDIR/pihole $GITDIR/automated\ install/*.sh $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/* diff --git a/test/centos7.epel.override b/test/centos7.epel.override new file mode 100644 index 00000000..3451f17d --- /dev/null +++ b/test/centos7.epel.override @@ -0,0 +1,7 @@ +[main] +verbose = 0 +socket_timeout = 3 +enabled = 1 +hostfilepath = /var/cache/yum/timedhosts.txt +maxhostfileage = 1 +exclude=.edu diff --git a/test/test_any_automated_install.py b/test/test_any_automated_install.py index 41a939e0..61849f54 100644 --- a/test/test_any_automated_install.py +++ b/test/test_any_automated_install.py @@ -150,10 +150,10 @@ def get_directories_recursive(host, directory): def test_installPihole_fresh_install_readableFiles(host): ''' - confirms all neccessary files are readable by pihole user + confirms all necessary files are readable by pihole user ''' - # Whiptail dialog returns Cancel for user prompt - mock_command('whiptail', {'*': ('', '0')}, host) + # dialog returns Cancel for user prompt + mock_command('dialog', {'*': ('', '0')}, host) # mock git pull mock_command_passthrough('git', {'pull': ('', '0')}, host) # mock systemctl to not start lighttpd and FTL @@ -393,8 +393,8 @@ def test_installPihole_fresh_install_readableBlockpage(host, test_webpage): "127.0.0.1", # "pi.hole" ] - # Whiptail dialog returns Cancel for user prompt - mock_command('whiptail', {'*': ('', '0')}, host) + # dialog returns Cancel for user prompt + mock_command('dialog', {'*': ('', '0')}, host) # mock git pull mock_command_passthrough('git', {'pull': ('', '0')}, host) @@ -483,7 +483,6 @@ def test_installPihole_fresh_install_readableBlockpage(host, test_webpage): setup_var_file += "{}={}\n".format(k, v) setup_var_file += "INSTALL_WEB_SERVER=true\n" setup_var_file += "INSTALL_WEB_INTERFACE=true\n" - setup_var_file += "IPV4_ADDRESS=127.0.0.1\n" setup_var_file += "EOF\n" host.run(setup_var_file) installWeb = host.run(''' @@ -871,8 +870,8 @@ def test_FTL_download_aarch64_no_errors(host): ''' confirms only aarch64 package is downloaded for FTL engine ''' - # mock whiptail answers and ensure installer dependencies - mock_command('whiptail', {'*': ('', '0')}, host) + # mock dialog answers and ensure installer dependencies + mock_command('dialog', {'*': ('', '0')}, host) host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -905,23 +904,6 @@ def test_FTL_binary_installed_and_responsive_no_errors(host): assert expected_stdout in installed_binary.stdout -# def test_FTL_support_files_installed(host): -# ''' -# confirms FTL support files are installed -# ''' -# support_files = host.run(''' -# source /opt/pihole/basic-install.sh -# FTLdetect -# stat -c '%a %n' /var/log/pihole-FTL.log -# stat -c '%a %n' /run/pihole-FTL.port -# stat -c '%a %n' /run/pihole-FTL.pid -# ls -lac /run -# ''') -# assert '644 /run/pihole-FTL.port' in support_files.stdout -# assert '644 /run/pihole-FTL.pid' in support_files.stdout -# assert '644 /var/log/pihole-FTL.log' in support_files.stdout - - def test_IPv6_only_link_local(host): ''' confirms IPv6 blocking is disabled for Link-local address @@ -1118,7 +1100,7 @@ def test_os_check_passes(host): def test_package_manager_has_installer_deps(host): ''' Confirms OS is able to install the required packages for the installer''' - mock_command('whiptail', {'*': ('', '0')}, host) + mock_command('dialog', {'*': ('', '0')}, host) output = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -1131,7 +1113,7 @@ def test_package_manager_has_installer_deps(host): def test_package_manager_has_pihole_deps(host): ''' Confirms OS is able to install the required packages for Pi-hole ''' - mock_command('whiptail', {'*': ('', '0')}, host) + mock_command('dialog', {'*': ('', '0')}, host) output = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -1145,7 +1127,7 @@ def test_package_manager_has_pihole_deps(host): def test_package_manager_has_web_deps(host): ''' Confirms OS is able to install the required packages for web ''' - mock_command('whiptail', {'*': ('', '0')}, host) + mock_command('dialog', {'*': ('', '0')}, host) output = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect diff --git a/test/test_centos_7_support.py b/test/test_centos_7_support.py index f72740a6..c7e75813 100644 --- a/test/test_centos_7_support.py +++ b/test/test_centos_7_support.py @@ -26,8 +26,8 @@ def test_php_upgrade_user_optout_centos_eq_7(host): confirms installer behavior when user opt-out of installing PHP7 from REMI (php not currently installed) ''' - # Whiptail dialog returns Cancel for user prompt - mock_command('whiptail', {'*': ('', '1')}, host) + # dialog returns Cancel for user prompt + mock_command('dialog', {'*': ('', '1')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -45,8 +45,8 @@ def test_php_upgrade_user_optin_centos_eq_7(host): confirms installer behavior when user opt-in to installing PHP7 from REMI (php not currently installed) ''' - # Whiptail dialog returns Continue for user prompt - mock_command('whiptail', {'*': ('', '0')}, host) + # dialog returns Continue for user prompt + mock_command('dialog', {'*': ('', '0')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect diff --git a/test/test_centos_8_support.py b/test/test_centos_8_support.py index 464055b4..9adbe841 100644 --- a/test/test_centos_8_support.py +++ b/test/test_centos_8_support.py @@ -29,8 +29,8 @@ def test_php_upgrade_user_optout_skipped_centos_gte_8(host): latest CentOS (should trigger on CentOS7 only) (php not currently installed) ''' - # Whiptail dialog returns Cancel for user prompt - mock_command('whiptail', {'*': ('', '1')}, host) + # dialog dialog returns Cancel for user prompt + mock_command('dialog', {'*': ('', '1')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -50,8 +50,8 @@ def test_php_upgrade_user_optin_skipped_centos_gte_8(host): latest CentOS (should trigger on CentOS7 only) (php not currently installed) ''' - # Whiptail dialog returns Continue for user prompt - mock_command('whiptail', {'*': ('', '0')}, host) + # dialog dialog returns Continue for user prompt + mock_command('dialog', {'*': ('', '0')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect diff --git a/test/test_centos_common_support.py b/test/test_centos_common_support.py index 8903a7a0..ac408e92 100644 --- a/test/test_centos_common_support.py +++ b/test/test_centos_common_support.py @@ -36,7 +36,7 @@ def test_enable_epel_repository_centos(host): expected_stdout = info_box + (' Enabling EPEL package repository ' '(https://fedoraproject.org/wiki/EPEL)') assert expected_stdout in package_manager_detect.stdout - expected_stdout = tick_box + ' Installed epel-release' + expected_stdout = tick_box + ' Installed' assert expected_stdout in package_manager_detect.stdout epel_package = host.package('epel-release') assert epel_package.is_installed @@ -76,8 +76,8 @@ def test_php_version_lt_7_detected_upgrade_user_optout_centos(host): default_centos_php_version = php_package.version.split('.')[0] if int(default_centos_php_version) >= 7: # PHP7 is supported/recommended pytest.skip("Test deprecated . Detected default PHP version >= 7") - # Whiptail dialog returns Cancel for user prompt - mock_command('whiptail', {'*': ('', '1')}, host) + # dialog returns Cancel for user prompt + mock_command('dialog', {'*': ('', '1')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect @@ -101,8 +101,8 @@ def test_php_version_lt_7_detected_upgrade_user_optin_centos(host): default_centos_php_version = php_package.version.split('.')[0] if int(default_centos_php_version) >= 7: # PHP7 is supported/recommended pytest.skip("Test deprecated . Detected default PHP version >= 7") - # Whiptail dialog returns Continue for user prompt - mock_command('whiptail', {'*': ('', '0')}, host) + # dialog returns Continue for user prompt + mock_command('dialog', {'*': ('', '0')}, host) package_manager_detect = host.run(''' source /opt/pihole/basic-install.sh package_manager_detect diff --git a/test/tox.debian_9.ini b/test/tox.debian_9.ini deleted file mode 100644 index 56b9d37f..00000000 --- a/test/tox.debian_9.ini +++ /dev/null @@ -1,8 +0,0 @@ -[tox] -envlist = py38 - -[testenv] -whitelist_externals = docker -deps = -rrequirements.txt -commands = docker build -f _debian_9.Dockerfile -t pytest_pihole:test_container ../ - pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py diff --git a/test/tox.fedora_33.ini b/test/tox.fedora_33.ini deleted file mode 100644 index b17bd563..00000000 --- a/test/tox.fedora_33.ini +++ /dev/null @@ -1,8 +0,0 @@ -[tox] -envlist = py38 - -[testenv] -whitelist_externals = docker -deps = -rrequirements.txt -commands = docker build -f _fedora_33.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 ./test_fedora_support.py diff --git a/test/tox.ubuntu_16.ini b/test/tox.ubuntu_22.ini similarity index 75% rename from test/tox.ubuntu_16.ini rename to test/tox.ubuntu_22.ini index f8f6e92a..2a3285aa 100644 --- a/test/tox.ubuntu_16.ini +++ b/test/tox.ubuntu_22.ini @@ -4,5 +4,5 @@ envlist = py38 [testenv] whitelist_externals = docker deps = -rrequirements.txt -commands = docker build -f _ubuntu_16.Dockerfile -t pytest_pihole:test_container ../ +commands = docker build -f _ubuntu_22.Dockerfile -t pytest_pihole:test_container ../ pytest {posargs:-vv -n auto} ./test_any_automated_install.py ./test_any_utils.py