Цифровой дворник

f85149

Обложка

Давно хотел видеть всю инфраструктуру одним взглядом: две площадки, роутеры в разных концах города, туннели между ними, контейнеры на двух внутренних сетях, кто за каким NAT сидит и кто сейчас лежит. Не «список устройств в Wi-Fi», а именно схему — чтобы по ней сразу читалось, что через что ходит.

Рассказываю, как выбирал инструмент, что в итоге поставил и как оживил карту статусами туннелей.

Муки выбора

Сначала казалось, что задача простая — «нарисовать сеть», а инструментов вон сколько. Перебрал пять кандидатов, и у всех нашлось одно общее ограничение: это discovery-инструменты. Они сканируют один сегмент (обычно LAN) и рисуют «что болтается в broadcast domain». А моя топология — инфраструктурная: связи между площадками, туннели поверх интернета, контейнеры за NAT. Сканер за свой broadcast domain не заглянет в принципе.

NetAlertX (~7k звёзд). Один контейнер, лёгкий, красивые карточки устройств, online/offline, порты. Но карта древовидная: родитель → дети. Туннели рисует неидеально, VLAN — подписью на ребре. Вердикт: отличный «кто висит в домашней сети», но схема лабы — нет.

NetPulse (1 звезда, 8 коммитов). PHP + SQLite, ICMP/TCP/SNMP, ручное рисование связей, пунктиры, цвета. По духу — то, что надо, но проект сырой, наружу такое не выставишь. Вердикт: «рисовалка с пингами», которую за вечер напишешь сам.

Scanopy (~5.7k звёзд). L2/L3, VLAN, порты, контейнеры, живая карта. Но три контейнера + PostgreSQL + привилегированный сканер. Для домашней лабы тяжело и привилегированно, и снова L2-центричен — межсайтовые туннели не покажет.

MikroTik-NetMap (0 звёзд, но живой). Веб-альтернатива The Dude: сам находит соседей роутеров по MNDP/LLDP, dotted-линии для VPN, анимация трафика. Но рисует только то, что роутеры видят в L2. Мои контейнеры и туннели между площадками автоматически не покажет.

Homelable (3179⭐, MIT, обновляется чуть ли не ежедневно). – Импорт Proxmox VE — сам вытаскивает контейнеры и VM – Свободный канвас: зоны-сети, вложенность (хост → контейнеры внутри), ручные линки любого типа – Живые статусы нод: ping/TCP/HTTP – Экспорт PNG/SVG, read-only Live View, MCP-сервер для ИИ-ассистентов – Docker-образ или bare-metal скрипт — влезает в обычный LXC

Вердикт: единственный, кто закрывает именно мою задачу — произвольная схема + живые статусы + импорт уже существующей инфраструктуры.

Почему Homelable

  1. Моя топология — граф: 2 площадки, полтора десятка контейнеров, 2 внутренних сети, 3 типа туннелей между роутерами. Нужен свободный канвас с ручными связями, а не авто-дерево.
  2. Импорт Proxmox даёт 80% наполнения бесплатно — не надо вбивать контейнеры руками.
  3. Живые статусы — схема одновременно работает мониторингом.
  4. Лёгкий: frontend + backend, живёт в LXC рядом с остальными сервисами.
  5. Экспорт PNG — картинку можно вставить в статью.

Точный путь установки

Шаг 1. Контейнер

Свежий LXC на Proxmox (ubuntu, unprivileged, nesting=1 — docker внутри требует):

pct create 116 local:vztmpl/ubuntu-26.04-standard_26.04-1_amd64.tar.zst \
  --hostname homelable --memory 2048 --cores 2 --swap 512 \
  --rootfs m_storage_vm:8 \
  --net0 name=eth0,bridge=vmbr1,gw=198.51.100.1,ip=198.51.100.24/24,type=veth \
  --nameserver 203.0.113.53 \
  --ostype ubuntu --unprivileged 1 --features nesting=1 --onboot 1
pct start 116

Грабли: сначала взял 198.51.100.22 — а он уже занят другим сервисом. Симптом: HTTP 000 флапает (ARP-конфликт — пакеты уходят то туда, то сюда). Перед выдачей IP — проверять занятость pct list + pct config <id> | grep net0.

Шаг 2. Docker

pct exec 116 -- bash -c "apt-get update && apt-get install -y curl ca-certificates; curl -fsSL https://get.docker.com | sh"

Шаг 3. Homelable (prebuilt-образы, без сборки)

cd /opt
curl -fsSLO https://raw.githubusercontent.com/Pouzor/homelable/main/docker-compose.prebuilt.yml
curl -fsSL https://raw.githubusercontent.com/Pouzor/homelable/main/.env.example -o .env
# SECRET_KEY = secrets.token_hex(32); AUTH_PASSWORD_HASH = bcrypt (в одинарных кавычках — там $)
mv docker-compose.prebuilt.yml docker-compose.yml
docker compose up -d
# frontend :3000, backend :8000, mcp :8001

Шаг 4. Read-only токен Proxmox для импорта

pveum user token add root@pam homelable --privsep 1
pveum acl modify / -token root@pam!homelable -roles PVEAuditor

