# Packages required for the Web admin interface (stored as an array)
@ -419,32 +427,74 @@ select_rpm_php(){
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}"
printf" %b Remi's RPM repository has been enabled for PHP7\\n""${TICK}"
# 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}"
else
printf" %b There was a problem updating to PHP7 via Remi's RPM repository\\n""${CROSS}"
exit1
fi
;;
# 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}"
exit1
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}"
;;
esac
fi
# Warn user of unsupported version of Fedora or CentOS
dialog --no-shadow --clear \
--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=$?
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}"
exit1
;;
"${DIALOG_ESC}")
printf" %b Escape pressed, exiting installer at unsupported RPM based distribution dialog window\\n""${CROSS}"
exit1
;;
esac
fi
fi
}
@ -636,40 +686,46 @@ 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}"
# 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}"
exit1
fi
dialog --no-shadow --clear \
--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 \
--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 \
--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 \
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=$?
case"${result}" in
"${DIALOG_CANCEL}"|"${DIALOG_ESC}")
printf" %b Installer exited at static IP message.\\n""${INFO}"
exit1
;;
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
localinterfacesArray=()
# Turn the available interfaces into a string so it can be used with dialog
localinterfacesList
# Number of available interfaces
local interfaceCount
# Whiptail variable storage
local chooseInterfaceCmd
# Temporary Whiptail options storage
local chooseInterfaceOptions
# Loop sentinel variable
localfirstLoop=1
# Find out how many interfaces are available to choose from
printf" %b Using interface: %s\\n""${INFO}""${PIHOLE_INTERFACE}"
fi
}
@ -789,57 +844,102 @@ 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;}
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
;;
"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
# 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. 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}" 3>&1 1>&2 2>&3)||\
{printf" %bCancel was selected, exiting installer%b\\n""${COL_LIGHT_RED}""${COL_NC}";exit 1;}
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 --clear \
--title "Invalid IP Address(es)"\
--backtitle "Invalid IP"\
--msgbox "\\nOne or both of the entered IP addresses were invalid. Please try again. \
printf" %bCancel was selected, exiting installer%b\\n""${COL_LIGHT_RED}""${COL_NC}"
exit1
;;
esac
# set the variables back to nothing,
if[["${PIHOLE_DNS_1}"=="${strInvalid}"]];then
PIHOLE_DNS_1=""
@ -988,12 +1122,25 @@ 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 --clear \
--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=$?
case${result} in
"${DIALOG_OK}")
DNSSettingsCorrect=True
;;
"${DIALOG_CANCEL}")
DNSSettingsCorrect=False
;;
"${DIALOG_ESC}")
printf" %bEscape pressed, exiting installer at DNS Settings%b\\n""${COL_LIGHT_RED}""${COL_NC}"
exit1
;;
esac
fi
done
else
@ -1023,106 +1170,122 @@ setDNS() {
# Allow the user to enable/disable logging
setLogging(){
# Local, named variables
local LogToggleCommand
local LogChooseOptions
local LogChoices
# 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
# Ask the user if they want to enable logging
dialog --no-shadow --clear \
--backtitle "Pihole Installation"\
--title "Enable Logging"\
--yesno "\\n\\nWould you like to enable query logging?"\
"${r}""${c}"
result=$?
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 <ESC>
printf" %bEscape pressed, exiting installer at Query Logging choice.%b\\n""${COL_LIGHT_RED}""${COL_NC}"
exit1
;;
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
)
# 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)
# 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 --clear \
--backtitle "Pihole Installation"\
--title "Admin Web Interface"\
--yesno "\\n\\nDo you want to install the Admin Web Interface?"\
"${r}""${c}"
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 <ESC>
printf" %bEscape pressed, exiting installer at Admin Web Interface choice.%b\\n""${COL_LIGHT_RED}""${COL_NC}"
exit1
;;
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 --clear \
--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=$?
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 <ESC>
printf" %bEscape pressed, exiting installer at web server choice.%b\\n""${COL_LIGHT_RED}""${COL_NC}"
exit1
;;
esac
fi
}
@ -1133,18 +1296,33 @@ 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):
# Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory
@ -1940,14 +2110,14 @@ Your 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 --clear \
--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(){
@ -1967,20 +2137,32 @@ 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\