Skip to content

selectel‐lxc

Matvey Gladkikh edited this page Sep 6, 2025 · 1 revision
#!/bin/bash
# Debian 12 @ Selectel: переключаем сеть на ifupdown+bridge br0, убираем cloud-init.
# КРАТКИЙ ПЛАН:
# 1) autodetect uplink + IP/GW/DNS
# 2) закрепить стабильное имя через systemd .link (wan0) на будущее
# 3) прописать /etc/network/interfaces: br0 c публичным IP, bridge_ports "wan0 <текущий_IF>"
# 4) отключить cloud-init для сети и выпилить его
# 5) поднять сеть сейчас, проверить; после перезагрузки будет уже 'wan0'.

set -euo pipefail

# --- helpers ---
ts() { date +%F_%H-%M-%S; }
prefix2mask() { local p=$1 m=4294967295; m=$(( (m << (32-p)) & 4294967295 )); printf "%d.%d.%d.%d\n" $((m>>24&255)) $((m>>16&255)) $((m>>8&255)) $((m&255)); }

echo "[1/7] Detect uplink + IPv4…"
DEF_IF=$(ip -o -4 route show to default | awk '{print $5}' | head -n1 || true)
[ -n "${DEF_IF:-}" ] || { echo "[ERR] No default IPv4 route"; exit 1; }

IP_CIDR=$(ip -o -4 addr show dev "$DEF_IF" | awk '$3=="inet"{print $4}' | head -n1 || true)
[ -n "${IP_CIDR:-}" ] || { echo "[ERR] No IPv4 on $DEF_IF"; exit 1; }
IP=${IP_CIDR%/*}; PFX=${IP_CIDR#*/}; NETMASK=$(prefix2mask "$PFX")
GW=$(ip -4 route show default 0.0.0.0/0 | awk '{print $3}' | head -n1)
[ -n "$GW" ] || { echo "[ERR] No default GW"; exit 1; }
DNS=$(awk '/^nameserver/{printf $2" "}' /etc/resolv.conf 2>/dev/null | sed 's/ $//'); [ -n "${DNS:-}" ] || DNS="1.1.1.1 8.8.8.8"
MAC=$(cat "/sys/class/net/$DEF_IF/address")
echo "    IF=$DEF_IF MAC=$MAC IP=$IP/$PFX NETMASK=$NETMASK GW=$GW DNS=[$DNS]"

echo "[2/7] Install ifupdown + bridge-utils…"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y >/dev/null 2>&1 || true
apt-get install -y ifupdown bridge-utils >/dev/null

echo "[3/7] Backup configs…"
BKP=backup.$(ts)
[ -f /etc/network/interfaces ] && cp -a /etc/network/interfaces /etc/network/interfaces.$BKP
[ -d /etc/cloud ] && cp -a /etc/cloud /etc/cloud.$BKP || true
[ -f /etc/lxc/default.conf ] && cp -a /etc/lxc/default.conf /etc/lxc/default.conf.$BKP || true
mkdir -p /etc/network/interfaces.d /etc/systemd/network /etc/cloud/cloud.cfg.d /etc/lxc

echo "[4/7] Pin stable name 'wan0' by MAC (applies after reboot)…"
cat >/etc/systemd/network/98-wan0.link <<EOF
[Match]
MACAddress=$MAC
[Link]
Name=wan0
EOF
udevadm control --reload || true

echo "[5/7] Write /etc/network/interfaces (br0 <- wan0 | $DEF_IF)…"
cat >/etc/network/interfaces <<EOF
# Loopback
auto lo
iface lo inet loopback

# Uplink (текущее имя) без IP — будет портом моста
allow-hotplug ${DEF_IF}
iface ${DEF_IF} inet manual

# Публичный мост с внешним IP
auto br0
iface br0 inet static
    address ${IP}
    netmask ${NETMASK}
    gateway ${GW}
    # Указываем ОБА имени: текущее и будущее стабильное (после ребута будет wan0)
    bridge_ports wan0 ${DEF_IF}
    bridge_fd 0
    bridge_hello 2
    bridge_maxage 12
    bridge_stp off
    dns-nameservers ${DNS}
EOF

echo "[6/7] Disable & remove cloud-init (network from ifupdown only)…"
# Запретить cloud-init трогать сеть
echo 'network: {config: disabled}' >/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
# Остановить/отключить сервисы (на всякий)
systemctl stop cloud-init cloud-init-local cloud-config cloud-final 2>/dev/null || true
systemctl disable cloud-init cloud-init-local cloud-config cloud-final 2>/dev/null || true
# Удалить пакет и следы
apt-get purge -y cloud-init >/dev/null 2>&1 || true
rm -rf /etc/cloud/ /var/lib/cloud/ || true

echo "[7/7] Bring network up NOW (safe sequence)…"
# Сбрасываем старый IP с uplink, поднимаем uplink как manual, затем мост
ifdown --force br0 2>/dev/null || true
ip addr flush dev "${DEF_IF}" || true
ifup "${DEF_IF}" || true
ifup br0
# Обеспечиваем дефолт через br0 (иногда маршрут остаётся на старом dev)
ip route replace default via "${GW}" dev br0 onlink

# Проверки
echo "[CHK] br0 address…"
ip -o -4 addr show dev br0 | grep -q "${IP}/" && echo " OK: br0 has ${IP}/${PFX}" || { echo " FAIL: br0 has no ${IP}"; exit 1; }
echo "[CHK] route to GW…"
ip r get "${GW}" >/dev/null 2>&1 && echo " OK: route to ${GW}" || { echo " FAIL: no route to GW"; exit 1; }

# Настройка LXC (если установлен): по умолчанию линк на br0
sed -i '/^lxc\.net\.0/d' /etc/lxc/default.conf 2>/dev/null || true
cat >>/etc/lxc/default.conf <<'EOF'
lxc.net.0.type = veth
lxc.net.0.link = br0
lxc.net.0.flags = up
EOF

echo
echo "=== DONE ==="
echo "br0 поднят, cloud-init удалён. Сейчас мост использует '${DEF_IF}',"
echo "после ПЕРЕЗАГРУЗКИ uplink будет называться 'wan0' автоматически (по MAC) —"
echo "конфиг уже учитывает оба имени в bridge_ports, так что всё поднимется само."
echo
echo "Сводка:"
ip -4 addr show br0
ip route
Clone this wiki locally