Skip to content

Instantly share code, notes, and snippets.

@alexellis
Last active September 7, 2025 08:40
Show Gist options
  • Save alexellis/6a9208a5730a01f3c476d10809a71426 to your computer and use it in GitHub Desktop.
Save alexellis/6a9208a5730a01f3c476d10809a71426 to your computer and use it in GitHub Desktop.
PiHole in SlicerVM.com
# Example from https://docs.slicervm.com/getting-started/walkthrough/
# Then under the hostgroup instead of userdata:
# userdata_file: ./userdata.sh
# Then add a DNAT rule from the host to the microVM via iptables (ask ChatGPT for this!)
# Or simply add a static route on your router via your Slicer host to the microVM - easy to do
# in most router admin interfaces, then also set the default DNS to the VM IP there too.
#!/usr/bin/env bash
set -euxo pipefail
# ---------- Tunables ----------
UPSTREAMS=("1.1.1.1" "9.9.9.9") # change if you like
ENABLE_DNSSEC="true" # "true" or "false"
ADMIN_PASS="" # leave empty to auto-generate
# -------------------------------
retry() { i=0; while true; do if "$@"; then return 0; fi; i=$((i+1)); [ "$i" -ge 30 ] && return 1; sleep 2; done; }
wait_default_route() { for _ in $(seq 1 60); do /usr/sbin/ip -4 route show default | /usr/bin/grep -q . && return 0; sleep 1; done; return 1; }
# 1) Network ready before any fetches
wait_default_route
# 2) Bring up systemd-resolved (no stub on :53 to avoid conflict)
# and point resolv.conf at resolved's generated file
/usr/bin/mkdir -p /etc/systemd || :
/usr/bin/tee /etc/systemd/resolved.conf >/dev/null <<EOF
[Resolve]
DNS=${UPSTREAMS[*]}
FallbackDNS=1.0.0.1 149.112.112.112
DNSStubListener=no
EOF
/bin/systemctl unmask systemd-resolved || :
/bin/systemctl enable --now systemd-resolved || :
if [ -f /run/systemd/resolve/resolv.conf ]; then
chattr -i /etc/resolv.conf || :
chattr -i /etc/systemd/resolved.conf || :
/bin/ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
else
# fallback if resolved isn't providing it for some reason
/usr/bin/tee /etc/resolv.conf >/dev/null <<EOF
$(for s in "${UPSTREAMS[@]}"; do echo "nameserver $s"; done)
options timeout:2 attempts:2
EOF
fi
# 3) Speed up apt (prefer IPv4)
# NOTE: do this BEFORE update to avoid AAAA timeouts
/usr/bin/tee /etc/apt/apt.conf.d/99force-ipv4 >/dev/null <<'EOF'
Acquire::ForceIPv4 "true";
EOF
# 4) Base tools
retry /usr/bin/apt-get update
DEBIAN_FRONTEND=noninteractive retry /usr/bin/apt-get install -y \
curl ca-certificates iproute2 procps e2fsprogs openssl dnsutils || :
# 5) Detect primary interface + IP/CIDR
IFACE="$(/usr/sbin/ip -o -4 route show to default | /usr/bin/awk '{print $5}' | /usr/bin/head -n1)"
IP_CIDR="$(/usr/sbin/ip -o -4 addr show dev "${IFACE}" | /usr/bin/awk '{print $4}' | /usr/bin/head -n1)"
VM_IP="$(echo "$IP_CIDR" | /usr/bin/cut -d/ -f1)"
# 6) Preseed Pi-hole v6 config (TOML + setupVars)
/usr/bin/mkdir -p /etc/pihole
# pihole.toml
/usr/bin/tee /etc/pihole/pihole.toml >/dev/null <<EOF
[dns]
interface = "0.0.0.0"
upstreams = [$(printf '"%s",' "${UPSTREAMS[@]}" | sed 's/,$//')]
dnssec = ${ENABLE_DNSSEC}
EOF
# setupVars.conf (some installers still consult it)
/usr/bin/tee /etc/pihole/setupVars.conf >/dev/null <<EOF
PIHOLE_INTERFACE=${IFACE}
IPV4_ADDRESS=${IP_CIDR}
IPV6_ADDRESS=
DNSMASQ_LISTENING=single
PIHOLE_DNS_1=${UPSTREAMS[0]}
PIHOLE_DNS_2=${UPSTREAMS[1]:-${UPSTREAMS[0]}}
DNSSEC=${ENABLE_DNSSEC}
QUERY_LOGGING=true
INSTALL_WEB_SERVER=true
INSTALL_WEB_INTERFACE=true
LIGHTTPD_ENABLED=true
BLOCKING_ENABLED=true
WEBPASSWORD=
EOF
# 7) Unattended install
retry /usr/bin/curl -fsSL https://install.pi-hole.net -o /tmp/pihole-install.sh
PIHOLE_SKIP_OS_CHECK=true /bin/bash /tmp/pihole-install.sh --unattended || :
# 8) CLI path + admin password
PIHOLE_BIN="/usr/local/bin/pihole"; [ -x "$PIHOLE_BIN" ] || PIHOLE_BIN="/usr/bin/pihole"
if [ -z "${ADMIN_PASS}" ]; then ADMIN_PASS="$(/usr/bin/openssl rand -base64 18)"; fi
"${PIHOLE_BIN}" setpassword "${ADMIN_PASS}" || :
"${PIHOLE_BIN}" -g || :
# 9) Ensure service enabled & started
/bin/systemctl enable pihole-FTL || :
/bin/systemctl restart pihole-FTL || :
# 10) Output & quick hints
/usr/bin/printf "Pi-hole admin: http://%s/admin\n" "${VM_IP}"
/usr/bin/printf "Pi-hole admin password: %s\n" "${ADMIN_PASS}" > /root/pihole-admin-pass.txt
/usr/bin/printf "Saved admin password to /root/pihole-admin-pass.txt\n"
echo "Test locally: dig +short openfaas.com @127.0.0.1 || true"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment