feat: skrip auto pasang NIC macvlan + DHCP untuk instance incus
This commit is contained in:
commit
4a86be23c8
3 files changed
+234
No files matched your search
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 oxpoe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,85 @@
|
||||
# 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.
|
||||
|
||||
Cocok untuk instance yang perlu diakses langsung dari LAN (web, SSH, service yang di-publish podman/docker di dalamnya).
|
||||
|
||||
## Pemakaian
|
||||
|
||||
```bash
|
||||
./incus-macvlan.sh <instance> [device] [network]
|
||||
```
|
||||
|
||||
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 | 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 |
|
||||
| `-h, --help` | | Bantuan |
|
||||
|
||||
Argumen posisional: `$1` instance, `$2` device, `$3` network. Opsi mengalahkan posisional.
|
||||
|
||||
## 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)
|
||||
|
||||
```bash
|
||||
incus network create eth200 --type=macvlan parent=enp2s0
|
||||
```
|
||||
|
||||
Atau biarkan skrip membuatnya dengan `--create`.
|
||||
|
||||
## Syarat
|
||||
|
||||
- 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.
|
||||
|
||||
## Catatan penting
|
||||
|
||||
- **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.:
|
||||
|
||||
```ini
|
||||
# /etc/systemd/network/20-eth1.network
|
||||
[Match]
|
||||
Name=eth1
|
||||
[Network]
|
||||
DHCP=yes
|
||||
[DHCPv4]
|
||||
RouteMetric=50
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
## Lisensi
|
||||
|
||||
MIT — lihat [LICENSE](LICENSE).
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# incus-macvlan.sh — pasang NIC macvlan + aktifkan DHCP di guest incus,
|
||||
# supaya instance langsung dapat IP di LAN (mis. 192.168.200.x).
|
||||
#
|
||||
# Pakai:
|
||||
# ./incus-macvlan.sh <instance> [device] [network]
|
||||
# ./incus-macvlan.sh web1
|
||||
# ./incus-macvlan.sh web1 eth1 eth200
|
||||
#
|
||||
# Opsi:
|
||||
# --parent <iface> interface fisik host (default: dari default route host)
|
||||
# --network <name> nama network macvlan (default: eth200)
|
||||
# --device <name> nama NIC di guest (default: eth1)
|
||||
# --create buat network macvlan kalau belum ada
|
||||
# -h, --help bantuan
|
||||
#
|
||||
# Idempotent: aman dijalankan berulang. Kalau instance sudah punya NIC
|
||||
# di network macvlan (termasuk dari profile), NIC tidak ditambahkan lagi.
|
||||
set -euo pipefail
|
||||
|
||||
INSTANCE=""; DEVICE="eth1"; NETWORK="eth200"; PARENT=""; CREATE=0
|
||||
POS=()
|
||||
|
||||
say(){ printf '%s\n' "$*"; }
|
||||
die(){ printf 'error: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--parent) PARENT="${2:?--parent butuh nilai}"; shift 2 ;;
|
||||
--network) NETWORK="${2:?--network butuh nilai}"; shift 2 ;;
|
||||
--device) DEVICE="${2:?--device butuh nilai}"; shift 2 ;;
|
||||
--create) CREATE=1; shift ;;
|
||||
-h|--help) sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
-*) die "opsi tak dikenal: $1" ;;
|
||||
*) POS+=("$1"); shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
INSTANCE="${POS[0]:-}"
|
||||
[ -n "${POS[1]:-}" ] && DEVICE="${POS[1]}"
|
||||
[ -n "${POS[2]:-}" ] && NETWORK="${POS[2]}"
|
||||
[ -n "$INSTANCE" ] || die "pakai: $(basename "$0") <instance> [device] [network]"
|
||||
|
||||
[[ "$DEVICE" =~ ^[A-Za-z0-9_.-]+$ ]] || die "nama device tidak valid: $DEVICE"
|
||||
[[ "$NETWORK" =~ ^[A-Za-z0-9_.-]+$ ]] || die "nama network tidak valid: $NETWORK"
|
||||
command -v incus >/dev/null 2>&1 || die "perintah 'incus' tidak ditemukan"
|
||||
incus info "$INSTANCE" </dev/null >/dev/null 2>&1 || die "instance '$INSTANCE' tidak ditemukan"
|
||||
|
||||
if [ -z "$PARENT" ]; then
|
||||
PARENT="$(ip route show default 2>/dev/null | awk '{print $5; exit}')"
|
||||
PARENT="${PARENT:-enp2s0}"
|
||||
fi
|
||||
|
||||
# ---- network macvlan ----
|
||||
if incus network list -c n -f csv </dev/null 2>/dev/null | grep -qx "$NETWORK"; then
|
||||
say "network '$NETWORK' sudah ada"
|
||||
else
|
||||
[ "$CREATE" = 1 ] || die "network '$NETWORK' belum ada (pakai --create, parent $PARENT)"
|
||||
say "membuat network macvlan '$NETWORK' (parent $PARENT)"
|
||||
incus network create "$NETWORK" --type=macvlan parent="$PARENT" </dev/null
|
||||
fi
|
||||
|
||||
# ---- pastikan running ----
|
||||
STATE="$(incus info "$INSTANCE" </dev/null | awk -F': ' '/^Status:/{print $2}')"
|
||||
if [ "$STATE" != "RUNNING" ]; then
|
||||
say "menyalakan instance '$INSTANCE'"
|
||||
incus start "$INSTANCE" </dev/null
|
||||
sleep 3
|
||||
fi
|
||||
|
||||
# ---- pasang NIC (kalau belum ada NIC di network ini, termasuk dari profile) ----
|
||||
if incus config show --expanded "$INSTANCE" </dev/null 2>/dev/null | grep -q "network: $NETWORK"; then
|
||||
say "instance sudah punya NIC di network '$NETWORK' (dilewati)"
|
||||
elif incus config device list "$INSTANCE" </dev/null | grep -qx "$DEVICE"; then
|
||||
say "device '$DEVICE' sudah ada (dilewati)"
|
||||
else
|
||||
if incus config device add "$INSTANCE" "$DEVICE" nic network="$NETWORK" name="$DEVICE" </dev/null; then
|
||||
say "NIC '$DEVICE' (network $NETWORK) ditambahkan"
|
||||
else
|
||||
say "peringatan: gagal menambah NIC '$DEVICE' (lanjut cek DHCP)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---- aktifkan DHCP di guest untuk semua NIC tanpa IPv4 ----
|
||||
say "mengaktifkan DHCP di guest"
|
||||
incus exec "$INSTANCE" -- sh -c '
|
||||
configure_one() {
|
||||
dev="$1"
|
||||
if systemctl is-active --quiet NetworkManager 2>/dev/null; then
|
||||
nmcli device connect "$dev" >/dev/null 2>&1 || true
|
||||
elif systemctl is-active --quiet systemd-networkd 2>/dev/null || [ -d /etc/systemd/network ]; then
|
||||
printf "[Match]\nName=%s\n[Network]\nDHCP=yes\n" "$dev" > "/etc/systemd/network/20-$dev.network"
|
||||
elif command -v dhcpcd >/dev/null 2>&1; then dhcpcd "$dev" >/dev/null 2>&1 || true
|
||||
elif command -v dhclient >/dev/null 2>&1; then dhclient "$dev" >/dev/null 2>&1 || true
|
||||
elif command -v udhcpc >/dev/null 2>&1; then udhcpc -i "$dev" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
for i in /sys/class/net/*; do
|
||||
dev=$(basename "$i"); [ "$dev" = lo ] && continue
|
||||
ip -4 addr show "$dev" 2>/dev/null | grep -q "inet " && continue
|
||||
configure_one "$dev"
|
||||
done
|
||||
systemctl restart systemd-networkd >/dev/null 2>&1 || true
|
||||
' </dev/null || say "peringatan: konfigurasi DHCP di guest gagal (lanjut)"
|
||||
|
||||
# ---- tunggu IP LAN ----
|
||||
IP=""
|
||||
for _ in $(seq 1 20); do
|
||||
IP="$(incus list "$INSTANCE" -c 4 -f csv </dev/null 2>/dev/null \
|
||||
| tr ',' '\n' | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' \
|
||||
| grep -vE '^(10\.|127\.)' | head -1 || true)"
|
||||
[ -n "$IP" ] && break
|
||||
sleep 1
|
||||
done
|
||||
|
||||
say ""
|
||||
if [ -n "$IP" ]; then
|
||||
say "instance : $INSTANCE"
|
||||
say "network : $NETWORK (parent $PARENT)"
|
||||
say "IP LAN : $IP"
|
||||
say "SSH : ssh root@$IP"
|
||||
else
|
||||
say "instance : $INSTANCE"
|
||||
say "IP LAN : belum terdeteksi"
|
||||
say "cek : incus exec $INSTANCE -- ip -4 addr"
|
||||
exit 1
|
||||
fi
|
||||
Reference in new issue
Block a user