diff --git a/README.md b/README.md index dcd3a76..6a77416 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,68 @@ # auto-macvlan -Skrip untuk memasang **NIC macvlan** ke instance **Incus** dan mengaktifkan **DHCP di guest**, sehingga instance langsung mendapat IP di LAN (mis. `192.168.200.x`) — bukan IP NAT internal incus. +Skrip **untuk dijalankan di dalam guest** incus: mengaktifkan **DHCP** pada NIC tambahan (mis. macvlan) supaya guest langsung mendapat IP LAN (`192.168.200.x`). -Cocok untuk instance yang perlu diakses langsung dari LAN (web, SSH, service yang di-publish podman/docker di dalamnya). +Sisi host (menambah NIC macvlan ke instance) dianggap sudah diatur sendiri. -## Pemakaian +## `guest-dhcp.sh` + +Jalankan di dalam guest (Debian/Ubuntu/Alpine, dll): ```bash -./incus-macvlan.sh [device] [network] +# auto: semua NIC non-lo yang belum punya IPv4 +./guest-dhcp.sh + +# NIC tertentu +./guest-dhcp.sh eth1 + +# beberapa NIC +./guest-dhcp.sh eth1 eth2 ``` -Contoh: - -```bash -# pakai default: device eth1, network eth200 -./incus-macvlan.sh web1 - -# tentukan device & network -./incus-macvlan.sh web1 eth1 eth200 - -# buat network macvlan bila belum ada -./incus-macvlan.sh web1 --create --parent enp2s0 -``` - -## Opsi +Opsi: | Opsi | Default | Keterangan | |---|---|---| -| `--parent ` | dari default route host | Interface fisik host untuk parent macvlan | -| `--network ` | `eth200` | Nama network macvlan di incus | -| `--device ` | `eth1` | Nama NIC di dalam guest | -| `--create` | mati | Buat network macvlan kalau belum ada | +| `--metric N` | `50` | `RouteMetric` DHCPv4. Lebih kecil dari NIC incusbr0 (100) agar NIC ini jadi default route. `0` = tidak di-set. | | `-h, --help` | | Bantuan | -Argumen posisional: `$1` instance, `$2` device, `$3` network. Opsi mengalahkan posisional. +### Cara menjalankan -## Yang dilakukan - -1. Cek instance ada dan berjalan (start bila perlu). -2. Pastikan network macvlan ada (buat dengan `--create` bila perlu). -3. Pasang NIC `nic network= name=` ke instance (hotplug). -4. Aktifkan DHCP di guest: - - **NetworkManager** → `nmcli` - - **systemd-networkd** → `/etc/systemd/network/20-.network` - - fallback: `dhcpcd` / `dhclient` / `udhcpc` -5. Tunggu dan tampilkan IP LAN. - -Idempotent — aman dijalankan ulang. - -## Persiapan network macvlan (sekali) +**Di dalam guest:** ```bash -incus network create eth200 --type=macvlan parent=enp2s0 +curl -fsSL https://gitea.oxpoe.qzz.io/oxpoe/auto-macvlan/raw/branch/main/guest-dhcp.sh | bash ``` -Atau biarkan skrip membuatnya dengan `--create`. +**Dari host incus:** -## Syarat +```bash +curl -fsSL https://gitea.oxpoe.qzz.io/oxpoe/auto-macvlan/raw/branch/main/guest-dhcp.sh -o /tmp/guest-dhcp.sh +incus file push /tmp/guest-dhcp.sh /root/guest-dhcp.sh +incus exec -- bash /root/guest-dhcp.sh +``` -- Host Incus punya NIC fisik yang terhubung ke LAN (parent, mis. `enp2s0`). -- **DHCP server di LAN** aktif (IP instance berasal dari router LAN, bukan incus). -- Guest punya salah satu DHCP client di atas. +### Yang dilakukan -## Catatan penting +- Mendeteksi NIC tanpa IPv4 (atau yang kamu sebutkan). +- Mengaktifkan DHCP sesuai pengelola jaringan yang tersedia: + **NetworkManager** (`nmcli`), **systemd-networkd** (`/etc/systemd/network/20-.network`), + **dhcpcd**, **dhclient**, atau **udhcpc**. +- Menulis `[DHCPv4] RouteMetric=50` (networkd) agar NIC LAN menang atas incusbr0. +- Menunggu dan mencetak IP tiap NIC. -- **Host Incus tidak bisa menghubungi instance lewat IP LAN macvlan** (batasan macvlan). Dari host, kelola lewat `incus exec`; instance tetap bisa diakses dari perangkat LAN lain. -- Bila instance punya **dua NIC** (incusbr0 + macvlan) dan default route dari incusbr0 menang, balasan ke LAN bisa keluar lewat NIC yang salah. Solusi: jadikan macvlan default dengan metrik lebih rendah, mis.: +Persisten: file `.network` tetap ada setelah reboot (untuk systemd-networkd). - ```ini - # /etc/systemd/network/20-eth1.network - [Match] - Name=eth1 - [Network] - DHCP=yes - [DHCPv4] - RouteMetric=50 +## Catatan + +- Skrip ini **hanya** mengurus DHCP di guest. Menambah NIC ke network macvlan tetap di host: + ```bash + incus config device add eth1 nic network=eth200 name=eth1 ``` - - atau nonaktifkan NIC incusbr0 bila tidak diperlukan. -- IP yang didapat dinamis dari LAN. Kalau butuh statis, atur DHCP reservation di router atau konfigurasi statis di guest. +- Bila guest punya dua NIC (incusbr0 + macvlan), jadikan macvlan sebagai default + (metrik lebih rendah) agar balasan ke LAN tidak keluar lewat NIC yang salah. + `--metric` (default 50) sudah melakukan ini untuk systemd-networkd. +- Host incus tidak bisa menjangkau guest lewat IP macvlan (batasan macvlan); dari host pakai `incus exec`. ## Lisensi diff --git a/guest-dhcp.sh b/guest-dhcp.sh new file mode 100755 index 0000000..aa7a7d4 --- /dev/null +++ b/guest-dhcp.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# +# guest-dhcp.sh — aktifkan DHCP untuk NIC tambahan (mis. macvlan) DI DALAM guest incus. +# Jalankan di dalam guest (SSH atau `incus exec`), karena sisi host (add NIC) sudah diatur. +# +# Pakai: +# ./guest-dhcp.sh # auto: semua NIC non-lo yang belum punya IPv4 +# ./guest-dhcp.sh eth1 # NIC tertentu +# ./guest-dhcp.sh eth1 eth2 +# +# Opsi: +# --metric N RouteMetric DHCPv4 (default 50; 0 = tidak di-set) +# lebih kecil dari NIC incusbr0 (100) agar NIC ini jadi default route +# -h, --help +# +# Idempotent. Mendukung NetworkManager, systemd-networkd, dhcpcd, dhclient, udhcpc. +set -euo pipefail + +METRIC=50 +TARGETS=() +while [ $# -gt 0 ]; do + case "$1" in + --metric) METRIC="${2:?--metric butuh angka}"; shift 2 ;; + -h|--help) sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; + -*) echo "opsi tak dikenal: $1" >&2; exit 2 ;; + *) TARGETS+=("$1"); shift ;; + esac +done + +have_ip(){ ip -4 addr show "$1" 2>/dev/null | grep -q 'inet '; } + +# auto-deteksi NIC tanpa IPv4 +if [ ${#TARGETS[@]} -eq 0 ]; then + for d in /sys/class/net/*; do + n="$(basename "$d")"; [ "$n" = lo ] && continue + have_ip "$n" || TARGETS+=("$n") + done +fi + +if [ ${#TARGETS[@]} -eq 0 ]; then + echo "Semua NIC sudah punya IPv4. Tidak ada yang perlu dikonfigurasi." + exit 0 +fi + +# deteksi pengelola jaringan +NM=0; NETD=0 +if command -v systemctl >/dev/null 2>&1; then + systemctl is-active --quiet NetworkManager 2>/dev/null && NM=1 + systemctl is-active --quiet systemd-networkd 2>/dev/null && NETD=1 +fi + +for iface in "${TARGETS[@]}"; do + echo "== konfigurasi $iface" + if [ "$NM" = 1 ]; then + nmcli device connect "$iface" >/dev/null 2>&1 || { + nmcli connection add type ethernet ifname "$iface" con-name "$iface" ipv4.method auto >/dev/null 2>&1 || true + nmcli connection up "$iface" >/dev/null 2>&1 || true + } + elif [ "$NETD" = 1 ] || [ -d /etc/systemd/network ]; then + { + printf '[Match]\nName=%s\n[Network]\nDHCP=yes\n' "$iface" + [ "$METRIC" -gt 0 ] && printf '[DHCPv4]\nRouteMetric=%s\n' "$METRIC" + } > "/etc/systemd/network/20-$iface.network" + systemctl restart systemd-networkd >/dev/null 2>&1 || true + elif command -v dhcpcd >/dev/null 2>&1; then + dhcpcd "$iface" >/dev/null 2>&1 || true + elif command -v dhclient >/dev/null 2>&1; then + dhclient "$iface" >/dev/null 2>&1 || true + elif command -v udhcpc >/dev/null 2>&1; then + udhcpc -i "$iface" >/dev/null 2>&1 || true + else + echo " ! tidak ada DHCP client (NetworkManager/systemd-networkd/dhcpcd/dhclient/udhcpc)" >&2 + exit 1 + fi +done + +# tunggu IP +for _ in $(seq 1 20); do + ready=0 + for iface in "${TARGETS[@]}"; do have_ip "$iface" && ready=$((ready+1)); done + [ "$ready" -eq ${#TARGETS[@]} ] && break + sleep 1 +done + +echo +for iface in "${TARGETS[@]}"; do + ip4="$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1)" + printf '%-8s %s\n' "$iface" "${ip4:-belum dapat IP}" +done