docs: AI project context (docs/ai) and repository documentation refresh

- docs/ai/: stable, repo-verified context - README, architecture, tech-stack,
  edge-cases, plan (confirmed active work only), migration-tofu (the blue-green
  OpenTofu migration runbook and per-service findings), legacy-warning, links.
- AGENTS.md: slimmed to a working contract that points at docs/ai instead of
  restating it; CLAUDE.md is an adapter that @-includes it.
- README.md, ansible/README.md, ansible/roles/README.md,
  roles/lxc_docker_host/README.md: bring wording in line with the current
  control plane (Makefile entry point, registry, tofu, memoir-bot gone).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uoq5AVK8mkBgg83Mq6o5V
This commit is contained in:
Dmitry
2026-09-03 07:06:10 +03:00
co-authored by Claude Sonnet 5
parent 5e27ba2513
commit d2e1e6876a
13 changed files with 1955 additions and 377 deletions
+54 -41
View File
@@ -12,8 +12,10 @@ Ansible is the control plane for HomeLab infrastructure changes.
## Layout
- `inventory/hosts.yml` — canonical host list and host-specific facts.
- `inventory/group_vars/all/services.yml` — service registry and reverse-proxy input; deployment playbooks still duplicate these facts.
- `playbooks/` — entry points for tasks.
- `roles/` — reusable configuration units.
- `Makefile` — canonical manual entry point and safety gates.
## Current Groups
@@ -24,38 +26,43 @@ Ansible is the control plane for HomeLab infrastructure changes.
- `monitoring_exporters` — hosts exposing Node Exporter metrics.
- `monitoring_smart_exporters` — Proxmox nodes exposing SMART metrics.
- `vpn_openvpn` — OpenVPN transport hosts: `ru-vps`, `ovpn-mini`.
- `shell_hosts` — hosts with unified bash config: `ru-vps`, `cloud-pc`, `mini-pc`.
- `shell_hosts` — hosts with unified bash config: `ru-vps`, `cloud-pc`, `mini-pc`, `hermes-ai`.
- `servers` — all managed hosts.
## First Checks
Install control-node dependencies locally:
From the repository root, use the Nix environment and install Galaxy collections once per clone:
```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
ansible-galaxy collection install -r requirements.yml -p collections
nix develop
ansible-galaxy collection install -r ansible/requirements.yml -p ansible/collections
```
Run from `ansible/`:
Run manual operations through Make from `ansible/`:
```bash
ansible-playbook playbooks/check.yml
make help
make check
make status EXTRA="--limit '!gyro'"
make lint
```
`make setup` remains a local venv fallback when Nix is unavailable.
## Controlled Updates
Service updates are manual and use pinned `tag@sha256:digest` image references only; floating tags and auto-update agents are not used.
Service updates are manual. Active update-managed remote images are pinned as
`tag@sha256:digest`; the frozen Prometheus stack is tag-only. Floating
auto-update agents are not used.
Run the dedicated playbook for the target service from `ansible/`:
Run the dedicated Make target from `ansible/`:
```bash
.venv/bin/ansible-playbook playbooks/vaultwarden-update.yml
.venv/bin/ansible-playbook playbooks/gitea-update.yml
.venv/bin/ansible-playbook playbooks/adguard-update.yml
.venv/bin/ansible-playbook playbooks/mihomo-update.yml
.venv/bin/ansible-playbook playbooks/grimmory-update.yml
make update-vaultwarden
make update-gitea
make update-adguard
make update-mihomo
make update-grimmory
```
Update flow is always: fresh backup/audit first, then the update playbook, then health verification.
@@ -69,55 +76,62 @@ Update flow is always: fresh backup/audit first, then the update playbook, then
Use the dedicated hardening playbook only when explicitly approved:
```bash
.venv/bin/ansible-playbook playbooks/ru-vps-mihomo-harden.yml -e ru_vps_mihomo_harden_confirm=true
make mihomo-harden CONFIRM=1
```
It rotates the live Mihomo SOCKS credentials on `ru-vps`, locks the proxy to loopback, and removes the public UFW exposure for ports `7890` and `7891`.
The rotated credentials are not recoverable for clients unless you roll back the saved config backup.
For Proxmox API playbooks, create ignored `.env` from `.env.example` and load it:
For Proxmox API playbooks, create ignored `.env` in the **repository root** from
`.env.example`. It is shared with OpenTofu (`tofu/`). Make loads it
automatically:
```bash
cp .env.example .env
. ./.env
.venv/bin/ansible-playbook playbooks/pve-ovpn-mini.yml
cp ../.env.example ../.env # секреты живут в корне репозитория
make env-check
make dry-ovpn-mini
make deploy-ovpn-mini
```
Or bootstrap the token from `mini-pc` with sudo:
```bash
.venv/bin/ansible-playbook playbooks/bootstrap-pve-api-token.yml -K
make bootstrap-pve-token
```
Create the separate read-only PVE token used by the monitoring exporter:
```bash
.venv/bin/ansible-playbook playbooks/bootstrap-monitoring-pve-token.yml
make bootstrap-monitoring-token
```
OpenVPN transport:
```bash
.venv/bin/ansible-playbook playbooks/openvpn-vps-mini.yml -K
.venv/bin/ansible-playbook playbooks/openvpn-check.yml
make openvpn
make openvpn-check
```
Monitoring is provisioned in two steps after loading the monitoring secrets from ignored `.env` or Ansible Vault:
CT 146 can be provisioned separately. Uptime Kuma is the active monitoring service:
```bash
. ./.env
.venv/bin/ansible-playbook playbooks/pve-monitoring.yml
.venv/bin/ansible-playbook playbooks/monitoring.yml
make deploy-monitoring
make uptime-kuma
```
`pve-monitoring.yml` creates CT `146` (`monitoring`, `192.168.1.30`) on `cloud-pc`. `monitoring.yml` configures exporters, the `ru-vps` probe vantage point, and the central Prometheus stack. It is frozen while Uptime Kuma is in use; do not run it unless restoring Prometheus monitoring.
`pve-monitoring.yml` creates CT `146` (`monitoring`, `192.168.1.30`) on
`cloud-pc`. The older `monitoring.yml` configures Prometheus, Alertmanager,
Grafana and exporters; it is frozen and `make monitoring CONFIRM=1` is reserved
for an explicitly approved restoration decision.
## Gyro Investment Allocator
`pve-gyro.yml` creates unprivileged CT `150` (`gyro`, `192.168.1.35`) on `mini-pc`. `gyro.yml` installs Python 3.13+, pinned `uv`, the `gyro` service user, a container-local GitHub deploy key, restrictive firewall rules, and a weekday systemd timer.
Production `gyro` now runs in Tofu-provisioned CT `156` (`gyro`, `192.168.1.35`) on `mini-pc`. CT `150` is stopped and kept only as rollback for at least a week; it is not removed.
UFW is the currently enforced isolation layer: inbound is denied except SSH from LAN/OpenVPN, and east-west outbound is denied except the Mihomo HTTP proxy. The equivalent CT `150` Proxmox firewall is staged, but the cluster-wide PVE firewall remains disabled; do not enable it without auditing every node and guest with `firewall=1`.
`make gyro` configures Python 3.13+, pinned `uv`, the `gyro` service user, the container-local GitHub deploy key, restrictive firewall rules, and the weekday systemd timer. Do not use `make deploy-gyro` for the cutover path.
UFW is the currently enforced isolation layer: inbound is denied except SSH from LAN/OpenVPN, and east-west outbound is denied except the Mihomo HTTP proxy. The equivalent CT `156` Proxmox firewall is already carried over; the cluster-wide PVE firewall remains disabled, so do not enable it without auditing every node and guest with `firewall=1`.
The role keeps deployment and the timer disabled by default. The active host vars deploy `git@github.com:ada-dmitry/t_tech-gyro.git` with GitHub's verified ED25519 host key; the timer still requires the ignored Vault file:
@@ -129,17 +143,17 @@ ansible-vault encrypt inventory/host_vars/gyro/vault.yml
After encrypting the secrets, set `gyro_timer_enabled: true` in `main.yml` and apply with `--ask-vault-pass`. `DRY_RUN_OVERRIDE` remains `true` until real trading is explicitly approved.
```bash
. ./.env
.venv/bin/ansible-playbook playbooks/pve-gyro.yml
.venv/bin/ansible-playbook playbooks/gyro.yml --ask-vault-pass
make gyro
```
The timer runs at 11:00 Europe/Moscow from Monday through Friday and uses `OnFailure=` for a best-effort Telegram alert. CT `150` is included in the daily mini-pc PBS job and backup freshness audit.
The timer runs at 11:00 Europe/Moscow from Monday through Friday and uses `OnFailure=` for a best-effort Telegram alert. PBS backup jobs and the backup freshness audit derive the current Gyro VMID from the registry once regenerated, so CT `156` is picked up automatically.
The legacy `pve-gyro.yml` remains available for rollback recovery only and is blocked by default after cutover unless an explicit override is passed.
Uptime Kuma uses the existing monitoring LXC and stops/disables `homelab-monitoring` without deleting its configuration or data. Its UI is available only from the LAN at `http://192.168.1.30:3001`; create monitors and notification settings in the UI.
```bash
.venv/bin/ansible-playbook playbooks/uptime-kuma.yml
make uptime-kuma
```
## Emergency Reverse SSH
@@ -149,9 +163,8 @@ Uptime Kuma uses the existing monitoring LXC and stops/disables `homelab-monitor
Before applying, set `EMERGENCY_BOT_TOKEN`, `EMERGENCY_ALLOWED_USER_IDS`, `EMERGENCY_VPS_HOST_KEY`, and `EMERGENCY_MINI_PC_HOST_KEY` in ignored `.env` or Ansible Vault. The host-key variables must be verified public host keys, not values obtained during deployment.
```bash
. ./.env
.venv/bin/ansible-playbook playbooks/pve-emergency-bot.yml
.venv/bin/ansible-playbook playbooks/emergency-access.yml
make deploy-emergency-bot
make emergency-access
```
From an authorized private Telegram chat, use the `Enable SSH`, `Status`, and `Stop` buttons or `/emergency ssh`, `/emergency status`, and `/emergency stop`. `/emergency ssh` enables a 60-minute tunnel only; it does not expose a public port. Connect while it is active with:
@@ -167,13 +180,13 @@ The target account is `ansible`; it has no password login. Use the existing priv
Bootstrap the Ansible service account on shell hosts:
```bash
.venv/bin/ansible-playbook -i inventory/hosts.yml playbooks/bootstrap-ansible-user.yml -K
make bootstrap-ansible-user
```
When a task needs privilege escalation:
```bash
ansible-playbook playbooks/<name>.yml -K
make play-<name> EXTRA="-K"
```
## Workflow
+14 -3
View File
@@ -36,12 +36,23 @@ systemd-юнит `Type=oneshot` с `docker compose up -d --remove-orphans`,
Подробности и пример плейбука Gitea на новых ролях:
[`compose_service/README.md`](compose_service/README.md).
**Статус:** роли созданы и проверены синтаксически, но пока не подключены ни
к одному живому сервису. Перевод `pve-*.yml` на них — отдельный этап.
**Статус:** `compose_service` подключён в `playbooks/ru-vps-base.yml` (стек
Caddy на ru-vps) — это его первый и пока единственный потребитель.
`lxc_docker_host` не подключён нигде. Перевод `pve-*.yml` на обе роли —
отдельный этап.
## Источник данных
Факты о сервисах (vmid, узел, адрес, порты, домен, образы с digest, ресурсы,
бэкап, мониторинг, порядок автозапуска) собраны в реестре
`ansible/inventory/group_vars/all/services.yml` (`homelab_services`).
Его уже потребляет `playbooks/reverse-proxy.yml`.
Программные потребители реестра:
- `playbooks/reverse-proxy.yml` — сборка Caddyfile;
- `playbooks/ru-vps-base.yml` — стек Caddy и его закреплённый образ;
- `playbooks/pve-backup-jobs.yml` — списки VMID заданий PBS (поле `backup.job`);
- `roles/backup_audit` — VMID для аудита (флаг `monitoring.backup_audit_vmid`);
- `playbooks/validate.yml` — сверка реестра с фактическим состоянием Proxmox.
Остальное (`pve-*.yml`, `status.yml`, monitoring, SSH config) по-прежнему
дублирует значения и должно меняться согласованно.
+2 -2
View File
@@ -5,8 +5,8 @@ Docker»: пакеты, проверка `/dev/fuse`, `storage-driver: fuse-over
запуск демона и базовый UFW.
Роль вынесена из повторяющихся блоков `playbooks/pve-*.yml`
(gitea, vaultwarden, mihomo, adguard, memoir-bot, docker-test, grimmory,
hermes-ai) — суммарно около 350 строк копипасты.
(gitea, vaultwarden, mihomo, adguard, docker-test, grimmory, hermes-ai) —
суммарно около 350 строк копипасты.
## Что делает