MAATRIX / Блог / Netbird (self-hosted) на Debian 12: установка

Netbird (self-hosted) на Debian 12: установка

MAATRIX

Обычный WireGuard быстро упирается в потолок: каждый новый пир — это правка конфигов на всех остальных узлах, ручная раздача ключей и никакой видимости, кто к чему подключён. Netbird решает это на уровне mesh-сети поверх WireGuard — с автоматическим NAT traversal, единым дашбордом и ACL-политиками. Ниже — установка self-hosted версии на Debian 12 с нуля: от подготовки сервера до первого клиента и exit-node.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Netbird и зачем self-hosted

Netbird — это оверлейная сеть на базе WireGuard: агент на каждом устройстве поднимает зашифрованный туннель напрямую до других пиров, а центральный сервер (management + signal + relay) занимается только координацией — раздаёт ключи, следит за топологией и помогает пирам договориться о прямом соединении через NAT. Трафик между устройствами, как правило, идёт напрямую, а не через сервер — сервер нужен лишь тогда, когда прямое соединение установить не получилось (тогда включается relay-режим).

Облачная версия Netbird (netbird.io) удобна, но у неё есть ограничения бесплатного тарифа и она физически стоит за пределами вашей инфраструктуры. Self-hosted вариант даёт:

  • полный контроль над данными — учётные записи, ключи и логи не покидают ваш сервер;
  • отсутствие лимитов на количество пиров/пользователей из бесплатного тарифа облака;
  • возможность держать management-сервер в той же юрисдикции, что и остальная инфраструктура;
  • гибкость в выборе identity-provider (Zitadel, Keycloak, Auth0, Okta).

Из минусов — придётся самостоятельно следить за обновлениями, бэкапами и доступностью сервера: если management-сервер упадёт, установка новых пиров и правка политик станет невозможна (уже поднятые туннели между существующими пирами продолжат работать некоторое время по кешированной конфигурации).

Требования и подготовка Debian 12

Для self-hosted Netbird нужен:

  • сервер на Debian 12 с публичным IP, минимум 1 vCPU / 2 ГБ RAM для небольшой команды (для сотен пиров закладывайте больше — сервер держит открытые сессии и БД);
  • доменное имя, A-запись которого указывает на IP сервера — Caddy из установочного скрипта сам получит TLS-сертификат Let's Encrypt по этому домену;
  • открытые порты: 80/tcp и 443/tcp для дашборда, API и TLS-терминации, 3478/udp для STUN/TURN (coturn), а также диапазон 49152-65535/udp для TURN-релея NAT-трафика. Итоговый список портов скрипт покажет в выводе — он может немного отличаться в зависимости от версии, сверяйтесь с ним, а не только с этим списком.

Сначала — базовое обновление системы:

sudo apt update && sudo apt full-upgrade -y
sudo apt install -y ca-certificates curl gnupg

Если домен ещё не привязан к серверу, сделайте это до запуска установки — Caddy не сможет выпустить сертификат, пока DNS не смотрит на нужный IP. Как настроить A-запись и проверить резолв, разобрано в статье про настройку домена и DNS на Debian 12.

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка Docker и docker compose

Netbird self-hosted разворачивается через docker compose — ставим Docker из официального репозитория (пакет из стандартных репозиториев Debian обычно устаревший):

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Проверьте, что всё встало:

docker --version
docker compose version

Подробный разбор установки Docker на Debian 12, включая настройку прав пользователя и systemd-автозапуск, есть в отдельной статье про установку Docker на Debian 12 — если сомневаетесь в шаге, сверьтесь с ней.

Развёртывание Netbird: management, signal, relay, dashboard

Официальный репозиторий Netbird даёт готовый скрипт быстрого старта, который генерирует docker-compose.yml и .env со всеми нужными сервисами: management, signal, дашборд, coturn для TURN/STUN и Caddy как reverse-proxy с автоматическим TLS. В качестве identity-provider скрипт по умолчанию поднимает Zitadel в отдельном контейнере — это избавляет от необходимости заводить внешний OIDC-провайдер вручную.

mkdir -p ~/netbird && cd ~/netbird
curl -fsSL https://raw.githubusercontent.com/netbirdio/netbird/main/infrastructure_files/getting-started-with-zitadel.sh | bash -s your-domain.example.com

Имя скрипта и набор флагов время от времени меняются между релизами Netbird — если команда выше не сработает один в один, откройте infrastructure_files/ в репозитории netbirdio/netbird на GitHub и возьмите актуальный вариант для docker compose с Zitadel. Скрипт спросит домен (если не передали аргументом), сгенерирует случайные пароли/секреты в .env и создаст docker-compose.yml рядом.

После генерации файлов поднимаем стек:

cd ~/netbird
docker compose pull
docker compose up -d
docker compose ps

Дайте контейнерам минуту-две на старт — Zitadel инициализирует свою БД (Postgres) при первом запуске, это самый долгий шаг. Логи стоит посмотреть отдельно, если что-то не поднимается:

docker compose logs -f management
docker compose logs -f zitadel

Firewall на сервере настраивайте под открытые порты из .env/вывода скрипта — если используете ufw, пример базовой настройки под VPN-сервисы описан в статье про настройку файрвола на Debian 12; дополнительно откройте 3478/udp и диапазон TURN-релея.

Первый вход и подключение пиров

Откройте https://your-domain.example.com в браузере — попадёте на страницу входа Zitadel. При первом заходе нужно создать администратора: логин обычно zitadel-admin@your-domain.example.com с паролем из .env (переменная вида ZITADEL_ADMIN_PASSWORD), после первого входа система попросит сменить пароль. Затем откроется сам дашборд Netbird, где создаётся первый обычный пользователь и организация.

Дальше добавляем пиры. Есть два пути:

  • Интерактивный вход — на клиентской машине ставите агент и логинитесь через браузер (SSO-flow до Zitadel):
curl -fsSL https://pkgs.netbird.io/install.sh | sh
sudo netbird up --management-url https://your-domain.example.com

Команда выведет ссылку — откройте её, авторизуйтесь через Zitadel, и пир появится в дашборде.

  • Setup Keys для headless-серверов — в дашборде: Setup Keys → Create Setup Key, задаёте срок жизни и лимит использований, затем на сервере:
sudo netbird up --setup-key ВАШ_КЛЮЧ --management-url https://your-domain.example.com

Это удобно для автоматизации — ключ можно передать через Ansible/cloud-init и не завязываться на интерактивный логин.

Статус подключения на клиенте проверяется командой netbird status — она покажет список видимых пиров, их IP в оверлейной сети и то, идёт ли трафик напрямую (P2P) или через relay.

Группы, ACL и exit-node

По умолчанию Netbird создаёт группу All и добавляет туда каждый новый пир, а базовая политика разрешает трафик внутри неё — то есть все пиры видят друг друга. Для реальной инфраструктуры это обычно избыточно, и первое, что стоит сделать — развести устройства по группам и написать явные policy.

В разделе Access Control → Policies создаётся правило: источник (группа/пир), назначение (группа/пир), протокол и порты, direction (bidirectional/один сторона). Практичный подход:

  • одна группа admins — полный доступ ко всему;
  • группа servers — доступ только с admins и между собой по нужным портам (например, 22/tcp для SSH, 5432/tcp для БД);
  • группа remote-users — доступ только к конкретным сервисам, без доступа друг к другу.

Пример логики в виде таблицы:

ИсточникНазначениеПортыСмысл
admins*anyполный доступ администраторов
remote-usersservers:web443/tcpдоступ к веб-сервисам без доступа к базе
serversservers5432/tcpБД видна только другим серверам

