← Усі статті

Transparent Gateway · Proxmox · cloud-init · DevOps

Чому робочий Transparent Gateway ще не готовий до production

8 вересня 2026 р. · 4 хв читання

Відтворюваний deployment Transparent Gateway від Proxmox template до healthy gateway з двома відкинутими ручними шляхами

У попередніх трьох частинах я послідовно закрив DNS-витоки, прозоро завернув TCP-трафік у проксі та додав автоматичний конвеєр збору, перевірки й ранжування upstream. На схемі все вже виглядає як система. Але на практиці вона тримається на одному Debian-хості, який я кілька днів налаштовував руками.

Поки цей хост працює, проблема майже непомітна. Справжнє запитання з’являється пізніше: чи зможу я відтворити той самий gateway на чистій VM без пам’яті про випадкові команди, старі файли та порядок ручних виправлень?

У цій частині я не буду вдавати, що deployment уже автоматизований. Спочатку проведу аудит поточного стану, перевірю два очевидні підходи й сформулюю межу між Proxmox template, cloud-init, deployment та runtime. Практичну реалізацію винесу в окрему наступну частину.

Проблема: робочий gateway ще не означає відтворюваний gateway

Поточна VM не є повністю ручною. Proxmox створив її з cloud image, а cloud-init задав hostname, користувача, SSH-ключі та мережу. На самій машині це видно без здогадок:

Показати код
root@transparent-gateway-vm:~# systemd-detect-virt
kvm

root@transparent-gateway-vm:~# cloud-init status
status: done

root@transparent-gateway-vm:~# . /etc/os-release; echo "$PRETTY_NAME"
Debian GNU/Linux 13 (trixie)

Але далі автоматизація закінчується. Репозиторій лежить у /opt/transparent-gateway, поруч є локальні .env, inventory та файл credentials. Docker увімкнений у systemd, а контейнери мають restart policy. Окремого deployment-скрипта або systemd unit для всього gateway у репозиторії поки немає.

Тобто cloud-init створює сервер, але не створює сервіс. Між цими двома станами залишається набір ручних дій, які ніяк не зафіксовані.

Термінал Transparent Gateway: KVM, завершений cloud-init і шість запущених Docker Compose сервісів
Поточна VM вже створена через cloud-init і запускає шість Compose-сервісів. Але healthy-статус мають лише ASN updater, gateway і Redis — це один із сигналів, що runtime ще не має повної перевірки готовності.

Аудит перед автоматизацією: що насправді треба відтворити

Моя перша помилка була б почати одразу писати cloud-init. Перед автоматизацією треба зрозуміти, який фактичний стан ми намагаємося отримати.

У gateway зараз три різні мережеві ролі:

  • eth0 — management-мережа 192.168.88.0/24;
  • eth1 — клієнтська мережа 192.168.90.0/24, де gateway має адресу 192.168.90.1;
  • eth2 — лабораторна proxy/echo-мережа 10.10.10.0/24.

Поверх них працюють шість Compose-сервісів: Redis, ASN updater, fetcher, validator, ranker і сам gateway. Redis зберігає snapshots, validator монтує credentials лише для виконання proxy handshake, а gateway працює в network_mode: host, бо йому потрібні реальні інтерфейси, policy routing та правила перехоплення.

Це важливо: відтворити лише контейнери недостатньо. Якщо нова VM отримає інші інтерфейси, не матиме потрібного route або запустить gateway до готовності мережі, Docker формально працюватиме, але трафік клієнта не піде потрібним шляхом.

Перший глухий кут: просто клонувати готову VM

Найшвидший варіант очевидний: вимкнути поточну машину, зробити з неї template і надалі клонувати вже готовий gateway. Я майже пішов цим шляхом, бо він одразу дає всі пакети, Docker images і конфігурацію.

Проблема в тому, що такий template консервує не задум, а випадковий стан диска. Разом із корисними файлами в образ можуть потрапити:

  • старі credentials і provider tokens;
  • SSH host keys та cloud-init instance state;
  • Redis snapshot з попереднього середовища;
  • застарілі Docker images;
  • тимчасові backup-файли, про які вже ніхто не пам’ятає.

