diff --git a/pi-hole/basic-install.sh b/pi-hole/basic-install.sh deleted file mode 100755 index 29fe90c..0000000 --- a/pi-hole/basic-install.sh +++ /dev/null @@ -1,2517 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC1090 - -# Pi-hole: A black hole for Internet advertisements -# (c) 2017-2018 Pi-hole, LLC (https://pi-hole.net) -# Network-wide ad blocking via your own hardware. -# -# Installs and Updates Pi-hole -# -# This file is copyright under the latest version of the EUPL. -# Please see LICENSE file for your rights under this license. - -# pi-hole.net/donate -# -# Install with this command (from your Linux machine): -# -# curl -sSL https://install.pi-hole.net | bash - -# -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 -set -e - -######## VARIABLES ######### -# For better maintainability, we store as much information that can change in variables -# This allows us to make a change in one place that can propagate to all instances of the variable -# 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 - -# Location for final installation log storage -installLogLoc=/etc/pihole/install.log -# This is an important file as it contains information specific to the machine it's being installed on -setupVars=/etc/pihole/setupVars.conf -# Pi-hole uses lighttpd as a Web server, and this is the config file for it -# shellcheck disable=SC2034 -lighttpdConfig=/etc/lighttpd/lighttpd.conf -# This is a file used for the colorized output -coltable=/opt/pihole/COL_TABLE - -# We store several other folders and -webInterfaceGitUrl="https://github.com/pi-hole/AdminLTE.git" -webInterfaceDir="/var/www/html/admin" -piholeGitUrl="https://github.com/pi-hole/pi-hole.git" -PI_HOLE_LOCAL_REPO="/etc/.pihole" -# These are the names of pi-holes files, stored in an array -PI_HOLE_FILES=(chronometer list piholeDebug piholeLogFlush setupLCD update version gravity uninstall webpage) -# This folder is where the Pi-hole scripts will be installed -PI_HOLE_INSTALL_DIR="/opt/pihole" -PI_HOLE_CONFIG_DIR="/etc/pihole" -useUpdateVars=false - -adlistFile="/etc/pihole/adlists.list" -regexFile="/etc/pihole/regex.list" -# 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 -IPV4_ADDRESS="" -IPV6_ADDRESS="" -# By default, query logging is enabled and the dashboard is set to be installed -QUERY_LOGGING=true -INSTALL_WEB_INTERFACE=true - -if [ -z "${USER}" ]; then - USER="$(id -un)" -fi - - -# Find the rows and columns will default to 80x24 if it can not be detected -screen_size=$(stty size 2>/dev/null || echo 24 80) -rows=$(echo "${screen_size}" | awk '{print $1}') -columns=$(echo "${screen_size}" | awk '{print $2}') - -# Divide by two so the dialogs take up half of the screen, which looks nice. -r=$(( rows / 2 )) -c=$(( columns / 2 )) -# Unless the screen is tiny -r=$(( r < 20 ? 20 : r )) -c=$(( c < 70 ? 70 : c )) - -######## Undocumented Flags. Shhh ######## -# These are undocumented flags; some of which we can use when repairing an installation -# The runUnattended flag is one example of this -skipSpaceCheck=false -reconfigure=false -runUnattended=false -INSTALL_WEB_SERVER=true -# Check arguments for the undocumented flags -for var in "$@"; do - case "$var" in - "--reconfigure" ) reconfigure=true;; - "--i_do_not_follow_recommendations" ) skipSpaceCheck=true;; - "--unattended" ) runUnattended=true;; - "--disable-install-webserver" ) INSTALL_WEB_SERVER=false;; - esac -done - -# If the color table file exists, -if [[ -f "${coltable}" ]]; then - # source it - source ${coltable} -# Otherwise, -else - # Set these values so the installer can still run in color - 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]" - # shellcheck disable=SC2034 - DONE="${COL_LIGHT_GREEN}done! ${COL_NC}" - OVER="\\r\\033[K" -fi - -# A simple function that just echoes out our logo in ASCII format -# This lets users know that it is a Pi-hole, LLC product -show_ascii_berry() { - echo -e " - ${COL_LIGHT_GREEN}.;;,. - .ccccc:,. - :cccclll:. ..,, - :ccccclll. ;ooodc - 'ccll:;ll .oooodc - .;cll.;;looo:. - ${COL_LIGHT_RED}.. ','. - .',,,,,,'. - .',,,,,,,,,,. - .',,,,,,,,,,,,.... - ....''',,,,,,,'....... - ......... .... ......... - .......... .......... - .......... .......... - ......... .... ......... - ........,,,,,,,'...... - ....',,,,,,,,,,,,. - .',,,,,,,,,'. - .',,,,,,'. - ..'''.${COL_NC} -" -} - -# Compatibility -distro_check() { -# If apt-get is installed, then we know it's part of the Debian family -if command -v apt-get &> /dev/null; then - # Set some global variables here - # We don't set them earlier since the family might be Red Hat, so these values would be different - PKG_MANAGER="apt-get" - # A variable to store the command used to update the package cache - UPDATE_PKG_CACHE="${PKG_MANAGER} update" - # An array for something... - PKG_INSTALL=(${PKG_MANAGER} --yes --no-install-recommends install) - # 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" - # 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, - if ${PKG_MANAGER} install --dry-run iproute2 > /dev/null 2>&1; then - # we can install it - iproute_pkg="iproute2" - # Otherwise, - else - # use iproute - iproute_pkg="iproute" - fi - # Check for and determine version number (major and minor) of current php install - if command -v php &> /dev/null; then - phpInsVersion="$(php -v | head -n1 | grep -Po '(?<=PHP )[^ ]+')" - echo -e " ${INFO} Existing PHP installation detected : PHP version $phpInsVersion" - phpInsMajor="$(echo "$phpInsVersion" | cut -d\. -f1)" - phpInsMinor="$(echo "$phpInsVersion" | cut -d\. -f2)" - # Is installed php version 7.0 or greater - if [ "$(echo "$phpInsMajor.$phpInsMinor < 7.0" | bc )" == 0 ]; then - phpInsNewer=true - fi - fi - # Check if installed php is v 7.0, or newer to determine packages to install - if [[ "$phpInsNewer" != true ]]; then - # Prefer the php metapackage if it's there - if ${PKG_MANAGER} install --dry-run php > /dev/null 2>&1; then - phpVer="php" - # fall back on the php5 packages - else - phpVer="php5" - fi - else - # Newer php is installed, its common, cgi & sqlite counterparts are deps - phpVer="php$phpInsMajor.$phpInsMinor" - fi - # 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 - # Since our install script is so large, we need several other programs to successfully get a machine provisioned - # These programs are stored in an array so they can be looped through later - INSTALLER_DEPS=(apt-utils dialog debconf dhcpcd5 git ${iproute_pkg} whiptail) - # Pi-hole itself has several dependencies that also need to be installed - PIHOLE_DEPS=(bc cron curl dnsutils iputils-ping lsof netcat psmisc sudo unzip wget idn2 sqlite3 libcap2-bin dns-root-data resolvconf) - # 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 - PIHOLE_WEB_DEPS=(lighttpd ${phpVer}-common ${phpVer}-cgi ${phpVer}-${phpSqlite}) - # The Web server user, - LIGHTTPD_USER="www-data" - # group, - LIGHTTPD_GROUP="www-data" - # and config file - LIGHTTPD_CFG="lighttpd.conf.debian" - - # 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 - } - -# If apt-get is not found, check for rpm to see if it's a Red Hat family OS -elif command -v rpm &> /dev/null; then - # Then check if dnf or yum is the package manager - if command -v dnf &> /dev/null; then - PKG_MANAGER="dnf" - else - PKG_MANAGER="yum" - fi - - # Fedora and family update cache on every PKG_INSTALL call, no need for a separate update. - UPDATE_PKG_CACHE=":" - PKG_INSTALL=(${PKG_MANAGER} install -y) - PKG_COUNT="${PKG_MANAGER} check-update | egrep '(.i686|.x86|.noarch|.arm|.src)' | wc -l" - INSTALLER_DEPS=(dialog git iproute net-tools newt procps-ng which) - PIHOLE_DEPS=(bc bind-utils cronie curl findutils nmap-ncat sudo unzip wget libidn2 psmisc) - PIHOLE_WEB_DEPS=(lighttpd lighttpd-fastcgi php-common php-cli php-pdo) - LIGHTTPD_USER="lighttpd" - LIGHTTPD_GROUP="lighttpd" - LIGHTTPD_CFG="lighttpd.conf.fedora" - # If the host OS is Fedora, - if grep -qi 'fedora' /etc/redhat-release; then - # all required packages should be available by default with the latest fedora release - # ensure 'php-json' is installed on Fedora (installed as dependency on CentOS7 + Remi repository) - PIHOLE_WEB_DEPS+=('php-json') - # or if host OS is CentOS, - elif grep -qi 'centos' /etc/redhat-release; then - # Pi-Hole currently supports CentOS 7+ with PHP7+ - SUPPORTED_CENTOS_VERSION=7 - SUPPORTED_CENTOS_PHP_VERSION=7 - # Check current CentOS major release version - CURRENT_CENTOS_VERSION=$(rpm -q --queryformat '%{VERSION}' centos-release) - # Check if CentOS version is supported - if [[ $CURRENT_CENTOS_VERSION -lt $SUPPORTED_CENTOS_VERSION ]]; then - echo -e " ${CROSS} CentOS $CURRENT_CENTOS_VERSION is not suported." - echo -e " Please update to CentOS release $SUPPORTED_CENTOS_VERSION or later" - # exit the installer - exit - fi - # on CentOS we need to add the EPEL repository to gain access to Fedora packages - EPEL_PKG="epel-release" - rpm -q ${EPEL_PKG} &> /dev/null || rc=$? - if [[ $rc -ne 0 ]]; then - echo -e " ${INFO} Enabling EPEL package repository (https://fedoraproject.org/wiki/EPEL)" - "${PKG_INSTALL[@]}" ${EPEL_PKG} &> /dev/null - echo -e " ${TICK} Installed ${EPEL_PKG}" - fi - - # The default php on CentOS 7.x is 5.4 which is EOL - # Check if the version of PHP available via installed repositories is >= to PHP 7 - AVAILABLE_PHP_VERSION=$(${PKG_MANAGER} info php | grep -i version | grep -o '[0-9]\+' | head -1) - if [[ $AVAILABLE_PHP_VERSION -ge $SUPPORTED_CENTOS_PHP_VERSION ]]; then - # Since PHP 7 is available by default, install via default PHP package names - : # do nothing as PHP is current - else - REMI_PKG="remi-release" - REMI_REPO="remi-php72" - rpm -q ${REMI_PKG} &> /dev/null || rc=$? - if [[ $rc -ne 0 ]]; then - # The PHP version available via default repositories is older than version 7 - if ! whiptail --defaultno --title "PHP 7 Update (recommended)" --yesno "PHP 7.x is recommended for both security and language features.\\nWould you like to install PHP7 via Remi's RPM repository?\\n\\nSee: https://rpms.remirepo.net for more information" ${r} ${c}; then - # User decided to NOT update PHP from REMI, attempt to install the default available PHP version - echo -e " ${INFO} User opt-out of PHP 7 upgrade on CentOS. Deprecated PHP may be in use." - : # continue with unsupported php version - else - echo -e " ${INFO} Enabling Remi's RPM repository (https://rpms.remirepo.net)" - "${PKG_INSTALL[@]}" "https://rpms.remirepo.net/enterprise/${REMI_PKG}-$(rpm -E '%{rhel}').rpm" &> /dev/null - # enable the PHP 7 repository via yum-config-manager (provided by yum-utils) - "${PKG_INSTALL[@]}" "yum-utils" &> /dev/null - yum-config-manager --enable ${REMI_REPO} &> /dev/null - echo -e " ${TICK} Remi's RPM repository has been enabled for PHP7" - # trigger an install/update of PHP to ensure previous version of PHP is updated from REMI - if "${PKG_INSTALL[@]}" "php-cli" &> /dev/null; then - echo -e " ${TICK} PHP7 installed/updated via Remi's RPM repository" - else - echo -e " ${CROSS} There was a problem updating to PHP7 via Remi's RPM repository" - exit 1 - fi - fi - fi - fi - else - # If not a supported version of Fedora or CentOS, - echo -e " ${CROSS} Unsupported RPM based distribution" - # exit the installer - exit - fi - -# If neither apt-get or rmp/dnf are found -else - # it's not an OS we can support, - echo -e " ${CROSS} OS distribution not supported" - # so exit the installer - exit -fi -} - -# A function for checking if a folder is a git repository -is_repo() { - # Use a named, local variable instead of the vague $1, which is the first argument passed to this function - # These local variables should always be lowercase - local directory="${1}" - # A local variable for the current directory - local curdir - # A variable to store the return code - local rc - # Assign the current directory variable by using pwd - curdir="${PWD}" - # If the first argument passed to this function is a directory, - if [[ -d "${directory}" ]]; then - # move into the directory - cd "${directory}" - # 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 - git status --short &> /dev/null || rc=$? - # If the command was not successful, - else - # Set a non-zero return code if directory does not exist - rc=1 - fi - # Move back into the directory the user started in - cd "${curdir}" - # Return the code; if one is not set, return 0 - return "${rc:-0}" -} - -# A function to clone a repo -make_repo() { - # Set named variables for better readability - local directory="${1}" - local remoteRepo="${2}" - # The message to display when this function is running - str="Clone ${remoteRepo} into ${directory}" - # Display the message and use the color table to preface the message with an "info" indicator - echo -ne " ${INFO} ${str}..." - # If the directory exists, - if [[ -d "${directory}" ]]; then - # delete everything in it so git can clone into it - rm -rf "${directory}" - fi - # Clone the repo and return the return code from this command - git clone -q --depth 1 "${remoteRepo}" "${directory}" &> /dev/null || return $? - # Show a colored message showing it's status - echo -e "${OVER} ${TICK} ${str}" - # Always return 0? Not sure this is correct - return 0 -} - -# 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 -update_repo() { - # 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 - local directory="${1}" - local curdir - - # 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 - local str="Update repo in ${1}" - - # Make sure we know what directory we are in so we can move back into it - curdir="${PWD}" - # Move into the directory that was passed as an argument - cd "${directory}" &> /dev/null || return 1 - # Let the user know what's happening - echo -ne " ${INFO} ${str}..." - # Stash any local commits as they conflict with our working code - git stash --all --quiet &> /dev/null || true # Okay for stash failure - git clean --quiet --force -d || true # Okay for already clean directory - # Pull the latest commits - git pull --quiet &> /dev/null || return $? - # Show a completion message - echo -e "${OVER} ${TICK} ${str}" - # Move back into the original directory - cd "${curdir}" &> /dev/null || return 1 - return 0 -} - -# A function that combines the functions previously made -getGitFiles() { - # Setup named variables for the git repos - # We need the directory - local directory="${1}" - # as well as the repo URL - local remoteRepo="${2}" - # A local variable containing the message to be displayed - local str="Check for existing repository in ${1}" - # Show the message - echo -ne " ${INFO} ${str}..." - # Check if the directory is a repository - if is_repo "${directory}"; then - # Show that we're checking it - echo -e "${OVER} ${TICK} ${str}" - # Update the repo, returning an error message on failure - update_repo "${directory}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } - # If it's not a .git repo, - else - # Show an error - echo -e "${OVER} ${CROSS} ${str}" - # Attempt to make the repository, showing an error on failure - make_repo "${directory}" "${remoteRepo}" || { echo -e "\\n ${COL_LIGHT_RED}Error: Could not update local repository. Contact support.${COL_NC}"; exit 1; } - fi - # echo a blank line - echo "" - # and return success? - return 0 -} - -# Reset a repo to get rid of any local changed -resetRepo() { - # Use named variables for arguments - local directory="${1}" - # Move into the directory - cd "${directory}" &> /dev/null || return 1 - # Store the message in a variable - str="Resetting repository within ${1}..." - # Show the message - echo -ne " ${INFO} ${str}" - # Use git to remove the local changes - git reset --hard &> /dev/null || return $? - # And show the status - echo -e "${OVER} ${TICK} ${str}" - # Returning success anyway? - return 0 -} - -# 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 -find_IPv4_information() { - # Named, local variables - local route - # Find IP used to route to outside world by checking the the route to Google's public DNS server - route=$(ip route get 8.8.8.8) - # Use awk to strip out just the interface device as it is used in future commands - IPv4dev=$(awk '{for (i=1; i<=NF; i++) if ($i~/dev/) print $(i+1)}' <<< "${route}") - # Get just the IP address - IPv4bare=$(awk '{print $7}' <<< "${route}") - # Append the CIDR notation to the IP address - IPV4_ADDRESS=$(ip -o -f inet addr show | grep "${IPv4bare}" | awk '{print $4}' | awk 'END {print}') - # Get the default gateway (the way to reach the Internet) - IPv4gw=$(awk '{print $3}' <<< "${route}") -} - -# Get available interfaces that are UP -get_available_interfaces() { - # There may be more than one so it's all stored in a variable - availableInterfaces=$(ip --oneline link show up | grep -v "lo" | awk '{print $2}' | cut -d':' -f1 | cut -d'@' -f1) -} - -# A function for displaying the dialogs the user sees when first running the installer -welcomeDialogs() { - # Display the welcome dialog using an appropriately sized window via the calculation conducted earlier in the script - whiptail --msgbox --backtitle "Welcome" --title "Pi-hole automated installer" "\\n\\nThis installer will transform your device into a network-wide ad blocker!" ${r} ${c} - - # Request that users donate if they enjoy the software since we all work on it in our free time - whiptail --msgbox --backtitle "Plea" --title "Free and open source" "\\n\\nThe Pi-hole is free, but powered by your donations: http://pi-hole.net/donate" ${r} ${c} - - # Explain the need for a static address - 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. - -In the next section, you can choose to use your current network settings (DHCP) or to manually edit them." ${r} ${c} -} - -# We need to make sure there is enough space before installing, so there is a function to check this -verifyFreeDiskSpace() { - # 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. - local str="Disk space check" - # Required space in KB - local required_free_kilobytes=51200 - # Calculate existing free space on this machine - local existing_free_kilobytes - existing_free_kilobytes=$(df -Pk | grep -m1 '\/$' | awk '{print $4}') - - # If the existing space is not an integer, - if ! [[ "${existing_free_kilobytes}" =~ ^([0-9])+$ ]]; then - # show an error that we can't determine the free space - echo -e " ${CROSS} ${str}" - echo -e " ${INFO} Unknown free disk space!" - echo -e " ${INFO} We were unable to determine available free disk space on this system." - echo -e " ${INFO} You may override this check, however, it is not recommended" - echo -e " ${INFO} The option '${COL_LIGHT_RED}--i_do_not_follow_recommendations${COL_NC}' can override this" - echo -e " ${INFO} e.g: curl -L https://install.pi-hole.net | bash /dev/stdin ${COL_LIGHT_RED}