Exit-node (маршрутизация всего трафика клиента через один сервер, как классический VPN) настраивается через Network Routes: выбираете пир, который станет routing peer (у него должен быть доступ в интернет и включён IP forwarding — sysctl -w net.ipv4.ip_forward=1 на самом сервере), и добавляете маршрут 0.0.0.0/0, назначенный этому пиру. На клиентах, которым нужно ходить в интернет через этот exit-node, включаете использование маршрута в Network Routes → Peer Groups. По сути это тот же принцип, что и в классическом WireGuard на VPS, только правила добавляются через дашборд, а не руками в конфиг.

Обслуживание: обновления, бэкапы, диагностика

Self-hosted стек — это ваша ответственность, поэтому регламент обслуживания стоит завести сразу.

Обновление. Перед обновлением production management-сервера прочитайте changelog релиза — иногда меняется схема БД или формат .env. Стандартная процедура:

cd ~/netbird
docker compose pull
docker compose up -d
docker compose ps

Бэкапы. Критичные данные — это volume с БД Zitadel (Postgres), состояние management-сервера (обычно SQLite или тот же Postgres, в зависимости от конфигурации из скрипта) и сам .env/docker-compose.yml. Минимальный вариант — снимать docker compose stop → архивировать директорию с volume-данными → docker compose start, либо использовать pg_dump для Postgres без остановки сервисов. Если сервер уже настроен на регулярные снимки, логику удобно совместить с общим подходом из статьи про автоматические бэкапы на Debian 12.

Диагностика. Если пир не появляется в дашборде — сначала netbird status на клиенте, затем docker compose logs -f management и docker compose logs -f signal на сервере. Частые причины: домен не резолвится в момент установки, не совпадают часы на клиенте и сервере (JWT токены чувствительны к рассинхрону времени), либо firewall режет 3478/udp — тогда пиры видят друг друга в дашборде, но P2P-соединение не устанавливается и всё уходит в relay (что тоже работает, но с дополнительной задержкой).

Мониторинг. Полезно повесить внешний healthcheck на https://your-domain.example.com и алерт на недоступность контейнеров (docker compose ps в cron или через готовую систему мониторинга).

Арендуйте сервер под свои задачи!

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем self-hosted Netbird отличается от обычного WireGuard на сервере?

Обычный WireGuard — это туннель точка-точка, конфиги правятся вручную на каждом узле. Netbird добавляет поверх WireGuard координацию: автоматический обмен ключами, NAT traversal, дашборд, группы и ACL-политики — по сути mesh-сеть с управлением, а не набор ручных туннелей.

Обязательно ли отдельное доменное имя?

Практически да — Caddy из установочного скрипта использует домен для автоматического выпуска TLS-сертификата Let's Encrypt, а клиентские агенты обращаются к management-серверу по HTTPS. Поддомен на уже имеющемся домене подходит без проблем.

Можно ли отказаться от Zitadel и использовать другой identity-provider?

Да, Netbird поддерживает Keycloak, Auth0, Okta и другие OIDC-совместимые провайдеры — но тогда придётся настраивать .env вручную по документации конкретного провайдера, а не через готовый скрипт с Zitadel.

Что будет, если management-сервер временно недоступен?

Уже установленные P2P-туннели между пирами продолжат работать некоторое время на кешированной конфигурации, но добавить новый пир, изменить ACL или отозвать доступ в этот момент нельзя — поэтому сервер стоит держать на стабильном хостинге с мониторингом.

Как понять, что трафик идёт напрямую, а не через relay?

Команда netbird status на клиенте показывает тип соединения для каждого пира — прямое (P2P) или через relay. Если большинство пиров работают через relay, стоит проверить, не блокирует ли firewall UDP-порты STUN/TURN.

Сколько ресурсов нужно серверу под Netbird?

Для команды из нескольких десятков устройств хватает 1-2 vCPU и 2 ГБ RAM — основная нагрузка это Postgres от Zitadel и coturn при большом числе relay-сессий. Для сотен пиров закладывайте больше памяти и следите за нагрузкой отдельно, точных цифр без замера на своей нагрузке дать нельзя.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →