refactor: remove tools server, Vaultwarden, monitoring stack; rename plane→hub
Some checks failed
CI/CD / syntax-check (push) Successful in 1m30s
CI/CD / deploy (push) Failing after 6m8s

- Remove tools server entirely (roles/tools, playbooks/tools.yml, CI deploy step)
- Remove Vaultwarden (already absent from compose, clean up vars)
- Remove node-exporter, cadvisor, promtail from main stack
- Remove grafana/uptime-kuma Traefik routes (pointed to tools)
- Remove monitoring network from docker-compose
- Remove tools vault vars (grafana_admin_password, alertmanager telegram)
- Rename domain_plane: plane.walava.io → hub.walava.io
- Update CI workflow to only deploy main server
- Update STATUS.md and BACKLOG.md to reflect current state
This commit is contained in:
jack 2026-03-27 19:05:19 +07:00
parent 0a85e6fd2d
commit 44ccdf4882
31 changed files with 248 additions and 17798 deletions

View file

@ -1 +0,0 @@
{"sessionId":"7fb37d5d-263a-43f6-b0f8-390b858cbf0b","pid":44636,"acquiredAt":1774567037959}

View file

@ -30,8 +30,6 @@ jobs:
- name: Syntax check — main - name: Syntax check — main
run: ansible-playbook playbooks/deploy.yml --syntax-check run: ansible-playbook playbooks/deploy.yml --syntax-check
- name: Syntax check — tools
run: ansible-playbook playbooks/tools.yml --syntax-check
# ── Deploy (push to master only, after syntax-check passes) ──────────────── # ── Deploy (push to master only, after syntax-check passes) ────────────────
deploy: deploy:
@ -54,7 +52,6 @@ jobs:
chmod 600 ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519
# Scan host keys directly (no need for SSH_KNOWN_HOSTS secret) # Scan host keys directly (no need for SSH_KNOWN_HOSTS secret)
ssh-keyscan -p 22 87.249.49.32 >> ~/.ssh/known_hosts ssh-keyscan -p 22 87.249.49.32 >> ~/.ssh/known_hosts
ssh-keyscan -p 22 85.193.83.9 >> ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts
- name: Write vault password - name: Write vault password
@ -65,5 +62,3 @@ jobs:
- name: Deploy main server - name: Deploy main server
run: ansible-playbook playbooks/deploy.yml -l main run: ansible-playbook playbooks/deploy.yml -l main
- name: Deploy tools server
run: ansible-playbook playbooks/tools.yml -l tools

View file

@ -1,100 +1,66 @@
# Бэклог задач # Бэклог задач
> Задачи по приоритету. Обновляй этот файл при добавлении/завершении задач. > Задачи по приоритету. Обновляй этот файл при добавлении/завершении задач.
> Последнее обновление: 2026-03-23 > Последнее обновление: 2026-03-27
--- ---
## 🔴 Критично (сделать как можно скорее) ## 🔴 Критично
- [ ] **Настроить домен csrx.ru в SnappyMail** (admin панель → Domains) - [ ] **Обновить DNS: hub.walava.io**
IMAP: `mailserver`, порт 993, SSL Plane переименован с `plane.walava.io` на `hub.walava.io`.
SMTP: `mailserver`, порт 587, STARTTLS, с авторизацией В Cloudflare: добавить A-запись `hub` → 87.249.49.32, удалить старую `plane` (или оставить как алиас).
Без этого вход в mail.csrx.ru невозможен.
- [ ] **Бэкап tools-сервера**
Добавить скрипт для tools-сервера (роль backup не подключена к tools.yml):
- outline-db (PostgreSQL dump)
- n8n_data (Docker volume)
- mailserver/config (DKIM ключи, аккаунты)
- snappymail/data
- [ ] **plane-minio не бэкапится**
Вложения и файлы из Plane не входят в текущий бэкап. Нужен dump MinIO bucket `uploads`.
--- ---
## 🟡 Высокий приоритет ## 🟡 Высокий приоритет
- [ ] **Мониторинг tools-сервера** - [ ] **Собрать образ discord-bot**
Добавить node-exporter на tools-сервер и scrape-конфиг в Prometheus. Собрать и запушить `git.walava.io/jack/discord-bot:latest` в Forgejo registry.
После этого раскомментировать сервис в docker-compose.yml.j2.
- [ ] **mem_limit для plane-worker и plane-beat** - [ ] **Собрать образ walava-web**
Сейчас без ограничений памяти, риск OOM. Добавить `mem_limit: 256m`. Собрать и запушить `git.walava.io/jack/walava-web:latest` в Forgejo registry.
После этого раскомментировать сервис в docker-compose.yml.j2.
- [ ] **Проверить работу swap** - [ ] **Настроить UptimeRobot**
`roles/base/tasks/swap.yml` должен создавать 2GB swap. Проверить что он реально создан на сервере. Зарегистрироваться на uptimerobot.com, добавить мониторы:
- git.walava.io
- [ ] **Верификация бэкапов** - hub.walava.io
Добавить еженедельную проверку: скачать последний бэкап из S3, сделать test restore в Docker. - wiki.walava.io
- auto.walava.io
Настроить уведомления в Telegram/email.
--- ---
## 🟢 Обычный приоритет ## 🟢 Обычный приоритет
- [ ] **Верификация бэкапов**
Добавить еженедельную проверку: скачать последний бэкап из S3, сделать test restore в Docker.
- [ ] **Алерты на сбой бэкапа** - [ ] **Алерты на сбой бэкапа**
Если `backup-services` завершился с ошибкой — отправить алерт в Telegram. Если backup-services завершился с ошибкой — отправить уведомление в Discord.
- [ ] **Алерты на истечение TLS-сертификатов**
Добавить Prometheus правило: предупреждение за 7 дней до истечения сертификата.
- [ ] **Prometheus → tools-сервер**
Настроить federated scraping или remote_write для получения метрик tools-сервера.
- [ ] **Бакет S3 `visual-backup`**
Убедиться что бакет создан в Timeweb как "холодное хранилище" (тип: COLD).
---
## 📋 Бэклог (без срока)
- [ ] **Обновление образов** - [ ] **Обновление образов**
Регулярно проверять новые версии (образы запинены в `defaults/main.yml`): Регулярно проверять новые версии:
- Forgejo (сейчас `:9`) - Forgejo (сейчас `:9`)
- Traefik (сейчас `v3.3`) - Traefik (сейчас `v3.3`)
- Plane (сейчас `:stable`) - Plane (сейчас `:stable`)
- Authelia (сейчас `4.38`) - Docmost (сейчас `:latest`)
- n8n (сейчас `1.89.2`)
- [ ] **Автоматическое обновление Cloudflare IP-списков**
UFW разрешает только Cloudflare IPs. Список захардкожен — нужен cron для обновления.
- [ ] **Логи mail-сервера в Loki**
Добавить promtail pipeline для сбора логов mailserver с tools-сервера.
- [ ] **Двухфакторная аутентификация для n8n**
n8n сейчас доступен только с rate-limit middleware, без 2FA через Authelia.
--- ---
## ✅ Сделано ## ✅ Сделано
- [x] PTR-запись 85.193.83.9 → mx.csrx.ru (настроена в Timeweb, ожидает propagation 3-24ч)
- [x] DNS Cloudflare: MX→mx, SPF `-all`, DMARC `p=quarantine`, DKIM, autoconfig/autodiscover, A dash/mail/mx
- [x] Бэкап изменён с hourly на каждые 6 часов (00:00, 06:00, 12:00, 18:00)
- [x] Traefik с wildcard TLS через Cloudflare DNS-01 - [x] Traefik с wildcard TLS через Cloudflare DNS-01
- [x] Vaultwarden (менеджер паролей)
- [x] Forgejo + CI/CD через Forgejo Actions - [x] Forgejo + CI/CD через Forgejo Actions
- [x] Plane (управление проектами) - [x] Plane (управление проектами)
- [x] Outline wiki с email magic link авторизацией - [x] Docmost wiki (заменил Outline)
- [x] n8n автоматизация - [x] n8n автоматизация
- [x] docker-mailserver (Postfix + Dovecot), аккаунты: noreply, admin, jack
- [x] SnappyMail вебмейл на mail.csrx.ru
- [x] docker-mailserver на mx.csrx.ru (было mail.csrx.ru)
- [x] Certbot авторотация сертификата (cron 2x/день + deploy-hook)
- [x] DMARC p=quarantine, SPF -all, DKIM
- [x] Мониторинг (Prometheus + Grafana + Loki + AlertManager)
- [x] CrowdSec IDS + fail2ban - [x] CrowdSec IDS + fail2ban
- [x] Authelia 2FA SSO - [x] Бэкап каждые 6 часов → S3
- [x] Uptime Kuma статус-страница
- [x] Удаление Syncthing - [x] Удаление Syncthing
- [x] cloudflare_zone_id перенесён в vault - [x] Удаление Vaultwarden
- [x] Удаление tools-сервера (Grafana/Prometheus/Loki/AlertManager/Uptime Kuma)
- [x] Переезд с csrx.ru на walava.io

View file

@ -9,40 +9,30 @@
| Сервер | IP | Роль | Состояние | | Сервер | IP | Роль | Состояние |
|--------|----|------|-----------| |--------|----|------|-----------|
| **main** | 87.249.49.32 | Все продуктовые сервисы + мониторинг | ✅ Работает | | **main** | 87.249.49.32 | Все продуктовые сервисы | ✅ Работает |
| **tools** | 85.193.83.9 | Вспомогательные сервисы (пусто, ожидает мониторинг) | ✅ Работает |
> mon (188.225.79.34) — планируется к отключению.
--- ---
## Сервисы ## Сервисы (main, 87.249.49.32)
### Основной сервер (main, 87.249.49.32)
| Сервис | Домен | Статус | Заметки | | Сервис | Домен | Статус | Заметки |
|--------|-------|--------|---------| |--------|-------|--------|---------|
| Traefik | — | ✅ | Реверс-прокси, TLS wildcard `*.walava.io` через Cloudflare DNS-01 | | Traefik | — | ✅ | Реверс-прокси, TLS wildcard `*.walava.io` через Cloudflare DNS-01 |
| Vaultwarden | vault.walava.io | ✅ | Менеджер паролей |
| Forgejo | git.walava.io | ✅ | Git-сервер, SSH на порту 2222 | | Forgejo | git.walava.io | ✅ | Git-сервер, SSH на порту 2222 |
| Forgejo Actions | — | ✅ | CI/CD runner, деплой через push в master | | Forgejo Actions | — | ✅ | CI/CD runner, деплой через push в master |
| Plane | plane.walava.io | ✅ | Управление проектами | | Plane | hub.walava.io | ✅ | Управление проектами |
| Outline Wiki | wiki.walava.io | 🔄 Переезд (CI в процессе) | SMTP: Resend через walava.io | | Docmost | wiki.walava.io | ✅ | Wiki. S3: walava-docmost |
| n8n | auto.walava.io | 🔄 Переезд (CI в процессе) | Workflow автоматизация | | n8n | auto.walava.io | ✅ | Workflow автоматизация |
| outline-mcp | — | 🔄 Переезд | MCP сервер для Claude |
| discord-bot | — | ✅ | Деплой-нотификации в Discord |
| walava-web | walava.io | ✅ | Лендинг (заглушка) |
| Grafana | dash.walava.io | ✅ | Дашборды мониторинга |
| Prometheus | — | ✅ | Сбор метрик, 30 дней хранения |
| Loki + Promtail | — | ✅ | Сбор логов |
| AlertManager | — | ✅ | Алерты в Telegram |
| CrowdSec | — | ✅ | IDS, банит злоумышленников | | CrowdSec | — | ✅ | IDS, банит злоумышленников |
| Uptime Kuma | status.walava.io | ✅ | Публичная страница статуса | | discord-bot | — | ⏳ Ожидает образ | Нужно собрать и запушить в Forgejo registry |
| Бэкап | — | ✅ | Каждые 6 часов → S3 `walava-backup/data/`, 7 дней | | walava-web | walava.io | ⏳ Ожидает образ | Нужно собрать и запушить в Forgejo registry |
### Tools-сервер (tools, 85.193.83.9) ---
Outline и n8n **переехали на main**. Сервер ожидает переноса мониторинга. ## Мониторинг
Используется **UptimeRobot** (внешний, бесплатный) для проверки доступности сервисов.
Grafana/Prometheus/Loki/AlertManager/Uptime Kuma удалены — tools-сервер упразднён.
--- ---
@ -51,27 +41,28 @@ Outline и n8n **переехали на main**. Сервер ожидает п
Используется **Resend** (resend.com) для исходящей почты. Используется **Resend** (resend.com) для исходящей почты.
- Домен `walava.io` верифицирован в Resend - Домен `walava.io` верифицирован в Resend
- Отправитель: `noreply@walava.io` - Отправитель: `noreply@walava.io`
- Outline шлёт magic link напрямую через `smtp.resend.com:587` - Docmost шлёт инвайты/magic links через `smtp.resend.com:587`
- API ключ: в vault как `vault_resend_api_key` - API ключ: в vault как `vault_resend_api_key`
**Входящая почта не настроена** (нет MX, не нужна). **Входящая почта не настроена** (нет MX, не нужна).
--- ---
## S3 (Timeweb Object Storage) ## S3 (Timeweb Object Storage, endpoint: s3.twcstorage.ru)
| Bucket | Назначение | | Bucket | Назначение |
|--------|-----------| |--------|-----------|
| `walava-backup` | Бэкапы (каждые 6 часов, 7 дней хранения) | | `walava-backup` | Бэкапы (каждые 6 часов, 7 дней хранения) |
| `walava-outline` | Файлы Outline (вложения, изображения) | | `walava-docmost` | Файлы Docmost (вложения, изображения) |
--- ---
## CI/CD ## CI/CD
- Репозиторий: `git.walava.io/jack/infra` - Репозиторий: `git.walava.io/jack/infra`
- Триггер: push в `master` запускает `ansible-playbook playbooks/deploy.yml` + `playbooks/tools.yml` - Триггер: push в `master` запускает `ansible-playbook playbooks/deploy.yml`
- Runner: `act_runner` на main-сервере - Runner: `act_runner` на main-сервере
- SSH ключ: `ci_deploy_pubkey` в `main.yml`, приватный ключ в Forgejo secret `SSH_PRIVATE_KEY`
- **Правило**: все изменения только через git, никаких ручных правок на сервере - **Правило**: все изменения только через git, никаких ручных правок на сервере
--- ---
@ -84,35 +75,30 @@ Outline и n8n **переехали на main**. Сервер ожидает п
| Forgejo data | tar volume | | Forgejo data | tar volume |
| Plane DB | pg_dump → gzip | | Plane DB | pg_dump → gzip |
| Plane MinIO | tar volume | | Plane MinIO | tar volume |
| Outline DB | pg_dump → gzip | | Docmost DB | pg_dump → gzip |
| n8n workflows | tar volume | | n8n workflows | tar volume |
| Vaultwarden | tar volume |
| Uptime Kuma | tar volume |
| Traefik acme.json | в составе volumes |
Расписание: 00:00, 06:00, 12:00, 18:00 UTC. Хранение: 7 дней. Расписание: 00:00, 06:00, 12:00, 18:00 UTC. Хранение: 7 дней.
--- ---
## Сети Docker
- `proxy` — публичная, только для Traefik (ACME + исходящий интернет)
- `backend` — internal, Traefik ↔ сервисы
- `forgejo-db` — internal, Forgejo ↔ PostgreSQL
- `forgejo-ssh` — публичная, для SSH-клиентов
- `plane-internal` — internal, все компоненты Plane
- `runner-jobs` — публичная, для job-контейнеров CI/CD
- `docmost-internal` — internal, Docmost ↔ DB ↔ Redis
- `n8n-internal` — internal, n8n изоляция
---
## Известные проблемы / TODO ## Известные проблемы / TODO
| Проблема | Статус | | Проблема | Статус |
|----------|--------| |----------|--------|
| Outline + n8n переезд на main | 🔄 CI задеплоен, ожидаем старт контейнеров | | discord-bot без образа | ⏳ Собрать и запушить `git.walava.io/jack/discord-bot:latest` |
| Authelia всё ещё запущена | ⚠️ Нужно удалить после деплоя (remove_orphans уберёт) | | walava-web без образа | ⏳ Собрать и запушить `git.walava.io/jack/walava-web:latest` |
| Мониторинг переезд на tools | ⏳ Следующий шаг | | DNS: hub.walava.io | ⚠️ Обновить A-запись в Cloudflare (было plane.walava.io) |
| Отключить mon-сервер | ⏳ После переноса мониторинга |
---
## Сети Docker (main)
- `proxy` — публичная, только для Traefik (нужна для ACME)
- `backend` — internal, Traefik ↔ сервисы
- `forgejo-db` — internal, Forgejo ↔ PostgreSQL
- `forgejo-ssh` — публичная, для SSH-клиентов
- `plane-internal` — internal, все компоненты Plane
- `runner-jobs` — публичная, для job-контейнеров CI/CD
- `monitoring` — internal, стек мониторинга
- `outline-internal` — internal, Outline ↔ DB ↔ Redis
- `n8n-internal` — internal, n8n изоляция

View file

