🤖 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`.
79 lines
8.4 KiB
Markdown
79 lines
8.4 KiB
Markdown
---
|
||
title: Архитектура фреймворка
|
||
description: Четыре опоры репозиториев узла, субмодуль commons и поток диспетчеризации.
|
||
weight: 11
|
||
---
|
||
|
||
Фреймворк apex делит автоматизацию флота между одним общим репозиторием ([«commons»](/apex/glossary#commons)) и отдельными репозиториями для каждого [узла](/apex/glossary#node). В commons сосредоточено всё общее для флота: [движок](/apex/glossary#engine), стандартные [действия](/apex/glossary#action) и [ядровая композиция](/apex/glossary#core-composition). Репозиторий узла содержит специфичные для хоста данные: его идентичность, хостовые [конфигурации](/apex/glossary#configs), сервисные [композиции](/apex/glossary#compositions) и локальные [проприетарии](/apex/glossary#proprietaries).
|
||
|
||
## Четыре опоры {#pillars}
|
||
|
||
Каждый репозиторий узла имеет одинаковую структуру:
|
||
|
||
{{< filetree/container >}}
|
||
{{< filetree/folder name="<node>.<your-domain>" state="open" >}}
|
||
{{< filetree/folder name="commons" state="closed" >}}{{< /filetree/folder >}}
|
||
{{< filetree/folder name="proprietaries" state="closed" >}}{{< /filetree/folder >}}
|
||
{{< filetree/folder name="configs" state="closed" >}}{{< /filetree/folder >}}
|
||
{{< filetree/folder name="compositions" state="closed" >}}{{< /filetree/folder >}}
|
||
{{< filetree/file name="node.env" >}}
|
||
{{< filetree/file name="init.sh" >}}
|
||
{{< /filetree/folder >}}
|
||
{{< /filetree/container >}}
|
||
|
||
| Опора | Содержимое | Владение |
|
||
|---|---|---|
|
||
| `commons/` | Git-субмодуль → `apex.ermnvldmr.com`, закреплённый на релизном теге | Общее, версионируемое |
|
||
| `proprietaries/` | Узло-локальные действия, библиотеки и исходники инструментов ([накладываются оверлеем](/apex/glossary#overlay) поверх commons) | Узел |
|
||
| `configs/` | Исходники конфигурации хоста: `ufw/`, `cron/crontab`, `systemd/`, `crowdsec/` | Узел |
|
||
| `compositions/` | По одному каталогу на проект, ядровая обёртка `apex/` и реестр адресации | Узел |
|
||
|
||
Фиксация субмодуля — версионный контракт фреймворка: узел выполняет именно ту версию движка и ядровой композиции, которая зафиксирована в его gitlink. Обновление узла выполняется явно: достаточно переключиться на новый тег внутри `commons/` и закоммитить изменённый указатель.
|
||
|
||
## Поток диспетчеризации {#dispatch}
|
||
|
||
Лаунчер `commons/apex` работает с локальным чекаутом; передавать узел в качестве аргумента не нужно нигде.
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A["apex <group>/<action> [args]"] --> B{Схема размещения}
|
||
B -- "каталог commons/ с node.env рядом" --> C[Checkout узла:<br/>оверлей = proprietaries/actions]
|
||
B -- иначе --> D[Автономный commons:<br/>без оверлея]
|
||
C --> E["Разрешение оверлея<br/>(сначала proprietaries)"]
|
||
D --> E
|
||
E --> F["Разрешение идентичности<br/>(FQDN + node.env)"]
|
||
F --> G["Построение ctx<br/>(log, sys, tpl, host, ufw,<br/>crowdsec, systemd, notify)"]
|
||
G --> H["разбор аргументов (Meta)"]
|
||
H --> I["run(ctx, args)"]
|
||
```
|
||
|
||
Движок определяет режим работы по своему расположению на диске. Если он запущен из каталога `commons/`, а в родительском каталоге присутствует `node.env`, то родительский каталог принимается за корень репозитория узла, а `proprietaries/actions/` становится деревом оверлея. При любом другом расположении commons считается автономным чекаутом и выступает собственным корнем.
|
||
|
||
Команда перечисления (`apex --help`) никогда не импортирует модули действий: краткие описания и маркеры отключения извлекаются статически с помощью модуля `ast`. При диспетчеризации загружается ровно один модуль по вычисленному пути. Подробнее — в разделе [Концепция: Действия и оверлей](/apex/concepts/actions-and-overlay).
|
||
|
||
## Модель «capture-up» {#capture-up}
|
||
|
||
Репозитории узлов служат реестрами состояния, а не просто источниками конфигурации: хост сам фиксирует то, что выполняет на практике.
|
||
|
||
1. Регулярная задача `sync/repository` на хосте коммитит рабочее дерево в ветку `sync/<node>` (включая указатель субмодуля commons), делает rebase поверх `origin/main` и выполняет push с флагом `--force-with-lease`.
|
||
2. Запланированное CI-задание в репозитории узла вливает ветку `sync/<node>` обратно в `main` от имени бота.
|
||
|
||
Благодаря циклу [«capture-up»](/apex/glossary#capture-up) любой дрейф конфигурации на хосте превращается в коммит: изменение наглядно отображается в diff и легко откатывается, исключая незаметные расхождения. Если субмодуль commons имеет незакоммиченные изменения («грязный») или каталог `compositions/` отсутствует, синхронизация прерывается без коммита, поэтому повреждённое состояние чекаута никогда не попадёт в историю.
|
||
|
||
> [!NOTE]
|
||
> CI-задание слияния клонирует репозиторий *без* субмодулей: субмодуль commons подключён по SSH-URL, недоступному стандартному токену CI, а самому слиянию требуется лишь обновить указатель gitlink.
|
||
|
||
## Проектные ограничения {#constraints}
|
||
|
||
- **Только стандартная библиотека (stdlib).** Движок работает на штатном Python 3 из Debian — без `pip` и сторонних зависимостей. Каталог `vendor/` зарезервирован для зафиксированного чистого Python-кода, но по умолчанию поставляется пустым.
|
||
- **Ручные compose-файлы.** Никаких промежуточных манифестов или кодогенерации: файлы compose служат единственным источником истины.
|
||
- **Автоматическая проверка вместо соглашений.** Всё, что можно проверить или применить автоматически, выполняется действием (проверка якорных IP, откат crontab, самовосстановление блоков-маркеров), а не остаётся на совести документации.
|
||
|
||
---
|
||
|
||
**См. также:**
|
||
|
||
- [Концепция: Действия и оверлей](/apex/concepts/actions-and-overlay)
|
||
- [Концепция: Разрешение идентичности узла](/apex/concepts/node-identity)
|
||
- [Руководство: Сборка репозитория узла](/apex/guides/node-repository)
|