diff --git a/docs/architecture.md b/docs/architecture.md index e97c906..4912ef5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,51 +1,64 @@ # Архитектура Server Monitor Manager -## 1. Компоненты +## 1. Выбранная топология -Для первого тестирования используется переходный режим **SSH pull**: Windows-клиент вызывает на сервере ограниченный forced-command и получает snapshot. Постоянный агент и control node ниже описывают следующий этап после проверки UX на трёх серверах. +Первый рабочий вариант использует один **Mesh Hub** на Linux-сервере с белым IP. Остальные узлы не требуют входящего публичного порта и устанавливают исходящее WireGuard-соединение с Hub. -### Desktop client +```text +Windows client -- ограниченный SSH --> Mesh Hub (публичный UDP) + ^ + | + исходящие WireGuard-туннели + | + AI-agent / Home / Server2 / ... +``` -Windows-first приложение на WinUI 3. Оно показывает состояние всех серверов, графики, события, терминалы и связи. Клиент хранит пользовательские секреты в Windows Credential Locker/DPAPI и не передаёт приватные SSH-ключи control node. +Hub выполняет две разные функции: -### Control node +- control plane первого MVP: список узлов, политики Links и команды управления через ограниченный SSH forced-command; +- data plane первого MVP: маршрутизация WireGuard-трафика с обязательной фильтрацией nftables. -Небольшой координационный сервис, который можно установить на одном из своих серверов. Он принимает исходящие mTLS-соединения агентов, хранит инвентарь, короткую историю метрик, правила оповещений, команды и аудит. Для одного пользователя достаточно SQLite; внешний PostgreSQL не является требованием MVP. +Это осознанная звёздная топология. Прямые peer-to-peer соединения, relay и отказоустойчивый второй Hub не входят в первый MVP. -Control node не становится обязательным маршрутизатором трафика между серверами. При возможности соединение идёт напрямую. Relay добавляется позже как явно включаемый режим для узлов за NAT. +## 2. Текущий переходный режим -### Linux agent +### Windows client -Один статически собранный бинарный файл. Агент читает `/proc`, `/sys` и разрешённые systemd-состояния, агрегирует метрики локально и отправляет их наружу. По умолчанию он запускается непривилегированным пользователем и не открывает входящих портов. +Packaged WinUI 3 приложение хранит профили серверов локально, создаёт отдельную Ed25519 identity мониторинга и вызывает только разрешённые SSH-команды. Клиент показывает snapshot метрик, узлы Mesh и направленные Links. -Привилегированные операции выносятся в маленький отдельный helper с белым списком действий. Агент мониторинга не должен постоянно иметь `root` или `CAP_NET_ADMIN`. +### SSH monitoring endpoint -## 2. Потоки данных +На Hub и Node создаётся непривилегированный пользователь `ochenstarik-monitor`. Его ключ привязан к root-owned forced-command и не даёт shell, PTY или forwarding. В текущем протоколе доступны `metrics` и ограниченные команды `mesh` на Hub. -### Метрики +### Mesh Hub -Агент отправляет компактный snapshot каждые 5–15 секунд. Control node сохраняет сырые точки недолго, затем выполняет downsampling. При потере сети агент держит ограниченный дисковый буфер и не заполняет диск. +Hub хранит: -Минимальный snapshot: +- публичные WireGuard identities узлов; +- выданные внутренние адреса; +- желаемое и фактическое состояние Links; +- политики CIDR, протокола, порта и TTL; +- журнал управляющих операций. -- load average и использование CPU; -- использованная/доступная память и swap; -- заполнение и inode выбранных файловых систем; -- сетевые счётчики интерфейсов; -- uptime, температура при наличии датчиков; -- состояние выбранных systemd units; -- только метаданные процессов, разрешённые политикой. +Приватный WireGuard-ключ каждого Node создаётся на самом Node и никогда не передаётся Hub. Временный enrollment token не является ключом узла. -### Команды и терминал +### Node -Произвольная shell-команда не является обычной командой агента. Для безопасных операций используются типизированные действия: перезапуск разрешённой службы, чтение журнала с ограничением, получение списка процессов. Полный терминал создаётся как отдельная SSH-сессия от desktop client. +Node устанавливает исходящее WireGuard-соединение с Hub. Входящий публичный порт не нужен. Node применяет выданную конфигурацию, подтверждает её версию и хранит приватный ключ с правами `0600`. -### Links между серверами +## 3. Метрики -Link — отдельный ресурс, а не свойство группы серверов: +Текущий SSH snapshot содержит CPU/load, память, корневой диск, uptime и задержку. Следующая версия добавляет swap, inode, сетевые счётчики и выбранные systemd units. + +Постоянный Linux agent появится после стабилизации трёхсерверного сценария. Он будет отправлять метрики исходящим mTLS-соединением, вести ограниченный локальный буфер и не открывать публичный API. + +## 4. Links между серверами + +Link — направленный ресурс: ```text Draft -> Connecting -> Active -> Disconnecting -> Disabled + \-> Partial \-> Failed Active -> Expired -> Disabled ``` @@ -53,33 +66,42 @@ Active -> Expired -> Disabled Каждый Link содержит: - source и destination; -- разрешённые IP/CIDR и TCP/UDP-порты; -- режим `manual` или TTL; -- WireGuard peer identities; -- владельца, причину и запись аудита; -- фактическое состояние обоих узлов. +- разрешённый IP или CIDR; +- протокол TCP/UDP и список портов; +- ручной режим или TTL; +- причину, владельца и запись аудита; +- версию политики и подтверждение применения. -Control node передаёт каждому узлу только его часть конфигурации. Приватный WireGuard-ключ никогда не покидает узел. `Disconnect` удаляет peer и маршруты с обеих сторон; при недоступности одного узла команда остаётся обязательной и применяется при его следующем подключении. +Пустая политика не означает `allow all`. Ответный трафик существующего соединения разрешается stateful-правилом, обратное новое соединение требует отдельного Link. -## 3. Сценарий AI-агента +При `Disconnect` Hub сначала блокирует направление в nftables, затем фиксирует `Disabled`. Если подтверждение узла недоступно, интерфейс показывает `Partial`, а обязательное состояние применяется после reconnect. -1. На домашнем сервере создаётся отдельный пользователь, например `ai-agent-dev`, без root-доступа. -2. Рабочие каталоги и разрешённые команды ограничиваются Unix-правами, группами, контейнером или sandbox-профилем. -3. В Server Monitor Manager создаётся Link от сервера с AI-агентом к домашнему серверу только для адреса домашнего узла и SSH-порта. -4. AI-агент использует собственный SSH-ключ или короткоживущий SSH-сертификат. -5. Пользователь нажимает `Connect`; после разработки — `Disconnect`. -6. Отключение Link разрывает сетевую достижимость, а отзыв SSH-сертификата/ключа остаётся вторым независимым барьером. +## 5. Сценарий AI-агента -## 4. Режимы развёртывания +1. На целевом сервере создаётся отдельный Unix-пользователь, например `ai-agent-dev`, без root-доступа. +2. Рабочие каталоги и команды ограничиваются Unix-правами, группами, контейнером или sandbox-профилем. +3. Создаётся Link от узла с AI-агентом к целевому адресу и только необходимому SSH-порту. +4. AI-агент использует отдельную SSH identity, не ключ мониторинга приложения. +5. Пользователь включает Link на ограниченное время и после работы отключает его. -- **Single owner:** один control node, один пользователь, SQLite. Основной MVP. -- **Family/team:** несколько пользователей, роли и подтверждения. После MVP. -- **Direct local:** desktop подключается к агентам внутри одной сети без публичного control node. Возможен позже, но использует тот же протокол идентичности. +## 6. Следующий control layer -## 5. Целевые ограничения MVP +После проверки текущей топологии SSH-команды управления заменяются небольшим control service: -- агент: один бинарник, idle RAM до 50 МБ, CPU в простое менее 1%; -- control node: запуск без Kubernetes и обязательного Docker; -- отсутствие открытого agent API в интернет; -- работа при 50–100 серверах на одном небольшом control node; -- деградация без потери управления: графики могут иметь пробелы, но команды не выполняются повторно без idempotency key. +- SQLite для инвентаря, политик, истории и аудита; +- одноразовая enrollment-регистрация; +- исходящие mTLS-сессии агентов; +- WebSocket/stream событий для desktop client; +- idempotency key и защита от replay. + +Hub остаётся маршрутизатором Mesh первого поколения. Разделение control plane и data plane возможно позже без изменения модели направленных Links. + +## 7. Целевые ограничения MVP + +- без Kubernetes и обязательного Docker; +- отсутствие публичного agent API; +- вторичные серверы работают без белого IP; +- 50–100 узлов на одном небольшом Hub; +- Node agent: idle RAM до 50 МБ и CPU менее 1%; +- команды не повторяются без idempotency key; +- потеря истории метрик не должна приводить к потере управления Links. diff --git a/docs/installer-contract.md b/docs/installer-contract.md index 3bd963e..b7dac97 100644 --- a/docs/installer-contract.md +++ b/docs/installer-contract.md @@ -1,25 +1,74 @@ # Контракт Linux-установщика -Файл `ochenstarik-server-monitor-manager.sh` находится в `ochenstarik-ui/lightweight-server`; синхронная копия хранится в `deploy/` этого репозитория. +Единственный исходный файл `ochenstarik-server-monitor-manager.sh` хранится в `ochenstarik-ui/lightweight-server`. В репозитории desktop client не должна находиться устаревающая копия. -## Первый тестовый этап: SSH pull +## Поддерживаемые роли -До появления постоянного агента Windows-клиент получает метрики через OpenSSH. Установщик: +### Monitor only -- поддерживает Ubuntu/Debian с systemd; -- запрашивает публичный ключ `ssh-ed25519`, созданный Windows-клиентом; -- читает интерактивный ключ из `/dev/tty`, поэтому поддерживает установку через `curl | sudo bash`; -- поддерживает повторяемый режим через `SERVER_MONITOR_PUBLIC_KEY`; -- проверяет синтаксис ключа через `ssh-keygen`; -- устанавливает и включает OpenSSH Server, не меняя текущий SSH-порт; -- создаёт отдельного системного пользователя `ochenstarik-monitor` без пароля; -- устанавливает root-owned metrics command; -- записывает ключ как `restrict,command="..."`; -- не создаёт UFW-правил и не открывает дополнительных портов; -- поддерживает `install`, `status` и `uninstall`; -- допускает безопасный повторный запуск для замены ключа мониторинга. +Режим `install` устанавливает SSH monitoring endpoint без WireGuard: -Forced-command отдаёт только строки `KEY=VALUE`: +- Ubuntu/Debian с systemd; +- публичный ключ `ssh-ed25519` из Windows-клиента; +- отдельный системный пользователь `ochenstarik-monitor` без пароля; +- root-owned forced-command; +- сохранение существующего SSH-порта; +- отсутствие нового публичного API. + +### Hub + +Режим `hub` дополнительно: + +- устанавливает WireGuard и nftables; +- запрашивает публичный IPv4/домен и UDP-порт; +- создаёт `smm0` с адресом `10.77.0.1/24`; +- включает IPv4 forwarding; +- устанавливает минимальный root helper и systemd restore unit; +- хранит публичные identities Node и политики Links; +- разрешает транзит только по явной политике. + +### Node + +Режим `node`: + +- локально генерирует WireGuard keypair; +- принимает одноразовый enrollment token; +- отправляет Hub только публичный ключ; +- получает внутренний адрес и подписанную конфигурацию; +- создаёт только исходящее WireGuard-соединение; +- не требует белого IP или входящего публичного порта. + +## Команды жизненного цикла + +Целевой интерфейс: + +```text +install-monitor +install-hub +install-node +status +update +rollback +uninstall-monitor +uninstall-node +uninstall-hub +``` + +Каждая установка и обновление должны быть идемпотентными. Перед изменением рабочей конфигурации создаётся root-only backup. Ошибка проверки или запуска автоматически восстанавливает последнюю рабочую версию. + +Удаление роли должно убрать только принадлежащие ей файлы, units, интерфейсы и правила. Удаление Hub требует отдельного подтверждения и не должно молча оставлять включённый forwarding или nftables ACL. + +## Forced-command + +Ключ мониторинга допускает только: + +- `metrics`; +- read-only `mesh nodes`, `mesh links`, `mesh status` на Hub; +- строго типизированные изменения Link с проверкой параметров. + +Он не должен позволять shell, PTY, agent forwarding, TCP forwarding или произвольную команду. Полный SSH-терминал использует отдельную identity. + +## Минимальный metrics snapshot ```text PROTOCOL=1 @@ -29,13 +78,23 @@ LOAD1=0.42 CPU_COUNT=4 MEM_TOTAL_KB=... MEM_AVAILABLE_KB=... +SWAP_TOTAL_KB=... +SWAP_FREE_KB=... DISK_TOTAL_KB=... DISK_AVAILABLE_KB=... +DISK_INODES_TOTAL=... +DISK_INODES_FREE=... +NETWORK_RX_BYTES=... +NETWORK_TX_BYTES=... KERNEL=... ``` -Ключ мониторинга не должен позволять shell, PTY, agent forwarding, TCP forwarding или выполнение переданной клиентом команды. Полноценный SSH-терминал использует отдельную пользовательскую identity и не входит в этот ключ. +## Проверки перед применением -## Будущий этап: постоянный агент - -После проверки UX на нескольких серверах SSH pull будет дополнен статическим агентом для потоковых метрик, systemd events, короткого локального буфера и управляемых WireGuard Links. Агент будет регистрироваться одноразовым token и работать по исходящему mTLS-соединению без входящего API. +- `bash -n` и ShellCheck; +- проверка SSH-ключа через `ssh-keygen`; +- `sshd -t` перед reload; +- `wg-quick strip` и пробный запуск конфигурации; +- `nft --check` перед заменой таблицы; +- проверка systemd unit; +- сохранение активной SSH-сессии до подтверждения нового доступа. diff --git a/docs/roadmap.md b/docs/roadmap.md index 16f8757..4b54143 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,52 +1,85 @@ # План разработки -## Этап 0 — фундамент +## Этап 0 — репозиторий и контракт - [x] переименовать проект в Server Monitor Manager; -- [x] разделить мониторинг, терминал и Links в архитектуре; -- [x] определить безопасный контракт установки агента; +- [x] выбрать звёздную архитектуру Hub/Node для первого Mesh; +- [x] разделить monitoring identity, terminal identity и AI-agent identity; +- [x] описать направленные Links и kill switch; - [ ] выбрать лицензию; -- [ ] настроить CI, форматирование, тесты и релизные checksum. +- [ ] добавить CI, форматирование, тесты и release checksum; +- [ ] объединить PR приложения и установщика в `main`. -## Этап 1 — Windows MVP +## Этап 1 — Windows SSH MVP -- [x] установить .NET SDK и официальный WinUI 3 toolchain; -- [x] создать packaged WinUI 3 приложение с воспроизводимым CLI-запуском через WinApp; -- [x] реализовать shell: Overview, Servers, Links, Sessions, Settings; -- [x] добавить локальные demo-данные и адаптивный dashboard; -- [x] генерировать отдельный Ed25519 SSH-ключ и хранить его в локальном каталоге packaged-приложения; -- [x] сохранять профили серверов локально без паролей; -- [x] собрать и реально запустить x64-приложение. +- [x] создать packaged WinUI 3 приложение; +- [x] добавить адаптивный Overview и профили нескольких серверов; +- [x] генерировать отдельный Ed25519 SSH-ключ; +- [x] сохранять профили локально без паролей; +- [x] получать CPU/load, RAM, disk, uptime и latency; +- [x] собрать и реально запустить x64-приложение; +- [ ] редактирование и удаление серверов; +- [ ] единственный изменяемый Hub; +- [ ] настоящие страницы Servers, Links, Sessions и Settings. -## Этап 2 — мониторинг одного сервера +## Этап 2 — установщик Hub/Node -- [x] первый бездемонный Linux endpoint через SSH forced-command; -- [ ] статический постоянный Linux agent для amd64/arm64; -- [ ] control node с SQLite, mTLS enrollment и WebSocket событиями; -- [ ] CPU, RAM, disk, network, uptime и systemd units; -- [ ] ограниченный локальный буфер и downsampling; -- [ ] installer, update, rollback и uninstall; -- [ ] предупреждения о диске, памяти и недоступности. +- [x] SSH forced-command для Ubuntu/Debian; +- [x] роли `hub` и `node`; +- [x] WireGuard Hub и исходящие Node-соединения; +- [x] постоянный nftables ACL на Hub; +- [x] список узлов и handshake-состояние; +- [ ] явные зависимости `sudo`, `visudo` и `ping` для минимального Debian; +- [ ] безопасные `update` и `rollback`; +- [ ] полный `uninstall-monitor`, `uninstall-node` и `uninstall-hub`; +- [ ] интеграционный тест повторной установки и reboot. -## Этап 3 — несколько серверов и терминал +## Этап 3 — безопасная регистрация -- [ ] группы, теги, поиск и сводные статусы; -- [ ] прямой SSH из Windows-клиента; -- [ ] known_hosts pinning и отдельные profiles; -- [ ] типизированные безопасные действия с аудитом; -- [ ] экспорт диагностики без секретов. +- [ ] локальная генерация WireGuard-ключа на Node; +- [ ] одноразовый enrollment token; +- [ ] срок действия не более 10 минут; +- [ ] атомарное погашение token; +- [ ] отзыв и повторная регистрация Node; +- [ ] подтверждение fingerprint Hub; +- [ ] защита desktop SSH-ключа через DPAPI. -## Этап 4 — Links и AI-агенты +## Этап 4 — управляемые Links -- [ ] WireGuard peer helper с минимальными привилегиями; -- [ ] policies по CIDR, протоколу, порту и TTL; -- [ ] connect/disconnect с подтверждением обоих узлов; +- [x] направленные пары source → destination; +- [x] ручное добавление и удаление nftables ACL из Windows-клиента; +- [ ] политики по CIDR, TCP/UDP и порту; +- [ ] TTL и автоматическое истечение; +- [ ] состояния Connecting, Active, Disconnecting, Partial, Disabled и Failed; +- [ ] версия политики и подтверждение применения; - [ ] обязательное отключение после reconnect; -- [ ] отдельная automation identity для AI-агента; +- [ ] append-only аудит; - [ ] интеграционные тесты kill switch и частичных отказов. -## Этап 5 — другие платформы +## Этап 5 — мониторинг и терминал -- [ ] macOS и Linux desktop clients после стабилизации Core/API; -- [ ] Android/iOS как companion-клиенты; -- [ ] push-уведомления без передачи административных секретов стороннему push-провайдеру. +- [ ] swap, inode, network и выбранные systemd units; +- [ ] предупреждения по диску, памяти и недоступности; +- [ ] автоматическое обновление и короткая локальная история; +- [ ] графики и экспорт диагностики без секретов; +- [ ] отдельный прямой SSH-терминал; +- [ ] отдельная terminal identity и подтверждение пользователя; +- [ ] отдельная automation identity для AI-агента. + +## Этап 6 — постоянный control layer + +- [ ] статический Linux agent для amd64/arm64; +- [ ] SQLite inventory, policies, history и audit; +- [ ] исходящие mTLS agent sessions; +- [ ] WebSocket/stream событий для desktop client; +- [ ] ограниченный локальный буфер и downsampling; +- [ ] idempotency key и защита от replay; +- [ ] тест нагрузки 50–100 Node на одном Hub. + +## Этап 7 — релиз и другие платформы + +- [ ] подписанный Windows installer и GitHub Release; +- [ ] checksum Linux-установщика и бинарников; +- [ ] macOS и Linux desktop после стабилизации Core/API; +- [ ] Android/iOS companion clients; +- [ ] push-уведомления без административных секретов у push-провайдера. diff --git a/docs/security-model.md b/docs/security-model.md index a5f6ea1..cdea62e 100644 --- a/docs/security-model.md +++ b/docs/security-model.md @@ -2,55 +2,64 @@ ## Защищаемые данные -- учётные записи и сессии пользователей; -- device, agent, SSH и WireGuard identities; +- SSH, WireGuard, device и agent identities; +- topology, внутренние адреса, метрики и состояния Links; - команды, терминальные сессии и аудит; -- topology серверов, адреса и метрики; -- права автоматизаций, включая AI-агентов. +- права пользователей и AI-агентов. ## Границы доверия -Desktop client, control node и каждый agent считаются отдельными субъектами. Компрометация одного агента не должна выдавать ключи других узлов или право создавать новые Links. Control node координирует публичные параметры и политики, но не хранит приватные WireGuard/SSH-ключи узлов. +Windows client, Hub и каждый Node считаются отдельными субъектами. Компрометация одного Node не должна выдавать ключи других узлов или право создавать новые Links. -В первом SSH-MVP control node отсутствует. Windows-клиент генерирует отдельный Ed25519-ключ, а сервер привязывает его к `restrict,command`. Этот ключ предназначен только для чтения ограниченного snapshot метрик и не используется для интерактивного терминала или AI-агента. +Hub хранит только публичные WireGuard-ключи Node. Приватный ключ Node генерируется локально, не включается в enrollment token и не записывается на Hub. -## Регистрация агента +## SSH monitoring MVP -1. Пользователь создаёт одноразовый enrollment token со сроком жизни не более 10 минут. -2. Агент генерирует ключевую пару локально. -3. По TLS агент предъявляет token и публичный ключ. -4. Control node выдаёт agent certificate и помечает token использованным. -5. Последующие соединения требуют mTLS. Повторное использование token отклоняется. +Windows-клиент использует отдельный Ed25519-ключ только для forced-command. Этот ключ не используется для интерактивного терминала или AI-агента. Первый host key требует явного подтверждения fingerprint; последующие подключения проверяют сохранённый `known_hosts`. -## Авторизация +Приватный ключ клиента защищается Windows DPAPI и доступом текущего пользователя. Профили серверов не содержат паролей. -- read-only мониторинг отделён от управления; -- команды проверяются по типу ресурса и действию; -- полный терминал требует свежего подтверждения пользователя; -- создание Link требует точного набора маршрутов/портов, пустой набор не означает `allow all`; +## Регистрация Node + +1. На Hub создаётся случайный enrollment token со сроком жизни не более 10 минут. +2. Node локально генерирует WireGuard-ключ. +3. Node предъявляет token и публичный ключ по защищённому каналу. +4. Hub атомарно помечает token использованным, назначает адрес и возвращает подписанную конфигурацию. +5. Повторное использование, просроченный token и смена публичного ключа отклоняются. + +До появления mTLS enrollment выполняется через отдельную ограниченную SSH-команду. Token не должен содержать приватный WireGuard-ключ. + +## Авторизация Links + +- мониторинг read-only отделён от управления; +- Link всегда содержит source, destination, CIDR, протокол и порт; +- пустой список портов не означает разрешение всех портов; - automation identity не наследует интерактивные права владельца; -- команды имеют срок действия, nonce/idempotency key и защиту от replay. +- команды имеют TTL, nonce/idempotency key и версию политики; +- Hub проверяет имена и параметры повторно, независимо от проверки desktop client. ## Аудит -Записываются входы, регистрация устройств, изменение прав, команды, начало и завершение терминала, создание/подключение/отключение Link. Секреты и полный ввод терминала по умолчанию не журналируются. Аудит экспортируется во внешний append-only storage; локальный администратор control node всё равно считается способным изменить локальную БД. +Записываются регистрация и удаление узла, изменение прав, создание, включение, истечение и отключение Link, а также ошибки применения. Секреты, приватные ключи и полный ввод терминала не журналируются. + +Для первого MVP используется append-only JSONL с ограниченными правами и ротацией. После появления control service аудит переносится в SQLite с возможностью внешнего экспорта. ## Kill switch Отключение Link должно: -1. перевести желаемое состояние в `Disabled`; -2. удалить peer и маршруты на доступных узлах; -3. заблокировать повторное автоматическое включение; -4. сохранить обязательную команду для временно недоступного узла; -5. показать пользователю разницу между желаемым и фактическим состоянием. - -Кнопка не должна сообщать «отключено», пока оба узла не подтвердили применение или интерфейс явно не показывает частичное отключение. +1. немедленно удалить разрешающее правило на Hub; +2. записать желаемое состояние `Disabled` до отправки дополнительных команд; +3. запретить автоматическое восстановление после reboot/reconnect; +4. получить подтверждение применённой версии политики; +5. показывать `Partial`, если подтверждение одного из узлов отсутствует; +6. сохранить обязательную операцию для временно недоступного Node. ## Не входит в первый MVP -- выполнение произвольных root-команд из веб/API; -- хранение пользовательских приватных SSH-ключей на control node; -- автоматическое соединение всех серверов группы в одну flat network; -- публичный входящий порт агента; -- собственная криптография вместо TLS, SSH и WireGuard. +- выполнение произвольных root-команд; +- хранение пользовательских приватных SSH-ключей на Hub; +- автоматическое объединение всех серверов в flat network; +- публичный входящий API на Node; +- собственная криптография вместо SSH, TLS и WireGuard; +- автоматический failover между несколькими Hub.