2017-03-04 06:13:11 +01:00
#!/bin/bash
2017-01-08 17:42:39 +01:00
2019-01-09 04:01:19 +01:00
docker_checks( ) {
2019-01-10 07:28:33 +01:00
warn_msg = 'WARNING Misconfigured DNS in /etc/resolv.conf'
ns_count = " $( grep -c nameserver /etc/resolv.conf) "
ns_primary = " $( grep nameserver /etc/resolv.conf | head -1) "
ns_primary = " ${ ns_primary /nameserver / } "
warned = false
if [ " $ns_count " -lt 2 ] ; then
echo " $warn_msg : Two DNS servers are recommended, 127.0.0.1 and any backup server "
warned = true
fi
if [ " $ns_primary " != "127.0.0.1" ] ; then
echo " $warn_msg : Primary DNS should be 127.0.0.1 (found ${ ns_primary } ) "
warned = true
fi
if ! $warned ; then
echo "OK: Checks passed for /etc/resolv.conf DNS servers"
fi
echo
cat /etc/resolv.conf
2019-01-09 04:01:19 +01:00
}
2019-02-06 11:02:30 +01:00
fix_capabilities( ) {
[ ! -f /.piholeFirstBoot ] && return
setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN+ei $( which pihole-FTL) || ret = $?
if [ [ $ret -ne 0 && " ${ DNSMASQ_USER :- root } " != "root" ] ] ; then
echo "ERROR: Failed to set capabilities for pihole-FTL. Cannot run as non-root."
exit 1
fi
}
2018-08-03 05:49:55 +02:00
prepare_configs( ) {
2018-08-06 01:20:55 +02:00
# Done in /start.sh, don't do twice
2018-08-03 05:49:55 +02:00
PH_TEST = true . $PIHOLE_INSTALL
distro_check
installConfigs
2017-01-22 03:12:37 +01:00
touch " $setupVars "
2018-08-03 05:49:55 +02:00
set +e
mkdir -p /var/run/pihole /var/log/pihole
# Re-apply perms from basic-install over any volume mounts that may be present (or not)
2019-01-09 04:01:19 +01:00
# Also similar to preflights for FTL https://github.com/pi-hole/pi-hole/blob/master/advanced/Templates/pihole-FTL.service
2018-08-03 05:49:55 +02:00
chown pihole:root /etc/lighttpd
chown pihole:pihole " ${ PI_HOLE_CONFIG_DIR } /pihole-FTL.conf " "/var/log/pihole" " ${ regexFile } "
2018-08-06 05:23:22 +02:00
chmod 644 " ${ PI_HOLE_CONFIG_DIR } /pihole-FTL.conf "
# not sure why pihole:pihole user/group write perms are not enough for web to write...dirty fix:
chmod 777 " ${ regexFile } "
2018-08-03 05:49:55 +02:00
touch /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log
chown pihole:pihole /var/run/pihole /var/log/pihole
test -f /var/run/pihole/FTL.sock && rm /var/run/pihole/FTL.sock
chown pihole:pihole /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /etc/pihole /etc/pihole/dhcp.leases /var/log/pihole.log
chmod 0644 /var/log/pihole-FTL.log /run/pihole-FTL.pid /run/pihole-FTL.port /var/log/pihole.log
set -e
2018-08-06 01:20:55 +02:00
# Update version numbers
pihole updatechecker
2018-08-03 05:49:55 +02:00
# Re-write all of the setupVars to ensure required ones are present (like QUERY_LOGGING)
# If the setup variable file exists,
if [ [ -e " ${ setupVars } " ] ] ; then
# update the variables in the file
2018-08-04 22:58:05 +02:00
local USERWEBPASSWORD = " ${ WEBPASSWORD } "
2018-08-03 05:49:55 +02:00
. " ${ setupVars } "
2018-08-04 23:19:11 +02:00
# Stash and pop the user password to avoid setting the password to the hashed setupVar variable
WEBPASSWORD = " ${ USERWEBPASSWORD } "
2018-08-06 14:46:29 +02:00
# Clean up old before re-writing the required setupVars
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_SERVER/d;/INSTALL_WEB_INTERFACE/d;/LIGHTTPD_ENABLED/d;' " ${ setupVars } "
2018-08-03 05:49:55 +02:00
fi
# echo the information to the user
2019-02-09 06:14:44 +01:00
# P
2018-08-03 05:49:55 +02:00
{
echo " PIHOLE_INTERFACE= ${ PIHOLE_INTERFACE } "
echo " IPV4_ADDRESS= ${ IPV4_ADDRESS } "
echo " IPV6_ADDRESS= ${ IPV6_ADDRESS } "
echo " QUERY_LOGGING= ${ QUERY_LOGGING } "
echo " INSTALL_WEB_SERVER= ${ INSTALL_WEB_SERVER } "
echo " INSTALL_WEB_INTERFACE= ${ INSTALL_WEB_INTERFACE } "
echo " LIGHTTPD_ENABLED= ${ LIGHTTPD_ENABLED } "
} >> " ${ setupVars } "
2017-01-21 22:02:08 +01:00
}
2016-10-07 02:46:20 +02:00
validate_env( ) {
2019-02-08 02:51:15 +01:00
# Optional ServerIP is a valid IP
2018-01-27 04:32:39 +01:00
# nc won't throw any text based errors when it times out connecting to a valid IP, otherwise it complains about the DNS name being garbage
# if nc doesn't behave as we expect on a valid IP the routing table should be able to look it up and return a 0 retcode
if [ [ " $( nc -4 -w1 -z " $ServerIP " 53 2>& 1) " != "" ] ] || ! ip route get " $ServerIP " > /dev/null ; then
2017-05-19 07:36:53 +02:00
echo " ERROR: ServerIP Environment variable ( $ServerIP ) doesn't appear to be a valid IPv4 address "
exit 1
fi
# Optional IPv6 is a valid address
if [ [ -n " $ServerIPv6 " ] ] ; then
if [ [ " $ServerIPv6 " = = 'kernel' ] ] ; then
2018-01-05 05:30:40 +01:00
echo "ERROR: You passed in IPv6 with a value of 'kernel', this maybe beacuse you do not have IPv6 enabled on your network"
2017-05-19 07:36:53 +02:00
unset ServerIPv6
2018-01-05 05:30:40 +01:00
exit 1
2017-05-19 07:36:53 +02:00
fi
2018-01-27 04:32:39 +01:00
if [ [ " $( nc -6 -w1 -z " $ServerIPv6 " 53 2>& 1) " != "" ] ] || ! ip route get " $ServerIPv6 " > /dev/null ; then
2017-05-19 07:36:53 +02:00
echo " ERROR: ServerIPv6 Environment variable ( $ServerIPv6 ) doesn't appear to be a valid IPv6 address "
echo " TIP: If your server is not IPv6 enabled just remove '-e ServerIPv6' from your docker container"
exit 1
fi
fi ;
2016-10-07 02:46:20 +02:00
}
2016-10-30 18:13:52 +01:00
setup_dnsmasq_dns( ) {
2017-01-18 05:49:42 +01:00
. /opt/pihole/webpage.sh
2016-10-07 02:46:20 +02:00
local DNS1 = " ${ 1 :- 8 .8.8.8 } "
local DNS2 = " ${ 2 :- 8 .8.4.4 } "
2016-10-08 20:34:23 +02:00
local dnsType = 'default'
2016-10-07 02:46:20 +02:00
if [ " $DNS1 " != '8.8.8.8' ] || [ " $DNS2 " != '8.8.4.4' ] ; then
2017-11-20 06:15:44 +01:00
dnsType = 'custom'
2016-10-07 02:46:20 +02:00
fi ;
2017-11-20 06:15:44 +01:00
if [ ! -f /.piholeFirstBoot ] ; then
local setupDNS1 = " $( grep 'PIHOLE_DNS_1' ${ setupVars } ) "
local setupDNS2 = " $( grep 'PIHOLE_DNS_2' ${ setupVars } ) "
2019-02-14 06:14:25 +01:00
setupDNS1 = " ${ setupDNS1 /PIHOLE_DNS_1=/ } "
setupDNS2 = " ${ setupDNS2 /PIHOLE_DNS_2=/ } "
2017-11-20 06:15:44 +01:00
if [ [ -n " $DNS1 " && -n " $setupDNS1 " ] ] || \
[ [ -n " $DNS2 " && -n " $setupDNS2 " ] ] ; then
echo "Docker DNS variables not used"
fi
2019-02-14 06:14:25 +01:00
echo " Existing DNS servers used ( ${ setupDNS1 :- unset } & ${ setupDNS2 :- unset } ) "
2017-11-20 06:15:44 +01:00
return
fi
2016-10-07 02:46:20 +02:00
echo " Using $dnsType DNS servers: $DNS1 & $DNS2 "
2017-12-08 06:30:54 +01:00
if [ [ -n " $DNS1 " && -z " $setupDNS1 " ] ] ; then
2017-11-20 06:15:44 +01:00
change_setting "PIHOLE_DNS_1" " ${ DNS1 } "
fi
2017-12-08 06:30:54 +01:00
if [ [ -n " $DNS2 " && -z " $setupDNS2 " ] ] ; then
2019-02-09 06:14:44 +01:00
if [ [ " $DNS2 " = = "no" ] ] ; then
2018-07-06 10:01:41 +02:00
delete_setting "PIHOLE_DNS_2"
2019-02-09 06:14:44 +01:00
unset PIHOLE_DNS_2
2018-07-06 10:01:41 +02:00
else
change_setting "PIHOLE_DNS_2" " ${ DNS2 } "
fi
2017-11-20 06:15:44 +01:00
fi
2017-03-05 00:31:09 +01:00
}
setup_dnsmasq_interface( ) {
2018-07-30 01:14:24 +02:00
local interface = " ${ 1 :- eth0 } "
2017-03-05 00:31:09 +01:00
local interfaceType = 'default'
2018-07-30 01:14:24 +02:00
if [ " $interface " != 'eth0' ] ; then
2017-03-05 00:31:09 +01:00
interfaceType = 'custom'
fi ;
2018-07-30 01:14:24 +02:00
echo " DNSMasq binding to $interfaceType interface: $interface "
[ -n " $interface " ] && change_setting "PIHOLE_INTERFACE" " ${ interface } "
2017-03-05 00:31:09 +01:00
}
2018-09-29 22:17:21 +02:00
setup_dnsmasq_listening_behaviour( ) {
local dnsmasq_listening_behaviour = " ${ 1 } "
if [ -n " $dnsmasq_listening_behaviour " ] ; then
change_setting "DNSMASQ_LISTENING" " ${ dnsmasq_listening_behaviour } "
fi ;
}
2017-05-23 16:22:16 +02:00
setup_dnsmasq_config_if_missing( ) {
# When fresh empty directory volumes are used we miss this file
if [ ! -f /etc/dnsmasq.d/01-pihole.conf ] ; then
cp /etc/.pihole/advanced/01-pihole.conf /etc/dnsmasq.d/
fi ;
}
2017-03-05 00:31:09 +01:00
setup_dnsmasq( ) {
2018-07-30 01:14:24 +02:00
local dns1 = " $1 "
local dns2 = " $2 "
local interface = " $3 "
2018-09-29 22:17:21 +02:00
local dnsmasq_listening_behaviour = " $4 "
2017-03-05 00:31:09 +01:00
# Coordinates
2017-05-23 16:22:16 +02:00
setup_dnsmasq_config_if_missing
2018-07-30 01:14:24 +02:00
setup_dnsmasq_dns " $dns1 " " $dns2 "
setup_dnsmasq_interface " $interface "
2018-09-29 22:17:21 +02:00
setup_dnsmasq_listening_behaviour " $dnsmasq_listening_behaviour "
2019-02-08 02:51:15 +01:00
setup_dnsmasq_user " ${ DNSMASQ_USER } "
2017-03-05 00:31:09 +01:00
ProcessDNSSettings
2016-10-07 02:46:20 +02:00
}
2019-02-03 19:47:37 +01:00
setup_dnsmasq_user( ) {
2019-02-08 02:51:15 +01:00
local DNSMASQ_USER = " ${ 1 } "
2019-02-04 01:30:42 +01:00
2019-02-04 01:37:03 +01:00
# Run DNSMASQ as root user to avoid SHM permission issues
2019-02-04 01:30:42 +01:00
if grep -r -q '^\s*user=' /etc/dnsmasq.* ; then
# Change user that had been set previously to root
2019-02-05 07:17:54 +01:00
for f in $( grep -r -l '^\s*user=' /etc/dnsmasq.*) ; do
2019-02-04 01:37:03 +01:00
sed -i " /^\s*user=/ c\user= ${ DNSMASQ_USER } " " ${ f } "
2019-02-04 01:30:42 +01:00
done
else
2019-02-04 01:37:03 +01:00
echo -e " \nuser= ${ DNSMASQ_USER } " >> /etc/dnsmasq.conf
2019-02-04 01:30:42 +01:00
fi
2019-02-03 19:47:37 +01:00
}
2016-10-30 18:13:52 +01:00
setup_dnsmasq_hostnames( ) {
# largely borrowed from automated install/basic-install.sh
2017-01-08 17:42:39 +01:00
local IPV4_ADDRESS = " ${ 1 } "
local IPV6_ADDRESS = " ${ 2 } "
2016-10-30 18:13:52 +01:00
local hostname = " ${ 3 } "
2016-10-30 18:25:08 +01:00
local dnsmasq_pihole_01_location = "/etc/dnsmasq.d/01-pihole.conf"
2016-10-30 18:13:52 +01:00
if [ -z " $hostname " ] ; then
2016-10-30 18:25:08 +01:00
if [ [ -f /etc/hostname ] ] ; then
hostname = $( </etc/hostname)
elif [ -x " $( command -v hostname) " ] ; then
hostname = $( hostname -f)
fi
2016-10-30 18:13:52 +01:00
fi ;
2017-01-08 17:42:39 +01:00
if [ [ " ${ IPV4_ADDRESS } " != "" ] ] ; then
tmp = ${ IPV4_ADDRESS %/* }
sed -i " s/@IPV4@/ $tmp / " ${ dnsmasq_pihole_01_location }
2016-10-30 18:25:08 +01:00
else
2017-01-08 17:42:39 +01:00
sed -i '/^address=\/pi.hole\/@IPV4@/d' ${ dnsmasq_pihole_01_location }
sed -i '/^address=\/@HOSTNAME@\/@IPV4@/d' ${ dnsmasq_pihole_01_location }
2016-10-30 18:25:08 +01:00
fi
2017-01-08 17:42:39 +01:00
if [ [ " ${ IPV6_ADDRESS } " != "" ] ] ; then
sed -i " s/@IPv6@/ $IPV6_ADDRESS / " ${ dnsmasq_pihole_01_location }
2016-10-30 18:25:08 +01:00
else
sed -i '/^address=\/pi.hole\/@IPv6@/d' ${ dnsmasq_pihole_01_location }
sed -i '/^address=\/@HOSTNAME@\/@IPv6@/d' ${ dnsmasq_pihole_01_location }
fi
if [ [ " ${ hostname } " != "" ] ] ; then
sed -i " s/@HOSTNAME@/ $hostname / " ${ dnsmasq_pihole_01_location }
else
sed -i '/^address=\/@HOSTNAME@*/d' ${ dnsmasq_pihole_01_location }
fi
2016-10-30 18:13:52 +01:00
}
2017-07-26 21:36:32 +02:00
setup_lighttpd_bind( ) {
2018-07-30 01:14:24 +02:00
local serverip = " $1 "
2018-01-13 16:23:12 +01:00
# if using '--net=host' only bind lighttpd on $ServerIP and localhost
2018-07-30 01:14:24 +02:00
if grep -q "docker" /proc/net/dev ; then #docker (docker0 by default) should only be present on the host system
if ! grep -q "server.bind" /etc/lighttpd/lighttpd.conf ; then # if the declaration is already there, don't add it again
sed -i -E " s/server\.port\s+\=\s+([0-9]+)/server.bind\t\t = \" ${ serverip } \"\nserver.port\t\t = \1\n " \$ SERVER"\[\"socket\"\] == \"127\.0\.0\.1:\1\" \{\}/" /etc/lighttpd/lighttpd.conf
2017-07-26 23:50:23 +02:00
fi
fi
2017-07-26 21:36:32 +02:00
}
2016-10-07 02:46:20 +02:00
setup_php_env( ) {
if [ -z " $VIRTUAL_HOST " ] ; then
VIRTUAL_HOST = " $ServerIP "
fi ;
2016-10-21 05:36:55 +02:00
local vhost_line = " \t\t\t\"VIRTUAL_HOST\" => \" ${ VIRTUAL_HOST } \", "
local serverip_line = " \t\t\t\"ServerIP\" => \" ${ ServerIP } \", "
local php_error_line = " \t\t\t\"PHP_ERROR_LOG\" => \" ${ PHP_ERROR_LOG } \", "
# idempotent line additions
2016-11-02 04:46:29 +01:00
grep -qP " $vhost_line " " $PHP_ENV_CONFIG " || \
2016-10-22 20:39:12 +02:00
sed -i " /bin-environment/ a\\ ${ vhost_line } " " $PHP_ENV_CONFIG "
2016-11-02 04:46:29 +01:00
grep -qP " $serverip_line " " $PHP_ENV_CONFIG " || \
2016-10-22 20:39:12 +02:00
sed -i " /bin-environment/ a\\ ${ serverip_line } " " $PHP_ENV_CONFIG "
2016-11-02 04:46:29 +01:00
grep -qP " $php_error_line " " $PHP_ENV_CONFIG " || \
2016-10-22 20:39:12 +02:00
sed -i " /bin-environment/ a\\ ${ php_error_line } " " $PHP_ENV_CONFIG "
2016-10-07 02:46:20 +02:00
echo "Added ENV to php:"
2016-10-22 20:39:12 +02:00
grep -E '(VIRTUAL_HOST|ServerIP|PHP_ERROR_LOG)' " $PHP_ENV_CONFIG "
2016-10-07 02:46:20 +02:00
}
2017-11-15 05:33:05 +01:00
setup_web_port( ) {
local warning = "WARNING: Custom WEB_PORT not used"
# Quietly exit early for empty or default
if [ [ -z " ${ 1 } " || " ${ 1 } " = = '80' ] ] ; then return ; fi
if ! echo $1 | grep -q '^[0-9][0-9]*$' ; then
echo " $warning - $1 is not an integer "
return
fi
local -i web_port = " $1 "
if ( ( $web_port < 1 || $web_port > 65535 ) ) ; then
echo " $warning - $web_port is not within valid port range of 1-65535 "
return
fi
echo " Custom WEB_PORT set to $web_port "
echo " INFO: Without proper router DNAT forwarding to $ServerIP : $web_port , you may not get any blocked websites on ads "
2018-02-23 06:11:53 +01:00
# Update lighttpd's port
sed -i '/server.port\s*=\s*80\s*$/ s/80/' $WEB_PORT '/g' /etc/lighttpd/lighttpd.conf
# Update any default port 80 references in the HTML
grep -Prl '://127\.0\.0\.1/' /var/www/html/ | xargs -r sed -i " s|/127\.0\.0\.1/|/127.0.0.1: ${ WEB_PORT } /|g "
grep -Prl '://pi\.hole/' /var/www/html/ | xargs -r sed -i " s|/pi\.hole/|/pi\.hole: ${ WEB_PORT } /|g "
2017-11-15 05:33:05 +01:00
}
2018-09-18 07:11:26 +02:00
generate_password( ) {
2018-08-04 23:19:11 +02:00
if [ -z " ${ WEBPASSWORD +x } " ] ; then
2018-08-04 22:58:05 +02:00
# Not set at all, give the user a random pass
WEBPASSWORD = $( tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
echo " Assigning random password: $WEBPASSWORD "
fi ;
2018-09-18 07:11:26 +02:00
}
setup_web_password( ) {
PASS = " $1 "
2018-08-04 22:58:05 +02:00
# Turn bash debug on while setting up password (to print it)
2018-09-18 07:11:26 +02:00
if [ [ " $PASS " = = "" ] ] ; then
2018-08-04 22:58:05 +02:00
echo "" | pihole -a -p
else
2018-10-17 02:55:52 +02:00
echo " Setting password: ${ PASS } "
set -x
2018-09-18 07:11:26 +02:00
pihole -a -p " $PASS " " $PASS "
2018-08-04 22:58:05 +02:00
fi
2018-10-17 02:55:52 +02:00
# Turn bash debug back off after print password setup
# (subshell to null hides printing output)
{ set +x; } 2>/dev/null
# To avoid printing this if conditional in bash debug, turn off debug above..
# then re-enable debug if necessary (more code but cleaner printed output)
if [ " ${ PH_VERBOSE :- 0 } " -gt 0 ] ; then
set -x
2018-08-04 22:58:05 +02:00
fi
2017-02-09 05:46:46 +01:00
}
2017-10-14 14:53:29 +02:00
2016-10-21 05:36:55 +02:00
setup_ipv4_ipv6( ) {
local ip_versions = "IPv4 and IPv6"
if [ " $IPv6 " != "True" ] ; then
ip_versions = "IPv4"
2018-07-30 01:14:24 +02:00
sed -i '/use-ipv6.pl/ d' /etc/lighttpd/lighttpd.conf
2016-10-21 05:36:55 +02:00
fi ;
echo " Using $ip_versions "
}
2016-10-07 02:46:20 +02:00
test_configs( ) {
2016-10-07 19:14:12 +02:00
set -e
2018-09-18 07:11:26 +02:00
echo -n '::: Testing pihole-FTL DNS: '
2019-02-06 11:02:30 +01:00
sudo -u ${ DNSMASQ_USER :- root } pihole-FTL test || exit 1
2016-10-07 19:14:12 +02:00
echo -n '::: Testing lighttpd config: '
2018-01-25 19:45:05 +01:00
lighttpd -t -f /etc/lighttpd/lighttpd.conf || exit 1
2016-10-07 19:14:12 +02:00
set +e
2018-07-30 01:14:24 +02:00
echo "::: All config checks passed, cleared for startup ..."
2016-10-07 02:46:20 +02:00
}
2018-07-30 01:14:24 +02:00
setup_blocklists( ) {
local blocklists = " $1 "
# Exit/return early without setting up adlists with defaults for any of the following conditions:
# 1. NO_SETUP env is set
exit_string = " (exiting ${ FUNCNAME [0] } early) "
if [ -n " ${ NO_SETUP } " ] ; then
echo " ::: NO_SETUP requested ( $exit_string ) "
return
fi
# 2. The adlist file exists already (restarted container or volume mounted list)
if [ -f " ${ adlistFile } " ] ; then
echo " ::: Preexisting ad list ${ adlistFile } detected ( $exit_string ) "
cat " ${ adlistFile } "
return
fi
echo " ::: ${ FUNCNAME [0] } now setting default blocklists up: "
echo " ::: TIP: Use a docker volume for ${ adlistFile } if you want to customize for first boot "
2019-01-22 05:43:38 +01:00
installDefaultBlocklists
2018-07-30 01:14:24 +02:00
echo " ::: Blocklists ( ${ adlistFile } ) now set to: "
cat " ${ adlistFile } "
2016-10-07 02:46:20 +02:00
}