Restructure repo: per-server folders, inventory, domains
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 # источник правды о парке серверов
|
||||
<server-name>/ # одна папка на сервер, имя совпадает с inventory.servers[].name
|
||||
docker-compose.yml # compose этого узла
|
||||
.env # переменные окружения узла (включая пароли)
|
||||
<service>/ # конфиги конкретных сервисов (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: <name>` — IP подтягивается), либо буквального значения (`value: ...`). Состояние DNS у регистратора должно совпадать с этим файлом.
|
||||
|
||||
Правило: если сервис где-то крутится — его конфиг должен лежать в папке соответствующего сервера в этом репо. Никаких «живёт только на сервере» артефактов.
|
||||
Папка `servers/<name>/` содержит всё, что нужно для развёртывания этого узла. Имя папки = `name` в inventory.
|
||||
|
||||
## Сервисы основного сервера (`docker/docker-compose.yml`)
|
||||
## Где что прописывать при изменениях
|
||||
|
||||
Развёрнуты на `111.88.253.112`:
|
||||
**Добавили новый сервер:**
|
||||
1. Запись в `servers/inventory.yml` (name, host, role, env, location, tags, services).
|
||||
2. Папка `servers/<name>/` с `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/<name>/docker-compose.yml`. Внешние — через traefik-метки (`traefik.http.routers.<name>.*`) с хостом из `.env`. Внутренние — только в сети `internal`.
|
||||
2. Конфиги сервиса — в `servers/<name>/<service>/`, монтировать в контейнер 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: <name>` подтянут новый IP автоматически — но у регистратора надо обновить вручную.
|
||||
|
||||
## VPN
|
||||
**Добавили / изменили домен:**
|
||||
1. Запись в `domains.yml`: блок `domains` для домена, нужные `records`. Для записей, указывающих на наш узел — `server: <name>`, иначе `value: <строка>`.
|
||||
2. Синхронизировать у регистратора. Состояние DNS должно совпадать с файлом.
|
||||
|
||||
Входная (`62.84.114.137`) и выходная (`94.247.214.112`) ноды — оба на **3x-ui**. На основном сервере отдельно крутится **xray** как исходящий прокси для n8n и **mtg** как Telegram-прокси.
|
||||
**Добавили секрет:**
|
||||
1. В `.env` узла либо как файл в `servers/<name>/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.<name>.*` и хостом из `.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/<name>/` и коммитится в репо.
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# domains.yml — источник правды о DNS-записях.
|
||||
# Любые домены, которыми мы пользуемся, должны быть здесь.
|
||||
# Изменения в инфраструктуре (новый сервис, переезд узла, смена IP) обязательно
|
||||
# отражать тут — у регистратора должно быть ровно то, что описано в этом файле.
|
||||
|
||||
# Допустимые типы записей: A, AAAA, CNAME, MX, TXT, SRV, CAA.
|
||||
# server: <name> — ссылка на запись в 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)"
|
||||
@@ -0,0 +1,56 @@
|
||||
# inventory.yml — источник правды о парке серверов.
|
||||
# Добавить сервер = добавить запись сюда + папку servers/<name>/ с 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
|
||||
Reference in New Issue
Block a user