feat: guest-dhcp.sh — aktifkan DHCP NIC macvlan di dalam guest

This commit is contained in:
oxpoe committed 2026-10-17 14:14:52 +07:00
1 parent 4a86be23c8
commit 9392f8964b
2 files changed
+130 -57

No files matched your search

+41 -57
View File
@@ -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 <instance> [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 <iface>` | dari default route host | Interface fisik host untuk parent macvlan |
| `--network <name>` | `eth200` | Nama network macvlan di incus |
| `--device <name>` | `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=<network> name=<device>` ke instance (hotplug).
4. Aktifkan DHCP di guest:
- **NetworkManager** → `nmcli`
- **systemd-networkd** → `/etc/systemd/network/20-<device>.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 <instance>/root/guest-dhcp.sh
incus exec <instance> -- 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-<if>.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 <instance> 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
Executable
+89
View File
@@ -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