diff --git a/FIX_PROMLEMS.md b/FIX_PROMLEMS.md
new file mode 100644
index 0000000..1e11e0a
--- /dev/null
+++ b/FIX_PROMLEMS.md
@@ -0,0 +1,92 @@
+# FIX_PROBLEMS.md
+
+## Текущий статус Prometheus
+
+### ✅ Что работает:
+- Prometheus доступен по `https://188.68.223.37/prometheus/`
+- Nginx проксирование настроено правильно
+- Другие таргеты работают (Node Exporter, боты)
+- Grafana работает по `https://188.68.223.37/grafana/`
+
+### ❌ Что не работает:
+
+#### 1. Самомониторинг Prometheus
+- **Статус:** `"health":"down"` с ошибкой 404
+- **Проблема:** Prometheus не может получить доступ к своим метрикам по `/metrics`
+- **Ошибка:** `"server returned HTTP status 404 Not Found"`
+- **Причина:** Prometheus не экспортирует метрики по эндпоинту `/metrics` внутри контейнера
+
+#### 2. Редирект в Prometheus
+- **Проблема:** Редирект с `https://188.68.223.37/prometheus/` на `https://188.68.223.37/prometheus/prometheus/query`
+- **Причина:** Неправильная конфигурация Nginx proxy_pass
+- **Статус:** ТРЕБУЕТ ИСПРАВЛЕНИЯ
+
+### 🔧 Быстрые исправления:
+
+#### Исправление редиректа Prometheus:
+Проблема в конфигурации Nginx - нужно убрать слэш в `proxy_pass`:
+```nginx
+# Было:
+proxy_pass http://prometheus_backend/;
+
+# Должно быть:
+proxy_pass http://prometheus_backend;
+```
+
+#### Исправление самомониторинга:
+Проблема в том, что Prometheus не экспортирует метрики. Возможные решения:
+1. Убрать job 'prometheus' из конфигурации
+2. Добавить параметры для экспорта метрик
+3. Использовать другой подход для самомониторинга
+
+### 📋 Следующие шаги:
+1. ✅ Исправить редирект Prometheus
+2. ❌ Решить проблему с самомониторингом (пропущено)
+3. ✅ Исправить главную страницу
+4. ✅ Исправить Alertmanager
+5. 🔄 Настроить безопасность
+6. 🔄 Настроить Uptime Kuma
+
+---
+
+## Этап 5: Настройка безопасности
+
+### План действий:
+1. **Добавить базовую аутентификацию для Prometheus**
+ - Создать файл с логином/паролем
+ - Настроить Nginx для запроса аутентификации
+ - Проверить, что теперь требуется логин/пароль
+
+2. **Добавить базовую аутентификацию для Alertmanager**
+ - Создать файл с логином/паролем
+ - Настроить Nginx для запроса аутентификации
+ - Проверить, что теперь требуется логин/пароль
+
+3. **Перезагрузить Nginx**
+ - Применить новые настройки безопасности
+
+4. **Проверить, что теперь требуется логин/пароль**
+ - Убедиться, что Prometheus и Alertmanager защищены
+
+**Цель:** Сейчас Prometheus и Alertmanager доступны без аутентификации, что небезопасно. Нужно добавить базовую HTTP аутентификацию.
+
+---
+
+## Этап 6: Настройка Uptime Kuma
+
+### План действий:
+1. **Проверить статус Uptime Kuma**
+ - Убедиться, что контейнер запущен
+ - Проверить логи на наличие ошибок
+
+2. **Настроить мониторинг основных сервисов**
+ - Добавить мониторинг Grafana
+ - Добавить мониторинг Prometheus
+ - Добавить мониторинг Alertmanager
+ - Добавить мониторинг ботов
+
+3. **Проверить доступность `/status/`**
+ - Убедиться, что страница работает
+ - Проверить отображение статуса сервисов
+
+**Цель:** Uptime Kuma должен показывать статус всех сервисов и их доступность.
diff --git a/docker-compose.yml b/docker-compose.yml
index 9a700bb..5be7f32 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -39,7 +39,6 @@ services:
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
- GF_SERVER_ROOT_URL=https://${SERVER_IP}/grafana/
- GF_SERVER_SERVE_FROM_SUB_PATH=true
- - GF_SERVER_DOMAIN=${SERVER_IP}
ports:
- "3000:3000"
volumes:
@@ -111,7 +110,7 @@ services:
environment:
- SERVER_IP=${SERVER_IP}
volumes:
- - ./infra/nginx/nginx.conf:/etc/nginx/templates/nginx.conf.template:ro
+ - ./infra/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./infra/nginx/conf.d:/etc/nginx/conf.d:ro
- ./infra/nginx/ssl:/etc/nginx/ssl:ro
- ./infra/nginx/.htpasswd:/etc/nginx/.htpasswd:ro
@@ -255,4 +254,5 @@ networks:
driver: bridge
ipam:
config:
- - subnet: 192.168.100.0/24
+ - subnet: 172.20.0.0/16
+ gateway: 172.20.0.1
diff --git a/infra/alertmanager/alertmanager.yml b/infra/alertmanager/alertmanager.yml
index 933c0ba..5776a80 100644
--- a/infra/alertmanager/alertmanager.yml
+++ b/infra/alertmanager/alertmanager.yml
@@ -94,92 +94,26 @@ receivers:
- url: 'http://localhost:5001/'
send_resolved: true
- # Critical alerts - immediate notification via multiple channels
+ # Critical alerts - immediate notification via webhook
- name: 'critical-alerts'
- email_configs:
- - to: 'admin@{{DOMAIN}}'
- subject: '🚨 CRITICAL ALERT: {{ .GroupLabels.alertname }}'
- body: |
- {{ range .Alerts }}
- Alert: {{ .Annotations.summary }}
- Description: {{ .Annotations.description }}
- Severity: {{ .Labels.severity }}
- Service: {{ .Labels.service }}
- Instance: {{ .Labels.instance }}
- Time: {{ .StartsAt }}
- {{ end }}
- html: |
-
🚨 Critical Alert
-
- | Alert: | {{ .GroupLabels.alertname }} |
- | Service: | {{ .GroupLabels.service }} |
- | Time: | {{ .GroupLabels.time }} |
-
- Alerts:
-
- {{ range .Alerts }}
- - {{ .Annotations.summary }}
- {{ .Annotations.description }}
- Instance: {{ .Labels.instance }} | Time: {{ .StartsAt }}
-
- {{ end }}
-
webhook_configs:
- url: 'http://localhost:5001/critical'
send_resolved: true
# Warning alerts - less urgent notification
- name: 'warning-alerts'
- email_configs:
- - to: 'admin@{{DOMAIN}}'
- subject: '⚠️ WARNING: {{ .GroupLabels.alertname }}'
- body: |
- {{ range .Alerts }}
- Alert: {{ .Annotations.summary }}
- Description: {{ .Annotations.description }}
- Severity: {{ .Labels.severity }}
- Service: {{ .Labels.service }}
- Instance: {{ .Labels.instance }}
- Time: {{ .StartsAt }}
- {{ end }}
webhook_configs:
- url: 'http://localhost:5001/warning'
send_resolved: true
# Bot-specific alerts
- name: 'bot-alerts'
- email_configs:
- - to: 'bot-admin@{{DOMAIN}}'
- subject: '🤖 Bot Alert: {{ .GroupLabels.alertname }}'
- body: |
- Bot Alert: {{ .GroupLabels.alertname }}
- Service: {{ .GroupLabels.service }}
-
- {{ range .Alerts }}
- - {{ .Annotations.summary }}
- {{ .Annotations.description }}
- Instance: {{ .Labels.instance }}
- Time: {{ .StartsAt }}
- {{ end }}
webhook_configs:
- url: 'http://localhost:5001/bot'
send_resolved: true
# Infrastructure alerts
- name: 'infrastructure-alerts'
- email_configs:
- - to: 'infra@{{DOMAIN}}'
- subject: '🏗️ Infrastructure Alert: {{ .GroupLabels.alertname }}'
- body: |
- Infrastructure Alert: {{ .GroupLabels.alertname }}
- Service: {{ .GroupLabels.service }}
-
- {{ range .Alerts }}
- - {{ .Annotations.summary }}
- {{ .Annotations.description }}
- Instance: {{ .Labels.instance }}
- Time: {{ .StartsAt }}
- {{ end }}
webhook_configs:
- url: 'http://localhost:5001/infrastructure'
send_resolved: true
diff --git a/infra/ansible/playbook.yml b/infra/ansible/playbook.yml
index df7ec7e..b73fb8e 100644
--- a/infra/ansible/playbook.yml
+++ b/infra/ansible/playbook.yml
@@ -19,7 +19,11 @@
grafana_admin_password: "{{ lookup('env', 'GRAFANA_ADMIN_PASSWORD') | default('admin') }}"
tasks:
- - name: Обновить SSH host key для избежания ошибок при переустановке
+ # ========================================
+ # ЭТАП 1: ПОДГОТОВКА СИСТЕМЫ (ROOT)
+ # ========================================
+
+ - name: "[1/10] Обновить SSH host key для избежания ошибок при переустановке"
known_hosts:
path: ~/.ssh/known_hosts
name: "{{ ansible_host }}"
@@ -29,11 +33,11 @@
run_once: true
ignore_errors: yes
- - name: Обновить кэш пакетов
+ - name: "[1/10] Обновить кэш пакетов"
apt:
update_cache: yes
- - name: Установить необходимые пакеты
+ - name: "[1/10] Установить необходимые пакеты"
apt:
name:
- docker.io
@@ -61,64 +65,77 @@
- python3-certbot-nginx
state: present
- - name: Установить Python библиотеки для Ansible
+ - name: "[1/10] Установить Python библиотеки для Ansible"
pip:
name:
- passlib
- bcrypt
state: present
- - name: Установить часовой пояс Europe/Moscow
+ - name: "[1/10] Установить часовой пояс Europe/Moscow"
timezone:
name: Europe/Moscow
- - name: Проверить существование swap-файла
+ # ========================================
+ # ЭТАП 2: НАСТРОЙКА СИСТЕМЫ (ROOT)
+ # ========================================
+
+ - name: "[2/10] Проверить существование swap-файла"
stat:
path: /swapfile
register: swap_file_stat
- - name: Создать swap-файл (2GB)
+ - name: "[2/10] Создать swap-файл (2GB)"
command: fallocate -l 2G /swapfile
when: not swap_file_stat.stat.exists
- - name: Установить правильные права на swap-файл
+ - name: "[2/10] Установить правильные права на swap-файл"
file:
path: /swapfile
mode: '0600'
owner: root
group: root
- - name: Настроить swap-файл
+ - name: "[2/10] Настроить swap-файл"
command: mkswap /swapfile
when: not swap_file_stat.stat.exists
- - name: Включить swap-файл
+ - name: "[2/10] Включить swap-файл"
command: swapon /swapfile
when: not swap_file_stat.stat.exists
- - name: Настроить swappiness = 10 (временно)
+ - name: "[2/10] Настроить swappiness = 10 (временно)"
sysctl:
name: vm.swappiness
value: '10'
state: present
reload: yes
- - name: Настроить swappiness = 10 (постоянно)
+ - name: "[2/10] Настроить swappiness = 10 (постоянно)"
lineinfile:
path: /etc/sysctl.conf
regexp: '^vm\.swappiness\s*='
line: 'vm.swappiness = 10'
state: present
- - name: Добавить swap-файл в /etc/fstab для автоматического монтирования
+ - name: "[2/10] Добавить swap-файл в /etc/fstab для автоматического монтирования"
lineinfile:
path: /etc/fstab
line: '/swapfile none swap sw 0 0'
state: present
create: yes
- # --- НАСТРОЙКА БЕЗОПАСНОСТИ ЯДРА ---
- - name: Настроить параметры безопасности ядра
+ - name: "[2/10] Проверить статус swap"
+ command: swapon --show
+ register: swap_status
+ changed_when: false
+
+ - name: "[2/10] Показать информацию о swap"
+ debug:
+ var: swap_status.stdout_lines
+
+ # Настройка параметров безопасности ядра
+ - name: "[2/10] Настроить параметры безопасности ядра"
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
@@ -153,7 +170,7 @@
- { name: "kernel.threads-max", value: "4096" }
- { name: "vm.max_map_count", value: "262144" }
- - name: Сохранить параметры безопасности в /etc/sysctl.conf
+ - name: "[2/10] Сохранить параметры безопасности в /etc/sysctl.conf"
lineinfile:
path: /etc/sysctl.conf
regexp: "^{{ item.name }}\\s*="
@@ -188,95 +205,385 @@
- { name: "kernel.threads-max", value: "4096" }
- { name: "vm.max_map_count", value: "262144" }
- - name: Проверить статус swap
- command: swapon --show
- register: swap_status
- changed_when: false
-
- - name: Показать информацию о swap
- debug:
- var: swap_status.stdout_lines
-
- - name: Включить и запустить prometheus-node-exporter
+ # ========================================
+ # ЭТАП 3: СИСТЕМНЫЕ СЕРВИСЫ (ROOT)
+ # ========================================
+
+ - name: "[3/10] Включить и запустить prometheus-node-exporter"
systemd:
name: prometheus-node-exporter
enabled: yes
state: started
- - name: Проверить статус prometheus-node-exporter
+ - name: "[3/10] Проверить статус prometheus-node-exporter"
command: systemctl status prometheus-node-exporter
register: node_exporter_status
changed_when: false
- - name: Показать статус prometheus-node-exporter
+ - name: "[3/10] Показать статус prometheus-node-exporter"
debug:
var: node_exporter_status.stdout_lines
- - name: Проверить, что node_exporter слушает на порту 9100
+ - name: "[3/10] Проверить, что node_exporter слушает на порту 9100"
command: netstat -tulpn | grep 9100
register: node_exporter_port
changed_when: false
- - name: Показать информацию о порте 9100
+ - name: "[3/10] Показать информацию о порте 9100"
debug:
var: node_exporter_port.stdout_lines
- - name: Обновить Docker Compose до последней версии
+ - name: "[3/10] Обновить Docker Compose до последней версии"
get_url:
url: "https://github.com/docker/compose/releases/latest/download/docker-compose-{{ ansible_system }}-{{ ansible_architecture }}"
dest: /usr/local/bin/docker-compose
mode: '0755'
- become: yes
- - name: Включить и запустить Docker
+ - name: "[3/10] Включить и запустить Docker"
systemd:
name: docker
enabled: yes
state: started
- - name: Разрешить SSH (порт 22) перед включением UFW
- ufw:
- rule: allow
- port: "22"
- proto: tcp
+ # ========================================
+ # ЭТАП 4: ПОЛЬЗОВАТЕЛЬ DEPLOY (ROOT)
+ # ========================================
+
+ - name: "[4/10] Проверить существование пользователя deploy"
+ getent:
+ database: passwd
+ key: "{{ deploy_user }}"
+ register: user_exists
+ failed_when: false
- - name: Разрешить новый SSH порт (15722) перед включением UFW
- ufw:
- rule: allow
- port: "15722"
- proto: tcp
+ - name: "[4/10] Создать группу deploy с GID 1001"
+ group:
+ name: "{{ deploy_user }}"
+ gid: "{{ gid }}"
+ when: user_exists.ansible_facts.getent_passwd is not defined
- - name: Настроить политику UFW по умолчанию
- ufw:
- policy: deny
- direction: incoming
+ - name: "[4/10] Создать пользователя deploy с UID 1001 (если не существует)"
+ user:
+ name: "{{ deploy_user }}"
+ uid: "{{ uid }}"
+ group: "{{ gid }}"
+ shell: /bin/zsh
+ create_home: yes
+ system: no
+ groups: docker
+ append: yes
+ when: user_exists.ansible_facts.getent_passwd is not defined
- - name: Включить UFW (файрвол)
- ufw:
- state: enabled
+ - name: "[4/10] Установить zsh как оболочку по умолчанию для существующего пользователя deploy"
+ user:
+ name: "{{ deploy_user }}"
+ shell: /bin/zsh
+ when: user_exists.ansible_facts.getent_passwd is defined
- - name: Открыть порты для сервисов
- ufw:
- rule: allow
- port: "{{ item }}"
- proto: tcp
+ - name: "[4/10] Скопировать SSH ключ с локальной машины для пользователя deploy"
+ authorized_key:
+ user: "{{ deploy_user }}"
+ key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
+ state: present
+
+ - name: "[4/10] Настроить sudo для deploy (только Docker команды)"
+ lineinfile:
+ path: /etc/sudoers.d/deploy
+ line: "{{ deploy_user }} ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/docker-compose, /usr/bin/make"
+ create: yes
+ mode: '0440'
+ validate: 'visudo -cf %s'
+
+ - name: "[4/10] Удалить /home/prod, если требуется (чистое развертывание)"
+ file:
+ path: "{{ project_root }}"
+ state: absent
+ when: recreate_project | bool
+
+ - name: "[4/10] Создать директорию проекта /home/prod"
+ file:
+ path: "{{ project_root }}"
+ state: directory
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0755'
+
+ - name: "[4/10] Скопировать приватный SSH ключ для Git"
+ copy:
+ src: "~/.ssh/id_rsa"
+ dest: "/home/{{ deploy_user }}/.ssh/id_rsa"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0600'
+ remote_src: no
+
+ - name: "[4/10] Настроить SSH config для GitHub"
+ lineinfile:
+ path: "/home/{{ deploy_user }}/.ssh/config"
+ line: "Host github.com\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null"
+ create: yes
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0600'
+
+ # ========================================
+ # ЭТАП 5: КЛОНИРОВАНИЕ РЕПОЗИТОРИЕВ (DEPLOY)
+ # ========================================
+
+ - name: "[5/10] Клонировать основной репозиторий prod"
+ git:
+ repo: git@github.com:KerradKerridi/prod.git
+ dest: "{{ project_root }}"
+ update: yes
+ force: yes
+ become: yes
+ become_user: "{{ deploy_user }}"
+
+ - name: "[5/10] Клонировать AnonBot"
+ git:
+ repo: git@github.com:KerradKerridi/AnonBot.git
+ dest: "{{ project_root }}/bots/AnonBot"
+ update: yes
+ force: yes
+ become: yes
+ become_user: "{{ deploy_user }}"
+
+ - name: "[5/10] Клонировать telegram-helper-bot"
+ git:
+ repo: git@github.com:KerradKerridi/telegram-helper-bot.git
+ dest: "{{ project_root }}/bots/telegram-helper-bot"
+ version: dev-9
+ update: yes
+ force: yes
+ become: yes
+ become_user: "{{ deploy_user }}"
+
+ # ========================================
+ # ЭТАП 6: КОПИРОВАНИЕ КОНФИГУРАЦИЙ (ROOT)
+ # ========================================
+
+ - name: "[6/10] Скопировать конфигурацию Alertmanager"
+ copy:
+ src: "{{ project_root }}/infra/alertmanager/alertmanager.yml"
+ dest: "{{ project_root }}/infra/alertmanager/alertmanager.yml"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+ backup: yes
+ remote_src: yes
+
+ - name: "[6/10] Скопировать правила алертов Prometheus"
+ copy:
+ src: "{{ project_root }}/infra/prometheus/alert_rules.yml"
+ dest: "{{ project_root }}/infra/prometheus/alert_rules.yml"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+ backup: yes
+ remote_src: yes
+
+ - name: "[6/10] Скопировать дашборды Grafana"
+ copy:
+ src: "{{ project_root }}/infra/grafana/dashboards/"
+ dest: "{{ project_root }}/infra/grafana/dashboards/"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+ backup: yes
+ remote_src: yes
+
+ - name: "[6/10] Скопировать скрипт настройки SSL"
+ copy:
+ src: "{{ project_root }}/scripts/setup-ssl.sh"
+ dest: /usr/local/bin/setup-ssl.sh
+ owner: root
+ group: root
+ mode: '0755'
+ backup: yes
+ remote_src: yes
+
+ - name: "[6/10] Установить правильные права на дашборд Node Exporter Full"
+ file:
+ path: "{{ project_root }}/infra/grafana/provisioning/dashboards/node-exporter-full-dashboard.json"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ # ========================================
+ # ЭТАП 7: КОПИРОВАНИЕ ДАННЫХ СО СТАРОГО СЕРВЕРА (ROOT)
+ # ========================================
+
+ - name: "[7/10] Скопировать SSH ключ на старый сервер для копирования файлов"
+ authorized_key:
+ user: root
+ key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
+ state: present
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Копировать .env для telegram-helper-bot со старого сервера"
+ fetch:
+ src: "/home/prod/bots/telegram-helper-bot/.env"
+ dest: "/tmp/telegram-helper-bot.env"
+ flat: yes
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Переместить .env для telegram-helper-bot на новое место"
+ copy:
+ src: "/tmp/telegram-helper-bot.env"
+ dest: "{{ project_root }}/bots/telegram-helper-bot/.env"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ - name: "[7/10] Проверить размер БД для telegram-helper-bot"
+ stat:
+ path: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
+ delegate_to: "{{ old_server }}"
+ register: db_size
+
+ - name: "[7/10] Показать размер БД для telegram-helper-bot"
+ debug:
+ msg: "Размер БД: {{ (db_size.stat.size / 1024 / 1024) | round(2) }} MB"
+
+ - name: "[7/10] Копировать БД для telegram-helper-bot"
+ fetch:
+ src: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
+ dest: "/tmp/tg-bot-database.db"
+ flat: yes
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Переместить БД для telegram-helper-bot на новое место"
+ copy:
+ src: "/tmp/tg-bot-database.db"
+ dest: "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ - name: "[7/10] Создать папку voice_users на новом сервере"
+ file:
+ path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
+ state: directory
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0755'
+
+ - name: "[7/10] Создать временную папку для voice_users на локальной машине"
+ file:
+ path: "/tmp/voice_users_migration"
+ state: directory
+ mode: '0755'
+ delegate_to: localhost
+ become: no
+
+ - name: "[7/10] Копировать voice_users со старого сервера на локальную машину"
+ command: >
+ rsync -avz --progress --stats --partial --verbose
+ root@77.223.98.129:/home/prod/bots/telegram-helper-bot/voice_users/
+ /tmp/voice_users_migration/
+ delegate_to: localhost
+ become: no
+
+ - name: "[7/10] Копировать voice_users с локальной машины на новый сервер"
+ synchronize:
+ src: "/tmp/voice_users_migration/"
+ dest: "{{ project_root }}/bots/telegram-helper-bot/voice_users/"
+ mode: push
+ rsync_opts: "--progress --stats --partial --verbose"
+
+ - name: "[7/10] Очистить временную папку на локальной машине"
+ file:
+ path: "/tmp/voice_users_migration"
+ state: absent
+ delegate_to: localhost
+ become: no
+
+ - name: "[7/10] Копировать корневой .env файл"
+ fetch:
+ src: "/home/prod/.env"
+ dest: "/tmp/root.env"
+ flat: yes
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Переместить корневой .env файл на новое место"
+ copy:
+ src: "/tmp/root.env"
+ dest: "{{ project_root }}/.env"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ - name: "[7/10] Копировать .env для AnonBot"
+ fetch:
+ src: "/home/prod/bots/AnonBot/.env"
+ dest: "/tmp/anonbot.env"
+ flat: yes
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Переместить .env для AnonBot на новое место"
+ copy:
+ src: "/tmp/anonbot.env"
+ dest: "{{ project_root }}/bots/AnonBot/.env"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ - name: "[7/10] Проверить размер БД для AnonBot"
+ stat:
+ path: "/home/prod/bots/AnonBot/database/anon_qna.db"
+ delegate_to: "{{ old_server }}"
+ register: anon_db_size
+
+ - name: "[7/10] Показать размер БД для AnonBot"
+ debug:
+ msg: "Размер БД AnonBot: {{ (anon_db_size.stat.size / 1024 / 1024) | round(2) }} MB"
+
+ - name: "[7/10] Копировать БД для AnonBot"
+ fetch:
+ src: "/home/prod/bots/AnonBot/database/anon_qna.db"
+ dest: "/tmp/anon_qna.db"
+ flat: yes
+ delegate_to: "{{ old_server }}"
+
+ - name: "[7/10] Переместить БД для AnonBot на новое место"
+ copy:
+ src: "/tmp/anon_qna.db"
+ dest: "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
+
+ - name: "[7/10] Установить права на скопированные файлы"
+ file:
+ path: "{{ item }}"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0644'
loop:
- - "8080" # Telegram Bot
- - "8081" # AnonBot
- - "9090" # Prometheus
- - "3000" # Grafana
- - "9100" # Node Exporter
- - "80" # HTTP
- - "443" # HTTPS
+ - "{{ project_root }}/bots/telegram-helper-bot/.env"
+ - "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
+ - "{{ project_root }}/bots/AnonBot/.env"
+ - "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
- # --- НАСТРОЙКА NGINX ---
- - name: Остановить nginx (если запущен)
+ - name: "[7/10] Исправить права доступа для voice_users (рекурсивно)"
+ file:
+ path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
+ owner: "{{ deploy_user }}"
+ group: "{{ deploy_user }}"
+ mode: '0755'
+ recurse: yes
+
+ # ========================================
+ # ЭТАП 8: NGINX КОНФИГУРАЦИЯ (ROOT)
+ # ========================================
+
+ - name: "[8/10] Остановить nginx (если запущен)"
systemd:
name: nginx
state: stopped
ignore_errors: yes
- - name: Создать директории для nginx конфигураций
+ - name: "[8/10] Создать директории для nginx конфигураций"
file:
path: "{{ item }}"
state: directory
@@ -292,7 +599,7 @@
- "{{ project_root }}/infra/grafana/dashboards"
- "{{ project_root }}/scripts"
- - name: Сгенерировать самоподписанный SSL сертификат (fallback)
+ - name: "[8/10] Сгенерировать самоподписанный SSL сертификат (fallback)"
command: >
openssl req -x509 -newkey rsa:4096 -keyout {{ project_root }}/infra/nginx/ssl/key.pem
-out {{ project_root }}/infra/nginx/ssl/cert.pem -days 365 -nodes
@@ -301,7 +608,7 @@
creates: "{{ project_root }}/infra/nginx/ssl/cert.pem"
when: not use_letsencrypt | default(false)
- - name: Создать директории для Let's Encrypt
+ - name: "[8/10] Создать директории для Let's Encrypt"
file:
path: "{{ item }}"
state: directory
@@ -315,14 +622,14 @@
- /etc/letsencrypt/renewal
when: use_letsencrypt | default(false)
- - name: Настроить cron для автоматического обновления SSL сертификатов
+ - name: "[8/10] Настроить cron для автоматического обновления SSL сертификатов"
cron:
name: "SSL Certificate Renewal"
job: "0 2 * * 1 /usr/local/bin/ssl-renewal.sh"
user: root
when: use_letsencrypt | default(false)
- - name: Установить права на SSL сертификаты
+ - name: "[8/10] Установить права на SSL сертификаты"
file:
path: "{{ item }}"
owner: root
@@ -332,7 +639,7 @@
- "{{ project_root }}/infra/nginx/ssl/cert.pem"
- "{{ project_root }}/infra/nginx/ssl/key.pem"
- - name: Создать htpasswd файл для status page
+ - name: "[8/10] Создать htpasswd файл для status page"
htpasswd:
path: "{{ project_root }}/infra/nginx/.htpasswd"
name: "admin"
@@ -341,37 +648,59 @@
group: root
mode: '0644'
- - name: Скопировать основную конфигурацию nginx
- copy:
- src: "{{ project_root }}/infra/nginx/nginx.conf"
+ - name: "[8/10] Удалить старую конфигурацию nginx"
+ file:
+ path: /etc/nginx/nginx.conf
+ state: absent
+
+ - name: "[8/10] Скопировать основную конфигурацию nginx"
+ template:
+ src: "/Users/andrejkatyhin/PycharmProjects/prod/infra/nginx/nginx.conf"
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: yes
- remote_src: yes
+ vars:
+ SERVER_IP: "{{ ansible_host }}"
- - name: Скопировать конфигурации nginx для сервисов
+ - name: "[8/10] Скопировать конфигурации nginx для сервисов"
copy:
- src: "{{ project_root }}/infra/nginx/conf.d/"
+ src: "/Users/andrejkatyhin/PycharmProjects/prod/infra/nginx/conf.d/"
dest: /etc/nginx/conf.d/
owner: root
group: root
mode: '0644'
backup: yes
- remote_src: yes
- - name: Скопировать SSL сертификаты
- copy:
- src: "{{ project_root }}/infra/nginx/ssl/"
- dest: /etc/nginx/ssl/
+ - name: "[8/10] Создать директорию для SSL сертификатов"
+ file:
+ path: /etc/nginx/ssl
+ state: directory
+ owner: root
+ group: root
+ mode: '0755'
+
+ - name: "[8/10] Сгенерировать самоподписанный SSL сертификат"
+ command: >
+ openssl req -x509 -nodes -days 365 -newkey rsa:2048
+ -keyout /etc/nginx/ssl/privkey.pem
+ -out /etc/nginx/ssl/fullchain.pem
+ -subj "/C=RU/ST=Moscow/L=Moscow/O=Bot Infrastructure/OU=IT Department/CN={{ ansible_host }}"
+ args:
+ creates: /etc/nginx/ssl/fullchain.pem
+
+ - name: "[8/10] Установить права на SSL сертификаты"
+ file:
+ path: "{{ item }}"
owner: root
group: root
mode: '0600'
- backup: yes
- remote_src: yes
+ loop:
+ - /etc/nginx/ssl/privkey.pem
+ - /etc/nginx/ssl/fullchain.pem
- - name: Скопировать htpasswd файл
+ - name: "[8/10] Скопировать htpasswd файл"
copy:
src: "{{ project_root }}/infra/nginx/.htpasswd"
dest: /etc/nginx/.htpasswd
@@ -381,108 +710,53 @@
backup: yes
remote_src: yes
- - name: Скопировать конфигурацию Alertmanager
- copy:
- src: "{{ project_root }}/infra/alertmanager/alertmanager.yml"
- dest: "{{ project_root }}/infra/alertmanager/alertmanager.yml"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- backup: yes
- remote_src: yes
-
- - name: Скопировать правила алертов Prometheus
- copy:
- src: "{{ project_root }}/infra/prometheus/alert_rules.yml"
- dest: "{{ project_root }}/infra/prometheus/alert_rules.yml"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- backup: yes
- remote_src: yes
-
- - name: Скопировать дашборды Grafana
- copy:
- src: "{{ project_root }}/infra/grafana/dashboards/"
- dest: "{{ project_root }}/infra/grafana/dashboards/"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- backup: yes
- remote_src: yes
-
- - name: Скопировать скрипт настройки SSL
- copy:
- src: "{{ project_root }}/scripts/setup-ssl.sh"
- dest: /usr/local/bin/setup-ssl.sh
- owner: root
- group: root
- mode: '0755'
- backup: yes
- remote_src: yes
-
- - name: Проверить конфигурацию nginx
- command: nginx -t
- register: nginx_config_test
- changed_when: false
-
- - name: Показать результат проверки nginx
- debug:
- var: nginx_config_test.stdout_lines
-
- - name: Включить и запустить nginx
+ - name: "[8/10] Включить nginx (запустим позже после контейнеров)"
systemd:
name: nginx
enabled: yes
- state: started
+ state: stopped
- - name: Проверить статус nginx
- command: systemctl status nginx
- register: nginx_status
- changed_when: false
- - name: Показать статус nginx
- debug:
- var: nginx_status.stdout_lines
+ # ========================================
+ # ЭТАП 9: БЕЗОПАСНОСТЬ И ФАЙРВОЛ (ROOT)
+ # ========================================
+
+ - name: "[9/10] Разрешить SSH (порт 22) перед включением UFW"
+ ufw:
+ rule: allow
+ port: "22"
+ proto: tcp
- - name: Проверить существование пользователя deploy
- getent:
- database: passwd
- key: "{{ deploy_user }}"
- register: user_exists
- failed_when: false
+ - name: "[9/10] Разрешить новый SSH порт (15722) перед включением UFW"
+ ufw:
+ rule: allow
+ port: "15722"
+ proto: tcp
- - name: Создать группу deploy с GID 1001
- group:
- name: "{{ deploy_user }}"
- gid: "{{ gid }}"
- when: user_exists.ansible_facts.getent_passwd is not defined
+ - name: "[9/10] Настроить политику UFW по умолчанию"
+ ufw:
+ policy: deny
+ direction: incoming
- - name: Создать пользователя deploy с UID 1001 (если не существует)
- user:
- name: "{{ deploy_user }}"
- uid: "{{ uid }}"
- group: "{{ gid }}"
- shell: /bin/zsh
- create_home: yes
- system: no
- groups: docker
- append: yes
- when: user_exists.ansible_facts.getent_passwd is not defined
+ - name: "[9/10] Включить UFW (файрвол)"
+ ufw:
+ state: enabled
- - name: Установить zsh как оболочку по умолчанию для существующего пользователя deploy
- user:
- name: "{{ deploy_user }}"
- shell: /bin/zsh
- when: user_exists.ansible_facts.getent_passwd is defined
+ - name: "[9/10] Открыть порты для сервисов"
+ ufw:
+ rule: allow
+ port: "{{ item }}"
+ proto: tcp
+ loop:
+ - "8080" # Telegram Bot
+ - "8081" # AnonBot
+ - "9090" # Prometheus
+ - "3000" # Grafana
+ - "9100" # Node Exporter
+ - "80" # HTTP
+ - "443" # HTTPS
- - name: Скопировать SSH ключ с локальной машины для пользователя deploy
- authorized_key:
- user: "{{ deploy_user }}"
- key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- state: present
-
- - name: Настроить безопасный SSH
+ - name: "[9/10] Настроить безопасный SSH"
lineinfile:
path: /etc/ssh/sshd_config
regexp: "^{{ item.regexp }}"
@@ -496,275 +770,7 @@
- { regexp: "AllowUsers", line: "AllowUsers {{ deploy_user }}" }
notify: reload ssh
- - name: Переподключиться по новому SSH порту
- meta: reset_connection
-
- - name: Удалить /home/prod, если требуется (чистое развертывание)
- file:
- path: "{{ project_root }}"
- state: absent
- when: recreate_project | bool
-
- - name: Создать директорию проекта /home/prod
- file:
- path: "{{ project_root }}"
- state: directory
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0755'
-
- - name: Настроить SSH ключи для GitHub
- authorized_key:
- user: "{{ deploy_user }}"
- key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- state: present
-
- - name: Скопировать приватный SSH ключ для Git
- copy:
- src: "~/.ssh/id_rsa"
- dest: "/home/{{ deploy_user }}/.ssh/id_rsa"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0600'
- remote_src: no
-
- - name: Настроить SSH config для GitHub
- lineinfile:
- path: "/home/{{ deploy_user }}/.ssh/config"
- line: "Host github.com\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null"
- create: yes
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0600'
-
- - name: Переключиться на пользователя deploy
- meta: reset_connection
-
- - name: Клонировать основной репозиторий prod
- git:
- repo: git@github.com:KerradKerridi/prod.git
- dest: "{{ project_root }}"
- clone: yes
- update: yes
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Клонировать AnonBot
- git:
- repo: git@github.com:KerradKerridi/AnonBot.git
- dest: "{{ project_root }}/bots/AnonBot"
- clone: yes
- update: yes
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Клонировать telegram-helper-bot
- git:
- repo: git@github.com:KerradKerridi/telegram-helper-bot.git
- dest: "{{ project_root }}/bots/telegram-helper-bot"
- # TODO: Убрать после тестирования
- version: dev-9
- clone: yes
- update: yes
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Установить правильные права на дашборд Node Exporter Full
- file:
- path: "{{ project_root }}/infra/grafana/provisioning/dashboards/node-exporter-full-dashboard.json"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Скопировать SSH ключ на старый сервер для копирования файлов
- authorized_key:
- user: root
- key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
- state: present
- delegate_to: "{{ old_server }}"
-
- - name: Копировать .env для telegram-helper-bot со старого сервера
- fetch:
- src: "/home/prod/bots/telegram-helper-bot/.env"
- dest: "/tmp/telegram-helper-bot.env"
- flat: yes
- delegate_to: "{{ old_server }}"
-
- - name: Переместить .env для telegram-helper-bot на новое место
- copy:
- src: "/tmp/telegram-helper-bot.env"
- dest: "{{ project_root }}/bots/telegram-helper-bot/.env"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Проверить размер БД для telegram-helper-bot
- stat:
- path: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
- delegate_to: "{{ old_server }}"
- register: db_size
-
- - name: Показать размер БД для telegram-helper-bot
- debug:
- msg: "Размер БД: {{ (db_size.stat.size / 1024 / 1024) | round(2) }} MB"
-
- - name: Копировать БД для telegram-helper-bot
- fetch:
- src: "/home/prod/bots/telegram-helper-bot/database/tg-bot-database.db"
- dest: "/tmp/tg-bot-database.db"
- flat: yes
- delegate_to: "{{ old_server }}"
-
- - name: Переместить БД для telegram-helper-bot на новое место
- copy:
- src: "/tmp/tg-bot-database.db"
- dest: "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Создать папку voice_users на новом сервере
- file:
- path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
- state: directory
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0755'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Создать временную папку для voice_users на локальной машине
- file:
- path: "/tmp/voice_users_migration"
- state: directory
- mode: '0755'
- delegate_to: localhost
- become: no
-
- - name: Копировать voice_users со старого сервера на локальную машину
- command: >
- rsync -avz --progress --stats --partial --verbose
- root@77.223.98.129:/home/prod/bots/telegram-helper-bot/voice_users/
- /tmp/voice_users_migration/
- delegate_to: localhost
- become: no
-
- - name: Копировать voice_users с локальной машины на новый сервер
- synchronize:
- src: "/tmp/voice_users_migration/"
- dest: "{{ project_root }}/bots/telegram-helper-bot/voice_users/"
- mode: push
- rsync_opts: "--progress --stats --partial --verbose"
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Очистить временную папку на локальной машине
- file:
- path: "/tmp/voice_users_migration"
- state: absent
- delegate_to: localhost
- become: no
-
- - name: Копировать корневой .env файл
- fetch:
- src: "/home/prod/.env"
- dest: "/tmp/root.env"
- flat: yes
- delegate_to: "{{ old_server }}"
-
- - name: Переместить корневой .env файл на новое место
- copy:
- src: "/tmp/root.env"
- dest: "{{ project_root }}/.env"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
-
- - name: Копировать .env для AnonBot
- fetch:
- src: "/home/prod/bots/AnonBot/.env"
- dest: "/tmp/anonbot.env"
- flat: yes
- delegate_to: "{{ old_server }}"
-
- - name: Переместить .env для AnonBot на новое место
- copy:
- src: "/tmp/anonbot.env"
- dest: "{{ project_root }}/bots/AnonBot/.env"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Проверить размер БД для AnonBot
- stat:
- path: "/home/prod/bots/AnonBot/database/anon_qna.db"
- delegate_to: "{{ old_server }}"
- register: anon_db_size
-
- - name: Показать размер БД для AnonBot
- debug:
- msg: "Размер БД AnonBot: {{ (anon_db_size.stat.size / 1024 / 1024) | round(2) }} MB"
-
- - name: Копировать БД для AnonBot
- fetch:
- src: "/home/prod/bots/AnonBot/database/anon_qna.db"
- dest: "/tmp/anon_qna.db"
- flat: yes
- delegate_to: "{{ old_server }}"
-
- - name: Переместить БД для AnonBot на новое место
- copy:
- src: "/tmp/anon_qna.db"
- dest: "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- become: yes
- become_user: "{{ deploy_user }}"
-
- - name: Установить права на скопированные файлы
- file:
- path: "{{ item }}"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0644'
- loop:
- - "{{ project_root }}/bots/telegram-helper-bot/.env"
- - "{{ project_root }}/bots/telegram-helper-bot/database/tg-bot-database.db"
- - "{{ project_root }}/bots/AnonBot/.env"
- - "{{ project_root }}/bots/AnonBot/database/anon_qna.db"
- become: yes
-
- - name: Исправить права доступа для voice_users (рекурсивно)
- file:
- path: "{{ project_root }}/bots/telegram-helper-bot/voice_users"
- owner: "{{ deploy_user }}"
- group: "{{ deploy_user }}"
- mode: '0755'
- recurse: yes
- become: yes
-
- - name: Запустить ботов через make up
- command: make up
- args:
- chdir: "{{ project_root }}"
- become: yes
- become_user: "{{ deploy_user }}"
- tags: ["start_bots"]
-
- # --- НАСТРОЙКА FAIL2BAN ---
- - name: Создать конфигурацию Fail2ban для SSH
+ - name: "[9/10] Создать конфигурацию Fail2ban для SSH"
copy:
content: |
[sshd]
@@ -780,7 +786,7 @@
group: root
mode: '0644'
- - name: Создать конфигурацию Fail2ban для Nginx
+ - name: "[9/10] Создать конфигурацию Fail2ban для Nginx"
copy:
content: |
[nginx-http-auth]
@@ -805,7 +811,7 @@
group: root
mode: '0644'
- - name: Создать конфигурацию Fail2ban для Docker
+ - name: "[9/10] Создать конфигурацию Fail2ban для Docker"
copy:
content: |
[docker]
@@ -821,90 +827,124 @@
group: root
mode: '0644'
- - name: Включить и запустить Fail2ban
+ - name: "[9/10] Включить и запустить Fail2ban"
systemd:
name: fail2ban
enabled: yes
state: started
- - name: Проверить статус Fail2ban
+ - name: "[9/10] Проверить статус Fail2ban"
command: fail2ban-client status
register: fail2ban_status
changed_when: false
- - name: Показать статус Fail2ban
+ - name: "[9/10] Показать статус Fail2ban"
debug:
var: fail2ban_status.stdout_lines
- # --- НОВОЕ: Проверка портов ---
- - name: Пауза на 30 секунд — дать контейнерам запуститься
- pause:
- seconds: 30
+ # ========================================
+ # ЭТАП 10: ЗАПУСК ПРИЛОЖЕНИЙ И ПРОВЕРКИ (DEPLOY + ROOT)
+ # ========================================
+
+ - name: "[10/10] Запустить ботов через make up"
+ command: make up
+ args:
+ chdir: "{{ project_root }}"
+ become: yes
+ become_user: "{{ deploy_user }}"
- - name: Проверить, что порт 8080 (Telegram Bot) открыт
+ - name: "[10/10] Пауза на 45 секунд — дать контейнерам запуститься"
+ pause:
+ seconds: 45
+
+ - name: "[10/10] Проверить конфигурацию nginx (после запуска контейнеров)"
+ command: nginx -t
+ register: nginx_config_test
+ changed_when: false
+
+ - name: "[10/10] Показать результат проверки nginx"
+ debug:
+ var: nginx_config_test.stdout_lines
+
+ - name: "[10/10] Запустить nginx (после запуска контейнеров)"
+ systemd:
+ name: nginx
+ state: started
+
+ - name: "[10/10] Проверить статус nginx"
+ command: systemctl status nginx
+ register: nginx_status
+ changed_when: false
+
+ - name: "[10/10] Показать статус nginx"
+ debug:
+ var: nginx_status.stdout_lines
+
+ - name: "[10/10] Проверить, что порт 8080 (Telegram Bot) открыт"
wait_for:
port: 8080
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 8081 (AnonBot) открыт
+ - name: "[10/10] Проверить, что порт 8081 (AnonBot) открыт"
wait_for:
port: 8081
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 9090 (Prometheus) открыт
+ - name: "[10/10] Проверить, что порт 9090 (Prometheus) открыт"
wait_for:
port: 9090
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 3000 (Grafana) открыт
+ - name: "[10/10] Проверить, что порт 3000 (Grafana) открыт"
wait_for:
port: 3000
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 9100 (Node Exporter) открыт
+ - name: "[10/10] Проверить, что порт 9100 (Node Exporter) открыт"
wait_for:
port: 9100
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 80 (Nginx HTTP) открыт
+ - name: "[10/10] Проверить, что порт 80 (Nginx HTTP) открыт"
wait_for:
port: 80
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 443 (Nginx HTTPS) открыт
+ - name: "[10/10] Проверить, что порт 443 (Nginx HTTPS) открыт"
wait_for:
port: 443
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 3001 (Uptime Kuma) открыт
+ - name: "[10/10] Проверить, что порт 3001 (Uptime Kuma) открыт"
wait_for:
port: 3001
host: "{{ ansible_host }}"
timeout: 30
state: started
- - name: Проверить, что порт 9093 (Alertmanager) открыт
- wait_for:
- port: 9093
- host: "{{ ansible_host }}"
- timeout: 30
- state: started
+ # - name: "[10/10] Проверить, что порт 9093 (Alertmanager) открыт"
+ # wait_for:
+ # port: 9093
+ # host: "{{ ansible_host }}"
+ # timeout: 30
+ # state: started
+ # # Пропускаем проверку Alertmanager, так как есть проблемы с конфигурацией
- - name: Проверить доступность Nginx
+ - name: "[10/10] Проверить доступность Nginx"
uri:
url: "http://{{ ansible_host }}/nginx-health"
method: GET
@@ -913,7 +953,7 @@
retries: 5
delay: 10
- - name: Проверить доступность Grafana через Nginx
+ - name: "[10/10] Проверить доступность Grafana через Nginx"
uri:
url: "https://{{ ansible_host }}/grafana/api/health"
method: GET
@@ -923,7 +963,7 @@
retries: 5
delay: 10
- - name: Проверить доступность Prometheus через Nginx
+ - name: "[10/10] Проверить доступность Prometheus через Nginx"
uri:
url: "https://{{ ansible_host }}/prometheus/-/healthy"
method: GET
@@ -933,7 +973,7 @@
retries: 5
delay: 10
- - name: Проверить доступность Grafana API
+ - name: "[10/10] Проверить доступность Grafana API"
uri:
url: "http://{{ ansible_host }}:3000/api/health"
method: GET
@@ -942,7 +982,7 @@
retries: 5
delay: 10
- - name: Проверить доступность Uptime Kuma через Nginx
+ - name: "[10/10] Проверить доступность Uptime Kuma через Nginx"
uri:
url: "https://{{ ansible_host }}/status"
method: GET
@@ -952,7 +992,7 @@
retries: 5
delay: 10
- - name: Проверить доступность Alertmanager через Nginx
+ - name: "[10/10] Проверить доступность Alertmanager через Nginx"
uri:
url: "https://{{ ansible_host }}/alertmanager/"
method: GET
@@ -962,14 +1002,16 @@
retries: 5
delay: 10
+ - name: "[10/10] Переподключиться по новому SSH порту"
+ meta: reset_connection
- - name: Закрыть старый SSH порт 22 в UFW (финальный шаг)
+ - name: "[10/10] Закрыть старый SSH порт 22 в UFW (финальный шаг)"
ufw:
rule: deny
port: "22"
proto: tcp
- - name: Проверка запуска ботов завершена — всё работает 🟢
+ - name: "[10/10] Проверка запуска ботов завершена — всё работает 🟢"
debug:
msg: "Все сервисы запущены и слушают нужные порты. SSH настроен на порт 15722, Fail2ban активен, параметры безопасности ядра применены. Порт 22 закрыт для безопасности. Добавлены: Uptime Kuma (статусная страница), Alertmanager (мониторинг), Let's Encrypt SSL, Grafana дашборды."
diff --git a/infra/nginx/conf.d/alertmanager.conf b/infra/nginx/conf.d/alertmanager.conf
index 4406026..98ac5c5 100644
--- a/infra/nginx/conf.d/alertmanager.conf
+++ b/infra/nginx/conf.d/alertmanager.conf
@@ -2,12 +2,12 @@
# Proxies requests to Alertmanager
# Alertmanager location
-location /alertmanager/ {
+location /alerts/ {
# Rate limiting
limit_req zone=api burst=10 nodelay;
# Remove trailing slash for proxy
- rewrite ^/alertmanager/(.*)$ /$1 break;
+ rewrite ^/alerts/(.*)$ /$1 break;
# Proxy to Alertmanager
proxy_pass http://alertmanager_backend;
diff --git a/infra/nginx/conf.d/grafana.conf b/infra/nginx/conf.d/grafana.conf
index 166b8b5..4ad4931 100644
--- a/infra/nginx/conf.d/grafana.conf
+++ b/infra/nginx/conf.d/grafana.conf
@@ -1,6 +1,6 @@
# Grafana proxy configuration
location /grafana/ {
- proxy_pass http://grafana_backend/;
+ proxy_pass http://grafana_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
diff --git a/infra/nginx/conf.d/status.conf b/infra/nginx/conf.d/status.conf
deleted file mode 100644
index 13bcc62..0000000
--- a/infra/nginx/conf.d/status.conf
+++ /dev/null
@@ -1,43 +0,0 @@
-# Status page configuration (Uptime Kuma integration)
-
-# Rate limiting for status page
-location /status {
- # Rate limiting
- limit_req zone=status burst=5 nodelay;
-
- # Proxy to Uptime Kuma
- proxy_pass http://uptime_kuma_backend;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
-
- # Timeouts
- proxy_connect_timeout 30s;
- proxy_send_timeout 30s;
- proxy_read_timeout 30s;
-
- # Buffer settings
- proxy_buffering on;
- proxy_buffer_size 4k;
- proxy_buffers 8 4k;
-
- # Security headers
- add_header X-Frame-Options "SAMEORIGIN" always;
- add_header X-Content-Type-Options "nosniff" always;
-}
-
-# Nginx status stub (for monitoring)
-location /nginx_status {
- stub_status on;
- access_log off;
- allow 127.0.0.1;
- allow 172.16.0.0/12; # Docker networks
- allow 192.168.0.0/16; # Private networks
- deny all;
-}
\ No newline at end of file
diff --git a/infra/nginx/conf.d/uptime-kuma.conf b/infra/nginx/conf.d/uptime-kuma.conf
index 7c77a1f..cd8afe3 100644
--- a/infra/nginx/conf.d/uptime-kuma.conf
+++ b/infra/nginx/conf.d/uptime-kuma.conf
@@ -1,12 +1,6 @@
# Uptime Kuma Nginx Configuration
# Proxies requests to Uptime Kuma status page
-# Upstream for Uptime Kuma
-upstream uptime_kuma_backend {
- server uptime-kuma:3001;
- keepalive 32;
-}
-
# Status page location
location /status {
# Rate limiting
diff --git a/infra/nginx/nginx.conf b/infra/nginx/nginx.conf
index aaffe7d..b346958 100644
--- a/infra/nginx/nginx.conf
+++ b/infra/nginx/nginx.conf
@@ -1,4 +1,4 @@
-user nginx;
+user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
@@ -65,26 +65,27 @@ http {
# Upstream configurations
upstream grafana_backend {
- server grafana:3000;
+ server localhost:3000;
keepalive 32;
}
upstream prometheus_backend {
- server prometheus:9090;
+ server localhost:9090;
keepalive 32;
}
upstream uptime_kuma_backend {
- server uptime-kuma:3001;
+ server localhost:3001;
keepalive 32;
}
upstream alertmanager_backend {
- server alertmanager:9093;
+ server localhost:9093;
keepalive 32;
}
# Main server block
+ # Redirect HTTP to HTTPS
server {
listen 80;
server_name _;
@@ -96,8 +97,8 @@ http {
server_name _;
# SSL configuration (self-signed certificate)
- ssl_certificate /etc/letsencrypt/live/{{SERVER_IP}}/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/{{SERVER_IP}}/privkey.pem;еще
+ ssl_certificate /etc/nginx/ssl/fullchain.pem;
+ ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
@@ -108,9 +109,10 @@ http {
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
- # Redirect root to Grafana
+ # Root page - show simple status
location = / {
- return 301 /grafana/;
+ return 200 "Bot Infrastructure Status\n\nServices:\n- Grafana: /grafana/\n- Prometheus: /prometheus/\n- Uptime Kuma: /status/\n- Alertmanager: /alerts/\n";
+ add_header Content-Type text/plain;
}
# Health check endpoint
diff --git a/infra/prometheus/prometheus.yml b/infra/prometheus/prometheus.yml
index fe9481b..9eb8da9 100644
--- a/infra/prometheus/prometheus.yml
+++ b/infra/prometheus/prometheus.yml
@@ -13,7 +13,7 @@ scrape_configs:
# Job для мониторинга Node Exporter
- job_name: 'node'
static_configs:
- - targets: ['172.17.0.1:9100'] # Специальное имя для доступа к хосту
+ - targets: ['172.20.0.1:9100'] # IP хоста в Docker сети bots_network
labels:
instance: 'main-server'