Хосты: добавление, установка, доступ

Добавить хост
«Добавить хост» на странице «Хосты»:
- Имя — метка в интерфейсе.
- Адрес — IP или DNS-имя.
- SSH-порт — обычно 22.
- SSH-пользователь —
rootили пользователь сsudoбез пароля (NOPASSWD) — так настроены типовые образы VPS (ubuntu,debian,adminс cloud-init). Не-root командам установка сама добавляетsudo -n;sudo, требующий пароль, сразу даёт понятную ошибку, а не зависает. - Способ входа:
- хаб сгенерирует ключ (по умолчанию, рекомендуется) — после сохранения хаб покажет публичный ключ и готовые команды с кнопкой «копировать»: одна для выполнения на самом хосте (создаёт
~/.ssh, дописывает ключ вauthorized_keys, ставит права), другая — с вашей машины черезssh. Приватная половина не покидает хаб. Ключ можно открыть снова кнопкой «ключ» в строке хоста. - свой приватный ключ — содержимое
id_ed25519/id_rsa(не.pub), в формате OpenSSH/PEM, без пароля. Форма проверяет ключ сразу и называет причину отказа: вставлен.pub, формат PuTTY.ppk(экспортируйте в OpenSSH через puttygen), ключ с паролем (снимитеssh-keygen -p). - пароль — обычный пароль по SSH.
- хаб сгенерирует ключ (по умолчанию, рекомендуется) — после сохранения хаб покажет публичный ключ и готовые команды с кнопкой «копировать»: одна для выполнения на самом хосте (создаёт
Подготовить новый хост
Для свежего сервера, где есть только root и пароль (при входе по паролю включено по умолчанию, при ключе хаба — по желанию). Выполняется один раз, перед установкой; только Debian/Ubuntu — через apt-get, на другой системе честно отказывается.
- Пакеты —
dbus sudo iproute2 procps ca-certificates curl tmux btop(список правится в форме). Безdbusне откроется терминал и не сработают установки из интерфейса, безiproute2пуст список сокетов, безprocpsпроцессы не привязываются к портам. - Пользователь (по умолчанию
nkt) — с домашним каталогом и правиломNOPASSWDв/etc/sudoers.d/. Файл сначала проверяетсяvisudo -cfво временном месте: неверный файл вsudoers.dломаетsudoсразу для всех. - Ключ вместо пароля — хаб генерирует пару, дописывает публичную половину в
authorized_keysи проверяет вход новым соединением (для не-root — ещё иsudo -n). Только после этого запись хоста переводится на ключ; если проверка не прошла, пароль продолжает работать. - Выключить вход по паролю (по желанию) — drop-in
/etc/ssh/sshd_config.d/99-nkt-no-password.confс проверкойsshd -t, перезагрузкой без разрыва сессий и ещё одной проверкой входа по ключу. Если после перезагрузки демон не пускает, drop-in удаляется. Неудача здесь установку не срывает.
Переключатели в форме хоста
- Порт API — на чём слушает nkt на хосте (только loopback). Пусто — общий
NKT_HUB_HOST_API_PORT(8077). Смена переустанавливает nkt. - Веб-терминал — root-shell в браузере; выключен по умолчанию. Хранится в базе хаба и передаётся хосту при каждой установке — ручная правка
nkt.envна хосте потеряется при следующем обновлении. - Резервный канал — включён по умолчанию, см. ниже.
- Пакеты через кэш хаба — включён по умолчанию, см. Кэш пакетов.
Установка
После «Добавить хост» нажмите «установить». Установка, как и каждое обновление, — задание хаба: журнал в реальном времени, раздел «Задания», переживает перезагрузку страницы, отменяется кнопкой в строке хоста (по-настоящему прерывает текущий шаг). Временная ошибка SSH (отказ, обрыв, таймаут) повторяется трижды.
- Подключение по SSH, определение архитектуры.
- Бинарник nkt под неё — собирается из исходников хаба или берётся из кэша; без исходников — скачивается с GitHub Releases.
- Доставка бинарника, юнита и
nkt.env. Хаб при каждой доставке меряет оба пути — скачивание релиза с GitHub самим хостом и заливку по SFTP с хаба — и берёт быстрый («GitHub с хоста X МБ/с, SFTP с хаба Y МБ/с»). GitHub берётся, только если ассет релиза байт в байт совпадает с бинарником хаба; сумма изSHA256SUMSсверяется на хосте. Не получилось скачать — в том же задании идёт SFTP. systemctl daemon-reload && systemctl enable netknownsthat && systemctl restart netknownsthat— именноrestart, чтобы уже работающая служба подхватила новые бинарник и окружение.- Проверка
/healthи вход под учётной записью администратора хоста, которую хаб хранит зашифрованной. Если на хосте уже была учётка с другим паролем (прошлая ручная установка), хаб сам сбрасывает его командойnkt passwdпо тому же SSH.
Когда статус стал «подключён», «открыть» ведёт в панель хоста; сверху — узкая полоса хаба с именем хоста и «к списку хостов». Закрытый журнал установки открывается снова кнопкой «журнал установки».
Хаб, перезапущенный посреди установки, при старте сам переводит зависшие «установка» в «ошибка» — кнопки снова доступны.
Список хостов
Пока, кроме строки localhost, хостов нет, над списком стоит карточка «С чего начать» с тремя путями:
- Добавить хост — та же форма, что и кнопка в заголовке списка, или импорт из другого хаба — его файл экспорта (см. ниже).
- Посмотреть машину хаба — открывает строку localhost: находки, службы, firewall и сертификаты машины, на которой работает хаб.
- Попробовать выкладку — переход в «Выкладки», где «Новый конвейер» → «Примеры» даёт hello-app или httpbin на машине хаба.
Кнопка «Справка: демо без серверов» открывает быстрый старт с режимом fixtures. Карточка исчезает, как только появляется первый хост.
Каждый хост — в одну строку, а ширины колонок общие для всех групп: колонки разных групп стоят ровно друг под другом и не сдвигаются, когда меняются числа. Что не помещается — значком с подсказкой.
- Значок доступности перед именем: зелёный — ответил на последний опрос, красный — недоступен (в подсказке — когда отвечал), серый — ещё не опрашивался. Опрос — раз в
NKT_HUB_FINDINGS_POLL_INTERVAL(60 с) через уже открытое SSH-соединение. Щелчок по красному или серому значку опрашивает хост сразу, не дожидаясь таймера (пока идёт опрос, значок крутится); на хосте это ничего не меняет, поэтому доступно и роли «только чтение». - Значок ОС прямо перед именем — дистрибутив хоста по его
/etc/os-release(Ubuntu, Debian, Alpine…; подсказка — полное имя); хаб узнаёт его при опросе, у хоста без ответа — последний известный, у ещё не опрошенного — «?». Тот же значок — в заголовке открытого хоста, в выпадающих списках хостов, мониторинге, оповещениях, fail2ban и заданиях хаба, а у машин и контейнеров внутри хоста — их ОС (см. Контейнеры и ВМ). У машины без своего nkt (Windows) ОС берётся из списка машин её хоста. У запущенной машины под «+» — кнопка «Экран»: окно экрана открывается через её хост, nkt внутри машины для этого не нужен. - Адрес (перед «nkt») —
пользователь@адрес:порт, видны только два-три первых знака, так что ни пользователь, ни адрес на экране не читаются; целиком — в подсказке, иконка рядом копирует строку целиком. У машин внутри хоста — так же. - f2b — сколько адресов fail2ban держит сейчас (🛡 и число); красная иконка паузы — fail2ban остановлен, «—» — не установлен.
- Проблемы — счётчики находок; у недоступного хоста — красная иконка разрыва (в подсказке — когда отвечал) и числа от последнего удачного опроса (приглушённо) или «нет данных».
- nkt — версия nkt на хосте. Если отличается от хаба или обновление не применилось, рядом оранжевый значок ⚠ («на хабе: …» или «установлено … — обновление не применилось» — в подсказке), а кнопка становится «обновить». «Открыть» отставший хост сначала обновляет и переходит в панель только после успеха. Сравнение идёт с версией хаба из того же ответа, так что старая вкладка после обновления хаба не переустанавливает хосты по кругу.
- Виден — когда хост последний раз отвечал.
- «Обновить всё» — одно задание хаба на все отставшие хосты (журнал открывается сразу, уход со страницы его не прерывает), не больше трёх одновременно (иначе десятки SSH-подключений упираются в
MaxStartupssshd или в jump-хост). Окно подтверждения показывает, кого обновим и кого нет: хосты, где обновление уже идёт или ждёт очереди, не трогаются (рядом с кнопкой — «обновляется: N»), упавшие в прошлый раз — только по галочке «повторить неудачные». Подключение задание проверяет само, перед установкой на каждый хост (до 3 попыток за минуту): без подключения хост пропускается, в конце журнала — итог «обновлено, пропущено без подключения, ошибок установки». Пока обновления идут, список хостов обновляется каждые несколько секунд. - Sudo — что на самом деле разрешено пользователю хаба без пароля по последней проверке хоста (после установки, обновления, сужения, снятия правила и при открытии окна «sudo хаба»): красный знак ⚠ — «без пароля» (опасно: кто вошёл этим пользователем, сразу получает root), зелёный щит — «узкий sudo» (см. ниже), зелёная галочка — «нужен пароль», серый вопрос — «неизвестно». Щелчок по значку (и кнопка «сузить sudo» рядом с красным) открывает окно «sudo хаба» — что разрешено, «Сузить sudo», «Снять правило nkt» (после снятия для обновлений хабу снова нужен sudo или root).
- Канал — состояние резервного канала: серый — выключен; зелёный «подключён» — держится, работает обычный SSH; жёлтый «через резервный канал» — SSH сейчас недоступен, всё идёт через канал.
- «Изменить» — имя, адрес, порт, пользователь, способ входа; пустое поле секрета оставляет прежний. Там же «забыть ключ хоста».
- «Запустить все» / «остановить все» —
systemctl start|stop netknownsthatпо SSH на всех хостах; не переустановка.
Если nkt на хосте перезапускается (обновление пакетов, самообновление), хаб ждёт до 20 с, пробуя вход каждые 2 с, вместо ошибки. Если API так и не поднялся, ошибка говорит прямо: «SSH отвечает, но API nkt на хосте не поднялся» — и прикладывает снятую по SSH диагностику: состояние юнита, кто слушает порт API, последние строки журнала. «Обновить» с хаба переустановит и перезапустит службу по SSH.
Соединение хаба с хостом. На каждый хост у хаба одно общее SSH-соединение: по нему идут опрос, страницы, живые журналы, терминал. Ошибка отдельного запроса (браузер ушёл со страницы, запрос не успел за свой срок на нагруженном хосте) соединение не закрывает — хаб проверяет его keepalive-запросом SSH и закрывает, только если оно и правда мертво; занятое идущими запросами не закрывается и по простою. Вход хаба на хост, оборвавшийся на канале, повторяется по свежему соединению. Большие передачи — загрузка и скачивание архивов образов, образов машин, файлов проводника, бэкапов — идут по своему отдельному SSH-соединению: гигабайты не забивают общее, и обрыв передачи не задевает остальное. Красный значок «недоступен» ставится только после двух неудачных опросов подряд — одна случайная неудача его не зажигает.
Узкий sudo
NOPASSWD: ALL делает root любого, кто вошёл этим пользователем: людей, другие ключи в authorized_keys, взломанное приложение под ним. Сам хаб от этого почти ничего не получает — он и так root на хосте через nkt. Поэтому первая установка nkt под пользователем с полным sudo сразу его сужает:
- открытый ключ подписи хаба ложится в
/etc/nkt/hub-sign.pub(root, 0644); ключ выводится из мастер-ключа хаба; - правило
/etc/sudoers.d/nkt-hubзаменяется напользователь ALL=(root) NOPASSWD: /usr/local/bin/nkt hub-sudo(проверкаvisudo -cfдо замены); nkt hub-sudoвыполняет под root только запросы, подписанные хабом: операция из постоянного списка (установка или обновление nkt — бинарник и юнит по подписанным хэшам,nkt.envс паролем админа — в самом подписанном запросе, без временного файла на хосте; запуск, остановка и перезапуск службы, её журнал, пароль админа nkt, apt-прокси, база ClamAV с хаба, очистка при удалении хоста, снятие своего правила), с порядковым номером — повтор старого запроса отвергается. Файлы сначала копируются в каталог root и только там сверяются: подменить их после проверки нельзя.
Хосты, суженные nkt v1.11.111–1.11.117
С v1.11.119 nkt.env передаётся в подписанном запросе, а не файлом по хэшу; прежний hub-sudo такой запрос не принимает, совместимости нет. Обновление такого хоста с хаба откажет с инструкцией — на хосте под root:
rm -f /etc/nkt/hub-sign.pub && echo 'пользователь ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/nkt-hub && chmod 440 /etc/sudoers.d/nkt-hubЕсли вы входите этим пользователем и у него есть пароль sudo:
sudo sh -c "rm -f /etc/nkt/hub-sign.pub && echo 'пользователь ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/nkt-hub && chmod 440 /etc/sudoers.d/nkt-hub"затем в хабе «Переустановить» и «Сузить sudo».
Список операций зашит в nkt и меняется только с его версией; править его из интерфейса нельзя — иначе ограничение ничего бы не стоило. Сценарии хаба («Профили» → «Сценарии») узкий sudo не задевает: шаг install ставит nkt тем же заданием, остальные шаги идут через API nkt на хосте (он работает под root), а user add … sudo — это заведение на хосте пользователя с правами sudo, а не права хаба. Откуда хаб взял бинарник — релиз, своя сборка, копия без интернета, — не важно: подписывает хаб, которому хост уже доверяет.
Если sudo без пароля этому пользователю даёт ещё другое правило (например, 90-cloud-init-users), журнал установки предупреждает, значок остаётся красным, а окно «sudo хаба» показывает, откуда полный sudo, — см. ниже.
Без пароля на хосте с узким sudo не работает одно: установка nkt-edge на этот хост (certbot, своя служба, порты — это не операции hub-sudo). Хаб отказывает сразу, до задания: временно дайте пользователю правило NOPASSWD: ALL (или выберите хост под root), после установки — «Сузить sudo».
Ключ хаба пропал с хоста (файл /etc/nkt/hub-sign.pub удалён или остался от другого хаба): операции, которым нужен root, падают на «sudo просит пароль». Хаб тогда не советует давать пользователю NOPASSWD: ALL, а пишет, что ключа нет, и даёт команду, которая кладёт на хост только открытый ключ хаба, — её достаточно один раз выполнить на хосте со своим паролем. Если ключ на месте, а операция всё равно упала, хаб называет её: значит, она ещё не умеет узкий sudo.
Хосты, установленные раньше, остаются с полным sudo, пока его не сузить: в колонке Sudo рядом с красным ⚠ — кнопка «сузить sudo». Она и щелчок по значку открывают окно «sudo хаба»: состояние, список операций hub-sudo с пояснениями, само правило sudoers и путь ключа; кнопки «Сузить sudo» (при полном) и «Снять правило nkt». Сужение сначала, пока полный sudo ещё действует, кладёт ключ и проверяет подписанным запросом, что hub-sudo на хосте есть, — старый nkt такой команды не знает, и тогда окно просит сначала обновить nkt на хосте. Повторное «Сузить» на уже суженном хосте полного sudo не требует: хаб видит свой ключ и работающий hub-sudo и только отмечает «уже сужен».
Окно проверяет хост вживую при каждом открытии и по кнопке «Проверить заново»: ключ хаба на месте или нет, и что разрешено без пароля (sudo -n -l). Если правило sudoers меняли руками, значок в списке хостов исправляется сам. Та же проверка идёт после установки, обновления, сужения и снятия правила: значок ставится по тому, что на хосте, — например, остаётся красным, если у пользователя есть чужое правило с полным sudo. Постоянного опроса нет: каждый sudo пишется в журнал авторизации хоста.
Чужое правило с полным sudo. Пока полный sudo действует, хаб читает /etc/sudoers и /etc/sudoers.d/ и показывает строки, которые его дают (файл:строка, кто назван — пользователь, группа, все или алиас). Строку в отдельном файле sudoers.d, где назван только этот пользователь, на уже суженном хосте можно «Отключить»: она закомментируется, файл проверяется visudo до замены, прежний остаётся рядом как .nkt-bak (такие файлы sudo не читает). Правила групп, «для всех», алиасов и строки в самом /etc/sudoers касаются не только этого пользователя — их хаб не трогает и объясняет, что поправить вручную. Если у пользователя нет пароля (облачные образы), окно предупреждает: после отключения правила под этой учёткой sudo не будет вовсе.
Ключ SSH хоста
При первом подключении хаб запоминает ключ SSH хоста и дальше требует тот же, как known_hosts: подменённый ключ даёт ошибку «ключ SSH хоста изменился: запомнен SHA256:…, предъявлен SHA256:…», а не вход с паролем к чужой машине. После переустановки хоста нажмите «забыть ключ хоста» в форме «изменить» — следующее подключение запомнит новый. Там же виден отпечаток.
Резервный канал
Включён по умолчанию для новых хостов. Хаб открывает на хосте ещё один порт (8078, NKT_HUB_TUNNEL_PORT) и сам на него дозванивается тем же адресом, что и SSH, — отдельный адрес хаба не нужен, даже если хаб в домашней или офисной сети.
- Спасает, когда недоступен именно SSH: упал или неверно настроен sshd, протухли учётные данные, закрыт только 22-й порт. Файрвол, закрывший все входящие, закроет и его.
- Хаб всегда сначала пробует SSH; канал — только при неудаче.
- Панель и терминал идут через канал как есть. Обновление — иначе: SFTP и sudo по каналу не ходят, поэтому хаб отправляет собранный бинарник и
nkt.env/юнит наPOST /api/self-updateхоста, а тот раскладывает их и перезапускается черезsystemd-run. Самую первую установку канал не делает — только обновления уже установленного хоста. - Аутентификация — случайный токен на хост, новый при каждой установке, передаётся по SSH; хаб хранит его зашифрованным. Пять неверных попыток с одного адреса — временная блокировка. Сертификат хоста самоподписан; хаб закрепляет его отпечаток при первом подключении и сверяет каждый раз. Не совпал — соединение отвергается с записью в журнал; переустановка через хаб сбрасывает привязку.
Группы и профили
Хосты собираются в группы перетаскиванием. У группы может быть профиль (задаётся при создании группы): машины, создаваемые в ней, делаются по нему, а их строки подкрашены цветом профиля. Хосты, перенесённые в группу, не трогаются. Расхождение хоста с профилем видно в его «Проблемах». Профили хаба правятся в разделе «Профили».
Машины внутри хоста
Новая машина создаётся на хосте прямо из хаба: cloud-init, nkt внутрь, профиль группы. Найти машины на хосте (вкладка в том же окне) заводит записями домены libvirt, созданные не через nkt: у каждой — все её адреса (аренда libvirt, гостевой агент, ARP хоста; без loopback, link-local и внутренних мостов гостя), свои реквизиты SSH под строкой и «проверить доступ» — маршрут, ping, порт SSH с хоста и с хаба с диагнозом одной строкой. Машина на macvtap помечается: хост своих macvtap-гостей не видит, ей нужна связь напрямую.
Связь с машиной: авто — хаб пробует SSH машины напрямую (1,5 с, итог помнится 10 минут) и идёт мимо хоста, если тот отвечает, иначе через хост; напрямую; через хост.
Экспорт и импорт
«Экспорт» сохраняет всё, что долго заводить заново: хосты с зашифрованными SSH- и admin-секретами и настройками, группы (в том числе пустые), связь машин с хостами, кластеры Kubernetes (узлы, адрес API, kubeconfig, план WireGuard), профили и сценарии с историей, шаблоны машин, конвейеры выкладок с историей редакций, секретами (подпись вебхука, токены git и registry), адресом вебхука, выбранными проверками сухого прогона и историей .env, сайты выкладок (домены, прокси, стек или адрес, firewall, состояние; хост и конвейер — по именам: сайт, чьего хоста нет, не импортируется, а сайт без своего конвейера становится заведённым вручную), шаблоны fail2ban с историей версий, все nkt-edge с ролями (адрес, домен, токен, закреплённый сертификат, хост установки), API-токены (роль, пределы, адреса, срок, секрет), исходящие вебхуки и боты Telegram и Slack (токены и секреты; хосты в пределах — по именам, хоста с таким именем нет — токен или адресат не импортируется), настройки хаба (оповещения, кэш пакетов, разбор моделью с ключом API и всеми правлеными инструкциями, бета-канал, адрес сайта справки с историей, раскладка меню хаба и хоста), сохранённые наборы формы кластера, галочки и токены резервного канала. По галочке «Учётные записи веб-интерфейса» — ещё логины, роли и хэши паролей. Файл — JSON версии 5, версии 1–4 тоже импортируются.
Ключ шифрования хаба едет в файле: хаб-получатель расшифровывает им секреты (хостов, кластеров, конвейеров с историей
.env, edge, токенов, ботов, ключ модели) и сразу перешифровывает своим. Поэтому экспорт обязательно предлагает зашифровать файл паролем (Web Crypto, PBKDF2 + AES-256-GCM, пароль не уходит с браузера); пустой пароль — только через отдельное подтверждение. Формат общий сnkt hub delete -exportиnkt hub import.Импорт — через план:

окно показывает, что есть в файле по разделам и что из этого уже есть в хабе (по имени). У каждого совпадения — «пропустить» (по умолчанию) или «заменить», у раздела — «все пропустить / все заменить». Замена профиля, сценария, конвейера и шаблона fail2ban — новой версией в истории этого хаба (к прежней можно откатиться; у конвейера и
.env— тоже новой версией); у сайта заменяются домены, прокси, цель и состояние; у хоста заменяются адрес, доступ и секреты, а журнал и привязки остаются; у учётной записи — хэш пароля, роль и блокировка. Кластеры с занятым именем только пропускаются. После импорта — отчёт по разделам: добавлено, заменено, пропущено, ошибки.Адрес вебхука конвейера сохраняется — вебхуки в GitHub, GitLab и Gitea продолжают работать на новом хабе. Если такой адрес на хабе-получателе уже занят другим конвейером, выдаётся новый, и отчёт об этом говорит.
nkt hub importиз командной строки совпадения пропускает; заменить — через окно импорта.Не переносятся: образы для кластеров (только их список — импорт скажет, какие скопировать в
cluster-imagesруками), кэш пакетов, задания, история выкладок, журнал оповещений, сохранённые ответы модели, привязка сертификата резервного канала (новый хаб закрепит свою).История «Мониторинга» — по отдельной галочке в окне экспорта (по умолчанию выключена: файл заметно больше): почасовые и суточные сводки нагрузки и доступности, что хранит хаб, с целями доступности. В плане импорта — свой раздел, хосты сопоставляются по имени (машина хаба — «localhost»). Если у хоста здесь истории нет — она добавляется; если есть — по умолчанию пропуск, «дополнить» добавляет недостающие часы и дни, а имеющиеся не трогает. Хоста с таким именем нет — его история пропускается с пометкой в отчёте.
Хосты без nkt после импорта. Импорт ничего на хосты не ставит. Сразу после него хаб в фоне заходит на перенесённые хосты по SSH: где nkt нет (например, удалили перед переездом), хост становится «не установлен» — серый, с кнопкой установки, а не красным «недоступен». Над списком хостов — плашка «Хостов без nkt: N» с кнопкой «Установить»: окно установки на хосты с уже отмеченными ими (см. «Установка nkt на хосты»). Плашку можно закрыть крестиком: она не вернётся, пока не появится новый хост без nkt (запоминается в этом браузере).
Переезд хостов с узким sudo. На таком хосте лежит открытый ключ хаба, который его сузил, и подпись нового хаба он бы отверг. При импорте полного экспорта (с ключом) новый хаб запоминает ключ подписи прежнего (зашифрованным своим мастер-ключом) и подписывает таким хостам им. После установки или обновления nkt на хосте (и при «Сузить sudo») хаб меняет ключ хоста на свой операцией
hub-sudo rekey, подписанной прежним ключом: доверие передаёт тот, кому хост уже доверял, и прав сверх тех, что были у прежнего хаба, это не даёт. Полный экспорт нового хаба несёт и унаследованные ключи — следующий переезд тоже пройдёт.