Полностью автоматизированное развертывание Remnawave Panel, Remnawave Nodes, Subscription Page
и полная миграция данных Marzban → Remnawave (inbounds, hosts, users).
- Автодеплой панели Remnawave
- Автодеплой нод + автоматическая регистрация в панели
- Автодеплой страницы подписки (bundled / separate)
- Управление сертификатами (HTTP‑01 / DNS‑01)
- Интеграция с HAProxy (TLS passthrough, SNI‑routing)
- Полная миграция данных Marzban → Remnawave
- inbound VLESS Reality
- hosts (node-host configs)
- users (включая uuid, трафик, статус, срок действия)
- Legacy Router: поддержка старых ссылок формата
https://<domain>/sub/<marzban_token> - Smoke‑тесты панели, нод и страницы подписки
- Полный decommission нод
make panelПосле успешного развёртывания панели:
-
Зайдите в веб-интерфейс панели под
admin. -
Перейдите в Settings → API Tokens → Create Token.
-
Скопируйте значение токена (
ey...) и сохраните в:inventory/group_vars/panel/vault.yml
пример:
vault_remnawave_panel_api_token: "eyJhbGciO..."
Этот токен используется для API-вызовов и автоматического добавления inbound’ов.
make dns LIMIT=panel TAGS=cf_dnsПосле того как панель развернута и токен добавлен в vault, можно автоматически добавить Reality-inbound в профиль панели:
make inboundsПримеры:
# ограничить по хосту
make inbounds LIMIT=panel
# явно указать UUID профиля
make inbounds EXTRA='-e remnawave_profile_uuid=7988e3a1-5a32-461a-9136-c9475e92f19a'Inbound будет создан или обновлён идемпотентно (по tag), а затем автоматически зарегистрирован во внутреннем скваде Default-Squad.
Подробности см. в docs/remnawave_inbounds.md
Разворачивает отдельный контейнер Remnawave Subscription Page, проксируемый через Nginx (порт 443 или 4443).
make subПримеры:
# если страница подписки на том же хосте, что и панель
make sub LIMIT=panel
# если на отдельном сервере
make sub LIMIT=sub-hostПосле развёртывания:
- Сертификат для
sub.vpn-for-friends.comбудет автоматически получен (DNS‑01 или HTTP‑01); - Контейнер
remnawave-subscription-pageбудет запущен и доступен по HTTPS; - Для режима «bundled» (на том же хосте) страница подписки обращается к панели через локальный alias
remnawave; - Для режима «separate» — через публичный API
https://remna.vpn-for-friends.com/api.
Подробности см. в docs/remnawave_subscription_deploy.md
Перед развёртыванием ноды необходимо:
- В панели на вкладке Nodes → Add Node создать ноду и скопировать её
SECRET_KEY(строку видаeyJu...). - Сохранить этот ключ в vault конкретной ноды:
пример:
inventory/host_vars/de-fra-1/vault.yml
remnawave_secret_key: "eyJu..."
После этого можно запускать ноду:
make nodes LIMIT=de-fra-1 TAGS=nodemake nodes LIMIT=node-name TAGS=register_nodemake nodes LIMIT=node-name TAGS=register_hostmake nodes LIMIT=node-name TAGS=smoke_nodeКогда ноду нужно корректно вывести из работы (например, при обновлении или замене), процесс выполняется в три шага:
-
Отключить ноду и её хосты
make disable-node EXTRA='-e remnawave_node_name=de-fra-1 -e remnawave_enable_state=false -e remnawave_disable_hosts_of_node=true' -
Дождаться завершения активных сессий
- Убедитесь через панель или Grafana, что активных соединений нет.
- При необходимости можно запустить smoke-тесты:
make nodes LIMIT=de-fra-1 TAGS=smoke_node
-
Удалить ноду (и связанные хосты)
make delete-node EXTRA='-e remnawave_node_name=de-fra-1 -e remnawave_delete_hosts=true'
🔒 Обе операции безопасны и идемпотентны — повторный запуск не приведёт к ошибкам.
В репозитории присутствуют три специализированные роли, позволяющие полностью перенести конфигурацию из существующего Marzban-кластера в Remnawave:
-
Inbound VLESS TCP Reality
roles/remnawave_migrate_inbound -
Hosts (пулы адресов / Domain Bindings)
roles/remnawave_migrate_hosts -
Users (статусы, лимиты, UUID, squads, expireAt)
roles/remnawave_migrate_users
Все роли поддерживают DRY-RUN, работают идемпотентно и допускают повторный запуск без побочных эффектов.
Переносит профиль Reality из Marzban в Remnawave, маппируя:
- публичный ключ сервера,
- shortId,
- serverName,
- поток реальности,
- параметры VLESS,
- теги,
- слушающие адреса.
make migrate-inboundПримеры:
# Только посмотреть, что будет создано/обновлено
make migrate-inbound EXTRA='-e remnawave_migrate_inbound_dry_run=true'Подробности:
👉 docs/remnawave_migrate_inbound.md
Переносит host-binding’и (доменные имена, режимы, привязку к inbound'ам).
make migrate-hostsПримеры:
# DRY-RUN без внесения изменений
make migrate-hosts EXTRA='-e remnawave_migrate_hosts_dry_run=true'Документация:
👉 docs/remnawave_migrate_hosts.md
Самая сложная часть миграции — перенести всех пользователей Marzban:
- username / note
- статус (active / disabled / limited / expired)
- trafficLimit + стратегия
- expireAt → перевод unix-timestamp → ISO8601
- VLESS UUID — перенос 1:1
- squads (опционально)
- описание
- фильтрация по
usernames=[...]
Команда:
make migrate-users LIMIT=panelПримеры:
# Полный DRY-RUN всех пользователей
make migrate-users LIMIT=panel EXTRA='-e remnawave_migrate_users_dry_run=true'
# DRY-RUN только одного пользователя
make migrate-users LIMIT=panel EXTRA='-e remnawave_migrate_users_dry_run=true -e remnawave_migrate_users_usernames=["us_67"]'
# Применить реальные изменения для конкретного пользователя
make migrate-users LIMIT=panel EXTRA='-e remnawave_migrate_users_dry_run=false -e remnawave_migrate_users_usernames=["us_67"]'Роль гарантирует:
- идемпотентность: существующий пользователь → PATCH, нового → POST
- никакого «добавления _ в конце» (строгая нормализация)
- уведомления в выходном логе о
createилиupdate
Документация:
👉 docs/remnawave_migrate_users.md
| Раздел | Файл | Описание |
|---|---|---|
| Панель | docs/remnawave_panel.md | Установка панели и сервисов |
| Обновление (Upgrade) | docs/remnawave_upgrade.md | Безопасное обновление панели и нод (upgrade flow) |
| Inbounds | roles/remnawave_inbounds/README.md | Добавление и регистрация inbound’ов |
| HAProxy | docs/haproxy_tls_sni.md | Совместная работа панели и Xray |
| Ноды | docs/remnawave_node.md | Запуск контейнера с SECRET_KEY |
| Регистрация ноды | docs/remnawave_register_node.md | API-регистрация ноды |
| Регистрация Host | docs/remnawave_add_host.md | Добавление Host через API |
| Subscription Deploy | docs/remnawave_subscription_deploy.md | Развёртывание страницы подписки |
| Subscription Page | docs/remnawave_subscription_page.md | Конфигурация Nginx и Docker контейнера |
| Проверки | docs/smoke_tests.md | Smoke-тесты панели и нод |
| Отключение ноды | docs/remnawave_disable_node.md | Временное отключение ноды и хостов |
| Удаление ноды | docs/remnawave_delete_node.md | Полное удаление ноды и связанных хостов |
| Миграция Inbound | docs/remnawave_migrate_inbound.md | Перенос Reality-inbound |
| Миграция Hosts | docs/remnawave_migrate_hosts.md | Перенос Host-binding’ов |
| Миграция Users | docs/remnawave_migrate_users.md | Полная миграция пользователей |
flowchart TB
User[Пользователь] -->|запрос к remna.vpn-for-friends.com или sub.vpn-for-friends.com| CloudflareDNS[Cloudflare DNS]
CloudflareDNS --> PublicIP_One[Публичный IP Host1]
PublicIP_One --> HAProxy443
subgraph Host1 [Host1: panel + subpage + node]
HAProxy443[HAProxy 443 TCP SNI]
Nginx4443[Nginx 4443 loopback]
Xray8444[Xray 8444 loopback]
Panel3000[Panel app port 3000]
Sub3100[Subscription page port 3100 docker]
Certbot[Certbot ACME]
HAProxy443 -->|SNI remna.* , sub.*| Nginx4443
HAProxy443 -->|non-TLS/иное SNI| Xray8444
Sub3100 -->|HTTP /api| Nginx4443
Nginx4443 -->|proxy /api| Panel3000
Nginx4443 -->|proxy| Panel3000
Nginx4443 -->|proxy| Sub3100
Nginx4443 -. validation .-> Certbot
end
Certbot -. DNS-01 или HTTP-01 .-> CloudflareDNS
flowchart TB
User[Пользователь] -->|remna-domain| CloudflareDNS[Cloudflare DNS]
User -->|sub-domain| CloudflareDNS
CloudflareDNS -->|A remna-domain| PublicIP_Panel[Публичный IP Host1]
CloudflareDNS -->|A sub-domain| PublicIP_Sub[Публичный IP Host2]
PublicIP_Panel --> HAProxy1
subgraph Host1 [Host1: panel + node]
HAProxy1[HAProxy 443 TCP SNI]
Nginx1[Nginx 4443 loopback]
Xray1[Xray 8444 loopback]
Panel3000[Panel app port 3000]
Certbot1[Certbot ACME]
HAProxy1 -->|SNI remna-domain| Nginx1
HAProxy1 -->|non-TLS/иное SNI| Xray1
Nginx1 -->|proxy /api| Panel3000
Nginx1 -. validation .-> Certbot1
end
PublicIP_Sub --> Nginx2
subgraph Host2 [Host2: subpage only]
Nginx2[Nginx 443]
Sub3100[Subscription page port 3100 docker]
Certbot2[Certbot ACME]
Nginx2 -->|proxy| Sub3100
end
Sub3100 -->|HTTPS remna-domain /api| PublicIP_Panel
Certbot1 -. DNS-01 или HTTP-01 .-> CloudflareDNS
Certbot2 -. DNS-01 или HTTP-01 .-> CloudflareDNS
inventory/group_vars/all/vault.yml
inventory/group_vars/panel/vault.yml
inventory/host_vars/<node>/vault.yml
Не коммитим содержимое Vault в git.
Используйтеansible-vault editдля безопасного редактирования файлов.
curl -vk https://panel.example.com/health
docker logs remnanode --tail=50
echo | openssl s_client -connect IP:443 -servername panel.example.com
echo | openssl s_client -connect IP:443 -servername www.cloudflare.comPR приветствуются: дополнения к ролям, новые дашборды и правила, улучшения документации. Старайтесь сопровождать изменения коротким описанием и примерами проверки.