@ -4,11 +4,8 @@ domain_base: "walava.io"
# Derived domains # Derived domains
domain_git: "git.{{ domain_base }}" domain_git: "git.{{ domain_base }}"
domain_plane: "plane.{{ domain_base }}" domain_plane: "hub.{{ domain_base }}"
domain_traefik: "traefik.{{ domain_base }}" domain_traefik: "traefik.{{ domain_base }}"
domain_dashboard: "dash.{{ domain_base }}"
domain_auth: "auth.{{ domain_base }}"
domain_status: "status.{{ domain_base }}"
domain_wiki: "wiki.{{ domain_base }}" domain_wiki: "wiki.{{ domain_base }}"
domain_n8n: "auto.{{ domain_base }}" domain_n8n: "auto.{{ domain_base }}"
domain_landing: "{{ domain_base }}" domain_landing: "{{ domain_base }}"
@ -26,9 +23,6 @@ plane_secret_key: "{{ vault_plane_secret_key }}"
plane_minio_password: "{{ vault_plane_minio_password }}" plane_minio_password: "{{ vault_plane_minio_password }}"
traefik_dashboard_htpasswd: "{{ vault_traefik_dashboard_htpasswd }}" traefik_dashboard_htpasswd: "{{ vault_traefik_dashboard_htpasswd }}"
forgejo_runner_token: "{{ vault_forgejo_runner_token }}" forgejo_runner_token: "{{ vault_forgejo_runner_token }}"
grafana_admin_password: "{{ vault_grafana_admin_password }}"
alertmanager_telegram_token: "{{ vault_alertmanager_telegram_token }}"
alertmanager_telegram_chat_id: "{{ vault_alertmanager_telegram_chat_id }}"
crowdsec_bouncer_key: "{{ vault_crowdsec_bouncer_key }}" crowdsec_bouncer_key: "{{ vault_crowdsec_bouncer_key }}"
s3_access_key: "{{ vault_s3_access_key }}" s3_access_key: "{{ vault_s3_access_key }}"
s3_secret_key: "{{ vault_s3_secret_key }}" s3_secret_key: "{{ vault_s3_secret_key }}"
@ -48,9 +42,7 @@ discord_bot_app_id: "{{ vault_discord_bot_app_id }}"
discord_bot_public_key: "{{ vault_discord_bot_public_key }}" discord_bot_public_key: "{{ vault_discord_bot_public_key }}"
timeweb_token: "{{ vault_timeweb_token }}" timeweb_token: "{{ vault_timeweb_token }}"
# Server IPs (used for cross-server Traefik routing)
ip_main: "87.249.49.32" ip_main: "87.249.49.32"
ip_tools: "85.193.83.9"
# CI/CD deploy key (public key — not a secret) # CI/CD deploy key (public key — not a secret)
ci_deploy_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQSKgqMTT7uGo423Nrb94PgQ8cu2IiH96JOrIKhlvm/ ci-deploy@forgejo-runner" ci_deploy_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILQSKgqMTT7uGo423Nrb94PgQ8cu2IiH96JOrIKhlvm/ ci-deploy@forgejo-runner"

View file

@ -1,190 +1,181 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
34363131346366626337653162663033323865323130636637353265613034383739303463646531 36633364396561303333666464303364636135333533356136613233653230626239353935356135
3333363364363231363438393761343239626538333062620a303233636130376135306666316437 3938613863303862333531333832613834383330316666370a613833633230383661376661303435
64393437663837656430383565666337653730393262303036333039626535623134383537373836 36373864356135316238373733386536376539323365306161643330613233313230616233336565
3165643836376665300a356539623533313065316463303963656638323165656337653833633130 3838383831643930660a343733356362633661633535663561643661336231386363383437646632
39396639373862323234643362356566393765306366383631316638623931623536646561333965 65356462323933643161313935663463396461383438346530623663323463653037313537313933
33313463376462343063383435393138333236336137363230393462613466366361383761353834 66633233653434353237633036386537643866623631616232346165396231643837626536383563
65666364646164323131313334396164616161386331386364373231363563323835383432346438 34396338386533393731656439633031613065386662633437643937373565663930343933356137
37366664636661343662396231653664383433323533643266323131393363326436643331363831 32623936646261636363653562636338366531633635323330613436643462376665366165313261
66323532623236633337623366343436373731323635376433386433613737303763653563363332 33663564643330363838353564343837643230663433613165616633373563623430653963623734
31313165323364633230386661666135346635633239636363356466666464376236643532643530 30323130353431666666316232633366643532373161383939323638663761393831303666666538
31386264303066646133313836356465363938386565383763303132633961636537303431656231 63356337393064626339653935653762646638376161356139626562643463306234643262303366
36313037666135393733663434353361343630663464346664303261643439373135636436333066 38626461306634366463623866613935303137376334333364613866366364656530383630613864
66343933663466366466633838363438386161353239373165376337373366336231333435306636 30626234306530386133353861663737373462333331363566646433613939313961656336383733
62313762373330343031333064363030373066316662336432306236623439633331663935656432 33323232386633353866636663623230393065663333363539326462336132396234366536353533
33313064323631346363303930333461613963643464363662363830343064303337643238653435 38623164616466396164303138333335633664323861343139663530346262303666643833336132
35643338333134383936303637316232303330626263333434343764366433386139666266616166 64353432646463353861623630326330316432613835376462306262626434343539303263376439
35336131346462336631633432623662633730656662303265396633613333326135353537343965 62343536306236663761313865313236326163663665336135336639633835623738396363396236
37316634376133383632366533626631623134373066653633643266623739623036643238363966 61653639663436353932373561613566633831633139616137306232313261333663326432376333
36353236333161356531326161323433303265336533353539333030303737303837653237376438 39663433643237313338306162663530623861623736373662346136626562383436383439626264
36303562386137646133613864336230306635356233363737313632663963343432386434356237 63333565613531636234643565356339663938303332366233326463306439316564643631643962
62356664623239663562656538386134323563376637323934633535643865643139323166623166 30346230356532353064633364326236323762343261396238383235376431333962613030363439
64356262666464643638626236343439643361366461646131363063613831653337393966383065 31313934373264316162316438613431343131643134613731396566656666656364643766346232
37353063666264343831323861363531646437346438396566343061326236373236346265333237 63333463613661623565323034313464303630323238326363323866643964353932326463633066
65613461393864643539663434316666663235616362363535383334623862323839653666663865 30373435643061376135326339343762366636363032343162653465316132633934636564633231
36383237386464336661616630623535646465623463653939356234363034623038353662396566 64616564373232666366336632666534373430353962383536306230663266333766336435613631
63396435326538663137356338346337323364666136386433663338376562313430373039336333 63643866376264363534656563306461393536666437316135313836343764613431633634623461
61383063613065386132326334663765396535386363623734393130393335393666613265616232 35653439336266323466383432656461636539306432626332613638353264663936666633306331
38336439666166303037353436343063303034323830636135316535386433623031306563353736 35636238366362366238396366396332356433393635613433363665376631393964326430303539
61653733303864383663326664643761326665343363373338333266356464623430393262636465 34373966626134306237346261323234303362383430323738343839616639623265343532353332
62333931643433363262323831646135643237313535303638393763323463386165346335353333 62636338613730353537343463316531343565313861353336393264656361613036366238393735
31613236623739386661376130633736623937333733626163363962303134396231353835343233 36643138343864343233663564303832313064323631326238376438313365616365323765343464
63653533633330333964363839363062323866653236356532636137626236336636623630323036 36356636323437386537623436373230333762656334626330343433363331313835323430646237
39656365306162643535303661396336386265306634363832313764373264636164653966633731 39316464613238656665323561633737616462343531313739353434663734643165396131663363
38313032393164303833363964666238303339313933373262656435396162323462313561623938 36343763363738646131663236366262393834653230666332303031626365323438326332343631
38393230333961643533633264323165356162353738636662326561636535383534373666396334 31313533313562333932626136383033663935326632356334306162343039643562383665376664
63663565343938643035633337633931353333303630323339323533383862363230626533363062 34333636356634313933376238633166323762653132623338653934333231303462376534363833
35656133336532623838383061653737313932656664626630616662626363663432323665363933 64393364613566343236346464303138346365636562356339626134346631633032646631376234
37353130646231343134653834313966383435363532353039393463323536303232396437643161 61303261313335353764646564333334616263666439663339646230353162323533626231613062
35393039656462373436663334353939666163383861336139353263663437363837623664353161 61386162333564613432353231383265366262393764666139623230333135336634633938356236
62346661646463616233653164383638313834626534636638646139653032643935353665653163 32366161643530643563363534386563383338343538326433383436653966636332316139353539
64353733313932656139383030633437333632326261666363626263636438343537636134393961 65636334336531366561666466333038393831393439373365666164373739343933656561303538
66303366376433663737653164616561373938623039383238363264623431633033636466613233 34353436313836656662346435353538376565313765646465613464396164653766343165636533
63343463326264363263643861306561323237633837393233313263386438646136323934636262 31323563333332313833316161306534643664333934303136623961643837376435316233316362
63383531303030643939326134363634646539376530656335316130613963653131633962336638 65623536666466666432643466636566363437383532663133363030363338643331656666323764
30623633666663643762306461356138626634613665306638666135623561666434313539323766 38323733613138303461396330396164623132633536666539643334613163633734646137336666
65623562393734353536306334613430636661333865386238366265663366336239356231626535 61356464356639353035353131303333353532663861633633626536623963613432393366326463
33353837366234666264346137343431386461363162323031313263373533356234393834323535 62323963626261653333383031333766336535366539653036626265626463333763346435656234
65313365363631616365303166343262613139303239363839353638373736363364356535393932 37303833373863623762323062336563323533383437306337663733353730313736633166633033
38336633353732653733323234333263666266303261643836616236363432363937613530646362 31326664386633316437356131633434383161346664306432663034386464623630633366616231
37383234393337613463653537333031343338303465333335666632393630623165383031313535 35373437623630613165646562633562386135376261663762646234303365396661623330313038
38373231633238613331383834333437323962666665333231326539633930356266616636373961 64353263323331323961353031376566643162633334333865393164636132366465356336393836
65336161303236393639653765373834323732666535623330316636346335393064663836343537 39313634363734663935393938353539623165333165373938366333303362316364313466323130
66366336633134653464646137363562376263383662626336323434343330616230323538316439 63353630383333326461663838636534393337666630613333393839363433373035333862616633
63336165396431663037323333316366623537623331626130303633383063646438633931626266 31333538653464396265623663343436353532613334356362373936326364336432393465663239
34356264353732383039363061643733353363366136393964323262633565333862373962393939 35653036616363623333353664646165623137386365326134643733383832373363303737366431
66623966663839306235393765623033636336353639356366306365633637386638316538356333 64383065396362346262636334346236353466396434626365383439386134633439616561383136
35336334383662346234666238633465383765366537623133616465343863626165303465313063 65373534313638326132306134386337623465346162396239643733626238666439623562326637
30353337636432623966656563633332393032323237353336393338613164623831616137396533 30363461613462663931316537323930353337353936633436343035383833333362653666653330
39386631623166663039306262333030623033643832636433353263663636386233386266373732 66616331643235663038323736303231383337373037613361646562653830326238396639383532
61646437303664383434653965353634643365363664336661363863363339383734316262663865 34613762373566313962303537613035633961636138623936336635386331653135633338376533
35303765643536323263323166663061326339396465386134623230383730353539383965356131 31323162323530326562376234373262633734316135303132336236343762353932626330616162
66636534653136323262383166623262346632633231656530653032336136626439373263393933 65396337653163613834353161356530613938323532363133363839386463633161653231313965
33616366393466383462663737613463346561343065333432343962366532373133396462383033 30356361323036313163623962623335393864396136313462616266353330313937376533666136
33666533356239343161313734343234373139653235346130633865646362366433656463646337 65656262356266393765383934383166636262663035666332313431666534626538666638623961
32366265643434383366306364346236393935376263356632346265613032393563646432313734 31623639623261653861353231343536613135613637316237346339383333376134643464636639
31366134643731616366393164353230323138323138303066396235376366663031336466646234 33623937663139366363653266373135336266396262663864623430333764383363393435333135
30386261616530343631303563613530346437623966313933626332663138393732336138353932 36616139346538643434636233633331643535326334393231353338643333626264313632613230
30326531366134663665616432316138383639363766613661633238323165613039396537626433 30623233393835386136663835303634393236366137383238666233636663363965323131386266
37636635646463316636643764306139666264633534666361616538343838373135323161383130 37326439646165613264396631363431313234646538363531326232386266323335383665333062
62653664336662646330666565333632316266643737616436613130373430323935643162366531 66393461363465386330306430613764623462373235616633373134393161666165306636396430
33373061396533316266303334636432663161613635343030373166386463313235633965356161 35396634363132373761306463646535333662393266653334323864633836373336303334336630
63306335376636346238376535613761613539326535303761333863373362383366353936626632 65653636376532623938356666656363616161353562303139386661326136313333386434363931
33383730363162653839623931313936616436633564653835303836663830336337663737353434 63656334373335323133343661353266306239653234333964346139356461623638363566346166
66363964373864306465656366343638386362653836663931653238643136383762326461386366 35633764333764333662333138623439383663353662373465633937376664363130616532326466
36383335393130356666336338346534326432366630633931393934323836653963646132623263 34633734356365636633636561626363396238653739393635656666663530396363373463386630
36346636353334383165323461346536383962303263633438366661656565356539653339316236 30343666393762343763663562333335366436616463343438313932356462363066633535306137
32383163636666346331356435666133646363326539346262393234323863663332623438663336 38393766663534326561646635663333313636653430653239396631343934323639313336373437
65393037333162343334386437646562653735653366393636333338313035373562333731303965 36373966336232323664353330626131633437373937633961323232636166363461636639646539
61313664363861666630336237363037393333643038663537666135363866336432373266656661 66393530663063613834663738333238386631376138363863366533396135613465626639313836
64323065303430653138663330373731616362373433613939343365353065646663613837303265 65646131306535633335353937353362366533343561383539316266373637663065363734363662
33376436653334333762346664613532343765366132356234616566636166336165383339633563 35613437653232356236626337653930316130303933396563613737653765613030643436343534
65393235383135656132343866633866626336666663333230616263383862653539393731666665 63623966356364646463383064626466643337653730616666333066663031653233616537363732
65356537396438333031313835333865613465626236396339313433396537343964623234663033 32336531363830653032663639323662643663633731666634353365653766353538303634633532
37636165636137346432616666653333383162633932363238626238613361623932363632383363 35643363366634623764343766646233343732333535326335323931353939313961623361643336
39316238393939363637633333396137346463393363666236323561323764323065376136336439 62383262383438343761356436303637336262326637386137646436373536383139393033366638
65343534663538616565613130636435643132316437386538343531663130626162623435633834 63386465616661363337633232653531323137373237366663653861373131376162363365623138
37643766356335356535353363386465303963323465313765306334633066356538396464313735 30616435343466653438613863353164633464396435353461336261376661313762336337653963
66313062363739353865336631613935366465373832613461633530316437366235666266313134 61376339643165393539386465633737636236623066363364303863663634643963633139643564
35373730303230306330626630653637333964366130366230363864653662656662346365323739 36653261646462616462626634646262373638323162373736393463323063646237653266373962
63636539306561326131383139306136653833383461363833343034323234623463653462363039 34316432313338363231346235386134333334353733666337323335633330633962323930656637
61363332366237613962356530626165373731343136373032636235353633653130663061343666 30643031383338396338636566613036383031303331313664356165393433393635323333666533
63643339383635303233363435306466326135636539373862396365643232323139656261633030 62653964636265326133333339643433663362376337383533373939386465363438663239313566
39316235346561663439373361626665383030333562623562316665346262376363663830663737 30636463316132623631393135656439643264613830633134386135383931653761313666393938
37386135386535363863353638383035303933333336336234306166386236303339366666663066 64613130616361306663353038386337373033383330336564356332353530636233613635343063
38336330363235616230333438313433323034343863633139326139373436393531373963636636 63393264386234663135333533626162386335353463646535613361653764363165303230386262
61393439346539383661386236613262616366353366373033333365353235383861303735303330 34386261326639636461653035346239663861303662303865373032313361386262366636343037
35393138666232653364643539316333393464626361386630396631663330303561356336353334 34313738376335663734393062666336346665393961343634366237633765386430653063623834
39303063643261633361333137303837336433393363316364633534393064636634303231383339 63333265356664393337663138303466653833343664363262316565653933653039666561393138
37333235666137306438343233663566323931376437663730383938383163613732326130633038 39623366393437316261376436646630623662343933653930653766326461306266646430653761
63626635353665303265316264613263666365363331613231623132383237396663316465663562 36373337613765373438326339356161353661386335363039656430363563616563383832353863
35623563393239333866663433326337326365653030346137363464313632393865393932636637 36613634663063343934623533313337353635393535393530336636386138323330373235663139
34643133366132343130353330366261363031346336663233393132316432376132313361666637 34396538623838363564386132636361386266663762363163616331383938323139613132333263
31643634623435636134383139656131626361663263383762643131356430616632343633313064 62373037316434376531636661646366326163323735373966386133306539383533373161646139
31656365326361336133326462656161666139383630366266383265656239383432653530363930 32623866633434343363623866376232333434653561653664666661343936333932396664366634
34306638306266326361306134656535646266376261386632393763666536383533333530616236 35346234313830353165336437363365376436376431356538303038366466356366393661303835
64643362666335636335303030646437386563313137323630653563633362376165383935396164 35336231643934613739666461656332663530396437313262376138333734613932346436316635
61623765396463323063363931626162303662626563303937373035656138386639383436373135 38326335323531356164666232396633623331646530353166656432373336663035613832396438
64313730653530656562656562343664396234323638633732333031613035663961343663653166 37663030643964633861613337383931636238623864636363336631666539376237306564653930
66653030633435663766663066373635626537316464343766653435313835633861663637323035 34383536363363323937356666353931346562303035396539393038323830666337363664313137
32343932353961386636333230303166666533636336333632316661613939323961393235643436 37326331346139393533643530303231316432356333613063363666653832316431303735363464
38356633646633336261363338663836616237616634636336633631616166633962636338383639 62623130653566646235653436386433666263323561363732343764396439356363643336326137
64383837363634666135653066336363353037316230366639363930663239373232306264386539 61313833353066316138616365623332616564366435363561363864616366336636636563306234
62393861333230333663646138393439613536353461623164626462396363613838623332353530 62626566363663333761393563343037323936323530303930666364626661383965323135383330
64303637613530613736346135626139653861636637373833333766396331323738346334353164 33323339643234653563373661646430313462616634363431633436386334316333353263656636
38313533663230643766313339363233383338616130306334316136343134646339353332303130 34343061363233646238646563623237303231636632336462386565653533313330383362643235
30353861336562613166653431666562326530353162633036346265393439326231313261303866 31303939653664663531626566653439363331616661646231326232306238306663366332396466
36346162643231383962326365383739623936636536396631663639623165363232303638653436 38623834383339346533393664323561396137376539643135383138386630643737623739313964
38623032323739316134653232633262336332343037316161353938343237623238623165313534 33663839336366366537356561646335643236633832663630626337653138623830646661383635
64623430333233353738383763303030363965373137363732343531346665633738353639613165 39646438356533386239336234643065393338316664666435666330633765353633656133626239
32663734303666643365646364353535386265613531613733643732653537393231396230623765 34323962656238363731656161393530643662366337653939366435393738653832613031386230
35616235646232393765343062636639626564393934383462323138376633383032663635643335 32306134623164616365353735386434613739343265303031386163626135326332326666346138
30396534386139663431353935333765366362383539633131653835333933323937643564343166 65656239386332336637646464383530633137386363396531336464366465663036663331653230
64356262633933396637616563383063363666396437306263616233623066343265303138336330 65633464663234353765666337346537363639633833323239373264643837386533393131613165
38336464336663373539343332663562336638656437643063323435373334353030653132653932 30643138656666666639336637393631343464316536663539366333666535306566616362336364
65386232383466363830613030363233373430373636643763633430653233333939333131653665 37663934373462346231353434653632646435373934643831616636306438363363643266663933
30643437643731326435393631303835666138356564393662653165363238376165383532633130 31633364653364363061653566366336333264623238383130313738303837303163316639616361
37333565373330343631366333386636376166323864343334376530656331643831303063326138 65623736653133373266383735363930393263343161343966613233353030316336306238353831
65346263633039363630616538373932373031303363356339623036386630383838373037323536 34356432313563393635633235316238643638623437643135643262376533383463666138653539
37643965326564643435303137323665363735643730393136373439373564306632376166363864 36393130643663646333323365303733303764396330313236353836376366353364316130643036
33346132313331636230386135306465303338303162333465303533306335363638613766373139 38363734353363303262623638656663343037633135653333373265346637363835663936323836
36353737353835313435383439363162363234383864643661313466643262326136363332656666 39376235313962633632353366616531393365376662373265313433666364346532653834636535
61386432653733613632323530353939656632396166373361363061366531303231333036323161 39396531656266376635323833636530353761616362643064343130303833356339613863646234
62636535313439656531373163376563303231616534306238613966653333306233383265633134 32346365323162646561653638666236346166623165323031633961653635613062623631653731
36366266326361636635663037393563353231613362383561333062623731633361636561396335 64613265666236626466373635376565313533616431313963666135376637336633613663383965
62316362373232336531653432613732393938626562646132383232396438643539633731323930 66343231363738656164633164343139303166633362363464386235333437643262646634643063
63306563396132393932343037616566323338656234326537326539623861623065343237653766 64393364333936386565656465653236313062643035663565643537666138393938316565306136
37633230396430343063303565363034393332653261306431636134623764646361396238633364 35346539623539323866653632323136343535626634313633643135336664663166363639313333
31323732363432316134656664333232333838333130373065656633633235653832643061633133 62363866323833313162366466323130666366343534376462636431396433373035643662366236
36373835636536383964663039393838623932646237643966303436343361633732366162613836 61393730366332373666383837613534636166643761323334636430383531333362373632623833
65393930346435376330646337383631626632666638623536393363646335343035613832303732 35626566383231643938386565613461343564313863336337306264323863353362316265393266
62323562653732333830333039646466326531613230336536623864303935346330346331363338 39336462653464386432646137396633653931616565336139383632386133633135623833316666
63626237316633333963303861613366643465316435643364653631333662386331653461653238 36336639666134386636343730383962383564336333646239626532343663666338363031323034
34383335616438613363623737376130306631636230613637303631666339626431313666376530 30396635366563613164363332393933633334616261326533343461323862306539393939353539
38336664666330353636383565653162363735316566333362356261653264303866366462626235 30313832646432366431396566656266363139343861363962626664353762303533306664346162
65613563363634393739633035303230396537366161623832636364356363353261663362376234 31366337376363343762376333386437613330393665383861393465663761613939663039373165
66326164653066396434383534326639346634306138396464393666396363653161613461386631 32323964636462336336643436616563363533613738346230666566643339656630326639386566
63303938393837613136393133316466336634656536333931343839303366666664666162313236 31303638393162306434376238613933316230376334393838336139323762623532366136626663
31663632623633626637373839316537316166323633313063353436663466386535316462653338 65373930353862383633646335363763643637393335643966396464333630356663333832333330
39383734616133633064663631346364613436383634393934643633346231343236643035326237 35346236353337373732653466636364623931323863323439643962643034373765663636616666
62336432323064656633353633326539316638653036363665376263383965656333383533616366 65393632316138343131303030626231653164623661633662663732616336303137326231343334
38646433386636383865343162353633636533333464333564323365373461373665643136663664 36646535356236336537383637393864643566363438366163656134353931666464376332363933
32366366373133613532306434363436643337373235656362623265653435643634613533653236 62623362323539346336643266303035616333366666373437346132343734663763626233663666
36326234666134623165313964313038313863316433373261306138666231396632646630616532 61623061306336373165633365363335383838653534373434323132653465313838366239363338
62613334383230363532333137333933306336656166643831666535663838656363623962663739 62343765336266303661313635623237666263323938636335316133376134303539653661633637
31303533346631323365336431373738393837353239373031376134623464343561333261323763 62326232326235646365643037656138343930653233393833653565306636393063613830336235
38343861313437646539653033636137363036356564363963363037323533393535363231343566 62656132363566396665636633326538336339353638336538363630666662333362376564366136
31353065613731366163303062343131383531303635333266376339393237366662343532363537 61653537653238626538666664303963643463653234316662336162613831376231333038313964
32393066333962313835623165376531313532656264303964353062383537623966613562633039 65656330303936313339336464353433353532613363633432393630303337663765336432643466
39643239343336356130613666626433323938343937373564303738376430313534323632356232 31623437353431666338663036336530313638663862653261326561353864376562666361643230
39336432373161383663313534323237626466346164303862313931356663373432303738343931 63656665653862353534376364653266363032316236373161343934353765623334396331383638
66376465666564616235383339663263393733363066626663646532366165336235323934373732 38613030613830633662373865653036623331356131346464646639663732333135326638656163
66313138623331373239323839373735343162323439656633303233333464613662303833633133 33646263366462616531343066616637346562373533316561646535336164323332653631303232
66663233306537643239636564626564613231636664376133313930636261656438383931376230 63323631383032623466643638363364646136633936366366336530616232326339313036633037
64663138346136383265363938393532636438363333653332373235313638373730623032653064 37643536636264316537386666663663306161666166656662643531633766373839646465393933
34366139303865663338363862313032326635646130376364333565623238616537316236343364 63623933336135383931613539633066656665313733323065613937303366653031343837653037
61363762393661656639393632663064303731373030393538323031313166663232616538376163 30356331396532613935303736343565306430643663393037653932343465326636646664306462
39396363303066646263383733306236616663383066373532363664376137393566323866303836 64336336313737613337373763623562643532373533396435633739303161613433316465643238
39636362396335303938393836633632346264383930363365376430323661396537393261613834 34613733363939653963353165313331326537396336633833306130396266313139356330636132
31636262623235343338303466303733313337303132616130653937356464663738393930656466 64383536646566393530663430376331663630363366313962343433326662616238346234343761
35393831396331396463376461373066303234323330393861373736623139383466353062323434 35623630626265383138353533383561653065333535346263616164396431363663656638646534
32646264346666393434613739353939343566373165383636303531306331663062303938643562 66313537376334666631313061656633393238303536636263346663313066323864333836353262
30616661306539313833646364646535323333623839386535663863353037626661346331353666 39383063653831303066656265393165653764316130356633633539356335306637373735663762
39646264303533666265666539383262626663633234353163393539323266343763336665383732 31653864636632383661613931383836373131396532306637316533386466303663396365666462
65326335316639353566326266306561366230356135666435326637663434323637626539393535 39373034333165636535323963653639333339373637616464653437646334356635366334643735
62316634663262303365333966643564356638373832373566373331663064323765646330343434 66663166616133363334663366393238633963653734383535333737326536326331313830376336
30346336353566626136613264336634626230363664643834373334663331643938343932326465 31383765313931383237303637316230656436636566646139353631336363636632356534323835
65313561653761376635363963303136376566393730363630633965623935363931383864656433 31363338633466653336383265623233623731646534316466636431336433363663366433376430
63323136336562353636643730313661616634666464376334356161326265633463663165303664 31636461626663633639636633623364343066316636313433396533326536646166386562646237
33616630633331343535333761623936613963356630646631623232663161323435623533663830 39313333353135303430336130626531656365303437643230396161356539346161393635383833
35356432663133653831613464333433663330323335393562316335303066633132623264343538 33616232303262303761
30356532366661623730366134646337356430323232643661636666346635663437333738383332
66646638363539613939613332316633366462376264663165356535323233393334366432383738
39623238623961643632663533306330316265313038653230333861626663336565643961343933
30356366366332363864306362373835303938653737663531353736323332393232386364353334
32383939396134663438306233636637366235623437626434313630386563393161646130646635
66613039353435313062393930663437383732386138323232623063383364393465366532623132
31636436326234313534633234303261363866336561343630376531346336633232616364383162
63313835393035313938336238363331623937653438343737346135336237623564383534363434
33346135303932323065323762643731306666303935336662323939393135323337

