Last active
September 7, 2025 08:40
-
-
Save alexellis/6a9208a5730a01f3c476d10809a71426 to your computer and use it in GitHub Desktop.
PiHole in SlicerVM.com
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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