Через місяць незрозуміло, чим одна VM відрізняється від іншої і як оновити template без нового ручного ритуалу. Тому template має містити мінімальну операційну систему та cloud-init, а не готовий production state застосунку.

Другий глухий кут: запхати весь deployment у cloud-init

Після відмови від «золотого» образу виникає протилежна ідея: нехай cloud-init встановить Docker, клонує Git, створить усі файли, запише secrets і виконає docker compose up.

Для короткого демо це працює. Для gateway — швидко перетворюється на величезний блок runcmd, який важко повторно запустити та майже неможливо нормально тестувати. Ще гірше — cloud-init зберігає отриманий user-data на диску VM. Якщо передати там пароль проксі або API token, секрет залишиться у /var/lib/cloud/instances/... та може потрапити в логи.

У підсумку cloud-init знає забагато про застосунок, а застосунок залежить від одноразового механізму першого boot. Я знову отримую ручний сервер, тільки тепер ручні команди сховані у YAML.

Робоче розділення: template, bootstrap і deployment

Після двох невдалих крайнощів межа стала зрозумілою:

Показати код
Proxmox template

cloud-init: identity, SSH, network, базові пакети

deployment: checkout перевіреної версії, config, systemd

Docker Compose: сервіси та залежності

readiness check: чи можна вже віддавати трафік клієнтам

Cloud-init відповідає лише за те, щоб VM стала керованим Debian-хостом. Deployment-шар має бути звичайним кодом у репозиторії: його можна запустити ще раз, перевірити в review і прив’язати до конкретного Git commit або release.

Це також дає нормальну межу rollback. Якщо нова версія gateway не проходить readiness check, не потрібно відкочувати всю VM. Достатньо повернути попередню перевірену версію застосунку та залишити Redis volume недоторканим.

Архітектура відтворюваного Transparent Gateway: Proxmox template, cloud-init, deployment із Git, Docker Compose runtime і readiness
Робоче розділення відповідальності. Secrets входять лише на рівні deployment і runtime; клонування готової VM та весь deployment у cloud-init залишаються окремими глухими кутами.

Яким має бути наступний deployment

Після аудиту та двох глухих кутів вимоги стали конкретними. Нова VM має створюватися з мінімального template; cloud-init відповідає лише за identity, SSH, мережу й базову підготовку; deployment-код зберігається в репозиторії та прив’язується до перевіреного commit або release.

Окремо залишаються чотири принципові вимоги:

  • Secrets не проходять через template, Git або cloud-init user-data. На VM вони з’являються окремим контрольованим каналом і не друкуються в logs.
  • Running не дорівнює ready. Потрібно перевіряти не тільки контейнери, а свіжість snapshots, наявність upstream і end-to-end маршрут.
  • Rollback не повинен вимагати відновлення всієї VM. Версію застосунку та persistent data треба розділити.
  • Відтворюваність перевіряється новою VM. Reboot старого диска не доводить, що deployment повний.

Це вже не список абстрактних побажань. Кожна вимога походить із конкретної слабкості поточного хоста: частина конфігурації живе тільки на диску VM, application-level systemd unit відсутній, а healthcheck покриває лише частину конвеєра.

Що буде у практичній частині

У наступній статті перетворю ці вимоги на код: підготую мінімальний Proxmox template і cloud-init, повторюваний deployment, systemd, окрему доставку secrets та багаторівневий readiness check. Перевіркою стануть reboot і повний recreate з чистого template; окремий публічний HTTPS echo відрізнить лабораторний маршрут від реального internet egress.

Висновок

Головний результат цього аудиту — не cloud-init YAML і не ще одна схема. Я нарешті провів межу між створенням VM та розгортанням сервісу. Поточний cloud-init уже вміє створити Debian-хост, але Transparent Gateway поки залишається ручним застосунком на цьому хості.

Тепер зрозуміло, що саме треба довести практикою: secrets не витікають у службові файли, сервіси стартують у правильному порядку, readiness перевіряє весь маршрут, а чиста VM доходить до робочого стану за однією задокументованою процедурою. Саме це і буде предметом наступної частини.

Код проєкту: TransparentGateway на GitHub