View file

@ -1,23 +1,12 @@
# ── VISUAL Infrastructure ───────────────────────────────────────────────────── # ── VISUAL Infrastructure ─────────────────────────────────────────────────────
# main 87.249.49.32 — все сервисы (Traefik, Forgejo, Plane, Vaultwarden, Outline, n8n, CI/CD) # main 87.249.49.32 — все сервисы (Traefik, Forgejo, Plane, Docmost, n8n, CI/CD)
# tools 85.193.83.9 — мониторинг (Grafana, Prometheus, Loki, AlertManager, Uptime Kuma)
[main] [main]
main ansible_host=87.249.49.32 main ansible_host=87.249.49.32
[tools]
tools ansible_host=85.193.83.9
[all_servers:children]
main
tools
[all_servers:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_user=deploy
[servers] [servers]
main ansible_host=87.249.49.32 main ansible_host=87.249.49.32
[servers:vars] [servers:vars]
ansible_python_interpreter=/usr/bin/python3 ansible_python_interpreter=/usr/bin/python3
ansible_user=deploy

View file

@ -6,12 +6,5 @@
# #
# ALL SUBSEQUENT DEPLOYS (idempotent, run as deploy user): # ALL SUBSEQUENT DEPLOYS (idempotent, run as deploy user):
# ansible-playbook playbooks/site.yml # ansible-playbook playbooks/site.yml
#
# Per-server:
# ansible-playbook playbooks/deploy.yml # main server only
# ansible-playbook playbooks/tools.yml # tools server only (Outline + n8n)
#
# Secrets required in ~/.vault-password-file (see CLAUDE.md)
- import_playbook: deploy.yml - import_playbook: deploy.yml
- import_playbook: tools.yml

View file

@ -1,14 +0,0 @@
---
# Deploy tools stack (Outline wiki) on visual-tools server
# ansible-playbook playbooks/tools.yml
- name: Deploy tools stack
hosts: tools
become: true
roles:
- role: base
tags: base
- role: docker
tags: docker
- role: tools
tags: tools

View file

@ -18,16 +18,8 @@ plane_redis_image: "redis:7-alpine"
# Рекомендуется перейти на alpine/minio или собирать из исходников. # Рекомендуется перейти на alpine/minio или собирать из исходников.
plane_minio_image: "minio/minio:RELEASE.2025-04-22T22-12-26Z" # https://hub.docker.com/r/minio/minio/tags plane_minio_image: "minio/minio:RELEASE.2025-04-22T22-12-26Z" # https://hub.docker.com/r/minio/minio/tags
act_runner_image: "gitea/act_runner:0.3.0" # https://hub.docker.com/r/gitea/act_runner/tags act_runner_image: "gitea/act_runner:0.3.0" # https://hub.docker.com/r/gitea/act_runner/tags
prometheus_image: "prom/prometheus:v3.4.0" # https://hub.docker.com/r/prom/prometheus/tags
node_exporter_image: "prom/node-exporter:v1.9.1" # https://hub.docker.com/r/prom/node-exporter/tags
cadvisor_image: "gcr.io/cadvisor/cadvisor:v0.52.1" # https://github.com/google/cadvisor/releases
grafana_image: "grafana/grafana:11.6.1" # https://hub.docker.com/r/grafana/grafana/tags
alertmanager_image: "prom/alertmanager:v0.28.1" # https://hub.docker.com/r/prom/alertmanager/tags
loki_image: "grafana/loki:3.4.3" # https://hub.docker.com/r/grafana/loki/tags
promtail_image: "grafana/promtail:3.4.3" # https://hub.docker.com/r/grafana/promtail/tags
crowdsec_image: "crowdsecurity/crowdsec:v1.6.8" # https://hub.docker.com/r/crowdsecurity/crowdsec/tags crowdsec_image: "crowdsecurity/crowdsec:v1.6.8" # https://hub.docker.com/r/crowdsecurity/crowdsec/tags
redis_image: "redis:7-alpine" redis_image: "redis:7-alpine"
uptime_kuma_image: "louislam/uptime-kuma:1" # https://hub.docker.com/r/louislam/uptime-kuma/tags
docmost_image: "docmost/docmost:latest" # https://hub.docker.com/r/docmost/docmost/tags docmost_image: "docmost/docmost:latest" # https://hub.docker.com/r/docmost/docmost/tags
docmost_db_image: "postgres:16-alpine" docmost_db_image: "postgres:16-alpine"
docmost_redis_image: "redis:7-alpine" docmost_redis_image: "redis:7-alpine"

View file

@ -59,15 +59,6 @@
changed_when: false changed_when: false
ignore_errors: true ignore_errors: true
- name: Deploy Promtail config
ansible.builtin.template:
src: loki/promtail.yml.j2
dest: "{{ services_root }}/loki/promtail.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Deploy CrowdSec acquisition config - name: Deploy CrowdSec acquisition config
ansible.builtin.template: ansible.builtin.template:
src: crowdsec/acquis.yaml.j2 src: crowdsec/acquis.yaml.j2

View file

@ -16,9 +16,6 @@
- "{{ plane_redis_image }}" - "{{ plane_redis_image }}"
- "{{ plane_minio_image }}" - "{{ plane_minio_image }}"
- "{{ act_runner_image }}" - "{{ act_runner_image }}"
- "{{ node_exporter_image }}"
- "{{ cadvisor_image }}"
- "{{ promtail_image }}"
- "{{ crowdsec_image }}" - "{{ crowdsec_image }}"
- "{{ docmost_image }}" - "{{ docmost_image }}"
- "{{ docmost_db_image }}" - "{{ docmost_db_image }}"
@ -30,30 +27,6 @@
delay: 30 delay: 30
until: pull_result.rc == 0 until: pull_result.rc == 0
# ── UFW: allow tools Prometheus to scrape exporters on main ──────────────────
- name: Allow tools server to scrape node-exporter
community.general.ufw:
rule: allow
port: "9100"
proto: tcp
src: "{{ ip_tools }}"
- name: Allow tools server to scrape cAdvisor
community.general.ufw:
rule: allow
port: "8080"
proto: tcp
src: "{{ ip_tools }}"
- name: Remove legacy SMTP relay UFW rule (port 1025)
community.general.ufw:
rule: allow
port: "1025"
proto: tcp
src: "{{ ip_tools }}"
delete: true
failed_when: false
- name: Deploy Docker Compose stack - name: Deploy Docker Compose stack
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ services_root }}" project_src: "{{ services_root }}"

