Files
ermnvldmr.com/services/docs/content/ru/apex/concepts/tiered-storage.md
T
deytenit b3638f4d63 fix: cyrillic fonts, dev certs, page head, and ru-text typography (#67)
🤖 PR generated for branch `fix/cyrillic-fonts-dev-certs-and-page-head`.

### Changes Summary
- **Fonts**: Add Cyrillic glyph subsets for Lato, EB Garamond, and Fira
Code.
- **Dev**: Support remote Root CA and encrypted dev CA key in
`.env.dev`.
- **UI & Kits**: Add size variant to `Breadcrumbs` component and enlarge
`PageHead` breadcrumbs with tuned collapse scroll threshold.
- **ESLint**: Add `no-hanging-particles` i18n & markdown typography rule
with auto-fixer.
- **Content & i18n**: Apply `ru-text` editorial and typography polish
(em dashes, number ranges, «ё» restoration, non-breaking spaces) across
`services/www` and `services/docs`.
2026-10-25 15:21:09 +03:00

10 KiB

title, description, weight
title description weight
Многоуровневое хранилище и изоляция привилегий Структура ссылок @tier, разделяемое хранилище и локальные noroot-пользователи для проектов. 16

Данные сервисов никогда не хранятся внутри репозитория узла. Они распределяются по трём уровням хранилища — отдельным каталогам, настраиваемым индивидуально для каждого хоста, — и подключаются к композициям через стандартизированную структуру символьных ссылок. Права на эти каталоги делегируются системным пользователям проектов, благодаря чему ни один контейнер не ведёт запись от имени root.

Команда apex tiers/link <tier1> <tier2> <tier3> формирует два уровня символьных ссылок:

  • На уровне узла: compositions/@tierN → корень хранилища соответствующего уровня. Именно эти пути движок предоставляет в переменных APEX_TIER_ROOT1..3.
  • Для каждого проекта: в каталоге compositions/<project>/ создаётся путь <tier-root>/<project>/, на который указывает ссылка compositions/<project>/@tierN. Внутри каждого уровня поддерживается общий каталог shared/ с поддиректорией для каждого проекта, а внутри каталога уровня проекта создаётся относительная ссылка shared, ведущая обратно в общую зону.

Каждый проект дополнительно получает символьную ссылку compositions/<project>/.env → <tier1-root>/<project>/.env (создаётся пустым, если файл отсутствует). В нём хранятся незакоммиченные секреты (см. Концепция: Композиции и общее ядро). Ссылки @tierN и файлы .env исключены из git через .gitignore, благодаря чему репозиторий остаётся чистым источником кода.

Если по пути предполагаемой символьной ссылки уже существует обычный файл или каталог, действие предупреждает об этом и запрашивает подтверждение перед удалением. При отказе (включая неинтерактивный EOF) создание ссылки пропускается, а выполнение продолжается дальше.

Пользователи и группы

Команда apex tiers/useradd создаёт по одному заблокированному системному пользователю на проект — noroot-<project> (с санитизацией имени и собственной первичной группой), а также общефлотовую группу noroot-shared, в которую входят все пользователи проектов. Затем сгенерированные идентификаторы прописываются в файл .env соответствующего проекта между комментариями-маркерами, перезаписывая старый блок при повторных запусках:

# START AUTO GENERATED APEX-NOROOT-USERS
APEX_UID=998
APEX_GID=998
APEX_SHARED_GID=997
# END AUTO GENERATED APEX-NOROOT-USERS

Композиции подключают эти идентификаторы через переменные user: "${APEX_UID?error}:${APEX_GID?error}" и group_add: ["${APEX_SHARED_GID?error}"].

Матрица владения

Действие apex tiers/chown выставляет корректные права по всем трём уровням хранилища. Без аргументов оно обрабатывает корни уровней (APEX_TIER_ROOT1..3); при необходимости можно указать конкретные пути вручную.

Путь Владение Примечания
<tier-root> root:root Только inode каталога.
<tier-root>/shared root:root Только inode каталога (без рекурсии, чтобы не затронуть пользовательские данные проектов).
<tier-root>/node-infra root:root Рекурсивно.
<tier-root>/<project> uid:gid Рекурсивно; идентификаторы читаются из .env проекта.
<tier-root>/shared/<project> uid:shared_gid Рекурсивно, с установкой sticky-бита: участники могут добавлять файлы, но удалять — только собственные.

Проекты с неполным набором переменных APEX_UID, APEX_GID или APEX_SHARED_GID пропускаются с предупреждением и рекомендацией выполнить tiers/useradd.

Переменные уровней движка

Переменная Разрешается в 
APEX_TIER_ROOT1..3 Корни хранилищ уровней (compositions/@tierN, абсолютные пути).
APEX_TIER1..3 Каталоги данных ядрового проекта на каждом уровне (compositions/apex/@tierN).
APEX_TIER1..3_SHARED Общие области внутри уровней ядрового проекта.

Ядровая композиция монтирует каталоги исключительно через эти переменные. Контейнер резервного копирования, напротив, монтирует общий корень данных флота /srv в режиме «только для чтения» и сопоставляет контейнерные пути каждого сервиса с их реальными путями на хосте.

Резервное копирование

Команда apex backup/run <telegram-bot-url> полностью берёт на себя управление сервисом resticontainer (профиль manual, одноразовый запуск). Резервное копирование управляется метками: resticontainer находит все контейнеры с меткой restic.enable=true, считывает список путей restic.backup.paths (и необязательные параметры restic.backup.stop / restic.hooks.*), транслирует пути контейнеров в пути хоста и создаёт единый снимок restic.

  1. Проверяет доступность репозитория с помощью команды snapshots; при необходимости автоматически инициализирует его.
  2. Запускает команду backup с параметрами --host <APEX_NODE_HOST> и --tag biweekly. При этом resticontainer выполняет pre-hook сервиса, временно останавливает контейнеры с меткой restic.backup.stop, делает снимок хостовых путей, перезапускает остановленные контейнеры и запускает post-hooks. Запуск не засчитывается как успешный, если в репозитории не появился новый снимок (защита от ложного успеха при отсутствии помеченных сервисов).
  3. Применяет политику хранения с помощью forget --prune (хранятся 7 ежедневных, 4 еженедельных и 12 ежемесячных снимков).
  4. Отправляет статус выполнения в Telegram. Если уведомление не удалось доставить, операция завершается с кодом ошибки 1 даже при успешном бэкапе, чтобы сбой в канале оповещения не остался незамеченным.

Параметры подключения и учётные данные репозитория считываются из конфигурации APEX_RESTIC_* (см. Справочник: Переменные окружения). Состав сохраняемых данных определяется метками каждого отдельного сервиса. Например, для ядровых сервисов копируются только файлы конфигурации (динамические правила traefik, настройки xray и adguard), тогда как легко восстановимые данные уровня 3 (кэши и журналы) в снимок не включаются.


См. также: