chore: delete dead templates, remove duplicate MinIO task, update CLAUDE.md
- Delete grafana provisioning templates (grafana/loki removed) - Delete env.outline.j2 (Outline replaced by Docmost) - Remove duplicate MinIO bucket creation Ansible task (plane-createbuckets compose service handles this more reliably) - Update CLAUDE.md: single server, correct domains, remove tools references
This commit is contained in:
parent
5f44441bd1
commit
ccd7c44293
6 changed files with 24 additions and 132 deletions
48
CLAUDE.md
48
CLAUDE.md
|
|
@ -18,9 +18,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||||
|
|
||||||
1. **Только через CI/CD** — никогда не фикси что-либо вручную на сервере. Внеси изменение, закоммить, запуши → CI/CD сам задеплоит. Потом проверь результат.
|
1. **Только через CI/CD** — никогда не фикси что-либо вручную на сервере. Внеси изменение, закоммить, запуши → CI/CD сам задеплоит. Потом проверь результат.
|
||||||
2. **Syncthing удалён навсегда** — не упоминать, не предлагать вернуть.
|
2. **Syncthing удалён навсегда** — не упоминать, не предлагать вернуть.
|
||||||
3. **Секреты** — все в `inventory/group_vars/all/vault.yml` с префиксом `vault_`. В `main.yml` только алиасы `"{{ vault_* }}"`. Никаких plaintext секретов.
|
3. **Vaultwarden удалён навсегда** — не упоминать, не предлагать вернуть.
|
||||||
4. **Синтаксис-чек перед коммитом** — `ansible-playbook playbooks/deploy.yml --syntax-check`.
|
4. **Tools-сервер удалён навсегда** — один сервер `main`. Мониторинг через UptimeRobot (внешний).
|
||||||
5. **Обновляй доки** — после каждого изменения обновляй `docs/STATUS.md`, `docs/BACKLOG.md` или `docs/DECISIONS.md`.
|
5. **Секреты** — все в `inventory/group_vars/all/vault.yml` с префиксом `vault_`. В `main.yml` только алиасы `"{{ vault_* }}"`. Никаких plaintext секретов.
|
||||||
|
6. **Синтаксис-чек перед коммитом** — `ansible-playbook playbooks/deploy.yml --syntax-check`.
|
||||||
|
7. **Обновляй доки** — после каждого изменения обновляй `docs/STATUS.md`, `docs/BACKLOG.md` или `docs/DECISIONS.md`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -34,21 +36,14 @@ echo "yourpassword" > ~/.vault-password-file && chmod 600 ~/.vault-password-file
|
||||||
# Первичная настройка сервера (от root)
|
# Первичная настройка сервера (от root)
|
||||||
ansible-playbook playbooks/bootstrap.yml -u root
|
ansible-playbook playbooks/bootstrap.yml -u root
|
||||||
|
|
||||||
# Деплой основного сервера
|
# Деплой
|
||||||
ansible-playbook playbooks/deploy.yml
|
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-vault edit inventory/group_vars/all/vault.yml
|
||||||
|
|
||||||
# Проверка синтаксиса (без подключения к серверу)
|
# Проверка синтаксиса (без подключения к серверу)
|
||||||
ansible-playbook playbooks/deploy.yml --syntax-check
|
ansible-playbook playbooks/deploy.yml --syntax-check
|
||||||
ansible-playbook playbooks/tools.yml --syntax-check
|
|
||||||
|
|
||||||
# Dry run
|
# Dry run
|
||||||
ansible-playbook playbooks/deploy.yml --check
|
ansible-playbook playbooks/deploy.yml --check
|
||||||
|
|
@ -65,8 +60,7 @@ ansible-playbook playbooks/deploy.yml --tags backup
|
||||||
## Архитектура
|
## Архитектура
|
||||||
|
|
||||||
**Серверы:**
|
**Серверы:**
|
||||||
- `main` (87.249.49.32) — Traefik, Forgejo, Plane, Vaultwarden, Мониторинг, CI/CD runner
|
- `main` (87.249.49.32) — единственный сервер: Traefik, Forgejo, Plane, Docmost, n8n, CI/CD runner
|
||||||
- `tools` (85.193.83.9) — Outline wiki, n8n, docker-mailserver, SnappyMail
|
|
||||||
|
|
||||||
**Трафик:** Internet → Cloudflare proxy → Traefik (80/443) → сервисы.
|
**Трафик:** Internet → Cloudflare proxy → Traefik (80/443) → сервисы.
|
||||||
Порты 80/443 открыты только для IP-адресов Cloudflare (UFW whitelist).
|
Порты 80/443 открыты только для IP-адресов Cloudflare (UFW whitelist).
|
||||||
|
|
@ -74,14 +68,13 @@ ansible-playbook playbooks/deploy.yml --tags backup
|
||||||
**Секреты:** `inventory/group_vars/all/vault.yml` (Ansible Vault AES-256).
|
**Секреты:** `inventory/group_vars/all/vault.yml` (Ansible Vault AES-256).
|
||||||
Пароль vault: `~/.vault-password-file` (в `.gitignore`, никогда не коммитить).
|
Пароль vault: `~/.vault-password-file` (в `.gitignore`, никогда не коммитить).
|
||||||
|
|
||||||
**TLS:** Wildcard сертификат `*.csrx.ru` через Cloudflare DNS-01 (Traefik certresolver).
|
**TLS:** Wildcard сертификат `*.walava.io` через Cloudflare DNS-01 (Traefik certresolver).
|
||||||
|
|
||||||
**Роли:**
|
**Роли:**
|
||||||
- `base` — UFW, fail2ban, sshd, deploy user
|
- `base` — UFW, fail2ban, sshd, deploy user
|
||||||
- `docker` — Docker CE + Compose plugin
|
- `docker` — Docker CE + Compose plugin
|
||||||
- `services` — основной стек (templates → `/opt/services/`, docker compose up)
|
- `services` — основной стек (templates → `/opt/services/`, docker compose up)
|
||||||
- `tools` — tools-стек (templates → `/opt/tools/`, docker compose up)
|
- `backup` — backup каждые 6 часов → S3 (`walava-backup/`), только для main-сервера
|
||||||
- `backup` — backup каждые 6 часов → S3 (`visual-backup/data/`), только для main-сервера
|
|
||||||
|
|
||||||
**Шаблоны → файлы на сервере:**
|
**Шаблоны → файлы на сервере:**
|
||||||
- `roles/services/templates/docker-compose.yml.j2` → `/opt/services/docker-compose.yml`
|
- `roles/services/templates/docker-compose.yml.j2` → `/opt/services/docker-compose.yml`
|
||||||
|
|
@ -89,16 +82,11 @@ ansible-playbook playbooks/deploy.yml --tags backup
|
||||||
- `roles/services/templates/traefik/traefik.yml.j2` → `/opt/services/traefik/traefik.yml`
|
- `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`
|
- `roles/services/templates/traefik/dynamic/routes.yml.j2` → `/opt/services/traefik/dynamic/routes.yml`
|
||||||
|
|
||||||
**Добавление нового сервиса на main:**
|
**Добавление нового сервиса:**
|
||||||
1. Добавить контейнер в `docker-compose.yml.j2` в сеть `backend`
|
1. Добавить контейнер в `docker-compose.yml.j2` в сеть `backend`
|
||||||
2. Добавить роутер в `routes.yml.j2` (НЕ docker labels — используется file provider)
|
2. Добавить роутер в `routes.yml.j2` (НЕ docker labels — используется file provider)
|
||||||
3. Добавить домен в `inventory/group_vars/all/main.yml`
|
3. Добавить домен в `inventory/group_vars/all/main.yml`
|
||||||
4. Добавить DNS A-запись в Cloudflare
|
4. Добавить DNS A-запись в Cloudflare (через API или вручную)
|
||||||
|
|
||||||
**Добавление сервиса на 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`)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -107,6 +95,18 @@ ansible-playbook playbooks/deploy.yml --tags backup
|
||||||
Push в `master` → Forgejo Actions запускает:
|
Push в `master` → Forgejo Actions запускает:
|
||||||
```
|
```
|
||||||
ansible-playbook playbooks/deploy.yml
|
ansible-playbook playbooks/deploy.yml
|
||||||
ansible-playbook playbooks/tools.yml
|
|
||||||
```
|
```
|
||||||
Workflow: `.forgejo/workflows/deploy.yml`
|
Workflow: `.forgejo/workflows/deploy.yml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Домены (все на walava.io)
|
||||||
|
|
||||||
|
| Сервис | Домен |
|
||||||
|
|--------|-------|
|
||||||
|
| Forgejo | git.walava.io |
|
||||||
|
| Plane | hub.walava.io |
|
||||||
|
| Docmost | wiki.walava.io |
|
||||||
|
| n8n | auto.walava.io |
|
||||||
|
| Traefik dashboard | traefik.walava.io |
|
||||||
|
| Landing | walava.io |
|
||||||
|
|
|
||||||
|
|
@ -39,40 +39,6 @@
|
||||||
until: compose_result is succeeded
|
until: compose_result is succeeded
|
||||||
notify: Stack deployed
|
notify: Stack deployed
|
||||||
|
|
||||||
- name: Wait for MinIO to be ready
|
|
||||||
ansible.builtin.command: docker exec plane-minio curl -sf http://localhost:9000/minio/health/live
|
|
||||||
register: minio_ready
|
|
||||||
changed_when: false
|
|
||||||
retries: 15
|
|
||||||
delay: 10
|
|
||||||
until: minio_ready.rc == 0
|
|
||||||
|
|
||||||
- name: Get plane-internal network name
|
|
||||||
ansible.builtin.shell: >
|
|
||||||
docker inspect plane-minio |
|
|
||||||
python3 -c "import sys,json; d=json.load(sys.stdin)[0];
|
|
||||||
print([k for k in d['NetworkSettings']['Networks'] if 'plane-internal' in k][0])"
|
|
||||||
register: plane_internal_network
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Create MinIO uploads bucket via mc container
|
|
||||||
# minio/mc entrypoint = mc, поэтому нужен --entrypoint sh
|
|
||||||
# access-key = имя пользователя MinIO (plane-minio), secret-key = пароль
|
|
||||||
ansible.builtin.shell: |
|
|
||||||
docker run --rm \
|
|
||||||
--entrypoint sh \
|
|
||||||
--network "{{ plane_internal_network.stdout | trim }}" \
|
|
||||||
-e MC_ACCESS="{{ plane_minio_password }}" \
|
|
||||||
minio/mc:RELEASE.2025-05-21T01-59-54Z \
|
|
||||||
-c 'mc alias set local http://plane-minio:9000 plane-minio "{{ plane_minio_password }}" 2>/dev/null \
|
|
||||||
&& mc mb --ignore-existing local/uploads \
|
|
||||||
&& echo "Bucket created or already exists"'
|
|
||||||
register: minio_bucket
|
|
||||||
changed_when: "'Bucket created' in minio_bucket.stdout"
|
|
||||||
retries: 5
|
|
||||||
delay: 10
|
|
||||||
until: minio_bucket.rc == 0
|
|
||||||
|
|
||||||
# ── Forgejo Discord webhooks (deploys → #deploys channel) ────────────────────
|
# ── Forgejo Discord webhooks (deploys → #deploys channel) ────────────────────
|
||||||
- name: Check Discord webhooks on Forgejo repos
|
- name: Check Discord webhooks on Forgejo repos
|
||||||
ansible.builtin.uri:
|
ansible.builtin.uri:
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
# Outline env — generated by Ansible
|
|
||||||
NODE_ENV=production
|
|
||||||
SECRET_KEY={{ outline_secret_key }}
|
|
||||||
UTILS_SECRET={{ outline_utils_secret }}
|
|
||||||
|
|
||||||
# Database
|
|
||||||
DATABASE_URL=postgres://outline:{{ outline_db_password }}@outline-db:5432/outline
|
|
||||||
PGSSLMODE=disable
|
|
||||||
|
|
||||||
# Redis
|
|
||||||
REDIS_URL=redis://outline-redis:6379
|
|
||||||
|
|
||||||
# App URL
|
|
||||||
URL=https://{{ domain_wiki }}
|
|
||||||
PORT=3000
|
|
||||||
|
|
||||||
# S3 file storage (Timeweb Object Storage)
|
|
||||||
AWS_ACCESS_KEY_ID={{ s3_access_key }}
|
|
||||||
AWS_SECRET_ACCESS_KEY={{ s3_secret_key }}
|
|
||||||
AWS_REGION=ru-1
|
|
||||||
AWS_S3_UPLOAD_BUCKET_NAME=walava-outline
|
|
||||||
AWS_S3_UPLOAD_BUCKET_URL=https://s3.twcstorage.ru
|
|
||||||
AWS_S3_FORCE_PATH_STYLE=true
|
|
||||||
FILE_STORAGE=s3
|
|
||||||
|
|
||||||
# Auth
|
|
||||||
AUTH_PROVIDERS=email
|
|
||||||
|
|
||||||
# SMTP via Resend (direct — main server has outbound SMTP)
|
|
||||||
SMTP_HOST=smtp.resend.com
|
|
||||||
SMTP_PORT=587
|
|
||||||
SMTP_USERNAME=resend
|
|
||||||
SMTP_PASSWORD={{ resend_api_key }}
|
|
||||||
SMTP_FROM_EMAIL=noreply@{{ domain_base }}
|
|
||||||
SMTP_FROM_NAME=Visual Wiki
|
|
||||||
SMTP_SECURE=false
|
|
||||||
|
|
||||||
# Optional
|
|
||||||
DEFAULT_LANGUAGE=en_US
|
|
||||||
RATE_LIMITER_ENABLED=true
|
|
||||||
ENABLE_UPDATES=false
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# Generated by Ansible — do not edit manually
|
|
||||||
apiVersion: 1
|
|
||||||
|
|
||||||
providers:
|
|
||||||
- name: default
|
|
||||||
orgId: 1
|
|
||||||
folder: ""
|
|
||||||
type: file
|
|
||||||
disableDeletion: false
|
|
||||||
updateIntervalSeconds: 30
|
|
||||||
allowUiUpdates: false
|
|
||||||
options:
|
|
||||||
path: /etc/grafana/provisioning/dashboards/json
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# Generated by Ansible — do not edit manually
|
|
||||||
apiVersion: 1
|
|
||||||
|
|
||||||
datasources:
|
|
||||||
- name: Loki
|
|
||||||
type: loki
|
|
||||||
access: proxy
|
|
||||||
url: http://loki:3100
|
|
||||||
isDefault: false
|
|
||||||
editable: false
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# Generated by Ansible — do not edit manually
|
|
||||||
apiVersion: 1
|
|
||||||
|
|
||||||
datasources:
|
|
||||||
- name: Prometheus
|
|
||||||
type: prometheus
|
|
||||||
access: proxy
|
|
||||||
url: http://prometheus:9090
|
|
||||||
isDefault: true
|
|
||||||
editable: false
|
|
||||||
Loading…
Reference in a new issue