2015-11-25 13:43:59 -08:00
#!/usr/bin/env bash
2017-07-27 03:00:08 +10:00
# shellcheck disable=SC1090
2015-10-28 17:29:34 -05:00
# Pi-hole: A black hole for Internet advertisements
2018-01-20 05:29:38 -08:00
# (c) 2017-2018 Pi-hole, LLC (https://pi-hole.net)
2017-02-22 11:55:20 -06:00
# Network-wide ad blocking via your own hardware.
#
2017-07-27 03:00:08 +10:00
# Installs and Updates Pi-hole
2015-12-06 06:31:49 -08:00
#
2017-02-22 11:55:20 -06:00
# This file is copyright under the latest version of the EUPL.
# Please see LICENSE file for your rights under this license.
2015-10-28 17:29:34 -05:00
# pi-hole.net/donate
2015-06-13 22:14:21 -05:00
#
2017-07-06 19:25:56 -05:00
# Install with this command (from your Linux machine):
2015-06-13 22:14:21 -05:00
#
2018-01-20 05:29:38 -08:00
# curl -sSL https://install.pi-hole.net | bash
2015-06-13 22:14:21 -05:00
2017-07-06 19:25:56 -05:00
# -e option instructs bash to immediately exit if any command [1] has a non-zero exit status
# We do not want users to end up with a partially working install, so we exit the script
# instead of continuing the installation with something broken
2016-10-10 02:24:03 -07:00
set -e
2017-07-06 19:25:56 -05:00
2015-10-28 17:29:34 -05:00
######## VARIABLES #########
2017-07-06 19:25:56 -05:00
# For better maintainability, we store as much information that can change in variables
2018-02-07 16:45:23 +11:00
# This allows us to make a change in one place that can propagate to all instances of the variable
2017-07-06 19:25:56 -05:00
# These variables should all be GLOBAL variables, written in CAPS
# 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
2018-01-20 05:55:48 -08:00
# Location for final installation log storage
2018-01-20 06:20:06 -08:00
installLogLoc = /etc/pihole/install.log
2017-07-06 19:25:56 -05:00
# This is an important file as it contains information specific to the machine it's being installed on
2016-08-21 17:57:11 +01:00
setupVars = /etc/pihole/setupVars.conf
2017-07-06 19:25:56 -05:00
# Pi-hole uses lighttpd as a Web server, and this is the config file for it
2017-07-27 03:00:08 +10:00
# shellcheck disable=SC2034
2016-12-04 21:30:59 +01:00
lighttpdConfig = /etc/lighttpd/lighttpd.conf
2017-07-06 19:25:56 -05:00
# This is a file used for the colorized output
2017-06-21 12:49:05 +01:00
coltable = /opt/pihole/COL_TABLE
2015-10-31 09:15:57 -05:00
2017-07-06 19:25:56 -05:00
# We store several other folders and
2016-01-24 03:31:12 +00:00
webInterfaceGitUrl = "https://github.com/pi-hole/AdminLTE.git"
webInterfaceDir = "/var/www/html/admin"
piholeGitUrl = "https://github.com/pi-hole/pi-hole.git"
2016-11-02 00:14:25 -07:00
PI_HOLE_LOCAL_REPO = "/etc/.pihole"
2018-02-07 16:45:23 +11:00
# These are the names of pi-holes files, stored in an array
2017-01-14 20:16:27 -08:00
PI_HOLE_FILES = ( chronometer list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage)
2017-07-06 19:25:56 -05:00
# This folder is where the Pi-hole scripts will be installed
2017-01-08 23:01:18 -08:00
PI_HOLE_INSTALL_DIR = "/opt/pihole"
2016-08-19 22:31:11 +01:00
useUpdateVars = false
2016-01-23 00:13:16 +00:00
2018-04-17 09:50:25 +01:00
adlistFile = "/etc/pihole/adlists.list"
2017-07-06 19:25:56 -05:00
# Pi-hole needs an IP address; to begin, these variables are empty since we don't know what the IP is until
# this script can run
2016-11-01 09:45:22 +00:00
IPV4_ADDRESS = ""
IPV6_ADDRESS = ""
2017-07-06 19:25:56 -05:00
# By default, query logging is enabled and the dashboard is set to be installed
2016-11-01 16:46:54 +00:00
QUERY_LOGGING = true
2017-01-28 14:38:54 +00:00
INSTALL_WEB = true
2016-10-10 05:45:37 -07:00
2017-09-30 16:34:38 -04:00
# Find the rows and columns will default to 80x24 if it can not be detected
2016-11-02 05:17:28 -07:00
screen_size = $( stty size 2>/dev/null || echo 24 80)
2017-01-01 06:32:49 -08:00
rows = $( echo " ${ screen_size } " | awk '{print $1}' )
columns = $( echo " ${ screen_size } " | awk '{print $2}' )
2015-10-28 17:29:34 -05:00
# Divide by two so the dialogs take up half of the screen, which looks nice.
r = $(( rows / 2 ))
c = $(( columns / 2 ))
2016-10-26 10:44:15 -04:00
# Unless the screen is tiny
r = $(( r < 20 ? 20 : r ))
c = $(( c < 70 ? 70 : c ))
2015-10-28 17:29:34 -05:00
2016-10-15 20:52:20 +01:00
######## Undocumented Flags. Shhh ########
2017-07-06 19:25:56 -05:00
# These are undocumented flags; some of which we can use when repairing an installation
# The runUnattended flag is one example of this
2016-10-15 20:43:03 +01:00
skipSpaceCheck = false
2016-10-15 21:12:13 +01:00
reconfigure = false
2016-10-15 20:43:03 +01:00
runUnattended = false
2017-07-06 19:25:56 -05:00
# If the color table file exists,
2017-07-27 03:00:08 +10:00
if [ [ -f " ${ coltable } " ] ] ; then
2017-07-06 19:25:56 -05:00
# source it
2017-06-21 12:49:05 +01:00
source ${ coltable }
2018-02-07 16:45:23 +11:00
# Otherwise,
2017-06-21 12:49:05 +01:00
else
2017-07-06 19:25:56 -05:00
# Set these values so the installer can still run in color
2017-06-21 12:49:05 +01:00
COL_NC = '\e[0m' # No Color
COL_LIGHT_GREEN = '\e[1;32m'
COL_LIGHT_RED = '\e[1;31m'
TICK = " [ ${ COL_LIGHT_GREEN } ✓ ${ COL_NC } ] "
CROSS = " [ ${ COL_LIGHT_RED } ✗ ${ COL_NC } ] "
INFO = "[i]"
2017-07-27 03:00:08 +10:00
# shellcheck disable=SC2034
2017-06-21 12:49:05 +01:00
DONE = " ${ COL_LIGHT_GREEN } done! ${ COL_NC } "
2017-07-27 03:00:08 +10:00
OVER = "\\r\\033[K"
2017-06-21 12:49:05 +01:00
fi
2017-07-06 19:25:56 -05:00
# A simple function that just echoes out our logo in ASCII format
# This lets users know that it is a Pi-hole, LLC product
2017-03-08 21:14:21 -06:00
show_ascii_berry( ) {
2017-06-21 12:49:05 +01:00
echo -e "
${ COL_LIGHT_GREEN } .; ; ,.
2017-03-08 21:14:21 -06:00
.ccccc:,.
:cccclll:. ..,,
:ccccclll. ; ooodc
' ccll:; ll .oooodc
.; cll.; ; looo:.
2017-06-21 12:49:05 +01:00
${ COL_LIGHT_RED } .. ',' .
2017-03-08 21:14:21 -06:00
.',,,,,,' .
.' ,,,,,,,,,,.
.' ,,,,,,,,,,,,....
....'' ',,,,,,,' .......
......... .... .........
.......... ..........
.......... ..........
......... .... .........
........,,,,,,,' ......
....' ,,,,,,,,,,,,.
.',,,,,,,,,' .
.',,,,,,' .
2017-06-21 12:49:05 +01:00
..'' ' .${ COL_NC }
2017-03-08 21:14:21 -06:00
"
}
2016-08-19 22:31:11 +01:00
# Compatibility
2017-01-21 12:34:47 -08:00
distro_check( ) {
2017-07-07 09:05:19 -05:00
# If apt-get is installed, then we know it's part of the Debian family
2016-12-27 11:53:23 -08:00
if command -v apt-get & > /dev/null; then
2017-07-06 19:25:56 -05:00
# Set some global variables here
# We don't set them earlier since the family might be Red Hat, so these values would be different
2017-03-03 11:52:49 +01:00
PKG_MANAGER = "apt-get"
2017-07-06 19:25:56 -05:00
# A variable to store the command used to update the package cache
2017-05-09 13:11:28 -07:00
UPDATE_PKG_CACHE = " ${ PKG_MANAGER } update "
2017-07-06 19:25:56 -05:00
# An array for something...
2017-01-08 23:01:18 -08:00
PKG_INSTALL = ( ${ PKG_MANAGER } --yes --no-install-recommends install)
2016-11-02 05:17:28 -07:00
# grep -c will return 1 retVal on 0 matches, block this throwing the set -e with an OR TRUE
PKG_COUNT = " ${ PKG_MANAGER } -s -o Debug::NoLocking=true upgrade | grep -c ^Inst || true "
2017-07-06 19:25:56 -05:00
# Some distros vary slightly so these fixes for dependencies may apply
# Debian 7 doesn't have iproute2 so if the dry run install is successful,
2017-01-14 18:23:52 -08:00
if ${ PKG_MANAGER } install --dry-run iproute2 > /dev/null 2>& 1; then
2017-07-06 19:25:56 -05:00
# we can install it
2017-01-14 18:23:52 -08:00
iproute_pkg = "iproute2"
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-14 18:23:52 -08:00
else
2017-07-06 19:25:56 -05:00
# use iproute
2017-01-14 18:23:52 -08:00
iproute_pkg = "iproute"
fi
2017-07-06 19:25:56 -05:00
# We prefer the php metapackage if it's there
2017-01-14 18:23:52 -08:00
if ${ PKG_MANAGER } install --dry-run php > /dev/null 2>& 1; then
phpVer = "php"
2017-07-06 19:25:56 -05:00
# If not,
2017-01-14 18:23:52 -08:00
else
2017-07-06 19:25:56 -05:00
# fall back on the php5 packages
2017-01-14 18:23:52 -08:00
phpVer = "php5"
fi
2017-08-16 16:27:50 +01:00
# We also need the correct version for `php-sqlite` (which differs across distros)
if ${ PKG_MANAGER } install --dry-run ${ phpVer } -sqlite3 > /dev/null 2>& 1; then
phpSqlite = "sqlite3"
else
phpSqlite = "sqlite"
fi
2017-07-10 14:12:30 -05:00
# Since our install script is so large, we need several other programs to successfuly get a machine provisioned
2017-07-06 19:25:56 -05:00
# These programs are stored in an array so they can be looped through later
2017-02-27 15:21:59 -05:00
INSTALLER_DEPS = ( apt-utils dialog debconf dhcpcd5 git ${ iproute_pkg } whiptail)
2017-07-06 19:25:56 -05:00
# Pi-hole itself has several dependencies that also need to be installed
2018-03-06 18:44:57 +00:00
PIHOLE_DEPS = ( bc cron curl dnsutils iputils-ping lsof netcat sudo unzip wget idn2 sqlite3 libcap2-bin dns-root-data resolvconf)
2017-07-06 19:25:56 -05:00
# The Web dashboard has some that also need to be installed
# It's useful to separate the two since our repos are also setup as "Core" code and "Web" code
2017-08-16 16:27:50 +01:00
PIHOLE_WEB_DEPS = ( lighttpd ${ phpVer } -common ${ phpVer } -cgi ${ phpVer } -${ phpSqlite } )
2017-07-06 19:25:56 -05:00
# The Web server user,
2016-11-02 05:17:28 -07:00
LIGHTTPD_USER = "www-data"
2017-07-06 19:25:56 -05:00
# group,
2016-11-02 05:17:28 -07:00
LIGHTTPD_GROUP = "www-data"
2017-07-06 19:25:56 -05:00
# and config file
2018-03-18 00:38:34 +00:00
LIGHTTPD_CFG = "lighttpd.conf.debian"
2016-11-02 05:17:28 -07:00
2017-08-17 19:43:07 +01:00
# A function to check...
test_dpkg_lock( ) {
# An iterator used for counting loop iterations
i = 0
# fuser is a program to show which processes use the named files, sockets, or filesystems
# So while the command is true
while fuser /var/lib/dpkg/lock >/dev/null 2>& 1 ; do
# Wait half a second
sleep 0.5
# and increase the iterator
( ( i = i+1) )
done
# Always return success, since we only return if there is no
# lock (anymore)
return 0
}
2017-03-03 11:28:35 +01:00
2017-07-06 19:25:56 -05:00
# If apt-get is not found, check for rpm to see if it's a Red Hat family OS
2016-12-27 11:53:23 -08:00
elif command -v rpm & > /dev/null; then
2017-07-06 19:25:56 -05:00
# Then check if dnf or yum is the package manager
2016-12-27 11:53:23 -08:00
if command -v dnf & > /dev/null; then
2016-11-02 05:17:28 -07:00
PKG_MANAGER = "dnf"
else
PKG_MANAGER = "yum"
fi
2016-12-27 12:37:19 -08:00
2018-03-18 00:38:34 +00:00
# Fedora and family update cache on every PKG_INSTALL call, no need for a separate update.
2016-12-27 10:59:24 -08:00
UPDATE_PKG_CACHE = ":"
2017-01-17 13:00:17 -08:00
PKG_INSTALL = ( ${ PKG_MANAGER } install -y)
2016-11-02 05:17:28 -07:00
PKG_COUNT = " ${ PKG_MANAGER } check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l "
2017-02-27 15:21:59 -05:00
INSTALLER_DEPS = ( dialog git iproute net-tools newt procps-ng)
2018-03-07 22:23:05 +00:00
PIHOLE_DEPS = ( bc bind-utils cronie curl findutils nmap-ncat sudo unzip wget libidn2 psmisc)
2017-08-16 15:56:39 +01:00
PIHOLE_WEB_DEPS = ( lighttpd lighttpd-fastcgi php php-common php-cli php-pdo)
2018-01-07 22:21:04 -06:00
# EPEL (https://fedoraproject.org/wiki/EPEL) is required for lighttpd on CentOS
if grep -qi 'centos' /etc/redhat-release; then
2016-12-27 12:59:53 -08:00
INSTALLER_DEPS = ( " ${ INSTALLER_DEPS [@] } " "epel-release" ) ;
2016-11-02 05:17:28 -07:00
fi
LIGHTTPD_USER = "lighttpd"
LIGHTTPD_GROUP = "lighttpd"
2018-03-18 00:38:34 +00:00
LIGHTTPD_CFG = "lighttpd.conf.fedora"
2016-11-02 05:17:28 -07:00
2017-11-05 10:05:25 +01:00
# If neither apt-get or rmp/dnf are found
2016-04-25 22:51:00 -06:00
else
2017-07-06 19:25:56 -05:00
# it's not an OS we can support,
2017-06-21 12:49:05 +01:00
echo -e " ${ CROSS } OS distribution not supported "
2017-07-06 19:25:56 -05:00
# so exit the installer
2016-11-02 05:17:28 -07:00
exit
2016-04-25 22:51:00 -06:00
fi
2017-01-21 12:34:47 -08:00
}
2015-11-08 17:21:02 -06:00
2017-07-06 19:25:56 -05:00
# A function for checking if a folder is a git repository
2016-11-02 00:14:25 -07:00
is_repo( ) {
2017-07-06 19:25:56 -05:00
# Use a named, local variable instead of the vague $1, which is the first arguement passed to this function
# These local variables should always be lowercase
2016-11-02 13:34:57 +00:00
local directory = " ${ 1 } "
2017-07-10 14:12:30 -05:00
# A local variable for the current directory
2016-12-31 22:34:20 -08:00
local curdir
2017-07-06 19:25:56 -05:00
# A variable to store the return code
2016-12-31 22:34:20 -08:00
local rc
2017-07-06 19:25:56 -05:00
# Assign the current directory variable by using pwd
2016-12-31 22:34:20 -08:00
curdir = " ${ PWD } "
2017-07-06 19:25:56 -05:00
# If the first argument passed to this function is a directory,
2016-12-31 22:34:20 -08:00
if [ [ -d " ${ directory } " ] ] ; then
2017-07-06 19:25:56 -05:00
# move into the directory
2016-12-31 22:34:20 -08:00
cd " ${ directory } "
2017-07-06 19:25:56 -05:00
# Use git to check if the folder is a repo
# git -C is not used here to support git versions older than 1.8.4
2016-12-31 22:34:20 -08:00
git status --short & > /dev/null || rc = $?
2017-07-06 19:25:56 -05:00
# If the command was not successful,
2016-12-22 19:57:13 -06:00
else
2017-07-06 19:25:56 -05:00
# Set a non-zero return code if directory does not exist
2016-12-31 22:34:20 -08:00
rc = 1
2016-12-22 19:57:13 -06:00
fi
2017-07-06 19:25:56 -05:00
# Move back into the directory the user started in
2016-12-31 22:34:20 -08:00
cd " ${ curdir } "
2017-07-06 19:25:56 -05:00
# Return the code; if one is not set, return 0
2016-12-31 22:34:20 -08:00
return " ${ rc :- 0 } "
2016-11-02 00:14:25 -07:00
}
2017-07-06 19:25:56 -05:00
# A function to clone a repo
2016-11-02 00:14:25 -07:00
make_repo( ) {
2017-07-06 19:25:56 -05:00
# Set named variables for better readability
2016-11-02 13:34:57 +00:00
local directory = " ${ 1 } "
2016-12-20 17:22:57 -08:00
local remoteRepo = " ${ 2 } "
2017-07-06 19:25:56 -05:00
# The message to display when this function is running
2017-06-21 12:49:05 +01:00
str = " Clone ${ remoteRepo } into ${ directory } "
2017-07-06 19:25:56 -05:00
# Display the message and use the color table to preface the message with an "info" indicator
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# If the directory exists,
2016-12-31 22:34:20 -08:00
if [ [ -d " ${ directory } " ] ] ; then
2017-07-06 19:25:56 -05:00
# delete everything in it so git can clone into it
2016-12-31 22:34:20 -08:00
rm -rf " ${ directory } "
fi
2017-07-06 19:25:56 -05:00
# Clone the repo and return the return code from this command
2016-12-31 22:34:20 -08:00
git clone -q --depth 1 " ${ remoteRepo } " " ${ directory } " & > /dev/null || return $?
2017-07-06 19:25:56 -05:00
# Show a colored message showing it's status
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Always return 0? Not sure this is correct
2016-12-31 22:34:20 -08:00
return 0
2016-11-02 00:14:25 -07:00
}
2017-07-06 19:25:56 -05:00
# We need to make sure the repos are up-to-date so we can effectively install Clean out the directory if it exists for git to clone into
2016-11-02 00:14:25 -07:00
update_repo( ) {
2017-07-06 19:25:56 -05:00
# Use named, local variables
# As you can see, these are the same variable names used in the last function,
# but since they are local, their scope does not go beyond this function
# This helps prevent the wrong value from being assigned if you were to set the variable as a GLOBAL one
2016-12-20 17:22:57 -08:00
local directory = " ${ 1 } "
2017-01-28 17:32:42 -08:00
local curdir
2017-01-01 00:07:10 -08:00
2017-07-06 19:25:56 -05:00
# A variable to store the message we want to display;
# Again, it's useful to store these in variables in case we need to reuse or change the message;
# we only need to make one change here
2017-06-21 12:49:05 +01:00
local str = " Update repo in ${ 1 } "
2017-07-06 19:25:56 -05:00
# Make sure we know what directory we are in so we can move back into it
2017-01-28 17:32:42 -08:00
curdir = " ${ PWD } "
2017-07-06 19:25:56 -05:00
# Move into the directory that was passed as an argument
2017-01-28 17:32:42 -08:00
cd " ${ directory } " & > /dev/null || return 1
2017-07-06 19:25:56 -05:00
# Let the user know what's happening
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Stash any local commits as they conflict with our working code
2017-01-28 17:32:42 -08:00
git stash --all --quiet & > /dev/null || true # Okay for stash failure
2017-07-01 13:08:17 +01:00
git clean --quiet --force -d || true # Okay for already clean directory
2017-07-06 19:25:56 -05:00
# Pull the latest commits
2017-01-28 17:32:42 -08:00
git pull --quiet & > /dev/null || return $?
2017-07-06 19:25:56 -05:00
# Show a completion message
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Move back into the oiginal directory
2017-01-28 17:32:42 -08:00
cd " ${ curdir } " & > /dev/null || return 1
2017-01-01 00:07:10 -08:00
return 0
2016-11-02 00:14:25 -07:00
}
2017-07-06 19:25:56 -05:00
# A function that combines the functions previously made
2016-11-02 00:14:25 -07:00
getGitFiles( ) {
2017-07-06 19:25:56 -05:00
# Setup named variables for the git repos
# We need the directory
2016-12-20 17:22:57 -08:00
local directory = " ${ 1 } "
2017-07-06 19:25:56 -05:00
# as well as the repo URL
2016-12-20 17:22:57 -08:00
local remoteRepo = " ${ 2 } "
2017-07-06 19:25:56 -05:00
# A local varible containing the message to be displayed
2017-06-21 12:49:05 +01:00
local str = " Check for existing repository in ${ 1 } "
2017-07-06 19:25:56 -05:00
# Show the message
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Check if the directory is a repository
2016-12-20 17:22:57 -08:00
if is_repo " ${ directory } " ; then
2017-07-06 19:25:56 -05:00
# Show that we're checking it
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Update the repo, returning an error message on failure
2017-07-27 03:00:08 +10:00
update_repo " ${ directory } " || { echo -e " \\n ${ COL_LIGHT_RED } Error: Could not update local repository. Contact support. ${ COL_NC } " ; exit 1; }
2017-07-06 19:25:56 -05:00
# If it's not a .git repo,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# Show an error
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } "
2017-07-06 19:25:56 -05:00
# Attempt to make the repository, showing an error on falure
2017-07-27 03:00:08 +10:00
make_repo " ${ directory } " " ${ remoteRepo } " || { echo -e " \\n ${ COL_LIGHT_RED } Error: Could not update local repository. Contact support. ${ COL_NC } " ; exit 1; }
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# echo a blank line
2017-06-21 12:49:05 +01:00
echo ""
2017-07-06 19:25:56 -05:00
# and return success?
2016-12-31 22:34:20 -08:00
return 0
2016-11-02 00:14:25 -07:00
}
2017-07-06 19:25:56 -05:00
# Reset a repo to get rid of any local changed
2017-05-22 23:43:52 +02:00
resetRepo( ) {
2017-07-06 19:25:56 -05:00
# Use named varibles for arguments
2017-05-22 23:43:52 +02:00
local directory = " ${ 1 } "
2017-07-06 19:25:56 -05:00
# Move into the directory
2017-05-22 23:43:52 +02:00
cd " ${ directory } " & > /dev/null || return 1
2017-07-06 19:25:56 -05:00
# Store the message in a varible
2017-06-21 12:49:05 +01:00
str = " Resetting repository within ${ 1 } ... "
2017-07-06 19:25:56 -05:00
# Show the message
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } "
2017-07-06 19:25:56 -05:00
# Use git to remove the local changes
2017-05-22 23:43:52 +02:00
git reset --hard & > /dev/null || return $?
2017-07-06 19:25:56 -05:00
# And show the status
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Returning success anyway?
2016-12-31 22:34:20 -08:00
return 0
2016-11-02 00:14:25 -07:00
}
2017-07-06 19:25:56 -05:00
# We need to know the IPv4 information so we can effectively setup the DNS server
# Without this information, we won't know where to Pi-hole will be found
2016-10-10 05:45:37 -07:00
find_IPv4_information( ) {
2017-07-06 19:25:56 -05:00
# Named, local variables
2017-01-08 18:04:24 -08:00
local route
2017-07-06 19:25:56 -05:00
# Find IP used to route to outside world by checking the the route to Google's public DNS server
2017-01-08 18:04:24 -08:00
route = $( ip route get 8.8.8.8)
2017-07-06 19:25:56 -05:00
# Use awk to strip out just the interface device as it is used in future commands
2017-01-08 18:04:24 -08:00
IPv4dev = $( awk '{for (i=1; i<=NF; i++) if ($i~/dev/) print $(i+1)}' <<< " ${ route } " )
2017-07-06 19:25:56 -05:00
# Get just the IP address
2017-01-19 13:50:42 -08:00
IPv4bare = $( awk '{print $7}' <<< " ${ route } " )
2017-07-06 19:25:56 -05:00
# Append the CIDR notation to the IP address
2017-01-19 13:50:42 -08:00
IPV4_ADDRESS = $( ip -o -f inet addr show | grep " ${ IPv4bare } " | awk '{print $4}' | awk 'END {print}' )
2017-07-06 19:25:56 -05:00
# Get the default gateway (the way to reach the Internet)
2017-01-08 18:04:24 -08:00
IPv4gw = $( awk '{print $3}' <<< " ${ route } " )
2016-04-30 20:27:38 -06:00
}
2017-07-06 19:25:56 -05:00
# Get available interfaces that are UP
2016-10-10 03:16:22 -07:00
get_available_interfaces( ) {
2017-07-06 19:25:56 -05:00
# There may be more than one so it's all stored in a variable
2017-03-15 22:05:48 -07:00
availableInterfaces = $( ip --oneline link show up | grep -v "lo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1)
2016-10-10 03:16:22 -07:00
}
2015-11-09 18:33:32 -06:00
2017-07-06 19:25:56 -05:00
# A function for displaying the dialogs the user sees when first running the installer
2016-01-27 01:11:38 -05:00
welcomeDialogs( ) {
2017-07-06 19:25:56 -05:00
# Display the welcome dialog using an approriately sized window via the calculation conducted earlier in the script
2017-07-27 03:00:08 +10:00
whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" ${ r } ${ c }
2016-01-28 09:25:00 +00:00
2017-07-06 19:25:56 -05:00
# Request that users donate if they enjoy the software since we all work on it in our free time
2017-07-27 03:00:08 +10:00
whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" ${ r } ${ c }
2016-01-28 09:25:00 +00:00
2016-12-20 17:22:57 -08:00
# Explain the need for a static address
2017-07-27 03:00:08 +10:00
whiptail --msgbox --backtitle "Initiating network interface" --title "Static IP Needed" " \\n\\nThe Pi-hole is a SERVER so it needs a STATIC IP ADDRESS to function properly.
2016-06-10 17:47:27 -05:00
2016-08-19 22:31:11 +01:00
In the next section, you can choose to use your current network settings ( DHCP) or to manually edit them." ${ r } ${ c }
2015-11-08 17:21:02 -06:00
}
2017-07-06 19:25:56 -05:00
# We need to make sure there is enough space before installing, so there is a function to check this
2016-02-10 09:34:06 -06:00
verifyFreeDiskSpace( ) {
2016-08-12 12:44:45 +01:00
2016-12-20 17:22:57 -08:00
# 50MB is the minimum space needed (45MB install (includes web admin bootstrap/jquery libraries etc) + 5MB one day of logs.)
# - Fourdee: Local ensures the variable is only created, and accessible within this function/void. Generally considered a "good" coding practice for non-global variables.
2017-06-21 12:49:05 +01:00
local str = "Disk space check"
2017-07-06 19:25:56 -05:00
# Reqired space in KB
2016-12-20 17:22:57 -08:00
local required_free_kilobytes = 51200
2017-07-06 19:25:56 -05:00
# Calculate existing free space on this machine
2017-07-27 03:00:08 +10:00
local existing_free_kilobytes
existing_free_kilobytes = $( df -Pk | grep -m1 '\/$' | awk '{print $4}' )
2016-12-20 17:22:57 -08:00
2017-07-06 19:25:56 -05:00
# If the existing space is not an integer,
2016-12-20 17:22:57 -08:00
if ! [ [ " ${ existing_free_kilobytes } " = ~ ^( [ 0-9] ) +$ ] ] ; then
2017-07-06 19:25:56 -05:00
# show an error that we can't determine the free space
2017-06-21 12:49:05 +01:00
echo -e " ${ CROSS } ${ str }
Unknown free disk space!
We were unable to determine available free disk space on this system.
You may override this check, however, it is not recommended
The option '${COL_LIGHT_RED}--i_do_not_follow_recommendations${COL_NC}' can override this
e.g: curl -L https://install.pi-hole.net | bash /dev/stdin ${ COL_LIGHT_RED } <option>${ COL_NC } "
2017-07-06 19:25:56 -05:00
# exit with an error code
2016-12-20 17:22:57 -08:00
exit 1
2017-07-06 19:25:56 -05:00
# If there is insufficient free disk space,
2017-07-27 03:00:08 +10:00
elif [ [ " ${ existing_free_kilobytes } " -lt " ${ required_free_kilobytes } " ] ] ; then
2017-07-06 19:25:56 -05:00
# show an error message
2017-06-21 12:49:05 +01:00
echo -e " ${ CROSS } ${ str }
Your system disk appears to only have ${ existing_free_kilobytes } KB free
It is recommended to have a minimum of ${ required_free_kilobytes } KB to run the Pi-hole"
2017-07-06 19:25:56 -05:00
# if the vcgencmd command exists,
2017-06-21 12:49:05 +01:00
if command -v vcgencmd & > /dev/null; then
2017-07-06 19:25:56 -05:00
# it's probably a Raspbian install, so show a message about expanding the filesystem
2017-06-21 12:49:05 +01:00
echo " If this is a new install you may need to expand your disk
Run 'sudo raspi-config' , and choose the 'expand file system' option
After rebooting, run this installation again
e.g: curl -L https://install.pi-hole.net | bash"
fi
2017-07-06 19:25:56 -05:00
# Show there is not enough free space
2017-07-27 03:00:08 +10:00
echo -e " \\n ${ COL_LIGHT_RED } Insufficient free space, exiting... ${ COL_NC } "
2017-07-06 19:25:56 -05:00
# and exit with an error
2016-12-20 17:22:57 -08:00
exit 1
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-06-21 12:49:05 +01:00
else
2017-07-06 19:25:56 -05:00
# Show that we're running a disk space check
2017-06-21 12:49:05 +01:00
echo -e " ${ TICK } ${ str } "
2016-12-20 17:22:57 -08:00
fi
2016-02-10 09:34:06 -06:00
}
2017-07-06 19:25:56 -05:00
# A function that let's the user pick an interface to use with Pi-hole
2016-01-27 01:11:38 -05:00
chooseInterface( ) {
2016-12-20 17:22:57 -08:00
# Turn the available interfaces into an array so it can be used with a whiptail dialog
local interfacesArray = ( )
# 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 = $( echo " ${ availableInterfaces } " | wc -l)
2017-01-08 18:46:15 -08:00
2017-07-06 19:25:56 -05:00
# If there is one interface,
2017-07-27 03:00:08 +10:00
if [ [ " ${ interfaceCount } " -eq 1 ] ] ; then
2017-07-06 19:25:56 -05:00
# Set it as the interface to use since there is no other option
2017-01-14 18:23:52 -08:00
PIHOLE_INTERFACE = " ${ availableInterfaces } "
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-14 18:23:52 -08:00
else
2017-07-06 19:25:56 -05:00
# While reading through the available interfaces
2017-01-14 18:23:52 -08:00
while read -r line; do
2017-07-06 19:25:56 -05:00
# use a variable to set the option as OFF to begin with
2017-01-14 18:23:52 -08:00
mode = "OFF"
2017-07-06 19:25:56 -05:00
# If it's the first loop,
2017-07-27 03:00:08 +10:00
if [ [ " ${ firstLoop } " -eq 1 ] ] ; then
2017-07-06 19:25:56 -05:00
# set this as the interface to use (ON)
2017-01-14 18:23:52 -08:00
firstLoop = 0
mode = "ON"
fi
2017-07-06 19:25:56 -05:00
# Put all these interfaces into an array
2017-01-14 18:23:52 -08:00
interfacesArray += ( " ${ line } " "available" " ${ mode } " )
2017-07-06 19:25:56 -05:00
# Feed the available interfaces into this while loop
2017-01-14 18:23:52 -08:00
done <<< " ${ availableInterfaces } "
2017-07-06 19:25:56 -05:00
# The whiptail command that will be run, stored in a variable
2017-01-14 18:23:52 -08:00
chooseInterfaceCmd = ( whiptail --separate-output --radiolist "Choose An Interface (press space to select)" ${ r } ${ c } ${ interfaceCount } )
2017-07-06 19:25:56 -05:00
# Now run the command using the interfaces saved into the array
2017-01-14 18:23:52 -08:00
chooseInterfaceOptions = $( " ${ chooseInterfaceCmd [@] } " " ${ interfacesArray [@] } " 2>& 1 >/dev/tty) || \
2017-07-06 19:25:56 -05:00
# If the user chooses Canel, exit
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
2017-07-06 19:25:56 -05:00
# For each interface
2017-01-14 18:23:52 -08:00
for desiredInterface in ${ chooseInterfaceOptions } ; do
2017-07-06 19:25:56 -05:00
# Set the one the user selected as the interface to use
2017-01-14 18:23:52 -08:00
PIHOLE_INTERFACE = ${ desiredInterface }
2017-07-06 19:25:56 -05:00
# and show this information to the user
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Using interface: $PIHOLE_INTERFACE "
2017-01-14 18:23:52 -08:00
done
fi
2016-10-10 05:45:37 -07:00
}
2016-03-05 21:16:23 -08:00
2017-07-06 19:25:56 -05:00
# This lets us prefer ULA addresses over GUA
# This caused problems for some users when their ISP changed their IPv6 addresses
2017-06-02 23:01:48 +02:00
# See https://github.com/pi-hole/pi-hole/issues/1473#issuecomment-301745953
testIPv6( ) {
2017-07-06 19:25:56 -05:00
# first will contain fda2 (ULA)
2017-06-02 23:01:48 +02:00
first = " $( cut -f1 -d":" <<< " $1 " ) "
2017-07-06 19:25:56 -05:00
# value1 will contain 253 which is the decimal value corresponding to 0xfd
2017-12-06 22:31:12 +00:00
value1 = $(( ( 0 x$first ) / 256 ))
2017-07-06 19:25:56 -05:00
# will contain 162 which is the decimal value corresponding to 0xa2
2017-12-06 22:31:12 +00:00
value2 = $(( ( 0 x$first ) % 256 ))
2017-07-06 19:25:56 -05:00
# the ULA test is testing for fc00::/7 according to RFC 4193
2017-12-06 22:57:05 +00:00
if ( ( ( value1& 254) = = 252 ) ) ; then
2017-12-06 22:31:12 +00:00
echo "ULA"
fi
2017-07-06 19:25:56 -05:00
# the GUA test is testing for 2000::/3 according to RFC 4291
2017-12-06 22:57:05 +00:00
if ( ( ( value1& 112) = = 32 ) ) ; then
2017-12-06 22:31:12 +00:00
echo "GUA"
fi
2017-07-06 19:25:56 -05:00
# the LL test is testing for fe80::/10 according to RFC 4193
2017-12-06 22:57:05 +00:00
if ( ( ( value1) = = 254 ) ) && ( ( ( value2& 192) = = 128 ) ) ; then
2017-12-06 22:31:12 +00:00
echo "Link-local"
fi
2017-06-02 23:01:48 +02:00
}
2017-07-06 19:25:56 -05:00
# A dialog for showing the user about IPv6 blocking
2016-10-10 05:45:37 -07:00
useIPv6dialog( ) {
2017-06-02 23:01:48 +02:00
# Determine the IPv6 address used for blocking
IPV6_ADDRESSES = ( $( ip -6 address | grep 'scope global' | awk '{print $2}' ) )
2017-07-06 19:25:56 -05:00
# For each address in the array above, determine the type of IPv6 address it is
2017-06-02 23:01:48 +02:00
for i in " ${ IPV6_ADDRESSES [@] } " ; do
2017-07-06 19:25:56 -05:00
# Check if it's ULA, GUA, or LL by using the function created earlier
2017-06-02 23:01:48 +02:00
result = $( testIPv6 " $i " )
2017-07-06 19:25:56 -05:00
# If it's a ULA address, use it and store it as a global variable
2017-06-29 02:18:52 +01:00
[ [ " ${ result } " = = "ULA" ] ] && ULA_ADDRESS = " ${ i %/* } "
2017-07-06 19:25:56 -05:00
# If it's a GUA address, we can still use it si store it as a global variable
2017-06-29 02:18:52 +01:00
[ [ " ${ result } " = = "GUA" ] ] && GUA_ADDRESS = " ${ i %/* } "
2017-06-02 23:01:48 +02:00
done
# Determine which address to be used: Prefer ULA over GUA or don't use any if none found
2017-07-06 19:25:56 -05:00
# If the ULA_ADDRESS contains a value,
2017-06-02 23:01:48 +02:00
if [ [ ! -z " ${ ULA_ADDRESS } " ] ] ; then
2017-07-06 19:25:56 -05:00
# set the IPv6 address to the ULA address
2017-06-02 23:01:48 +02:00
IPV6_ADDRESS = " ${ ULA_ADDRESS } "
2017-07-06 19:25:56 -05:00
# Show this info to the user
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Found IPv6 ULA address, using it for blocking IPv6 ads "
2017-07-06 19:25:56 -05:00
# Otherwise, if the GUA_ADDRESS has a value,
2017-06-02 23:01:48 +02:00
elif [ [ ! -z " ${ GUA_ADDRESS } " ] ] ; then
2017-07-06 19:25:56 -05:00
# Let the user know
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Found IPv6 GUA address, using it for blocking IPv6 ads "
2017-07-06 19:25:56 -05:00
# And assign it to the global variable
2017-06-02 23:01:48 +02:00
IPV6_ADDRESS = " ${ GUA_ADDRESS } "
2017-07-06 19:25:56 -05:00
# If none of those work,
2017-06-02 23:01:48 +02:00
else
2017-07-06 19:25:56 -05:00
# explain that IPv6 blocking will not be used
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Unable to find IPv6 ULA/GUA address, IPv6 adblocking will not be enabled "
2017-07-06 19:25:56 -05:00
# So set the variable to be empty
2017-06-02 23:01:48 +02:00
IPV6_ADDRESS = ""
fi
2016-12-24 15:26:05 -08:00
2017-07-06 19:25:56 -05:00
# If the IPV6_ADDRESS contains a value
2016-12-24 15:26:05 -08:00
if [ [ ! -z " ${ IPV6_ADDRESS } " ] ] ; then
2017-07-06 19:25:56 -05:00
# Display that IPv6 is supported and will be used
2016-12-24 15:26:05 -08:00
whiptail --msgbox --backtitle "IPv6..." --title "IPv6 Supported" " $IPV6_ADDRESS will be used to block ads. " ${ r } ${ c }
fi
2015-11-09 18:33:32 -06:00
}
2017-07-06 19:25:56 -05:00
# A function to check if we should use IPv4 and/or IPv6 for blocking ads
2016-01-27 01:11:38 -05:00
use4andor6( ) {
2017-07-06 19:25:56 -05:00
# Named local variables
2016-12-20 17:22:57 -08:00
local useIPv4
local useIPv6
2017-07-06 19:25:56 -05:00
# Let use select IPv4 and/or IPv6 via a checklist
2016-12-20 17:22:57 -08:00
cmd = ( whiptail --separate-output --checklist "Select Protocols (press space to select)" ${ r } ${ c } 2)
2017-07-06 19:25:56 -05:00
# In an array, show the options available:
# IPv4 (on by default)
2016-12-20 17:22:57 -08:00
options = ( IPv4 "Block ads over IPv4" on
2017-07-06 19:25:56 -05:00
# or IPv6 (on by default if available)
2016-12-20 17:22:57 -08:00
IPv6 "Block ads over IPv6" on)
2017-07-06 19:25:56 -05:00
# In a variable, show the choices available; exit if Cancel is selected
2017-06-21 12:49:05 +01:00
choices = $( " ${ cmd [@] } " " ${ options [@] } " 2>& 1 >/dev/tty) || { echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
2017-07-06 19:25:56 -05:00
# For each choice available,
2017-01-08 18:46:15 -08:00
for choice in ${ choices }
do
2017-07-06 19:25:56 -05:00
# Set the values to true
2017-01-08 18:46:15 -08:00
case ${ choice } in
IPv4 ) useIPv4 = true; ;
IPv6 ) useIPv6 = true; ;
esac
done
2017-07-06 19:25:56 -05:00
# If IPv4 is to be used,
2017-07-27 03:00:08 +10:00
if [ [ " ${ useIPv4 } " ] ] ; then
2017-07-06 19:25:56 -05:00
# Run our function to get the information we need
2017-01-08 18:46:15 -08:00
find_IPv4_information
getStaticIPv4Settings
setStaticIPv4
fi
2017-07-06 19:25:56 -05:00
# If IPv6 is to be used,
2017-07-27 03:00:08 +10:00
if [ [ " ${ useIPv6 } " ] ] ; then
2017-07-06 19:25:56 -05:00
# Run our function to get this information
2017-01-08 18:46:15 -08:00
useIPv6dialog
fi
2017-07-06 19:25:56 -05:00
# Echo the information to the user
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } IPv4 address: ${ IPV4_ADDRESS } "
echo -e " ${ INFO } IPv6 address: ${ IPV6_ADDRESS } "
2017-07-06 19:25:56 -05:00
# If neither protocol is selected,
2017-07-27 03:00:08 +10:00
if [ [ ! " ${ useIPv4 } " ] ] && [ [ ! " ${ useIPv6 } " ] ] ; then
2017-07-06 19:25:56 -05:00
# Show an error in red
2017-06-21 12:49:05 +01:00
echo -e " ${ COL_LIGHT_RED } Error: Neither IPv4 or IPv6 selected ${ COL_NC } "
2017-07-06 19:25:56 -05:00
# and exit with an error
2016-12-20 17:22:57 -08:00
exit 1
fi
2015-11-09 18:33:32 -06:00
}
2015-11-08 17:21:02 -06:00
2017-07-06 19:25:56 -05:00
#
2016-01-27 01:11:38 -05:00
getStaticIPv4Settings( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-01-08 23:01:18 -08:00
local ipSettingsCorrect
2016-12-20 17:22:57 -08:00
# Ask if the user wants to use DHCP settings as their static IP
2017-07-06 19:25:56 -05:00
# This is useful for users that are using DHCP reservations; then we can just use the information gathered via our functions
2017-01-08 21:30:38 -08:00
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno " Do you want to use your current network settings as a static address?
2016-12-20 17:22:57 -08:00
IP address: ${ IPV4_ADDRESS }
2017-01-08 21:30:38 -08:00
Gateway: ${ IPv4gw } " ${ r } ${ c } ; then
2016-12-20 17:22:57 -08:00
# 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.
2016-04-03 18:05:11 -05:00
If you are worried, either manually set the address, or modify the DHCP reservation pool so it does not include the IP you want.
2016-08-19 22:31:11 +01:00
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 }
2017-07-06 19:25:56 -05:00
# Nothing else to do since the variables are already set above
2016-12-20 17:22:57 -08:00
else
# 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
2017-07-27 03:00:08 +10:00
until [ [ " ${ ipSettingsCorrect } " = True ] ] ; do
2017-01-08 18:46:15 -08:00
2016-12-20 17:22:57 -08:00
# Ask for the IPv4 address
2017-01-08 18:46:15 -08:00
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) || \
# Cancelling IPv4 settings window
2017-06-21 12:49:05 +01:00
{ ipSettingsCorrect = False; echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
echo -e " ${ INFO } Your static IPv4 address: ${ IPV4_ADDRESS } "
2017-01-08 18:46:15 -08:00
2016-12-20 17:22:57 -08:00
# Ask for the gateway
2017-01-08 18:46:15 -08:00
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) || \
# Cancelling gateway settings window
2017-06-21 12:49:05 +01:00
{ ipSettingsCorrect = False; echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
echo -e " ${ INFO } Your static IPv4 gateway: ${ IPv4gw } "
2017-01-08 18:46:15 -08:00
# Give the user a chance to review their settings before moving on
2017-01-08 21:30:38 -08:00
if whiptail --backtitle "Calibrating network interface" --title "Static IP Address" --yesno " Are these settings correct?
2017-06-21 12:49:05 +01:00
IP address: ${ IPV4_ADDRESS }
Gateway: ${ IPv4gw } " ${ r } ${ c } ; then
2017-01-08 18:46:15 -08:00
# After that's done, the loop ends and we move on
ipSettingsCorrect = True
2016-12-20 17:22:57 -08:00
else
2017-01-08 18:46:15 -08:00
# If the settings are wrong, the loop continues
2016-12-20 17:22:57 -08:00
ipSettingsCorrect = False
fi
done
# End the if statement for DHCP vs. static
fi
2015-11-08 17:21:02 -06:00
}
2017-07-06 19:25:56 -05:00
# dhcpcd is very annoying,
2016-01-27 01:11:38 -05:00
setDHCPCD( ) {
2017-07-07 09:05:19 -05:00
# but we can append these lines to dhcpcd.conf to enable a static IP
2017-02-01 18:33:42 -08:00
echo " interface ${ PIHOLE_INTERFACE }
2016-12-20 17:22:57 -08:00
static ip_address = ${ IPV4_ADDRESS }
static routers = ${ IPv4gw }
2017-05-05 12:03:51 -07:00
static domain_name_servers = 127.0.0.1" | tee -a /etc/dhcpcd.conf >/dev/null
2015-10-31 09:11:29 -05:00
}
2016-01-27 01:11:38 -05:00
setStaticIPv4( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2016-12-20 17:22:57 -08:00
local IFCFG_FILE
local IPADDR
local CIDR
2017-07-06 19:25:56 -05:00
# For the Debian family, if dhcpcd.conf exists,
2017-07-27 03:00:08 +10:00
if [ [ -f "/etc/dhcpcd.conf" ] ] ; then
2017-07-06 19:25:56 -05:00
# check if the IP is already in the file
2016-12-20 17:22:57 -08:00
if grep -q " ${ IPV4_ADDRESS } " /etc/dhcpcd.conf; then
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Static IP already configured "
2017-07-06 19:25:56 -05:00
# If it's not,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# set it using our function
2016-12-20 17:22:57 -08:00
setDHCPCD
2017-07-06 19:25:56 -05:00
# Then use the ip command to immediately set the new address
2016-12-20 17:22:57 -08:00
ip addr replace dev " ${ PIHOLE_INTERFACE } " " ${ IPV4_ADDRESS } "
2017-07-06 19:25:56 -05:00
# Also give a warning that the user may need to reboot their system
2017-06-21 12:49:05 +01:00
echo -e " ${ TICK } Set IP address to ${ IPV4_ADDRESS %/* }
2017-07-27 03:00:08 +10:00
You may need to restart after the install is complete"
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# If it's not Debian, check if it's the Fedora family by checking for the file below
2017-07-27 03:00:08 +10:00
elif [ [ -f " /etc/sysconfig/network-scripts/ifcfg- ${ PIHOLE_INTERFACE } " ] ] ; then
2017-07-06 19:25:56 -05:00
# If it exists,
2016-12-20 17:22:57 -08:00
IFCFG_FILE = /etc/sysconfig/network-scripts/ifcfg-${ PIHOLE_INTERFACE }
2017-11-05 15:28:44 -05:00
IPADDR = $( echo " ${ IPV4_ADDRESS } " | cut -f1 -d/)
2017-07-06 19:25:56 -05:00
# check if the desired IP is already set
2017-11-05 15:28:44 -05:00
if grep -q " ${ IPADDR } " " ${ IFCFG_FILE } " ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Static IP already configured "
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# Put the IP in variables without the CIDR notation
2016-12-20 17:22:57 -08:00
CIDR = $( echo " ${ IPV4_ADDRESS } " | cut -f2 -d/)
# Backup existing interface configuration:
cp " ${ IFCFG_FILE } " " ${ IFCFG_FILE } " .pihole.orig
2017-07-06 19:25:56 -05:00
# Build Interface configuration file using the GLOBAL variables we have
2016-12-20 17:22:57 -08:00
{
2017-04-03 17:29:57 +02:00
echo "# Configured via Pi-hole installer"
2016-12-20 17:22:57 -08:00
echo " DEVICE= $PIHOLE_INTERFACE "
echo "BOOTPROTO=none"
echo "ONBOOT=yes"
echo " IPADDR= $IPADDR "
echo " PREFIX= $CIDR "
echo " GATEWAY= $IPv4gw "
echo " DNS1= $PIHOLE_DNS_1 "
echo " DNS2= $PIHOLE_DNS_2 "
echo "USERCTL=no"
} > " ${ IFCFG_FILE } "
2017-07-06 19:25:56 -05:00
# Use ip to immediately set the new address
2016-12-20 17:22:57 -08:00
ip addr replace dev " ${ PIHOLE_INTERFACE } " " ${ IPV4_ADDRESS } "
2017-12-07 21:33:31 -06:00
# If NetworkMangler command line interface exists and ready to mangle,
if command -v nmcli & > /dev/null && nmcli general status & > /dev/null; then
2017-07-06 19:25:56 -05:00
# Tell NetworkManagler to read our new sysconfig file
2016-12-20 17:22:57 -08:00
nmcli con load " ${ IFCFG_FILE } " > /dev/null
fi
2017-07-06 19:25:56 -05:00
# Show a warning that the user may need to restart
2017-06-21 12:49:05 +01:00
echo -e " ${ TICK } Set IP address to ${ IPV4_ADDRESS %/* }
2017-07-27 03:00:08 +10:00
You may need to restart after the install is complete"
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# If all that fails,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# show an error and exit
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Warning: Unable to locate configuration file to set static IPv4 address "
2016-12-20 17:22:57 -08:00
exit 1
fi
2015-12-06 02:40:30 -08:00
}
2017-07-06 19:25:56 -05:00
# Check an IP address to see if it is a valid one
2016-10-19 19:47:45 -07:00
valid_ip( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2016-12-20 17:22:57 -08:00
local ip = ${ 1 }
local stat = 1
2017-07-06 19:25:56 -05:00
# If the IP matches the format xxx.xxx.xxx.xxx,
2017-07-27 03:00:08 +10:00
if [ [ " ${ ip } " = ~ ^[ 0-9] { 1,3} \. [ 0-9] { 1,3} \. [ 0-9] { 1,3} \. [ 0-9] { 1,3} $ ] ] ; then
2017-07-06 19:25:56 -05:00
# Save the old Interfal Field Separator in a variable
2016-12-20 17:22:57 -08:00
OIFS = $IFS
2017-07-06 19:25:56 -05:00
# and set the new one to a dot (period)
2016-12-20 17:22:57 -08:00
IFS = '.'
2017-07-06 19:25:56 -05:00
# Put the IP into an array
2016-12-20 17:22:57 -08:00
ip = ( ${ ip } )
2017-07-06 19:25:56 -05:00
# Restore the IFS to what it was
2016-12-20 17:22:57 -08:00
IFS = ${ OIFS }
2017-07-06 19:25:56 -05:00
## Evaluate each octet by checking if it's less than or equal to 255 (the max for each octet)
2017-07-27 03:00:08 +10:00
[ [ " ${ ip [0] } " -le 255 && " ${ ip [1] } " -le 255 \
&& " ${ ip [2] } " -le 255 && " ${ ip [3] } " -le 255 ] ]
2017-07-06 19:25:56 -05:00
# Save the exit code
2016-12-20 17:22:57 -08:00
stat = $?
fi
2017-07-06 19:25:56 -05:00
# Return the exit code
2016-12-20 17:22:57 -08:00
return ${ stat }
2016-02-20 17:33:20 +00:00
}
2017-07-06 19:25:56 -05:00
# A function to choose the upstream DNS provider(s)
2016-10-19 19:47:45 -07:00
setDNS( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-01-08 23:40:19 -08:00
local DNSSettingsCorrect
2017-07-06 19:25:56 -05:00
# In an array, list the available upstream providers
2017-01-21 16:14:05 -08:00
DNSChooseOptions = ( Google ""
OpenDNS ""
Level3 ""
Norton ""
Comodo ""
2017-02-18 13:42:13 +01:00
DNSWatch ""
2017-11-17 15:54:04 +13:00
Quad9 ""
2018-03-10 17:33:31 -06:00
FamilyShield ""
2018-04-01 17:59:08 -05:00
Cloudflare ""
2017-01-21 16:14:05 -08:00
Custom "" )
2017-07-06 19:25:56 -05:00
# In a whiptail dialog, show the options
2017-11-17 18:18:13 +13:00
DNSchoices = $( whiptail --separate-output --menu "Select Upstream DNS Provider. To use your own, select Custom." ${ r } ${ c } 7 \
2017-01-08 23:40:19 -08:00
" ${ DNSChooseOptions [@] } " 2>& 1 >/dev/tty) || \
2017-07-06 19:25:56 -05:00
# exit if Cancel is selected
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
2017-07-06 19:25:56 -05:00
# Display the selection
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } Using "
2017-07-06 19:25:56 -05:00
# Depending on the user's choice, set the GLOBAl variables to the IP of the respective provider
2017-01-08 23:40:19 -08:00
case ${ DNSchoices } in
Google)
2017-06-21 12:49:05 +01:00
echo "Google DNS servers"
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = "8.8.8.8"
PIHOLE_DNS_2 = "8.8.4.4"
; ;
OpenDNS)
2017-06-21 12:49:05 +01:00
echo "OpenDNS servers"
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = "208.67.222.222"
PIHOLE_DNS_2 = "208.67.220.220"
; ;
Level3)
2017-06-21 12:49:05 +01:00
echo "Level3 servers"
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = "4.2.2.1"
PIHOLE_DNS_2 = "4.2.2.2"
; ;
Norton)
2017-06-21 12:49:05 +01:00
echo "Norton ConnectSafe servers"
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = "199.85.126.10"
PIHOLE_DNS_2 = "199.85.127.10"
; ;
Comodo)
2017-06-21 12:49:05 +01:00
echo "Comodo Secure servers"
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = "8.26.56.26"
PIHOLE_DNS_2 = "8.20.247.20"
; ;
2017-02-18 13:42:13 +01:00
DNSWatch)
2017-06-21 12:49:05 +01:00
echo "DNS.WATCH servers"
2017-02-18 13:03:40 +01:00
PIHOLE_DNS_1 = "84.200.69.80"
PIHOLE_DNS_2 = "84.200.70.40"
; ;
2017-11-17 15:54:04 +13:00
Quad9)
echo "Quad9 servers"
PIHOLE_DNS_1 = "9.9.9.9"
2017-11-20 22:05:41 +04:00
PIHOLE_DNS_2 = "149.112.112.112"
2017-11-17 15:54:04 +13:00
; ;
2018-03-10 17:33:31 -06:00
FamilyShield)
echo "FamilyShield servers"
PIHOLE_DNS_1 = "208.67.222.123"
PIHOLE_DNS_2 = "208.67.220.123"
2018-03-10 17:36:47 -06:00
; ;
2018-04-01 17:59:08 -05:00
Cloudflare)
echo "Cloudflare servers"
PIHOLE_DNS_1 = "1.1.1.1"
PIHOLE_DNS_2 = "1.0.0.1"
; ;
2017-01-08 23:40:19 -08:00
Custom)
2017-07-06 19:25:56 -05:00
# Until the DNS settings are selected,
2017-07-27 03:00:08 +10:00
until [ [ " ${ DNSSettingsCorrect } " = True ] ] ; do
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
strInvalid = "Invalid"
2017-07-06 19:25:56 -05:00
# If the first
2017-07-27 03:00:08 +10:00
if [ [ ! " ${ PIHOLE_DNS_1 } " ] ] ; then
2017-07-06 19:25:56 -05:00
# and second upstream servers do not exist
2017-07-27 03:00:08 +10:00
if [ [ ! " ${ PIHOLE_DNS_2 } " ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
prePopulate = ""
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-08 23:40:19 -08:00
else
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
prePopulate = " , ${ PIHOLE_DNS_2 } "
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
elif [ [ " ${ PIHOLE_DNS_1 } " ] ] && [ [ ! " ${ PIHOLE_DNS_2 } " ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
prePopulate = " ${ PIHOLE_DNS_1 } "
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
elif [ [ " ${ PIHOLE_DNS_1 } " ] ] && [ [ " ${ PIHOLE_DNS_2 } " ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
prePopulate = " ${ PIHOLE_DNS_1 } , ${ PIHOLE_DNS_2 } "
fi
2016-12-20 17:22:57 -08:00
2017-07-06 19:25:56 -05:00
# Dialog for the user to enter custom upstream servers
2017-07-27 03:00:08 +10:00
piholeDNS = $( whiptail --backtitle "Specify Upstream DNS Provider(s)" --inputbox "Enter your desired upstream DNS provider(s), seperated by a comma.\\n\\nFor example '8.8.8.8, 8.8.4.4'" ${ r } ${ c } " ${ prePopulate } " 3>& 1 1>& 2 2>& 3) || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = $( echo " ${ piholeDNS } " | sed 's/[, \t]\+/,/g' | awk -F, '{print$1}' )
PIHOLE_DNS_2 = $( echo " ${ piholeDNS } " | sed 's/[, \t]\+/,/g' | awk -F, '{print$2}' )
2017-07-06 19:25:56 -05:00
# If the IP is valid,
2017-07-27 03:00:08 +10:00
if ! valid_ip " ${ PIHOLE_DNS_1 } " || [ [ ! " ${ PIHOLE_DNS_1 } " ] ] ; then
2017-07-06 19:25:56 -05:00
# store it in the variable so we can use it
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = ${ strInvalid }
fi
2017-07-06 19:25:56 -05:00
# Do the same for the secondary server
2017-07-27 03:00:08 +10:00
if ! valid_ip " ${ PIHOLE_DNS_2 } " && [ [ " ${ PIHOLE_DNS_2 } " ] ] ; then
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_2 = ${ strInvalid }
fi
2017-07-06 19:25:56 -05:00
# If either of the DNS servers are invalid,
2017-07-27 03:00:08 +10:00
if [ [ " ${ PIHOLE_DNS_1 } " = = " ${ strInvalid } " ] ] || [ [ " ${ PIHOLE_DNS_2 } " = = " ${ strInvalid } " ] ] ; then
2017-07-06 19:25:56 -05:00
# explain this to the user
2017-07-27 03:00:08 +10:00
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 }
2017-07-06 19:25:56 -05:00
# and set the variables back to nothing
2017-07-27 03:00:08 +10:00
if [ [ " ${ PIHOLE_DNS_1 } " = = " ${ strInvalid } " ] ] ; then
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_1 = ""
2017-01-08 18:46:15 -08:00
fi
2017-07-27 03:00:08 +10:00
if [ [ " ${ PIHOLE_DNS_2 } " = = " ${ strInvalid } " ] ] ; then
2017-01-08 23:40:19 -08:00
PIHOLE_DNS_2 = ""
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# Since the settings will not work, stay in the loop
2017-01-08 23:40:19 -08:00
DNSSettingsCorrect = False
2017-07-06 19:25:56 -05:00
# Othwerise,
2017-01-08 23:40:19 -08:00
else
2017-07-06 19:25:56 -05:00
# Show the settings
2017-07-27 03:00:08 +10:00
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
2017-07-06 19:25:56 -05:00
# and break from the loop since the servers are vaid
2017-01-08 23:40:19 -08:00
DNSSettingsCorrect = True
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-08 23:40:19 -08:00
else
2017-07-06 19:25:56 -05:00
# If the settings are wrong, the loop continues
2017-01-08 23:40:19 -08:00
DNSSettingsCorrect = False
2016-12-20 17:22:57 -08:00
fi
2017-01-08 23:40:19 -08:00
fi
done
; ;
esac
2016-01-25 00:11:00 -05:00
}
2017-07-06 19:25:56 -05:00
# Allow the user to enable/disable logging
2016-10-31 21:38:48 +00:00
setLogging( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2016-10-31 16:48:58 -07:00
local LogToggleCommand
local LogChooseOptions
local LogChoices
2017-07-06 19:25:56 -05:00
# Ask if the user wants to log queries
2017-07-27 03:00:08 +10:00
LogToggleCommand = ( whiptail --separate-output --radiolist "Do you want to log queries?\\n (Disabling will render graphs on the Admin page useless):" ${ r } ${ c } 6)
2017-07-06 19:25:56 -05:00
# The default selection is on
2016-12-31 17:25:48 +01:00
LogChooseOptions = ( "On (Recommended)" "" on
2016-12-20 17:22:57 -08:00
Off "" off)
2017-07-06 19:25:56 -05:00
# Get the user's choice
2017-06-21 12:49:05 +01:00
LogChoices = $( " ${ LogToggleCommand [@] } " " ${ LogChooseOptions [@] } " 2>& 1 >/dev/tty) || ( echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " && exit 1)
2016-12-20 17:22:57 -08:00
case ${ LogChoices } in
2017-07-06 19:25:56 -05:00
# If it's on
2016-12-20 17:22:57 -08:00
"On (Recommended)" )
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Logging On. "
2017-07-06 19:25:56 -05:00
# Set the GLOBAL variable to true so we know what they selected
2016-12-20 17:22:57 -08:00
QUERY_LOGGING = true
; ;
2017-07-06 19:25:56 -05:00
# Othwerise, it's off,
2016-12-20 17:22:57 -08:00
Off)
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Logging Off. "
2017-07-06 19:25:56 -05:00
# So set it to false
2016-12-20 17:22:57 -08:00
QUERY_LOGGING = false
; ;
esac
2016-10-31 21:38:48 +00:00
}
2018-02-07 16:45:23 +11:00
# Function to ask the user if they want to install the dashboard
2017-01-28 14:38:54 +00:00
setAdminFlag( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-01-28 14:38:54 +00:00
local WebToggleCommand
local WebChooseOptions
local WebChoices
2017-07-06 19:25:56 -05:00
# Similar to the logging function, ask what the user wants
2017-01-28 14:38:54 +00:00
WebToggleCommand = ( whiptail --separate-output --radiolist "Do you wish to install the web admin interface?" ${ r } ${ c } 6)
2017-07-06 19:25:56 -05:00
# with the default being enabled
2017-01-28 14:38:54 +00:00
WebChooseOptions = ( "On (Recommended)" "" on
Off "" off)
2017-06-21 12:49:05 +01:00
WebChoices = $( " ${ WebToggleCommand [@] } " " ${ WebChooseOptions [@] } " 2>& 1 >/dev/tty) || ( echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " && exit 1)
2017-07-06 19:25:56 -05:00
# Depending on their choice
2017-01-28 14:38:54 +00:00
case ${ WebChoices } in
"On (Recommended)" )
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Web Interface On "
2017-07-06 19:25:56 -05:00
# Set it to true
2017-01-28 14:38:54 +00:00
INSTALL_WEB = true
; ;
Off)
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Web Interface Off "
2017-07-06 19:25:56 -05:00
# or false
2017-01-28 14:38:54 +00:00
INSTALL_WEB = false
; ;
esac
}
2018-04-17 09:50:25 +01:00
# A function to display a list of example blocklists for users to select
chooseBlocklists( ) {
# Let user select (or not) blocklists via a checklist
cmd = ( whiptail --separate-output --checklist "In order to block ads Pi-Hole relies on blacklists, either sourced from third party curated lists, or through building up a custom blacklist.\\n\\nBelow you will find some examples of third party lists.\\n\\nPlease note, the installation can be completed without any of these lists selected, but nothing will be blocked until you add your own." " ${ r } " " ${ c } " 7)
# In an array, show the options available (all off by default):
options = ( StevenBlack "StevenBlack's Unified Hosts List" off
MalwareDom "MalwareDomains" off
Cameleon "Cameleon" off
ZeusTracker "ZeusTracker" off
DisconTrack "Disconnect.me Tracking" off
DisconAd "Disconnect.me Ads" off
HostsFile "Hosts-file.net Ads" off)
# In a variable, show the choices available; exit if Cancel is selected
choices = $( " ${ cmd [@] } " " ${ options [@] } " 2>& 1 >/dev/tty) || { echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
# For each choice available,
for choice in ${ choices }
do
# Set the values to true
case ${ choice } in
StevenBlack ) echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >> " ${ adlistFile } " ; ;
MalwareDom ) echo "https://mirror1.malwaredomains.com/files/justdomains" >> " ${ adlistFile } " ; ;
Cameleon ) echo "http://sysctl.org/cameleon/hosts" >> " ${ adlistFile } " ; ;
ZeusTracker ) echo "https://zeustracker.abuse.ch/blocklist.php?download=domainblocklist" >> " ${ adlistFile } " ; ;
DisconTrack ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt" >> " ${ adlistFile } " ; ;
DisconAd ) echo "https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt" >> " ${ adlistFile } " ; ;
HostsFile ) echo "https://hosts-file.net/ad_servers.txt" >> " ${ adlistFile } " ; ;
esac
done
}
2018-02-07 16:45:23 +11:00
# Check if /etc/dnsmasq.conf is from pi-hole. If so replace with an original and install new in .d directory
2016-10-19 19:47:45 -07:00
version_check_dnsmasq( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2016-12-20 17:22:57 -08:00
local dnsmasq_conf = "/etc/dnsmasq.conf"
local dnsmasq_conf_orig = "/etc/dnsmasq.conf.orig"
local dnsmasq_pihole_id_string = "addn-hosts=/etc/pihole/gravity.list"
2017-03-13 20:24:04 -04:00
local dnsmasq_original_config = " ${ PI_HOLE_LOCAL_REPO } /advanced/dnsmasq.conf.original "
local dnsmasq_pihole_01_snippet = " ${ PI_HOLE_LOCAL_REPO } /advanced/01-pihole.conf "
2016-12-20 17:22:57 -08:00
local dnsmasq_pihole_01_location = "/etc/dnsmasq.d/01-pihole.conf"
2017-07-06 19:25:56 -05:00
# If the dnsmasq config file exists
2017-07-27 03:00:08 +10:00
if [ [ -f " ${ dnsmasq_conf } " ] ] ; then
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } Existing dnsmasq.conf found... "
2017-07-06 19:25:56 -05:00
# If gravity.list is found within this file, we presume it's from older versions on Pi-hole,
2016-12-20 17:22:57 -08:00
if grep -q ${ dnsmasq_pihole_id_string } ${ dnsmasq_conf } ; then
2017-04-03 17:29:57 +02:00
echo " it is from a previous Pi-hole install."
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } Backing up dnsmasq.conf to dnsmasq.conf.orig... "
2017-07-06 19:25:56 -05:00
# so backup the original file
2016-12-20 17:22:57 -08:00
mv -f ${ dnsmasq_conf } ${ dnsmasq_conf_orig }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Backing up dnsmasq.conf to dnsmasq.conf.orig... "
echo -ne " ${ INFO } Restoring default dnsmasq.conf... "
2017-07-06 19:25:56 -05:00
# and replace it with the default
2016-12-20 17:22:57 -08:00
cp ${ dnsmasq_original_config } ${ dnsmasq_conf }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Restoring default dnsmasq.conf... "
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# Don't to anything
2017-04-03 17:29:57 +02:00
echo " it is not a Pi-hole file, leaving alone!"
2016-12-20 17:22:57 -08:00
fi
else
2017-07-06 19:25:56 -05:00
# If a file cannot be found,
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } No dnsmasq.conf found... restoring default dnsmasq.conf... "
2017-07-06 19:25:56 -05:00
# restore the default one
2016-12-20 17:22:57 -08:00
cp ${ dnsmasq_original_config } ${ dnsmasq_conf }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } No dnsmasq.conf found... restoring default dnsmasq.conf... "
2016-12-20 17:22:57 -08:00
fi
2017-06-21 12:49:05 +01:00
echo -en " ${ INFO } Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf... "
2018-03-06 18:44:57 +00:00
# Check to see if dnsmasq directory exists (it may not due to being a fresh install and dnsmasq no longer being a dependency)
if [ [ ! -d "/etc/dnsmasq.d" ] ] ; then
mkdir "/etc/dnsmasq.d"
fi
2017-07-06 19:25:56 -05:00
# Copy the new Pi-hole DNS config file into the dnsmasq.d directory
2016-12-20 17:22:57 -08:00
cp ${ dnsmasq_pihole_01_snippet } ${ dnsmasq_pihole_01_location }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Copying 01-pihole.conf to /etc/dnsmasq.d/01-pihole.conf "
2017-07-06 19:25:56 -05:00
# Replace our placeholder values with the GLOBAL DNS variables that we populated earlier
# First, swap in the interface to listen on
2017-03-03 23:14:12 +01:00
sed -i " s/@INT@/ $PIHOLE_INTERFACE / " ${ dnsmasq_pihole_01_location }
2016-12-20 17:22:57 -08:00
if [ [ " ${ PIHOLE_DNS_1 } " != "" ] ] ; then
2017-07-06 19:25:56 -05:00
# Then swap in the primary DNS server
2016-12-20 17:22:57 -08:00
sed -i " s/@DNS1@/ $PIHOLE_DNS_1 / " ${ dnsmasq_pihole_01_location }
else
2017-07-06 19:25:56 -05:00
#
2016-12-20 17:22:57 -08:00
sed -i '/^server=@DNS1@/d' ${ dnsmasq_pihole_01_location }
fi
if [ [ " ${ PIHOLE_DNS_2 } " != "" ] ] ; then
2017-07-06 19:25:56 -05:00
# Then swap in the primary DNS server
2016-12-20 17:22:57 -08:00
sed -i " s/@DNS2@/ $PIHOLE_DNS_2 / " ${ dnsmasq_pihole_01_location }
else
2017-07-06 19:25:56 -05:00
#
2016-12-20 17:22:57 -08:00
sed -i '/^server=@DNS2@/d' ${ dnsmasq_pihole_01_location }
fi
2017-07-06 19:25:56 -05:00
#
2016-12-20 17:22:57 -08:00
sed -i 's/^#conf-dir=\/etc\/dnsmasq.d$/conf-dir=\/etc\/dnsmasq.d/' ${ dnsmasq_conf }
2017-07-06 19:25:56 -05:00
# If the user does not want to enable logging,
2016-12-20 17:22:57 -08:00
if [ [ " ${ QUERY_LOGGING } " = = false ] ] ; then
2017-07-06 19:25:56 -05:00
# Disable it by commenting out the directive in the DNS config file
2016-10-31 21:38:48 +00:00
sed -i 's/^log-queries/#log-queries/' ${ dnsmasq_pihole_01_location }
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-10-31 21:38:48 +00:00
else
2017-07-06 19:25:56 -05:00
# enable it by uncommenting the directive in the DNS config file
2016-10-31 21:38:48 +00:00
sed -i 's/^#log-queries/log-queries/' ${ dnsmasq_pihole_01_location }
fi
2016-01-25 00:04:02 -05:00
}
2017-07-10 14:12:30 -05:00
# Clean an existing installation to prepare for upgrade/reinstall
2016-11-02 00:14:25 -07:00
clean_existing( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
# ${1} Directory to clean
2016-11-02 00:14:25 -07:00
local clean_directory = " ${ 1 } "
2017-07-06 19:25:56 -05:00
# Make ${2} the new one?
2017-01-14 20:16:27 -08:00
shift
2017-07-06 19:25:56 -05:00
# ${2} Array of files to remove
2017-01-14 20:16:27 -08:00
local old_files = ( " $@ " )
2016-11-02 00:14:25 -07:00
2017-07-06 19:25:56 -05:00
# For each script found in the old files array
2016-12-20 17:22:57 -08:00
for script in " ${ old_files [@] } " ; do
2017-07-06 19:25:56 -05:00
# Remove them
2017-01-14 20:16:27 -08:00
rm -f " ${ clean_directory } / ${ script } .sh "
2016-12-20 17:22:57 -08:00
done
2016-11-02 00:14:25 -07:00
}
2016-10-05 09:57:48 -07:00
2017-07-06 19:25:56 -05:00
# Install the scripts from repository to their various locations
2016-11-02 00:14:25 -07:00
installScripts( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-06-21 12:49:05 +01:00
local str = " Installing scripts from ${ PI_HOLE_LOCAL_REPO } "
echo -ne " ${ INFO } ${ str } ... "
2016-11-02 00:14:25 -07:00
2016-12-20 17:22:57 -08:00
# Clear out script files from Pi-hole scripts directory.
2017-01-14 20:16:27 -08:00
clean_existing " ${ PI_HOLE_INSTALL_DIR } " " ${ PI_HOLE_FILES [@] } "
2016-11-02 00:14:25 -07:00
# Install files from local core repository
2016-11-02 13:34:57 +00:00
if is_repo " ${ PI_HOLE_LOCAL_REPO } " ; then
2017-07-06 19:25:56 -05:00
# move into the directory
2016-11-02 00:14:25 -07:00
cd " ${ PI_HOLE_LOCAL_REPO } "
2017-07-06 19:25:56 -05:00
# Install the scripts by:
# -o setting the owner to the user
# -Dm755 create all leading components of destiantion except the last, then copy the source to the destiantion and setting the permissions to 755
#
# This first one is the directory
2017-01-08 23:01:18 -08:00
install -o " ${ USER } " -Dm755 -d " ${ PI_HOLE_INSTALL_DIR } "
2017-07-06 19:25:56 -05:00
# The rest are the scripts Pi-hole needs
2017-01-08 23:01:18 -08:00
install -o " ${ USER } " -Dm755 -t " ${ PI_HOLE_INSTALL_DIR } " gravity.sh
install -o " ${ USER } " -Dm755 -t " ${ PI_HOLE_INSTALL_DIR } " ./advanced/Scripts/*.sh
install -o " ${ USER } " -Dm755 -t " ${ PI_HOLE_INSTALL_DIR } " ./automated\ install/uninstall.sh
2017-06-21 12:49:05 +01:00
install -o " ${ USER } " -Dm755 -t " ${ PI_HOLE_INSTALL_DIR } " ./advanced/Scripts/COL_TABLE
2016-11-02 00:14:25 -07:00
install -o " ${ USER } " -Dm755 -t /usr/local/bin/ pihole
install -Dm644 ./advanced/bash-completion/pihole /etc/bash_completion.d/pihole
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-11-02 00:14:25 -07:00
else
2017-07-06 19:25:56 -05:00
# Show an error and exit
2017-07-27 03:00:08 +10:00
echo -e " ${ OVER } ${ CROSS } ${ str }
${ COL_LIGHT_RED } Error: Local repo ${ PI_HOLE_LOCAL_REPO } not found, exiting installer${ COL_NC } "
2016-11-02 00:14:25 -07:00
exit 1
fi
2015-12-03 09:25:13 -08:00
}
2017-07-06 19:25:56 -05:00
# Install the configs from PI_HOLE_LOCAL_REPO to their various locations
2016-01-27 01:11:38 -05:00
installConfigs( ) {
2017-06-21 12:49:05 +01:00
echo ""
echo -e " ${ INFO } Installing configs from ${ PI_HOLE_LOCAL_REPO } ... "
2017-07-06 19:25:56 -05:00
# Make sure Pi-hole's config files are in place
2016-12-20 17:22:57 -08:00
version_check_dnsmasq
2017-02-04 15:25:11 +00:00
2017-07-06 19:25:56 -05:00
# If the user chose to install the dashboard,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# and if the Web server conf directory does not exist,
2017-07-27 03:00:08 +10:00
if [ [ ! -d "/etc/lighttpd" ] ] ; then
2017-07-06 19:25:56 -05:00
# make it
2017-02-04 15:25:11 +00:00
mkdir /etc/lighttpd
2017-07-06 19:25:56 -05:00
# and set the owners
2017-02-04 15:25:11 +00:00
chown " ${ USER } " :root /etc/lighttpd
2017-07-06 19:25:56 -05:00
# Otherwise, if the config file already exists
2017-07-27 03:00:08 +10:00
elif [ [ -f "/etc/lighttpd/lighttpd.conf" ] ] ; then
2017-07-06 19:25:56 -05:00
# back up the original
2017-02-04 15:25:11 +00:00
mv /etc/lighttpd/lighttpd.conf /etc/lighttpd/lighttpd.conf.orig
fi
2017-07-06 19:25:56 -05:00
# and copy in the config file Pi-hole needs
2017-03-13 20:24:04 -04:00
cp ${ PI_HOLE_LOCAL_REPO } /advanced/${ LIGHTTPD_CFG } /etc/lighttpd/lighttpd.conf
2017-09-09 19:30:53 +01:00
# if there is a custom block page in the html/pihole directory, replace 404 handler in lighttpd config
if [ [ -f "/var/www/html/pihole/custom.php" ] ] ; then
sed -i 's/^\(server\.error-handler-404\s*=\s*\).*$/\1"pihole\/custom\.php"/' /etc/lighttpd/lighttpd.conf
fi
2017-07-06 19:25:56 -05:00
# Make the directories if they do not exist and set the owners
2017-02-04 15:25:11 +00:00
mkdir -p /var/run/lighttpd
chown ${ LIGHTTPD_USER } :${ LIGHTTPD_GROUP } /var/run/lighttpd
mkdir -p /var/cache/lighttpd/compress
chown ${ LIGHTTPD_USER } :${ LIGHTTPD_GROUP } /var/cache/lighttpd/compress
mkdir -p /var/cache/lighttpd/uploads
chown ${ LIGHTTPD_USER } :${ LIGHTTPD_GROUP } /var/cache/lighttpd/uploads
2016-12-20 17:22:57 -08:00
fi
2015-12-03 09:25:13 -08:00
}
2016-10-10 01:25:11 -07:00
stop_service( ) {
2016-12-20 17:22:57 -08:00
# Stop service passed in as argument.
# Can softfail, as process may not be installed when this is called
2018-03-18 00:38:34 +00:00
local str = " Stopping ${ 1 } service "
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2016-12-27 11:53:23 -08:00
if command -v systemctl & > /dev/null; then
2016-12-21 11:54:52 +01:00
systemctl stop " ${ 1 } " & > /dev/null || true
2016-12-20 17:22:57 -08:00
else
2016-12-21 11:54:52 +01:00
service " ${ 1 } " stop & > /dev/null || true
2016-12-20 17:22:57 -08:00
fi
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } ... "
2016-10-10 06:06:34 -07:00
}
2017-07-06 19:25:56 -05:00
# Start/Restart service passed in as argument
2016-10-10 06:06:34 -07:00
start_service( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2018-03-18 00:38:34 +00:00
local str = " Starting ${ 1 } service "
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# If systemctl exists,
2016-12-27 11:53:23 -08:00
if command -v systemctl & > /dev/null; then
2017-07-06 19:25:56 -05:00
# use that to restart the service
2016-12-21 11:54:52 +01:00
systemctl restart " ${ 1 } " & > /dev/null
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# fall back to the service command
2016-12-21 11:54:52 +01:00
service " ${ 1 } " restart & > /dev/null
2016-12-20 17:22:57 -08:00
fi
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2016-10-10 06:06:34 -07:00
}
2017-07-06 19:25:56 -05:00
# Enable service so that it will start with next reboot
2016-10-10 06:06:34 -07:00
enable_service( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2018-03-18 00:38:34 +00:00
local str = " Enabling ${ 1 } service to start on reboot "
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# If systemctl exists,
2016-12-27 11:53:23 -08:00
if command -v systemctl & > /dev/null; then
2017-07-06 19:25:56 -05:00
# use that to enable the service
2016-12-21 11:54:52 +01:00
systemctl enable " ${ 1 } " & > /dev/null
2018-03-17 22:48:11 +00:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# use update-rc.d to accomplish this
2016-12-21 11:54:52 +01:00
update-rc.d " ${ 1 } " defaults & > /dev/null
2016-12-20 17:22:57 -08:00
fi
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2015-12-03 09:25:13 -08:00
}
2016-10-09 22:05:06 -07:00
2018-03-06 18:44:57 +00:00
# Disable service so that it will not with next reboot
disable_service( ) {
# Local, named variables
2018-03-18 00:38:34 +00:00
local str = " Disabling ${ 1 } service "
2018-03-06 18:44:57 +00:00
echo -ne " ${ INFO } ${ str } ... "
# If systemctl exists,
if command -v systemctl & > /dev/null; then
# use that to disable the service
systemctl disable " ${ 1 } " & > /dev/null
2018-03-17 22:48:11 +00:00
# Otherwise,
2018-03-06 18:44:57 +00:00
else
# use update-rc.d to accomplish this
update-rc.d " ${ 1 } " disable & > /dev/null
fi
echo -e " ${ OVER } ${ TICK } ${ str } "
}
2018-03-07 23:31:28 +00:00
check_service_active( ) {
# If systemctl exists,
if command -v systemctl & > /dev/null; then
2018-03-17 22:56:50 +00:00
# use that to check the status of the service
2018-03-18 00:38:34 +00:00
systemctl is-enabled " ${ 1 } " > /dev/null
2018-03-17 22:48:11 +00:00
# Otherwise,
2018-03-07 23:31:28 +00:00
else
# fall back to service command
2018-03-18 00:38:34 +00:00
service " ${ 1 } " status > /dev/null
2018-03-18 00:13:10 +00:00
fi
2018-03-07 23:31:28 +00:00
}
2017-01-28 15:44:31 -08:00
update_package_cache( ) {
2017-07-06 19:25:56 -05:00
# Running apt-get update/upgrade with minimal output can cause some issues with
# requiring user input (e.g password for phpmyadmin see #218)
2016-12-20 17:22:57 -08:00
2017-07-06 19:25:56 -05:00
# Update package cache on apt based OSes. Do this every time since
# it's quick and packages can be updated at any time.
2016-12-20 17:22:57 -08:00
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-06-21 12:49:05 +01:00
local str = "Update local cache of available packages"
echo ""
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Create a command from the package cache variable
2017-03-03 11:35:44 +01:00
if eval " ${ UPDATE_PKG_CACHE } " & > /dev/null; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-28 16:33:40 -08:00
else
2017-07-06 19:25:56 -05:00
# show an error and exit
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } "
echo -ne " ${ COL_LIGHT_RED } Error: Unable to update package cache. Please try \" ${ UPDATE_PKG_CACHE } \" ${ COL_NC } "
2017-03-02 15:54:58 -08:00
return 1
2017-01-28 15:44:31 -08:00
fi
2016-10-10 02:24:03 -07:00
}
2017-07-06 19:25:56 -05:00
# Let user know if they have outdated packages on their system and
# advise them to run a package update at soonest possible.
2016-10-19 19:47:45 -07:00
notify_package_updates_available( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-06-21 12:49:05 +01:00
local str = " Checking ${ PKG_MANAGER } for upgraded packages "
2017-07-27 03:00:08 +10:00
echo -ne " \\n ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Store the list of packages in a variable
2016-12-20 17:22:57 -08:00
updatesToInstall = $( eval " ${ PKG_COUNT } " )
2017-07-27 03:00:08 +10:00
2016-12-29 01:34:49 -08:00
if [ [ -d " /lib/modules/ $( uname -r) " ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
if [ [ " ${ updatesToInstall } " -eq 0 ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } ... up to date! "
echo ""
2016-12-29 01:34:49 -08:00
else
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } ... ${ updatesToInstall } updates available "
echo -e " ${ INFO } ${ COL_LIGHT_GREEN } It is recommended to update your OS after installing the Pi-hole! ${ COL_NC } "
echo ""
2016-12-29 01:34:49 -08:00
fi
2016-12-29 01:35:52 -08:00
else
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str }
2017-07-27 03:00:08 +10:00
Kernel update detected. If the install fails, please reboot and try again\\ n"
2016-12-20 17:22:57 -08:00
fi
2016-10-09 22:00:23 -07:00
}
2017-07-06 19:25:56 -05:00
# What's this doing outside of a function in the middle of nowhere?
2017-06-21 12:49:05 +01:00
counter = 0
2017-07-06 19:25:56 -05:00
2016-10-19 19:47:45 -07:00
install_dependent_packages( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables should be used here, especially for an iterator
# Add one to the counter
2017-06-21 12:49:05 +01:00
counter = $(( counter+1))
2017-07-06 19:25:56 -05:00
# If it equals 1,
2017-07-27 03:00:08 +10:00
if [ [ " ${ counter } " = = 1 ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Installer Dependency checks... "
else
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Main Dependency checks... "
fi
2016-12-20 17:22:57 -08:00
# Install packages passed in via argument array
# No spinner - conflicts with set -e
declare -a argArray1 = ( " ${ !1 } " )
2016-12-21 22:20:23 -08:00
declare -a installArray
2016-12-20 17:22:57 -08:00
2016-12-21 22:20:23 -08:00
# Debian based package install - debconf will download the entire package list
# so we just create an array of packages not currently installed to cut down on the
# amount of download traffic.
# NOTE: We may be able to use this installArray in the future to create a list of package that were
# installed by us, and remove only the installed packages, and not the entire list.
2016-12-20 16:47:43 -08:00
if command -v debconf-apt-progress & > /dev/null; then
2017-07-06 19:25:56 -05:00
# For each package,
2016-12-20 16:47:43 -08:00
for i in " ${ argArray1 [@] } " ; do
2017-08-23 11:51:16 +10:00
echo -ne " ${ INFO } Checking for $i ... "
2017-07-06 19:25:56 -05:00
#
2016-12-21 22:57:42 -08:00
if dpkg-query -W -f= '${Status}' " ${ i } " 2>/dev/null | grep "ok installed" & > /dev/null; then
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Checking for $i "
2016-12-21 22:20:23 -08:00
else
2017-07-06 19:25:56 -05:00
#
2017-12-11 09:45:30 -08:00
echo -e " ${ OVER } ${ INFO } Checking for $i (will be installed) "
2017-07-06 19:25:56 -05:00
#
2016-12-21 22:20:23 -08:00
installArray += ( " ${ i } " )
fi
2016-12-20 16:47:43 -08:00
done
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
if [ [ " ${# installArray [@] } " -gt 0 ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-03-03 11:52:49 +01:00
test_dpkg_lock
2017-07-06 19:25:56 -05:00
#
2017-01-08 23:01:18 -08:00
debconf-apt-progress -- " ${ PKG_INSTALL [@] } " " ${ installArray [@] } "
2016-12-24 16:52:46 -08:00
return
fi
2017-06-21 12:49:05 +01:00
echo ""
2017-07-06 19:25:56 -05:00
#
2016-12-21 23:38:31 -08:00
return 0
2016-12-20 16:47:43 -08:00
fi
2016-12-21 23:38:31 -08:00
2017-07-06 19:25:56 -05:00
# Install Fedora/CentOS packages
2016-12-21 23:38:31 -08:00
for i in " ${ argArray1 [@] } " ; do
2017-08-23 11:51:16 +10:00
echo -ne " ${ INFO } Checking for $i ... "
2017-07-06 19:25:56 -05:00
#
2016-12-22 03:21:37 -08:00
if ${ PKG_MANAGER } -q list installed " ${ i } " & > /dev/null; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Checking for $i "
2016-12-21 23:38:31 -08:00
else
2017-12-11 09:45:30 -08:00
echo -e " ${ OVER } ${ INFO } Checking for $i (will be installed) "
2017-07-06 19:25:56 -05:00
#
2016-12-21 23:38:31 -08:00
installArray += ( " ${ i } " )
fi
done
2017-11-05 11:02:04 +01:00
#
if [ [ " ${# installArray [@] } " -gt 0 ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-11-05 11:02:04 +01:00
" ${ PKG_INSTALL [@] } " " ${ installArray [@] } " & > /dev/null
return
fi
echo ""
return 0
2015-12-03 09:25:13 -08:00
}
2017-07-06 19:25:56 -05:00
# Install the Web interface dashboard
2016-01-27 01:11:38 -05:00
installPiholeWeb( ) {
2017-06-21 12:49:05 +01:00
echo ""
echo " ${ INFO } Installing blocking page... "
2016-12-20 17:22:57 -08:00
2017-09-09 19:07:48 +01:00
local str = "Creating directory for blocking page, and copying files"
echo -ne " ${ INFO } ${ str } ... "
# Install the directory
install -d /var/www/html/pihole
# and the blockpage
install -D ${ PI_HOLE_LOCAL_REPO } /advanced/{ index,blockingpage} .* /var/www/html/pihole/
2017-10-04 01:13:02 +11:00
# Remove superseded file
if [ [ -e "/var/www/html/pihole/index.js" ] ] ; then
rm "/var/www/html/pihole/index.js"
fi
2017-09-09 19:07:48 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2016-12-20 17:22:57 -08:00
2017-09-09 19:07:48 +01:00
local str = "Backing up index.lighttpd.html"
echo -ne " ${ INFO } ${ str } ... "
# If the default index file exists,
if [ [ -f "/var/www/html/index.lighttpd.html" ] ] ; then
# back it up
mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.orig
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2018-03-17 22:48:11 +00:00
# Otherwise,
2017-09-09 19:07:48 +01:00
else
# don't do anything
echo -e " ${ OVER } ${ CROSS } ${ str }
2017-12-06 15:17:31 +00:00
No default index.lighttpd.html file found... not backing up"
2016-12-20 17:22:57 -08:00
fi
2017-01-27 21:50:32 -08:00
2017-07-06 19:25:56 -05:00
# Install Sudoers file
2017-06-21 12:49:05 +01:00
echo ""
local str = "Installing sudoer file"
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Make the .d directory if it doesn't exist
2016-12-20 17:22:57 -08:00
mkdir -p /etc/sudoers.d/
2017-07-06 19:25:56 -05:00
# and copy in the pihole sudoers file
2017-03-13 20:24:04 -04:00
cp ${ PI_HOLE_LOCAL_REPO } /advanced/pihole.sudo /etc/sudoers.d/pihole
2016-12-22 13:26:11 +01:00
# Add lighttpd user (OS dependent) to sudoers file
echo " ${ LIGHTTPD_USER } ALL=NOPASSWD: /usr/local/bin/pihole " >> /etc/sudoers.d/pihole
2016-12-23 16:57:51 +01:00
2017-07-06 19:25:56 -05:00
# If the Web server user is lighttpd,
2016-12-23 17:12:38 +01:00
if [ [ " $LIGHTTPD_USER " = = "lighttpd" ] ] ; then
2016-12-23 16:57:51 +01:00
# Allow executing pihole via sudo with Fedora
# Usually /usr/local/bin is not permitted as directory for sudoable programms
echo "Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin" >> /etc/sudoers.d/pihole
fi
2017-07-06 19:25:56 -05:00
# Set the strict permissions on the file
2016-12-20 17:22:57 -08:00
chmod 0440 /etc/sudoers.d/pihole
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2015-12-03 09:25:13 -08:00
}
2017-07-06 19:25:56 -05:00
# Installs a cron file
2016-01-27 01:11:38 -05:00
installCron( ) {
2016-12-20 17:22:57 -08:00
# Install the cron job
2017-06-21 12:49:05 +01:00
local str = "Installing latest Cron script"
echo ""
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Copy the cron file over from the local repo
2017-03-13 20:24:04 -04:00
cp ${ PI_HOLE_LOCAL_REPO } /advanced/pihole.cron /etc/cron.d/pihole
2017-10-21 15:52:53 +02:00
# Randomize gravity update time
2017-12-21 12:42:47 +01:00
sed -i " s/59 1 / $(( 1 + RANDOM % 58 )) $(( 3 + RANDOM % 2 )) / " /etc/cron.d/pihole
# Randomize update checker time
sed -i " s/59 17/ $(( 1 + RANDOM % 58 )) $(( 12 + RANDOM % 8 )) / " /etc/cron.d/pihole
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2015-12-03 09:25:13 -08:00
}
2017-07-06 19:25:56 -05:00
# Gravity is a very important script as it aggregates all of the domains into a single HOSTS formatted list,
# which is what Pi-hole needs to begin blocking ads
2016-01-27 01:11:38 -05:00
runGravity( ) {
2017-07-06 19:25:56 -05:00
# Run gravity in the current shell
2018-02-22 14:45:31 +00:00
{ /opt/pihole/gravity.sh --force; }
2016-01-19 22:52:29 +00:00
}
2017-07-06 19:25:56 -05:00
# Check if the pihole user exists and create if it does not
2016-10-19 19:47:45 -07:00
create_pihole_user( ) {
2017-06-21 12:49:05 +01:00
local str = "Checking for user 'pihole'"
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# If the user pihole exists,
2017-01-14 17:01:47 -08:00
if id -u pihole & > /dev/null; then
2017-07-06 19:25:56 -05:00
# just show a success
2017-06-21 12:49:05 +01:00
echo -ne " ${ OVER } ${ TICK } ${ str } "
2018-03-17 22:48:11 +00:00
# Otherwise,
2017-01-14 17:01:47 -08:00
else
2017-06-21 12:49:05 +01:00
echo -ne " ${ OVER } ${ CROSS } ${ str } "
local str = "Creating user 'pihole'"
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# create her with the useradd command
2017-01-14 17:01:47 -08:00
useradd -r -s /usr/sbin/nologin pihole
2017-06-21 12:49:05 +01:00
echo -ne " ${ OVER } ${ TICK } ${ str } "
2017-01-14 17:01:47 -08:00
fi
2016-01-25 00:28:53 -05:00
}
2016-01-20 23:34:18 +00:00
2017-07-06 19:25:56 -05:00
# Allow HTTP and DNS traffic
2016-05-14 17:05:40 -06:00
configureFirewall( ) {
2017-06-21 12:49:05 +01:00
echo ""
2017-07-06 19:25:56 -05:00
# If a firewall is running,
2017-01-24 15:44:48 -08:00
if firewall-cmd --state & > /dev/null; then
2017-07-06 19:25:56 -05:00
# ask if the user wants to install Pi-hole's default firwall rules
2017-07-27 03:00:08 +10:00
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${ r } ${ c } || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ INFO } Not installing firewall rulesets. " ; return 0; }
2018-03-06 18:44:57 +00:00
echo -e " ${ TICK } Configuring FirewallD for httpd and pihole-FTL "
2017-07-06 19:25:56 -05:00
# Allow HTTP and DNS traffice
2017-03-16 09:29:33 +11:00
firewall-cmd --permanent --add-service= http --add-service= dns
2017-07-06 19:25:56 -05:00
# Reload the firewall to apply these changes
2016-12-29 15:57:29 -08:00
firewall-cmd --reload
2017-01-17 13:56:34 -08:00
return 0
2016-12-31 19:07:40 -08:00
# Check for proper kernel modules to prevent failure
2017-01-13 18:12:03 +01:00
elif modinfo ip_tables & > /dev/null && command -v iptables & > /dev/null; then
2016-12-31 19:07:40 -08:00
# If chain Policy is not ACCEPT or last Rule is not ACCEPT
# then check and insert our Rules above the DROP/REJECT Rule.
2017-01-01 14:38:10 -08:00
if iptables -S INPUT | head -n1 | grep -qv '^-P.*ACCEPT$' || iptables -S INPUT | tail -n1 | grep -qv '^-\(A\|P\).*ACCEPT$' ; then
2017-07-27 03:00:08 +10:00
whiptail --title "Firewall in use" --yesno "We have detected a running firewall\\n\\nPi-hole currently requires HTTP and DNS port access.\\n\\n\\n\\nInstall Pi-hole default firewall rules?" ${ r } ${ c } || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ INFO } Not installing firewall rulesets. " ; return 0; }
2017-07-27 03:00:08 +10:00
echo -e " ${ TICK } Installing new IPTables firewall rulesets "
2016-12-31 19:07:40 -08:00
# Check chain first, otherwise a new rule will duplicate old ones
iptables -C INPUT -p tcp -m tcp --dport 80 -j ACCEPT & > /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -C INPUT -p tcp -m tcp --dport 53 -j ACCEPT & > /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 53 -j ACCEPT
iptables -C INPUT -p udp -m udp --dport 53 -j ACCEPT & > /dev/null || iptables -I INPUT 1 -p udp -m udp --dport 53 -j ACCEPT
2017-05-20 15:47:51 +02:00
iptables -C INPUT -p tcp -m tcp --dport 4711:4720 -i lo -j ACCEPT & > /dev/null || iptables -I INPUT 1 -p tcp -m tcp --dport 4711:4720 -i lo -j ACCEPT
2017-01-17 13:56:34 -08:00
return 0
2016-12-31 19:07:40 -08:00
fi
2018-03-17 22:48:11 +00:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# no firewall is running
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } No active firewall detected.. skipping firewall configuration "
2017-07-06 19:25:56 -05:00
# so just exit
2017-01-17 13:56:34 -08:00
return 0
2016-12-20 17:22:57 -08:00
fi
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } Skipping firewall configuration "
2016-05-14 17:05:40 -06:00
}
2017-07-06 19:25:56 -05:00
#
2016-08-26 22:45:38 +01:00
finalExports( ) {
2017-07-06 19:25:56 -05:00
# If the Web interface is not set to be installed,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = false ] ] ; then
2017-07-06 19:25:56 -05:00
# and if there is not an IPv4 address,
2017-07-27 03:00:08 +10:00
if [ [ " ${ IPV4_ADDRESS } " ] ] ; then
2017-07-06 19:25:56 -05:00
# there is no block page, so set IPv4 to 0.0.0.0 (all IP addresses)
2017-02-04 15:25:11 +00:00
IPV4_ADDRESS = "0.0.0.0"
fi
2017-07-27 03:00:08 +10:00
if [ [ " ${ IPV6_ADDRESS } " ] ] ; then
2017-07-06 19:25:56 -05:00
# and IPv6 to ::/0
2017-02-04 15:25:11 +00:00
IPV6_ADDRESS = "::/0"
fi
fi
2017-07-06 19:25:56 -05:00
# If the setup variable file exists,
2017-07-27 03:00:08 +10:00
if [ [ -e " ${ setupVars } " ] ] ; then
# update the variables in the file
2017-09-22 19:14:11 +10:00
sed -i.update.bak '/PIHOLE_INTERFACE/d;/IPV4_ADDRESS/d;/IPV6_ADDRESS/d;/PIHOLE_DNS_1/d;/PIHOLE_DNS_2/d;/QUERY_LOGGING/d;/INSTALL_WEB/d;/LIGHTTPD_ENABLED/d;' " ${ setupVars } "
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# echo the information to the user
2016-10-10 02:57:04 -07:00
{
2016-12-20 17:22:57 -08:00
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 } "
2017-01-28 14:38:54 +00:00
echo " INSTALL_WEB= ${ INSTALL_WEB } "
2017-07-17 01:44:14 +10:00
echo " LIGHTTPD_ENABLED= ${ LIGHTTPD_ENABLED } "
2016-10-10 05:45:37 -07:00
} >> " ${ setupVars } "
2016-12-28 16:31:55 +00:00
2017-07-26 14:34:40 +01:00
# Bring in the current settings and the functions to manipulate them
2016-12-28 16:31:55 +00:00
source " ${ setupVars } "
2017-03-13 20:24:04 -04:00
source " ${ PI_HOLE_LOCAL_REPO } /advanced/Scripts/webpage.sh "
2017-01-02 10:50:59 +01:00
2017-07-26 14:34:40 +01:00
# Look for DNS server settings which would have to be reapplied
2017-07-26 12:15:23 -04:00
ProcessDNSSettings
2017-01-02 10:50:59 +01:00
2017-07-26 12:15:23 -04:00
# Look for DHCP server settings which would have to be reapplied
ProcessDHCPSettings
2015-11-07 12:07:50 -06:00
}
2017-07-06 19:25:56 -05:00
# Install the logrotate script
2017-01-27 14:16:24 +01:00
installLogrotate( ) {
2017-07-06 19:25:56 -05:00
2017-06-21 12:49:05 +01:00
local str = "Installing latest logrotate script"
echo ""
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# Copy the file over from the local repo
2017-03-13 20:24:04 -04:00
cp ${ PI_HOLE_LOCAL_REPO } /advanced/logrotate /etc/pihole/logrotate
2017-01-27 14:28:59 +01:00
# Different operating systems have different user / group
# settings for logrotate that makes it impossible to create
# a static logrotate file that will work with e.g.
# Rasbian and Ubuntu at the same time. Hence, we have to
# customize the logrotate script here in order to reflect
# the local properties of the /var/log directory
logusergroup = " $( stat -c '%U %G' /var/log) "
2017-07-06 19:25:56 -05:00
# If the variable has a value,
2017-07-27 03:00:08 +10:00
if [ [ ! -z " ${ logusergroup } " ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-06-03 14:51:35 +02:00
sed -i " s/# su #/su ${ logusergroup } /g; " /etc/pihole/logrotate
2017-01-27 14:28:59 +01:00
fi
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2017-01-27 14:16:24 +01:00
}
2017-07-06 19:25:56 -05:00
# Install base files and web interface
2016-08-19 22:45:24 +01:00
installPihole( ) {
2017-07-06 19:25:56 -05:00
# Create the pihole user
2016-12-20 17:22:57 -08:00
create_pihole_user
2017-01-28 15:45:14 +00:00
2017-07-06 19:25:56 -05:00
# If the user wants to install the Web interface,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
if [ [ ! -d "/var/www/html" ] ] ; then
2017-07-06 19:25:56 -05:00
# make the Web directory if necessary
2017-01-28 15:45:14 +00:00
mkdir -p /var/www/html
fi
2017-07-06 19:25:56 -05:00
# Set the owner and permissions
2017-01-28 15:45:14 +00:00
chown ${ LIGHTTPD_USER } :${ LIGHTTPD_GROUP } /var/www/html
chmod 775 /var/www/html
2017-07-06 19:25:56 -05:00
# Give pihole access to the Web server group
2017-01-28 15:45:14 +00:00
usermod -a -G ${ LIGHTTPD_GROUP } pihole
2017-07-06 19:25:56 -05:00
# If the lighttpd command is executable,
2017-07-27 03:00:08 +10:00
if [ [ -x " $( command -v lighty-enable-mod) " ] ] ; then
2017-07-06 19:25:56 -05:00
# enable fastcgi and fastcgi-php
2017-01-28 15:45:14 +00:00
lighty-enable-mod fastcgi fastcgi-php > /dev/null || true
else
2017-07-06 19:25:56 -05:00
# Othweise, show info about installing them
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Warning: 'lighty-enable-mod' utility not found
2017-07-27 03:00:08 +10:00
Please ensure fastcgi is enabled if you experience issues\\ n"
2017-01-28 15:45:14 +00:00
fi
2016-12-20 17:22:57 -08:00
fi
2017-07-06 19:25:56 -05:00
# Install scripts,
2016-12-20 17:22:57 -08:00
installScripts
2017-07-06 19:25:56 -05:00
# configs,
2016-12-20 17:22:57 -08:00
installConfigs
2017-07-06 19:25:56 -05:00
# If the user wants to install the dashboard,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# do so
2017-01-28 15:25:02 +00:00
installPiholeWeb
fi
2017-07-06 19:25:56 -05:00
# Install the cron file
2016-12-20 17:22:57 -08:00
installCron
2017-07-06 19:25:56 -05:00
# Install the logrotate file
2017-01-27 14:16:24 +01:00
installLogrotate
2017-07-06 19:25:56 -05:00
# Check if FTL is installed
2017-07-27 03:00:08 +10:00
FTLdetect || echo -e " ${ CROSS } FTL Engine not installed "
2017-07-06 19:25:56 -05:00
# Configure the firewall
2016-12-20 17:22:57 -08:00
configureFirewall
2017-07-26 14:34:40 +01:00
#update setupvars.conf with any variables that may or may not have been changed during the install
2016-12-20 17:22:57 -08:00
finalExports
2016-08-19 22:45:24 +01:00
}
2017-07-06 19:25:56 -05:00
# At some point in the future this list can be pruned, for now we'll need it to ensure updates don't break.
# Refactoring of install script has changed the name of a couple of variables. Sort them out here.
2016-11-01 09:36:59 +00:00
accountForRefactor( ) {
2016-12-20 17:22:57 -08:00
sed -i 's/piholeInterface/PIHOLE_INTERFACE/g' ${ setupVars }
sed -i 's/IPv4_address/IPV4_ADDRESS/g' ${ setupVars }
sed -i 's/IPv4addr/IPV4_ADDRESS/g' ${ setupVars }
sed -i 's/IPv6_address/IPV6_ADDRESS/g' ${ setupVars }
sed -i 's/piholeIPv6/IPV6_ADDRESS/g' ${ setupVars }
sed -i 's/piholeDNS1/PIHOLE_DNS_1/g' ${ setupVars }
sed -i 's/piholeDNS2/PIHOLE_DNS_2/g' ${ setupVars }
2016-11-01 09:36:59 +00:00
}
updatePihole( ) {
2016-11-02 09:33:17 +00:00
accountForRefactor
# Install base files and web interface
installScripts
2017-07-06 19:25:56 -05:00
# Install config files
2018-03-23 10:53:22 +00:00
installConfigs
2017-07-06 19:25:56 -05:00
# If the user wants to install the dasboard,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# do so
2017-01-28 15:25:02 +00:00
installPiholeWeb
fi
2017-07-06 19:25:56 -05:00
# Install the cron file
2016-11-02 09:33:17 +00:00
installCron
2017-07-06 19:25:56 -05:00
# Install logrotate
2017-01-27 14:16:24 +01:00
installLogrotate
2017-07-06 19:25:56 -05:00
# Detect if FTL is installed
2017-06-21 12:49:05 +01:00
FTLdetect || echo -e " ${ CROSS } FTL Engine not installed. "
2016-08-19 22:45:24 +01:00
2017-07-26 14:34:40 +01:00
#update setupvars.conf with any variables that may or may not have been changed during the install
finalExports
2017-07-17 01:44:14 +10:00
2016-08-19 22:45:24 +01:00
}
2016-12-23 16:53:42 +00:00
2017-07-06 19:25:56 -05:00
# SELinux
2016-12-23 10:27:52 -06:00
checkSelinux( ) {
2017-07-06 19:25:56 -05:00
# If the getenforce command exists,
2016-12-27 11:53:23 -08:00
if command -v getenforce & > /dev/null; then
2017-07-06 19:25:56 -05:00
# Store the current mode in a variable
2016-12-23 17:16:03 +00:00
enforceMode = $( getenforce)
2017-07-27 03:00:08 +10:00
echo -e " \\n ${ INFO } SELinux mode detected: ${ enforceMode } "
2017-07-06 19:25:56 -05:00
# If it's enforcing,
2016-12-23 17:16:03 +00:00
if [ [ " ${ enforceMode } " = = "Enforcing" ] ] ; then
2017-07-06 19:25:56 -05:00
# Explain Pi-hole does not support it yet
2017-07-27 03:00:08 +10:00
whiptail --defaultno --title "SELinux Enforcing Detected" --yesno "SELinux is being ENFORCED on your system! \\n\\nPi-hole currently does not support SELinux, but you may still continue with the installation.\\n\\nNote: Web Admin will not be fully functional unless you set your policies correctly\\n\\nContinue installing Pi-hole?" ${ r } ${ c } || \
{ echo -e " \\n ${ COL_LIGHT_RED } SELinux Enforcing detected, exiting installer ${ COL_NC } " ; exit 1; }
echo -e " ${ INFO } Continuing installation with SELinux Enforcing
${ INFO } Please refer to official SELinux documentation to create a custom policy"
2016-12-20 17:22:57 -08:00
fi
fi
2015-11-07 12:07:50 -06:00
}
2017-07-06 19:25:56 -05:00
# Installation complete message with instructions for the user
2016-01-27 01:11:38 -05:00
displayFinalMessage( ) {
2017-07-06 19:25:56 -05:00
# If
2017-07-27 03:00:08 +10:00
if [ [ " ${# 1 } " -gt 0 ] ] ; then
2017-05-23 10:44:11 +02:00
pwstring = " $1 "
2017-07-06 19:25:56 -05:00
# else, if the dashboard password in the setup variables exists,
2017-05-23 10:44:11 +02:00
elif [ [ $( grep 'WEBPASSWORD' -c /etc/pihole/setupVars.conf) -gt 0 ] ] ; then
2017-07-06 19:25:56 -05:00
# set a variable for evaluation later
2017-05-23 10:44:11 +02:00
pwstring = "unchanged"
else
2017-07-06 19:25:56 -05:00
# set a variable for evaluation later
2017-05-23 10:44:11 +02:00
pwstring = "NOT SET"
fi
2017-07-06 19:25:56 -05:00
# If the user wants to install the dashboard,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# Store a message in a variable and display it
2017-01-28 15:43:33 +00:00
additional = " View the web interface at http://pi.hole/admin or http:// ${ IPV4_ADDRESS %/* } /admin
2017-05-23 10:44:11 +02:00
Your Admin Webpage login password is ${ pwstring } "
2017-01-28 15:43:33 +00:00
fi
2016-12-20 17:22:57 -08:00
# 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:
2015-12-31 20:26:05 -06:00
2016-11-01 09:45:22 +00:00
IPv4: ${ IPV4_ADDRESS %/* }
2017-01-01 07:10:14 -08:00
IPv6: ${ IPV6_ADDRESS :- "Not Configured" }
2015-12-31 20:26:05 -06:00
2016-04-03 18:05:11 -05:00
If you set a new IP address, you should restart the Pi.
2015-12-31 20:26:05 -06:00
2016-05-25 18:55:36 -04:00
The install log is in /etc/pihole.
2016-12-15 14:10:55 +01:00
2017-01-28 15:43:33 +00:00
${ additional } " ${ r } ${ c }
2016-08-19 22:31:11 +01:00
}
2016-10-19 19:47:45 -07:00
update_dialogs( ) {
2017-07-06 19:25:56 -05:00
# If pihole -r "reconfigure" option was selected,
2017-07-27 03:00:08 +10:00
if [ [ " ${ reconfigure } " = true ] ] ; then
2017-07-06 19:25:56 -05:00
# set some variables that will be used
2016-12-20 17:22:57 -08:00
opt1a = "Repair"
opt1b = "This will retain existing settings"
strAdd = "You will remain on the same version"
2017-07-06 19:25:56 -05:00
# Othweise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# set some variables with different values
2016-12-20 17:22:57 -08:00
opt1a = "Update"
opt1b = "This will retain existing settings."
strAdd = "You will be updated to the latest version."
fi
opt2a = "Reconfigure"
opt2b = "This will allow you to enter new settings"
2017-07-06 19:25:56 -05:00
# Display the information to the user
2017-07-27 03:00:08 +10:00
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 \
2016-12-20 17:22:57 -08:00
" ${ opt1a } " " ${ opt1b } " \
2017-01-08 18:46:15 -08:00
" ${ opt2a } " " ${ opt2b } " 3>& 2 2>& 1 1>& 3) || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Cancel was selected, exiting installer ${ COL_NC } " ; exit 1; }
2017-01-08 18:46:15 -08:00
2017-11-05 10:18:39 +01:00
# Set the variable based on if the user chooses
2017-01-08 18:46:15 -08:00
case ${ UpdateCmd } in
2017-07-06 19:25:56 -05:00
# repair, or
2017-01-08 18:46:15 -08:00
${ opt1a } )
2017-07-27 03:00:08 +10:00
echo -e " ${ INFO } ${ opt1a } option selected "
2017-01-08 18:46:15 -08:00
useUpdateVars = true
; ;
2017-11-05 10:16:56 +01:00
# reconfigure,
2017-01-08 18:46:15 -08:00
${ opt2a } )
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } ${ opt2a } option selected "
2017-01-08 18:46:15 -08:00
useUpdateVars = false
; ;
2016-12-20 17:22:57 -08:00
esac
2015-12-31 20:26:05 -06:00
}
2017-01-28 15:15:42 +00:00
clone_or_update_repos( ) {
2017-07-06 19:25:56 -05:00
# If the user wants to reconfigure,
2017-05-22 06:47:26 +10:00
if [ [ " ${ reconfigure } " = = true ] ] ; then
2017-06-21 12:49:05 +01:00
echo " ${ INFO } Performing reconfiguration, skipping download of local repos "
2017-07-06 19:25:56 -05:00
# Reset the Core repo
2017-05-22 23:43:52 +02:00
resetRepo ${ PI_HOLE_LOCAL_REPO } || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Unable to reset ${ PI_HOLE_LOCAL_REPO } , exiting installer ${ COL_NC } " ; \
2017-05-22 23:43:52 +02:00
exit 1; \
}
2017-07-06 19:25:56 -05:00
# If the Web interface was installed,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# reset it's repo
2017-05-22 23:43:52 +02:00
resetRepo ${ webInterfaceDir } || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Unable to reset ${ webInterfaceDir } , exiting installer ${ COL_NC } " ; \
2017-01-28 15:15:42 +00:00
exit 1; \
}
2017-05-22 23:43:52 +02:00
fi
2017-07-06 19:25:56 -05:00
# Otherwise, a repair is happening
2017-05-22 06:47:26 +10:00
else
2017-07-06 19:25:56 -05:00
# so get git files for Core
2017-05-22 06:47:26 +10:00
getGitFiles ${ PI_HOLE_LOCAL_REPO } ${ piholeGitUrl } || \
2017-07-27 03:00:08 +10:00
{ echo -e " ${ COL_LIGHT_RED } Unable to clone ${ piholeGitUrl } into ${ PI_HOLE_LOCAL_REPO } , unable to continue ${ COL_NC } " ; \
2017-05-22 06:47:26 +10:00
exit 1; \
}
2017-07-06 19:25:56 -05:00
# If the Web interface was installed,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# get the Web git files
2017-01-28 15:15:42 +00:00
getGitFiles ${ webInterfaceDir } ${ webInterfaceGitUrl } || \
2017-06-21 12:49:05 +01:00
{ echo -e " ${ COL_LIGHT_RED } Unable to clone ${ webInterfaceGitUrl } into ${ webInterfaceDir } , exiting installer ${ COL_NC } " ; \
2017-01-28 15:15:42 +00:00
exit 1; \
}
fi
2017-05-22 06:47:26 +10:00
fi
2017-01-28 15:15:42 +00:00
}
2018-02-22 20:13:38 -08:00
# Download FTL binary to random temp directory and install FTL binary
2017-02-20 08:24:19 -08:00
FTLinstall( ) {
2017-07-06 19:25:56 -05:00
# Local, named variables
2017-02-20 08:24:19 -08:00
local binary = " ${ 1 } "
2017-02-20 10:25:17 -08:00
local latesttag
2017-07-12 22:02:07 +01:00
local str = "Downloading and Installing FTL"
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } ${ str } ... "
2017-02-20 08:24:19 -08:00
2017-07-06 19:25:56 -05:00
# Find the latest version tag for FTL
2017-02-20 10:25:17 -08:00
latesttag = $( curl -sI https://github.com/pi-hole/FTL/releases/latest | grep "Location" | awk -F '/' '{print $NF}' )
2017-02-20 11:49:20 -08:00
# Tags should always start with v, check for that.
if [ [ ! " ${ latesttag } " = = v* ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } "
echo -e " ${ COL_LIGHT_RED } Error: Unable to get latest release location from GitHub ${ COL_NC } "
2017-02-20 08:24:19 -08:00
return 1
fi
2017-07-12 22:02:07 +01:00
2018-02-22 20:13:38 -08:00
# Move into the temp ftl directory
2018-03-07 22:19:11 +00:00
pushd " $( mktemp -d) " > /dev/null || { echo "Unable to make temporary directory for FTL binary download" ; return 1; }
2018-02-22 20:13:38 -08:00
2018-02-18 13:07:22 +01:00
# Always replace pihole-FTL.service
install -T -m 0755 " ${ PI_HOLE_LOCAL_REPO } /advanced/pihole-FTL.service " "/etc/init.d/pihole-FTL"
2018-03-06 18:44:57 +00:00
local ftlBranch
local url
local ftlBranch
2018-03-18 00:38:34 +00:00
2018-03-06 18:44:57 +00:00
if [ [ -f "/etc/pihole/ftlbranch" ] ] ; then
ftlBranch = $( </etc/pihole/ftlbranch)
else
ftlBranch = "master"
fi
2018-03-18 00:38:34 +00:00
2018-03-06 18:44:57 +00:00
# Determine which version of FTL to download
if [ [ " ${ ftlBranch } " = = "master" ] ] ; then
url = " https://github.com/pi-hole/FTL/releases/download/ ${ latesttag % $'\r' } "
else
url = " https://ftl.pi-hole.net/ ${ ftlBranch } "
fi
2017-07-06 19:25:56 -05:00
# If the download worked,
2018-03-06 18:44:57 +00:00
if curl -sSL --fail " ${ url } / ${ binary } " -o " ${ binary } " ; then
2017-07-06 19:25:56 -05:00
# get sha1 of the binary we just downloaded for verification.
2018-03-18 00:38:34 +00:00
curl -sSL --fail " ${ url } / ${ binary } .sha1 " -o " ${ binary } .sha1 "
2018-03-07 23:31:28 +00:00
2017-07-06 19:25:56 -05:00
# If we downloaded binary file (as opposed to text),
2017-02-20 15:27:24 -08:00
if sha1sum --status --quiet -c " ${ binary } " .sha1; then
2017-02-20 14:44:34 -08:00
echo -n "transferred... "
2017-07-06 19:25:56 -05:00
# Stop FTL
2017-02-21 16:42:52 +01:00
stop_service pihole-FTL & > /dev/null
2017-07-06 19:25:56 -05:00
# Install the new version with the correct permissions
2018-02-22 20:13:38 -08:00
install -T -m 0755 " ${ binary } " /usr/bin/pihole-FTL
2017-07-06 19:25:56 -05:00
# Move back into the original directory the user was in
2018-03-07 22:23:05 +00:00
popd > /dev/null || { echo "Unable to return to original directory after FTL binary download." ; return 1; }
2017-07-06 19:25:56 -05:00
# Install the FTL service
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } ${ str } "
2018-03-07 23:31:28 +00:00
# If the --resolver flag returns True (exit code 0), then we can safely stop & disable dnsmasq
if pihole-FTL --resolver > /dev/null; then
2018-03-18 00:13:10 +00:00
if which dnsmasq > /dev/null; then
2018-03-07 23:31:28 +00:00
if check_service_active "dnsmasq" ; then
echo " ${ INFO } FTL can now resolve DNS Queries without dnsmasq running separately "
stop_service dnsmasq
2018-03-14 20:01:06 +00:00
disable_service dnsmasq
2018-03-18 00:13:10 +00:00
fi
2018-03-07 23:31:28 +00:00
fi
2018-03-18 00:38:34 +00:00
2018-03-07 23:31:28 +00:00
#ensure /etc/dnsmasq.conf contains `conf-dir=/etc/dnsmasq.d`
confdir = "conf-dir=/etc/dnsmasq.d"
conffile = "/etc/dnsmasq.conf"
if ! grep -q " $confdir " " $conffile " ; then
echo " $confdir " >> " $conffile "
fi
fi
2017-02-20 09:36:24 -08:00
return 0
2017-07-06 19:25:56 -05:00
# Otherise,
2017-02-20 09:36:24 -08:00
else
2018-02-22 20:13:38 -08:00
# the download failed, so just go back to the original directory
2018-03-07 22:19:11 +00:00
popd > /dev/null || { echo "Unable to return to original directory after FTL binary download." ; return 1; }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } "
echo -e " ${ COL_LIGHT_RED } Error: Download of binary from Github failed ${ COL_NC } "
2017-02-20 09:36:24 -08:00
return 1
2018-03-18 00:38:34 +00:00
fi
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-02-20 11:45:58 -08:00
else
2018-03-07 22:19:11 +00:00
popd > /dev/null || { echo "Unable to return to original directory after FTL binary download." ; return 1; }
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } "
2017-07-06 19:25:56 -05:00
# The URL could not be found
2017-06-21 12:49:05 +01:00
echo -e " ${ COL_LIGHT_RED } Error: URL not found ${ COL_NC } "
2018-02-22 20:13:38 -08:00
return 1
2017-02-20 08:24:19 -08:00
fi
}
2018-04-02 21:53:32 +01:00
get_binary_name( ) {
# Local, named variables
2017-02-20 08:24:19 -08:00
local machine
2017-07-06 19:25:56 -05:00
# Store architecture in a variable
2017-02-21 09:14:49 -08:00
machine = $( uname -m)
2017-02-13 10:29:27 +01:00
2017-06-21 12:49:05 +01:00
local str = "Detecting architecture"
echo -ne " ${ INFO } ${ str } ... "
2017-07-06 19:25:56 -05:00
# If the machine is arm or aarch
2017-07-27 03:00:08 +10:00
if [ [ " ${ machine } " = = "arm" * || " ${ machine } " = = *"aarch" * ] ] ; then
2017-02-13 10:29:27 +01:00
# ARM
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
local rev
rev = $( uname -m | sed "s/[^0-9]//g;" )
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
local lib
lib = $( ldd /bin/ls | grep -E '^\s*/lib' | awk '{ print $1 }' )
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
if [ [ " ${ lib } " = = "/lib/ld-linux-aarch64.so.1" ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected ARM-aarch64 architecture "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-02-13 10:29:27 +01:00
binary = "pihole-FTL-aarch64-linux-gnu"
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
elif [ [ " ${ lib } " = = "/lib/ld-linux-armhf.so.3" ] ] ; then
2017-07-06 19:25:56 -05:00
#
2017-07-27 03:00:08 +10:00
if [ [ " ${ rev } " -gt 6 ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected ARM-hf architecture (armv7+) "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-02-20 11:14:23 +01:00
binary = "pihole-FTL-arm-linux-gnueabihf"
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-02-20 11:14:23 +01:00
else
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected ARM-hf architecture (armv6 or lower) Using ARM binary "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-02-20 11:14:23 +01:00
binary = "pihole-FTL-arm-linux-gnueabi"
fi
2017-02-13 10:29:27 +01:00
else
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected ARM architecture "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-02-13 10:29:27 +01:00
binary = "pihole-FTL-arm-linux-gnueabi"
fi
2017-07-27 03:00:08 +10:00
elif [ [ " ${ machine } " = = "ppc" ] ] ; then
2017-06-20 08:28:04 +12:00
# PowerPC
2017-07-27 03:00:08 +10:00
echo -e " ${ OVER } ${ TICK } Detected PowerPC architecture "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-06-20 08:28:04 +12:00
binary = "pihole-FTL-powerpc-linux-gnu"
2017-07-27 03:00:08 +10:00
elif [ [ " ${ machine } " = = "x86_64" ] ] ; then
2017-02-13 10:29:27 +01:00
# 64bit
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected x86_64 architecture "
2017-07-06 19:25:56 -05:00
# set the binary to be used
2017-02-13 10:29:27 +01:00
binary = "pihole-FTL-linux-x86_64"
else
# Something else - we try to use 32bit executable and warn the user
2017-07-27 03:00:08 +10:00
if [ [ ! " ${ machine } " = = "i686" ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } ${ str } ...
2017-07-27 03:00:08 +10:00
${ COL_LIGHT_RED } Not able to detect architecture ( unknown: ${ machine } ) , trying 32bit executable${ COL_NC }
Contact Pi-hole Support if you experience issues ( e.g: FTL not running) "
2017-02-13 16:50:48 +01:00
else
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Detected 32bit (i686) architecture "
2017-02-13 14:42:11 +01:00
fi
2017-02-13 10:29:27 +01:00
binary = "pihole-FTL-linux-x86_32"
fi
2018-04-02 21:53:32 +01:00
}
2017-02-13 10:29:27 +01:00
2018-04-02 21:53:32 +01:00
FTLcheckUpdate( )
{
2018-04-02 23:22:06 +01:00
get_binary_name
#In the next section we check to see if FTL is already installed (in case of pihole -r).
#If the installed version matches the latest version, then check the installed sha1sum of the binary vs the remote sha1sum. If they do not match, then download
echo -e " ${ INFO } Checking for existing FTL binary... "
local ftlLoc
ftlLoc = $( which pihole-FTL 2>/dev/null)
2018-03-18 00:38:34 +00:00
2018-03-06 18:44:57 +00:00
local ftlBranch
2018-03-18 00:38:34 +00:00
2018-03-06 18:44:57 +00:00
if [ [ -f "/etc/pihole/ftlbranch" ] ] ; then
ftlBranch = $( </etc/pihole/ftlbranch)
else
ftlBranch = "master"
fi
2018-04-02 21:53:32 +01:00
local remoteSha1
local localSha1
2018-03-06 18:44:57 +00:00
if [ [ ! " ${ ftlBranch } " = = "master" ] ] ; then
2018-04-02 21:53:32 +01:00
if [ [ ${ ftlLoc } ] ] ; then
# We already have a pihole-FTL binary downloaded.
# Alt branches don't have a tagged version against them, so just confirm the checksum of the local vs remote to decide whether we download or not
remoteSha1 = $( curl -sSL --fail " https://ftl.pi-hole.net/ ${ ftlBranch } / ${ binary } .sha1 " | cut -d ' ' -f 1)
localSha1 = $( sha1sum " $( which pihole-FTL) " | cut -d ' ' -f 1)
if [ [ " ${ remoteSha1 } " != " ${ localSha1 } " ] ] ; then
echo -e " ${ INFO } Checksums do not match, downloading from ftl.pi-hole.net. "
return 0
else
echo -e " ${ INFO } Checksum of installed binary matches remote. No need to download! "
return 1
fi
else
return 0
fi
2018-03-06 18:44:57 +00:00
else
if [ [ ${ ftlLoc } ] ] ; then
2018-03-06 18:49:38 +00:00
local FTLversion
FTLversion = $( /usr/bin/pihole-FTL tag)
local FTLlatesttag
FTLlatesttag = $( curl -sI https://github.com/pi-hole/FTL/releases/latest | grep 'Location' | awk -F '/' '{print $NF}' | tr -d '\r\n' )
2018-03-06 18:44:57 +00:00
if [ [ " ${ FTLversion } " != " ${ FTLlatesttag } " ] ] ; then
2018-04-02 21:53:32 +01:00
return 0
2018-03-06 18:44:57 +00:00
else
echo -e " ${ INFO } Latest FTL Binary already installed ( ${ FTLlatesttag } ). Confirming Checksum... "
2017-07-24 23:22:04 +01:00
2018-03-06 18:49:38 +00:00
remoteSha1 = $( curl -sSL --fail " https://github.com/pi-hole/FTL/releases/download/ ${ FTLversion % $'\r' } / ${ binary } .sha1 " | cut -d ' ' -f 1)
localSha1 = $( sha1sum " $( which pihole-FTL) " | cut -d ' ' -f 1)
2017-07-12 22:02:07 +01:00
2018-03-06 18:44:57 +00:00
if [ [ " ${ remoteSha1 } " != " ${ localSha1 } " ] ] ; then
echo -e " ${ INFO } Corruption detected... "
2018-04-02 21:53:32 +01:00
return 0
2018-03-06 18:44:57 +00:00
else
echo -e " ${ INFO } Checksum correct. No need to download! "
2018-04-02 21:53:32 +01:00
return 1
2018-03-06 18:44:57 +00:00
fi
fi
else
2018-04-02 21:53:32 +01:00
return 0
2018-03-06 18:44:57 +00:00
fi
2017-07-25 22:49:06 +01:00
fi
2018-04-02 21:53:32 +01:00
}
# Detect suitable FTL binary platform
FTLdetect( ) {
echo ""
echo -e " ${ INFO } FTL Checks... "
if FTLcheckUpdate ; then
FTLinstall " ${ binary } " || return 1
fi
2018-03-07 23:31:28 +00:00
echo ""
2018-01-20 05:55:48 -08:00
}
2017-07-25 22:49:06 +01:00
2018-01-20 05:55:48 -08:00
make_temporary_log( ) {
# Create a random temporary file for the log
TEMPLOG = $( mktemp /tmp/pihole_temp.XXXXXX)
# Open handle 3 for templog
# https://stackoverflow.com/questions/18460186/writing-outputs-to-log-file-and-console
exec 3>" $TEMPLOG "
# Delete templog, but allow for addressing via file handle
# This lets us write to the log without having a temporary file on the drive, which
2018-01-20 06:20:06 -08:00
# is meant to be a security measure so there is not a lingering file on the drive during the install process
2018-01-20 05:55:48 -08:00
rm " $TEMPLOG "
}
2017-02-13 14:47:06 +01:00
2018-01-20 05:55:48 -08:00
copy_to_install_log( ) {
# Copy the contents of file descriptor 3 into the install log
# Since we use color codes such as '\e[1;33m', they should be removed
2018-01-20 06:20:06 -08:00
sed 's/ \[[0-9;]\{1,5\}m//g' < /proc/$$ /fd/3 > " ${ installLogLoc } "
2017-02-13 11:07:29 +01:00
}
2017-02-13 10:29:27 +01:00
2016-10-08 12:17:04 -07:00
main( ) {
2017-01-01 06:45:03 -08:00
######## FIRST CHECK ########
2017-07-06 19:25:56 -05:00
# Must be root to install
2017-06-21 12:49:05 +01:00
local str = "Root user check"
echo ""
2017-07-06 19:25:56 -05:00
# If the user's id is zero,
2017-07-27 03:00:08 +10:00
if [ [ " ${ EUID } " -eq 0 ] ] ; then
2017-07-06 19:25:56 -05:00
# they are root and all is good
2017-06-21 12:49:05 +01:00
echo -e " ${ TICK } ${ str } "
2018-01-20 05:13:55 -08:00
# Show the Pi-hole logo so people know it's genuine since the logo and name are trademarked
show_ascii_berry
2018-01-20 06:20:06 -08:00
make_temporary_log
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-01 06:45:03 -08:00
else
2017-07-06 19:25:56 -05:00
# They do not have enough privileges, so let the user know
2017-06-21 12:49:05 +01:00
echo -e " ${ CROSS } ${ str }
2017-07-27 03:00:08 +10:00
${ COL_LIGHT_RED } Script called with non-root privileges${ COL_NC }
2018-01-27 14:36:11 +02:00
The Pi-hole requires elevated privileges to install and run
2017-07-27 03:00:08 +10:00
Please check the installer for any concerns regarding this requirement
Make sure to download this script from a trusted source\\ n"
2017-06-21 12:49:05 +01:00
echo -ne " ${ INFO } Sudo utility check "
2017-01-01 06:45:03 -08:00
2017-07-06 19:25:56 -05:00
# If the sudo command exists,
2017-01-01 06:45:03 -08:00
if command -v sudo & > /dev/null; then
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ TICK } Sudo utility check "
2017-07-06 19:25:56 -05:00
# Download the install script and run it with admin rights
2017-01-23 14:28:56 -08:00
exec curl -sSL https://raw.githubusercontent.com/pi-hole/pi-hole/master/automated%20install/basic-install.sh | sudo bash " $@ "
2017-01-01 06:45:03 -08:00
exit $?
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-01 06:45:03 -08:00
else
2017-07-06 19:25:56 -05:00
# Let them know they need to run it as root
2017-06-21 12:49:05 +01:00
echo -e " ${ OVER } ${ CROSS } Sudo utility check
2017-07-27 03:00:08 +10:00
Sudo is needed for the Web Interface to run pihole commands\\ n
2017-06-21 12:49:05 +01:00
${ COL_LIGHT_RED } Please re-run this installer as root${ COL_NC } "
2017-01-01 06:45:03 -08:00
exit 1
fi
fi
2017-01-21 12:34:47 -08:00
# Check for supported distribution
distro_check
2016-12-23 10:27:52 -06:00
# Check arguments for the undocumented flags
2016-12-20 17:22:57 -08:00
for var in " $@ " ; do
case " $var " in
2017-06-21 12:49:05 +01:00
"--reconfigure" ) reconfigure = true; ;
2018-02-12 21:28:43 +01:00
"--i_do_not_follow_recommendations" ) skipSpaceCheck = true; ;
2017-06-21 12:49:05 +01:00
"--unattended" ) runUnattended = true; ;
2016-12-20 17:22:57 -08:00
esac
done
2017-07-06 19:25:56 -05:00
# If the setup variable file exists,
2017-07-27 03:00:08 +10:00
if [ [ -f " ${ setupVars } " ] ] ; then
2017-07-06 19:25:56 -05:00
# if it's running unattended,
2016-12-20 17:22:57 -08:00
if [ [ " ${ runUnattended } " = = true ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Performing unattended setup, no whiptail dialogs will be displayed "
2017-07-06 19:25:56 -05:00
# Use the setup variables
2016-12-20 17:22:57 -08:00
useUpdateVars = true
2017-07-06 19:25:56 -05:00
# Otherwise,
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
# show the available options (repair/reconfigure)
2016-12-20 17:22:57 -08:00
update_dialogs
fi
fi
# Start the installer
# Verify there is enough disk space for the install
if [ [ " ${ skipSpaceCheck } " = = true ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Skipping free disk space verification "
2016-12-20 17:22:57 -08:00
else
verifyFreeDiskSpace
fi
# Update package cache
2017-03-02 15:54:58 -08:00
update_package_cache || exit 1
2016-12-20 17:22:57 -08:00
# Notify user of package availability
notify_package_updates_available
# Install packages used by this installation script
install_dependent_packages INSTALLER_DEPS[ @]
2016-12-23 16:55:56 +00:00
# Check if SELinux is Enforcing
checkSelinux
2017-07-27 03:00:08 +10:00
if [ [ " ${ useUpdateVars } " = = false ] ] ; then
2016-12-20 17:22:57 -08:00
# Display welcome dialogs
welcomeDialogs
# Create directory for Pi-hole storage
mkdir -p /etc/pihole/
2018-03-18 00:38:34 +00:00
2018-03-06 18:44:57 +00:00
#Do we need to stop pihole-FTL or dnsmasq(if coming from an old install)?
if [ [ $( which pihole-FTL 2>/dev/null) ] ] ; then
2018-03-18 00:38:34 +00:00
if pihole-FTL --resolver > /dev/null; then
2018-03-06 18:44:57 +00:00
stop_service pihole-FTL
else
stop_service dnsmasq
fi
else
if [ [ $( which dnsmasq 2>/dev/null) ] ] ; then
stop_service dnsmasq
fi
fi
2017-06-29 02:18:52 +01:00
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-01-28 21:37:21 +00:00
stop_service lighttpd
fi
2016-12-20 17:22:57 -08:00
# Determine available interfaces
get_available_interfaces
# Find interfaces and let the user choose one
chooseInterface
# Decide what upstream DNS Servers to use
setDNS
2018-04-17 09:50:25 +01:00
# If adlists.list file does not exist, give the user the choice of adding some example lists
if [ [ ! -f " ${ adlistFile } " ] ] ; then
chooseBlocklists
fi
2016-12-22 22:34:38 -06:00
# Let the user decide if they want to block ads over IPv4 and/or IPv6
use4andor6
2017-01-28 14:38:54 +00:00
# Let the user decide if they want the web interface to be installed automatically
setAdminFlag
2016-12-20 17:22:57 -08:00
# Let the user decide if they want query logging enabled...
setLogging
2017-01-28 15:15:42 +00:00
# Clone/Update the repos
clone_or_update_repos
2016-12-20 17:22:57 -08:00
2017-07-06 19:25:56 -05:00
# Install packages used by the Pi-hole
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# Install the Web dependencies
2017-01-28 18:41:37 +00:00
DEPS = ( " ${ PIHOLE_DEPS [@] } " " ${ PIHOLE_WEB_DEPS [@] } " )
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-28 18:39:15 +00:00
else
2017-07-06 19:25:56 -05:00
# just install the Core dependencies
2017-01-28 18:41:37 +00:00
DEPS = ( " ${ PIHOLE_DEPS [@] } " )
2017-01-28 15:11:39 +00:00
fi
2017-12-06 14:32:39 +00:00
2017-01-28 18:39:15 +00:00
install_dependent_packages DEPS[ @]
2017-12-06 14:32:39 +00:00
# On some systems, lighttpd is not enabled on first install. We need to enable it here if the user
# has chosen to install the web interface, else the `LIGHTTPD_ENABLED` check will fail
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
enable_service lighttpd
fi
2017-07-26 14:34:40 +01:00
if [ [ -x " $( command -v systemctl) " ] ] ; then
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED = $( systemctl is-enabled lighttpd | grep -c 'enabled' || true )
else
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED = $( service lighttpd status | awk '/Loaded:/ {print $0}' | grep -c 'enabled' || true )
fi
2016-12-20 17:22:57 -08:00
# Install and log everything to a file
2018-01-20 06:20:06 -08:00
installPihole | tee -a /proc/$$ /fd/3
2016-12-20 17:22:57 -08:00
else
2017-12-24 13:09:45 +00:00
# Source ${setupVars} to use predefined user variables in the functions
source ${ setupVars }
2017-01-28 15:15:42 +00:00
# Clone/Update the repos
clone_or_update_repos
2017-01-28 18:39:15 +00:00
2017-01-28 19:05:55 +00:00
# Install packages used by the Pi-hole
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# Install the Web dependencies
2017-01-28 18:41:37 +00:00
DEPS = ( " ${ PIHOLE_DEPS [@] } " " ${ PIHOLE_WEB_DEPS [@] } " )
2017-07-06 19:25:56 -05:00
# Otherwise,
2017-01-28 18:39:15 +00:00
else
2017-07-06 19:25:56 -05:00
# just install the Core dependencies
2017-01-28 18:41:37 +00:00
DEPS = ( " ${ PIHOLE_DEPS [@] } " )
2017-01-28 15:11:39 +00:00
fi
2017-01-28 18:39:15 +00:00
install_dependent_packages DEPS[ @]
2016-12-20 17:22:57 -08:00
2017-07-26 14:34:40 +01:00
if [ [ -x " $( command -v systemctl) " ] ] ; then
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED = $( systemctl is-enabled lighttpd | grep -c 'enabled' || true )
else
# Value will either be 1, if true, or 0
LIGHTTPD_ENABLED = $( service lighttpd status | awk '/Loaded:/ {print $0}' | grep -c 'enabled' || true )
fi
2018-01-20 06:20:06 -08:00
updatePihole | tee -a /proc/$$ /fd/3
2016-12-20 17:22:57 -08:00
fi
2018-01-20 06:20:06 -08:00
# Copy the temp log file into final log location for storage
2018-01-20 05:55:48 -08:00
copy_to_install_log
2016-12-20 17:22:57 -08:00
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-01-28 15:25:02 +00:00
# Add password to web UI if there is none
pw = ""
2017-07-06 19:25:56 -05:00
# If no password is set,
2017-01-28 15:25:02 +00:00
if [ [ $( grep 'WEBPASSWORD' -c /etc/pihole/setupVars.conf) = = 0 ] ] ; then
2017-07-06 19:25:56 -05:00
# generate a random password
2017-01-28 15:25:02 +00:00
pw = $( tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
2017-07-27 03:00:08 +10:00
# shellcheck disable=SC1091
2017-05-02 22:25:47 +01:00
. /opt/pihole/webpage.sh
2017-05-02 22:37:38 +01:00
echo " WEBPASSWORD= $( HashPassword ${ pw } ) " >> ${ setupVars }
2017-01-28 15:25:02 +00:00
fi
2016-12-20 17:22:57 -08:00
fi
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Restarting services... "
2016-12-20 17:22:57 -08:00
# Start services
2018-03-06 18:44:57 +00:00
# Only start and enable dnsmasq if FTL does not have the --resolver switch
2018-03-18 00:38:34 +00:00
if ! pihole-FTL --resolver > /dev/null; then
2018-03-06 18:44:57 +00:00
start_service dnsmasq
enable_service dnsmasq
fi
2017-01-28 15:25:02 +00:00
2017-07-06 19:25:56 -05:00
# If the Web server was installed,
2017-07-17 01:44:14 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
if [ [ " ${ LIGHTTPD_ENABLED } " = = "1" ] ] ; then
start_service lighttpd
enable_service lighttpd
else
echo -e " ${ INFO } Lighttpd is disabled, skipping service restart "
fi
2017-01-28 15:25:02 +00:00
fi
2017-07-06 19:25:56 -05:00
# Enable FTL
2017-02-21 11:18:47 +01:00
start_service pihole-FTL
enable_service pihole-FTL
2017-09-20 17:29:11 +10:00
# Download and compile the aggregated block list
runGravity
2017-10-28 15:40:48 +02:00
# Force an update of the updatechecker
. /opt/pihole/updatecheck.sh
2017-12-28 18:41:22 +01:00
. /opt/pihole/updatecheck.sh x remote
2017-10-28 15:40:48 +02:00
2017-07-06 19:25:56 -05:00
#
2017-01-28 15:25:02 +00:00
if [ [ " ${ useUpdateVars } " = = false ] ] ; then
displayFinalMessage " ${ pw } "
fi
2017-06-29 02:18:52 +01:00
2017-07-06 19:25:56 -05:00
# If the Web interface was installed,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-07-06 19:25:56 -05:00
# If there is a password,
2017-06-21 12:49:05 +01:00
if ( ( ${# pw } > 0 ) ) ; then
2017-07-06 19:25:56 -05:00
# display the password
2017-06-21 12:49:05 +01:00
echo -e " ${ INFO } Web Interface password: ${ COL_LIGHT_GREEN } ${ pw } ${ COL_NC }
2017-07-27 03:00:08 +10:00
This can be changed using 'pihole -a -p' \\ n"
2017-06-21 12:49:05 +01:00
fi
fi
2017-01-28 15:25:02 +00:00
2017-07-06 19:25:56 -05:00
#
2016-12-20 17:22:57 -08:00
if [ [ " ${ useUpdateVars } " = = false ] ] ; then
2017-07-06 19:25:56 -05:00
# If the Web interface was installed,
2017-07-27 03:00:08 +10:00
if [ [ " ${ INSTALL_WEB } " = = true ] ] ; then
2017-06-21 12:49:05 +01:00
echo -e " View the web interface at http://pi.hole/admin or http:// ${ IPV4_ADDRESS %/* } /admin "
echo ""
2017-01-28 15:25:02 +00:00
fi
2017-07-06 19:25:56 -05:00
# Explain to the user how to use Pi-hole as their DNS server
2017-06-21 12:49:05 +01:00
echo " You may now configure your devices to use the Pi-hole as their DNS server"
[ [ -n " ${ IPV4_ADDRESS %/* } " ] ] && echo -e " ${ INFO } Pi-hole DNS (IPv4): ${ IPV4_ADDRESS %/* } "
[ [ -n " ${ IPV6_ADDRESS } " ] ] && echo -e " ${ INFO } Pi-hole DNS (IPv6): ${ IPV6_ADDRESS } "
echo -e " If you set a new IP address, please restart the server running the Pi-hole"
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
INSTALL_TYPE = "Installation"
2016-12-20 17:22:57 -08:00
else
2017-07-06 19:25:56 -05:00
#
2017-06-21 12:49:05 +01:00
INSTALL_TYPE = "Update"
2016-12-20 17:22:57 -08:00
fi
2017-06-29 02:18:52 +01:00
2017-07-06 19:25:56 -05:00
# Display where the log file is
2018-01-20 08:45:41 -08:00
echo -e " \\n ${ INFO } The install log is located at: ${ installLogLoc }
2017-06-21 12:49:05 +01:00
${ COL_LIGHT_GREEN } ${ INSTALL_TYPE } Complete! ${ COL_NC } "
2017-07-26 14:34:40 +01:00
2018-04-02 21:53:32 +01:00
if [ [ " ${ INSTALL_TYPE } " = = "Update" ] ] ; then
echo ""
/usr/local/bin/pihole version --current
fi
2016-10-08 12:17:04 -07:00
}
2017-07-06 19:25:56 -05:00
#
2016-11-03 22:34:04 -05:00
if [ [ " ${ PH_TEST } " != true ] ] ; then
2016-12-20 17:22:57 -08:00
main " $@ "
2016-10-10 23:14:39 -05:00
fi