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>
4.9 KiB
4.9 KiB
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— почему всё устроено именно так
После завершения работы обнови соответствующий документ.
Правила работы
- Только через CI/CD — никогда не фикси что-либо вручную на сервере. Внеси изменение, закоммить, запуши → CI/CD сам задеплоит. Потом проверь результат.
- Syncthing удалён — не предлагай его вернуть, не упоминай как отсутствующий сервис.
- Секреты — все в
inventory/group_vars/all/vault.ymlс префиксомvault_. Вmain.ymlтолько алиасы"{{ vault_* }}". Никаких plaintext секретов. - Синтаксис-чек перед коммитом —
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 runnertools(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 userdocker— Docker CE + Compose pluginservices— основной стек (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.ymlroles/services/templates/env.j2→/opt/services/.env(mode 0600)roles/services/templates/traefik/traefik.yml.j2→/opt/services/traefik/traefik.ymlroles/services/templates/traefik/dynamic/routes.yml.j2→/opt/services/traefik/dynamic/routes.yml
Добавление нового сервиса на main:
- Добавить контейнер в
docker-compose.yml.j2в сетьbackend - Добавить роутер в
routes.yml.j2(НЕ docker labels — используется file provider) - Добавить домен в
inventory/group_vars/all/main.yml - Добавить DNS A-запись в Cloudflare
Добавление сервиса на tools:
- Добавить контейнер в
roles/tools/templates/docker-compose.yml.j2 - Добавить роутер в
routes.yml.j2сurl: "http://{{ ip_tools }}:PORT" - Открыть порт в 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