Cluster · разработчикам
Хранилище и копии
Данные юзербота находятся в собственной Mekansm. При запуске с --volumes она размещается в отдельном ограниченном томе. Модуль получает свой раздел через API, полный доступ db.full открывает прикладные разделы того же юзербота. Служебная база, пароли входа, фактическая Telegram-сессия и ключ ядра в этот API не входят.
Квота
В квоту входят значения базы, файлы, журнал, расписание, публикации, сборки, копии и резерв терминала. При 90% появляется уведомление, при 100% запрещается увеличение данных. Удаление, вход и продление остаются доступны. Пользователь сам выбирает, что удалить.
Том при --volumes имеет дополнительное место для уплотнения Mekansm и временного восстановления: два пользовательских лимита плюс 64 MiB. Это служебный резерв, пользовательский API не разрешает занять его обычными данными. На сервере нужно учитывать весь размер тома и свободное место для новых пользователей.
Истёкшие данные, записи журнала, незаконченные файлы и временные записи удаляются обслуживанием. Обработка идёт порциями с курсором. Размер освобождается и для записей за первой тысячей. Неиспользуемая сборка удаляется через час либо сразу при удалении экземпляра.
Файлы
Файл сначала создаётся с объявленным размером. Ядро резервирует размер и служебную запись, затем принимает части до 64 KiB. offset следующей части должен совпадать с уже записанным размером. Завершение проверяет длину и SHA256, если он был указан. До завершения файл находится в uploading, после него в ready. Незавершённая загрузка не становится готовым файлом от одного наличия байтов на диске.
Список возвращает files и курсор after. Для следующей страницы передаётся полученный курсор; None означает конец. Имя файла является подписью, серверный путь по нему не строится. Чтение проверяет права и срок хранения. Выбранное файловое поле конфигуратора даёт модулю доступ к конкретному файлу без полного доступа к чужим разделам. Методы и типы в SDK.md.
Терминал
Доступен овнерам через сайт и команду !exec. Доверка и модули не получают API запуска терминала. Это Bash в отдельной среде gVisor, с постоянным каталогом, PTY, вводом, состоянием процесса и остановкой. Сервер управления, другие юзерботы и файл сессии туда не подключаются.
Через python -m terminal_client можно обращаться к API базы, файлов, вебклиента, Telegram и личного бота с полномочиями овнера. Это проверенный интерфейс ядра, ключ авторизации Telegram из него не получается.
При первом запуске резервируется половина свободной квоты, максимум 1 GiB, минимум 16 MiB. Терминалу нужен --volumes. Одновременно до восьми процессов, не больше 30 запусков в минуту на юзербота. Остановка процесса закрывает всю среду, включая отделившиеся дочерние процессы. При удалении овнера ядро закрывает всю среду терминала, включая другие активные и отделившиеся процессы. История сохраняет команду, состояние и последние 64 KiB вывода. Отдельная галочка скрывает команду и вывод из истории. В памяти остаются до 32 последних завершённых процессов юзербота не дольше часа; сохранённая история в пользовательской базе от этого не удаляется.
Поддержка получает доступ только после подтверждения пользователя и до отзыва или завершения ремонта. Команды ремонта не добавляются в историю терминала, действия поддержки не записываются как пользовательские события ядра. Собственные сообщения модулей продолжают записываться по обычным правилам. Такой доступ проверяется при запуске и во время процесса. Закрытие доступа останавливает среду. Обычный терминал и терминал ремонта используют разные полномочия: при смене режима предыдущая среда закрывается.
Административная проверка данных работает отдельно от поддержки. Она допускает только определённые операции чтения и не предоставляет терминал, Telegram-сессию или содержимое файлов. Разрешение привязано к администратору и юзерботу, имеет причину и срок до двух часов. Открытие и запросы хранятся в отдельном журнале центральной базы 30 дней. Прикладные результаты чтения в этот журнал не копируются. Подробнее в MODERATION.md.
Копия юзербота
Копия создаётся на странице файлов и занимает квоту. Можно настроить период и количество копий. При обновлении экземпляра по умолчанию сохраняется одна копия его данных, следующая заменяет предыдущую.
Полная копия содержит данные, конфигурацию, страницы модулей, сетевые профили, журнал, расписание, полученные события обмена, файлы, настройки ядра, овнеров, доверку и рабочие файлы терминала. Список договоров включается для просмотра. Копия экземпляра содержит только его прикладные данные, настройки и файлы. Telegram-сессия, входы на сайт и служебные ключи не включаются.
ZIP содержит и секреты, которые пользователь сохранил в конфигурации самого модуля. База зашифрована на сервере, скачанный ZIP не шифруется автоматически. Копии внутри юзербота не спасают при потере серверного диска.
При создании полной копии активный терминал этого юзербота останавливается, чтобы его файлы не менялись во время копирования. Ссылки сохраняются, если они остаются внутри рабочего каталога; специальные файлы не принимаются. Образ файловой системы из загруженного ZIP не подключается.
Записи базы снимаются в одной транзакции, готовые неизменяемые файлы удерживаются жёсткими ссылками на время сборки ZIP. Архивирование и вычисление SHA256 выполняются в рабочем потоке, не занимая общую блокировку ядра. Другой юзербот может выполнять запросы во время большой копии. Описание копии ограничено 16 MiB, файлов не больше 10000; получение записей не обрезается первой тысячей.
Если процесс оборвался до завершения копии, при следующем запуске ядро удаляет её незаконченный файл, временный каталог и резерв. Удаление пользовательского хранилища ждёт окончания текущего копирования или восстановления, затем обслуживание повторяет очистку.
Для восстановления нужен остановленный юзербот, пароль и TOTP овнера. Проверяются ID среды, типы записей, права, пути, размеры и суммы файлов. Новые файлы готовятся отдельно, их распаковка также не держит общую блокировку ядра. Уже существующие файлы сохраняются, одинаковый ID заменяется версией из копии; восстановление не удаляет автоматически файлы, созданные после неё. Переключение сохраняется в Mekansm; при сбое между базой и состоянием ядро завершает его после запуска. Неверная копия не меняет прежние записи.
После восстановления модули остановлены, сборка выполняется заново. У задач отзываются прежние ключи, принадлежность браузерному входу и полномочия старого вызова. После ручного включения они выполняются с действующими правами модуля. Прежние входящие ключи, кнопки и ожидающие вызовы обработчиков не оживляются из архива. Сохранённые события обмена восстанавливаются как данные с прежними номерами, их получение не запускает обработчик автоматически. Отсутствующая версия модуля показывается как недоступная. Договор не получает доступ к другому экземпляру после переустановки под тем же именем.
Копия сервиса
Оператор останавливает сайт и ядро, затем создаёт копию в новый каталог вне данных:
systemctl stop cluster-api cluster-core
/opt/cluster/env/bin/cluster --path /var/lib/cluster snapshot /backup/cluster-copy --key-file /etc/cluster/core.key
systemctl start cluster-core cluster-apiКоманда проверяет отсутствие работающего ядра, подключённых томов и принадлежащих ему сред. Центральная Mekansm пересоздаётся без Telegram-сессий, кодов писем и старых входов. Ключ ядра не копируется, его нужно хранить отдельно. Файлы копии закрываются правами каталога. Для внешнего хранения оператор добавляет шифрование и свой срок удаления копий.
Восстановление сервиса выполняется в новый пустой каталог с тем же ключом:
/opt/cluster/env/bin/cluster --path /var/lib/cluster-restored restore-service /backup/cluster-copy --key-file /etc/cluster/core.keyПеред записью сверяется состав, размер и SHA256 всех файлов, затем проверяется Mekansm. SHA256 проверяет целостность копии, не подтверждает её автора. Восстанавливается операторская копия из доверенного закрытого хранилища. Копия сохраняет и проверяет состав каталогов, включая пустые, и их права. Пользователь не может вызвать эту операцию через сайт или модуль.
Пути установленных пакетов и версий вебшопа переносятся в новый каталог. Удалённые профили сохраняют своё состояние, их доступ не возвращается. Входы и доступ поддержки отозваны, юзерботы остановлены, Telegram нужно подключить заново. Предыдущий каталог не перезаписывается. Для запуска восстановленного сервиса используются прежние --volumes и пределы хранилища. Размер образа проверяется при открытии, копия не расширяет том автоматически.
Изображения профилей и публикаций
Изображения находятся в личной базе автора по ключам profile-image/<profile>/<kind> и catalog-image/<module>/<kind>. Каждая запись хранит PNG в base64 и сумму charge, включающую строку и служебный резерв. Учёт ведётся одной транзакцией с usage. При замене вычитается прежняя сумма, при удалении запись и её сумма убираются. Временный файл сайта удаляется после сохранения изображения.
В служебной базе находятся настройки профиля person/<profile> и связи friend/<profile>/<other>. Обе стороны связи изменяются одной транзакцией. Эти сведения не открываются модульным API базы. Изображения не подключаются в модульные разделы. Обычная резервная копия юзербота их не экспортирует, восстановление прикладных данных оставляет их на месте. При полном удалении профиля личная база удаляется вместе с изображениями, связи дружбы убираются отдельно.