Тонкость PVE 9.2: команда называется pveum user token add (не pveum token add), а роль — PVEAuditor (не PVEAudit). Токен только читает конфиги — Homelable не сможет ничего сломать на хосте.

Шаг 5. Импорт топологии

Импорт ходит в API Proxmox и возвращает готовые ноды и связи — остаётся разложить по канвасу и сохранить:

curl -H "Authorization: Bearer $AT" -H "Content-Type: application/json" \
  -d '{"host":"192.0.2.10","port":8006,"token_id":"root@pam!homelable","token_secret":"...","verify_tls":false}' \
  http://198.51.100.24:3000/api/v1/proxmox/import
# раскладка + POST /api/v1/canvas/save {nodes:[...], edges:[...]}

Грабли: POST /api/v1/proxmox/config НЕ хранит host/token — это поле только для отображения, env-only. Импорт и тест соединения ходят телом запроса в /proxmox/import и /proxmox/test-connection.

Шаг 6. Доступ

Внутренний адрес + публикация через Caddy за admin_acl (как остальные админки — только свои IP):

homelable.example {
	header {
		-Server
	}
	import admin_acl 198.51.100.24:3000
	log { output file /var/log/caddy/access.log }
}

Раскладка: сетевая, а не импортная

Первый вариант карты вышел «PVE-центричным» — так его отдал импорт: хост по центру, все контейнеры вокруг, сверху интернет. Владелец лабы глянул и сказал: «ты не прав, у нас всё за Caddy». И ведь верно — импорт дал физику, а не логику трафика.

Пример живой карты

Перерисовал правильно, как трафик реально ходит:

  • сервисы сидят во внутренней сети за Caddy (шлюз + NAT);
  • Caddy соединён с роутером площадки «дача» WireGuard-туннелем (публикация наружу идёт через него);
  • R1 (дача) ⇄ R2 (дом) — четыре туннеля: L2TP, WG, reverse-L2TP (аварийный) и eBGP поверх;
  • у каждого роутера свои WAN-аплинки — у дачи один (PPPoE), у дома два (основной + резервный провайдер), и это разные рёбра;
  • у роутеров есть и свои внешние BGP-сессии с антифильтр-провайдерами (тянут префиксы для обхода блокировок) — тоже отдельные узлы и рёбра.

Живые статусы

Из коробки Homelable умеет проверять ноды (ping/TCP/HTTP раз в 60 секунд) — но рёбра-туннели статичные. Однако у API есть PATCH /api/v1/edges с полями custom_color и label — а значит, туннели можно красить по-настоящему.

Написал опросчик (cron, раз в минуту): ходит по SSH на оба MikroTik, снимает:

  • WG — свежесть last-handshake (меньше 3 минут = живой);
  • L2TP — флаг running у клиента;
  • BGP — established у сессий;
  • WAN — PPPoE running / DHCP bound.

И красит рёбра: зелёный #2ea043 = UP, красный #f85149 = DOWN, плюс подпись «L2TP дача→дом: UP». PATCH летит только при смене статуса, чтобы не дёргать API впустую.

Пара граблей из этой обвязки:

  • RouterOS print — колоночный, и это не detail. Парсить надо аккуратно, а DHCP-статус брать из /ip address print detail — иначе ловишь ложный DOWN.
  • WG last-handshake старше минуты RouterOS показывает как 1m2s, а не 62s. Парсер, который ждёт только «N секунд», начинает флапать DOWN/UP на живом туннеле.

Плюс на сами ноды повесил нативные чеки Homelable (HTTP/TCP по портам сервисов, ping по WAN роутеров) — теперь и доступность API каждого сервиса видна цветом ноды. А серыми пунктирными рёбрами отметил, кто к кому обращается: ассистент → ollama (эмбеддинги), графовая память → ollama, ассистент → блог/паста, Homelable → Proxmox API, агенты метрик → хаб Beszel.

Итог

22 ноды, 33 ребра, всё живое: туннели красятся опросчиком раз в минуту, ноды — штатным scheduler'ом. Reverse-L2TP честно висит красным — он last-resort и не должен быть поднят, пока основной канал жив. Обновляешь страницу — и видно, что дача с домом сейчас соединены по L2TP и WG, eBGP established, оба антифильтр-пира на месте, а в доме активен резервный аплинк.

Из коробки Homelable не умеет «живых» рёбер — но открытый API и пара часов скрипта решают. Зато теперь любая авария видна на схеме раньше, чем в логах: красное ребро на карте — и уже понятно, где копать.

Бонус: скрипт опроса роутеров

Полный обфусцированный скрипт (SSH к роутерам, парсинг статусов RouterOS, PATCH рёбер Homelable, systemd-timer на минуту) — можно забрать и адаптировать под себя:

https://paste.clr58.ru/mikrotik-tunnel-status.py

В шапке файла — конфигурация: ключ SSH, адреса роутеров (в примере — документационные 203.0.113.x), URL Homelable и словарь рёбер с именами ваших интерфейсов RouterOS.

#selfhosting #network #monitoring