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`.
This commit is contained in:
deytenit authored and GitHub committed 2026-10-25 15:21:09 +03:00
1 parent c6487dc258
commit b3638f4d63
111 files changed
+2350 -1512

No files matched your search

@@ -1,14 +1,14 @@
---
title: Сборка репозитория узла
description: Соберите четыре опоры, зафиксируйте commons и подключите поток capture-up.
description: Соберите четыре опоры, зафиксируйте commons и подключите поток capture-up.
weight: 21
---
**Контекст:** у каждого [узла](/apex/glossary#node) — ровно один репозиторий. Название репозитория может быть любым: [идентичность](/apex/glossary#node-identity) задаётся явно в файле `node.env`, поэтому имя репозитория служит лишь удобным обозначением. В этом руководстве мы пошагово соберём такой репозиторий с нуля.
**Контекст:** у каждого [узла](/apex/glossary#node) — ровно один репозиторий. Название репозитория может быть любым: [идентичность](/apex/glossary#node-identity) задаётся явно в файле `node.env`, поэтому имя репозитория служит лишь удобным обозначением. В этом руководстве мы пошагово соберём такой репозиторий с нуля.
{{% steps %}}
### Инициализируйте репозиторий и зафиксируйте commons
### Инициализируйте репозиторий и зафиксируйте commons
```bash
git init <node-repo> && cd <node-repo>
@@ -18,7 +18,7 @@ git add .gitmodules commons
mkdir -p proprietaries/actions proprietaries/lib configs compositions/apex .github/workflows
```
Ссылка gitlink фиксирует точную версию движка, на&nbsp;которой работает узел. Чтобы обновить движок в&nbsp;будущем, достаточно переключиться на&nbsp;новый тег внутри каталога `commons/` и&nbsp;закоммитить смещение указателя.
Ссылка gitlink фиксирует точную версию движка, на которой работает узел. Чтобы обновить движок в будущем, достаточно переключиться на новый тег внутри каталога `commons/` и закоммитить смещение указателя.
### Объявите идентичность
@@ -30,14 +30,14 @@ APEX_GIT_AUTHOR_NAME=apex [bot]
APEX_GIT_AUTHOR_EMAIL=apex@localhost
```
Файл `node.env` явно задаёт параметры идентификации узла (доменная зона не&nbsp;подразумевается заранее):
Файл `node.env` явно задаёт параметры идентификации узла (доменная зона не подразумевается заранее):
- `APEX_NODE_FQDN`&nbsp;— FQDN хоста для&nbsp;маршрутизации Traefik по&nbsp;правилу `Host()` (если не&nbsp;указан, движок выведет предупреждение и&nbsp;возьмёт имя хоста из&nbsp;ОС).
- `APEX_NODE_HOST`&nbsp;— публичный адрес хоста для&nbsp;параметра `--host` резервного копирования и&nbsp;метки `instance` в&nbsp;системе мониторинга и&nbsp;уведомлениях (по&nbsp;умолчанию совпадает с&nbsp;`APEX_NODE_FQDN`). Первая часть FQDN до&nbsp;точки используется как короткое имя (`name`) узла.
- `APEX_SUBNET`&nbsp;— выделенная подсеть /24 для&nbsp;внутренней сети `direct`. Параметр **обязателен**: без&nbsp;него запуск завершится с&nbsp;кодом&nbsp;66 (см. [Concept: Fleet addressing scheme](/apex/concepts/addressing)).
- `APEX_GIT_AUTHOR_NAME` и&nbsp;`APEX_GIT_AUTHOR_EMAIL`&nbsp;— имя и&nbsp;почта сервисного бота capture-up (если не&nbsp;заданы, применяются значения по&nbsp;умолчанию).
- `APEX_NODE_FQDN` — FQDN хоста для маршрутизации Traefik по правилу `Host()` (если не указан, движок выведет предупреждение и возьмёт имя хоста из ОС).
- `APEX_NODE_HOST` — публичный адрес хоста для параметра `--host` резервного копирования и метки `instance` в системе мониторинга и уведомлениях (по умолчанию совпадает с `APEX_NODE_FQDN`). Первая часть FQDN до точки используется как короткое имя (`name`) узла.
- `APEX_SUBNET` — выделенная подсеть /24 для внутренней сети `direct`. Параметр **обязателен**: без него запуск завершится с кодом 66 (см. [Concept: Fleet addressing scheme](/apex/concepts/addressing)).
- `APEX_GIT_AUTHOR_NAME` и `APEX_GIT_AUTHOR_EMAIL` — имя и почта сервисного бота capture-up (если не заданы, применяются значения по умолчанию).
### Напишите базовую обёртку и&nbsp;файлы переменных окружения
### Напишите базовую обёртку и файлы переменных окружения
```yaml {filename="compositions/apex/docker-compose.yml"}
name: apex
@@ -60,11 +60,11 @@ APEX_OBS_BASIC_AUTH_USER=<node-user>
# APEX_RESTIC_AWS_ENDPOINT= # напр., URL S3-совместимого эндпоинта
```
Файл `apex.env` хранит только публичные параметры конфигурации, которые безопасно коммитить в&nbsp;репозиторий. Переменная `COMPOSE_PROFILES` определяет набор опциональных базовых сервисов: `adguard`, `xray`, `alloy` (агент сбора метрик и&nbsp;логов) и&nbsp;`manual` (разовые запуски бэкапа); список может быть пустым.
Файл `apex.env` хранит только публичные параметры конфигурации, которые безопасно коммитить в репозиторий. Переменная `COMPOSE_PROFILES` определяет набор опциональных базовых сервисов: `adguard`, `xray`, `alloy` (агент сбора метрик и логов) и `manual` (разовые запуски бэкапа); список может быть пустым.
Все секреты, которые нельзя хранить в&nbsp;Git, задокументируйте в&nbsp;`compositions/apex/SECRETS.md`. Это поможет при&nbsp;развёртывании нового узла заполнить локальный файл `.env`: пароль `APEX_RESTIC_PASSWORD`, ключи доступа к&nbsp;S3, токен `APEX_TRAEFIK_CF_DNS_API_TOKEN`, почту `APEX_TRAEFIK_ACME_EMAIL`, а&nbsp;также `APEX_OBS_BASIC_AUTH_PASS` (если включён мониторинг).
Все секреты, которые нельзя хранить в Git, задокументируйте в `compositions/apex/SECRETS.md`. Это поможет при развёртывании нового узла заполнить локальный файл `.env`: пароль `APEX_RESTIC_PASSWORD`, ключи доступа к S3, токен `APEX_TRAEFIK_CF_DNS_API_TOKEN`, почту `APEX_TRAEFIK_ACME_EMAIL`, а также `APEX_OBS_BASIC_AUTH_PASS` (если включён мониторинг).
### Настройте правила игнорирования для&nbsp;Git
### Настройте правила игнорирования для Git
```gitignore {filename=".gitignore"}
**/@tier1
@@ -78,15 +78,15 @@ __pycache__/
### Добавьте bootstrap-скрипт
Скрипт `init.sh` подготавливает свежий клон репозитория на&nbsp;хосте: выполняет `git submodule update --init --recursive`, настраивает хуки `git config core.hooksPath commons/githooks`, добавляет репозиторий в&nbsp;доверенные (`git config --global --add safe.directory <repo>`) и&nbsp;прописывает `<repo>/commons` в&nbsp;переменную `PATH` командной оболочки, чтобы утилита `apex` была доступна глобально. Не&nbsp;забудьте выставить флаг исполняемого файла: `chmod +x init.sh`.
Скрипт `init.sh` подготавливает свежий клон репозитория на хосте: выполняет `git submodule update --init --recursive`, настраивает хуки `git config core.hooksPath commons/githooks`, добавляет репозиторий в доверенные (`git config --global --add safe.directory <repo>`) и прописывает `<repo>/commons` в переменную `PATH` командной оболочки, чтобы утилита `apex` была доступна глобально. Не забудьте выставить флаг исполняемого файла: `chmod +x init.sh`.
### Заведите реестр адресации
Создайте файл `compositions/ADDRESSING.md` с&nbsp;подсетью узла (`APEX_SUBNET`) и&nbsp;схемой распределения адресов: диапазоны `.10`–`.19` зарезервированы за&nbsp;базовыми сервисами (core), а&nbsp;`.20` и&nbsp;выше выделяются под&nbsp;проекты. Все назначаемые в&nbsp;будущем [якорные IP](/apex/glossary#anchor-ip) фиксируются в&nbsp;этом документе.
Создайте файл `compositions/ADDRESSING.md` с подсетью узла (`APEX_SUBNET`) и схемой распределения адресов: диапазоны `.10`–`.19` зарезервированы за базовыми сервисами (core), а `.20` и выше выделяются под проекты. Все назначаемые в будущем [якорные IP](/apex/glossary#anchor-ip) фиксируются в этом документе.
### Подключите CI capture-up
Настройте периодический CI-workflow, который автоматически вливает ветку `sync/<node>` в&nbsp;`main` (если ветка существует) с&nbsp;авторством бота. Шаг checkout должен выполняться **без** загрузки подмодулей: слияние только сдвигает указатель `commons`, а&nbsp;SSH-ссылка на&nbsp;подмодуль недоступна по&nbsp;стандартному CI-токену. Полный цикл описан в&nbsp;разделе [Concept: Framework architecture](/apex/concepts/architecture) ([capture-up](/apex/glossary#capture-up)).
Настройте периодический CI-workflow, который автоматически вливает ветку `sync/<node>` в `main` (если ветка существует) с авторством бота. Шаг checkout должен выполняться **без** загрузки подмодулей: слияние только сдвигает указатель `commons`, а SSH-ссылка на подмодуль недоступна по стандартному CI-токену. Полный цикл описан в разделе [Concept: Framework architecture](/apex/concepts/architecture) ([capture-up](/apex/glossary#capture-up)).
### Проверьте работу
@@ -94,18 +94,18 @@ __pycache__/
./commons/apex --help
```
В&nbsp;списке должны появиться все базовые действия из&nbsp;commons, а&nbsp;позже&nbsp;— и&nbsp;локальные действия из&nbsp;proprietaries. При&nbsp;запуске вне хоста (до&nbsp;заполнения `node.env`) появится предупреждение о&nbsp;том, что `APEX_NODE_FQDN` не&nbsp;задан: в&nbsp;этом случае движок подставит системное имя хоста. При&nbsp;этом переменная `APEX_SUBNET` обязательно должна быть указана, иначе выполнение завершится с&nbsp;кодом&nbsp;66. Закоммитьте подготовленный репозиторий в&nbsp;ветку `main`.
В списке должны появиться все базовые действия из commons, а позже — и локальные действия из proprietaries. При запуске вне хоста (до заполнения `node.env`) появится предупреждение о том, что `APEX_NODE_FQDN` не задан: в этом случае движок подставит системное имя хоста. При этом переменная `APEX_SUBNET` обязательно должна быть указана, иначе выполнение завершится с кодом 66. Закоммитьте подготовленный репозиторий в ветку `main`.
{{% /steps %}}
## Заметки
- Каталог `proprietaries/` изначально может быть пустым (сохраните структуру с&nbsp;помощью файлов `.gitkeep`): движок корректно работает без&nbsp;пользовательских переопределений.
- Переносите конфигурационные файлы хоста в&nbsp;`configs/` (`ufw/`, `cron/crontab`, `systemd/`, `crowdsec/`) по&nbsp;мере подключения шагов `configure/*`. Действия считывают шаблоны из&nbsp;`configs/` напрямую.
- Каталог `proprietaries/` изначально может быть пустым (сохраните структуру с помощью файлов `.gitkeep`): движок корректно работает без пользовательских переопределений.
- Переносите конфигурационные файлы хоста в `configs/` (`ufw/`, `cron/crontab`, `systemd/`, `crowdsec/`) по мере подключения шагов `configure/*`. Действия считывают шаблоны из `configs/` напрямую.
---
**См.&nbsp;также:**
**См. также:**
- [Getting started with an apex node](/apex/getting-started)
- [Concept: Framework architecture](/apex/concepts/architecture)