From 6dd6b586b5c8bead41d88a021b6f75c524bf0904 Mon Sep 17 00:00:00 2001 From: maximilion96 Date: Sat, 13 Jun 2026 12:50:37 +0300 Subject: [PATCH] Restructure repo: per-server folders, inventory, domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - servers/inventory.yml — реестр узлов (имена, IP, роли, сервисы). - domains.yml — реестр DNS-записей для mxti.ru (reg.ru). - docker/ → servers/ru-docker-infra/ — конфиги основного сервера. - CLAUDE.md переписан: структура репо, чек-листы по изменениям, конвенции (роли вместо IP, секреты тоже в репо). Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 89 ++++++++++--------- domains.yml | 32 +++++++ servers/inventory.yml | 56 ++++++++++++ {docker => servers/ru-docker-infra}/.env | 0 .../ru-docker-infra}/docker-compose.yml | 0 .../ru-docker-infra}/mtg/config.toml | 0 .../ru-docker-infra}/xray/config.json | 0 7 files changed, 136 insertions(+), 41 deletions(-) create mode 100644 domains.yml create mode 100644 servers/inventory.yml rename {docker => servers/ru-docker-infra}/.env (100%) rename {docker => servers/ru-docker-infra}/docker-compose.yml (100%) rename {docker => servers/ru-docker-infra}/mtg/config.toml (100%) rename {docker => servers/ru-docker-infra}/xray/config.json (100%) diff --git a/CLAUDE.md b/CLAUDE.md index ecf7b7e..b411b5e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,61 +1,68 @@ # Personal Infrastructure -Репозиторий моей личной инфраструктуры. Всё разворачивается через Docker (предпочтительный метод), конфиги хранятся в этом репо. +Репозиторий моей личной инфраструктуры: VPN, git-хостинг, автоматизация, реверс-прокси и всё, что будет добавляться дальше. Цель — держать в одном месте всё, что нужно, чтобы развернуть любой узел с нуля. -## Серверы +Принципы: -| IP | Локация | Роль | -|---|---|---| -| `111.88.253.112` | Yandex Cloud | Основной сервер — все основные сервисы (n8n, gitea, traefik, portainer, postgres, redis, xray, mtg) | -| `62.84.114.137` | Yandex Cloud | Входная нода VPN (3x-ui) | -| `94.247.214.20` | Нидерланды | Реверс-прокси для n8n (принимает SSH-туннель с основного сервера) | -| `94.247.214.112` | Нидерланды | Выходная нода VPN (3x-ui) | +- **Docker — предпочтительный способ развёртывания.** Если можно завернуть в compose — заворачиваем. +- **Репозиторий — единственный источник правды.** На самих серверах ничего уникального жить не должно: все конфиги, compose-файлы, скрипты, артефакты, `.env` — в git. Сервер тянет нужную папку и поднимает её. +- **Секреты тоже в репо.** `.env` с паролями коммитим вместе с остальным (репо приватный). Приватные ключи (`ssh/tunnel_key` и т.п.) — туда же, как файлы рядом с compose. ## Структура репозитория -Всё, что нужно для развёртывания, хранится в этом репо. Под каждый сервер — отдельная папка верхнего уровня со всеми его конфигами, compose-файлами, артефактами и т.п. +``` +servers/ + inventory.yml # источник правды о парке серверов + / # одна папка на сервер, имя совпадает с inventory.servers[].name + docker-compose.yml # compose этого узла + .env # переменные окружения узла (включая пароли) + / # конфиги конкретных сервисов (xray, mtg, nginx, ...) + ssh/ # ключи и прочие чувствительные файлы +domains.yml # источник правды о DNS-записях для всех доменов +CLAUDE.md # этот файл — обзор и правила +README.md +``` -| Папка | Сервер | Назначение | -|---|---|---| -| `docker/` | `111.88.253.112` | Основной сервер (текущее содержимое) | -| _tbd_ | `62.84.114.137` | Входная нода VPN | -| _tbd_ | `94.247.214.20` | NL реверс-прокси для n8n | -| _tbd_ | `94.247.214.112` | Выходная нода VPN | +`servers/inventory.yml` — реестр узлов: имена, адреса, роли, локации, ssh-настройки, список сервисов. Любые ответы про «какой сервер», «где что крутится», «какой у него IP» берём оттуда. -Папки для остальных серверов добавим по мере того, как будем переносить туда конфиги. Имена папок — по роли сервера (например, `vpn-entry/`, `nl-proxy/`, `vpn-exit/`), не по IP. +`domains.yml` — реестр DNS-записей. Для каждого домена перечислены все нужные записи (A, CNAME, TXT, MX и т.п.) с указанием либо узла из inventory (`server: ` — IP подтягивается), либо буквального значения (`value: ...`). Состояние DNS у регистратора должно совпадать с этим файлом. -Правило: если сервис где-то крутится — его конфиг должен лежать в папке соответствующего сервера в этом репо. Никаких «живёт только на сервере» артефактов. +Папка `servers//` содержит всё, что нужно для развёртывания этого узла. Имя папки = `name` в inventory. -## Сервисы основного сервера (`docker/docker-compose.yml`) +## Где что прописывать при изменениях -Развёрнуты на `111.88.253.112`: +**Добавили новый сервер:** +1. Запись в `servers/inventory.yml` (name, host, role, env, location, tags, services). +2. Папка `servers//` с `docker-compose.yml` и `.env`. +3. Если узлу нужен домен — добавить записи в `domains.yml` и прописать их у регистратора. +4. Если узел упоминается смысловой ролью (например, тут есть бэкенд для другого узла) — обновить соответствующие compose/конфиги, ссылаясь на роль, а не IP. -- **traefik** — реверс-прокси + Let's Encrypt, слушает 80/443, маршрутизирует по Host-меткам. -- **postgres** (16-alpine) — общая БД для n8n и gitea. -- **redis** (7-alpine) — кэш и очередь Bull для n8n. -- **n8n** — автоматизация. HTTP(S)_PROXY через `xray` для обхода блокировок. Публикуется по `${N8N_HOST}` через traefik, а также пробрасывается SSH-туннелем (`tunnel` сервис) на `94.247.214.20:5678` для внешнего доступа через NL-реверс-прокси. -- **tunnel** (autossh) — обратный SSH-туннель `-R` на `94.247.214.20`, пользователь `tunnel`, ключ в `./ssh/tunnel_key`. -- **xray** — исходящий прокси для n8n (порт 8080 во внутренней сети). -- **gitea** — git-хостинг, БД в общем postgres (`gitea`/`gitea`), SSH на хосте проброшен на `222`. -- **portainer** — UI для управления docker. -- **mtg** — Telegram MTProto-прокси с fake TLS, проксируется через traefik TCP по SNI `${MTG_FAKE_TLS_HOST}`. +**Добавили сервис на существующий сервер:** +1. Сервис в `servers//docker-compose.yml`. Внешние — через traefik-метки (`traefik.http.routers..*`) с хостом из `.env`. Внутренние — только в сети `internal`. +2. Конфиги сервиса — в `servers///`, монтировать в контейнер read-only. +3. Новые переменные — в `.env` узла. В compose использовать `${VAR}`, не хардкодить. +4. Запись `services: [...]` у узла в `inventory.yml`. +5. Если сервис публикуется наружу — DNS-запись в `domains.yml` и у регистратора. -Сети: `proxy` (внешний трафик через traefik) и `internal` (между сервисами и БД). +**Изменили IP / переехали:** +1. Только `inventory.yml` (поле `host`). Compose-файлы IP не содержат — там ссылки на сервисы по имени или на роли. +2. Проверить `domains.yml`: записи со ссылкой `server: ` подтянут новый IP автоматически — но у регистратора надо обновить вручную. -## VPN +**Добавили / изменили домен:** +1. Запись в `domains.yml`: блок `domains` для домена, нужные `records`. Для записей, указывающих на наш узел — `server: `, иначе `value: <строка>`. +2. Синхронизировать у регистратора. Состояние DNS должно совпадать с файлом. -Входная (`62.84.114.137`) и выходная (`94.247.214.112`) ноды — оба на **3x-ui**. На основном сервере отдельно крутится **xray** как исходящий прокси для n8n и **mtg** как Telegram-прокси. +**Добавили секрет:** +1. В `.env` узла либо как файл в `servers//ssh/` (или аналогичной служебной папке). +2. Никогда не хардкодить в compose или конфиг-файлах — только через `${VAR}` или монтируемый файл. -## Конфиги в репо - -- `docker/docker-compose.yml` — основной compose. -- `docker/.env` — переменные (`*_HOST`, пароли, `N8N_ENCRYPTION_KEY`, `ACME_EMAIL`, `TIMEZONE`). Не коммитить секреты. -- `docker/xray/config.json` — конфиг xray-клиента. -- `docker/mtg/config.toml` — конфиг mtg. -- `docker/ssh/tunnel_key` — приватный ключ для autossh-туннеля (не в git). +**Удалили сервис / сервер:** +1. Убрать запись из `inventory.yml` (или из `services` узла). +2. Удалить соответствующий блок из compose и папку с конфигами. ## Конвенции -- Новые сервисы добавляем в `docker/docker-compose.yml`, публикуем через traefik с метками `traefik.http.routers..*` и хостом из `.env`. -- Внутренние сервисы — только в сети `internal`, публичные — в `proxy` (или в обеих, если нужен доступ к БД). -- Секреты — через `.env`, не хардкодить в compose. +- Адреса серверов — только в `inventory.yml`. В compose и доках ссылаемся на роли (`core`, `vpn-entry`, `reverse-proxy`, `vpn-exit` и т.п.). +- Сети compose: `proxy` для внешнего трафика через traefik, `internal` для межсервисной коммуникации и БД. Сервис в обеих сетях — только если ему правда нужен доступ и снаружи, и к внутренним зависимостям. +- Имя папки сервера = `name` в inventory, по роли, не по IP. +- Любой артефакт, без которого сервер не поднимется (compose, `.env`, конфиг, ключ) — лежит в `servers//` и коммитится в репо. diff --git a/domains.yml b/domains.yml new file mode 100644 index 0000000..67cd857 --- /dev/null +++ b/domains.yml @@ -0,0 +1,32 @@ +# domains.yml — источник правды о DNS-записях. +# Любые домены, которыми мы пользуемся, должны быть здесь. +# Изменения в инфраструктуре (новый сервис, переезд узла, смена IP) обязательно +# отражать тут — у регистратора должно быть ровно то, что описано в этом файле. + +# Допустимые типы записей: A, AAAA, CNAME, MX, TXT, SRV, CAA. +# server: — ссылка на запись в servers/inventory.yml (host подставляется оттуда). +# value: <строка> — буквальное значение записи (для CNAME/TXT/MX/...). + +domains: + - name: mxti.ru + registrar: reg.ru + records: + - host: www + type: A + server: ru-docker-infra + purpose: "основной сервер (traefik)" + + - host: git + type: A + server: ru-docker-infra + purpose: "gitea через traefik" + + - host: portainer + type: A + server: ru-docker-infra + purpose: "portainer UI" + + - host: n8n + type: A + server: nl-reverse-proxy + purpose: "n8n через NL реверс-прокси (autossh-туннель с ru-docker-infra)" diff --git a/servers/inventory.yml b/servers/inventory.yml new file mode 100644 index 0000000..f9b2dce --- /dev/null +++ b/servers/inventory.yml @@ -0,0 +1,56 @@ +# inventory.yml — источник правды о парке серверов. +# Добавить сервер = добавить запись сюда + папку servers// с docker-compose.yml. + +defaults: # общие настройки, чтобы не повторять в каждом сервере + ssh_user: agent # отдельный non-root пользователь для бота + branch: main # ветка, которую тянут серверы + compose_path: servers/{name}/docker-compose.yml # {name} подставляется из поля name + +servers: + - name: ru-docker-infra # основной сервер в Яндекс.Облаке + host: 111.88.253.112 + role: core # основной узел: все ключевые сервисы + env: prod + location: yandex-cloud + tags: [traefik, n8n, gitea, postgres, redis, portainer, xray, mtg] + services: + - traefik + - postgres + - redis + - n8n + - tunnel # autossh-туннель на nl-reverse-proxy + - xray # исходящий прокси для n8n + - gitea + - portainer + - mtg # Telegram MTProto-прокси + managed: true + + - name: ru-vpn # входная нода VPN + host: 62.84.114.137 + role: vpn-entry + env: prod + location: yandex-cloud + tags: [3x-ui, vpn] + services: + - 3x-ui + managed: true + + - name: nl-reverse-proxy # реверс-прокси для n8n (принимает SSH-туннель) + host: 94.247.214.20 + role: reverse-proxy + env: prod + location: netherlands + tags: [n8n, ssh-tunnel] + services: + - nginx # tbd: уточнить, чем именно проксируется + managed: true + + - name: nl-vpn # выходная нода VPN + host: 94.247.214.112 + role: vpn-exit + env: prod + location: netherlands + tags: [3x-ui, vpn] + services: + - 3x-ui + managed: true diff --git a/docker/.env b/servers/ru-docker-infra/.env similarity index 100% rename from docker/.env rename to servers/ru-docker-infra/.env diff --git a/docker/docker-compose.yml b/servers/ru-docker-infra/docker-compose.yml similarity index 100% rename from docker/docker-compose.yml rename to servers/ru-docker-infra/docker-compose.yml diff --git a/docker/mtg/config.toml b/servers/ru-docker-infra/mtg/config.toml similarity index 100% rename from docker/mtg/config.toml rename to servers/ru-docker-infra/mtg/config.toml diff --git a/docker/xray/config.json b/servers/ru-docker-infra/xray/config.json similarity index 100% rename from docker/xray/config.json rename to servers/ru-docker-infra/xray/config.json