From 42aad8a117de0827dac49bc6baa105019391b514 Mon Sep 17 00:00:00 2001 From: "l.kirchner" Date: Fri, 22 May 2026 00:11:49 +0200 Subject: [PATCH] fix(build): add DNS server prompt for static IPs + better network diagnostics For DHCP setups DNS is delivered with the lease, but with a static IP the container inherits /etc/resolv.conf from the PVE host - which is often unreachable from the container's VLAN. Changes: - New NAMESERVER prompt (only shown for static IPs, defaults to gateway) - pct create now passes --nameserver when set - Network wait loop tests L3 and DNS separately so failures point at the actual cause (no route to gateway vs. bad DNS server) - Refactored pct create args into an array for cleaner conditional flags --- lib/build.func | 73 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/build.func b/lib/build.func index df87c30..37f9e70 100644 --- a/lib/build.func +++ b/lib/build.func @@ -34,6 +34,7 @@ DEFAULT_BRIDGE="${DEFAULT_BRIDGE:-vmbr0}" DEFAULT_TEMPLATE_STORAGE="${DEFAULT_TEMPLATE_STORAGE:-local}" DEFAULT_ROOTFS_STORAGE="${DEFAULT_ROOTFS_STORAGE:-local-lvm}" DEFAULT_TEMPLATE_PATTERN="${DEFAULT_TEMPLATE_PATTERN:-debian-12-standard}" +DEFAULT_NAMESERVER="${DEFAULT_NAMESERVER:-}" # ── error trap ─────────────────────────────────────────────────────────────── _on_error() { @@ -64,8 +65,8 @@ show_header() { # ── prompts ────────────────────────────────────────────────────────────────── # Each prompt is skipped if the corresponding variable is already set in env. -# VLAN_TAG uses ${VLAN_TAG+x} so that explicitly setting it to "" via env -# skips the prompt (= "no VLAN, don't ask"). +# VLAN_TAG and NAMESERVER use ${VAR+x} so that explicitly setting them to "" +# via env skips the prompt (= "no VLAN" / "inherit DNS from host"). prompt_lxc_config() { if [[ -z "${CTID:-}" ]]; then read -rp "Container ID [auto]: " CTID @@ -112,6 +113,13 @@ prompt_lxc_config() { if [[ "$IPCFG" != "dhcp" && -z "$GATEWAY" ]]; then read -rp "Gateway: " GATEWAY fi + # DNS: only meaningful for static IPs (DHCP gets DNS from the lease). + # Default suggestion is the gateway, which doubles as DNS in most homelabs. + if [[ "$IPCFG" != "dhcp" && -z "${NAMESERVER+x}" ]]; then + local default_ns="${DEFAULT_NAMESERVER:-$GATEWAY}" + read -rp "DNS server [$default_ns] (empty = inherit from PVE host): " NAMESERVER + NAMESERVER="${NAMESERVER:-$default_ns}" + fi } # ── template ───────────────────────────────────────────────────────────────── @@ -142,36 +150,63 @@ create_lxc() { net_opts+=",ip=$IPCFG,gw=$GATEWAY" fi + # Assemble pct args as an array so conditional flags stay clean. + local pct_args=( + "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" + --hostname "$CT_HOSTNAME" + --cores "$CORES" + --memory "$RAM" + --swap 512 + --rootfs "$ROOTFS_STORAGE:$DISK_SIZE" + --net0 "$net_opts" + --features nesting=1 + --unprivileged 1 + --onboot 1 + --ostype debian + --password "$ROOT_PASSWORD" + ) + [[ -n "${NAMESERVER:-}" ]] && pct_args+=(--nameserver "$NAMESERVER") + msg_info "Creating unprivileged LXC $CTID ($CT_HOSTNAME)..." msg_info " net0: $net_opts" - pct create "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" \ - --hostname "$CT_HOSTNAME" \ - --cores "$CORES" \ - --memory "$RAM" \ - --swap 512 \ - --rootfs "$ROOTFS_STORAGE:$DISK_SIZE" \ - --net0 "$net_opts" \ - --features nesting=1 \ - --unprivileged 1 \ - --onboot 1 \ - --ostype debian \ - --password "$ROOT_PASSWORD" + [[ -n "${NAMESERVER:-}" ]] && msg_info " dns: $NAMESERVER" + pct create "${pct_args[@]}" msg_ok "LXC $CTID created" msg_info "Starting LXC..." pct start "$CTID" sleep 5 - msg_info "Waiting for network..." - local i + msg_info "Waiting for network + DNS..." + local i ping_ok=0 dns_ok=0 + # We test L3 (gateway/internet) and DNS separately so we can give a useful + # error message instead of a generic "network never came up". for i in {1..30}; do + if [[ $ping_ok -eq 0 ]] && pct exec "$CTID" -- bash -c "ping -c 1 -W 2 1.1.1.1 >/dev/null 2>&1 || ping -c 1 -W 2 ${GATEWAY:-1.1.1.1} >/dev/null 2>&1"; then + ping_ok=1 + fi if pct exec "$CTID" -- getent hosts deb.debian.org >/dev/null 2>&1; then - msg_ok "Network up" - return 0 + dns_ok=1 + break fi sleep 2 done - msg_err "Network never came up. Check bridge/VLAN/gateway settings." + + if [[ $dns_ok -eq 1 ]]; then + msg_ok "Network + DNS up" + return 0 + fi + + if [[ $ping_ok -eq 1 ]]; then + msg_err "L3 connectivity OK but DNS resolution failed." + msg_err "Container can reach the internet but can't resolve names." + msg_err "Re-run with NAMESERVER= set, or fix /etc/resolv.conf inside the LXC." + else + msg_err "Network never came up. Check bridge/VLAN/gateway settings:" + msg_err " pct exec $CTID -- ip a" + msg_err " pct exec $CTID -- ip r" + msg_err " pct exec $CTID -- ping -c2 ${GATEWAY:-}" + fi exit 1 }