Remove deprecated files related to homelab architecture, container context, and various scripts. This cleanup includes the removal of configuration files for Nextcloud, Gitea, and VPN setups, as well as documentation files that are no longer relevant. This helps streamline the project and eliminate outdated references.

This commit is contained in:
2026-02-25 17:03:10 +03:00
parent 3c00fbf67b
commit b0d2746490
74 changed files with 2662 additions and 7107 deletions

View File

@@ -0,0 +1,99 @@
# Архитектура и подключение
Краткое описание домашнего контура: сеть, доступ, гипервизор и ключевые контейнеры.
---
## Сеть и доступ
- **Внешний IP:** 185.35.193.144
- **Домашний сервер (Proxmox):** 192.168.1.150 (LAN)
- Подключение: `ssh root@192.168.1.150`
- **DNS домена katykhin.ru:** Beget.com
- Учётная запись: логин `amauri7g`, пароль `QgkaKL3RykeI`, ID аккаунта 2536839. Режим API включён. Домен **katykhin.store** в аккаунте есть, но не используется (поддоменов нет).
- **Reverse proxy и SSL:** Nginx Proxy Manager (NPM) на контейнере 100.
**Поддомены katykhin.ru:**
В панели Beget отображаются все перечисленные ниже; через API `getSubdomainList` приходят только часть (в т.ч. служебные `_acme-challenge.*`). Полный список ведём вручную.
| Поддомен | Назначение |
|----------|------------|
| api.katykhin.ru | — |
| call.katykhin.ru | Galene (видеозвонки) |
| cloud.katykhin.ru | — |
| docs.katykhin.ru | — |
| git.katykhin.ru | — |
| home.katykhin.ru | Homepage |
| immich.katykhin.ru | — |
| mini-lm.katykhin.ru | — |
| obsidian.katykhin.ru | — |
| share.katykhin.ru | — |
| video.katykhin.ru | Invidious |
| wallos.katykhin.ru | Wallos |
| _acme-challenge.call.katykhin.ru | Служебный (DNS-01 Let's Encrypt) |
*Назначение для api, cloud, docs, git, immich, mini-lm, obsidian, share можно заполнить позже при описании контейнеров.*
---
## Гипервизор
- **Proxmox VE.** Гости — в основном **LXC-контейнеры**, одна **KVM VM** (Immich, ID 200).
- Управление LXC: `pct` (например `pct exec <ID> -- bash`). Управление VM: `qm`.
- IP контейнера задаётся вручную (статически в LXC или через DHCP-резерв на роутере). Схема: **ID контейнера = последний октет IP** (например контейнер 105 → 192.168.1.105; исключения вносить в таблицу контейнеров).
**Создание контейнера через pct (пример):** ВМ с ID 105, 1 ядро, 1 ГБ RAM, IP 192.168.1.105. Шаблон — из local (подставь свой, например `debian-12-standard`). Шлюз ниже — типичный для домашней сети; при необходимости замени на свой.
```bash
pct create 105 local:vztmpl/debian-12-standard_12.2-1_amd64.tar.zst \
--hostname ct105 \
--memory 1024 \
--cores 1 \
--net0 name=eth0,bridge=vmbr0,ip=192.168.1.105/24,gw=192.168.1.1,type=veth
```
После создания: `pct start 105`; зайти в консоль: `pct enter 105` или `pct exec 105 -- bash`.
---
## Ключевые контейнеры и ВМ
| ID | Назначение | IP | Ресурсы | Домены (через NPM) |
|-----|-------------------------------|----------------|------------|---------------------|
| 100 | NPM, Homepage, AdGuard, Wallos | 192.168.1.100 | 1 core, 2 GB | home.katykhin.ru, wallos.katykhin.ru, adguard.local. → [Контейнер 100 (подробно)](../containers/container-100.md) |
| 101 | Nextcloud | 192.168.1.101 | 2 core, 3 GB | cloud.katykhin.ru. → [Контейнер 101 (подробно)](../containers/container-101.md) |
| 103 | Gitea, сервис Obsidian (5984) | 192.168.1.103 | 1 core, 2 GB | obsidian.katykhin.ru → [Контейнер 103 (подробно)](../containers/container-103.md) |
| 104 | Paperless | 192.168.1.104 | 1 core, 2 GB | docs.katykhin.ru → [Контейнер 104 (подробно)](../containers/container-104.md) |
| 105 | RAG-service | 192.168.1.105 | 1 core, 1 GB | mini-lm.katykhin.ru → [Контейнер 105 (подробно)](../containers/container-105.md) |
| 107 | Invidious (misc) | 192.168.1.107 | 1 core, 2 GB | video.katykhin.ru → [Контейнер 107 (подробно)](../containers/container-107.md) |
| 108 | Galene | 192.168.1.108 | 1 core, 256 MB | call.katykhin.ru → [Контейнер 108 (подробно)](../containers/container-108.md) |
| 200 | Immich, immich-pt и др. | 192.168.1.200 | 3 core, 10 GB | immich.katykhin.ru → [ВМ 200 (подробно)](../containers/container-200.md) |
*100108 — LXC-контейнеры (pct), 200 — KVM-ВМ (qm).* Домены api, git, share и др. в NPM при необходимости добавить позже.
---
## Поток запросов (упрощённо)
1. Запрос из интернета: `https://video.katykhin.ru` → роутер (порты 80/443 на 185.35.193.144) → проброс на 192.168.1.100.
2. NPM (контейнер 100) принимает HTTPS, проверяет Host, смотрит proxy_host → upstream (например 192.168.1.107:3000 для video.katykhin.ru, 192.168.1.200:2283 для immich.katykhin.ru).
3. Бэкенд-сервис (например Invidious в контейнере 107) отдаёт страницу; при «без прокси» видео стримится напрямую с YouTube в браузер.
---
## SSL-сертификаты
- **Let's Encrypt:** certbot на контейнере 100; для доменов без доступа по HTTP-01 используется **DNS-01** (Beget API). После выпуска/продления сертификаты подкладываются в NPM (custom_ssl) и перезагружается nginx.
**Полная инструкция:** [Выпуск сертификата Let's Encrypt (DNS-01)](../network/ssl-letsencrypt-dns01.md).
- **Самоподписные:** при необходимости добавляются вручную в NPM (БД + файлы в custom_ssl).
---
## Дополнительно
- **Схема сети и зависимости:** полная топология (роутер, Proxmox, контейнеры, VPS), таблица IP/доменов, маршруты NPM, кто от кого зависит, единые точки отказа (SPOF). → [Схема сети и зависимости](../network/network-topology.md).
- **Homepage:** на контейнере 100, конфиг сервисов в `/opt/docker/homepage/config/services.yaml` (ссылки на NPM, Invidious, AdGuard, Immich, Galene и т.д.).
- **VPN (VPS):** отдельный сервер 185.103.253.99, AmneziaWG для обхода блокировок. → [VPN-сервер (VPS, AmneziaWG)](../vps/vpn-vps-amneziawg.md).
- **Роутер:** Netcraze Speedster, два WireGuard/AmneziaWG (Германия / США), маршрутизация части трафика через VPN. → [Роутер Netcraze Speedster](../network/router-netcraze-speedster.md).
- **VPS Миран (СПБ):** боты (telegram-helper-bot, anonBot), prod-инфраструктура, STUN/TURN для Galene. → [VPS Миран: боты и STUN/TURN](../vps/vps-miran-bots.md).
- Подробнее по контейнерам и сервисам — в отдельных статьях (по мере появления).

View File

@@ -0,0 +1,262 @@
# Фаза 1: Стратегия бэкапов Proxmox
Цель: при смерти SSD с системой или потере `/etc/pve` — развернуть Proxmox, восстановить контейнеры/ВМ, поднять сервисы без многочасового восстановления и угадывания паролей.
**Приоритет №1.** ИБП уже есть; защищаемся от смерти диска.
---
## Что бэкапить
| Объект | Зачем |
|--------|--------|
| **LXC и VM целиком** (vzdump) | Восстановление контейнера/ВМ из одного архива: ОС, конфиги, данные на корневом томе. Не только данные внутри — сам образ для restore. |
| **/etc/pve** | Конфиги кластера, VM/LXC (ID, сеть, диски, задачи), пользователи Proxmox, права. Без этого после переустановки Proxmox не восстановить привязку дисков и настройки. |
---
## Пошаговый план
### Шаг 1. Определить хранилище для бэкапов
**Выбранная схема:**
| Место | Описание | Что туда |
|-------|----------|----------|
| **Локально: /dev/sdb1 (1 ТБ под бэкапы)** | Отдельный SSD 2 ТБ; под копии выделен 1 ТБ, смонтирован в `/mnt/backup`. Второй ТБ — в запас. | Proxmox vzdump (через UI), затем те же данные (dump, etc-pve, фотки, VPS) в Yandex через restic. Фотки: оригиналы + метаданные + БД Immich; остальное пересчитать можно. VPS: Amnezia — конфиг; Миран — БД бота + контент (контент можно в S3 Мирана; копию на sdb1 — опционально). Конфигурацию серверов не бэкапим — есть Ansible. |
| **Офсайт: Yandex Object Storage (S3)** | Арендованный бакет, S3-совместимый API. [Yandex Object Storage](https://yandex.cloud/ru/docs/storage/s3/). | **Restic** с хоста (cron на ноде Proxmox): выгрузка содержимого `/mnt/backup` (или выбранных каталогов). Retention: 7 daily, 4 weekly, 6 monthly. |
- **Вариант A (альтернатива):** Отдельный диск/раздел на том же хосте — у тебя это sdb1.
- **Вариант B:** Сетевое хранилище (NFS/SMB) — не используется в текущей схеме.
- **Вариант C:** Внешний USB — опционально для 3-2-1 (см. ниже).
**3-2-1:** Три копии: (1) прод — система и данные на основном диске; (2) локальный бэкап — sdb1; (3) офсайт — Yandex. Два типа носителей: локальный SSD и облачное object storage. Один офсайт — да. **Стратегия удовлетворяет 3-2-1.** Опционально: четвёртая копия на внешнем USB/другом ПК для параноидального сценария (пожар/кража) — по желанию.
**Принято:** Точка монтирования — `/mnt/backup`. На диске 2 ТБ выделено 1 ТБ под бэкапы; второй ТБ пока в запас, назначение не определено.
**Действие:** Разметить 1 ТБ на /dev/sdb1, создать ФС (ext4/xfs), смонтировать в `/mnt/backup`. Структуру каталогов — см. раздел «Структура локального хранилища» ниже.
---
### Шаг 2. Добавить Backup Storage в Proxmox
1. В веб-интерфейсе: **Datacenter → Storage → Add**.
2. Тип: **Directory** (если папка на локальном диске) или **NFS/CIFS** (если сетевое).
3. Указать:
- **ID** (например `backup-local` или `backup-nfs`),
- **Directory** — путь, например `/mnt/backup/dump`,
- Включить опции **Content: VZDump backup file** (и при необходимости **ISO**, **Container template** — по желанию).
4. Сохранить. Убедиться, что storage виден и доступен для записи.
Если используешь NFS: сначала смонтировать NFS в `/mnt/backup` на хосте (fstab или systemd mount), затем добавить Storage с Directory `/mnt/backup/dump`.
**Для выбранной схемы:** Directory = `/mnt/backup/proxmox/dump` (см. структуру ниже).
---
### Структура локального хранилища (1 ТБ на sdb1)
«Аналог S3» на одном диске — это просто понятная иерархия каталогов. **MinIO не используем:** лишний сервис; достаточно директорий и restic с бэкендом `local` (если понадобится локальный restic) и `s3` для Yandex. Proxmox пишет в **Directory** — ему достаточно пути.
Пример структуры под `/mnt/backup`:
```
/mnt/backup/
├── proxmox/
│ ├── dump/ ← Proxmox Backup Job (VZDump) — сюда добавляем Storage в PVE
│ └── etc-pve/ ← архивы tar.gz из cron (backup-etc-pve.sh)
├── restic/
│ ├── local/ ← репозитории restic для локальных снапшотов (опционально)
│ └── ... ← или restic только в Yandex, локально только сырые копии
├── photos/ ← Immich: оригиналы фото + метаданные + БД (остальное пересчитать)
├── vps/ ← Amnezia: конфиг. Миран: БД бота (+ контент при необходимости; основной контент можно в S3 Мирана)
└── other/ ← прочие важные данные (конфиги, скрипты, что ещё решите)
```
Квоты: при необходимости ограничить размер по каталогам (например `proxmox/dump` — не более 500 ГБ) через отдельные подразделы или скрипты очистки (retention).
---
### Шифрование диска бэкапов (LUKS)
**LUKS** (Linux Unified Key Setup) — стандартное шифрование раздела в Linux. Если диск с бэкапами украдут или вынесут, без пароля/ключа данные не прочитать. Минусы: нужно вводить пароль при загрузке (или хранить ключ на другом носителе), небольшая нагрузка на CPU.
**Принято:** LUKS пока не используем. Раздел sdb1 — без шифрования. При необходимости можно добавить позже (потребуется перенос данных).
---
### Restic и Yandex Object Storage
- **Restic** поддерживает бэкенд **S3**. Yandex Object Storage совместим с S3 API — используешь endpoint бакета и ключи (Access Key / Secret).
- **Retention в Yandex:** 7 daily, 4 weekly, 6 monthly — `restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6` и затем `prune`.
- **Что гнать в Yandex через restic:** Proxmox dump (каталог `proxmox/dump`), `/etc/pve` (архивы из `proxmox/etc-pve`), фотки (оригиналы + метаданные + БД Immich), бэкапы с VPS — см. «Принятые решения: что куда» ниже.
**Локально отдельной политики retention для restic не нужно:** на sdb1 retention задаётся в самом Proxmox Backup Job (например «keep last 7») и в скрипте бэкапа `/etc/pve` (удалять архивы старше N дней). Restic используется только для отправки в Yandex с политикой 7/4/6. Локальных restic-репозиториев можно не заводить — только каталоги и выгрузка их содержимого в облако.
Документация Yandex: [Object Storage S3](https://yandex.cloud/ru/docs/storage/s3/). Нужны: bucket name, region, endpoint, Static Key (Access Key ID + Secret Access Key). **Бакет создан; ключи и endpoint зафиксировать при настройке restic.**
---
### Хранилище паролей (варианты)
Чтобы не терять пароли при восстановлении и держать креды в одном месте:
| Вариант | Плюсы | Минусы |
|--------|--------|--------|
| **Vaultwarden** (self-hosted, Bitwarden-совместимый) | Один сервер в твоём контуре (например CT 100 или отдельный LXC), клиенты Bitwarden на ПК/телефоне, бесплатно | Нужен HTTPS (NPM уже есть), бэкап базы Vaultwarden — в общий план бэкапов |
| **Bitwarden Cloud** (официальный облачный) | Не нужно поднимать сервер, синхронизация везде | Платно (или ограничения бесплатного), данные у третьей стороны |
| **KeePass / KeePassXC** (файл .kdbx) | Локально, один зашифрованный файл; можно положить в бэкап (restic/local) и открывать с любого ПК | Нет удобной синхронизации на телефон из коробки (нужен общий файл через Nextcloud/флешку) |
| **1Password / др. облачные менеджеры** | Удобно, кросс-девайс | Платно, данные у провайдера |
**Принято:** Развернуть **Vaultwarden** на контейнере **107 или 103** (не на 100). Домен через NPM, бэкап данных Vaultwarden включить в то, что уходит в restic → Yandex.
---
### Где запускать бэкапы (централизация)
**С хоста Proxmox (cron на ноде):**
- **Proxmox Backup Job** уже выполняется на хосте и пишет vzdump всех выбранных LXC/VM в `/mnt/backup/proxmox/dump` — это и есть «бэкапы всех контейнеров и ВМ», централизованно.
- **Restic** (backup/forget/prune) тоже запускаем с хоста по cron: бэкапит каталоги на хосте (например весь `/mnt/backup` или выбранные подкаталоги) в Yandex S3. Данные для бэкапа — локальные пути (dump, etc-pve, а фотки и данные с VPS нужно либо копировать на хост в `/mnt/backup` скриптами, либо монтировать и тогда restic будет их читать с хоста). Контейнеры и ВМ целиком не бэкапим через restic — ими занимается только Proxmox Backup Job.
---
### Шаг 3. Настроить расписание бэкапа LXC и VM
1. **Datacenter → Backup** (или **Backup** в меню узла).
2. **Add** — создаётся задача (Job).
3. Параметры:
- **Storage** — выбранное хранилище (шаг 2).
- **Schedule** — например `0 2 * * *` (каждую ночь в 02:00). Подстроить под окно, когда нагрузка минимальна.
- **Selection mode:** включить нужные узлы (или **All**), затем отметить **галочками** конкретные **LXC (100108) и VM (200)**. Либо выбрать "Backup all" для всех VMs/containers.
- **Mode:**
- **Snapshot** — контейнер/ВМ не останавливается, создаётся снимок (рекомендуется для минимизации даунтайма).
- **Suspend** — ВМ приостанавливается на время бэкапа (более консистентно для БД, но даунтайм).
Для LXC обычно достаточно **Snapshot**; для VM 200 (Immich с БД) можно оставить Snapshot, при необходимости позже добавить отдельный консистентный бэкап БД изнутри гостя.
- **Compression:** ZSTD (хороший компромисс скорость/размер).
- **Retention:** например «Keep last 7» или «Keep last 4 weekly» — чтобы не забивать диск.
4. Сохранить job. Проверить по кнопке **Backup now**, что задача запускается и файлы появляются в Storage.
Важно: бэкап должен включать **и LXC, и VM 200**. Не только данные внутри них (те уже описаны в документации контейнеров), а именно полный dump для restore.
---
### Шаг 4. Бэкап /etc/pve
Конфиги кластера и виртуалок лежат в `/etc/pve`. Их нужно копировать регулярно и хранить в безопасном месте (желательно не только на том же диске, что и система).
**Вариант A: cron на хосте Proxmox**
1. Создать скрипт, например `/root/scripts/backup-etc-pve.sh`:
```bash
#!/bin/bash
BACKUP_ROOT="/mnt/backup/proxmox/etc-pve" # по структуре выше
DATE=$(date +%Y%m%d-%H%M)
mkdir -p "$BACKUP_ROOT"
tar -czf "$BACKUP_ROOT/etc-pve-$DATE.tar.gz" -C / etc/pve
# опционально: удалять бэкапы старше N дней
# find "$BACKUP_ROOT" -name 'etc-pve-*.tar.gz' -mtime +30 -delete
```
2. Сделать исполняемым: `chmod +x /root/scripts/backup-etc-pve.sh`.
3. Добавить в cron: `crontab -e`, например раз в день после основного backup job:
`0 3 * * * /root/scripts/backup-etc-pve.sh`
**Вариант B:** Тот же скрипт можно вызывать из задачи в Proxmox (Script/Command в задаче типа Hook script), но проще и надёжнее — отдельный cron на хосте.
Бэкапы `/etc/pve` хранить **локально** (`/mnt/backup/proxmox/etc-pve`) и **в Yandex** — включить этот каталог в источники restic (мало весит, критично при потере хоста). Файлы с ограниченными правами (chmod 600); `/etc/pve` содержит секреты — не выкладывать в открытый доступ.
---
### Шаг 5. Хранить секреты отдельно (пароли, ключи)
Чтобы «не вспоминать пароли 3 часа» после восстановления:
Завести **секретное хранилище** — Vaultwarden на CT 107 или 103 (см. выше). Туда: root Proxmox, пользователи PVE, пароли БД и сервисов (Nextcloud, Gitea, Paperless, Immich, NPM, Galene и т.д.), API-ключи (Beget, certbot, Wallos и др.). Полный список кредов по контейнерам — в статьях container-100 … container-200; свести в один список в Vaultwarden и обновлять при смене паролей.
Это не «шаг бэкапа», но обязательная часть восстановления: без паролей восстановленные контейнеры не войдут в сервисы.
---
### Шаг 6. Тестовое восстановление одного контейнера
Без проверки восстановления нельзя считать стратегию рабочей.
1. Выбрать **некритичный** контейнер (например 105 — RAG, или 107 — Invidious), для которого краткий даунтайм допустим.
2. Убедиться, что есть свежий backup этого контейнера в Storage (после шага 3).
3. **Восстановление:**
- В Proxmox UI: **Datacenter → Backup** → выбрать storage → найти backup нужного CT → **Restore**. Указать **new VMID** (например 999 для теста) и **Storage** для дисков.
- Или с CLI:
`qmrestore` для VM, для LXC — через GUI или `pct restore` (см. справку `pct restore`).
Для LXC типично: Backup → Restore → задать новый ID (например 999), node, storage.
4. Запустить восстановленный контейнер (ID 999), проверить:
- заходит по SSH/консоль;
- сервисы внутри запускаются (docker/ systemd);
- с хоста пинг и при необходимости один сервис по порту.
5. После проверки удалить тестовый контейнер (999), освободить место.
Если что-то пошло не так (не находится диск, ошибка прав, сеть) — зафиксировать и поправить стратегию (пути storage, режим backup, права).
---
### Шаг 7. Документировать процедуру восстановления «с нуля»
Кратко зафиксировать в отдельном разделе (здесь или в architecture):
1. Установка Proxmox на новое железо (или новый диск).
2. Восстановление конфигов: распаковать последний `etc-pve-*.tar.gz` в `/etc/pve` (с учётом того, что нужно корректно подставить ноды и storage; при одномузловой установке обычно достаточно скопировать файлы).
3. Подключение storage с backup (или копирование последних vzdump на новый storage).
4. Восстановление контейнеров и ВМ из backup по одному (Restore с указанием VMID и storage).
5. Запуск контейнеров/ВМ, проверка сети и сервисов.
6. Использование сохранённых паролей/ключей для входа и проверки сервисов.
После первого успешного тестового восстановления (шаг 6) эту процедуру можно уточнить и дописать по факту.
---
## Чек-лист фазы 1
- [ ] Разметка: 1 ТБ на sdb1, ФС, монтирование в `/mnt/backup` (без LUKS).
- [ ] В Proxmox добавлен Storage для VZDump → `/mnt/backup/proxmox/dump`.
- [ ] Настроена регулярная задача Backup: все LXC (100108) и VM (200), расписание (например ночь), retention.
- [ ] Проверен ручной запуск Backup now — файлы появляются в storage.
- [ ] Настроен бэкап `/etc/pve` (скрипт + cron) → `/mnt/backup/proxmox/etc-pve`.
- [ ] Restic: cron на хосте, выгрузка нужных каталогов из `/mnt/backup` в Yandex S3, retention 7/4/6.
- [ ] Yandex: ключи и endpoint зафиксированы, restic успешно пишет в бакет.
- [ ] Vaultwarden развёрнут (CT 107 или 103), секреты перенесены, бэкап данных Vaultwarden входит в restic.
- [ ] Выполнено тестовое восстановление одного контейнера (другой VMID), проверена работоспособность.
- [ ] В документации зафиксирована процедура полного восстановления Proxmox «с нуля».
---
## Ссылки
- [Архитектура и подключение](../architecture/architecture.md) — хосты, IP, домены.
- [Схема сети и зависимости](../network/network-topology.md) — SPOF, зависимость от Proxmox и бэкапов.
- Документация контейнеров (100108, 200) — бэкапы *данных внутри* сервисов (БД, тома); фаза 1 дополняет это бэкапом на уровне PVE.
---
## Принятые решения (сводка)
| Вопрос | Решение |
|--------|---------|
| Точка монтирования, второй ТБ | `/mnt/backup`; второй ТБ на sdb1 — в запас, назначение позже. |
| Шифрование (LUKS) | Пока не делаем; раздел без шифрования. |
| Proxmox vzdump | Локально в `proxmox/dump` + дублировать в Yandex через restic. |
| Фотки | Оригиналы + метаданные + БД Immich; остальное пересчитать. |
| VPS | Amnezia — конфиг. Миран — БД бота + контент (контент можно в S3 Мирана; копия на sdb1 — по желанию). Конфиг серверов не бэкапим — Ansible. |
| Где запускать бэкапы | Cron на хосте Proxmox: Backup Job (vzdump) + restic в Yandex. |
| Retention локально | Только в Proxmox Job и в скрипте etc-pve; отдельного restic-репозитория локально не делаем. |
| /etc/pve | Локально и в Yandex (через restic). |
| Пароли | Vaultwarden на CT 107 или 103. |
| Yandex | Бакет создан; ключи и endpoint зафиксировать при настройке restic. |
| MinIO | Не используем; директории + restic (s3 для Yandex). |
---
## Осталось сделать
- **Yandex:** подготовить Static Key (Access Key + Secret), записать endpoint и имя бакета — понадобятся для настройки restic.

View File

@@ -0,0 +1,258 @@
# Контейнер 100 (nginx): NPM, Homepage, AdGuard, Wallos и сопутствующие сервисы
Подробное описание LXC-контейнера **100** на Proxmox (192.168.1.100): reverse proxy, DNS-фильтрация, дашборд, учёт подписок, мониторинг логов и маршрутов VPN.
---
## Общие сведения
- **Хостнейм:** nginx
- **IP:** 192.168.1.100/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 2 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 100 -- bash` или `ssh` на 192.168.1.100, если настроен.
Диск контейнера: порядка 10 GB, занято ~4.6 GB (логи и данные сервисов). Следить за местом (см. раздел «Логи и ротация» и TODO).
---
## Доступ и логины
- **Debian (CT 100):** логин `root` (или консольный пользователь Debian), пароль `waccEk-fyqbux-rarja3`.
- **AdGuard Home:** http://192.168.1.100:3000, пользователь `kerrad`, пароль `waccEk-fyqbux-rarja3`.
- **Nginx Proxy Manager:** http://192.168.1.100:81, имя `Kerrad`, email `j3tears100@gmail.com`, пароль `kqEUubVq02DJTS8`.
- **Wallos:** https://wallos.katykhin.ru (через NPM), Webлогин/пароль сохранены в менеджере паролей; Basic Auth в NPM — логин `admin`, пароль `fy8lNlWvvJryfrUVMZr8`.
- **Homepage:** https://home.katykhin.ru, логин `admin`, пароль `fy8lNlWvvJryfrUVMZr8`.
---
## Сервисы (Docker)
Все сервисы запущены в Docker. Сети: **proxy_network** (общая для NPM, Homepage, Wallos, dockerproxy, AdGuard), **adguard_proxy_network** (AdGuard дополнительно). Контейнер **vpn-route-check** в режиме `network_mode: host`.
| Контейнер | Образ | Порты (хост) | Назначение |
|-------------------|------------------------------------|-------------------|------------|
| npm | jc21/nginx-proxy-manager:latest | 80, 81, 443 | Reverse proxy, SSL, админка NPM |
| adguard | adguard/adguardhome:latest | 53/tcp+udp, 6768, 853, 3000 | DNS, DoT, веб-интерфейс, опционально DHCP |
| homepage | ghcr.io/gethomepage/homepage:latest| 4000→3000 | Дашборд сервисов (home.katykhin.ru) |
| dockerproxy | tecnativa/docker-socket-proxy | 2375 (внутри сети)| Прокси к Docker API для Homepage (только чтение) |
| wallos | bellamy/wallos:latest | 8282→80 | Учёт подписок (wallos.katykhin.ru) |
| log-dashboard | nginx:alpine | 8088→80 | Просмотр ленты обращений NPM (статика из html) |
| vpn-route-check | свой образ (build) | host | Проверка маршрутов VPN по доменам, дашборд на 8765 |
---
## 1. Nginx Proxy Manager (NPM)
**Каталог:** `/opt/docker/nginx-proxy/`
**Compose:** `docker-compose.yml` (образ `jc21/nginx-proxy-manager:latest`, restart unless-stopped).
**Порты:** 80 (HTTP), 81 (админка), 443 (HTTPS).
**Тома:**
- `./data``/data` (конфиги nginx, БД SQLite, логи, custom_ssl, proxy_host)
- `./letsencrypt``/etc/letsencrypt` (в контейнере; с хоста certbot пишет в системный `/etc/letsencrypt`, см. ниже).
**Сеть:** proxy_network.
**Основные пути на хосте:**
- `/opt/docker/nginx-proxy/data/` — данные NPM (в т.ч. `nginx/proxy_host/*.conf`, `logs/`, `custom_ssl/`, `database.sqlite`).
- `/opt/docker/nginx-proxy/data/logs/` — логи nginx: `proxy-host-*_access.log`, `proxy-host-*_error.log`, `fallback_http_access.log`, `fallback_http_error.log`, `letsencrypt.log` и др.
- `/opt/docker/nginx-proxy/letsencrypt/` — копия/симлинки сертификатов для контейнера (56 KB); основные сертификаты выпускаются certbot на хосте в `/etc/letsencrypt/live/<домен>/` и при продлении копируются в NPM (custom_ssl) через deploy-hook.
**Certbot на хосте (внутри CT 100):**
- Установлен в системе, таймер `certbot.timer` (проверка продления дважды в день).
- Учётные данные Beget API: `/root/.secrets/certbot/beget.ini`.
- Deploy-hookи: `/etc/letsencrypt/renewal-hooks/deploy/` — скрипты `copy-*-to-npm.sh` (video, docs, immich, mini-lm и т.д.) копируют `fullchain.pem` и `privkey.pem` в соответствующий каталог `custom_ssl/npm-<id>/` и делают `docker exec npm nginx -s reload`.
Подробнее по SSL: [Выпуск сертификата Let's Encrypt (DNS-01)](../network/ssl-letsencrypt-dns01.md).
**Команды:**
```bash
docker logs npm
docker exec npm nginx -s reload
```
---
## 2. AdGuard Home
**Каталог:** `/opt/docker/adguard/`
**Compose:** `docker-compose.yml` (образ `adguard/adguardhome:latest`).
**Порты:** 53 (DNS TCP/UDP), 6768 (DHCP при необходимости), 853 (DoT), 3000 (веб-интерфейс).
**Тома:** `./data/work`, `./data/conf` → соответствующие пути в контейнере.
**Сеть:** adguard_proxy_network и proxy_network (доступ с NPM по имени `adguard`).
**Конфиг:** `/opt/docker/adguard/data/conf/AdGuardHome.yaml` (upstream DNS, кэш, привязки, пользователи и т.д.). Данные и кэш: `data/work/`.
Доступ в веб: http://192.168.1.100:3000. В NPM настроен proxy на adguard (в т.ч. для adguard.local). Виджет и пароль для Homepage задаются в `services.yaml` (в контейнере).
**Команды:**
```bash
docker logs adguard
docker restart adguard
```
---
## 3. Homepage
**Каталог:** `/opt/docker/homepage/config/`
**Compose:** в `/opt/docker/homepage/docker-compose.yml` (homepage + dockerproxy).
**Порты:** 4000 (хост) → 3000 (контейнер).
**Тома:** `./config``/app/config`, `./config/images``/app/public/images`.
**Переменные:** `TZ=Europe/Moscow`, `HOMEPAGE_ALLOWED_HOSTS=home.katykhin.ru`, `DOCKER_HOST=tcp://dockerproxy:2375`.
**Сеть:** proxy_network.
**Основные файлы конфигурации:**
- `services.yaml` — список сервисов, виджеты (NPM, AdGuard, Proxmox и др.), ссылки, пинги. Пароли и токены виджетов хранятся здесь (не коммитить в открытый репозиторий).
- `docker.yaml` — подключение к Docker через dockerproxy (host/port).
- `settings.yaml`, `widgets.yaml`, `bookmarks.yaml`, `custom.css`, `proxmox.yaml`, `kubernetes.yaml` при необходимости.
Логи Homepage: `/opt/docker/homepage/config/logs/` (~588 KB).
**Команды:**
```bash
cd /opt/docker/homepage && docker compose up -d
docker logs homepage
```
---
## 4. Docker Socket Proxy (dockerproxy)
Запускается из того же compose, что и Homepage. Даёт Homepage доступ к Docker API только на чтение (CONTAINERS, SERVICES, TASKS, IMAGES, INFO, NETWORKS, VOLUMES; POST=0). Сокет хоста монтируется read-only. Отдельных конфигов нет.
---
## 5. Wallos
**Каталог:** `/opt/docker/wallos/`
**Compose:** `docker-compose.yml` (образ `bellamy/wallos:latest`).
**Порты:** 8282 (хост) → 80 (контейнер).
**Тома:** `./db``/var/www/html/db`.
**Сеть:** proxy_network. Доступ через NPM: https://wallos.katykhin.ru (с Basic Auth в NPM).
**Команды:**
```bash
docker logs wallos
docker restart wallos
```
---
## 6. Log-dashboard (лента обращений NPM)
Показывает обработанные access-логи NPM в виде ленты с фильтрацией по домену и геолокацией.
- **Контейнер:** `log-dashboard`, образ `nginx:alpine`, порт **8088** (хост) → 80.
- **Том:** `/opt/docker/log-dashboard/html``/usr/share/nginx/html` (только чтение). Контейнер отдаёт статический HTML.
- **Генерация контента:** на **хосте** (внутри CT 100) по крону каждые **15 минут** выполняется:
```bash
python3 /opt/docker/log-dashboard/gen-dashboard.py /opt/docker/log-dashboard/html/index.html
```
Скрипт читает логи из `/opt/docker/nginx-proxy/data/logs/`, парсит access-формат NPM, добавляет геолокацию (ip-api.com, кэш в `ip_cache.json`), пишет результат в `index.html`.
- **Cron:** запись в crontab root: `*/15 * * * * ... gen-dashboard.py ...`.
Доступ: http://192.168.1.100:8088 (или через NPM, если настроен proxy). Контейнер запускается отдельно (не из общего compose в каталогах выше — при перезагрузке CT нужно проверить, что он поднят).
---
## 7. VPN Route Check
**Каталог:** `/opt/docker/vpn-route-check/`
**Compose:** `docker-compose.yml` (сборка своего образа, `network_mode: host`).
Проверяет, идут ли запросы к заданным доменам через VPN или через основное подключение (подключение к роутеру по telnet, разбор маршрутов). Результаты отдаёт на порту **8765** (на хосте). В Homepage добавлена ссылка на http://192.168.1.100:8765.
**Переменные окружения в compose:** `ROUTER_TELNET_HOST`, `ROUTER_TELNET_USER`, `ROUTER_TELNET_PASSWORD` — **заданы в самом файле** (не в .env). Рекомендация: вынести в `.env` и не коммитить пароль (см. TODO).
**Том:** volume `vpn-route-check-data` → `/data` (в контейнере).
**Команды:**
```bash
cd /opt/docker/vpn-route-check && docker compose up -d
docker logs vpn-route-check
```
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|-------|----------------------------|
| 80 | NPM (HTTP) |
| 81 | NPM (админка) |
| 443 | NPM (HTTPS) |
| 53 | AdGuard (DNS TCP/UDP) |
| 6768 | AdGuard (DHCP при необходимости) |
| 853 | AdGuard (DoT) |
| 3000 | AdGuard (веб) |
| 4000 | Homepage |
| 8088 | Log-dashboard |
| 8282 | Wallos |
| 8765 | VPN Route Check (host) |
---
## Логи и ротация
- **NPM:** логи в `/opt/docker/nginx-proxy/data/logs/`.
- Для файлов **proxy-host-*_access.log** настроен logrotate: `/etc/logrotate.d/npm-access` — ротация при 100 MB, 4 копии, copytruncate, compress.
- Файлы **fallback_http_access.log**, **fallback_http_error.log** и другие **fallback_*** в правиле не указаны** — ротация по размеру/времени для них не настроена, каталог уже ~67 MB. Риск разрастания (см. TODO).
- **Certbot:** `/etc/logrotate.d/certbot` — ротация логов letsencrypt (weekly, 12 копий).
- **AdGuard:** данные и логи в `data/work/` и `data/conf/` (~85 MB). Стоит проверить настройки хранения логов запросов в веб-интерфейсе AdGuard (ограничение по времени/размеру).
- **Homepage:** небольшие логи в `config/logs/`.
---
## Запуск и порядок поднятия
1. Создать сеть (если ещё нет): `docker network create proxy_network`.
2. NPM: `cd /opt/docker/nginx-proxy && docker compose up -d`.
3. AdGuard: `cd /opt/docker/adguard && docker compose up -d` (создаёт свою сеть и подключается к proxy_network).
4. Homepage (+ dockerproxy): `cd /opt/docker/homepage && docker compose up -d`.
5. Wallos: `cd /opt/docker/wallos && docker compose up -d`.
6. VPN Route Check: `cd /opt/docker/vpn-route-check && docker compose up -d`.
7. Log-dashboard: при необходимости запустить контейнер с монтом html и портом 8088.
После изменений в NPM (proxy, SSL): перезагрузка nginx внутри контейнера — `docker exec npm nginx -s reload`. Certbot продлевает сертификаты по таймеру; deploy-hookи копируют их в NPM и перезагружают nginx.
---
## Уязвимости и риски
1. **Пароли и креды в конфигах:** В `services.yaml` (Homepage) хранятся пароли виджетов (AdGuard, NPM, Proxmox). Файл лежит только на сервере; не помещать в публичный репозиторий.
2. **VPN Route Check:** Логин и пароль роутера прописаны в `docker-compose.yml`. Доступ к compose = доступ к роутеру. Рекомендуется вынести в `.env` и ограничить права на файл.
3. **AdGuard на 3000:** Веб-интерфейс доступен по порту 3000 на хосте. Доступ из LAN; при необходимости закрыть фаерволом снаружи или использовать только через NPM (proxy).
4. **NPM на 81:** Админка NPM по порту 81. Убедиться, что с интернета доступ только через VPN или не пробрасывать 81 наружу.
5. **Логи NPM:** Часть логов (fallback_*) не ротируется — возможен рост и заполнение диска (см. TODO).
---
## TODO по контейнеру 100
- [ ] **Логи NPM:** Добавить в logrotate ротацию для `fallback_http_access.log`, `fallback_http_error.log` (и при необходимости других fallback_*) по размеру или по дням, чтобы не забивать диск.
- [ ] **Логи AdGuard:** Проверить в веб-интерфейсе AdGuard настройки хранения логов запросов (срок/размер) и при необходимости ограничить.
- [ ] **VPN Route Check:** Вынести `ROUTER_TELNET_*` в `.env`, подключать в compose через `env_file`, не коммитить .env в репозиторий.
- [ ] **Log-dashboard:** Зафиксировать способ запуска контейнера (отдельный compose или скрипт) и добавить его в документацию/автозапуск при перезагрузке CT.
- [ ] **Мониторинг диска:** Настроить оповещение (например, из Prometheus/Alertmanager или скрипт по крону) при заполнении корня или `/opt/docker` выше порога (например 80%).
- [ ] **Резервное копирование:** Регулярный бэкап критичных папок (оценка размеров на момент документации):
- `/opt/docker/nginx-proxy/data` — ~68 MB (конфиги NPM, БД, логи, custom_ssl).
- `/opt/docker/adguard/data` — ~85 MB (конфиги и данные AdGuard).
- `/opt/docker/homepage/config` — ~0.7 MB (конфиги Homepage).
- `/opt/docker/wallos/db` — ~0.2 MB (БД Wallos).
- `/opt/docker/vpn-route-check` — ~0.1 MB (скрипты и конфиг).
- `/etc/letsencrypt` — ~0.5 MB (структура сертификатов, live/archive).
- `/root/.secrets/certbot` и `/etc/letsencrypt/renewal-hooks/deploy/` — секреты и deploy-hookи.
Эти размеры небольшие сейчас, но могут расти за счёт логов и числа доменов — учитывать при выборе стратегии бэкапа.
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домены, схема сети.
- [Выпуск сертификата Let's Encrypt (DNS-01)](../network/ssl-letsencrypt-dns01.md) — certbot, Beget API, интеграция с NPM.
- [Роутер Netcraze Speedster](../network/router-netcraze-speedster.md) — VPN и telnet, используемые vpn-route-check.

View File

@@ -0,0 +1,164 @@
# Контейнер 101 (nextcloud): Nextcloud, PostgreSQL, Redis
Подробное описание LXC-контейнера **101** на Proxmox (192.168.1.101): облачное хранилище Nextcloud за NPM (https://cloud.katykhin.ru), PostgreSQL 16, Redis для кэша и блокировок, внешнее хранилище «Игры».
---
## Общие сведения
- **Хостнейм:** nextcloud
- **IP:** 192.168.1.101/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 2 core, 3 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 101 -- bash` или по SSH на 192.168.1.101, если настроен.
Диск контейнера: ~10 GB, занято ~3.8 GB. Основной объём данных — в смонтированных каталогах хоста: `/mnt/nextcloud-data/` (приложение + БД) и `/mnt/nextcloud-extra/` (внешнее хранилище «Игры», порядка нескольких TB). Следить за местом на корне и за логами (см. раздел «Логи» и TODO).
---
## Доступ и логины
- **Debian (CT 101):** логин `root` (пароль — в менеджере паролей или как настраивал при установке).
- **Nextcloud (веб):** https://cloud.katykhin.ru (через NPM). Логины пользователей — учётные записи Nextcloud (в т.ч. админ); пароли в менеджере паролей или задаются при первом входе.
---
## Сервисы (Docker Compose)
Один проект: `/opt/nextcloud/docker-compose.yml`. Сеть: **nextcloud_default** (bridge).
| Сервис | Образ | Порты (хост) | Назначение |
|-----------|--------------------|--------------|------------|
| nextcloud | nextcloud:latest | 8080→80 | Nextcloud (Apache), доступ по https://cloud.katykhin.ru через NPM |
| db | postgres:16 | — | PostgreSQL 16, БД nextcloud |
| redis | redis:7-alpine | — | Redis (кэш, блокировки), appendonly |
---
## 1. Nextcloud
**Образ:** `nextcloud:latest` (на момент проверки — Nextcloud 32.0.6).
**Порты:** 8080 (хост) → 80 (контейнер). Снаружи доступ только через NPM: https://cloud.katykhin.ru → proxy на 192.168.1.101:8080.
**Тома:**
- `/mnt/nextcloud-data/html``/var/www/html` (код, `config/`, `data/`, приложения).
- `/mnt/nextcloud-extra``/mnt/nextcloud-extra` (внутри контейнера; используется для внешнего хранилища «Игры»).
- `/opt/nextcloud/php-uploads.ini``/usr/local/etc/php/conf.d/zz-uploads.ini` (лимиты загрузки).
**Переменные окружения (compose):**
- `NEXTCLOUD_TRUSTED_DOMAINS`: cloud.katykhin.ru 192.168.1.101
- `OVERWRITEPROTOCOL`, `OVERWRITEHOST`, `OVERWRITECLIURL`: https и cloud.katykhin.ru
- `REDIS_HOST`: redis
- `POSTGRES_*`: хост db, БД nextcloud, пользователь и пароль БД (в compose заданы `nextcloud` / `nextcloud`; в `config.php` приложения может быть другой пользователь БД, заданный при установке).
**Конфиг приложения:** `/var/www/html/config/config.php` (внутри контейнера; на хосте путь — `/mnt/nextcloud-data/html/config/config.php`). В нём: trusted_domains, overwrite*, redis, datadirectory (`/var/www/html/data`), dbtype pgsql, dbhost/dbname/dbuser/dbpassword, instanceid, passwordsalt, secret и др. Редактировать при необходимости через `occ config:system:set` или правку файла с последующим перезапуском контейнера.
**PHP (загрузки):** `/opt/nextcloud/php-uploads.ini` на хосте:
- `upload_max_filesize = 64G`, `post_max_size = 64G`
- `memory_limit = 2G`, `max_execution_time = 7200`, `max_input_time = 7200`
- `upload_max_chunk_size` задаётся в config.php (67108864).
**Внешнее хранилище:** В Nextcloud настроено локальное внешнее хранилище «Игры» (Local): точка монтирования в интерфейсе — «/Игры», каталог на диске — `/mnt/nextcloud-extra/games`. Данные лежат на хосте в `/mnt/nextcloud-extra/` (в т.ч. каталог `games`); объём порядка нескольких TB.
**Команды:**
```bash
docker exec nextcloud-nextcloud-1 php /var/www/html/occ status
docker exec nextcloud-nextcloud-1 php /var/www/html/occ config:list system
docker exec nextcloud-nextcloud-1 php /var/www/html/occ files_external:list
docker logs nextcloud-nextcloud-1
docker restart nextcloud-nextcloud-1
```
Обновление приложения (если нужно): через `occ upgrade` или официальную инструкцию Nextcloud; перед этим — бэкап данных и БД.
---
## 2. PostgreSQL (db)
**Образ:** postgres:16.
**Том:** `/mnt/nextcloud-data/pgdata``/var/lib/postgresql/data`.
**Переменные:** `POSTGRES_DB=nextcloud`, `POSTGRES_USER=nextcloud`, `POSTGRES_PASSWORD=nextcloud` (в compose; приложение может подключаться под другим пользователем из config.php).
**Healthcheck:** `pg_isready -U nextcloud`.
Подключение к БД с хоста CT 101 (для администрирования):
```bash
docker exec -it nextcloud-db-1 psql -U nextcloud -d nextcloud
```
---
## 3. Redis
**Образ:** redis:7-alpine.
**Команда:** `redis-server --appendonly yes`.
**Том:** анонимный Docker volume (данные Redis в `/var/lib/docker/volumes/...` на хосте CT 101). Используется Nextcloud для memcache.distributed и memcache.locking; пароль не задан (доступ только внутри сети контейнеров).
---
## Порты
| Порт | Сервис | Примечание |
|------|----------|------------|
| 8080 | Nextcloud| HTTP внутри LAN; снаружи доступ через NPM (HTTPS cloud.katykhin.ru). |
PostgreSQL и Redis не проброшены на хост — доступ только из сети nextcloud_default.
---
## Логи и ротация
- **Nextcloud:** основной лог приложения — `/var/www/html/data/nextcloud.log` (в контейнере; на хосте — `/mnt/nextcloud-data/html/data/nextcloud.log`). На момент проверки файл уже порядка **сотен MB**. Встроенной ротации по размеру/времени в Nextcloud нет; в контейнере и на хосте **logrotate для этого файла не настроен** — риск разрастания и заполнения раздела (см. TODO).
- **PostgreSQL:** логи по умолчанию в stdout (видны через `docker logs nextcloud-db-1`). Отдельного файлового лога и logrotate не проверялось.
- **Docker:** вывод контейнеров — `docker logs`. Ротация логов Docker (json-file) зависит от настроек демона; при необходимости задать max-size/max-file в `/etc/docker/daemon.json`.
Рекомендуется добавить правило logrotate для `nextcloud.log` (по размеру или по дням) и при необходимости ограничить уровень логирования в Nextcloud.
---
## Запуск и обновление
Рабочий каталог: `/opt/nextcloud/`.
```bash
cd /opt/nextcloud
docker compose up -d
docker compose ps
docker compose logs -f nextcloud
```
Перед обновлением образов — сделать бэкап БД и каталога данных:
- БД: `docker exec nextcloud-db-1 pg_dump -U nextcloud nextcloud`
- Данные: `/mnt/nextcloud-data/html` (в т.ч. `config/`, `data/`), при необходимости `/mnt/nextcloud-extra`.
---
## Уязвимости и риски
1. **Пароли в compose:** В `docker-compose.yml` заданы `POSTGRES_PASSWORD: nextcloud` и те же учётные данные в блоке nextcloud. Файл лежит на сервере; не коммитить в публичный репозиторий. При необходимости вынести секреты в `.env`.
2. **Пароль БД в config.php:** В `config/config.php` хранится пароль подключения к PostgreSQL (и другие секреты). Права на файл должны ограничивать чтение (владелец www-data, режим 640 или строже).
3. **Nextcloud доступ по 8080:** Порт 8080 открыт на 0.0.0.0 внутри CT 101. Доступ из интернета только через NPM (HTTPS). Убедиться, что на роутере/фаерволе не пробрасывается 8080 на 192.168.1.101.
4. **Redis без пароля:** Приемлемо, так как Redis не проброшен наружу и доступен только контейнерам в одной сети. При добавлении других стеков в тот же Docker-сеть — учитывать, что Redis доступен без аутентификации.
5. **Логи:** Отсутствие ротации для `nextcloud.log` может привести к заполнению диска (см. TODO).
6. **Квота и внешнее хранилище «Игры»:** после переноса данных с SSD на HDD и смены пути внешнего хранилища (`/mnt/nextcloud-extra/games`) в БД могли остаться старые записи `storage` и кэша (oc_storages/oc_filecache) для прежнего пути. Это приводит к завышенному «Использовано» и постоянному статусу «Ожидается» у «Игры». При будущих переносах хранилища важно очищать устаревшие storages и запускать пересканирование (occ files:scan и files_external:scan), чтобы квота считалась корректно.
---
## TODO по контейнеру 101
- [ ] **Ротация nextcloud.log:** Настроить logrotate для `/mnt/nextcloud-data/html/data/nextcloud.log` (или пути на хосте CT 101): ротация по размеру (например 100200 MB) или по дням, сжатие, ограничение числа копий. Либо включить в Nextcloud логирование в syslog и ротировать его.
- [ ] **Уровень логирования:** В Nextcloud при необходимости снизить уровень лога (loglevel) в config.php или через `occ config:system:set loglevel --value 1` (1 = только ошибки), чтобы уменьшить рост лога.
- [ ] **Резервное копирование:** Регулярный бэкап:
- дамп PostgreSQL (данные в `/mnt/nextcloud-data/pgdata`, сейчас ~2.3 GB);
- каталог `/mnt/nextcloud-data/html` (код, `config/`, `data/` — сейчас ~2.3 GB);
- при необходимости внешнее хранилище `/mnt/nextcloud-extra` (в т.ч. `games` — сейчас ~5.9 TB).
Проверить, что бэкап включает конфиг и что восстановление из дампа и данных проверено.
- [ ] **Мониторинг диска:** Следить за занятостью корня контейнера и раздела, на котором лежат `/mnt/nextcloud-data` и `/mnt/nextcloud-extra`. При необходимости — алерты при достижении порога (например 85%).
- [ ] **Trusted domains:** В config.php на момент проверки указан только `cloud.katykhin.ru`. В compose задан также `192.168.1.101` — при необходимости доступа по IP добавить его в trusted_domains через `occ config:system:set trusted_domains 1 --value 192.168.1.101` (индексы по необходимости скорректировать).
- [ ] **Cron Nextcloud:** Убедиться, что фоновые задачи выполняются (режим cron или AJAX). Проверить: `docker exec nextcloud-nextcloud-1 php /var/www/html/occ background:job:list` или настройки в разделе «Основные» веб-интерфейса. При использовании cron на хосте — добавить задачу вида `*/5 * * * * docker exec nextcloud-nextcloud-1 php /var/www/html/cron.php`.
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домен cloud.katykhin.ru, NPM.
- [Контейнер 100](container-100.md) — NPM, через который открыт доступ к Nextcloud по HTTPS.

View File

@@ -0,0 +1,208 @@
# Контейнер 103 (Gitea): Gitea, PostgreSQL, act_runner, CouchDB (Obsidian)
Подробное описание LXC-контейнера **103** на Proxmox (192.168.1.103): Git-сервер Gitea с Actions (runner), база PostgreSQL, CouchDB для синхронизации Obsidian (домен obsidian.katykhin.ru).
---
## Общие сведения
- **Хостнейм:** gitea
- **IP:** 192.168.1.103/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 2 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 103 -- bash` или `ssh` на 192.168.1.103, если настроен.
Диск контейнера: 15 GB, занято ~2.6 GB. Основной объём — данные Docker (образы, тома Gitea, PostgreSQL, CouchDB). Следить за местом и логами (см. раздел «Логи и ротация» и TODO).
---
## Доступ и логины
- **Debian (CT 103):** логин `root` (пароль — в менеджере паролей или как настраивал при установке).
- **Gitea (веб):** http://192.168.1.103:3000 (или через NPM по домену git.katykhin.ru, если настроен). Учётные записи — пользователи Gitea. Репозитории могут иметь origin на Gitea; при необходимости пуш в GitHub — отдельный remote (например `github`), команда вида `git push github main`.
- **CouchDB (Obsidian sync):** http://192.168.1.103:5984. Админ (пользователь **obsidian**) и пароль заданы в `/opt/docker/couchdb/local.d/local.ini` (секция `[admins]`); клиент Obsidian подключается по URL и своим учётным данным.
---
## Сервисы (Docker)
Два независимых набора сервисов:
1. **Gitea (compose)** — в `/opt/gitea/`: Gitea, PostgreSQL, act_runner. Сеть **gitea_default**.
2. **CouchDB** — запущен отдельным контейнером (без compose в репозитории), данные в `/opt/docker/couchdb/`.
| Контейнер | Образ | Порты (хост) | Назначение |
|-----------------|--------------------------|------------------|------------|
| gitea | gitea:1.25 | 3000, 2222 | Git-сервер, веб, SSH для Git |
| gitea-db-1 | postgres:16-alpine | — | БД Gitea |
| gitea-runner-1 | gitea/act_runner:latest | — | Gitea Actions (CI) |
| couchdb | couchdb:3 | 5984 | Бэкенд синхронизации Obsidian (obsidian.katykhin.ru) |
---
## 1. Gitea (сервер)
**Каталог:** `/opt/gitea/`
**Compose:** `docker-compose.yml`. Запуск: `cd /opt/gitea && docker compose up -d`.
**Порты:** 3000 (HTTP), 2222 (SSH для git clone по SSH).
**Тома:**
- `gitea-data` (volume) → `/data` (внутри: `git/repositories`, `gitea/` — конфиг, логи, сессии, аватары, вложения, indexers, LFS, Actions logs/artifacts).
- `gitea-postgres` → данные PostgreSQL.
- `runner-data` → данные act_runner.
**Переменные окружения (compose):**
- База: `GITEA__database__*` (postgres, db:5432, user/passwd `gitea`).
- Сервер: `GITEA__server__DOMAIN`, `ROOT_URL` = 192.168.1.103:3000, `SSH_PORT` = 2222.
- Runner: `GITEA_RUNNER_REGISTRATION_TOKEN` из файла `.env` (не коммитить).
**Конфиг приложения:** внутри тома `gitea-data`, путь в контейнере `/data/gitea/conf/app.ini`. На хосте: `/var/lib/docker/volumes/gitea_gitea-data/_data/gitea/conf/app.ini`.
В нём: репозитории в `/data/git/repositories`, БД postgres (db:5432), LFS, сессии (file), логи в `/data/gitea/log`, `MODE = console` (логи в stdout → Docker). OFFLINE_MODE = true. INTERNAL_TOKEN и LFS_JWT_SECRET заданы в app.ini.
**Команды:**
```bash
cd /opt/gitea && docker compose up -d
docker logs gitea
docker exec gitea ls -la /data/gitea/conf
```
---
## 2. PostgreSQL (Gitea)
**Образ:** postgres:16-alpine.
**Том:** `gitea-postgres``/var/lib/postgresql/data`.
**Переменные:** POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB = gitea (заданы в compose).
Healthcheck: pg_isready. Зависимость: Gitea ждёт здоровой БД.
**Команды:**
```bash
docker exec gitea-db-1 pg_isready -U gitea
docker exec gitea-db-1 psql -U gitea -d gitea -c '\\dt'
```
---
## 3. Gitea act_runner (Actions)
**Образ:** gitea/act_runner:latest.
**Тома:** `runner-data``/data`; `/var/run/docker.sock` → сокет Docker (для запуска job-контейнеров).
**Переменные:** GITEA_INSTANCE_URL=http://server:3000, GITEA_RUNNER_REGISTRATION_TOKEN из `.env`, GITEA_RUNNER_NAME=gitea-103-runner, GITEA_RUNNER_LABELS=docker:docker://alpine:latest.
Регистрация runner выполняется при первом запуске по токену из Gitea (Администрирование → Actions → Runners). Токен хранится в `/opt/gitea/.env`.
**Команды:**
```bash
docker logs gitea-runner-1
docker restart gitea-runner-1
```
---
## 4. CouchDB (Obsidian sync)
**Образ:** couchdb:3.
**Порты:** 5984 (хост) → 5984 (контейнер).
**Тома (binds):**
- `/opt/docker/couchdb/data``/opt/couchdb/data`
- `/opt/docker/couchdb/local.d``/opt/couchdb/etc/local.d`
Контейнер запущен вручную (не из compose в `/opt/gitea`), политика перезапуска `unless-stopped`. После перезагрузки CT Docker поднимает контейнер автоматически.
**Конфигурация на хосте:**
- `/opt/docker/couchdb/local.d/docker.ini` — базовая секция [couchdb], uuid.
- `/opt/docker/couchdb/local.d/local.ini` — [httpd] enable_cors; [cors] origins=*, credentials, methods, headers; [admins] — пользователь (имя **obsidian**) и хэш пароля (pbkdf2). Пароль админа CouchDB хранится в этом файле; не коммитить и не светить в документации.
**Смена пароля CouchDB:** через API CouchDB (PUT /_node/_local/_config/admins/obsidian) или пересоздание контейнера с новыми переменными/конфигом. После смены — `docker restart couchdb`.
**CORS:** сейчас origins=* — приемлемо в пределах домашней сети. При выводе доступа через NPM (obsidian.katykhin.ru) можно ограничить origins до конкретного домена.
**Данные:** БД Obsidian (vault) в `/opt/docker/couchdb/data` (шарды, _dbs.couch, _nodes.couch). Размер порядка десятков MB.
**Доступ:** Снаружи — http://192.168.1.103:5984. Через NPM: obsidian.katykhin.ru → proxy на 192.168.1.103:5984 (если настроен). Клиент Obsidian Sync подключается к CouchDB по URL и своим учётным данным.
**Команды:**
```bash
docker logs couchdb
docker restart couchdb
curl -s http://192.168.1.103:5984/
```
**Рекомендация:** Оформить запуск CouchDB в отдельный `docker-compose.yml` в `/opt/docker/couchdb/` для воспроизводимости и документирования (см. TODO).
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|-------|----------------------------|
| 3000 | Gitea (веб) |
| 2222 | Gitea (SSH для git) |
| 5984 | CouchDB (Obsidian sync) |
---
## Логи и ротация
- **Gitea:** в app.ini задано `MODE = console`, `ROOT_PATH = /data/gitea/log`. Логи идут в stdout и попадают в драйвер Docker **json-file** без ограничения размера и количества файлов — со временем каталог `/var/lib/docker/containers/<id>/*.log` может разрастаться (см. TODO).
- **PostgreSQL:** логи в stdout контейнера, то же хранилище Docker.
- **act_runner:** логи в stdout.
- **CouchDB:** логи в stdout.
**Системный logrotate** в CT затрагивает только стандартные сервисы (apt, dpkg, btmp, wtmp и т.д.). Отдельных правил для Docker или Gitea нет. Ротация логов контейнеров не настроена — задаётся через `docker-compose` (logging driver options: max-size, max-file) или через `/etc/docker/daemon.json` (default).
**Риск:** при активном использовании Gitea и Actions логи контейнеров могут заполнить диск. Нужно включить ограничение размера логов Docker (см. TODO).
---
## Запуск и порядок поднятия
1. **Gitea (compose):**
`cd /opt/gitea && docker compose up -d`
Порядок: db → server (healthcheck) → runner.
2. **CouchDB:** уже запущен отдельным контейнером. Если после перезагрузки контейнер не поднялся:
```bash
docker run -d --name couchdb --restart unless-stopped \
-p 5984:5984 \
-v /opt/docker/couchdb/data:/opt/couchdb/data \
-v /opt/docker/couchdb/local.d:/opt/couchdb/etc/local.d \
couchdb:3
```
(Параметры приведены по текущему inspect; предпочтительно перейти на compose в `/opt/docker/couchdb/`.)
После смены конфига Gitea (app.ini): перезапуск контейнера — `docker restart gitea`. После смены пароля/пользователя в CouchDB local.ini — `docker restart couchdb`.
---
## Уязвимости и риски
1. **Пароли в конфигах:** В `docker-compose.yml` (Gitea) заданы пароль БД и креды Gitea (gitea/gitea). Файл лежит только на сервере; не помещать в публичный репозиторий. То же для `/opt/gitea/.env` (GITEA_RUNNER_REGISTRATION_TOKEN).
2. **Пароль админа CouchDB** хранится в `/opt/docker/couchdb/local.d/local.ini` (секция [admins]). Ограничить права на каталог (например chmod 700 local.d, владелец root).
3. **Gitea и CouchDB по IP:** Доступ по 192.168.1.103:3000 и :5984 из LAN. Если нужен доступ снаружи — только через NPM (HTTPS, домены git.katykhin.ru, obsidian.katykhin.ru) и не пробрасывать порты 3000/5984 напрямую в интернет.
4. **Логи Docker:** Ротация не настроена — возможен рост логов и заполнение диска (см. TODO).
5. **CouchDB CORS:** В конфиге включены CORS с origins = * и credentials = true. Достаточно для Obsidian; при расширении использования оценить ограничение origins.
---
## TODO по контейнеру 103
- [ ] **Логи Docker:** Включить ограничение размера логов для контейнеров: в `docker-compose.yml` (Gitea) добавить для сервисов `logging: driver: json-file options: max-size: "50m" max-file: "3"` или задать default в `/etc/docker/daemon.json` и перезапустить Docker. После этого перезапустить контейнеры.
- [ ] **CouchDB compose:** Создать `/opt/docker/couchdb/docker-compose.yml` с текущими томами и портами, перейти на `docker compose up -d` вместо ручного `docker run`, зафиксировать в документации.
- [ ] **Домены и NPM:** При необходимости настроить в NPM proxy для git.katykhin.ru → 192.168.1.103:3000 и obsidian.katykhin.ru → 192.168.1.103:5984, выпустить SSL (certbot + deploy в NPM). В Gitea при использовании домена обновить ROOT_URL и DOMAIN в compose/app.ini.
- [ ] **Мониторинг диска:** Следить за местом на корне (df -h). При желании — оповещение при заполнении выше порога (например 80%).
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/var/lib/docker/volumes/gitea_gitea-data`** — репозитории, конфиг Gitea, логи, сессии, вложения, LFS, Actions (артефакты/логи). Размер: git ~25 MB, gitea (всё остальное) ~сотни MB в зависимости от репо и логов. Бэкапить весь volume или минимум `_data/git`, `_data/gitea/conf`, `_data/gitea/sessions`, при необходимости `_data/gitea/attachments`, `_data/gitea/actions_*`.
- **`/var/lib/docker/volumes/gitea_gitea-postgres`** — БД Gitea. Размер ~71 MB. Для консистентного бэкапа — дамп через `pg_dump` (см. ниже).
- **`/var/lib/docker/volumes/gitea_runner-data`** — данные runner (~8 KB). По желанию.
- **`/opt/gitea`** — docker-compose.yml, .env (секреты). ~12 KB. Обязательно; .env не коммитить.
- **`/opt/docker/couchdb/data`** — данные CouchDB (Obsidian). ~56 MB.
- **`/opt/docker/couchdb/local.d`** — конфиги CouchDB (в т.ч. admins). ~12 KB. Обязательно; не светить в открытом доступе.
Рекомендуемый способ для PostgreSQL: `docker exec gitea-db-1 pg_dump -U gitea gitea > backup_gitea_$(date +%Y%m%d).sql` и сохранять дамп вне контейнера. Для Gitea data — копирование тома или `tar` по каталогам с остановкой записи (при возможности кратко приостановить Gitea или делать бэкап в момент минимальной активности).
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домены (в т.ч. obsidian.katykhin.ru), схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который при необходимости проксируются git.katykhin.ru и obsidian.katykhin.ru.

View File

@@ -0,0 +1,158 @@
# Контейнер 104 (Paperless): Paperless-ngx, PostgreSQL, Redis
Подробное описание LXC-контейнера **104** на Proxmox (192.168.1.104): архив документов Paperless-ngx (домен docs.katykhin.ru), PostgreSQL 18, Redis 8 для очередей задач.
---
## Общие сведения
- **Хостнейм:** paperless
- **IP:** 192.168.1.104/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 2 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 104 -- bash` или по SSH на 192.168.1.104, если настроен.
Диск контейнера: ~10 GB, занято ~3.9 GB. Основной объём данных — в каталоге **/mnt/paperless-data/** (ZFS: `tank/subvol-104-disk-0`): данные приложения, медиа (документы), БД PostgreSQL. Плюс образы и тома Docker (~2 GB). Следить за местом и логами (см. раздел «Логи и ротация» и TODO).
---
## Доступ и логины
- **Debian (CT 104):** логин `root` (пароль — в менеджере паролей или как настраивал при установке).
- **Paperless (веб):** http://192.168.1.104:8000 (или через NPM: https://docs.katykhin.ru, если настроен). Учётные записи — пользователи Paperless (создаются в веб-интерфейсе).
---
## Сервисы (Docker Compose)
Один проект: **/opt/paperless/docker-compose.yml**. Сеть: **paperless_default** (bridge).
| Контейнер | Образ | Порты (хост) | Назначение |
|--------------------------|--------------------------|--------------|------------|
| paperless-webserver-1 | paperless-ngx/paperless-ngx:latest | 8000 | Веб-интерфейс, API, OCR, фоновые задачи (Celery) |
| paperless-db-1 | postgres:18 | — | БД Paperless |
| paperless-broker-1 | redis:8 | — | Очередь задач (Celery broker) |
---
## 1. Paperless-ngx (webserver)
**Каталог:** `/opt/paperless/`
**Compose:** `docker-compose.yml`, переменные из **docker-compose.env** (не коммитить).
**Порты:** 8000 (хост) → 8000 (контейнер).
**Тома:**
- `/mnt/paperless-data/data``/usr/src/paperless/data` (конфиг, индекс, логи, celerybeat-schedule, lock-файлы).
- `/mnt/paperless-data/media``/usr/src/paperless/media` (оригиналы и производные документов: `documents/`).
- `./export``/usr/src/paperless/export` (экспорт из приложения).
- `./consume``/usr/src/paperless/consume` (каталог для автоматического импорта: сюда класть файлы для постановки в очередь).
**Переменные окружения:** из `docker-compose.env`: PAPERLESS_URL, PAPERLESS_SECRET_KEY, PAPERLESS_TIME_ZONE, PAPERLESS_OCR_LANGUAGE(S). В compose заданы: PAPERLESS_REDIS=redis://broker:6379, PAPERLESS_DBHOST=db.
**Структура данных на хосте:**
- `/mnt/paperless-data/data/``index/` (поисковый индекс), `log/` (celery.log, paperless.log; приложение может создавать rotated файлы celery.log.1, .2 и т.д.), `celerybeat-schedule.db`, `.index_version`, `migration_lock`.
- `/mnt/paperless-data/media/documents/` — подкаталоги с оригинальными и обработанными файлами документов.
**Команды:**
```bash
cd /opt/paperless && docker compose up -d
docker logs paperless-webserver-1
docker exec paperless-webserver-1 document_exporter /usr/src/paperless/export --no-input # экспорт
```
Импорт: положить файлы (PDF, изображения и т.д.) в `/opt/paperless/consume/` на хосте — Paperless подхватит их и обработает (OCR, теги, корреспонденты настраиваются в веб-интерфейсе).
---
## 2. PostgreSQL (db)
**Образ:** postgres:18.
**Том:** `/mnt/paperless-data/pgdata``/var/lib/postgresql`.
**Переменные:** POSTGRES_DB=paperless, POSTGRES_USER=paperless, POSTGRES_PASSWORD=paperless (в compose).
Зависимость: webserver зависит от db и broker.
**Команды:**
```bash
docker exec paperless-db-1 pg_isready -U paperless
docker exec paperless-db-1 psql -U paperless -d paperless -c '\dt'
```
---
## 3. Redis (broker)
**Образ:** redis:8.
**Том:** volume `redisdata``/data` (внутри контейнера). На хосте: `/var/lib/docker/volumes/paperless_redisdata/_data`.
Используется как брокер для Celery (очередь задач OCR и др.).
**Команды:**
```bash
docker exec paperless-broker-1 redis-cli ping
docker logs paperless-broker-1
```
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|------|----------------------|
| 8000 | Paperless-ngx (веб) |
---
## Логи и ротация
- **Paperless:** логи приложения в **/mnt/paperless-data/data/log/**:
- `celery.log` — фоновые задачи (OCR, индекс и т.д.); приложение может делать собственную ротацию (celery.log.1, .2, .3). На момент проверки каталог ~568 KB.
- `paperless.log` — основной лог приложения.
Для этих файлов **нет правил logrotate** на хосте — при длительной работе объём может расти (см. TODO).
- **Docker:** драйвер логов контейнеров — **json-file** без ограничения размера и количества файлов. Рост логов контейнеров (stdout/stderr) может заполнять диск.
**Системный logrotate** в CT — только стандартные правила (apt, dpkg, btmp, wtmp). Отдельных правил для Paperless или Docker нет.
**Риск:** при большом количестве документов и активной очереди Celery логи в `data/log/` и логи Docker могут разрастаться. Рекомендуется настроить ротацию (см. TODO).
---
## Запуск и порядок поднятия
1. Убедиться, что смонтирован `/mnt/paperless-data` (ZFS или иной бэкенд).
2. `cd /opt/paperless && docker compose up -d`.
Порядок: broker и db поднимаются первыми, затем webserver (depends_on).
После смены переменных в `docker-compose.env` или compose: `docker compose up -d` (пересоздание при необходимости). Обновление образа: `docker compose pull && docker compose up -d`.
---
## Уязвимости и риски
1. **Пароли в конфигах:** В `docker-compose.yml` заданы пароль БД (paperless/paperless). В `docker-compose.env` — PAPERLESS_SECRET_KEY, PAPERLESS_URL и др. Файлы лежат только на сервере; не помещать в публичный репозиторий. Ограничить права на `docker-compose.env` (например chmod 600).
2. **Доступ по порту 8000:** Веб-интерфейс доступен по 192.168.1.104:8000 из LAN. Снаружи доступ только через NPM (https://docs.katykhin.ru). Не пробрасывать 8000 в интернет.
3. **Логи:** Ротация логов Paperless (`data/log/`) и Docker не настроена — возможен рост и заполнение диска (см. TODO).
4. **Каталог consume:** Файлы в `/opt/paperless/consume/` автоматически обрабатываются и удаляются после импорта. Не класть туда единственные копии важных файлов без бэкапа.
---
## TODO по контейнеру 104
- [ ] **Логи Paperless:** Настроить logrotate для `/mnt/paperless-data/data/log/*.log`: например еженедельная ротация или по размеру (max 50100 MB), хранить 34 копии, сжатие. Создать `/etc/logrotate.d/paperless` и проверить работу.
- [ ] **Логи Docker:** Включить ограничение размера логов контейнеров: в `docker-compose.yml` добавить для сервисов `logging: driver: json-file options: max-size: "50m" max-file: "3"` или задать default в `/etc/docker/daemon.json` и перезапустить Docker, затем контейнеры.
- [ ] **Домен и NPM:** При необходимости настроить в NPM proxy для docs.katykhin.ru → 192.168.1.104:8000, выпустить SSL. В Paperless в `docker-compose.env` задать PAPERLESS_URL=https://docs.katykhin.ru (если ещё не задан).
- [ ] **Мониторинг диска:** Следить за местом на корне и на `/mnt/paperless-data` (df -h). При желании — оповещение при заполнении выше порога (например 80%).
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/mnt/paperless-data/data`** — конфиг, индекс, логи, celerybeat-schedule. ~1 MB (логи могут расти).
- **`/mnt/paperless-data/media`** — все документы (оригиналы и производные). ~178 MB (будет расти с новыми документами).
- **`/mnt/paperless-data/pgdata`** — БД PostgreSQL. ~22 MB. Для консистентного бэкапа предпочтительно дамп: `docker exec paperless-db-1 pg_dump -U paperless paperless > backup_paperless_$(date +%Y%m%d).sql`.
- **`/var/lib/docker/volumes/paperless_redisdata`** — данные Redis. ~12 KB. Восстановление не критично (очередь задач), по желанию.
- **`/opt/paperless`** — docker-compose.yml, docker-compose.env (секреты), каталоги consume/export. ~20 KB. Обязательно; docker-compose.env не коммитить.
Учитывать, что `/mnt/paperless-data` может быть отдельным ZFS-томом (tank/subvol-104-disk-0) — при бэкапе с хоста Proxmox нужно включить этот каталог или снапшот ZFS.
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домен docs.katykhin.ru, схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который проксируется docs.katykhin.ru.
- [Paperless + Ollama: поиск по документам](paperless-ollama.md) — интеграция Paperless-ngx с Ollama для вопросов по документам.

View File

@@ -0,0 +1,127 @@
# Контейнер 105 (RAG-service): RAG API (mini-lm)
Подробное описание LXC-контейнера **105** на Proxmox (192.168.1.105): сервис RAG (Retrieval-Augmented Generation) на базе sentence-transformers, API для семантического поиска и эмбеддингов. Домен: mini-lm.katykhin.ru.
---
## Общие сведения
- **Хостнейм:** rag-service
- **IP:** 192.168.1.105/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 1 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 105 -- bash` или по SSH на 192.168.1.105, если настроен.
Диск контейнера: ~10 GB, занято **~6.8 GB (74%)**. Основной объём: образ Docker (~4.1 GB), build cache (~2.4 GB, можно освободить `docker builder prune`), данные приложения в `/home/rag-service/data/` (модели ~734 MB, векторы ~2 MB). Следить за местом: при нехватке — почистить build cache и/или ограничить логи Docker (см. TODO).
---
## Доступ и логины
- **Debian (CT 105):** логин `root` (пароль — в менеджере паролей или как настраивал при установке).
- **RAG API:** http://192.168.1.105:8000 (или через NPM: https://mini-lm.katykhin.ru). Авторизация по заголовку **X-API-Key**; ключ задаётся в `.env` (RAG_API_KEY). При RAG_ALLOW_NO_AUTH=true запросы без ключа допускаются (не рекомендуется снаружи).
---
## Сервисы (Docker Compose)
Один проект: **/home/rag-service/docker-compose.yml**. Образ собирается локально из **Dockerfile** в том же каталоге. Сеть: **rag-service_default** (bridge).
| Контейнер | Образ | Порты (хост) | Назначение |
|-------------|--------------------------|--------------|------------|
| rag-service | rag-service-rag-service (build) | 8000 | FastAPI: эмбеддинги, поиск по векторам, health |
---
## 1. RAG-service (приложение)
**Каталог:** `/home/rag-service/`
**Compose:** `docker-compose.yml`, переменные из **.env** (не коммитить). Образ: `build: context: ., dockerfile: Dockerfile`.
**Порты:** 8000 (хост) → 8000 (контейнер).
**Тома:**
- `./data/models``/app/data/models` (кэш моделей sentence-transformers: all-MiniLM-L12-v2, rubert-base-cased и др.).
- `./data/vectors``/app/data/vectors` (файл векторов, например `vectors.npz`; автосохранение по RAG_AUTOSAVE_INTERVAL).
**Переменные окружения (из .env и compose):**
- Модель: RAG_MODEL (по умолчанию sentence-transformers/all-MiniLM-L12-v2), RAG_CACHE_DIR=/app/data/models.
- Векторы: RAG_VECTORS_PATH=/app/data/vectors/vectors.npz, RAG_MAX_EXAMPLES, RAG_SCORE_MULTIPLIER, RAG_BATCH_SIZE, RAG_MIN_TEXT_LENGTH.
- API: RAG_API_HOST=0.0.0.0, RAG_API_PORT=8000.
- Безопасность: **RAG_API_KEY** (обязателен для продакшена), RAG_ALLOW_NO_AUTH (по умолчанию false).
- Автосохранение: RAG_AUTOSAVE_INTERVAL (секунды).
- Логи: LOG_LEVEL (по умолчанию INFO).
**Healthcheck:** GET /api/v1/health с заголовком X-API-Key (если RAG_API_KEY задан). interval 30s, start_period 60s.
**Структура на хосте:**
- `/home/rag-service/data/models/` — подкаталоги вида `models--sentence-transformers--all-MiniLM-L12-v2`, `models--DeepPavlov--rubert-base-cased` (скачанные модели). ~734 MB.
- `/home/rag-service/data/vectors/` — vectors.npz и др. ~2 MB.
- `/home/rag-service/.env` — секреты и настройки. Обязательно бэкапить отдельно, не коммитить.
- Исходный код приложения (app/, Dockerfile, pyproject.toml и т.д.) — в том же homedir; при пересборке образа используется этот контекст.
**Команды:**
```bash
cd /home/rag-service && docker compose up -d
docker logs rag-service
docker compose build --no-cache # пересборка после изменений кода
curl -s -H "X-API-Key: <key>" http://192.168.1.105:8000/api/v1/health
```
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|------|---------------------|
| 8000 | RAG API (веб, API) |
---
## Логи и ротация
- **RAG-service:** логи приложения идут в **stdout** контейнера (LOG_LEVEL из .env) и попадают в драйвер Docker **json-file** без ограничения размера и количества файлов.
- **Системный logrotate** в CT — только стандартные правила (apt, dpkg, btmp, wtmp). Отдельных правил для RAG или Docker нет.
**Риск:** при активной работе логи контейнера могут разрастаться и вместе с образом и build cache заполнить диск (уже 74%). Рекомендуется включить ограничение логов Docker и следить за местом (см. TODO).
---
## Запуск и порядок поднятия
1. Зануться в каталог: `cd /home/rag-service`.
2. При первом запуске или после изменений кода: `docker compose build` (при необходимости `docker compose up -d --build`).
3. Запуск: `docker compose up -d`.
После смены переменных в `.env`: `docker compose up -d` (пересоздание контейнера при необходимости). После смены кода или Dockerfile: `docker compose build && docker compose up -d`.
---
## Уязвимости и риски
1. **Секреты в .env:** RAG_API_KEY и прочие переменные хранятся в `/home/rag-service/.env`. Файл не должен попадать в публичный репозиторий. Ограничить права (chmod 600) и владельца.
2. **Доступ по порту 8000:** API доступен по 192.168.1.105:8000 из LAN. Снаружи доступ только через NPM (https://mini-lm.katykhin.ru). Не пробрасывать 8000 в интернет без защиты (API key обязателен при RAG_ALLOW_NO_AUTH=false).
3. **Логи Docker:** Ротация не настроена — возможен рост логов и заполнение диска (см. TODO).
4. **Мало места на диске (74%):** Образ ~4 GB, build cache ~2.4 GB. При нехватке места: `docker builder prune` (освободит кэш сборки), при необходимости увеличить диск контейнера или перенести данные моделей на отдельный том.
5. **Ресурсы:** В compose закомментированы deploy.resources (limits/reservations). При 1 GB RAM контейнера возможны OOM при тяжёлых моделях или батчах; при необходимости увеличить память CT или выставить limits в compose.
---
## TODO по контейнеру 105
- [ ] **Логи Docker:** Включить ограничение размера логов: в `docker-compose.yml` добавить для сервиса `logging: driver: json-file options: max-size: "50m" max-file: "3"` или задать default в `/etc/docker/daemon.json`, перезапустить Docker и контейнер.
- [ ] **Мониторинг диска:** Следить за местом (df -h). Уже 74% — при достижении 85%+ выполнить `docker builder prune` и/или оценить увеличение диска. При желании — оповещение при заполнении выше порога.
- [ ] **Домен и NPM:** При необходимости настроить в NPM proxy для mini-lm.katykhin.ru → 192.168.1.105:8000, выпустить SSL. В клиентах использовать https и передавать X-API-Key.
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/home/rag-service/data/models`** — кэш моделей (sentence-transformers, rubert и др.). ~734 MB. Восстановление: при потере модели скачаются заново при первом запросе, но бэкап ускоряет восстановление.
- **`/home/rag-service/data/vectors`** — векторы (vectors.npz). ~2 MB. Важно бэкапить, если векторы содержат уникальные данные и не воссоздаются автоматически.
- **`/home/rag-service/.env`** — секреты и настройки. Обязательно; не коммитить.
- **`/home/rag-service/docker-compose.yml`**, **Dockerfile**, при необходимости весь каталог **app/** и конфиги (pyproject.toml, env.example и т.д.) — для воспроизведения сборки. Размер кода порядка мегабайт.
Образ Docker бэкапить не обязательно (собирается из Dockerfile); при восстановлении на новом хосте: скопировать данные и код, задать .env, выполнить `docker compose build && docker compose up -d`.
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домен mini-lm.katykhin.ru, схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который проксируется mini-lm.katykhin.ru.

View File

@@ -0,0 +1,183 @@
# Контейнер 107 (Invidious): Invidious, Companion, PostgreSQL
Подробное описание LXC-контейнера **107** на Proxmox (192.168.1.107): Invidious (альтернативный фронтенд YouTube), Invidious Companion и PostgreSQL 14. Домен: video.katykhin.ru.
---
## Общие сведения
- **Хостнейм:** misc
- **IP:** 192.168.1.107/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 2 GB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 107 -- bash` или по SSH на 192.168.1.107, если настроен.
Диск контейнера: 15 GB, занято ~2.1 GB (16%). Основной объём: образы и тома Docker (~0.8 GB), код Invidious в `/opt/invidious/` (~11 MB), данные PostgreSQL (~51 MB). Запас по месту большой, но при росте логов и БД всё равно стоит следить за заполнением (см. раздел «Логи и ротация» и TODO).
---
## Доступ и логины
- **Debian (CT 107):** логин `root` (пароль — в менеджере паролей или как настраивал при установке).
- **Invidious (веб):** http://192.168.1.107:3000 (или через NPM: https://video.katykhin.ru). Пользовательские аккаунты и настройки создаются в самом Invidious.
---
## Сервисы (Docker Compose)
Один проект: **/opt/invidious/docker-compose.yml** (внутри gitрепозитория Invidious: `/opt/invidious/`). Сеть: **invidious_default** (bridge).
| Контейнер | Образ | Порты (хост) | Назначение |
|--------------------------|------------------------------------------|--------------|------------|
| invidious-invidious-1 | quay.io/invidious/invidious:latest | 3000 | Веб-интерфейс Invidious, API |
| invidious-companion-1 | quay.io/invidious/invidious-companion | — (8282 внутри) | Companionсервис для запросов к YouTube |
| invidious-invidious-db-1 | postgres:14 | — | БД Invidious |
---
## 1. Invidious (основной сервис)
**Каталог:** `/opt/invidious/`
**Compose:** `docker-compose.yml` (лежит в корне репозитория).
**Порты:** 3000 (хост) → 3000 (контейнер). NPM (контейнер 100) проксирует https://video.katykhin.ru → 192.168.1.107:3000.
**Тома и конфиги:**
- Invidious не использует отдельные bindтома для конфигов/данных — данные хранятся в PostgreSQL (`invidious_postgresdata`), а конфиг задаётся через переменную `INVIDIOUS_CONFIG` в compose (inline YAML).
- Отдельных каталогов с логами Invidious на хосте нет — логи идут в stdout контейнера (см. раздел «Логи и ротация»).
**Основная конфигурация (в docker-compose.yml, секция `environment / INVIDIOUS_CONFIG`):**
- `db`: dbname=invidious, user=kemal, password=kemal, host=invidious-db, port=5432, check_tables=true.
- `invidious_companion`: URL сервиса companion (`http://companion:8282/companion`).
- `invidious_companion_key` и `SERVER_SECRET_KEY` (в companion) — общий секрет между Invidious и Companion (сейчас заданы прямо в compose; **не выкладывать в публичный репозиторий**).
- `external_port: 443`, `domain: "video.katykhin.ru"`, `https_only: true` — Invidious знает про внешний домен и порт, отдаёт ссылки на https.
- Прочие опции (feeds, captions, hmac_key, default_user_preferences и т.д.).
**Команды:**
```bash
cd /opt/invidious && docker compose up -d
docker logs invidious-invidious-1
curl -s http://127.0.0.1:3000/api/v1/stats
```
---
## 2. Invidious Companion
**Образ:** `quay.io/invidious/invidious-companion:latest`.
**Порты:** 8282 (внутри docker-сети). НСЛУШАЕТ напрямую на хосте; Invidious обращается к нему по имени `companion` в сети `invidious_default`.
**Тома:**
- volume `companioncache``/var/tmp/youtubei.js` (кэш jsресурсов YouTube / youtubei).
**Безопасность:**
- `SERVER_SECRET_KEY` совпадает с `invidious_companion_key` в конфиге Invidious — это shared secret для обмена.
- Контейнер запущен с `read_only: true`, `cap_drop: [ALL]`, `no-new-privileges:true` — хорошая практика sandboxing.
**Команды:**
```bash
docker logs invidious-companion-1
```
---
## 3. PostgreSQL (invidious-db)
**Образ:** postgres:14.
**Том:** volume `postgresdata``/var/lib/postgresql/data`. На хосте: `/var/lib/docker/volumes/invidious_postgresdata/_data` (~51 MB).
**Дополнительные mounts:**
- `/opt/invidious/config/sql``/config/sql` — SQLскрипты инициализации/миграций из репозитория Invidious (~40 KB).
- `/opt/invidious/docker/init-invidious-db.sh``/docker-entrypoint-initdb.d/init-invidious-db.sh` — скрипт инициализации БД при первом запуске.
**Переменные окружения:** POSTGRES_DB=invidious, POSTGRES_USER=kemal, POSTGRES_PASSWORD=kemal (заданы в compose; не публиковать).
**Команды:**
```bash
docker exec invidious-invidious-db-1 pg_isready -U kemal
docker exec invidious-invidious-db-1 psql -U kemal -d invidious -c '\\dt'
```
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|------|--------------------------|
| 3000 | Invidious (веб, API) |
Companion и PostgreSQL доступны только внутри docker-сети `invidious_default`.
---
## Логи и ротация
- **Invidious и Companion:** логи идут в stdout контейнеров и сохраняются драйвером Docker **json-file**. В compose для `invidious` и `companion` заданы опции:
- `max-size: "1G"`, `max-file: "4"` — максимум ~4 GB логов на контейнер. На момент проверки общий размер `/var/lib/docker` ~774 MB, запас по логам большой.
- **PostgreSQL:** контейнер `invidious-db` использует json-file **без ограничений** (`Config:{}`) — логи БД могут разрастаться (см. TODO).
**Системный logrotate** в CT — только стандартные правила (apt, dpkg, btmp, wtmp). Отдельных правил для Docker или PostgreSQL нет.
**Вывод:** для Invidious и Companion уже есть базовая защита от разрастания логов (1G×4), но для БД и общего Dockerдвижка ротация не настроена централизованно.
---
## Запуск и порядок поднятия
1. Зайти в каталог: `cd /opt/invidious`.
2. Проверить/при необходимости подредактировать `docker-compose.yml` (секция `INVIDIOUS_CONFIG`, домен video.katykhin.ru, секреты).
3. Запуск/перезапуск:
```bash
docker compose up -d
```
Порядок: сначала поднимается `invidious-db`, затем `invidious` (depends_on с healthcheck), параллельно Companion.
После изменения конфигурации (секция `INVIDIOUS_CONFIG` или окружения Companion/DB):
`cd /opt/invidious && docker compose up -d` — конфигурация применяется при перезапуске контейнеров.
---
## Уязвимости и риски
1. **Секреты и пароли в docker-compose.yml:**
В `INVIDIOUS_CONFIG` заданы:
- пароли БД (user/password kemal),
- `invidious_companion_key`,
- `hmac_key` и др. чувствительные значения.
Файл лежит только на сервере; его нельзя публиковать. Рекомендуется:
- ограничить права на `/opt/invidious/docker-compose.yml` (например chmod 600, владелец root),
- при переносе конфигурации использовать приватные репозитории или отдельные `.env`/секреты.
2. **PostgreSQL логи без лимитов:**
Контейнер `invidious-db` использует json-file без max-size/max-file — логи БД со временем могут занять существенный объём, особенно при ошибках или verboseрежиме (см. TODO).
3. **Доступ к Invidious:**
- В LAN сервис доступен по http://192.168.1.107:3000.
- Наружу следует пускать только через NPM (https://video.katykhin.ru), без прямого проброса порта 3000 на интернет.
4. **Обновления Invidious:**
В репозитории `/opt/invidious` лежит копия официального кода. Образ используется `latest` — при обновлении нужно внимательно следить за совместимостью БД и параметров, и перед апдейтом делать бэкап БД (см. TODO по бэкапам).
---
## TODO по контейнеру 107
- [ ] **Логи PostgreSQL:** Добавить ограничение логов для контейнера `invidious-invidious-db-1`:
либо через `logging` в `docker-compose.yml` (аналогично `invidious`/`companion`, но с меньшим лимитом, например `max-size: "200m"`, `max-file: "5"`), либо через глобальный `/etc/docker/daemon.json`. После изменения — перезапустить контейнер.
- [ ] **Права на конфиги:** Ограничить доступ к `docker-compose.yml` и, при необходимости, к другим файлам с секретами (chmod 600, владелец root), убедиться, что эти файлы не попадают в публичные репозитории.
- [ ] **Мониторинг диска:** Сейчас используется ~2.1 GB из 15 GB, но при росте логов/БД стоит настроить оповещение при заполнении >80% и периодически проверять `du -sh /var/lib/docker /var/lib/docker/volumes/invidious_postgresdata/_data`.
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/var/lib/docker/volumes/invidious_postgresdata/_data`** — БД Invidious (~51 MB).
Рекомендуемый способ — логический дамп:
```bash
docker exec invidious-invidious-db-1 pg_dump -U kemal invidious > backup_invidious_$(date +%Y%m%d).sql
```
и хранить дампы вне контейнера (на Proxmoxхосте/внешнем хранилище).
- **`/opt/invidious`** — код Invidious, `docker-compose.yml`, `config/sql`, `docker/init-invidious-db.sh` (~11 MB).
Важно сохранить локальные правки (особенно секцию `INVIDIOUS_CONFIG` и домен/HTTPSнастройки).
- **`/var/lib/docker/volumes/invidious_companioncache/_data`** — кэш Companion (~4 KB). Бэкап не критичен; при потере восстановится автоматически.
- [ ] **Документация по обновлению:** Зафиксировать отдельной заметкой процедуру апдейта Invidious (pull нового образа, миграции, проверка конфигов и обратимости через бэкап БД).
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домен video.katykhin.ru, схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который проксируется video.katykhin.ru.

View File

@@ -0,0 +1,136 @@
# Контейнер 108 (Galene): Galene видеоконференции
Подробное описание LXC-контейнера **108** на Proxmox (192.168.1.108): сервер видеоконференций Galene (домен call.katykhin.ru). STUN/TURN вынесены на внешний VPS (coTURN), в контейнере — только Galene как systemd-сервис, без Docker.
---
## Общие сведения
- **Хостнейм:** galene
- **IP:** 192.168.1.108/24
- **ОС:** Debian 12 (bookworm)
- **Ресурсы:** 1 core, 256 MB RAM (из [архитектуры](../architecture/architecture.md))
- **Доступ:** с Proxmox — `pct exec 108 -- bash` или по SSH на 192.168.1.108, если настроен.
Диск контейнера: ~4 GB, занято ~1.2 GB (33%). Основной объём: система, код Galene в `/opt/galene/` (~6.6 MB), данные в `/opt/galene-data/` (~1.7 MB). Логи — в systemd journal (~8 MB). Следить за местом и ротацией journal (см. раздел «Логи и ротация» и TODO).
---
## Доступ и логины
- **Debian (CT 108):** логин `root`, пароль `Galene108!`.
- **Galene (веб):** https://call.katykhin.ru (через NPM → 192.168.1.108:8443). Вход в группы — по паролям, заданным в конфигах групп в `/opt/galene-data/groups/` (операторы и участники).
---
## Сервисы (systemd, без Docker)
| Сервис | Назначение | Порт (хост) |
|------------------|--------------------------------------------------|-------------|
| galene.service | Galene Videoconference Server (galene-server) | 8443 (HTTP) |
| coturn | Не запущен (disabled) — TURN на внешнем VPS | — |
| ssh, cron, postfix@- | Стандартные сервисы CT | 22, 25 |
Galene слушает на **0.0.0.0:8443** по HTTP (`-insecure`). TLS обеспечивает NPM на контейнере 100 (https://call.katykhin.ru → proxy на 192.168.1.108:8443).
---
## 1. Galene (galene.service)
**Unit:** `/etc/systemd/system/galene.service`
**Бинарник:** `/opt/galene-server` (собран из исходников в `/opt/galene/`).
**Рабочий каталог:** `/opt/galene-data`.
**Параметры запуска:** `-http 0.0.0.0:8443 -insecure -turn "" -static /opt/galene-data/static`
- `-insecure` — HTTP без TLS (TLS на NPM).
- `-turn ""` — встроенный TURN не используется; ICE-серверы заданы в `data/ice-servers.json` (внешний coTURN на VPS).
- Статика отдаётся из `/opt/galene-data/static`.
**Структура данных на хосте:**
- **`/opt/galene-data/`** — данные и конфиги:
- **`data/`** — глобальные настройки:
- `config.json` — proxyURL (например https://call.katykhin.ru/).
- `ice-servers.json` — список STUN/TURN (URL, username, credential для TURN на VPS). **Содержит креды TURN — не публиковать.**
- `cert.pem`, `key.pem` — локальные сертификаты (для внутренних нужд; внешний HTTPS через NPM).
- **`groups/`** — конфиги групп (по одному JSON на группу): имя файла вида `<groupname>-<suffix>.json`. В каждом файле: пользователи и пароли (операторы/участники), `wildcard-user`, `max-clients`, `allow-recording`, `autolock` и т.д. **Пароли пользователей групп хранятся в этих файлах — не публиковать.**
- **`static/`** — копия/кастомизация статики из `/opt/galene/static/` (HTML, CSS, JS для веб-клиента).
- **`/opt/galene/`** — исходный код Galene (репозиторий), бинарник `galene-server` собирается отсюда. При обновлении: пересборка и перезапуск сервиса.
**Команды:**
```bash
systemctl status galene
systemctl restart galene
journalctl -u galene.service -f
curl -s -k https://192.168.1.108:8443/ # или через NPM: https://call.katykhin.ru/
```
---
## 2. coTURN (не используется в CT)
Сервис **coturn** в контейнере установлен, но **disabled и inactive**. STUN/TURN для Galene вынесены на внешний сервер (VPS Миран: 185.147.80.190, см. [VPS Миран: боты и STUN/TURN](vps-miran-bots.md)). Клиенты получают список STUN/TURN из `ice-servers.json` в `/opt/galene-data/data/`.
При необходимости поднять TURN локально — настроить coturn и указать его в `ice-servers.json` или в параметрах galene-server.
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|------|----------------------------|
| 8443 | Galene (HTTP, TLS на NPM) |
| 22 | SSH |
| 25 | Postfix (localhost) |
---
## Логи и ротация
- **Galene:** логи пишутся в **stdout/stderr** и попадают в **systemd journal** (journalctl -u galene.service). Отдельных файловых логов в `/opt/galene-data/` нет. На момент проверки журнал занимает ~8 MB.
- **Ротация journal:** управляется настройками journald (например `/etc/systemd/journald.conf`: SystemMaxUse, MaxFileSec). Отдельного правила logrotate для Galene нет — ротация только за счёт journald. При долгой работе и активном трафике журнал может расти (см. TODO).
- **Системный logrotate** в CT — стандартные правила (apt, dpkg, btmp, wtmp). Для Galene отдельного файла логов нет.
**Риск:** при большом количестве подключений и ошибок объём journal может вырасти. Рекомендуется ограничить размер журнала в journald.conf и при желании настроить выгрузку логов Galene в файл с logrotate (см. TODO).
---
## Запуск и порядок поднятия
1. Убедиться, что доступны каталоги `/opt/galene` и `/opt/galene-data` и в `data/` есть `config.json`, `ice-servers.json`.
2. Запуск сервиса: `systemctl start galene` (или при загрузке CT — `systemctl enable galene` уже выполнен, т.к. сервис активен).
3. NPM на контейнере 100 должен проксировать https://call.katykhin.ru на 192.168.1.108:8443.
После смены конфигов в `/opt/galene-data/data/` или в `groups/`: `systemctl restart galene`. После обновления кода в `/opt/galene/` — пересобрать бинарник, заменить `/opt/galene-server` и перезапустить сервис.
---
## Уязвимости и риски
1. **Пароли и креды в конфигах:** В `/opt/galene-data/data/ice-servers.json` хранится TURN credential. В каждом файле в `/opt/galene-data/groups/*.json` — пароли пользователей (операторы, участники). Эти каталоги не должны попадать в публичный репозиторий. Ограничить права (например chmod 600 на файлы с паролями), хранить бэкапы в защищённом месте.
2. **Доступ по порту 8443:** Galene слушает на всех интерфейсах (0.0.0.0:8443). Из LAN доступ по http://192.168.1.108:8443. Снаружи доступ только через NPM (https://call.katykhin.ru). Не пробрасывать 8443 в интернет напрямую.
3. **Логи в journal:** Ротация только через journald; при необходимости ограничить SystemMaxUse и проверить, что старые логи не заполняют диск (см. TODO).
4. **Мало RAM (256 MB):** Контейнер с небольшим объёмом памяти; при большом числе одновременных участников возможны проблемы. При необходимости увеличить память CT в Proxmox.
---
## TODO по контейнеру 108
- [ ] **Ротация journal:** Проверить/задать в `/etc/systemd/journald.conf` параметры `SystemMaxUse=`, `MaxFileSec=` (или аналог), чтобы журнал не разрастался бесконечно. После изменений — `systemctl restart systemd-journald` (учёт потери текущего лога при рестарте).
- [ ] **Права на конфиги:** Ограничить доступ к файлам с паролями и кредами: `chmod 600` на `ice-servers.json`, на файлы в `groups/`. Владелец root.
- [ ] **Мониторинг диска:** Следить за местом (df -h) и размером журнала. При желании — оповещение при заполнении выше порога (например 80%).
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/opt/galene-data`** — данные и конфиги: `data/` (config.json, ice-servers.json, cert.pem, key.pem), `groups/` (все JSON групп), `static/` при наличии кастомизаций. ~1.7 MB. **Обязательно;** содержит пароли и TURN credential — хранить бэкапы в защищённом месте, не публиковать.
- **`/opt/galene`** — исходный код и бинарник (или только скрипты сборки и версию). ~6.6 MB. Нужен для воспроизведения сборки galene-server; при использовании upstream репозитория можно восстанавливать из git, но локальные патчи стоит бэкапить.
- **`/etc/systemd/system/galene.service`** — unit-файл. Небольшой размер; включить в бэкап конфигов системы.
Восстановление: скопировать `/opt/galene-data` и при необходимости `/opt/galene`, установить unit, выполнить `systemctl daemon-reload && systemctl start galene`. TURN на VPS должен быть доступен и креды в `ice-servers.json` совпадать с настройками coTURN.
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров, домен call.katykhin.ru, схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который проксируется call.katykhin.ru.
- [VPS Миран (СПБ): боты и STUN/TURN](vps-miran-bots.md) — внешний coTURN для Galene (STUN/TURN сервер).

View File

@@ -0,0 +1,241 @@
# ВМ 200 (Immich): Immich, PostgreSQL, Redis, ML, deduper
Подробное описание **KVM-ВМ 200** на Proxmox (192.168.1.200): хост для Immich (фото/видео), PostgreSQL, Redis (Valkey), Immich Machine Learning (CUDA), upload-optimizer, power-tools, public-proxy и отдельный стек immich-deduper + Qdrant. Домен: immich.katykhin.ru. Данные и Docker размещены на отдельном диске `/mnt/data` (350 GB).
---
## Общие сведения
- **Тип:** KVM-виртуальная машина (управление: `qm` на Proxmox).
- **Имя ВМ:** immich
- **IP:** 192.168.1.200/24
- **ОС:** Debian 13 (trixie)
- **Ресурсы:** 3 core, 10 GB RAM, GPU (hostpci0 для VGA; ML-контейнер с NVIDIA).
- **Доступ:** SSH под пользователем **admin** (не root): `ssh admin@192.168.1.200` с хоста 192.168.1.150 или из LAN. Для выполнения команд с правами root: `sudo ...`.
**Диски:**
- **Корневой диск** (sda1): 35 GB, занято **~29 GB (87%)** — система, образы/кэш в пределах корня. **Критично:** мало свободного места; при росте логов или обновлениях возможны сбои. Следить за местом и логированием (см. TODO).
- **Данные** (sdb1): 344 GB, смонтирован в **/mnt/data**, занято ~177 GB (55%). Здесь: библиотека Immich, БД PostgreSQL, Docker root, containerd, Ollama, данные deduper.
---
## Доступ и логины
- **ВМ (Debian):** пользователь **admin** (вход по SSH-ключу или паролю; пароль задан при cloud-init, хранить в менеджере паролей). Root через `sudo`.
- **Immich (веб):** учётные записи — пользователи Immich (создаются в веб-интерфейсе). Доступ к сервисам:
| Сервис | Доступ | Адрес |
|--------------|---------------------|--------|
| Immich | Публичный (NPM) | https://immich.katykhin.ru |
| Power Tools | Публичный (Basic Auth в NPM) | https://immich-pt.katykhin.ru |
| Public Share | Публичный (NPM) | https://share.katykhin.ru |
| Deduper | Только LAN | http://192.168.1.200:8086 |
Логины и пароли Power Tools / Immich — в менеджере паролей; в открытую документацию не вносить.
---
## Сервисы (Docker Compose)
Два проекта:
1. **Immich**`/opt/immich/docker-compose.yml`. Сеть **immich_default**; дополнительно сеть **immich-deduper** (external) для доступа postgres к deduper.
2. **immich-deduper**`/opt/immich-deduper/docker-compose.yml`. Сеть **immich-deduper** (external), общая с Immich для доступа к БД.
| Контейнер | Образ / тег | Порты (хост) | Назначение |
|---------------------------|-------------------------------------------------------|------------------|------------|
| immich_upload_optimizer | miguelangel-nubla/immich-upload-optimizer:latest | 2283 | Прокси перед Immich (оптимизация загрузок); NPM смотрит сюда |
| immich_server | immich-app/immich-server:v2 | 2284→2283 | Основное приложение Immich |
| immich_postgres | immich-app/postgres:14-vectorchord... | — | PostgreSQL с расширениями (pgvector и др.) |
| immich_redis | valkey/valkey:9 | — | Кэш/очереди |
| immich_machine_learning | immich-app/immich-machine-learning:v2-cuda | — | ML (распознавание и т.д.), с GPU |
| immich_power_tools | varun-raj/immich-power-tools:latest | 8001→3000 | Дополнительные утилиты |
| immich_public_proxy | alangrainger/immich-public-proxy:latest | 8501→3000 | Публичный прокси к Immich |
| immich-deduper | razgrizhsu/immich-deduper:latest-cpu | 8086 | Поиск дубликатов |
| immich-deduper-qdrant | qdrant/qdrant:v1.16.3 | — | Векторная БД для deduper |
---
## 1. Immich (основной стек)
**Каталог:** `/opt/immich/`
**Compose:** `docker-compose.yml`, переменные из **.env** (не коммитить).
**Порты:** Внешний доступ в NPM настроен на **2283** (upload_optimizer). Дополнительно открыты: 2284 (server), 8001 (power-tools), 8501 (public-proxy).
**Пути из .env (на хосте):**
- **UPLOAD_LOCATION** — каталог загруженных файлов (фото/видео). На момент проверки: `/mnt/data/library` (~148 GB).
- **DB_DATA_LOCATION** — данные PostgreSQL. На момент проверки: `/mnt/data/postgres` (~657 MB).
**Тома (по умолчанию из .env):**
- `${UPLOAD_LOCATION}``/data` в immich_server (и в upload_optimizer через upstream).
- `${DB_DATA_LOCATION}``/var/lib/postgresql/data` в immich_postgres.
- model-cache (volume) → кэш моделей ML в immich_machine_learning.
- /etc/localtime — для времени.
**Переменные окружения (.env):** DB_PASSWORD, DB_USERNAME, DB_DATABASE_NAME, DB_HOST, DB_PORT, IMMICH_URL, IMMICH_API_KEY, EXTERNAL_IMMICH_URL, GEMINI_API_KEY (и др.). Файл содержит секреты — не публиковать, ограничить права (chmod 600).
**Команды:**
```bash
cd /opt/immich && docker compose up -d
docker logs immich_server
docker logs immich_upload_optimizer
```
---
## 2. Immich Machine Learning
Использует образ с **CUDA** и `deploy.resources.reservations.devices` (nvidia, count: 1). Кэш моделей в volume **model-cache**. Контейнер не публикует порты; общается с immich_server по внутренней сети.
---
## 3. Upload optimizer, power-tools, public-proxy
- **immich_upload_optimizer:** принимает трафик на 2283, проксирует на immich-server:2283. NPM проксирует https://immich.katykhin.ru на 192.168.1.200:2283.
- **power-tools:** веб-интерфейс на порту 8001 (внутри LAN).
- **immich_public_proxy:** порт 8501, прокси к immich-server:2283 (для публичных ссылок и т.п.).
---
## 4. PostgreSQL и Redis
- **immich_postgres:** данные в `/mnt/data/postgres`. Healthcheck включён. Подключение из deduper через сеть immich-deduper (database подключён к default и immich-deduper).
- **immich_redis:** Valkey 9, без постоянного тома в стандартной конфигурации (при перезапуске кэш сбрасывается).
---
## 5. immich-deduper
**Каталог:** `/opt/immich-deduper/`
**Compose:** `docker-compose.yml`, переменные из **.env**.
**Порты:** 8086 (хост).
**Тома (из .env):**
- **DEDUP_DATA** — каталог данных deduper (на момент проверки: `/opt/immich-deduper/data`, ~231 MB с учётом всего каталога). Внутри: кэш и данные Qdrant (`DEDUP_DATA/qdrant`).
- **IMMICH_PATH** — путь к библиотеке Immich только для чтения (`/mnt/data/library`).
- Подключение к БД Immich через переменные PSQL_* и сеть immich-deduper.
**Команды:**
```bash
cd /opt/immich-deduper && docker compose up -d
docker logs immich-deduper
```
---
## Порты (сводка на хосте)
| Порт | Сервис / примечание |
|-------|----------------------------------------|
| 2283 | Upload optimizer (основной вход для NPM) |
| 2284 | Immich server (прямой доступ) |
| 8001 | Power-tools |
| 8501 | Public proxy |
| 8086 | immich-deduper |
---
## Расширение диска данных (без даунтайма)
Диск данных ВМ (sdb1, /mnt/data) можно увеличить на Proxmox без остановки Immich. Пример: с 350 GB до 700 GB.
**1. На хосте Proxmox (192.168.1.150):** увеличить виртуальный диск:
```bash
qm resize 200 scsi1 +350G
```
**2. Внутри ВМ (ssh admin@192.168.1.200):** расширить раздел:
```bash
sudo growpart /dev/sdb 1
```
**3. Внутри ВМ:** расширить файловую систему (онлайн, без размонтирования):
```bash
sudo resize2fs /dev/sdb1
```
Операция занимает порядка 30 секунд; перезагрузка не требуется.
---
## Включение Machine Learning и Smart Search
После загрузки фото можно включить ML (распознавание, смарт-поиск). Предусловия: GPU passthrough в ВМ настроен и работает (`nvidia-smi` внутри ВМ), в compose для `immich-machine-learning` заданы `runtime: nvidia` и `deploy.resources.reservations.devices` (nvidia).
1. **Включить ML через API** (подставить свой API-ключ из .env или из веб-интерфейса Immich → Administration → API Keys):
```bash
curl -s "http://192.168.1.200:2284/api/system-config" -H "x-api-key: YOUR_API_KEY" | \
python3 -c "import sys,json; c=json.load(sys.stdin); c['machineLearning']['enabled']=True; print(json.dumps(c))" | \
curl -s -X PUT "http://192.168.1.200:2284/api/system-config" -H "x-api-key: YOUR_API_KEY" -H "Content-Type: application/json" -d @-
```
2. **Сменить CLIP-модель** для поиска на русском: Immich UI → Administration → Settings → Machine Learning → Smart Search → Model Name: `nllb-clip-large-siglip__mrl` → Save.
3. **Язык пользователя:** в настройках пользователя Immich выставить русский (NLLB-модель ожидает запросы на языке из настроек).
4. **Запустить переиндексацию:** Administration → Jobs → Smart Search → нажать «All». На большом объёме фото (порядка десятков тысяч) на GPU займёт 2030 минут.
5. **По желанию снизить RAM ВМ** до 8 GB после индексации (на хосте Proxmox): `qm set 200 --memory 8192 --cores 3`.
---
## Логи и ротация
- **Docker:** данные Docker (образы, контейнеры, overlay) хранятся в **/mnt/data/docker** (Docker Root Dir). Логи контейнеров — драйвер **json-file** без ограничения размера и количества файлов (Config:{} у immich_server и immich_postgres). При активной работе логи могут разрастаться и занимать место на **корневом** разделе (если логи пишутся на корень) или в overlay на /mnt/data — уточнить расположение логов контейнеров (часто в /mnt/data/docker/containers). В любом случае ограничение логов не задано (см. TODO).
- **Системный logrotate:** стандартные правила (apt, dpkg, cloud-init, unattended-upgrades, wtmp). Отдельных правил для Immich или Docker нет.
**Риск:** корневой диск заполнен на 87%. Рост логов, обновления и кэш могут привести к нехватке места. Необходимо ограничить логи Docker и следить за местом на корне (см. TODO).
---
## Запуск и порядок поднятия
1. Создать внешнюю сеть (если ещё нет):
`docker network create immich-deduper`
2. Immich:
`cd /opt/immich && docker compose up -d`
Порядок: database, redis → immich-server (и ML, upload_optimizer, power_tools, public_proxy).
3. Deduper:
`cd /opt/immich-deduper && docker compose up -d`
После смены .env или compose: перезапуск соответствующих стеков. Обновление образов: `docker compose pull && docker compose up -d` (для Immich при обновлении проверять совместимость БД и миграции).
---
## Уязвимости и риски
1. **Секреты в .env:** В `/opt/immich/.env` и `/opt/immich-deduper/.env` хранятся пароли БД, API-ключи (IMMICH_API_KEY, GEMINI_API_KEY), креды для deduper (PSQL_*). Файлы не должны попадать в публичный репозиторий. Ограничить права (chmod 600), хранить бэкапы в защищённом месте.
2. **Корневой диск 87%:** Критично мало свободного места. При 100% возможны сбои обновлений и работы сервисов. Срочно: освободить место и/или перенести часть данных на /mnt/data, ограничить логи Docker (см. TODO).
3. **Логи Docker без лимитов:** Ротация не настроена — возможен рост логов и заполнение диска.
4. **Доступ по портам:** Сервисы доступны по 2283, 2284, 8001, 8501, 8086 из LAN. Снаружи доступ только через NPM (https://immich.katykhin.ru → 2283). Не пробрасывать порты напрямую в интернет.
5. **GPU и PCI-passthrough:** ВМ использует hostpci0 (VGA). Убедиться, что драйверы NVIDIA и доступ к GPU корректны для immich_machine_learning.
---
## TODO по ВМ 200
- [ ] **Корневой диск:** Снизить использование корня (87%). Варианты: перенести логи Docker на /mnt/data (если сейчас пишутся на корень), очистить старые образы/кэш (`docker system prune` с осторожностью), увеличить размер корневого диска ВМ в Proxmox. Настроить мониторинг и оповещение при заполнении >90%.
- [ ] **Логи Docker:** Включить ограничение размера логов для всех контейнеров Immich и deduper: в `docker-compose.yml` добавить для каждого сервиса `logging: driver: json-file options: max-size: "100m" max-file: "3"` или задать default в `/etc/docker/daemon.json`. Убедиться, что Docker Root Dir остаётся на /mnt/data и логи не пишутся на корень. После изменений перезапустить контейнеры.
- [ ] **Права на конфиги:** Ограничить доступ к .env (chmod 600), не коммитить в публичные репозитории.
- [ ] **Резервное копирование:** Регулярный бэкап критичных данных (оценка размеров на момент документации):
- **`/mnt/data/library`** — библиотека Immich (фото, видео, превью). ~148 GB. Основной объём; бэкап обязателен (внешний диск, сетевое хранилище).
- **`/mnt/data/postgres`** — данные PostgreSQL Immich. ~657 MB. Для консистентного бэкапа предпочтительно дамп:
`docker exec immich_postgres pg_dump -U <DB_USERNAME> <DB_DATABASE_NAME> > backup_immich_$(date +%Y%m%d).sql` (подставить из .env). Хранить дампы вне ВМ.
- **`/opt/immich`** — docker-compose.yml, .env (секреты), hwaccel.ml.yml. ~20 KB. Обязательно; .env не коммитить.
- **`/opt/immich-deduper`** — docker-compose.yml, .env, каталог data (данные и кэш Qdrant). ~231 MB. Восстановление deduper возможно заново, но данные индексов — в data.
- **`/mnt/data/docker`** — образы и метаданные контейнеров (~16 GB). При восстановлении ВМ образы можно заново скачать; при необходимости бэкапить только метаданные томов или полный каталог.
- **`/mnt/data/ollama`** — данные Ollama (~4.1 GB). Бэкапить при использовании Ollama на этой ВМ.
Учитывать, что /mnt/data смонтирован с отдельного диска (tank или аналог в Proxmox); при бэкапе с хоста включить этот диск или снапшоты.
- [ ] **Документация по обновлению Immich:** Зафиксировать процедуру обновления (версия в IMMICH_VERSION, backup БД, docker compose pull, миграции, откат при сбое).
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — таблица контейнеров и ВМ, домен immich.katykhin.ru, схема сети.
- [Контейнер 100 (nginx)](container-100.md) — NPM, через который проксируется immich.katykhin.ru.
- [Paperless + Ollama: поиск по документам](paperless-ollama.md) — использование Ollama (обычно на этой ВМ) для ответов по документам из Paperless.

View File

@@ -0,0 +1,82 @@
# Paperless + Ollama: поиск по документам Paperless-ngx
Скрипт **paperless-ollama-ask.py** позволяет задавать вопросы по документам из Paperless-ngx (контейнер 104) и получать ответы от модели Ollama (обычно на ВМ 200). Работает так: ищет документы по тексту (OCR), собирает выдержки и подставляет их в промпт для локальной LLM.
---
## Требования
- Python 3.9+
- Запущенный **Paperless-ngx** (см. `container-104.md`) с доступным API
- Запущенный **Ollama** (обычно на ВМ 200, см. `container-200.md`)
Скрипт хранится в репозитории в `homelab/paperless-ollama-ask.py`, документация — в этом файле.
---
## Переменные окружения
| Переменная | Обязательная | По умолчанию | Пример |
|----------------------|--------------|------------------------|----------------------------------|
| `PAPERLESS_URL` | да | — | `http://192.168.1.104:8000` |
| `PAPERLESS_TOKEN` | да | — | токен API из Paperless |
| `OLLAMA_URL` | нет | `http://localhost:11434` | `http://192.168.1.200:11434` |
| `OLLAMA_MODEL` | нет | `saiga` | имя модели в Ollama |
| `PAPERLESS_MAX_DOCS` | нет | `5` | максимум документов в промпте |
**PAPERLESS_TOKEN:** берётся в веб-интерфейсе Paperless: профиль пользователя → токен API (см. документацию Paperless-ngx).
---
## Как это работает
1. Скрипт выполняет поиск в Paperless по строке запроса (full-text по OCR).
2. Берёт до `PAPERLESS_MAX_DOCS` подходящих документов.
3. Собирает выдержки/полный текст и формирует промпт для модели Ollama.
4. Отправляет промпт на `OLLAMA_URL` и выводит ответ в stdout.
---
## Примеры запуска
```bash
cd homelab
export PAPERLESS_URL="http://192.168.1.104:8000" # контейнер 104
export PAPERLESS_TOKEN="твой_токен_из_Paperless"
# Если Ollama на ВМ 200:
export OLLAMA_URL="http://192.168.1.200:11434"
# Вопросы по документам
python3 paperless-ollama-ask.py "номер паспорта?"
python3 paperless-ollama-ask.py "когда истекает договор?"
```
---
## Где запускать
- **На ВМ с Ollama (обычно ВМ 200):**
- `OLLAMA_URL=http://localhost:11434`
- `PAPERLESS_URL` — адрес контейнера 104 (`http://192.168.1.104:8000` или домен, который проксирует NPM).
- **На другой машине (например, твой ноут):**
- `PAPERLESS_URL` и `OLLAMA_URL` указывают на IP/домены Paperless и Ollama.
- Учесть доступность портов и фаервол.
---
## Безопасность и ограничение доступа
- **Токен Paperless** даёт доступ к документам — хранить его только в приватных местах (env, .env вне репозитория).
- **Ollama** обычно слушает на 11434; при пробросе наружу стоит ограничить доступ (файрвол, VPN).
- Запросы и выдержки из документов уходят в локальную модель; при использовании удалённых/облачных моделей учитывать конфиденциальность.
---
## Связь с другими документами
- [Контейнер 104 (Paperless)](container-104.md) — где крутится Paperless-ngx и какие порты/тома используются.
- [ВМ 200 (Immich)](container-200.md) — может одновременно работать как хост для Ollama (порт 11434).

View File

@@ -0,0 +1,233 @@
# Схема сети и зависимости инфраструктуры
Полная топология: домашняя сеть, Proxmox, контейнеры/ВМ, внешние VPS, маршруты и зависимости. Помогает видеть единые точки отказа (single point of failure).
---
## Граф зависимостей (dependency graph)
Цепочка обслуживания **любого** публичного запроса к доменам katykhin.ru:
```mermaid
flowchart TB
subgraph External["Внешний мир"]
DNS["DNS (Beget)\n*.katykhin.ru → IP"]
end
subgraph Edge["Граница сети"]
Router["Роутер\n192.168.1.1\nпроброс 80/443 → .100"]
end
subgraph Gateway["Единая точка входа"]
NPM["NPM\nCT 100\nтерминация SSL, маршрут по Host"]
end
subgraph Backends["Сервисы"]
S101["Nextcloud\nCT 101"]
S103["Gitea / CouchDB\nCT 103"]
S104["Paperless\nCT 104"]
S105["RAG API\nCT 105"]
S107["Invidious\nCT 107"]
S108["Galene\nCT 108"]
S200["Immich\nVM 200"]
end
subgraph Data["Данные"]
D101["PostgreSQL\nRedis\nCT 101"]
D103["PostgreSQL\nCT 103"]
D104["PostgreSQL\nRedis\nCT 104"]
D107["PostgreSQL\nCT 107"]
D200["PostgreSQL\nRedis\nVM 200"]
end
subgraph External2["Внешние зависимости"]
coTURN["coTURN\nVPS Миран 185.147.80.190"]
end
DNS --> Router
Router --> NPM
NPM --> S101
NPM --> S103
NPM --> S104
NPM --> S105
NPM --> S107
NPM --> S108
NPM --> S200
S101 --> D101
S103 --> D103
S104 --> D104
S107 --> D107
S200 --> D200
S108 -.-> coTURN
```
**Каноническая цепочка для одного запроса:**
```
DNS → Router → NPM → Service → Database
```
- **DNS** — без правильных записей запрос не дойдёт до твоего IP.
- **Router** — без проброса 80/443 трафик не попадёт в LAN на NPM.
- **NPM** — без него нет HTTPS и нет маршрутизации по домену на нужный бэкенд (узкое место: все сервисы проходят через один узел).
- **Service** — приложение (Nextcloud, Invidious, Immich и т.д.).
- **Database** — отказ БД/Redis ломает только свой сервис, не остальные.
**Узкие места, которые видно из графа:**
| Узел | Почему узкое место |
|------|--------------------|
| **NPM** | Один контейнер на все домены: отказ или перегрузка NPM роняет весь публичный доступ ко всем сервисам. |
| **Router** | Один прибор на вход в сеть: отказ = нет доступа извне. |
| **DNS** | Один регистратор/API: смена IP или ошибка в записях — домены перестают вести к тебе. |
| **Сервис/БД** | Ломается только один бэкенд; остальные цепочки независимы. |
Исключения из цепочки:
- **Galene (108)** дополнительно зависит от **coTURN (VPS Миран)** для STUN/TURN — на графе это отдельная зависимость от внешнего узла.
- **RAG (105)** без внешней БД в стеке — только NPM → Service.
- **AdGuard, Homepage, Wallos** живут на том же хосте, что и NPM (CT 100), но логически стоят «рядом» с NPM (доступ к ним тоже через роутер и при необходимости через NPM).
---
## Схема сети (упрощённо)
```
Интернет (пользователи)
┌───────────────────────────────┐
│ Роутер 192.168.1.1 │ Внешний IP: 185.35.193.144
│ Netcraze Speedster │ Проброс 80/443 → .100
│ VPN: AmneziaWG DE / US │
└───────────────┬───────────────┘
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌────────────────┐ ┌─────────────────┐
│ Proxmox │ │ CT 100 │ │ Остальные CT/VM │
│ 192.168.1.150│ │ 192.168.1.100 │ │ .101 .103 .104 │
│ (гипервизор) │ │ NPM, AdGuard, │ │ .105 .107 .108 │
│ │ │ Homepage, │ │ VM 200 .200 │
│ pct / qm │ │ Wallos, etc. │ │ (бэкенды) │
└──────────────┘ └───────┬────────┘ └────────┬────────┘
│ │ │
│ │ HTTPS по Host │
│ └──────────────────────┘
│ (NPM проксирует на бэкенды)
│ Туннели VPN (роутер ↔ VPS)
├──────────────────────────────────────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────┐
│ VPS DE │ │ VPS US │ │ VPS Миран (СПБ) │
│ 185.103.253.99 │ │ 147.45.124.117 │ │ 185.147.80.190 │
│ AmneziaWG │ │ AmneziaWG │ │ coTURN (Galene), │
│ (обход блок.) │ │ (обход блок.) │ │ боты, Prometheus │
└──────────────────┘ └──────────────────┘ └──────────────────────┘
```
**Поток публичного трафика:**
Запрос из интернета (например `https://video.katykhin.ru`) → роутер (185.35.193.144:443) → проброс на 192.168.1.100:443 → NPM (контейнер 100) → по Host выбирается proxy host → запрос на бэкенд (например 192.168.1.107:3000 для Invidious). Ответ идёт обратно по той же цепочке.
---
## Узлы, IP и домены (сводная таблица)
| Узел | IP / адрес | Роль | Домены / примечание |
|------|------------|------|----------------------|
| **Роутер** | 192.168.1.1 | Шлюз LAN, проброс 80/443, VPN-клиент (AmneziaWG) | Внешний IP: 185.35.193.144 |
| **Proxmox** | 192.168.1.150 | Гипервизор (LXC + KVM) | Управление: `pct`, `qm` |
| **CT 100** | 192.168.1.100 | NPM, Homepage, AdGuard, Wallos, log-dashboard, vpn-route-check | home.katykhin.ru, wallos.katykhin.ru, adguard.local; приём 80/443 |
| **CT 101** | 192.168.1.101 | Nextcloud, PostgreSQL, Redis | cloud.katykhin.ru |
| **CT 103** | 192.168.1.103 | Gitea, PostgreSQL, act_runner, CouchDB (Obsidian) | git.katykhin.ru, obsidian.katykhin.ru |
| **CT 104** | 192.168.1.104 | Paperless-ngx, PostgreSQL, Redis | docs.katykhin.ru |
| **CT 105** | 192.168.1.105 | RAG API (mini-lm) | mini-lm.katykhin.ru |
| **CT 107** | 192.168.1.107 | Invidious, Companion, PostgreSQL | video.katykhin.ru |
| **CT 108** | 192.168.1.108 | Galene (видеозвонки) | call.katykhin.ru |
| **VM 200** | 192.168.1.200 | Immich, PostgreSQL, Redis, ML, deduper, Power Tools, Public Share | immich.katykhin.ru, immich-pt.katykhin.ru, share.katykhin.ru |
| **VPS DE** | 185.103.253.99 | AmneziaWG (обход блокировок) | Туннель с роутера (10.8.1.x) |
| **VPS US** | 147.45.124.117 | AmneziaWG (второй выход) | Туннель с роутера |
| **VPS Миран** | 185.147.80.190 | coTURN (STUN/TURN для Galene), боты, prod | call.katykhin.ru использует STUN/TURN |
| **DNS** | Beget.com | Домен katykhin.ru, поддомены, API для DNS-01 | Все *.katykhin.ru |
---
## Маршруты NPM (домен → бэкенд)
Все публичные HTTPS-запросы к доменам katykhin.ru приходят на **192.168.1.100** (NPM). NPM по заголовку Host направляет трафик на соответствующий бэкенд:
| Домен | Upstream (хост:порт) | Контейнер/ВМ |
|-------|----------------------|---------------|
| home.katykhin.ru | Homepage (внутри 100) | CT 100 |
| wallos.katykhin.ru | wallos:80 | CT 100 |
| adguard.local | adguard:3000 | CT 100 |
| cloud.katykhin.ru | 192.168.1.101:8080 | CT 101 |
| docs.katykhin.ru | 192.168.1.104:8000 | CT 104 |
| video.katykhin.ru | 192.168.1.107:3000 | CT 107 |
| call.katykhin.ru | 192.168.1.108:8443 | CT 108 |
| immich.katykhin.ru | 192.168.1.200:2283 | VM 200 |
| immich-pt.katykhin.ru | 192.168.1.200:8001 | VM 200 |
| share.katykhin.ru | 192.168.1.200:8501 | VM 200 |
| mini-lm.katykhin.ru | 192.168.1.105:8000 | CT 105 |
| git.katykhin.ru | 192.168.1.103:3000 | CT 103 |
| obsidian.katykhin.ru | 192.168.1.103:5984 | CT 103 |
(Точный список proxy host — в NPM на CT 100; при добавлении доменов таблицу обновлять.)
---
## Зависимости (кто от кого зависит)
### Публичный доступ из интернета
- **Все публичные HTTPS-сервисы** зависят от:
1. **Роутер** — без него нет входа 80/443 на LAN.
2. **Контейнер 100 (NPM)** — без NPM нет терминации SSL и маршрутизации по Host.
3. **Certbot + Beget DNS** — без них нет валидных сертификатов (либо только HTTP или самоподписные).
4. **DNS (Beget)** — без записей *.katykhin.ru запросы не дойдут до твоего IP.
- **Каждый бэкенд** (101, 103, 104, 105, 107, 108, 200) при доступе снаружи зависит от NPM и роутера; при доступе только из LAN может работать и без NPM (по IP и порту).
### Внутри хостов
- **NPM (100):** зависит от certbot (файлы сертификатов) и от конфигурации proxy_host (куда слать трафик). Не зависит от других контейнеров для старта.
- **Homepage (100):** зависит от NPM (ссылки), AdGuard (виджет), dockerproxy (виджеты Docker). Работает и без них, но без данных.
- **AdGuard (100):** самостоятельный; NPM может проксировать к нему по имени.
- **Wallos (100):** самостоятельный; NPM проксирует.
- **Контейнеры 101, 103, 104, 107, 200:** каждый свой стек: приложение зависит от своей БД (PostgreSQL) и при необходимости от Redis. Порядок запуска: сначала БД/Redis, потом приложение (обычно задано в docker-compose через depends_on).
- **Контейнер 105 (RAG):** один контейнер, без внешней БД в стеке.
- **Контейнер 108 (Galene):** не зависит от других контейнеров в LAN; зависит от **внешнего coTURN** (VPS Миран 185.147.80.190) для STUN/TURN — без него видеозвонки могут не устанавливаться за строгим NAT/фаерволом.
- **Immich (200):** зависит от PostgreSQL, Redis, при необходимости от immich-deduper (сеть и БД). ML-контейнер опционально (GPU).
### Внешние сервисы
- **Роутер → VPN:** зависит от VPS (185.103.253.99 или 147.45.124.117) и от AmneziaWG на них. При падении VPS соответствующий туннель недоступен.
- **Galene → coTURN:** зависит от VPS Миран (185.147.80.190). При падении coTURN видеозвонки могут не работать в части сценариев.
---
## Единые точки отказа (SPOF)
| Точка | Что ломается при отказе | Как смягчить |
|-------|-------------------------|--------------|
| **Роутер** | Весь доступ из интернета к домашней сети (в т.ч. все домены). Нет VPN-выхода, если туннели подняты на роутере. | Резервный роутер / запасной канал; доступ к управлению из LAN. |
| **Proxmox (192.168.1.150)** | Все контейнеры и ВМ недоступны (они на нём запущены). | Резервное питание, мониторинг, бэкапы конфигов и данных. |
| **Контейнер 100 (NPM)** | Публичный HTTPS ко всем сервисам: без NPM нет терминации SSL и маршрутизации. Сервисы по IP:порт из LAN могут быть доступны, если порты не закрыты. | Мониторинг NPM и Docker на 100; быстрый перезапуск; бэкап конфигов NPM. |
| **Certbot / Beget API** | Истечение сертификатов → браузеры начнут ругаться. Продление через DNS-01 зависит от Beget. | Следить за продлением (таймер certbot); иметь запасной способ выпуска (другой DNS или ручной сертификат). |
| **DNS (Beget)** | Смена IP или потеря записей — домены перестанут вести на твой хост. | Ведение записей вручную/через API; при смене IP обновить A-записи. |
| **VPS Миран (coTURN)** | Galene: проблемы с установкой видеозвонов за NAT. Остальные сервисы не зависят. | Локальный coTURN на 108 или другом хосте как запасной вариант. |
| **Конкретный бэкенд (101, 103, …)** | Падает только свой сервис (Nextcloud, Gitea, Invidious и т.д.). Остальные работают. | Зависимости внутри стека (БД первым) и мониторинг каждого хоста. |
---
## Связь с другими документами
- [Архитектура и подключение](../architecture/architecture.md) — общее описание, таблица контейнеров, поток запросов.
- [Контейнер 100](../containers/container-100.md) — NPM, AdGuard, Homepage, порядок запуска.
- [Роутер Netcraze Speedster](router-netcraze-speedster.md) — проброс портов, VPN.
- [VPN-сервер (VPS, AmneziaWG)](../vps/vpn-vps-amneziawg.md) — туннели с роутера.
- [VPS Миран: боты и STUN/TURN](../vps/vps-miran-bots.md) — coTURN для Galene.

View File

@@ -0,0 +1,102 @@
# Роутер Netcraze Speedster
Домашний маршрутизатор с веб-админкой и поддержкой WireGuard/AmneziaWG. Используется для выхода в интернет и выборочной маршрутизации части трафика через VPN (два профиля: Германия и США).
---
## Доступ и логины
- **Веб-интерфейс:** http://192.168.1.1 — логин `admin`, пароль `eC1cLwZPRoDVEY1`.
- **Веб-CLI (ограниченный):** http://192.168.1.1/a — отправка отдельных команд из браузера.
- **Полноценный CLI:** по **telnet** на 192.168.1.1, порт **2048** (стандартный 23 изменён). Пароль администратора тот же: `eC1cLwZPRoDVEY1`. SSH в настройках включался, но **не работает** — используется telnet.
Подключение по telnet с компьютера в домашней сети:
```bash
telnet 192.168.1.1 2048
```
После ввода пароля администратора доступна CLI с автодополнением по Tab (команды и параметры текущего уровня).
---
## VPN (WireGuard / AmneziaWG)
Настройка выполнялась по инструкции для Keenetic с AmneziaWG: [Installing VPN on a Keenetic Router](https://docs.amnezia.org/documentation/instructions/keenetic-os-awg/) (импорт .conf из AmneziaVPN, при необходимости ручная установка asc-параметров обфускации в CLI).
**Два подключения WireGuard:**
| Подключение | Пир (сервер) | Назначение | Статус в скринах |
|--------------------|------------------------|----------------|-------------------|
| netcraze_amnezia | 185.103.253.99:33118 | Германия (AWG) | Включено |
| router_us | 147.45.124.117:37135 | США (AWG) | Выключено |
- Внутренний адрес клиента для **netcraze_amnezia:** 10.8.1.2/32 (порт 42472).
- Для **router_us:** 10.8.1.2/32 (порт 43116).
Переключение: в разделе **Интернет → Другие подключения** включается или выключается нужное WireGuard-подключение. В **Приоритеты подключений** оба профиля работают в режиме резервирования.
---
## Приоритеты подключений
**Интернет → Приоритеты подключений:**
- **Политика по умолчанию** — основное подключение (Ethernet / PPPoE).
- **netcraze_amnezia** — режим резервирования, WireGuard (Германия).
- **us** — режим резервирования, WireGuard (router_us, США).
Нужная политика выбирается для устройств/сегментов на вкладке **Применение политик**. Для выхода части трафика через VPN можно создать отдельную политику с одним VPN-подключением и назначить её нужным устройствам или сегментам (например, гостевой WiFi).
---
## Маршрутизация
**Сетевые правила → Маршрутизация → IPv4-маршруты:**
- Пользовательские маршруты с приоритетом над динамическими.
- **Шлюз** в таблице: 10.8.1.2 (внутренний адрес VPN-клиента на роутере).
- **Интерфейсы:** `netcraze_amnezia` и `router_us` — трафик к указанным сетям назначения уходит через соответствующий VPN.
- Записей много (порядка 2000+); для части сетей включено **«Добавлять автоматически»**. Списки конкретных IP/сетей в документацию не выносятся — при необходимости экспорт/импорт через кнопки в веб-интерфейсе.
---
## DNS
**Сетевые правила → Интернет-фильтры → Настройка DNS:**
- **Системный профиль:** DNS провайдера (подключение Ethernet), например 178.155.7.18, 217.66.16.35; разрешён транзит запросов.
- **DoT-серверы:** 1.1.1.1 (Cloudflare) и 8.8.8.8 (Google), интерфейс «Любой».
При необходимости игнорирование DNS провайдера включается в **Интернет → Кабель Ethernet → Порты и VLANы**.
---
## Основные команды CLI (telnet)
После входа в CLI доступны стандартные команды Keenetic-подобной оболочки. Автодополнение: **Tab** в приглашении выводит список доступных команд на текущем уровне.
**Полезные команды:**
- `show interface` — список интерфейсов (в т.ч. WireGuard по имени подключения; по описанию можно найти имя интерфейса, например Wireguard1).
- `system configuration save` — сохранение конфигурации.
- `exit` — выход из CLI.
**Ручная установка asc-параметров AmneziaWG (если веб не импортировал их):**
По [инструкции Amnezia](https://docs.amnezia.org/documentation/instructions/keenetic-os-awg/) для версий KeeneticOS 4.3.3 и ниже параметры обфускации (Jc, Jmin, Jmax, S1, S2, H1H4) задаются в CLI командой вида:
```text
interface Wireguard1 wireguard asc 6 10 50 90 62 1455064900 852483043 2078090415 1981181588
```
(имя интерфейса и значения — из .conf и `show interface`; для 4.3.4+ импорт из файла может подставлять их автоматически.)
Полный перечень команд — в [руководстве по CLI](https://support.keenetic.com/hero/kn-1012/en/18480-command-line-interface--cli-.html) и в разделе загрузок на support.keenetic.com для модели Speedster.
---
## Связь с другими статьями
- Серверы VPN: [VPN-сервер (VPS, AmneziaWG)](../vps/vpn-vps-amneziawg.md), [Перенос конфигурации AmneziaWG](../vps/vpn-migrate-config.md).
- Домашняя сеть и Proxmox: [Архитектура и подключение](../architecture/architecture.md).

View File

@@ -0,0 +1,102 @@
# Инструкция: выпуск сертификата Let's Encrypt (DNS-01)
Универсальная инструкция для использования как промпт в следующих проектах. Подходит, когда HTTP-01 недоступен (порт 80 закрыт, блокировки, инстанс за NAT).
---
## Когда использовать DNS-01
- **HTTP-01** не срабатывает: таймаут, «Connection refused», порт 80 недоступен с интернета, провайдер или регион блокирует запросы от Let's Encrypt.
- **DNS-01**: проверка владения доменом по TXT-записи `_acme-challenge.<домен>`. До сервера стучаться не нужно — важен только DNS.
---
## Общий алгоритм
1. Выбрать DNS-провайдера домена и проверить, есть ли у него API или плагин для certbot/acme.sh.
2. Установить certbot и плагин для этого DNS (или использовать acme.sh с DNS API).
3. Создать файл учётных данных (логин/API-токен провайдера), права 600.
4. Запросить сертификат: `certbot certonly --authenticator dns-<провайдер> ... -d example.com`.
5. Подложить полученные `fullchain.pem` и `privkey.pem` в reverse proxy (Nginx Proxy Manager, nginx, Caddy и т.д.).
6. Настроить автообновление (systemd timer certbot + deploy-hook при продлении).
---
## Пример: Beget.com (certbot-dns-beget-api)
**Условия:** домен на Beget, доступ к API (логин + пароль или отдельный API-пароль).
1. **Установка (Debian/Ubuntu):**
```bash
apt install certbot
pip3 install certbot-dns-beget-api # или: python3 -m pip install certbot-dns-beget-api --break-system-packages
```
2. **Файл учётных данных** (например `/root/.secrets/certbot/beget.ini`):
```ini
dns_beget_api_username = ВАШ_ЛОГИН_BEGET
dns_beget_api_password = ВАШ_ПАРОЛЬ_ИЛИ_API_ПАРОЛЬ
```
```bash
chmod 600 /root/.secrets/certbot/beget.ini
```
3. **Запрос сертификата:**
```bash
certbot certonly \
--authenticator dns-beget-api \
--dns-beget-api-credentials /root/.secrets/certbot/beget.ini \
--dns-beget-api-propagation-seconds 120 \
-d example.com \
--non-interactive \
--agree-tos \
--email your@email.com
```
4. **Где лежат файлы после выпуска:**
- Сертификат: `/etc/letsencrypt/live/<домен>/fullchain.pem`
- Ключ: `/etc/letsencrypt/live/<домен>/privkey.pem`
5. **Интеграция с Nginx Proxy Manager (NPM):**
- Либо вручную скопировать в каталог custom_ssl (например `custom_ssl/npm-<id>/fullchain.pem` и `privkey.pem`) и перезагрузить nginx в контейнере NPM.
- Либо добавить запись в БД NPM (таблица `certificate`, provider `other`) и положить те же файлы в каталог, на который ссылается конфиг nginx (например `custom_ssl/npm-<certificate_id>/`).
6. **Продление и deploy-hook** (чтобы после `certbot renew` сертификат автоматически подхватывался NPM):
```bash
# /etc/letsencrypt/renewal-hooks/deploy/copy-to-npm.sh
# RENEWED_LINEAGE = путь к обновлённому сертификату, например /etc/letsencrypt/live/example.com
if [ "$RENEWED_LINEAGE" = "/etc/letsencrypt/live/EXAMPLE_DOMAIN" ]; then
cp "$RENEWED_LINEAGE/fullchain.pem" /path/to/npm/custom_ssl/npm-ID/
cp "$RENEWED_LINEAGE/privkey.pem" /path/to/npm/custom_ssl/npm-ID/
chmod 644 /path/to/npm/custom_ssl/npm-ID/fullchain.pem
chmod 600 /path/to/npm/custom_ssl/npm-ID/privkey.pem
docker exec CONTAINER_NPM nginx -s reload
fi
```
Сделать скрипт исполняемым: `chmod +x ...`
7. **Проверка автообновления:** таймер certbot обычно уже включён:
```bash
systemctl list-timers | grep certbot
```
---
## Другие DNS-провайдеры (идеи для промпта)
- **Cloudflare:** `certbot-dns-cloudflare`, переменные `dns_cloudflare_api_token` или `dns_cloudflare_email` + `dns_cloudflare_api_key`.
- **Reg.ru:** плагин `certbot-dns-regru`, свои переменные в credentials-файле.
- **NIC.ru:** `certbot-dns-nicru`.
- **Без API:** `certbot certonly --manual --preferred-challenges dns -d example.com` — выводит TXT-значение, пользователь вручную добавляет запись в DNS, затем продолжает по Enter.
---
## Краткий чеклист для нового домена/проекта
- [ ] Домен и DNS у одного провайдера; выяснить, есть ли API/плагин для ACME DNS-01.
- [ ] Установить certbot и нужный DNS-плагин.
- [ ] Создать credentials-файл (chmod 600), не коммитить в git.
- [ ] Выпустить сертификат: `certbot certonly --authenticator dns-... -d domain`.
- [ ] Подложить fullchain.pem и privkey.pem в reverse proxy.
- [ ] Добавить deploy-hook для продления и перезагрузки nginx/прокси.
- [ ] Убедиться, что certbot.timer включён для автоматического renew.

View File

@@ -0,0 +1,60 @@
# Перенос конфигурации AmneziaWG между серверами
Как развернуть тот же VPN на новом VPS и переключиться с одного сервера на другой без потери параметров обфускации. На роутере создаётся второе VPN-подключение, переключение — выбор нужного (Германия или США / новый сервер).
---
## Два текущих сервера
| Параметр | Германия (основной) | США (второй) |
|------------|---------------------|---------------------|
| IP | 185.103.253.99 | 147.45.124.117 |
| Порт AWG | 33118/UDP | 37135/UDP |
| Сеть | — | Netmask 255.255.254.0, Gateway 147.45.124.1 |
| Регион | Франкфурт-на-Майне | USA |
| Статус | Основной | Возможен отказ позже |
Подробнее про сервер в Германии: [VPN-сервер (VPS, AmneziaWG)](vpn-vps-amneziawg.md).
---
## Параметры обфускации совпадают
На обоих серверах снят вывод `wg show` (AmneziaWG). Параметры обфускации **идентичны**:
| Параметр | Значение |
|----------|-----------|
| jc | 6 |
| jmin | 10 |
| jmax | 50 |
| s1 | 90 |
| s2 | 62 |
| h1 | 1455064900 |
| h2 | 852483043 |
| h3 | 2078090415 |
| h4 | 1981181588 |
Отличаются только: IP сервера, порт UDP, имя интерфейса (wg0 / awg0), ключи и список пиров. То есть один и тот же «профиль» обфускации можно воспроизвести на новом VPS — клиенты будут вести себя так же с точки зрения DPI.
---
## Как перенести конфиг на новый сервер
Если позже арендуешь другой VPS (вместо США или дополнительно), конфигурацию можно перенести полностью.
1. **Развернуть сервер:** Ubuntu (или другая ОС из [требований Amnezia](https://docs.amnezia.org/ru/documentation/supported-linux-os-for-vps)), Docker, доступ по SSH с твоего ключа.
2. **Установить AmneziaWG через приложение AmneziaVPN:** добавить новый сервер по IP, установить протокол AmneziaWG. В настройках протокола на сервере задать те же параметры обфускации, что и сейчас: **jc, jmin, jmax, s1, s2, h1h4** (значения из таблицы выше).
3. **Клиенты:** для нового сервера в AmneziaVPN сгенерировать новые гостевые конфиги (или конфиг с полным доступом). В конфиге будет новый Endpoint = IP:порт нового VPS. Старые ключи/пиры с предыдущего сервера на новый не копировать — у нового сервера свой ключ; важны только параметры обфускации на сервере и в клиенте.
4. **Роутер:** создать второе VPN-подключение (второй профиль/интерфейс) с конфигом для нового сервера. Переключение — выбор активного подключения (Германия или США / новый хост).
Итог: параметры обфускации задаются вручную при настройке AmneziaWG на новом VPS так же, как на текущих; клиентские конфиги получаются из приложения уже с новым Endpoint.
---
## Роутер: два подключения, переключение
- В настройках роутера создаётся **дополнительное** VPN-подключение (второй профиль AmneziaWG/WireGuard).
- Один профиль — Germany (185.103.253.99:33118), второй — USA (147.45.124.117:37135) или будущий новый сервер.
- Переключение: выбираешь активное подключение — либо одно, либо другое (или отключено). Маршруты/политики при необходимости те же для обоих (например, весь трафик в туннель или только часть по правилам).
Так можно в любой момент перейти с USA на новый VPS: добавляешь новый профиль с конфигом нового сервера и переключаешься на него.

View File

@@ -0,0 +1,95 @@
# VPN-сервер (VPS, AmneziaWG)
Отдельный VPS в другой стране для обхода блокировок. Развёрнут протокол **AmneziaWG** (маскировка VPN-трафика под обычный UDP, устойчивость к DPI). Трафик с домашнего контура при необходимости можно маршрутизировать через этот сервер.
---
## Доступ и логины
- **SSH:** `ssh root@185.103.253.99` (доступ по SSH-ключу). IP: 185.103.253.99, ОС Ubuntu, ядро 6.8.
- **Веб-интерфейсов на сервере нет.** Управление VPN — через приложение AmneziaVPN на клиенте (добавление сервера по IP, установка AmneziaWG, гостевые конфиги).
**Хостинг (First Byte):**
- Тариф: KVM-SSD-1-FRA
- Дата открытия: 2026-01-24
- Доменное имя: vm3839421.firstbyte.club
- Регион: Германия, Франкфурт-на-Майне
---
## Что развёрнуто
- **Docker** — один контейнер: **amnezia-awg** (образ `amnezia-awg`).
- **AmneziaWG** слушает порт **33118/UDP** на всех интерфейсах.
- Контейнер запущен с `--restart=always`, примонтирован `/lib/modules` (для ядерного модуля WireGuard). Сеть — bridge, проброс порта 33118/udp на хост.
- Дополнительно: **vps-metrics** (systemd-сервис) — API метрик для виджета Homepage.
Каталог образа/скриптов на хосте: `/opt/amnezia/amnezia-awg/` (там лежит Dockerfile; сам сервер AmneziaWG настраивается через приложение AmneziaVPN при установке протокола на этот VPS).
---
## Протокол AmneziaWG
- Форк WireGuard с обфускацией трафика: динамические заголовки, рандомизация размеров пакетов, маскировка под другие UDP-протоколы (QUIC, DNS и т.д.). Это затрудняет определение и блокировку VPN системами DPI.
- Криптография и производительность — как у WireGuard; совместимость с обычным WireGuard ограничена (нужен именно клиент AmneziaWG/AmneziaVPN).
Подробнее: [документация Amnezia](https://docs.amnezia.org/ru/documentation/amnezia-wg), [AmneziaWG 2.0 на self-hosted](https://docs.amnezia.org/ru/documentation/instructions/new-amneziawg-selfhosted).
---
## Как подключиться к VPN
1. Установи клиент **AmneziaVPN** на устройство (Windows, macOS, Linux, Android, iOS): [amnezia.org/downloads](https://amnezia.org/ru/downloads).
2. Добавь сервер: в приложении создай новое подключение и укажи **185.103.253.99** (логин/пароль или SSH-ключ — как настраивал при первом развёртывании). Либо вставь ключ подключения в формате `vpn://...`, если он был сгенерирован и сохранён.
3. В настройках этого сервера установи/выбери протокол **AmneziaWG** (при первом развёртывании он ставится через приложение на VPS).
4. Для доступа с других устройств без полного доступа к серверу: в AmneziaVPN создай **гостевое** подключение по AmneziaWG и передай сгенерированный ключ или конфиг (.conf) на нужное устройство.
Конфигурации и ключи хранятся в приложении и (при экспорте) в выданных тебе файлах; на VPS в открытом виде в доку не дублируются.
---
## Полезные команды на VPS
```bash
# Статус контейнера
docker ps -a | grep amnezia
# Логи (если включены)
docker logs amnezia-awg
# Интерфейс WireGuard внутри контейнера (публичные ключи, пиры, handshake)
docker exec amnezia-awg wg show
# Перезапуск VPN-контейнера
docker restart amnezia-awg
```
Порт на хосте:
```bash
ss -ulnp | grep 33118
```
---
## Связь с домашним контуром
- Домашний сервер (Proxmox): 192.168.1.150, внешний IP 185.35.193.144.
- При необходимости маршрутизировать трафик (например, YouTube/Invidious) через этот VPN настраивается отдельно: маршруты и/или policy-based routing на роутере или на конкретных хостах/контейнерах.
В документе по [архитектуре](../architecture/architecture.md) этот VPS упоминается как отдельный узел; детали доступа и протокола — в этой статье.
---
## Второй VPS (USA)
Есть второй сервер в США; от него возможен отказ в пользу одного Germany или нового хостинга.
- **IP:** 147.45.124.117
- **Сеть:** Netmask 255.255.254.0, Gateway 147.45.124.1
- **SSH:** `ssh root@147.45.124.117`
- **AmneziaWG:** контейнер `amnezia-awg2`, порт **37135/UDP**.
Параметры обфускации на обоих серверах (Германия и США) **одинаковые** — конфиг можно полностью перенести на новый сервер при переезде. На роутере создаётся второе VPN-подключение; переключение между Germany и USA — выбор нужного профиля.
**Подробно:** [Перенос конфигурации AmneziaWG между серверами](vpn-migrate-config.md).

105
docs/vps/vps-miran-bots.md Normal file
View File

@@ -0,0 +1,105 @@
# VPS Миран (СПБ): боты и STUN/TURN
VPS в ЦОД Миран (Санкт-Петербург). Развёрнуты два Telegram-бота (telegram-helper-bot, anonBot), инфраструктура prod (мониторинг, метрики), а также сервер STUN/TURN для Galene (call.katykhin.ru).
---
## Доступ и логины
- **SSH:** `ssh -p 15722 deploy@185.147.80.190` (пользователь deploy, в группе docker). IP: 185.147.80.190, хостнейм vm220416.vds.miran.ru, ОС Ubuntu.
- **S3 (контент ботов):** URL https://api.s3.miran.ru, порт 443. Access key: `j3tears100@gmail.com`, Secret key: `wQ1-6sZEPs92sbZTSf96` (полная таблица — в разделе «S3» ниже).
- **Админка Миран (панель хостинга VPS):** логин `j3tears100@gmail.com`, пароль `gonPok-xifrys-4nuxde`.
- **Grafana, Uptime Kuma, админки ботов:** логины и пароли — в `.env` проекта prod или в менеджере паролей.
---
## Что развёрнуто
### 1. Боты и prod (Docker Compose)
Проект в `/home/prod/`: `docker-compose.yml`, каталоги `bots/`, `infra/`, CI (GitHub Actions в `.github/`). Запуск от пользователя deploy.
| Сервис | Образ / контейнер | Порт | Назначение |
|------------------|---------------------|-------|--------------------------|
| telegram-bot | prod-telegram-bot | 8080 | telegram-helper-bot |
| anon-bot | prod-anon-bot | 8081 | anonBot |
| prometheus | prom/prometheus | 9090 | Метрики |
| alertmanager | prom/alertmanager | 9093 | Алерты |
| grafana | grafana/grafana | 3000 | Дашборды |
| uptime-kuma | louislam/uptime-kuma| 3001 | Мониторинг доступности |
Сеть контейнеров: `prod_bots_network` (bridge). Переменные окружения и секреты — в `.env` и настройках сервисов (в доку не дублируются).
### 2. STUN/TURN (Galene)
**coTURN** — системный сервис `coturn`, конфиг `/etc/turnserver.conf`.
- **Порты:** 3478/UDP (STUN/TURN), TLS/DTLS отключены (`no-tls`, `no-dtls`).
- **Realm:** call.katykhin.ru
- **External IP:** 185.147.80.190
- **Диапазон портов для релея:** 4915249252
- Учётные данные для Galene заданы в конфиге (user/realm); на сервере Galene (контейнер 108) в настройках указывается этот TURN-сервер для обхода NAT.
Трафик с Galene (домашний сервер 192.168.1.108, call.katykhin.ru) уходит на этот VPS для STUN/TURN, чтобы видеозвонки работали при симметричном NAT и ограничениях провайдера.
### 3. S3 (контент ботов)
Объектное хранилище Миран (S3-совместимый API) для контента, который отдают боты (медиа, файлы). Доступ по HTTPS.
| Параметр | Значение |
|-------------|----------|
| URL | https://api.s3.miran.ru |
| Порт | 443 (HTTPS) |
| Access key | j3tears100@gmail.com |
| Secret key | wQ1-6sZEPs92sbZTSf96 |
В ботаx (переменные окружения prod) заданы `S3_ENDPOINT_URL=https://api.s3.miran.ru`, регион и креды для загрузки/выдачи контента. Для локальной разработки или других клиентов использовать те же endpoint и ключи.
### 4. Остальное на хосте
- **nginx** — порты 80 и 443; по умолчанию отдаёт статику из `/var/www/html`.
- **prometheus-node-exporter** — порт 9100, метрики хоста для Prometheus.
- **vps-metrics** — systemd-сервис, API метрик для виджета Homepage (порт 3497).
- **cron** — по расписанию при необходимости.
---
## Порты (сводка)
| Порт | Служба / контейнер | Протокол |
|--------|--------------------------|----------|
| 15722 | SSH | TCP |
| 80, 443| nginx | TCP |
| 3478 | coturn (STUN/TURN) | UDP |
| 3497 | vps-metrics (Homepage) | TCP |
| 8080 | telegram-bot | TCP |
| 8081 | anon-bot | TCP |
| 9090 | Prometheus | TCP |
| 9093 | Alertmanager | TCP |
| 9100 | node-exporter | TCP |
| 3000 | Grafana | TCP |
| 3001 | Uptime Kuma | TCP |
---
## Управление ботами и prod
Рабочий каталог Compose: `/home/prod/`. От пользователя deploy:
```bash
cd /home/prod
docker compose ps
docker compose up -d
docker compose logs -f telegram-bot
```
Образы ботов собираются из репозитория (Dockerfile в проекте); деплой через Makefile / CI при необходимости.
---
## Связь с домашним контуром
- **Galene** (контейнер 108, call.katykhin.ru): в настройках сервера Galene указан TURN-сервер 185.147.80.190:3478 (realm call.katykhin.ru), чтобы клиенты за NAT могли устанавливать медиа-сессии через этот VPS.
- **Homepage** (контейнер 100): виджет метрик может показывать данные с vps-metrics (185.147.80.190:3497).
Остальные узлы homelab (Proxmox, NPM и т.д.) описаны в [архитектуре](../architecture/architecture.md).