2017-03-04 06:13:11 +01:00
#!/bin/bash
2022-07-19 19:22:49 +02:00
# If user has set QUERY_LOGGING Env Var, copy it out to _OVERRIDE,
# else it will get overridden itself when we source basic-install.sh
[ -n " ${ QUERY_LOGGING } " ] && export QUERY_LOGGING_OVERRIDE = " ${ QUERY_LOGGING } "
2022-07-12 00:50:05 +02:00
# Some of the bash_functions use utilities from Pi-hole's utils.sh
# shellcheck disable=SC2154
# shellcheck source=/dev/null
2023-02-16 00:48:53 +01:00
# . /opt/pihole/utils.sh
#######################
# returns value from FTLs config file using pihole-FTL --config
#
# Takes one argument: key
# Example getFTLConfigValue dns.piholePTR
#######################
getFTLConfigValue( ) {
2023-07-09 18:02:38 +02:00
pihole-FTL --config -q " ${ 1 } "
2023-02-16 00:48:53 +01:00
}
#######################
# sets value in FTLs config file using pihole-FTL --config
#
# Takes two arguments: key and value
# Example setFTLConfigValue dns.piholePTR PI.HOLE
#
# Note, for complex values such as dns.upstreams, you should wrap the value in single quotes:
# setFTLConfigValue dns.upstreams '[ "8.8.8.8" , "8.8.4.4" ]'
#######################
setFTLConfigValue( ) {
pihole-FTL --config " ${ 1 } " " ${ 2 } " >/dev/null
}
# export adlistFile="/etc/pihole/adlists.list"
# shellcheck disable=SC2034
ensure_basic_configuration( ) {
echo " [i] Ensuring basic configuration by re-running select functions from basic-install.sh"
# installScripts > /dev/null
# installLogrotate || true #installLogRotate can return 2 or 3, but we are still OK to continue in that case
# set +e
mkdir -p /var/run/pihole /var/log/pihole
touch /var/log/pihole/FTL.log /var/log/pihole/pihole.log
chown -R pihole:pihole /var/run/pihole /var/log/pihole
# In case of `pihole` UID being changed, re-chown the pihole scripts and pihole command
# chown -R pihole:root "${PI_HOLE_INSTALL_DIR}"
# chown pihole:root "${PI_HOLE_BIN_DIR}/pihole"
mkdir -p /etc/pihole
2023-08-10 00:31:39 +02:00
if [ [ -z " ${ PYTEST } " ] ] ; then
if [ [ ! -f /etc/pihole/adlists.list ] ] ; then
echo "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" >/etc/pihole/adlists.list
fi
2023-08-09 23:13:28 +02:00
fi
2023-08-10 00:31:39 +02:00
2023-02-16 00:48:53 +01:00
chown -R pihole:pihole /etc/pihole
# set -e
2023-06-29 18:25:08 +02:00
# If FTLCONF_files_macvendor is not set
if [ [ -z " ${ FTLCONF_files_macvendor :- } " ] ] ; then
# User is not passing in a custom location - so force FTL to use the file we moved to / during the build
setFTLConfigValue "files.macvendor" "/macvendor.db"
chown pihole:pihole /macvendor.db
fi
2023-02-16 00:48:53 +01:00
}
2022-07-12 00:50:05 +02:00
2022-08-24 22:27:38 +02:00
fix_capabilities( ) {
# Testing on Docker 20.10.14 with no caps set shows the following caps available to the container:
# Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
# FTL can also use CAP_NET_ADMIN and CAP_SYS_NICE. If we try to set them when they haven't been explicitly enabled, FTL will not start. Test for them first:
2022-08-29 14:22:50 +02:00
echo " [i] Setting capabilities on pihole-FTL where possible"
2023-02-16 00:48:53 +01:00
capsh --has-p= cap_chown 2>/dev/null && CAP_STR += ',CAP_CHOWN'
capsh --has-p= cap_net_bind_service 2>/dev/null && CAP_STR += ',CAP_NET_BIND_SERVICE'
capsh --has-p= cap_net_raw 2>/dev/null && CAP_STR += ',CAP_NET_RAW'
capsh --has-p= cap_net_admin 2>/dev/null && CAP_STR += ',CAP_NET_ADMIN' || DHCP_READY = 'false'
capsh --has-p= cap_sys_nice 2>/dev/null && CAP_STR += ',CAP_SYS_NICE'
2022-08-24 22:27:38 +02:00
if [ [ ${ CAP_STR } ] ] ; then
# We have the (some of) the above caps available to us - apply them to pihole-FTL
2022-08-29 14:17:22 +02:00
echo " [i] Applying the following caps to pihole-FTL:"
2022-08-29 17:49:16 +02:00
IFS = ',' read -ra CAPS <<< " ${ CAP_STR : 1 } "
for i in " ${ CAPS [@] } " ; do
echo " * ${ i } "
done
2022-08-24 22:27:38 +02:00
setcap ${ CAP_STR : 1 } +ep " $( which pihole-FTL) " || ret = $?
2023-02-06 00:55:24 +01:00
if [ [ $DHCP_READY = = false ] ] && [ [ $FTLCONF_dhcp_active = = true ] ] ; then
2022-08-24 22:27:38 +02:00
# DHCP is requested but NET_ADMIN is not available.
echo "ERROR: DHCP requested but NET_ADMIN is not available. DHCP will not be started."
echo " Please add cap_net_admin to the container's capabilities or disable DHCP."
DHCP_ACTIVE = 'false'
2023-02-05 22:21:49 +01:00
setFTLConfigValue dhcp.active false
2022-08-24 22:27:38 +02:00
fi
if [ [ $ret -ne 0 && " ${ DNSMASQ_USER :- pihole } " != "root" ] ] ; then
2022-08-29 14:17:22 +02:00
echo " [!] ERROR: Unable to set capabilities for pihole-FTL. Cannot run as non-root."
echo " If you are seeing this error, please set the environment variable 'DNSMASQ_USER' to the value 'root'"
2022-08-24 22:27:38 +02:00
exit 1
fi
else
2022-08-29 14:17:22 +02:00
echo " [!] WARNING: Unable to set capabilities for pihole-FTL."
echo " Please ensure that the container has the required capabilities."
2022-08-24 22:27:38 +02:00
exit 1
fi
}
2019-02-03 19:47:37 +01:00
2022-07-12 00:50:05 +02:00
apply_FTL_Configs_From_Env( ) {
2023-02-05 22:21:49 +01:00
# Get all exported environment variables starting with FTLCONF_ as a prefix and call the setFTLConfigValue
2022-07-12 00:50:05 +02:00
# function with the environment variable's suffix as the key. This allows applying any pihole-FTL.conf
# setting defined here: https://docs.pi-hole.net/ftldns/configfile/
2023-02-06 00:55:24 +01:00
echo ""
echo "==========Applying settings from environment variables=========="
source /opt/pihole/COL_TABLE
2023-01-20 19:22:32 +01:00
declare -px | grep FTLCONF_ | sed -E 's/declare -x FTLCONF_([^=]+)=\"(|.+)\"/\1 \2/' | while read -r name value
2022-07-12 00:50:05 +02:00
do
2023-06-19 00:10:46 +02:00
# Replace underscores with dots in the name to match pihole-FTL expectiations
2023-02-06 00:55:24 +01:00
name = " ${ name //_/. } "
2023-10-16 18:11:11 +02:00
# Special handling for some FTL Config values
case " $name " in
# Convert the semicolon separated list to a JSON array
"dns.upstreams" )
value = '["' ${ value //;/ \" , \" } '"]'
; ;
# The following config names have an underscore in them,
# so we need to re-convert the dot back to an underscore
"webserver.tls.rev.proxy" )
name = "webserver.tls.rev_proxy"
; ;
"webserver.api.totp.secret" )
name = "webserver.api.totp_secret"
; ;
"webserver.api.allow.destructive" )
name = "webserver.api.allow_destructive"
; ;
"misc.delay.startup" )
name = "misc.delay_startup"
; ;
"misc.dnsmasq.lines" )
name = "misc.dnsmasq_lines"
; ;
esac
# Mask the value if it is a password, else display the value as is
2023-02-11 14:59:28 +01:00
if [ " $name " = = "webserver.api.password" ] ; then
masked_value = $( printf " % ${# value } s " | tr " " "*" )
else
masked_value = $value
2023-02-06 00:55:24 +01:00
fi
2023-07-09 18:02:38 +02:00
if pihole-FTL --config " ${ name } " " ${ value } " > /ftlconfoutput; then
2023-02-11 14:59:28 +01:00
echo " ${ TICK } Applied pihole-FTL setting $name = $masked_value "
2023-02-06 00:55:24 +01:00
else
2023-02-11 14:59:28 +01:00
echo " ${ CROSS } Error Applying pihole-FTL setting $name = $masked_value "
echo " ${ INFO } $( cat /ftlconfoutput) "
2023-02-06 00:55:24 +01:00
fi
done
echo "================================================================"
echo ""
2022-07-12 00:50:05 +02:00
}
setup_FTL_query_logging( ) {
if [ " ${ QUERY_LOGGING_OVERRIDE } " = = "false" ] ; then
2022-08-29 14:17:22 +02:00
echo " [i] Disabling Query Logging"
2023-02-05 22:21:49 +01:00
setFTLConfigValue dns.queryLogging " ${ QUERY_LOGGING_OVERRIDE } "
2022-07-12 00:50:05 +02:00
else
# If it is anything other than false, set it to true
2022-08-29 14:17:22 +02:00
echo " [i] Enabling Query Logging"
2023-02-05 22:21:49 +01:00
setFTLConfigValue dns.queryLogging true
2022-07-12 00:50:05 +02:00
fi
}
2016-10-07 02:46:20 +02:00
2020-02-26 18:27:42 +01:00
load_web_password_secret( ) {
# If WEBPASSWORD is not set at all, attempt to read password from WEBPASSWORD_FILE,
# allowing secrets to be passed via docker secrets
if [ -z " ${ WEBPASSWORD +x } " ] && [ -n " ${ WEBPASSWORD_FILE } " ] && [ -r " ${ WEBPASSWORD_FILE } " ] ; then
WEBPASSWORD = $( <" ${ WEBPASSWORD_FILE } " )
fi ;
}
2018-09-18 07:11:26 +02:00
setup_web_password( ) {
2022-05-30 08:00:16 +02:00
if [ -z " ${ WEBPASSWORD +x } " ] ; then
2022-07-19 19:22:49 +02:00
# ENV WEBPASSWORD_OVERRIDE is not set
2022-05-30 08:00:16 +02:00
2023-02-05 22:21:49 +01:00
# Exit if password is already set (TODO: Revisit this. Maybe make setting password in environment variable mandatory?)
if [ [ $( pihole-FTL --config webserver.api.pwhash) != '""' ] ] ; then
return
fi
2022-06-06 21:12:24 +02:00
# Generate new random password
WEBPASSWORD = $( tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
2022-08-29 14:17:22 +02:00
echo " [i] Assigning random password: $WEBPASSWORD "
2022-05-30 08:00:16 +02:00
else
2022-07-19 19:22:49 +02:00
# ENV WEBPASSWORD_OVERRIDE is set and will be used
2022-08-29 14:17:22 +02:00
echo " [i] Assigning password defined by Environment Variable"
2022-07-19 19:22:49 +02:00
# WEBPASSWORD="$WEBPASSWORD"
2022-05-30 08:00:16 +02:00
fi
2021-04-14 18:13:01 +02:00
# Explicitly turn off bash printing when working with secrets
{ set +x; } 2>/dev/null
2022-07-19 19:22:49 +02:00
if [ [ " $WEBPASSWORD " = = "" ] ] ; then
2018-08-04 22:58:05 +02:00
echo "" | pihole -a -p
else
2022-07-19 19:22:49 +02:00
pihole -a -p " $WEBPASSWORD " " $WEBPASSWORD "
2018-08-04 22:58:05 +02:00
fi
2018-10-17 02:55:52 +02:00
# 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
2023-02-16 00:48:53 +01:00
# setup_blocklists() {
# # Exit/return early without setting up adlists with defaults for any of the following conditions:
# # 1. skip_setup_blocklists env is set
# exit_string="(exiting ${FUNCNAME[0]} early)"
# if [ -n "${skip_setup_blocklists}" ]; then
# echo " [i] skip_setup_blocklists requested $exit_string"
# return
# fi
# # 2. The adlist file exists already (restarted container or volume mounted list)
# if [ -f "${adlistFile}" ]; then
# echo " [i] Preexisting ad list ${adlistFile} detected $exit_string"
# return
# fi
# echo " [i] ${FUNCNAME[0]} now setting default blocklists up: "
# echo " [i] TIP: Use a docker volume for ${adlistFile} if you want to customize for first boot"
# # installDefaultBlocklists
# echo " [i] Blocklists (${adlistFile}) now set to:"
# cat "${adlistFile}"
# }