View file

@ -1,72 +0,0 @@
# Generated by Ansible — do not edit manually
# Authelia v4 configuration
theme: dark
server:
host: 0.0.0.0
port: 9091
log:
level: warn
jwt_secret: "{{ authelia_jwt_secret }}"
default_redirection_url: "https://{{ domain_auth }}"
session:
name: authelia_session
secret: "{{ authelia_session_secret }}"
expiration: 12h
inactivity: 30m
domain: "{{ domain_base }}"
redis:
host: authelia-redis
port: 6379
regulation:
max_retries: 3
find_time: 2m
ban_time: 10m
storage:
encryption_key: "{{ authelia_storage_key }}"
local:
path: /config/db.sqlite3
notifier:
disable_startup_check: true
filesystem:
filename: /config/notifications.txt
authentication_backend:
password_reset:
disable: false
file:
path: /config/users.yml
password:
algorithm: argon2id
iterations: 3
memory: 65536
parallelism: 4
key_length: 32
salt_length: 16
access_control:
default_policy: deny
rules:
# Authelia portal itself — всегда доступен
- domain: "{{ domain_auth }}"
policy: bypass
# Traefik dashboard — только admin, требует 2FA
- domain: "{{ domain_traefik }}"
policy: two_factor
subject: "group:admins"
# Plane god-mode — только admin, требует 2FA
- domain: "{{ domain_plane }}"
resources:
- "^/god-mode/.*$"
policy: two_factor
subject: "group:admins"

View file

@ -1,12 +0,0 @@
# Generated by Ansible — do not edit manually
# Authelia users database
# To update password hash: docker exec authelia authelia crypto hash generate argon2 --password 'yourpassword'
# To set up TOTP: visit https://{{ domain_auth }} and login — QR code will appear on first use
users:
{{ authelia_admin_user }}:
displayname: "Admin"
password: "{{ authelia_admin_password_hash }}"
email: "{{ acme_email }}"
groups:
- admins

View file

@ -23,9 +23,6 @@ networks:
internal: true internal: true
runner-jobs: runner-jobs:
driver: bridge driver: bridge
monitoring:
driver: bridge
internal: true
docmost-internal: docmost-internal:
driver: bridge driver: bridge
internal: true internal: true
@ -396,58 +393,6 @@ services:
- backend - backend
- runner-jobs - runner-jobs
# ── Monitoring exporters (metrics scraped by tools Prometheus over network) ──
# Ports exposed: tools server must have UFW rules allowing ip_main:9100/8080
node-exporter:
image: {{ node_exporter_image }}
container_name: node-exporter
restart: unless-stopped
networks:
- monitoring
ports:
- "9100:9100"
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
cadvisor:
image: {{ cadvisor_image }}
container_name: cadvisor
restart: unless-stopped
networks:
- monitoring
ports:
- "8080:8080"
privileged: true
devices:
- /dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
- /dev/disk:/dev/disk:ro
# ── Logging (Promtail pushes to Loki on tools server) ─────────────────────
promtail:
image: {{ promtail_image }}
container_name: promtail
restart: unless-stopped
networks:
- monitoring
volumes:
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- {{ services_root }}/loki/promtail.yml:/etc/promtail/config.yml:ro
command: -config.file=/etc/promtail/config.yml
# ── Security Stack ───────────────────────────────────────────────────────── # ── Security Stack ─────────────────────────────────────────────────────────
# CrowdSec: анализирует логи Traefik, банит злоумышленников по IP # CrowdSec: анализирует логи Traefik, банит злоумышленников по IP
# Использует community-репутацию + локальный анализ поведения # Использует community-репутацию + локальный анализ поведения
@ -456,8 +401,7 @@ services:
container_name: crowdsec container_name: crowdsec
restart: unless-stopped restart: unless-stopped
networks: networks:
- monitoring - proxy
- proxy # needs internet for hub/threat-intel downloads
environment: environment:
- COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/linux - COLLECTIONS=crowdsecurity/traefik crowdsecurity/http-cve crowdsecurity/linux
- GID=1000 - GID=1000
@ -481,7 +425,6 @@ services:
# FORGEJO_TOKEN: "${FORGEJO_RUNNER_TOKEN}" # FORGEJO_TOKEN: "${FORGEJO_RUNNER_TOKEN}"
# FORGEJO_URL: "https://{{ domain_git }}" # FORGEJO_URL: "https://{{ domain_git }}"
# FORGEJO_REPO: "jack/infra" # FORGEJO_REPO: "jack/infra"
# PROMETHEUS_URL: "http://{{ ip_tools }}:9090"
# volumes: # volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro # - /var/run/docker.sock:/var/run/docker.sock:ro
# networks: # networks:

