Skip to content

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

Хосты на хабе

Добавить хост ​

«Добавить хост» на странице «Хосты»:

  • Имя — метка в интерфейсе.
  • Адрес — 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, на другой системе честно отказывается.

  1. Пакеты — dbus sudo iproute2 procps ca-certificates curl tmux btop (список правится в форме). Без dbus не откроется терминал и не сработают установки из интерфейса, без iproute2 пуст список сокетов, без procps процессы не привязываются к портам.
  2. Пользователь (по умолчанию nkt) — с домашним каталогом и правилом NOPASSWD в /etc/sudoers.d/. Файл сначала проверяется visudo -cf во временном месте: неверный файл в sudoers.d ломает sudo сразу для всех.
  3. Ключ вместо пароля — хаб генерирует пару, дописывает публичную половину в authorized_keys и проверяет вход новым соединением (для не-root — ещё и sudo -n). Только после этого запись хоста переводится на ключ; если проверка не прошла, пароль продолжает работать.
  4. Выключить вход по паролю (по желанию) — 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 (отказ, обрыв, таймаут) повторяется трижды.

  1. Подключение по SSH, определение архитектуры.
  2. Бинарник nkt под неё — собирается из исходников хаба или берётся из кэша; без исходников — скачивается с GitHub Releases.
  3. Доставка бинарника, юнита и nkt.env. Хаб при каждой доставке меряет оба пути — скачивание релиза с GitHub самим хостом и заливку по SFTP с хаба — и берёт быстрый («GitHub с хоста X МБ/с, SFTP с хаба Y МБ/с»). GitHub берётся, только если ассет релиза байт в байт совпадает с бинарником хаба; сумма из SHA256SUMS сверяется на хосте. Не получилось скачать — в том же задании идёт SFTP.
  4. systemctl daemon-reload && systemctl enable netknownsthat && systemctl restart netknownsthat — именно restart, чтобы уже работающая служба подхватила новые бинарник и окружение.
  5. Проверка /health и вход под учётной записью администратора хоста, которую хаб хранит зашифрованной. Если на хосте уже была учётка с другим паролем (прошлая ручная установка), хаб сам сбрасывает его командой nkt passwd по тому же SSH.

Когда статус стал «подключён», «открыть» ведёт в панель хоста; сверху — узкая полоса хаба с именем хоста и «к списку хостов». Закрытый журнал установки открывается снова кнопкой «журнал установки».

Хаб, перезапущенный посреди установки, при старте сам переводит зависшие «установка» в «ошибка» — кнопки снова доступны.

Список хостов ​

Пока, кроме строки localhost, хостов нет, над списком стоит карточка «С чего начать» с тремя путями:

  1. Добавить хост — та же форма, что и кнопка в заголовке списка, или импорт из другого хаба — его файл экспорта (см. ниже).
  2. Посмотреть машину хаба — открывает строку localhost: находки, службы, firewall и сертификаты машины, на которой работает хаб.
  3. Попробовать выкладку — переход в «Выкладки», где «Новый конвейер» → «Примеры» даёт 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-подключений упираются в MaxStartups sshd или в 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:

sh
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:

sh
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, подписанной прежним ключом: доверие передаёт тот, кому хост уже доверял, и прав сверх тех, что были у прежнего хаба, это не даёт. Полный экспорт нового хаба несёт и унаследованные ключи — следующий переезд тоже пройдёт.