DNS names: flat franksdank.cloud scheme + dnsmasq LAN DNS on dankclaw
Phase 1 of the local-DNS-name work. Users type a name, not a port. - dnsmasq quadlet on dankclaw (rootless, slirp4netns, port 53 published): serves the flat name scheme from addn-hosts, upstream 1.1.1.1/1.0.0.1. Image built from the in-repo Containerfile (localhost/dnsmasq:latest). - Caddyfiles (both hosts): all *.dankclaw.local / *.dankserver.local vhosts renamed to flat <service>.franksdank.cloud. Explicit http:// site addresses for now; TLS (wildcard LE via DNS-01/Porkbun) lands in phase 2. - Drift reconciliation (live /etc/caddy/Caddyfile on dankserver differs from the repo): added the live-only llms.franksdank.cloud vhost (OpenWebUI on :3000). Dropped the legacy search vhost from dankserver (the name belongs to dankclaw's gluetun-routed SearXNG; the legacy instance stays reachable at 192.168.0.235:8081). - Homepage service links updated to the new names. - New test seams (TDD): tests/dnsmasq.bats (quadlet boot-persistence, port 53, conf/record validity, Caddyfile<->addn-hosts cross-check on the right host IPs); caddyfile.bats naming-convention tests updated. LAN clients get this DNS from the SURFboard G36 (DNS Relay -> statically configured -> 192.168.0.143); the router change is a pending user step.
This commit is contained in:
+18
-10
@@ -2,14 +2,22 @@
|
||||
# Reverse proxy for the Dankclaw stack. Caddy runs as a container on the
|
||||
# podman network; upstreams are container names. Homepage is password
|
||||
# protected. Replace the bcrypt hashes below (caddy hash-password) at deploy.
|
||||
#
|
||||
# Naming: flat franksdank.cloud scheme (see docs/Infrastructure/Domain-DNS.md).
|
||||
# DNS for these names is served by the dnsmasq quadlet on this host
|
||||
# (dankclaw/dnsmasq/addn-hosts) and handed to LAN clients by the SURFboard
|
||||
# G36 router (DNS Relay -> statically configured -> 192.168.0.143).
|
||||
#
|
||||
# Phase 1 uses explicit http:// site addresses (no TLS yet). Phase 2 drops
|
||||
# the prefix and adds a wildcard Let's Encrypt cert via DNS-01 (Porkbun).
|
||||
|
||||
{
|
||||
admin off
|
||||
email admin@dankclaw.local
|
||||
email admin@franksdank.cloud
|
||||
}
|
||||
|
||||
# --- Homepage (password protected) ---
|
||||
dankclaw.local {
|
||||
http://dankclaw.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -18,7 +26,7 @@ dankclaw.local {
|
||||
}
|
||||
|
||||
# --- SearXNG (behind the Gluetun tunnel) ---
|
||||
search.dankclaw.local {
|
||||
http://search.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -26,14 +34,14 @@ search.dankclaw.local {
|
||||
}
|
||||
|
||||
# --- ComfyUI ---
|
||||
comfyui.dankclaw.local {
|
||||
http://comfyui.franksdank.cloud {
|
||||
reverse_proxy comfyui:8188
|
||||
}
|
||||
|
||||
# --- OpenWebUI ---
|
||||
# open-webui is a quadlet container on slirp4netns (isolated), so Caddy cannot
|
||||
# reach it by container name. Proxy to its published LAN port instead.
|
||||
chat.dankclaw.local {
|
||||
http://chat.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -41,7 +49,7 @@ chat.dankclaw.local {
|
||||
}
|
||||
|
||||
# --- Hermes ---
|
||||
hermes.dankclaw.local {
|
||||
http://hermes.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -49,12 +57,12 @@ hermes.dankclaw.local {
|
||||
}
|
||||
|
||||
# --- Gitea (migrated) ---
|
||||
gitea.dankclaw.local {
|
||||
http://gitea.franksdank.cloud {
|
||||
reverse_proxy gitea-server:3000
|
||||
}
|
||||
|
||||
# --- Grafana ---
|
||||
grafana.dankclaw.local {
|
||||
http://grafana.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -62,7 +70,7 @@ grafana.dankclaw.local {
|
||||
}
|
||||
|
||||
# --- Prometheus ---
|
||||
prometheus.dankclaw.local {
|
||||
http://prometheus.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -70,7 +78,7 @@ prometheus.dankclaw.local {
|
||||
}
|
||||
|
||||
# --- Loki ---
|
||||
loki.dankclaw.local {
|
||||
http://loki.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# Minimal dnsmasq image for the LAN DNS quadlet (dankclaw).
|
||||
# Build on dankclaw: podman build -t localhost/dnsmasq:latest -f Containerfile .
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache dnsmasq
|
||||
@@ -0,0 +1,34 @@
|
||||
# A records for the flat franksdank.name scheme (dnsmasq addn-hosts format:
|
||||
# <IP> <name> [<name> ...]). Every Caddy vhost name has exactly one record,
|
||||
# pointing at the host that runs it. Keep in sync with the Caddyfiles
|
||||
# (tests/dnsmasq.bats cross-checks this).
|
||||
#
|
||||
# 192.168.0.235 = dankserver (media/library stack)
|
||||
# 192.168.0.143 = dankclaw (AI/search/dev stack)
|
||||
|
||||
# --- dankserver services ---
|
||||
192.168.0.235 dankserver.franksdank.cloud
|
||||
192.168.0.235 plex.franksdank.cloud
|
||||
192.168.0.235 plex.franksdank.casa
|
||||
192.168.0.235 books.franksdank.cloud
|
||||
192.168.0.235 llms.franksdank.cloud
|
||||
192.168.0.235 romm.franksdank.cloud
|
||||
192.168.0.235 files.franksdank.cloud
|
||||
192.168.0.235 jellyfin.franksdank.cloud
|
||||
192.168.0.235 radarr.franksdank.cloud
|
||||
192.168.0.235 sonarr.franksdank.cloud
|
||||
192.168.0.235 lidarr.franksdank.cloud
|
||||
192.168.0.235 readarr.franksdank.cloud
|
||||
192.168.0.235 prowlarr.franksdank.cloud
|
||||
192.168.0.235 qbittorrent.franksdank.cloud
|
||||
|
||||
# --- dankclaw services ---
|
||||
192.168.0.143 dankclaw.franksdank.cloud
|
||||
192.168.0.143 search.franksdank.cloud
|
||||
192.168.0.143 comfyui.franksdank.cloud
|
||||
192.168.0.143 chat.franksdank.cloud
|
||||
192.168.0.143 hermes.franksdank.cloud
|
||||
192.168.0.143 gitea.franksdank.cloud
|
||||
192.168.0.143 grafana.franksdank.cloud
|
||||
192.168.0.143 prometheus.franksdank.cloud
|
||||
192.168.0.143 loki.franksdank.cloud
|
||||
@@ -0,0 +1,24 @@
|
||||
# dnsmasq — LAN DNS for the homelab.
|
||||
#
|
||||
# Runs in a rootless podman quadlet on dankclaw (192.168.0.143) with port 53
|
||||
# published to the LAN. Serves the flat franksdank.cloud / franksdank.casa
|
||||
# name scheme from addn-hosts (one A record per Caddy vhost); everything else
|
||||
# goes to the pinned upstream resolvers. The SURFboard G36 router hands this
|
||||
# server out to DHCP clients, so LAN devices resolve service names without
|
||||
# per-device config. See docs/Infrastructure/LAN-DNS.md.
|
||||
|
||||
# The slirp netns has no useful /etc/resolv.conf; pin upstreams instead.
|
||||
no-resolv
|
||||
server=1.1.1.1
|
||||
server=1.0.0.1
|
||||
|
||||
# Local service names (must stay in sync with the Caddyfile vhosts).
|
||||
addn-hosts=/etc/dnsmasq/addn-hosts
|
||||
|
||||
# Never resolve single-label names or private/bogus ranges as public names.
|
||||
domain-needed
|
||||
bogus-priv
|
||||
|
||||
# Cache.
|
||||
cache-size=1000
|
||||
neg-ttl=300
|
||||
@@ -0,0 +1,32 @@
|
||||
# Quadlet unit: dnsmasq LAN DNS (rootless, boot-persistent).
|
||||
#
|
||||
# Install path on dankclaw: ~/.config/containers/systemd/dnsmasq.container
|
||||
# Unit name: dnsmasq.service (container name: dnsmasq)
|
||||
#
|
||||
# The LAN's authoritative DNS for the flat franksdank.cloud / franksdank.casa
|
||||
# name scheme. It serves A records from addn-hosts (one per Caddy vhost) and
|
||||
# forwards everything else to pinned upstream resolvers. The SURFboard G36
|
||||
# router hands this server out to DHCP clients (DNS Relay -> statically
|
||||
# configured -> 192.168.0.143), so no client needs per-device config.
|
||||
#
|
||||
# Runs on slirp4netns with port 53 published to the LAN (the same pattern as
|
||||
# open-webui). Config mounts from /opt/dnsmasq. See docs/Infrastructure/LAN-DNS.md.
|
||||
|
||||
[Unit]
|
||||
Description=dnsmasq LAN DNS container
|
||||
After=network.target
|
||||
|
||||
[Container]
|
||||
ContainerName=dnsmasq
|
||||
Network=slirp4netns
|
||||
Image=localhost/dnsmasq:latest
|
||||
PublishPort=53:53/tcp
|
||||
PublishPort=53:53/udp
|
||||
Volume=/opt/dnsmasq/dnsmasq.conf:/etc/dnsmasq.conf:ro
|
||||
Volume=/opt/dnsmasq/addn-hosts:/etc/dnsmasq/addn-hosts:ro
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
+28
-23
@@ -1,14 +1,22 @@
|
||||
# Dankserver Caddyfile
|
||||
# Deploy: copy to /etc/caddy/Caddyfile on dankserver
|
||||
# Deploy: copy to /etc/caddy/Caddyfile on dankserver (host Caddy service)
|
||||
# See ../docs/Dankserver/ for service documentation.
|
||||
#
|
||||
# Naming: flat franksdank.cloud scheme (see docs/Infrastructure/Domain-DNS.md).
|
||||
# DNS for these names is served by the dnsmasq quadlet on dankclaw
|
||||
# (dankclaw/dnsmasq/addn-hosts) and handed to LAN clients by the SURFboard
|
||||
# G36 router (DNS Relay -> statically configured -> 192.168.0.143).
|
||||
#
|
||||
# Phase 1 uses explicit http:// site addresses (no TLS yet). Phase 2 drops
|
||||
# the prefix and adds a wildcard Let's Encrypt cert via DNS-01 (Porkbun).
|
||||
|
||||
{
|
||||
admin off
|
||||
email admin@dankserver.local
|
||||
email admin@franksdank.cloud
|
||||
}
|
||||
|
||||
# --- Homepage (password protected) ---
|
||||
dankserver.local {
|
||||
http://dankserver.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -17,29 +25,26 @@ dankserver.local {
|
||||
}
|
||||
|
||||
# --- Plex (existing, kept) ---
|
||||
plex.franksdank.casa {
|
||||
http://plex.franksdank.casa {
|
||||
reverse_proxy localhost:32400
|
||||
}
|
||||
|
||||
plex.franksdank.cloud {
|
||||
reverse_proxy localhost:32400
|
||||
}
|
||||
|
||||
plex.dankserver.local {
|
||||
http://plex.franksdank.cloud {
|
||||
reverse_proxy localhost:32400
|
||||
}
|
||||
|
||||
# --- Calibre-Web (existing, kept) ---
|
||||
books.franksdank.cloud {
|
||||
http://books.franksdank.cloud {
|
||||
reverse_proxy localhost:8083
|
||||
}
|
||||
|
||||
books.dankserver.local {
|
||||
reverse_proxy localhost:8083
|
||||
# --- OpenWebUI (live name from the host Caddyfile; LLM chat UI on this host) ---
|
||||
http://llms.franksdank.cloud {
|
||||
reverse_proxy localhost:3000
|
||||
}
|
||||
|
||||
# --- RomM ---
|
||||
romm.dankserver.local {
|
||||
http://romm.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -47,7 +52,7 @@ romm.dankserver.local {
|
||||
}
|
||||
|
||||
# --- Copyparty ---
|
||||
files.dankserver.local {
|
||||
http://files.franksdank.cloud {
|
||||
basicauth {
|
||||
dank $2a$14$REPLACE_WITH_HASH
|
||||
}
|
||||
@@ -55,7 +60,7 @@ files.dankserver.local {
|
||||
}
|
||||
|
||||
# --- Jellyfin ---
|
||||
jellyfin.dankserver.local {
|
||||
http://jellyfin.franksdank.cloud {
|
||||
reverse_proxy 127.0.0.1:8096
|
||||
|
||||
transport http {
|
||||
@@ -64,36 +69,36 @@ jellyfin.dankserver.local {
|
||||
}
|
||||
|
||||
# --- *arr Stack ---
|
||||
radarr.dankserver.local {
|
||||
http://radarr.franksdank.cloud {
|
||||
reverse_proxy localhost:7878
|
||||
}
|
||||
|
||||
sonarr.dankserver.local {
|
||||
http://sonarr.franksdank.cloud {
|
||||
reverse_proxy localhost:8989
|
||||
}
|
||||
|
||||
lidarr.dankserver.local {
|
||||
http://lidarr.franksdank.cloud {
|
||||
reverse_proxy localhost:8686
|
||||
}
|
||||
|
||||
readarr.dankserver.local {
|
||||
http://readarr.franksdank.cloud {
|
||||
reverse_proxy localhost:8787
|
||||
}
|
||||
|
||||
prowlarr.dankserver.local {
|
||||
http://prowlarr.franksdank.cloud {
|
||||
reverse_proxy localhost:9696
|
||||
}
|
||||
|
||||
qbittorrent.dankserver.local {
|
||||
http://qbittorrent.franksdank.cloud {
|
||||
reverse_proxy localhost:8080
|
||||
}
|
||||
|
||||
# --- Optional: Jackett ---
|
||||
# jackett.dankserver.local {
|
||||
# http://jackett.franksdank.cloud {
|
||||
# reverse_proxy localhost:9117
|
||||
# }
|
||||
|
||||
# --- Optional: Whisparr ---
|
||||
# whisparr.dankserver.local {
|
||||
# http://whisparr.franksdank.cloud {
|
||||
# reverse_proxy localhost:6969
|
||||
# }
|
||||
|
||||
@@ -9,25 +9,25 @@
|
||||
},
|
||||
{
|
||||
"name": "RomM",
|
||||
"url": "http://romm.dankserver.local",
|
||||
"url": "http://romm.franksdank.cloud",
|
||||
"description": "Retro game manager and player for the ROM collection.",
|
||||
"docs": "docs/Dankserver/RomM.md"
|
||||
},
|
||||
{
|
||||
"name": "Copyparty",
|
||||
"url": "http://files.dankserver.local",
|
||||
"url": "http://files.franksdank.cloud",
|
||||
"description": "High-speed file sharing and streaming server.",
|
||||
"docs": "docs/Dankserver/Copyparty.md"
|
||||
},
|
||||
{
|
||||
"name": "Calibre-Web",
|
||||
"url": "http://books.dankserver.local",
|
||||
"url": "http://books.franksdank.cloud",
|
||||
"description": "E-book library browser and reader.",
|
||||
"docs": "docs/Dankserver/Calibre-Web.md"
|
||||
},
|
||||
{
|
||||
"name": "Plex",
|
||||
"url": "http://plex.dankserver.local",
|
||||
"url": "http://plex.franksdank.cloud",
|
||||
"description": "Media server (existing host service, proxied).",
|
||||
"docs": "docs/Dankserver/Dankserver Stack.md"
|
||||
}
|
||||
|
||||
@@ -9,49 +9,49 @@
|
||||
},
|
||||
{
|
||||
"name": "SearXNG",
|
||||
"url": "http://search.dankclaw.local",
|
||||
"url": "http://search.franksdank.cloud",
|
||||
"description": "Privacy-respecting metasearch engine (through Gluetun VPN).",
|
||||
"docs": "docs/Dankclaw/SearXNG.md"
|
||||
},
|
||||
{
|
||||
"name": "ComfyUI",
|
||||
"url": "http://comfyui.dankclaw.local",
|
||||
"url": "http://comfyui.franksdank.cloud",
|
||||
"description": "Node-based AI image generation (CPU backend on Strix Halo).",
|
||||
"docs": "docs/Dankclaw/ComfyUI.md"
|
||||
},
|
||||
{
|
||||
"name": "OpenWebUI",
|
||||
"url": "http://chat.dankclaw.local",
|
||||
"url": "http://chat.franksdank.cloud",
|
||||
"description": "Chat interface for local LLMs (llama.cpp on :7770).",
|
||||
"docs": "docs/Dankclaw/OpenWebUI.md"
|
||||
},
|
||||
{
|
||||
"name": "Hermes",
|
||||
"url": "http://hermes.dankclaw.local",
|
||||
"url": "http://hermes.franksdank.cloud",
|
||||
"description": "Self-improving AI agent (Nous Research).",
|
||||
"docs": "docs/Dankclaw/Hermes.md"
|
||||
},
|
||||
{
|
||||
"name": "Gitea",
|
||||
"url": "http://gitea.dankclaw.local",
|
||||
"url": "http://gitea.franksdank.cloud",
|
||||
"description": "Self-hosted Git service with issues and PRs.",
|
||||
"docs": "docs/Dankclaw/Gitea.md"
|
||||
},
|
||||
{
|
||||
"name": "Grafana",
|
||||
"url": "http://grafana.dankclaw.local",
|
||||
"url": "http://grafana.franksdank.cloud",
|
||||
"description": "Dashboards for metrics and logs.",
|
||||
"docs": "docs/Infrastructure/Grafana.md"
|
||||
},
|
||||
{
|
||||
"name": "Prometheus",
|
||||
"url": "http://prometheus.dankclaw.local",
|
||||
"url": "http://prometheus.franksdank.cloud",
|
||||
"description": "Metrics collection for the whole stack.",
|
||||
"docs": "docs/Infrastructure/Prometheus.md"
|
||||
},
|
||||
{
|
||||
"name": "Loki",
|
||||
"url": "http://loki.dankclaw.local",
|
||||
"url": "http://loki.franksdank.cloud",
|
||||
"description": "Log storage and query backend.",
|
||||
"docs": "docs/Infrastructure/Loki.md"
|
||||
}
|
||||
|
||||
@@ -12,9 +12,14 @@ load helpers
|
||||
[ -f "$REPO_ROOT/dankclaw/Caddyfile" ]
|
||||
}
|
||||
|
||||
@test "Caddyfiles use the .local hostname convention" {
|
||||
grep -qE '\.dankserver\.local' "$REPO_ROOT/dankserver/Caddyfile"
|
||||
grep -qE '\.dankclaw\.local' "$REPO_ROOT/dankclaw/Caddyfile"
|
||||
@test "Caddyfiles use the flat franksdank.cloud hostname convention" {
|
||||
grep -qE '\.franksdank\.cloud' "$REPO_ROOT/dankserver/Caddyfile"
|
||||
grep -qE '\.franksdank\.cloud' "$REPO_ROOT/dankclaw/Caddyfile"
|
||||
}
|
||||
|
||||
@test "no .local vhost names remain in either Caddyfile" {
|
||||
! grep -qE '^([a-z0-9.-]+\.)?(dankserver|dankclaw)\.local[[:space:]]*\{' \
|
||||
"$REPO_ROOT/dankserver/Caddyfile" "$REPO_ROOT/dankclaw/Caddyfile"
|
||||
}
|
||||
|
||||
@test "Caddyfiles have balanced braces" {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bats
|
||||
# Seam: LAN DNS (dnsmasq) on dankclaw.
|
||||
#
|
||||
# The dnsmasq quadlet is the LAN's authoritative DNS for the flat
|
||||
# franksdank.cloud / franksdank.casa name scheme. Every Caddy vhost name
|
||||
# must have an A record pointing at the host that runs it, records must
|
||||
# stay inside the LAN, and the quadlet must be boot-persistent.
|
||||
|
||||
load helpers
|
||||
|
||||
DNSMASQ_DIR="$REPO_ROOT/dankclaw/dnsmasq"
|
||||
QUADLET="$DNSMASQ_DIR/dnsmasq.container"
|
||||
CONF="$DNSMASQ_DIR/dnsmasq.conf"
|
||||
HOSTS="$DNSMASQ_DIR/addn-hosts"
|
||||
|
||||
@test "the dnsmasq quadlet container file exists" {
|
||||
[ -f "$QUADLET" ]
|
||||
}
|
||||
|
||||
@test "the dnsmasq quadlet is installed for boot" {
|
||||
grep -q 'WantedBy=default.target' "$QUADLET"
|
||||
}
|
||||
|
||||
@test "the dnsmasq quadlet publishes port 53 tcp and udp" {
|
||||
grep -qE '^PublishPort=53:53/tcp$' "$QUADLET"
|
||||
grep -qE '^PublishPort=53:53/udp$' "$QUADLET"
|
||||
}
|
||||
|
||||
@test "the dnsmasq quadlet restarts on failure" {
|
||||
grep -q '^Restart=always' "$QUADLET"
|
||||
}
|
||||
|
||||
@test "dnsmasq.conf exists and pins upstream resolvers" {
|
||||
[ -f "$CONF" ]
|
||||
grep -q '^no-resolv' "$CONF"
|
||||
grep -qE '^server=[0-9.]+$' "$CONF"
|
||||
}
|
||||
|
||||
@test "dnsmasq.conf loads the addn-hosts record file" {
|
||||
grep -q '^addn-hosts=' "$CONF"
|
||||
}
|
||||
|
||||
@test "every addn-hosts line is a valid IPv4 address plus hostnames" {
|
||||
local bad=0 line
|
||||
while IFS= read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
case "$line" in \#*) continue ;; esac
|
||||
if ! echo "$line" | grep -qE '^([0-9]{1,3}\.){3}[0-9]{1,3}[[:space:]]+[a-z0-9.-]+([[:space:]]+[a-z0-9.-]+)*$'; then
|
||||
echo "BAD LINE: $line"
|
||||
bad=1
|
||||
fi
|
||||
done < "$HOSTS"
|
||||
[ "$bad" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "every addn-hosts IP is inside the homelab LAN" {
|
||||
! awk '!/^[[:space:]]*#/ && NF {print $1}' "$HOSTS" \
|
||||
| grep -vE '^(192\.168\.0\.[0-9]{1,3})$' \
|
||||
| grep -q .
|
||||
}
|
||||
|
||||
@test "every addn-hosts name is under franksdank.cloud or franksdank.casa" {
|
||||
local bad=0 line ip n
|
||||
while IFS= read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
case "$line" in \#*) continue ;; esac
|
||||
ip="$(echo "$line" | awk '{print $1}')"
|
||||
for n in $(echo "$line" | cut -d' ' -f2-); do
|
||||
echo "$n" | grep -qE '\.(franksdank\.(cloud|casa))$' \
|
||||
|| { echo "UNEXPECTED TLD on $ip: $n"; bad=1; }
|
||||
done
|
||||
done < "$HOSTS"
|
||||
[ "$bad" -eq 0 ]
|
||||
}
|
||||
|
||||
# vhost_names <caddyfile> — print site-block names under the flat scheme
|
||||
vhost_names() {
|
||||
grep -oE '^(http://)?[a-z0-9.-]+\.franksdank\.(cloud|casa)[[:space:]]*\{' "$1" \
|
||||
| sed -E 's#^http://##; s/[[:space:]]*\{$//'
|
||||
}
|
||||
|
||||
# record_ip_for <name> — print the IP a name maps to in addn-hosts
|
||||
record_ip_for() {
|
||||
awk -v n="$1" '{ip=$1; for (i=2; i<=NF; i++) if ($i==n) print ip}' "$HOSTS" | head -1
|
||||
}
|
||||
|
||||
@test "every dankserver Caddyfile vhost has an A record on 192.168.0.235" {
|
||||
local names n ip
|
||||
names="$(vhost_names "$REPO_ROOT/dankserver/Caddyfile")"
|
||||
[ -n "$names" ] || { echo "no .franksdank vhosts found in dankserver/Caddyfile"; return 1; }
|
||||
while IFS= read -r n; do
|
||||
[ -z "$n" ] && continue
|
||||
ip="$(record_ip_for "$n")"
|
||||
[ "$ip" = "192.168.0.235" ] || { echo "$n -> '$ip' (want 192.168.0.235)"; return 1; }
|
||||
done <<< "$names"
|
||||
}
|
||||
|
||||
@test "every dankclaw Caddyfile vhost has an A record on 192.168.0.143" {
|
||||
local names n ip
|
||||
names="$(vhost_names "$REPO_ROOT/dankclaw/Caddyfile")"
|
||||
[ -n "$names" ] || { echo "no .franksdank vhosts found in dankclaw/Caddyfile"; return 1; }
|
||||
while IFS= read -r n; do
|
||||
[ -z "$n" ] && continue
|
||||
ip="$(record_ip_for "$n")"
|
||||
[ "$ip" = "192.168.0.143" ] || { echo "$n -> '$ip' (want 192.168.0.143)"; return 1; }
|
||||
done <<< "$names"
|
||||
}
|
||||
|
||||
@test "no secret material in the dnsmasq files" {
|
||||
local f
|
||||
for f in "$DNSMASQ_DIR"/*; do
|
||||
has_no_leaked_secret "$f"
|
||||
done
|
||||
}
|
||||
Reference in New Issue
Block a user