View file

@ -1,36 +0,0 @@
# Generated by Ansible — do not edit manually
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 30d
compactor:
working_directory: /loki/retention
delete_request_store: filesystem
retention_enabled: true

View file

@ -1,38 +0,0 @@
# Generated by Ansible — do not edit manually
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://{{ ip_tools }}:3100/loki/api/v1/push
scrape_configs:
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: [__meta_docker_container_name]
regex: /(.*)
target_label: container
- source_labels: [__meta_docker_container_log_stream]
target_label: stream
- source_labels: [__meta_docker_container_label_com_docker_compose_service]
target_label: service
- job_name: syslog
static_configs:
- targets: [localhost]
labels:
job: syslog
__path__: /var/log/syslog
- job_name: auth
static_configs:
- targets: [localhost]
labels:
job: auth
__path__: /var/log/auth.log

View file

@ -65,22 +65,6 @@ http:
middlewares: [rate-limit-default] middlewares: [rate-limit-default]
priority: 10 priority: 10
grafana:
rule: "Host(`{{ domain_dashboard }}`)"
entrypoints: [websecure]
tls:
certresolver: letsencrypt
service: grafana
middlewares: [rate-limit-default]
uptime-kuma:
rule: "Host(`{{ domain_status }}`)"
entrypoints: [websecure]
tls:
certresolver: letsencrypt
service: uptime-kuma
middlewares: [rate-limit-default]
walava-landing: walava-landing:
rule: "Host(`{{ domain_landing }}`)" rule: "Host(`{{ domain_landing }}`)"
entrypoints: [websecure] entrypoints: [websecure]
@ -131,16 +115,6 @@ http:
servers: servers:
- url: "http://plane-space:3000" - url: "http://plane-space:3000"
grafana:
loadBalancer:
servers:
- url: "http://{{ ip_tools }}:3000"
uptime-kuma:
loadBalancer:
servers:
- url: "http://{{ ip_tools }}:3001"
walava-landing: walava-landing:
loadBalancer: loadBalancer:
servers: servers:

View file

@ -1,11 +0,0 @@
---
tools_root: /opt/tools
# Image versions (mirrors services role — keep in sync)
prometheus_image: "prom/prometheus:v3.4.0"
node_exporter_image: "prom/node-exporter:v1.9.1"
cadvisor_image: "gcr.io/cadvisor/cadvisor:v0.52.1"
grafana_image: "grafana/grafana:11.6.1"
alertmanager_image: "prom/alertmanager:v0.28.1"
loki_image: "grafana/loki:3.4.3"
uptime_kuma_image: "louislam/uptime-kuma:1"

View file

