infra/CLAUDE.md
jack 207e1dcff0
All checks were successful
CI/CD / syntax-check (push) Successful in 1m29s
CI/CD / deploy (push) Successful in 16m39s
chore: project cleanup and docs update
- Remove Syncthing mention from authelia comment in docker-compose
- Fix backup.sh.j2 comment: hourly → every 6 hours
- Update CLAUDE.md: add docs update rule, fix backup schedule note
- Update STATUS.md: dash.csrx.ru fixed, PTR pending, backup schedule, mail hostnames
- Update BACKLOG.md: mark DNS/PTR/backup-schedule done, add SnappyMail domain task
- Update DECISIONS.md: fix backup section (no --storage-class COLD, correct schedule)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:00:35 +07:00

112 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## ⚠️ ЧИТАЙ СНАЧАЛА
Перед любой работой прочитай эти файлы:
- **`docs/STATUS.md`** — текущее состояние всех сервисов, известные проблемы
- **`docs/BACKLOG.md`** — что нужно сделать (приоритеты), что уже сделано
- **`docs/DECISIONS.md`** — почему всё устроено именно так
После завершения работы **обнови** соответствующий документ.
---
## Правила работы
1. **Только через CI/CD** — никогда не фикси что-либо вручную на сервере. Внеси изменение, закоммить, запуши → CI/CD сам задеплоит. Потом проверь результат.
2. **Syncthing удалён навсегда** — не упоминать, не предлагать вернуть.
3. **Секреты** — все в `inventory/group_vars/all/vault.yml` с префиксом `vault_`. В `main.yml` только алиасы `"{{ vault_* }}"`. Никаких plaintext секретов.
4. **Синтаксис-чек перед коммитом**`ansible-playbook playbooks/deploy.yml --syntax-check`.
5. **Обновляй доки** — после каждого изменения обновляй `docs/STATUS.md`, `docs/BACKLOG.md` или `docs/DECISIONS.md`.
---
## Команды
```bash
# Prerequisites (один раз, на машине оператора)
ansible-galaxy collection install community.general community.docker ansible.posix
echo "yourpassword" > ~/.vault-password-file && chmod 600 ~/.vault-password-file
# Первичная настройка сервера (от root)
ansible-playbook playbooks/bootstrap.yml -u root
# Деплой основного сервера
ansible-playbook playbooks/deploy.yml
# Деплой tools-сервера
ansible-playbook playbooks/tools.yml
# Деплой всего сразу
ansible-playbook playbooks/site.yml
# Редактировать секреты
ansible-vault edit inventory/group_vars/all/vault.yml
# Проверка синтаксиса (без подключения к серверу)
ansible-playbook playbooks/deploy.yml --syntax-check
ansible-playbook playbooks/tools.yml --syntax-check
# Dry run
ansible-playbook playbooks/deploy.yml --check
# Только конкретная роль
ansible-playbook playbooks/deploy.yml --tags base
ansible-playbook playbooks/deploy.yml --tags docker
ansible-playbook playbooks/deploy.yml --tags services
ansible-playbook playbooks/deploy.yml --tags backup
```
---
## Архитектура
**Серверы:**
- `main` (87.249.49.32) — Traefik, Forgejo, Plane, Vaultwarden, Мониторинг, CI/CD runner
- `tools` (85.193.83.9) — Outline wiki, n8n, docker-mailserver, SnappyMail
**Трафик:** Internet → Cloudflare proxy → Traefik (80/443) → сервисы.
Порты 80/443 открыты только для IP-адресов Cloudflare (UFW whitelist).
**Секреты:** `inventory/group_vars/all/vault.yml` (Ansible Vault AES-256).
Пароль vault: `~/.vault-password-file``.gitignore`, никогда не коммитить).
**TLS:** Wildcard сертификат `*.csrx.ru` через Cloudflare DNS-01 (Traefik certresolver).
**Роли:**
- `base` — UFW, fail2ban, sshd, deploy user
- `docker` — Docker CE + Compose plugin
- `services` — основной стек (templates → `/opt/services/`, docker compose up)
- `tools` — tools-стек (templates → `/opt/tools/`, docker compose up)
- `backup` — backup каждые 6 часов → S3 (`visual-backup/data/`), только для main-сервера
**Шаблоны → файлы на сервере:**
- `roles/services/templates/docker-compose.yml.j2``/opt/services/docker-compose.yml`
- `roles/services/templates/env.j2``/opt/services/.env` (mode 0600)
- `roles/services/templates/traefik/traefik.yml.j2``/opt/services/traefik/traefik.yml`
- `roles/services/templates/traefik/dynamic/routes.yml.j2``/opt/services/traefik/dynamic/routes.yml`
**Добавление нового сервиса на main:**
1. Добавить контейнер в `docker-compose.yml.j2` в сеть `backend`
2. Добавить роутер в `routes.yml.j2` (НЕ docker labels — используется file provider)
3. Добавить домен в `inventory/group_vars/all/main.yml`
4. Добавить DNS A-запись в Cloudflare
**Добавление сервиса на tools:**
1. Добавить контейнер в `roles/tools/templates/docker-compose.yml.j2`
2. Добавить роутер в `routes.yml.j2` с `url: "http://{{ ip_tools }}:PORT"`
3. Открыть порт в UFW (задача в `roles/tools/tasks/main.yml`)
---
## CI/CD
Push в `master` → Forgejo Actions запускает:
```
ansible-playbook playbooks/deploy.yml
ansible-playbook playbooks/tools.yml
```
Workflow: `.forgejo/workflows/deploy.yml`