infra/CLAUDE.md
jack 66b70827df
Some checks failed
CI/CD / syntax-check (push) Successful in 1m31s
CI/CD / deploy (push) Has been cancelled
chore: full project cleanup + documentation
Syncthing removal (was already decided, now fully removed):
- roles/base/tasks/firewall.yml: remove 3 UFW rules (ports 22000/21027)
- inventory/group_vars/all/main.yml: remove domain_sync, domain_mon, syncthing_basic_auth_htpasswd
- roles/services/templates/env.j2: remove DOMAIN_SYNC
- roles/services/templates/authelia/configuration.yml.j2: remove Syncthing 2FA rule
- roles/services/tasks/directories.yml: remove syncthing/config and syncthing/data dirs
- roles/services/defaults/main.yml: remove syncthing_image
- roles/services/tasks/main.yml: remove syncthing image pull

Security hardening:
- inventory/group_vars/all/main.yml: move cloudflare_zone_id to vault
- inventory/group_vars/all/vault.yml: add vault_cloudflare_zone_id

.gitignore improvements:
- add *.env, acme.json, *.log, editor dirs, venv, temp files

Documentation (new):
- docs/STATUS.md: all services, servers, known issues
- docs/BACKLOG.md: prioritized task list, done/todo
- docs/DECISIONS.md: architecture decisions and rationale
- CLAUDE.md: rewritten with read-first docs, rules, full arch reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 19:58:12 +07:00

4.9 KiB
Raw Blame History

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.

Команды

# 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 — hourly backup script → S3 cold (visual-backup/data/)

Шаблоны → файлы на сервере:

  • 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