mirror of
https://github.com/pi-hole/docker-pi-hole.git
synced 2024-06-28 20:20:57 +02:00
Merge pull request #133 from diginc/dev
Development version of v3.0.1 release
This commit is contained in:
commit
4f8d7f4720
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
**/*.sw*
|
24
README.md
24
README.md
|
@ -17,16 +17,24 @@ One crucial thing to know before starting is the docker-pi-hole container needs
|
||||||
```
|
```
|
||||||
IMAGE='diginc/pi-hole'
|
IMAGE='diginc/pi-hole'
|
||||||
IP_LOOKUP="$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')" # May not work for VPN / tun0
|
IP_LOOKUP="$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')" # May not work for VPN / tun0
|
||||||
|
IPv6_LOOKUP="$(ip -6 route get 2001:4860:4860::8888 | awk '{ print $10; exit }')" # May not work for VPN / tun0
|
||||||
IP="${IP:-$IP_LOOKUP}" # use $IP, if set, otherwise IP_LOOKUP
|
IP="${IP:-$IP_LOOKUP}" # use $IP, if set, otherwise IP_LOOKUP
|
||||||
docker run -p 53:53/tcp -p 53:53/udp -p 80:80 --cap-add=NET_ADMIN -e ServerIP="$IP" --restart=always --name pihole -d $IMAGE
|
IPv6="${IPv6:-$IPv6_LOOKUP}" # use $IPv6, if set, otherwise IP_LOOKUP
|
||||||
|
|
||||||
# Recommended auto ad list updates & log rotation:
|
docker run -d \
|
||||||
wget -O- https://raw.githubusercontent.com/diginc/docker-pi-hole/master/docker-pi-hole.cron | sudo tee /etc/cron.d/docker-pi-hole
|
--name pihole \
|
||||||
|
-p 53:53/tcp -p 53:53/udp -p 80:80 \
|
||||||
|
-v </path/to/store/pihole>:/etc/pihole \
|
||||||
|
-v </path/to/store/dnsmasq.d>:/etc/dnsmasq.d \
|
||||||
|
-e ServerIP="${IP:-$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')}" \
|
||||||
|
-e ServerIPv6="${IPv6:-$(ip -6 route get 2001:4860:4860::8888 | awk '{ print $10; exit }')}" \
|
||||||
|
--restart=always \
|
||||||
|
diginc/pi-hole
|
||||||
```
|
```
|
||||||
|
|
||||||
This is just an example and might need changing. As mentioned on line 2, the auto IP_LOOKUP variable may not work for VPN tunnel interfaces.
|
Volumes aren't required but are recommended for persisting data across docker re-creations for updating images. This is just an example and might need changing. As mentioned on line 2, the auto IP_LOOKUP variable may not work for VPN tunnel interfaces.
|
||||||
|
|
||||||
**Automatic Ad List Updates** - [docker-pi-hole.cron](https://github.com/diginc/docker-pi-hole/blob/master/docker-pi-hole.cron) is a modified version of upstream pi-hole's crontab entries using `docker exec` to run the same update scripts inside the docker container. The cron automatically updates pi-hole ad lists and cleans up pi-hole logs nightly. If you're not using the `docker run` with `--name pihole` from default container run command be sure to fill in your container's DOCKER_NAME into the variable in the cron file.
|
**Automatic Ad List Updates** - since 3.0+ release cron is baked into the container and will grab the newest versions of your lists and flush your logs. **Set TZ** environment variable to make sure the midnight log rotation syncs up with your timezone's midnight.
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
|
@ -34,12 +42,14 @@ In addition to the required environment variable you saw above (`-e ServerIP="$I
|
||||||
|
|
||||||
| Env Variable | Default | Description |
|
| Env Variable | Default | Description |
|
||||||
| ------------ | ------- | ----------- |
|
| ------------ | ------- | ----------- |
|
||||||
| ServerIP | REQUIRED! | Set to your server's external IP in order to override what Pi-Hole users. Pi-Hole auto discovers the unusable internal docker IP otherwise |
|
| ServerIP | REQUIRED! | Set to your server's external IP in order to override what Pi-Hole users requests get sent to. This container is designed to fail when not set since it is pretty useless without it. |
|
||||||
| WEBPASSWORD | <random> | Set this to your desired password or on first boot we'll randomly set one. `docker logs pihole` can tell you what it got set to. To change it check out the tips below |
|
| ServerIPv6 | optional | Where IPv6 ad requests end up, not required if you're not running ipv6 network |
|
||||||
|
| WEBPASSWORD | <random> | Recommended! Set this to your desired password or on first boot we'll randomly set one. `docker logs pihole` can tell you what it got set to. To change it check out the tips below |
|
||||||
| DNS1 | 8.8.8.8 | Primary upstream DNS for Pi-Hole's DNSMasq to use, defaults to google |
|
| DNS1 | 8.8.8.8 | Primary upstream DNS for Pi-Hole's DNSMasq to use, defaults to google |
|
||||||
| DNS2 | 8.8.4.4 | Secondary upstream DNS for Pi-Hole's DNSMasq to use, defaults to google |
|
| DNS2 | 8.8.4.4 | Secondary upstream DNS for Pi-Hole's DNSMasq to use, defaults to google |
|
||||||
| VIRTUAL_HOST | Server_IP | What your web server 'virtual host' is, accessing admin through this Hostname/IP allows you to make changes to the whitelist / blacklists in addition to the default 'http://pi.hole/admin/' address |
|
| VIRTUAL_HOST | Server_IP | What your web server 'virtual host' is, accessing admin through this Hostname/IP allows you to make changes to the whitelist / blacklists in addition to the default 'http://pi.hole/admin/' address |
|
||||||
| IPv6 | True | Allows forced disabling of IPv6 for docker setups that can't support it (like unraid) |
|
| IPv6 | True | Allows forced disabling of IPv6 for docker setups that can't support it (like unraid) |
|
||||||
|
| TZ | UCT | Customize your container's timezone, useful if you use the cron for pihole updates |
|
||||||
|
|
||||||
*OPTIONAL Advanced* Environment Variables
|
*OPTIONAL Advanced* Environment Variables
|
||||||
|
|
||||||
|
|
|
@ -4,26 +4,22 @@ MAINTAINER adam@diginc.us <adam@diginc.us>
|
||||||
ENV IMAGE alpine
|
ENV IMAGE alpine
|
||||||
ENV PATH /opt/pihole:${PATH}
|
ENV PATH /opt/pihole:${PATH}
|
||||||
|
|
||||||
COPY install.sh /install.sh
|
COPY install.sh /usr/local/bin/docker-install.sh
|
||||||
COPY ./alpine/service /usr/local/bin/service
|
|
||||||
ENV setupVars /etc/pihole/setupVars.conf
|
ENV setupVars /etc/pihole/setupVars.conf
|
||||||
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
||||||
|
ENV S6OVERLAY_RELEASE https://github.com/just-containers/s6-overlay/releases/download/v1.19.1.1/s6-overlay-amd64.tar.gz
|
||||||
|
|
||||||
ENV TINI_VERSION v0.13.0
|
RUN apk upgrade --update && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static /tini
|
apk add bind-tools wget curl bash libcap && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static.asc /tini.asc
|
curl -L -s $S6OVERLAY_RELEASE \
|
||||||
|
| tar xvzf - -C / && \
|
||||||
# Tini and package requirements
|
docker-install.sh && \
|
||||||
RUN apk add --update 'gnupg<2.1.17-r0' && \
|
|
||||||
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 0527A9B7 && \
|
|
||||||
gpg --verify /tini.asc && \
|
|
||||||
chmod +x /tini && \
|
|
||||||
apk add wget bash && \
|
|
||||||
/install.sh && \
|
|
||||||
rm -rf /var/cache/apk/*
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
# Customized from submodules
|
ENTRYPOINT [ "/init" ]
|
||||||
COPY ./alpine/nginx.conf /etc/nginx/nginx.conf
|
|
||||||
|
ADD s6/alpine-root /
|
||||||
|
COPY s6/service /usr/local/bin/service
|
||||||
|
|
||||||
# Things installer did and fix alpine+nginx differences
|
# Things installer did and fix alpine+nginx differences
|
||||||
ENV WEBLOGDIR /var/log/nginx
|
ENV WEBLOGDIR /var/log/nginx
|
||||||
|
@ -35,29 +31,30 @@ RUN mkdir -p /etc/pihole/ && \
|
||||||
touch ${WEBLOGDIR}/access.log ${WEBLOGDIR}/error.log && \
|
touch ${WEBLOGDIR}/access.log ${WEBLOGDIR}/error.log && \
|
||||||
chown -R nginx:nginx ${WEBLOGDIR} && \
|
chown -R nginx:nginx ${WEBLOGDIR} && \
|
||||||
sed -i 's|^user\s*=.*$|user = nginx|' $PHP_CONFIG && \
|
sed -i 's|^user\s*=.*$|user = nginx|' $PHP_CONFIG && \
|
||||||
|
sed -i '/^;pid/ s|^;||' $PHP_CONFIG && \
|
||||||
chmod 775 /var/www/html && \
|
chmod 775 /var/www/html && \
|
||||||
touch /var/log/pihole.log && \
|
touch /var/log/pihole.log && \
|
||||||
chmod 644 /var/log/pihole.log && \
|
chmod 644 /var/log/pihole.log && \
|
||||||
chown dnsmasq:root /var/log/pihole.log && \
|
chown dnsmasq:root /var/log/pihole.log && \
|
||||||
sed -i "s/@INT@/eth0/" /etc/dnsmasq.d/01-pihole.conf && \
|
sed -i "s/@INT@/eth0/" /etc/dnsmasq.d/01-pihole.conf && \
|
||||||
|
setcap CAP_NET_BIND_SERVICE=+eip `which dnsmasq` && \
|
||||||
|
cp -f /usr/bin/list.sh /opt/pihole/list.sh && \
|
||||||
echo 'Done!'
|
echo 'Done!'
|
||||||
|
|
||||||
#sed -i 's|"cd /etc/.pihole/ && git describe --tags --abbrev=0"|"cat /etc/pi-hole_version.txt"|g' /var/www/html/admin/footer.php && \
|
|
||||||
#sed -i 's|"git describe --tags --abbrev=0"|"cat /etc/AdminLTE_version.txt"|g' /var/www/html/admin/footer.php && \
|
|
||||||
#sed -i 's|www-data|nginx|g' /etc/sudoers.d/pihole && \
|
|
||||||
|
|
||||||
# php config start passes special ENVs into
|
# php config start passes special ENVs into
|
||||||
ENV PHP_ENV_CONFIG '/etc/php5/fpm.d/envs.conf'
|
ENV PHP_ENV_CONFIG '/etc/php5/fpm.d/envs.conf'
|
||||||
ENV PHP_ERROR_LOG '/var/log/nginx/error.log'
|
ENV PHP_ERROR_LOG '/var/log/nginx/error.log'
|
||||||
COPY ./start.sh /
|
COPY ./start.sh /
|
||||||
COPY ./bash_functions.sh /
|
COPY ./bash_functions.sh /
|
||||||
|
|
||||||
# IPV6 disable flag for networks/devices that do not support it
|
# IPv6 disable flag for networks/devices that do not support it
|
||||||
ENV IPv6 True
|
ENV IPv6 True
|
||||||
|
|
||||||
EXPOSE 53 53/udp
|
EXPOSE 53 53/udp
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
ENV S6_LOGGING 0
|
||||||
|
ENV S6_KEEP_ENV 1
|
||||||
|
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
ENTRYPOINT ["/tini", "--"]
|
|
||||||
CMD [ "/start.sh" ]
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# lazy cheap service script patch for alpine
|
|
||||||
dnsmasq_start() {
|
|
||||||
dnsmasq -7 /etc/dnsmasq.d
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsmasq_stop() {
|
|
||||||
kill -9 $(pidof dnsmasq)
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsmasq_restart() {
|
|
||||||
dnsmasq_stop; dnsmasq_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
status() {
|
|
||||||
if pidof $service 2&>1 > /dev/null ; then
|
|
||||||
echo "$service running"
|
|
||||||
else
|
|
||||||
echo "$service not running"
|
|
||||||
fi;
|
|
||||||
}
|
|
||||||
|
|
||||||
nginx_start() {
|
|
||||||
nginx -t && \
|
|
||||||
nginx
|
|
||||||
}
|
|
||||||
nginx_stop() {
|
|
||||||
nginx -t && \
|
|
||||||
kill -9 $(pidof nginx)
|
|
||||||
}
|
|
||||||
nginx_restart() {
|
|
||||||
nginx_stop
|
|
||||||
nginx_start
|
|
||||||
}
|
|
||||||
dnsmasq_status() {
|
|
||||||
status
|
|
||||||
}
|
|
||||||
nginx_status() {
|
|
||||||
status
|
|
||||||
}
|
|
||||||
|
|
||||||
service="$1"
|
|
||||||
command="$2"
|
|
||||||
if [[ "$service" == 'lighttpd' ]] ; then
|
|
||||||
echo -e "Lighttpd replaced by nginx in diginc/pi-hole:alpine\nrunning service nginx $command instead";
|
|
||||||
service='nginx'
|
|
||||||
fi;
|
|
||||||
|
|
||||||
|
|
||||||
if [[ "$service" == 'dnsmasq' ]] || [[ "$service" == 'nginx' ]] ; then
|
|
||||||
${service}_${command} || echo "Unknown option $command"
|
|
||||||
else
|
|
||||||
echo "$service service wrapper not patched into alpine container"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
|
@ -2,6 +2,7 @@
|
||||||
. /opt/pihole/webpage.sh
|
. /opt/pihole/webpage.sh
|
||||||
setupVars="$setupVars"
|
setupVars="$setupVars"
|
||||||
ServerIP="$ServerIP"
|
ServerIP="$ServerIP"
|
||||||
|
ServerIPv6="$ServerIPv6"
|
||||||
IPv6="$IPv6"
|
IPv6="$IPv6"
|
||||||
|
|
||||||
prepare_setup_vars() {
|
prepare_setup_vars() {
|
||||||
|
@ -13,6 +14,32 @@ validate_env() {
|
||||||
echo "ERROR: To function correctly you must pass an environment variables of 'ServerIP' into the docker container with the IP of your docker host from which you are passing web (80) and dns (53) ports from"
|
echo "ERROR: To function correctly you must pass an environment variables of 'ServerIP' into the docker container with the IP of your docker host from which you are passing web (80) and dns (53) ports from"
|
||||||
exit 1
|
exit 1
|
||||||
fi;
|
fi;
|
||||||
|
|
||||||
|
# Debian
|
||||||
|
nc_error='Name or service not known'
|
||||||
|
if [[ "$IMAGE" == 'alpine' ]] ; then
|
||||||
|
nc_error='bad address'
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Required ServerIP is a valid IP
|
||||||
|
if nc -w1 -z "$ServerIP" 53 2>&1 | grep -q "$nc_error" ; then
|
||||||
|
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
|
||||||
|
echo "WARNING: You passed in IPv6 with a value of 'kernel', this maybe beacuse you do not have IPv6 enabled on your network"
|
||||||
|
unset ServerIPv6
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if nc -w 1 -z "$ServerIPv6" 53 2>&1 | grep -q "$nc_error" || ! ip route get "$ServerIPv6" ; then
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_dnsmasq_dns() {
|
setup_dnsmasq_dns() {
|
||||||
|
@ -134,7 +161,13 @@ setup_web_password() {
|
||||||
WEBPASSWORD=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
|
WEBPASSWORD=$(tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 8)
|
||||||
echo "Assigning random password: $WEBPASSWORD"
|
echo "Assigning random password: $WEBPASSWORD"
|
||||||
fi;
|
fi;
|
||||||
pihole -a -p "$WEBPASSWORD"
|
set -x
|
||||||
|
if [[ "$WEBPASSWORD" == "" ]] ; then
|
||||||
|
echo "" | pihole -a -p
|
||||||
|
else
|
||||||
|
pihole -a -p "$WEBPASSWORD" "$WEBPASSWORD"
|
||||||
|
fi
|
||||||
|
{ set +x; } 2>/dev/null
|
||||||
}
|
}
|
||||||
setup_ipv4_ipv6() {
|
setup_ipv4_ipv6() {
|
||||||
local ip_versions="IPv4 and IPv6"
|
local ip_versions="IPv4 and IPv6"
|
||||||
|
@ -142,7 +175,7 @@ setup_ipv4_ipv6() {
|
||||||
ip_versions="IPv4"
|
ip_versions="IPv4"
|
||||||
case $IMAGE in
|
case $IMAGE in
|
||||||
"debian") sed -i '/use-ipv6.pl/ d' /etc/lighttpd/lighttpd.conf ;;
|
"debian") sed -i '/use-ipv6.pl/ d' /etc/lighttpd/lighttpd.conf ;;
|
||||||
"alpine") sed -i '/listen \[::\]:80;/ d' /etc/nginx/nginx.conf ;;
|
"alpine") sed -i '/listen \[::\]:80/ d' /etc/nginx/nginx.conf ;;
|
||||||
esac
|
esac
|
||||||
fi;
|
fi;
|
||||||
echo "Using $ip_versions"
|
echo "Using $ip_versions"
|
||||||
|
@ -178,7 +211,11 @@ test_configs_alpine() {
|
||||||
}
|
}
|
||||||
|
|
||||||
test_framework_stubbing() {
|
test_framework_stubbing() {
|
||||||
if [ -n "$PYTEST" ] ; then sed -i 's/^gravity_spinup$/#gravity_spinup # DISABLED FOR PYTEST/g' "$(which gravity.sh)"; fi;
|
if [ -n "$PYTEST" ] ; then
|
||||||
|
echo ":::::: Tests are being ran - stub out ad list fetching and add a fake ad block"
|
||||||
|
sed -i 's/^gravity_spinup$/#gravity_spinup # DISABLED FOR PYTEST/g' "$(which gravity.sh)"
|
||||||
|
echo 'testblock.pi-hole.local' >> /etc/pihole/blacklist.txt
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
docker_main() {
|
docker_main() {
|
||||||
|
|
|
@ -6,22 +6,23 @@ RUN [ "cross-build-start" ]
|
||||||
ENV IMAGE debian
|
ENV IMAGE debian
|
||||||
ENV PATH /opt/pihole:${PATH}
|
ENV PATH /opt/pihole:${PATH}
|
||||||
|
|
||||||
COPY install.sh /install.sh
|
COPY install.sh /usr/local/bin/docker-install.sh
|
||||||
ENV setupVars /etc/pihole/setupVars.conf
|
ENV setupVars /etc/pihole/setupVars.conf
|
||||||
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
||||||
|
ENV S6OVERLAY_RELEASE https://github.com/just-containers/s6-overlay/releases/download/v1.19.1.1/s6-overlay-armhf.tar.gz
|
||||||
|
|
||||||
ENV TINI_VERSION v0.13.0
|
RUN apt-get update && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-armhf /tini
|
apt-get install -y wget curl net-tools cron && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-armhf.asc /tini.asc
|
curl -L -s $S6OVERLAY_RELEASE \
|
||||||
|
| tar xvzf - -C / && \
|
||||||
RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 0527A9B7 && \
|
docker-install.sh && \
|
||||||
gpg --verify /tini.asc && \
|
|
||||||
chmod +x /tini && \
|
|
||||||
apt-get -q update && \
|
|
||||||
apt-get install -y wget net-tools && \
|
|
||||||
/install.sh && \
|
|
||||||
rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/init" ]
|
||||||
|
|
||||||
|
ADD s6/debian-root /
|
||||||
|
COPY s6/service /usr/local/bin/service
|
||||||
|
|
||||||
# php config start passes special ENVs into
|
# php config start passes special ENVs into
|
||||||
ENV PHP_ENV_CONFIG '/etc/lighttpd/conf-enabled/15-fastcgi-php.conf'
|
ENV PHP_ENV_CONFIG '/etc/lighttpd/conf-enabled/15-fastcgi-php.conf'
|
||||||
ENV PHP_ERROR_LOG '/var/log/lighttpd/error.log'
|
ENV PHP_ERROR_LOG '/var/log/lighttpd/error.log'
|
||||||
|
@ -35,8 +36,10 @@ ENV IPv6 True
|
||||||
EXPOSE 53 53/udp
|
EXPOSE 53 53/udp
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
ENV S6_LOGGING 0
|
||||||
|
ENV S6_KEEP_ENV 1
|
||||||
|
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
ENTRYPOINT ["/tini", "--"]
|
|
||||||
CMD [ "/start.sh" ]
|
|
||||||
|
|
||||||
RUN [ "cross-build-end" ]
|
RUN [ "cross-build-end" ]
|
||||||
|
|
|
@ -4,22 +4,23 @@ MAINTAINER adam@diginc.us <adam@diginc.us>
|
||||||
ENV IMAGE debian
|
ENV IMAGE debian
|
||||||
ENV PATH /opt/pihole:${PATH}
|
ENV PATH /opt/pihole:${PATH}
|
||||||
|
|
||||||
COPY install.sh /install.sh
|
COPY install.sh /usr/local/bin/docker-install.sh
|
||||||
ENV setupVars /etc/pihole/setupVars.conf
|
ENV setupVars /etc/pihole/setupVars.conf
|
||||||
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
ENV PIHOLE_INSTALL /tmp/ph_install.sh
|
||||||
|
ENV S6OVERLAY_RELEASE https://github.com/just-containers/s6-overlay/releases/download/v1.19.1.1/s6-overlay-amd64.tar.gz
|
||||||
|
|
||||||
ENV TINI_VERSION v0.13.0
|
RUN apt-get update && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
|
apt-get install -y wget curl net-tools cron && \
|
||||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc /tini.asc
|
curl -L -s $S6OVERLAY_RELEASE \
|
||||||
|
| tar xvzf - -C / && \
|
||||||
RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 0527A9B7 && \
|
docker-install.sh && \
|
||||||
gpg --verify /tini.asc && \
|
|
||||||
chmod +x /tini && \
|
|
||||||
apt-get -q update && \
|
|
||||||
apt-get install -y wget net-tools && \
|
|
||||||
/install.sh && \
|
|
||||||
rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
rm -rf /var/cache/apt/archives /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/init" ]
|
||||||
|
|
||||||
|
ADD s6/debian-root /
|
||||||
|
COPY s6/service /usr/local/bin/service
|
||||||
|
|
||||||
# php config start passes special ENVs into
|
# php config start passes special ENVs into
|
||||||
ENV PHP_ENV_CONFIG '/etc/lighttpd/conf-enabled/15-fastcgi-php.conf'
|
ENV PHP_ENV_CONFIG '/etc/lighttpd/conf-enabled/15-fastcgi-php.conf'
|
||||||
ENV PHP_ERROR_LOG '/var/log/lighttpd/error.log'
|
ENV PHP_ERROR_LOG '/var/log/lighttpd/error.log'
|
||||||
|
@ -33,6 +34,8 @@ ENV IPv6 True
|
||||||
EXPOSE 53 53/udp
|
EXPOSE 53 53/udp
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
|
ENV S6_LOGGING 0
|
||||||
|
ENV S6_KEEP_ENV 1
|
||||||
|
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS 2
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-c"]
|
SHELL ["/bin/bash", "-c"]
|
||||||
ENTRYPOINT ["/tini", "--"]
|
|
||||||
CMD [ "/start.sh" ]
|
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
IMAGE=${1:-'diginc/pi-hole:alpine'}
|
IMAGE=${1:-'diginc/pi-hole:alpine'}
|
||||||
IP_LOOKUP="$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')" # May not work for VPN / tun0
|
IP_LOOKUP="$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')" # May not work for VPN / tun0
|
||||||
|
IPv6_LOOKUP="$(ip -6 route get 2001:4860:4860::8888 | awk '{ print $10; exit }')" # May not work for VPN / tun0
|
||||||
IP="${IP:-$IP_LOOKUP}" # use $IP, if set, otherwise IP_LOOKUP
|
IP="${IP:-$IP_LOOKUP}" # use $IP, if set, otherwise IP_LOOKUP
|
||||||
|
IPv6="${IPv6:-$IPv6_LOOKUP}" # use $IPv6, if set, otherwise IP_LOOKUP
|
||||||
|
|
||||||
|
echo "IP: ${IP} - IPv6: ${IPv6}"
|
||||||
|
|
||||||
# Default ports + daemonized docker container
|
# Default ports + daemonized docker container
|
||||||
docker run -p 53:53/tcp -p 53:53/udp -p 80:80 \
|
docker run -d \
|
||||||
--cap-add=NET_ADMIN \
|
|
||||||
-e ServerIP="$IP" \
|
|
||||||
--name pihole \
|
--name pihole \
|
||||||
|
-p 53:53/tcp -p 53:53/udp -p 80:80 \
|
||||||
|
-v /etc/volumes/pihole:/etc/pihole \
|
||||||
|
-v /etc/volumes/dnsmasq.d:/etc/dnsmasq.d \
|
||||||
|
-e ServerIP="${IP:-$(ip route get 8.8.8.8 | awk '{ print $NF; exit }')}" \
|
||||||
|
-e ServerIPv6="${IPv6:-$(ip -6 route get 2001:4860:4860::8888 | awk '{ print $10; exit }')}" \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
-d "$IMAGE"
|
diginc/pi-hole
|
||||||
|
|
||||||
|
docker logs pihole 2> /dev/null | grep 'password:'
|
||||||
|
|
24
install.sh
24
install.sh
|
@ -1,7 +1,8 @@
|
||||||
#!/bin/bash -x
|
#!/bin/bash -ex
|
||||||
mkdir -p /etc/pihole/
|
mkdir -p /etc/pihole/
|
||||||
export CORE_TAG='v2.13.2'
|
export CORE_TAG='v3.0.1'
|
||||||
export WEB_TAG='v2.5.2'
|
export WEB_TAG='v3.0.1'
|
||||||
|
export FTL_TAG='v2.7'
|
||||||
|
|
||||||
# Make pihole scripts fail searching for `systemctl`,
|
# Make pihole scripts fail searching for `systemctl`,
|
||||||
# which fails pretty miserably in docker compared to `service`
|
# which fails pretty miserably in docker compared to `service`
|
||||||
|
@ -21,6 +22,11 @@ if [[ "$IMAGE" == 'alpine' ]] ; then
|
||||||
sed -i 's/www-data/nginx/g' "$PIHOLE_INSTALL"
|
sed -i 's/www-data/nginx/g' "$PIHOLE_INSTALL"
|
||||||
sed -i '/LIGHTTPD_CFG/d' "${PIHOLE_INSTALL}"
|
sed -i '/LIGHTTPD_CFG/d' "${PIHOLE_INSTALL}"
|
||||||
sed -i '/etc\/cron.d\//d' "${PIHOLE_INSTALL}"
|
sed -i '/etc\/cron.d\//d' "${PIHOLE_INSTALL}"
|
||||||
|
# For new FTL install lines
|
||||||
|
sed -i 's/sha1sum --status --quiet/sha1sum -s/g' "${PIHOLE_INSTALL}"
|
||||||
|
sed -i 's/install -T/install /g' "${PIHOLE_INSTALL}"
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sed -i '/FTLinstall/ s/${binary}/pihole-FTL-musl-linux-x86_64/g' "${PIHOLE_INSTALL}"
|
||||||
LIGHTTPD_USER="nginx" # shellcheck disable=SC2034
|
LIGHTTPD_USER="nginx" # shellcheck disable=SC2034
|
||||||
LIGHTTPD_GROUP="nginx" # shellcheck disable=SC2034
|
LIGHTTPD_GROUP="nginx" # shellcheck disable=SC2034
|
||||||
LIGHTTPD_CFG="lighttpd.conf.debian" # shellcheck disable=SC2034
|
LIGHTTPD_CFG="lighttpd.conf.debian" # shellcheck disable=SC2034
|
||||||
|
@ -36,13 +42,17 @@ if [[ "$IMAGE" == 'debian' ]] ; then
|
||||||
install_dependent_packages PIHOLE_DEPS[@]
|
install_dependent_packages PIHOLE_DEPS[@]
|
||||||
install_dependent_packages PIHOLE_WEB_DEPS[@]
|
install_dependent_packages PIHOLE_WEB_DEPS[@]
|
||||||
sed -i "/sleep 2/ d" /etc/init.d/dnsmasq # SLOW
|
sed -i "/sleep 2/ d" /etc/init.d/dnsmasq # SLOW
|
||||||
|
# IPv6 support for nc openbsd better than traditional
|
||||||
|
apt-get install -y --force-yes netcat-openbsd
|
||||||
elif [[ "$IMAGE" == 'alpine' ]] ; then
|
elif [[ "$IMAGE" == 'alpine' ]] ; then
|
||||||
apk add \
|
apk add \
|
||||||
dnsmasq \
|
dnsmasq \
|
||||||
nginx \
|
nginx \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
php5-fpm php5-json php5-openssl php5-zip libxml2 \
|
php5-fpm php5-json php5-openssl php5-zip php5-sockets libxml2 \
|
||||||
bc bash curl perl sudo git
|
bc bash curl perl sudo git
|
||||||
|
# S6 service like to be blocking/foreground
|
||||||
|
sed -i 's|^;daemonize = yes|daemonize = no|' /etc/php5/php-fpm.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
piholeGitUrl="${piholeGitUrl}"
|
piholeGitUrl="${piholeGitUrl}"
|
||||||
|
@ -64,9 +74,13 @@ tmpLog="${tmpLog}"
|
||||||
instalLogLoc="${instalLogLoc}"
|
instalLogLoc="${instalLogLoc}"
|
||||||
installPihole | tee "${tmpLog}"
|
installPihole | tee "${tmpLog}"
|
||||||
sed -i 's/readonly //g' /opt/pihole/webpage.sh
|
sed -i 's/readonly //g' /opt/pihole/webpage.sh
|
||||||
|
if [[ "$IMAGE" == 'alpine' ]] ; then
|
||||||
|
cp /etc/.pihole/advanced/pihole.cron /etc/crontabs/pihole
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
mv "${tmpLog}" "${instalLogLoc}"
|
mv "${tmpLog}" "${instalLogLoc}"
|
||||||
|
|
||||||
# Fix dnsmasq in docker
|
# Fix dnsmasq in docker
|
||||||
grep -q '^user=root' || echo -e '\nuser=root' >> /etc/dnsmasq.conf
|
grep -q '^user=root' || echo -e '\nuser=root' >> /etc/dnsmasq.conf
|
||||||
echo 'done'
|
echo 'Docker install successful'
|
||||||
|
|
10
s6/alpine-root/etc/cont-init.d/20-start.sh
Normal file
10
s6/alpine-root/etc/cont-init.d/20-start.sh
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
# Early DNS Startup for the gravity list process to use
|
||||||
|
dnsmasq -7 /etc/dnsmasq.d
|
||||||
|
|
||||||
|
/start.sh
|
||||||
|
gravity.sh
|
||||||
|
|
||||||
|
# Done with DNS, let s6 services start up properly configured dns now
|
||||||
|
killall -9 dnsmasq
|
1
s6/alpine-root/etc/fix-attrs.d/01-resolver-resolv
Normal file
1
s6/alpine-root/etc/fix-attrs.d/01-resolver-resolv
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/etc/resolv.conf false doesntexist,0:1000 0664 0664
|
|
@ -12,8 +12,10 @@ http {
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
# PHP SERVER_NAME is empty unless set, which can bug out ipv6less setups
|
||||||
listen [::]:80;
|
server_name dockerpi.hole;
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
root /var/www/html;
|
root /var/www/html;
|
||||||
index pihole/index.php index.php;
|
index pihole/index.php index.php;
|
||||||
error_page 404 =200 /pihole/index.php;
|
error_page 404 =200 /pihole/index.php;
|
5
s6/alpine-root/etc/services.d/cron/run
Normal file
5
s6/alpine-root/etc/services.d/cron/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
s6-echo "Starting crond"
|
||||||
|
|
||||||
|
exec -c
|
||||||
|
fdmove -c 2 1 /usr/sbin/crond -f -L /var/log/cron -l 0 -c /etc/crontabs
|
3
s6/alpine-root/etc/services.d/dnsmasq/finish
Normal file
3
s6/alpine-root/etc/services.d/dnsmasq/finish
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
kill -9 $(pgrep dnsmasq)
|
5
s6/alpine-root/etc/services.d/dnsmasq/run
Normal file
5
s6/alpine-root/etc/services.d/dnsmasq/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting dnsmasq"
|
||||||
|
|
||||||
|
s6-setuidgid dnsmasq dnsmasq -7 /etc/dnsmasq.d --no-daemon
|
6
s6/alpine-root/etc/services.d/nginx/run
Normal file
6
s6/alpine-root/etc/services.d/nginx/run
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-svwait -u -t 5000 /var/run/s6/services/php-fpm
|
||||||
|
s6-echo "Starting nginx"
|
||||||
|
|
||||||
|
nginx -g "daemon off;"
|
5
s6/alpine-root/etc/services.d/php-fpm/run
Normal file
5
s6/alpine-root/etc/services.d/php-fpm/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting php-fpm"
|
||||||
|
|
||||||
|
php-fpm5 -d daemonize=no
|
4
s6/alpine-root/etc/services.d/pihole-FTL/run
Normal file
4
s6/alpine-root/etc/services.d/pihole-FTL/run
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting pihole-FTL"
|
||||||
|
pihole-FTL no-daemon
|
10
s6/alpine-root/usr/bin/host-ip
Executable file
10
s6/alpine-root/usr/bin/host-ip
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/with-contenv sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script will determine the network IP of the container.
|
||||||
|
#
|
||||||
|
# Return format should be a single IP address.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Default to using the value of the $HOSTNAME ENV variable.
|
||||||
|
getent hosts ${1:-$HOSTNAME} | awk '{print $1}'
|
235
s6/alpine-root/usr/bin/list.sh
Executable file
235
s6/alpine-root/usr/bin/list.sh
Executable file
|
@ -0,0 +1,235 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Pi-hole: A black hole for Internet advertisements
|
||||||
|
# (c) 2017 Pi-hole, LLC (https://pi-hole.net)
|
||||||
|
# Network-wide ad blocking via your own hardware.
|
||||||
|
#
|
||||||
|
# Whitelists and blacklists domains
|
||||||
|
#
|
||||||
|
# This file is copyright under the latest version of the EUPL.
|
||||||
|
# Please see LICENSE file for your rights under this license.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#globals
|
||||||
|
basename=pihole
|
||||||
|
piholeDir=/etc/${basename}
|
||||||
|
whitelist=${piholeDir}/whitelist.txt
|
||||||
|
blacklist=${piholeDir}/blacklist.txt
|
||||||
|
readonly wildcardlist="/etc/dnsmasq.d/03-pihole-wildcard.conf"
|
||||||
|
reload=false
|
||||||
|
addmode=true
|
||||||
|
verbose=true
|
||||||
|
|
||||||
|
domList=()
|
||||||
|
domToRemoveList=()
|
||||||
|
|
||||||
|
listMain=""
|
||||||
|
listAlt=""
|
||||||
|
|
||||||
|
helpFunc() {
|
||||||
|
|
||||||
|
if [[ ${listMain} == ${whitelist} ]]; then
|
||||||
|
letter="w"
|
||||||
|
word="white"
|
||||||
|
else
|
||||||
|
letter="b"
|
||||||
|
word="black"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat << EOM
|
||||||
|
::: Immediately ${word}lists one or more domains in the hosts file
|
||||||
|
:::
|
||||||
|
::: Usage: pihole -${letter} domain1 [domain2 ...]
|
||||||
|
:::
|
||||||
|
::: Options:
|
||||||
|
::: -d, --delmode Remove domains from the ${word}list
|
||||||
|
::: -nr, --noreload Update ${word}list without refreshing dnsmasq
|
||||||
|
::: -q, --quiet Output is less verbose
|
||||||
|
::: -h, --help Show this help dialog
|
||||||
|
::: -l, --list Display your ${word}listed domains
|
||||||
|
EOM
|
||||||
|
if [[ "${letter}" == "b" ]]; then
|
||||||
|
echo "::: -wild, --wildcard Add wildcard entry (only blacklist)"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
EscapeRegexp() {
|
||||||
|
# This way we may safely insert an arbitrary
|
||||||
|
# string in our regular expressions
|
||||||
|
# Also remove leading "." if present
|
||||||
|
echo $* | sed 's/^\.*//' | sed "s/[]\.|$(){}?+*^]/\\\\&/g" | sed "s/\\//\\\\\//g"
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleOther(){
|
||||||
|
# First, convert everything to lowercase
|
||||||
|
domain=$(sed -e "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/" <<< "$1")
|
||||||
|
|
||||||
|
#check validity of domain
|
||||||
|
validDomain=$(echo "${domain}" | perl -lne 'print if /(?!.*[^a-z0-9-\.].*)^((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9-]+\.)*[a-z]{2,63}/')
|
||||||
|
if [ -z "${validDomain}" ]; then
|
||||||
|
echo "::: $1 is not a valid argument or domain name"
|
||||||
|
else
|
||||||
|
domList=("${domList[@]}" ${validDomain})
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
PoplistFile() {
|
||||||
|
#check whitelist file exists, and if not, create it
|
||||||
|
if [[ ! -f ${whitelist} ]]; then
|
||||||
|
touch ${whitelist}
|
||||||
|
fi
|
||||||
|
for dom in "${domList[@]}"; do
|
||||||
|
# Logic : If addmode then add to desired list and remove from the other; if delmode then remove from desired list but do not add to the other
|
||||||
|
if ${addmode}; then
|
||||||
|
AddDomain "${dom}" "${listMain}"
|
||||||
|
RemoveDomain "${dom}" "${listAlt}"
|
||||||
|
if [[ "${listMain}" == "${whitelist}" || "${listMain}" == "${blacklist}" ]]; then
|
||||||
|
RemoveDomain "${dom}" "${wildcardlist}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
RemoveDomain "${dom}" "${listMain}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
AddDomain() {
|
||||||
|
list="$2"
|
||||||
|
domain=$(EscapeRegexp "$1")
|
||||||
|
|
||||||
|
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
|
||||||
|
|
||||||
|
bool=true
|
||||||
|
#Is the domain in the list we want to add it to?
|
||||||
|
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
|
||||||
|
|
||||||
|
if [[ "${bool}" == false ]]; then
|
||||||
|
#domain not found in the whitelist file, add it!
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: Adding $1 to $list..."
|
||||||
|
fi
|
||||||
|
reload=true
|
||||||
|
# Add it to the list we want to add it to
|
||||||
|
echo "$1" >> "${list}"
|
||||||
|
else
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: ${1} already exists in ${list}, no need to add!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ "${list}" == "${wildcardlist}" ]]; then
|
||||||
|
|
||||||
|
source "${piholeDir}/setupVars.conf"
|
||||||
|
#Remove the /* from the end of the IPv4addr.
|
||||||
|
IPV4_ADDRESS=${IPV4_ADDRESS%/*}
|
||||||
|
IPV6_ADDRESS=${IPV6_ADDRESS}
|
||||||
|
|
||||||
|
bool=true
|
||||||
|
#Is the domain in the list?
|
||||||
|
grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false
|
||||||
|
|
||||||
|
if [[ "${bool}" == false ]]; then
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: Adding $1 to wildcard blacklist..."
|
||||||
|
fi
|
||||||
|
reload=true
|
||||||
|
echo "address=/$1/${IPV4_ADDRESS}" >> "${wildcardlist}"
|
||||||
|
if [[ ${#IPV6_ADDRESS} > 0 ]] ; then
|
||||||
|
echo "address=/$1/${IPV6_ADDRESS}" >> "${wildcardlist}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: ${1} already exists in wildcard blacklist, no need to add!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveDomain() {
|
||||||
|
list="$2"
|
||||||
|
domain=$(EscapeRegexp "$1")
|
||||||
|
|
||||||
|
if [[ "${list}" == "${whitelist}" || "${list}" == "${blacklist}" ]]; then
|
||||||
|
|
||||||
|
bool=true
|
||||||
|
#Is it in the list? Logic follows that if its whitelisted it should not be blacklisted and vice versa
|
||||||
|
grep -Ex -q "${domain}" "${list}" > /dev/null 2>&1 || bool=false
|
||||||
|
if [[ "${bool}" == true ]]; then
|
||||||
|
# Remove it from the other one
|
||||||
|
echo "::: Removing $1 from $list..."
|
||||||
|
# Busybox sed compatible case-insensitive domain removal
|
||||||
|
sed -i "$(grep -in "^${domain}$" ${list} | awk -F':' '{print $1}' | tr '\n' ',' | sed 's/,$/\n/')d" ${list}
|
||||||
|
reload=true
|
||||||
|
else
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: ${1} does not exist in ${list}, no need to remove!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ "${list}" == "${wildcardlist}" ]]; then
|
||||||
|
|
||||||
|
bool=true
|
||||||
|
#Is it in the list?
|
||||||
|
grep -e "address=\/${domain}\/" "${wildcardlist}" > /dev/null 2>&1 || bool=false
|
||||||
|
if [[ "${bool}" == true ]]; then
|
||||||
|
# Remove it from the other one
|
||||||
|
echo "::: Removing $1 from $list..."
|
||||||
|
# Busybox sed compatible case-insensitive domain removal
|
||||||
|
sed -i "$(grep -in "/${domain}/" ${list} | awk -F':' '{print $1}' | tr '\n' ',' | sed 's/,$/\n/')d" ${list}
|
||||||
|
reload=true
|
||||||
|
else
|
||||||
|
if [[ "${verbose}" == true ]]; then
|
||||||
|
echo "::: ${1} does not exist in ${list}, no need to remove!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Reload() {
|
||||||
|
# Reload hosts file
|
||||||
|
pihole -g -sd
|
||||||
|
}
|
||||||
|
|
||||||
|
Displaylist() {
|
||||||
|
if [[ ${listMain} == ${whitelist} ]]; then
|
||||||
|
string="gravity resistant domains"
|
||||||
|
else
|
||||||
|
string="domains caught in the sinkhole"
|
||||||
|
fi
|
||||||
|
verbose=false
|
||||||
|
echo -e " Displaying $string \n"
|
||||||
|
count=1
|
||||||
|
while IFS= read -r RD; do
|
||||||
|
echo "${count}: ${RD}"
|
||||||
|
count=$((count+1))
|
||||||
|
done < "${listMain}"
|
||||||
|
exit 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for var in "$@"; do
|
||||||
|
case "${var}" in
|
||||||
|
"-w" | "whitelist" ) listMain="${whitelist}"; listAlt="${blacklist}";;
|
||||||
|
"-b" | "blacklist" ) listMain="${blacklist}"; listAlt="${whitelist}";;
|
||||||
|
"-wild" | "wildcard" ) listMain="${wildcardlist}";;
|
||||||
|
"-nr"| "--noreload" ) reload=false;;
|
||||||
|
"-d" | "--delmode" ) addmode=false;;
|
||||||
|
"-f" | "--force" ) force=true;;
|
||||||
|
"-q" | "--quiet" ) verbose=false;;
|
||||||
|
"-h" | "--help" ) helpFunc;;
|
||||||
|
"-l" | "--list" ) Displaylist;;
|
||||||
|
* ) HandleOther "${var}";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [[ $# = 0 ]]; then
|
||||||
|
helpFunc
|
||||||
|
fi
|
||||||
|
|
||||||
|
PoplistFile
|
||||||
|
|
||||||
|
if ${reload}; then
|
||||||
|
Reload
|
||||||
|
fi
|
||||||
|
|
12
s6/alpine-root/usr/bin/set-contenv
Executable file
12
s6/alpine-root/usr/bin/set-contenv
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/execlineb -S0
|
||||||
|
|
||||||
|
if { s6-test $# -eq 2 }
|
||||||
|
|
||||||
|
backtick -in FILENAME {
|
||||||
|
pipeline { s6-echo "${1}" }
|
||||||
|
tr "a-z" "A-Z"
|
||||||
|
}
|
||||||
|
import -u FILENAME
|
||||||
|
|
||||||
|
redirfd -w 1 /var/run/s6/container_environment/${FILENAME}
|
||||||
|
s6-echo -n -- ${2}
|
10
s6/debian-root/etc/cont-init.d/20-start.sh
Normal file
10
s6/debian-root/etc/cont-init.d/20-start.sh
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
# Early DNS Startup for the gravity list process to use
|
||||||
|
dnsmasq -7 /etc/dnsmasq.d
|
||||||
|
|
||||||
|
/start.sh
|
||||||
|
gravity.sh
|
||||||
|
|
||||||
|
# Done with DNS, let s6 services start up properly configured dns now
|
||||||
|
killall -9 dnsmasq
|
1
s6/debian-root/etc/fix-attrs.d/01-resolver-resolv
Normal file
1
s6/debian-root/etc/fix-attrs.d/01-resolver-resolv
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/etc/resolv.conf false doesntexist,0:1000 0664 0664
|
5
s6/debian-root/etc/services.d/cron/run
Normal file
5
s6/debian-root/etc/services.d/cron/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
s6-echo "Starting crond"
|
||||||
|
|
||||||
|
exec -c
|
||||||
|
fdmove -c 2 1 /usr/sbin/cron -f
|
3
s6/debian-root/etc/services.d/dnsmasq/finish
Normal file
3
s6/debian-root/etc/services.d/dnsmasq/finish
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
kill -9 $(pgrep dnsmasq)
|
5
s6/debian-root/etc/services.d/dnsmasq/run
Normal file
5
s6/debian-root/etc/services.d/dnsmasq/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting dnsmasq"
|
||||||
|
|
||||||
|
s6-setuidgid root dnsmasq -7 /etc/dnsmasq.d --no-daemon
|
5
s6/debian-root/etc/services.d/lighttpd/run
Normal file
5
s6/debian-root/etc/services.d/lighttpd/run
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting lighttpd"
|
||||||
|
|
||||||
|
lighttpd -D -f /etc/lighttpd/lighttpd.conf
|
4
s6/debian-root/etc/services.d/pihole-FTL/run
Normal file
4
s6/debian-root/etc/services.d/pihole-FTL/run
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
s6-echo "Starting pihole-FTL"
|
||||||
|
pihole-FTL no-daemon
|
10
s6/debian-root/usr/bin/host-ip
Executable file
10
s6/debian-root/usr/bin/host-ip
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/with-contenv sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# This script will determine the network IP of the container.
|
||||||
|
#
|
||||||
|
# Return format should be a single IP address.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Default to using the value of the $HOSTNAME ENV variable.
|
||||||
|
getent hosts ${1:-$HOSTNAME} | awk '{print $1}'
|
12
s6/debian-root/usr/bin/set-contenv
Executable file
12
s6/debian-root/usr/bin/set-contenv
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/execlineb -S0
|
||||||
|
|
||||||
|
if { s6-test $# -eq 2 }
|
||||||
|
|
||||||
|
backtick -in FILENAME {
|
||||||
|
pipeline { s6-echo "${1}" }
|
||||||
|
tr "a-z" "A-Z"
|
||||||
|
}
|
||||||
|
import -u FILENAME
|
||||||
|
|
||||||
|
redirfd -w 1 /var/run/s6/container_environment/${FILENAME}
|
||||||
|
s6-echo -n -- ${2}
|
30
s6/service
Executable file
30
s6/service
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This script patches all service commands into the appropriate s6- commands
|
||||||
|
# pi-hole upstream scripts need a 'service' interface. why not systemd? docker said so.
|
||||||
|
start() {
|
||||||
|
s6-svc -wU -u -T2500 /var/run/s6/services/$service
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
s6-svc -wD -d -T2500 /var/run/s6/services/$service
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
#s6-svc -t -wR -T5000 /var/run/s6/services/$service
|
||||||
|
}
|
||||||
|
|
||||||
|
status() {
|
||||||
|
s6-svstat /var/run/s6/services/$service
|
||||||
|
}
|
||||||
|
|
||||||
|
service="$1"
|
||||||
|
command="$2"
|
||||||
|
|
||||||
|
if [[ ! -d "/var/run/s6/services/$service" ]] ; then
|
||||||
|
echo "s6 service not found for $service, exiting..."
|
||||||
|
exit
|
||||||
|
fi;
|
||||||
|
|
||||||
|
${command} "${service}"
|
5
start.sh
5
start.sh
|
@ -16,7 +16,7 @@ export IPv6
|
||||||
. /bash_functions.sh
|
. /bash_functions.sh
|
||||||
|
|
||||||
echo " ::: Starting docker specific setup for docker diginc/pi-hole"
|
echo " ::: Starting docker specific setup for docker diginc/pi-hole"
|
||||||
validate_env
|
validate_env || exit 1
|
||||||
prepare_setup_vars
|
prepare_setup_vars
|
||||||
change_setting "IPV4_ADDRESS" "$ServerIP"
|
change_setting "IPV4_ADDRESS" "$ServerIP"
|
||||||
change_setting "IPV6_ADDRESS" "$ServerIPv6"
|
change_setting "IPV6_ADDRESS" "$ServerIPv6"
|
||||||
|
@ -27,5 +27,6 @@ setup_dnsmasq_hostnames "$ServerIP" "$ServerIPv6" "$HOSTNAME"
|
||||||
setup_ipv4_ipv6
|
setup_ipv4_ipv6
|
||||||
test_configs
|
test_configs
|
||||||
test_framework_stubbing
|
test_framework_stubbing
|
||||||
|
echo "::: Docker start setup complete - beginning s6 services"
|
||||||
|
|
||||||
docker_main "$IMAGE"
|
# s6's init takes care of running services now, no more main start services function
|
||||||
|
|
|
@ -10,12 +10,14 @@ check_output = testinfra.get_backend(
|
||||||
def DockerGeneric(request, args, image, cmd):
|
def DockerGeneric(request, args, image, cmd):
|
||||||
assert 'docker' in check_output('id'), "Are you in the docker group?"
|
assert 'docker' in check_output('id'), "Are you in the docker group?"
|
||||||
if 'diginc/pi-hole' in image:
|
if 'diginc/pi-hole' in image:
|
||||||
args += " -v /dev/null:/etc/pihole/adlists.default -e PYTEST=\"True\""
|
args += " --dns 127.0.0.1 -v /dev/null:/etc/.pihole/adlists.default -e PYTEST=\"True\""
|
||||||
docker_run = "docker run -d {} {} {}".format(args, image, cmd)
|
docker_run = "docker run -d {} {} {}".format(args, image, cmd)
|
||||||
|
print docker_run
|
||||||
docker_id = check_output(docker_run)
|
docker_id = check_output(docker_run)
|
||||||
|
|
||||||
def teardown():
|
def teardown():
|
||||||
check_output("docker rm -f %s", docker_id)
|
check_output("docker logs {}".format(docker_id))
|
||||||
|
check_output("docker rm -f {}".format(docker_id))
|
||||||
request.addfinalizer(teardown)
|
request.addfinalizer(teardown)
|
||||||
|
|
||||||
docker_container = testinfra.get_backend("docker://" + docker_id)
|
docker_container = testinfra.get_backend("docker://" + docker_id)
|
||||||
|
@ -42,7 +44,7 @@ def Docker(request, args, image, cmd):
|
||||||
''' One-off Docker container run '''
|
''' One-off Docker container run '''
|
||||||
return DockerGeneric(request, args, image, cmd)
|
return DockerGeneric(request, args, image, cmd)
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def DockerPersist(request, persist_args, persist_image, persist_cmd, Dig):
|
def DockerPersist(request, persist_args, persist_image, persist_cmd, Dig):
|
||||||
''' Persistent Docker container for multiple tests '''
|
''' Persistent Docker container for multiple tests '''
|
||||||
persistent_container = DockerGeneric(request, persist_args, persist_image, persist_cmd)
|
persistent_container = DockerGeneric(request, persist_args, persist_image, persist_cmd)
|
||||||
|
@ -52,7 +54,7 @@ def DockerPersist(request, persist_args, persist_image, persist_cmd, Dig):
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def args(request):
|
def args(request):
|
||||||
return '-e ServerIP="192.168.100.2"'
|
return '-e ServerIP="127.0.0.1" -e ServerIPv6="::1"'
|
||||||
|
|
||||||
@pytest.fixture(params=['alpine', 'debian'])
|
@pytest.fixture(params=['alpine', 'debian'])
|
||||||
def tag(request):
|
def tag(request):
|
||||||
|
@ -68,27 +70,27 @@ def image(request, tag):
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def cmd(request):
|
def cmd(request):
|
||||||
return '/start.sh'
|
return 'tail -f /dev/null'
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def persist_args(request):
|
def persist_args(request):
|
||||||
return '-e ServerIP="192.168.100.2"'
|
return '-e ServerIP="127.0.0.1" -e ServerIPv6="::1"'
|
||||||
|
|
||||||
@pytest.fixture(scope='session', params=['alpine', 'debian'])
|
@pytest.fixture(scope='module', params=['alpine', 'debian'])
|
||||||
def persist_tag(request):
|
def persist_tag(request):
|
||||||
return request.param
|
return request.param
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def persist_webserver(request, persist_tag):
|
def persist_webserver(request, persist_tag):
|
||||||
return WEB_SERVER[persist_tag]
|
return WEB_SERVER[persist_tag]
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def persist_image(request, persist_tag):
|
def persist_image(request, persist_tag):
|
||||||
return 'diginc/pi-hole:{}'.format(persist_tag)
|
return 'diginc/pi-hole:{}'.format(persist_tag)
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def persist_cmd(request):
|
def persist_cmd(request):
|
||||||
return '/start.sh'
|
return 'tail -f /dev/null'
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def Slow():
|
def Slow():
|
||||||
|
@ -96,7 +98,7 @@ def Slow():
|
||||||
Run a slow check, check if the state is correct for `timeout` seconds.
|
Run a slow check, check if the state is correct for `timeout` seconds.
|
||||||
"""
|
"""
|
||||||
import time
|
import time
|
||||||
def slow(check, timeout=5):
|
def slow(check, timeout=20):
|
||||||
timeout_at = time.time() + timeout
|
timeout_at = time.time() + timeout
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -110,7 +112,7 @@ def Slow():
|
||||||
return
|
return
|
||||||
return slow
|
return slow
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='module')
|
||||||
def Dig(request):
|
def Dig(request):
|
||||||
''' separate container to link to pi-hole and perform lookups '''
|
''' separate container to link to pi-hole and perform lookups '''
|
||||||
''' a docker pull is faster than running an install of dnsutils '''
|
''' a docker pull is faster than running an install of dnsutils '''
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
import pytest
|
import pytest
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# Override these docker command pieces to minimize parameter repititon
|
DEFAULTARGS = '-e ServerIP="127.0.0.1" '
|
||||||
@pytest.fixture()
|
|
||||||
def cmd(request):
|
|
||||||
return 'tail -f /dev/null'
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('args,expected_ipv6,expected_stdout', [
|
@pytest.mark.parametrize('args,expected_ipv6,expected_stdout', [
|
||||||
('-e ServerIP="1.2.3.4"', True, 'IPv4 and IPv6'),
|
(DEFAULTARGS, True, 'IPv4 and IPv6'),
|
||||||
('-e ServerIP="1.2.3.4" -e "IPv6=True"', True, 'IPv4 and IPv6'),
|
(DEFAULTARGS + '-e "IPv6=True"', True, 'IPv4 and IPv6'),
|
||||||
('-e ServerIP="1.2.3.4" -e "IPv6=False"', False, 'IPv4'),
|
(DEFAULTARGS + '-e "IPv6=False"', False, 'IPv4'),
|
||||||
('-e ServerIP="1.2.3.4" -e "IPv6=foobar"', False, 'IPv4'),
|
(DEFAULTARGS + '-e "IPv6=foobar"', False, 'IPv4'),
|
||||||
])
|
])
|
||||||
def test_IPv6_not_True_removes_ipv6(Docker, tag, args, expected_ipv6, expected_stdout):
|
def test_IPv6_not_True_removes_ipv6(Docker, tag, args, expected_ipv6, expected_stdout):
|
||||||
''' When a user overrides IPv6=True they only get IPv4 listening webservers '''
|
''' When a user overrides IPv6=True they only get IPv4 listening webservers '''
|
||||||
IPV6_LINE = { 'alpine': 'listen \[::\]:80',
|
IPV6_LINE = { 'alpine': 'listen [::]:80 default_server',
|
||||||
'debian': 'use-ipv6.pl' }
|
'debian': 'use-ipv6.pl' }
|
||||||
WEB_CONFIG = { 'alpine': '/etc/nginx/nginx.conf',
|
WEB_CONFIG = { 'alpine': '/etc/nginx/nginx.conf',
|
||||||
'debian': '/etc/lighttpd/lighttpd.conf' }
|
'debian': '/etc/lighttpd/lighttpd.conf' }
|
||||||
|
|
||||||
function = Docker.run('. /bash_functions.sh ; setup_ipv4_ipv6')
|
function = Docker.run('. /bash_functions.sh ; setup_ipv4_ipv6')
|
||||||
assert "Using {}".format(expected_stdout) in function.stdout
|
assert "Using {}".format(expected_stdout) in function.stdout
|
||||||
ipv6 = Docker.run('grep -q \'{}\' {}'.format(IPV6_LINE[tag], WEB_CONFIG[tag])).rc == 0
|
config = Docker.run('cat {}'.format( WEB_CONFIG[tag])).stdout
|
||||||
assert ipv6 == expected_ipv6
|
assert (IPV6_LINE[tag] in config) == expected_ipv6
|
||||||
|
|
||||||
@pytest.mark.parametrize('args, expected_stdout, dns1, dns2', [
|
@pytest.mark.parametrize('args, expected_stdout, dns1, dns2', [
|
||||||
('-e ServerIP="1.2.3.4"', 'default DNS', '8.8.8.8', '8.8.4.4' ),
|
('-e ServerIP="1.2.3.4"', 'default DNS', '8.8.8.8', '8.8.4.4' ),
|
||||||
|
@ -53,8 +50,8 @@ def test_DNS_interface_override_defaults(Docker, args, expected_stdout, expected
|
||||||
assert expected_config_line + '\n' == docker_dns_interface
|
assert expected_config_line + '\n' == docker_dns_interface
|
||||||
|
|
||||||
expected_debian_lines = [
|
expected_debian_lines = [
|
||||||
'"VIRTUAL_HOST" => "192.168.100.2"',
|
'"VIRTUAL_HOST" => "127.0.0.1"',
|
||||||
'"ServerIP" => "192.168.100.2"',
|
'"ServerIP" => "127.0.0.1"',
|
||||||
'"PHP_ERROR_LOG" => "/var/log/lighttpd/error.log"'
|
'"PHP_ERROR_LOG" => "/var/log/lighttpd/error.log"'
|
||||||
]
|
]
|
||||||
@pytest.mark.parametrize('tag,expected_lines,repeat_function', [
|
@pytest.mark.parametrize('tag,expected_lines,repeat_function', [
|
||||||
|
@ -80,13 +77,13 @@ def test_webPassword_env_assigns_password_to_file(Docker, args, secure, setupVar
|
||||||
''' When a user sets webPassword env the admin password gets set to that '''
|
''' When a user sets webPassword env the admin password gets set to that '''
|
||||||
function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`')
|
function = Docker.run('. /bash_functions.sh ; eval `grep setup_web_password /start.sh`')
|
||||||
if secure and 'WEBPASSWORD' not in args:
|
if secure and 'WEBPASSWORD' not in args:
|
||||||
assert 'Assigning random password' in function.stdout
|
assert 'assigning random password' in function.stdout.lower()
|
||||||
else:
|
else:
|
||||||
assert 'Assigning random password' not in function.stdout
|
assert 'assigning random password' not in function.stdout.lower()
|
||||||
|
|
||||||
if secure:
|
if secure:
|
||||||
assert 'New password set' in function.stdout
|
assert 'new password set' in function.stdout.lower()
|
||||||
assert Docker.run('grep -q \'{}\' {}'.format(setupVarsHash, '/etc/pihole/setupVars.conf')).rc == 0
|
assert Docker.run('grep -q \'{}\' {}'.format(setupVarsHash, '/etc/pihole/setupVars.conf')).rc == 0
|
||||||
else:
|
else:
|
||||||
assert 'Password removed' in function.stdout
|
assert 'password removed' in function.stdout.lower()
|
||||||
assert Docker.run('grep -q \'^WEBPASSWORD=$\' /etc/pihole/setupVars.conf').rc == 0
|
assert Docker.run('grep -q \'^WEBPASSWORD=$\' /etc/pihole/setupVars.conf').rc == 0
|
||||||
|
|
|
@ -5,14 +5,11 @@ def start_cmd():
|
||||||
''' broken by default, required override '''
|
''' broken by default, required override '''
|
||||||
return None
|
return None
|
||||||
|
|
||||||
START_DNS_STDOUT = {
|
|
||||||
'alpine': '',
|
|
||||||
'debian': 'Restarting DNS forwarder and DHCP server: dnsmasq.\n'
|
|
||||||
}
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def RunningPiHole(DockerPersist, Slow, persist_webserver, persist_tag, start_cmd):
|
def RunningPiHole(DockerPersist, Slow, persist_webserver, persist_tag, start_cmd):
|
||||||
''' Override the RunningPiHole to run and check for success of a
|
''' Override the RunningPiHole to run and check for success of a
|
||||||
dnsmasq start based `pihole` script command '''
|
dnsmasq start based `pihole` script command '''
|
||||||
|
#print DockerPersist.run('ps -ef').stdout
|
||||||
Slow(lambda: DockerPersist.run('pgrep dnsmasq').rc == 0)
|
Slow(lambda: DockerPersist.run('pgrep dnsmasq').rc == 0)
|
||||||
Slow(lambda: DockerPersist.run('pgrep {}'.format(persist_webserver)).rc == 0)
|
Slow(lambda: DockerPersist.run('pgrep {}'.format(persist_webserver)).rc == 0)
|
||||||
oldpid = DockerPersist.run('pidof dnsmasq')
|
oldpid = DockerPersist.run('pidof dnsmasq')
|
||||||
|
@ -21,7 +18,7 @@ def RunningPiHole(DockerPersist, Slow, persist_webserver, persist_tag, start_cmd
|
||||||
newpid = DockerPersist.run('pidof dnsmasq')
|
newpid = DockerPersist.run('pidof dnsmasq')
|
||||||
for pid in [oldpid, newpid]:
|
for pid in [oldpid, newpid]:
|
||||||
assert pid != ''
|
assert pid != ''
|
||||||
# ensure a new pid for dnsmasq appeared
|
# ensure a new pid for dnsmasq appeared due to service restart
|
||||||
assert oldpid != newpid
|
assert oldpid != newpid
|
||||||
assert cmd.rc == 0
|
assert cmd.rc == 0
|
||||||
# Save out cmd result to check different stdout of start/enable/disable
|
# Save out cmd result to check different stdout of start/enable/disable
|
||||||
|
@ -34,8 +31,8 @@ def test_pihole_start_cmd(RunningPiHole, start_cmd, persist_tag):
|
||||||
assert RunningPiHole.cmd.stdout == START_DNS_STDOUT[persist_tag]
|
assert RunningPiHole.cmd.stdout == START_DNS_STDOUT[persist_tag]
|
||||||
|
|
||||||
@pytest.mark.parametrize('start_cmd,hostname,expected_ip', [
|
@pytest.mark.parametrize('start_cmd,hostname,expected_ip', [
|
||||||
('enable', 'pi.hole', '192.168.100.2'),
|
('enable', 'pi.hole', '127.0.0.1'),
|
||||||
('disable', 'pi.hole', '192.168.100.2'),
|
('disable', 'pi.hole', '127.0.0.1'),
|
||||||
])
|
])
|
||||||
def test_pihole_start_cmd(RunningPiHole, Dig, persist_tag, start_cmd, hostname, expected_ip):
|
def test_pihole_start_cmd(RunningPiHole, Dig, persist_tag, start_cmd, hostname, expected_ip):
|
||||||
''' the start_cmd tests are all built into the RunningPiHole fixture in this file '''
|
''' the start_cmd tests are all built into the RunningPiHole fixture in this file '''
|
||||||
|
@ -43,5 +40,5 @@ def test_pihole_start_cmd(RunningPiHole, Dig, persist_tag, start_cmd, hostname,
|
||||||
lookup = RunningPiHole.dig.run(dig_cmd).stdout.rstrip('\n')
|
lookup = RunningPiHole.dig.run(dig_cmd).stdout.rstrip('\n')
|
||||||
assert lookup == expected_ip
|
assert lookup == expected_ip
|
||||||
|
|
||||||
stdout = "::: Blocking has been {}d!\n{}".format(start_cmd, START_DNS_STDOUT[persist_tag])
|
stdout = "::: Blocking has been {}d!\n".format(start_cmd)
|
||||||
assert RunningPiHole.cmd.stdout == stdout
|
assert RunningPiHole.cmd.stdout == stdout
|
||||||
|
|
|
@ -7,7 +7,7 @@ run_local = testinfra.get_backend(
|
||||||
|
|
||||||
def test_scripts_pass_shellcheck():
|
def test_scripts_pass_shellcheck():
|
||||||
''' Make sure shellcheck does not find anything wrong with our shell scripts '''
|
''' Make sure shellcheck does not find anything wrong with our shell scripts '''
|
||||||
shellcheck = "find . -name '*.sh' | while read file; do shellcheck $file; done;"
|
shellcheck = "find . -name '*.sh' -a ! ( -name 'list.sh' ) | while read file; do shellcheck -e SC1008 $file; done;"
|
||||||
results = run_local(shellcheck)
|
results = run_local(shellcheck)
|
||||||
print results.stdout
|
print results.stdout
|
||||||
assert '' == results.stdout
|
assert '' == results.stdout
|
||||||
|
|
|
@ -14,7 +14,6 @@ def test_pihole_default_run_command(Docker, tag):
|
||||||
assert False, '{}: Couldn\'t find proc {}'.format(tag, expected_proc)
|
assert False, '{}: Couldn\'t find proc {}'.format(tag, expected_proc)
|
||||||
|
|
||||||
@pytest.mark.parametrize('args', [ '' ])
|
@pytest.mark.parametrize('args', [ '' ])
|
||||||
@pytest.mark.parametrize('cmd', [ 'tail -f /dev/null' ])
|
|
||||||
def test_ServerIP_missing_triggers_start_error(Docker):
|
def test_ServerIP_missing_triggers_start_error(Docker):
|
||||||
''' When args to docker are empty start.sh exits saying ServerIP is required '''
|
''' When args to docker are empty start.sh exits saying ServerIP is required '''
|
||||||
start = Docker.run('/start.sh')
|
start = Docker.run('/start.sh')
|
||||||
|
@ -22,8 +21,20 @@ def test_ServerIP_missing_triggers_start_error(Docker):
|
||||||
assert start.rc == 1
|
assert start.rc == 1
|
||||||
assert error_msg in start.stdout
|
assert error_msg in start.stdout
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('args,error_msg,expect_rc', [
|
||||||
|
('-e ServerIP="1.2.3.z"', "ServerIP Environment variable (1.2.3.z) doesn't appear to be a valid IPv4 address",1),
|
||||||
|
('-e ServerIP="1.2.3.4" -e ServerIPv6="1234:1234:1234:ZZZZ"', "Environment variable (1234:1234:1234:ZZZZ) doesn't appear to be a valid IPv6 address",1),
|
||||||
|
('-e ServerIP="1.2.3.4" -e ServerIPv6="kernel"', "WARNING: You passed in IPv6 with a value of 'kernel'",0),
|
||||||
|
])
|
||||||
|
def test_ServerIP_invalid_IPs_triggers_exit_error(Docker, error_msg, expect_rc):
|
||||||
|
''' When args to docker are empty start.sh exits saying ServerIP is required '''
|
||||||
|
start = Docker.run('/start.sh')
|
||||||
|
assert start.rc == expect_rc
|
||||||
|
assert 'ERROR' in start.stdout
|
||||||
|
assert error_msg in start.stdout
|
||||||
|
|
||||||
@pytest.mark.parametrize('hostname,expected_ip', [
|
@pytest.mark.parametrize('hostname,expected_ip', [
|
||||||
('pi.hole', '192.168.100.2'),
|
('pi.hole', '127.0.0.1'),
|
||||||
('google-public-dns-a.google.com', '8.8.8.8'),
|
('google-public-dns-a.google.com', '8.8.8.8'),
|
||||||
('b.resolvers.Level3.net', '4.2.2.2')
|
('b.resolvers.Level3.net', '4.2.2.2')
|
||||||
])
|
])
|
||||||
|
@ -37,28 +48,32 @@ def test_indecies_are_present(RunningPiHole):
|
||||||
File('/var/www/html/pihole/index.html').exists
|
File('/var/www/html/pihole/index.html').exists
|
||||||
File('/var/www/html/pihole/index.js').exists
|
File('/var/www/html/pihole/index.js').exists
|
||||||
|
|
||||||
@pytest.mark.parametrize('ip', [ 'localhost', '[::]' ])
|
@pytest.mark.parametrize('addr', [ 'testblock.pi-hole.local' ])
|
||||||
@pytest.mark.parametrize('url', [ '/', '/index.html', '/any.html' ] )
|
@pytest.mark.parametrize('url', [ '/', '/index.html', '/any.html' ] )
|
||||||
def test_html_index_requests_load_as_expected(RunningPiHole, ip, url):
|
def test_html_index_requests_load_as_expected(RunningPiHole, Slow, addr, url):
|
||||||
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(ip, url)
|
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(addr, url)
|
||||||
http_rc = RunningPiHole.run(command)
|
http_rc = RunningPiHole.run(command)
|
||||||
assert RunningPiHole.run('grep -q "Access to the following site has been blocked" /tmp/curled_file ').rc == 0
|
assert http_rc.rc == 0
|
||||||
assert int(http_rc.stdout) == 200
|
assert int(http_rc.stdout) == 200
|
||||||
|
page_contents = RunningPiHole.run('cat /tmp/curled_file ').stdout
|
||||||
|
assert 'blocked' in page_contents
|
||||||
|
|
||||||
@pytest.mark.parametrize('ip', [ '127.0.0.1', '[::]' ] )
|
@pytest.mark.parametrize('addr', [ 'testblock.pi-hole.local' ])
|
||||||
@pytest.mark.parametrize('url', [ '/index.js', '/any.js'] )
|
@pytest.mark.parametrize('url', [ '/index.js', '/any.js'] )
|
||||||
def test_javascript_requests_load_as_expected(RunningPiHole, ip, url):
|
def test_javascript_requests_load_as_expected(RunningPiHole, addr, url):
|
||||||
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(ip, url)
|
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(addr, url)
|
||||||
http_rc = RunningPiHole.run(command)
|
http_rc = RunningPiHole.run(command)
|
||||||
assert RunningPiHole.run('md5sum /tmp/curled_file /var/www/html/pihole/index.js').rc == 0
|
assert http_rc.rc == 0
|
||||||
assert int(http_rc.stdout) == 200
|
assert int(http_rc.stdout) == 200
|
||||||
|
assert RunningPiHole.run('md5sum /tmp/curled_file /var/www/html/pihole/index.js').rc == 0
|
||||||
|
|
||||||
# IPv6 checks aren't passing CORS, removed :(
|
# IPv6 checks aren't passing CORS, removed :(
|
||||||
@pytest.mark.parametrize('ip', [ 'localhost' ] )
|
@pytest.mark.parametrize('addr', [ 'localhost' ] )
|
||||||
@pytest.mark.parametrize('url', [ '/admin/', '/admin/index.php' ] )
|
@pytest.mark.parametrize('url', [ '/admin/', '/admin/index.php' ] )
|
||||||
def test_admin_requests_load_as_expected(RunningPiHole, ip, url):
|
def test_admin_requests_load_as_expected(RunningPiHole, addr, url):
|
||||||
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(ip, url)
|
command = 'curl -s -o /tmp/curled_file -w "%{{http_code}}" http://{}{}'.format(addr, url)
|
||||||
http_rc = RunningPiHole.run(command)
|
http_rc = RunningPiHole.run(command)
|
||||||
|
assert http_rc.rc == 0
|
||||||
assert int(http_rc.stdout) == 200
|
assert int(http_rc.stdout) == 200
|
||||||
assert RunningPiHole.run('wc -l /tmp/curled_file ') > 10
|
assert RunningPiHole.run('wc -l /tmp/curled_file ') > 10
|
||||||
assert RunningPiHole.run('grep -q "Content-Security-Policy" /tmp/curled_file ').rc == 0
|
assert RunningPiHole.run('grep -q "Content-Security-Policy" /tmp/curled_file ').rc == 0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user