Docker sets iptables FORWARD policy to DROP, which blocks libvirt's NAT networking (libvirt defaults to nftables which doesn't interact with Docker's iptables chain). Fix: setup-libvirt.sh now detects Docker and offers to switch libvirt to the iptables firewall backend, so both sets of rules coexist. The --check command warns about this mismatch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
141 lines
5.3 KiB
Bash
Executable File
141 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Setup sudo-less libvirt access for KVM-based harmony examples.
|
|
#
|
|
# Run once on a fresh machine. After this, all KVM operations work
|
|
# without sudo — libvirt authenticates via group membership.
|
|
#
|
|
# Usage:
|
|
# ./setup-libvirt.sh # interactive, asks before each step
|
|
# ./setup-libvirt.sh --yes # non-interactive, runs everything
|
|
|
|
USER="${USER:-$(whoami)}"
|
|
AUTO_YES=false
|
|
[[ "${1:-}" == "--yes" ]] && AUTO_YES=true
|
|
|
|
green() { printf '\033[32m%s\033[0m\n' "$*"; }
|
|
red() { printf '\033[31m%s\033[0m\n' "$*"; }
|
|
bold() { printf '\033[1m%s\033[0m\n' "$*"; }
|
|
|
|
confirm() {
|
|
if $AUTO_YES; then return 0; fi
|
|
read -rp "$1 [Y/n] " answer
|
|
[[ -z "$answer" || "$answer" =~ ^[Yy] ]]
|
|
}
|
|
|
|
bold "Harmony KVM/libvirt setup"
|
|
echo
|
|
|
|
# ── Step 1: Install packages ────────────────────────────────────────────
|
|
|
|
echo "Checking required packages..."
|
|
MISSING=()
|
|
for pkg in qemu-full libvirt dnsmasq ebtables; do
|
|
if ! pacman -Qi "$pkg" &>/dev/null; then
|
|
MISSING+=("$pkg")
|
|
fi
|
|
done
|
|
|
|
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
|
echo "Missing packages: ${MISSING[*]}"
|
|
if confirm "Install them?"; then
|
|
sudo pacman -S --needed "${MISSING[@]}"
|
|
else
|
|
red "Skipped package installation"
|
|
fi
|
|
else
|
|
green "[ok] All packages installed"
|
|
fi
|
|
|
|
# ── Step 2: Add user to libvirt group ────────────────────────────────────
|
|
|
|
if groups "$USER" 2>/dev/null | grep -qw libvirt; then
|
|
green "[ok] $USER is in libvirt group"
|
|
else
|
|
echo "$USER is NOT in the libvirt group"
|
|
if confirm "Add $USER to libvirt group?"; then
|
|
sudo usermod -aG libvirt "$USER"
|
|
green "[ok] Added $USER to libvirt group"
|
|
echo " Note: you need to log out and back in (or run 'newgrp libvirt') for this to take effect"
|
|
fi
|
|
fi
|
|
|
|
# ── Step 3: Start libvirtd ───────────────────────────────────────────────
|
|
|
|
if systemctl is-active --quiet libvirtd; then
|
|
green "[ok] libvirtd is running"
|
|
else
|
|
echo "libvirtd is not running"
|
|
if confirm "Enable and start libvirtd?"; then
|
|
sudo systemctl enable --now libvirtd
|
|
green "[ok] libvirtd started"
|
|
fi
|
|
fi
|
|
|
|
# ── Step 4: Default storage pool ─────────────────────────────────────────
|
|
|
|
if virsh -c qemu:///system pool-info default &>/dev/null; then
|
|
green "[ok] Default storage pool exists"
|
|
else
|
|
echo "Default storage pool does not exist"
|
|
if confirm "Create default storage pool at /var/lib/libvirt/images?"; then
|
|
sudo virsh pool-define-as default dir --target /var/lib/libvirt/images
|
|
sudo virsh pool-autostart default
|
|
sudo virsh pool-start default
|
|
green "[ok] Default storage pool created"
|
|
fi
|
|
fi
|
|
|
|
# ── Step 5: Fix Docker + libvirt FORWARD conflict ────────────────────────
|
|
|
|
# Docker sets iptables FORWARD policy to DROP, which blocks libvirt NAT.
|
|
# Libvirt defaults to nftables which doesn't interact with Docker's iptables.
|
|
# Fix: switch libvirt to iptables backend so rules coexist with Docker.
|
|
|
|
if docker info &>/dev/null; then
|
|
echo "Docker detected."
|
|
NETCONF="/etc/libvirt/network.conf"
|
|
if grep -q '^firewall_backend' "$NETCONF" 2>/dev/null; then
|
|
CURRENT=$(grep '^firewall_backend' "$NETCONF" | head -1)
|
|
if echo "$CURRENT" | grep -q 'iptables'; then
|
|
green "[ok] libvirt firewall_backend is already iptables"
|
|
else
|
|
echo "libvirt firewall_backend is: $CURRENT"
|
|
echo "Docker's iptables FORWARD DROP will block libvirt NAT."
|
|
if confirm "Switch libvirt to iptables backend?"; then
|
|
sudo sed -i 's/^firewall_backend.*/firewall_backend = "iptables"/' "$NETCONF"
|
|
echo "Restarting libvirtd to apply..."
|
|
sudo systemctl restart libvirtd
|
|
green "[ok] Switched to iptables backend"
|
|
fi
|
|
fi
|
|
else
|
|
echo "libvirt uses nftables (default), but Docker's iptables FORWARD DROP blocks NAT."
|
|
if confirm "Set libvirt to use iptables backend (recommended with Docker)?"; then
|
|
echo 'firewall_backend = "iptables"' | sudo tee -a "$NETCONF" >/dev/null
|
|
echo "Restarting libvirtd to apply..."
|
|
sudo systemctl restart libvirtd
|
|
# Re-activate networks so they get iptables rules
|
|
for net in $(virsh -c qemu:///system net-list --name 2>/dev/null); do
|
|
virsh -c qemu:///system net-destroy "$net" 2>/dev/null
|
|
virsh -c qemu:///system net-start "$net" 2>/dev/null
|
|
done
|
|
green "[ok] Switched to iptables backend and restarted networks"
|
|
fi
|
|
fi
|
|
else
|
|
green "[ok] Docker not detected, no FORWARD conflict"
|
|
fi
|
|
|
|
# ── Done ─────────────────────────────────────────────────────────────────
|
|
|
|
echo
|
|
bold "Setup complete."
|
|
echo
|
|
echo "If you were added to the libvirt group, apply it now:"
|
|
echo " newgrp libvirt"
|
|
echo
|
|
echo "Then verify:"
|
|
echo " cargo run -p opnsense-vm-integration -- --check"
|