@ -1,817 +0,0 @@
{
"__inputs": [
{
"name": "DS_PROMETHEUS",
"label": "Prometheus",
"description": "Prometheus as the datasource is obligatory",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "7.4.5"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": ""
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "table",
"name": "Table",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": 14282,
"graphTooltip": 0,
"id": null,
"iteration": 1617715580880,
"links": [],
"panels": [
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 8,
"panels": [],
"title": "CPU",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 24,
"x": 0,
"y": 1
},
"hiddenSeries": false,
"id": 15,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_cpu_usage_seconds_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name) *100",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "CPU Usage",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "percent",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 8
},
"id": 11,
"panels": [],
"title": "Memory",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"hiddenSeries": false,
"id": 9,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(container_memory_rss{instance=~\"$host\",name=~\"$container\",name=~\".+\"}) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Usage",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "bytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"hiddenSeries": false,
"id": 14,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(container_memory_cache{instance=~\"$host\",name=~\"$container\",name=~\".+\"}) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Cached",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "bytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 2,
"panels": [],
"title": "Network",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 18
},
"hiddenSeries": false,
"id": 4,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"hideEmpty": false,
"hideZero": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"sideWidth": null,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_network_receive_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Received Network Traffic",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:674",
"format": "Bps",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:675",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 18
},
"hiddenSeries": false,
"id": 6,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_network_transmit_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name)",
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Sent Network Traffic",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:832",
"format": "Bps",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:833",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 26
},
"id": 19,
"panels": [],
"title": "Misc",
"type": "row"
},
{
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {
"align": null,
"filterable": false
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "id"
},
"properties": [
{
"id": "custom.width",
"value": 260
}
]
},
{
"matcher": {
"id": "byName",
"options": "Running"
},
"properties": [
{
"id": "unit",
"value": "d"
},
{
"id": "decimals",
"value": 1
},
{
"id": "custom.displayMode",
"value": "color-text"
},
{
"id": "color",
"value": {
"fixedColor": "dark-green",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 27
},
"id": 17,
"options": {
"showHeader": true,
"sortBy": []
},
"pluginVersion": "7.4.5",
"targets": [
{
"expr": "(time() - container_start_time_seconds{instance=~\"$host\",name=~\"$container\",name=~\".+\"})/86400",
"format": "table",
"instant": true,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Containers Info",
"transformations": [
{
"id": "filterFieldsByName",
"options": {
"include": {
"names": [
"container_label_com_docker_compose_project",
"container_label_com_docker_compose_project_working_dir",
"image",
"instance",
"name",
"Value",
"container_label_com_docker_compose_service"
]
}
}
},
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": "Running",
"container_label_com_docker_compose_project": "Label",
"container_label_com_docker_compose_project_working_dir": "Working dir",
"container_label_com_docker_compose_service": "Service",
"image": "Registry Image",
"instance": "Instance",
"name": "Name"
}
}
}
],
"type": "table"
}
],
"schemaVersion": 27,
"style": "dark",
"tags": [
"cadvisor",
"docker"
],
"templating": {
"list": [
{
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values({__name__=~\"container.*\"},instance)",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": "Host",
"multi": false,
"name": "host",
"options": [],
"query": {
"query": "label_values({__name__=~\"container.*\"},instance)",
"refId": "Prometheus-host-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": "Container",
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)",
"refId": "Prometheus-container-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Cadvisor exporter",
"uid": "pMEd7m0Mz",
"version": 1,
"description": "Simple exporter for cadvisor only"
}

File diff suppressed because it is too large Load diff

View file

@ -1,167 +0,0 @@
---
- name: Create tools root directory
ansible.builtin.file:
path: "{{ tools_root }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0750"
- name: Create tools subdirectories
ansible.builtin.file:
path: "{{ tools_root }}/{{ item }}"
state: directory
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0755"
loop:
- prometheus
- prometheus/rules
- grafana/provisioning/datasources
- grafana/provisioning/dashboards
- grafana/provisioning/dashboards/json
- loki
- name: Deploy .env file
ansible.builtin.template:
src: env.j2
dest: "{{ tools_root }}/.env"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0600"
- name: Deploy docker-compose.yml
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ tools_root }}/docker-compose.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0640"
- name: Deploy Prometheus config
ansible.builtin.template:
src: prometheus/prometheus.yml.j2
dest: "{{ tools_root }}/prometheus/prometheus.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Prometheus alert rules
ansible.builtin.template:
src: prometheus/rules/alerts.yml.j2
dest: "{{ tools_root }}/prometheus/rules/alerts.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy AlertManager config
ansible.builtin.template:
src: prometheus/alertmanager.yml.j2
dest: "{{ tools_root }}/prometheus/alertmanager.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Loki config
ansible.builtin.template:
src: loki/loki.yml.j2
dest: "{{ tools_root }}/loki/loki.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Grafana Prometheus datasource
ansible.builtin.template:
src: grafana/provisioning/datasources/prometheus.yml.j2
dest: "{{ tools_root }}/grafana/provisioning/datasources/prometheus.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Grafana Loki datasource
ansible.builtin.template:
src: grafana/provisioning/datasources/loki.yml.j2
dest: "{{ tools_root }}/grafana/provisioning/datasources/loki.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Grafana dashboard provisioning config
ansible.builtin.template:
src: grafana/provisioning/dashboards/dashboards.yml.j2
dest: "{{ tools_root }}/grafana/provisioning/dashboards/dashboards.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy Node Exporter Full dashboard JSON
ansible.builtin.copy:
src: grafana/dashboards/node-exporter-full.json
dest: "{{ tools_root }}/grafana/provisioning/dashboards/json/node-exporter-full.json"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Deploy cAdvisor dashboard JSON
ansible.builtin.copy:
src: grafana/dashboards/cadvisor.json
dest: "{{ tools_root }}/grafana/provisioning/dashboards/json/cadvisor.json"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
- name: Pull monitoring images
ansible.builtin.command: docker pull {{ item }}
loop:
- "{{ prometheus_image }}"
- "{{ alertmanager_image }}"
- "{{ node_exporter_image }}"
- "{{ cadvisor_image }}"
- "{{ grafana_image }}"
- "{{ loki_image }}"
- "{{ uptime_kuma_image }}"
register: pull_result
changed_when: "'Status: Downloaded newer image' in pull_result.stdout"
retries: 5
delay: 30
until: pull_result.rc == 0
# ── UFW: allow main server to reach monitoring services ───────────────────────
- name: Allow main server to reach Loki (Promtail log push)
community.general.ufw:
rule: allow
port: "3100"
proto: tcp
src: "{{ ip_main }}"
- name: Allow main server to reach Prometheus (discord-bot metrics)
community.general.ufw:
rule: allow
port: "9090"
proto: tcp
src: "{{ ip_main }}"
- name: Allow main Traefik to reach Grafana
community.general.ufw:
rule: allow
port: "3000"
proto: tcp
src: "{{ ip_main }}"
- name: Allow main Traefik to reach Uptime Kuma
community.general.ufw:
rule: allow
port: "3001"
proto: tcp
src: "{{ ip_main }}"
- name: Start tools stack
community.docker.docker_compose_v2:
project_src: "{{ tools_root }}"
state: present
pull: never
remove_orphans: true
retries: 3
delay: 15
register: compose_result
until: compose_result is succeeded

View file

@ -1,157 +0,0 @@
# Tools stack — generated by Ansible
# Do not edit manually; re-run ansible-playbook playbooks/tools.yml
# Monitoring: Prometheus, Grafana, Loki, AlertManager, Uptime Kuma, node-exporter, cAdvisor
networks:
monitoring:
driver: bridge
volumes:
prometheus_data:
grafana_data:
loki_data:
uptime_kuma_data:
services:
# ── Prometheus ─────────────────────────────────────────────────────────────
prometheus:
image: {{ prometheus_image }}
container_name: prometheus
restart: unless-stopped
networks:
- monitoring
ports:
- "127.0.0.1:9090:9090" # exposed to main via UFW rule for discord-bot
volumes:
- prometheus_data:/prometheus
- {{ tools_root }}/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- {{ tools_root }}/prometheus/rules:/etc/prometheus/rules:ro
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=30d"
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
- "--web.console.templates=/usr/share/prometheus/consoles"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:9090/-/healthy"]
interval: 30s
timeout: 5s
retries: 3
alertmanager:
image: {{ alertmanager_image }}
container_name: alertmanager
restart: unless-stopped
networks:
- monitoring
volumes:
- {{ tools_root }}/prometheus/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
command:
- "--config.file=/etc/alertmanager/alertmanager.yml"
- "--storage.path=/alertmanager"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:9093/-/healthy"]
interval: 30s
timeout: 5s
retries: 3
# ── Exporters (monitor the tools host itself) ───────────────────────────────
node-exporter:
image: {{ node_exporter_image }}
container_name: node-exporter
restart: unless-stopped
networks:
- monitoring
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
cadvisor:
image: {{ cadvisor_image }}
container_name: cadvisor
restart: unless-stopped
networks:
- monitoring
privileged: true
devices:
- /dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
- /dev/disk:/dev/disk:ro
# ── Grafana ─────────────────────────────────────────────────────────────────
grafana:
image: {{ grafana_image }}
container_name: grafana
restart: unless-stopped
security_opt:
- no-new-privileges:true
depends_on:
- prometheus
networks:
- monitoring
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
- {{ tools_root }}/grafana/provisioning:/etc/grafana/provisioning:ro
env_file: .env
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_DOMAIN={{ domain_dashboard }}
- GF_SERVER_ROOT_URL=https://{{ domain_dashboard }}
- GF_AUTH_ANONYMOUS_ENABLED=false
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
interval: 30s
timeout: 5s
retries: 3
# ── Loki ────────────────────────────────────────────────────────────────────
loki:
image: {{ loki_image }}
container_name: loki
restart: unless-stopped
networks:
- monitoring
ports:
- "3100:3100" # exposed to main for Promtail log ingestion
volumes:
- loki_data:/loki
- {{ tools_root }}/loki/loki.yml:/etc/loki/local-config.yaml:ro
command: -config.file=/etc/loki/local-config.yaml
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3100/ready"]
interval: 30s
timeout: 5s
retries: 3
# ── Uptime Kuma ─────────────────────────────────────────────────────────────
uptime-kuma:
image: {{ uptime_kuma_image }}
container_name: uptime-kuma
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- monitoring
ports:
- "3001:3001"
volumes:
- uptime_kuma_data:/app/data
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:3001/"]
interval: 30s
timeout: 5s
retries: 3

View file

@ -1,2 +0,0 @@
# Generated by Ansible — do not edit manually
GF_SECURITY_ADMIN_PASSWORD={{ grafana_admin_password }}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,36 +0,0 @@
# Generated by Ansible — do not edit manually
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 30d
compactor:
working_directory: /loki/retention
delete_request_store: filesystem
retention_enabled: true

View file

@ -1,38 +0,0 @@
# Generated by Ansible — do not edit manually
global:
resolve_timeout: 5m
route:
group_by: [alertname, severity]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: all
receivers:
- name: all
telegram_configs:
- bot_token: "{{ alertmanager_telegram_token }}"
chat_id: {{ alertmanager_telegram_chat_id }}
message: |
{{ '{{' }} range .Alerts {{ '}}' }}
{{ '{{' }} if eq .Status "firing" {{ '}}' }}🔴{{ '{{' }} else {{ '}}' }}🟢{{ '{{' }} end {{ '}}' }} *{{ '{{' }} .Labels.alertname {{ '}}' }}*
{{ '{{' }} .Annotations.summary {{ '}}' }}
{{ '{{' }} .Annotations.description {{ '}}' }}
{{ '{{' }} end {{ '}}' }}
parse_mode: Markdown
discord_configs:
- webhook_url: "{{ discord_webhook_alerts }}"
title: >-
{{ '{{' }} if eq (index .Alerts 0).Status "firing" {{ '}}' }}🔴 Alert{{ '{{' }} else {{ '}}' }}🟢 Resolved{{ '{{' }} end {{ '}}' }}
message: |
{{ '{{' }} range .Alerts {{ '}}' }}
**{{ '{{' }} .Labels.alertname {{ '}}' }}**
{{ '{{' }} .Annotations.summary {{ '}}' }}
{{ '{{' }} .Annotations.description {{ '}}' }}
{{ '{{' }} end {{ '}}' }}
inhibit_rules:
- source_matchers: [severity="critical"]
target_matchers: [severity="warning"]
equal: [alertname]

View file

@ -1,49 +0,0 @@
# Generated by Ansible — do not edit manually
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
instance: "{{ domain_base }}"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
# tools server metrics
- job_name: node-exporter-tools
static_configs:
- targets: ["node-exporter:9100"]
labels:
host: tools
- job_name: cadvisor-tools
static_configs:
- targets: ["cadvisor:8080"]
labels:
host: tools
- job_name: alertmanager
static_configs:
- targets: ["alertmanager:9093"]
# main server metrics (scraped over network)
- job_name: node-exporter-main
static_configs:
- targets: ["{{ ip_main }}:9100"]
labels:
host: main
- job_name: cadvisor-main
static_configs:
- targets: ["{{ ip_main }}:8080"]
labels:
host: main

View file

@ -1,86 +0,0 @@
# Generated by Ansible — do not edit manually
groups:
- name: host
rules:
- alert: HighCPULoad
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Высокая нагрузка CPU ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "CPU загружен более 85% на протяжении 5 минут."
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Высокое использование RAM ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "Использование RAM превысило 85%."
- alert: CriticalMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 95
for: 2m
labels:
severity: critical
annotations:
summary: "Критическое использование RAM ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "RAM заполнена на 95%+. Возможны OOM kills."
- alert: DiskSpaceWarning
expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|aufs"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay|aufs"})) * 100 > 75
for: 5m
labels:
severity: warning
annotations:
summary: "Заканчивается место на диске ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "Диск {{ '{{' }} $labels.mountpoint {{ '}}' }} занят на {{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%."
- alert: DiskSpaceCritical
expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|aufs"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay|aufs"})) * 100 > 90
for: 2m
labels:
severity: critical
annotations:
summary: "Критически мало места на диске ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "Диск {{ '{{' }} $labels.mountpoint {{ '}}' }} занят на {{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%."
- alert: SwapUsageHigh
expr: (1 - (node_memory_SwapFree_bytes / node_memory_SwapTotal_bytes)) * 100 > 50
for: 5m
labels:
severity: warning
annotations:
summary: "Высокое использование swap ({{ '{{' }} $value | printf \"%.0f\" {{ '}}' }}%)"
description: "Swap используется более чем на 50% — RAM под давлением."
- name: containers
rules:
- alert: ContainerDown
expr: absent(container_last_seen{name=~".+"}) or time() - container_last_seen{name=~".+"} > 60
for: 2m
labels:
severity: critical
annotations:
summary: "Контейнер {{ '{{' }} $labels.name {{ '}}' }} недоступен"
description: "Контейнер не отвечает более 2 минут."
- alert: ContainerHighMemory
expr: (container_memory_usage_bytes{name=~".+"} / (container_spec_memory_limit_bytes{name=~".+"} > 0)) * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "Контейнер {{ '{{' }} $labels.name {{ '}}' }} использует 90%+ памяти"
description: "Контейнер близок к mem_limit — возможен OOM kill."
- alert: ContainerRestarting
expr: increase(container_last_seen{name=~".+"}[5m]) == 0 and rate(container_cpu_usage_seconds_total{name=~".+"}[5m]) == 0
for: 0m
labels:
severity: warning
annotations:
summary: "Контейнер {{ '{{' }} $labels.name {{ '}}' }} возможно перезапускается"
description: "Контейнер не активен — проверьте docker ps."