- Add fail2ban installation and configuration for SSH, Nginx, and Docker - Implement kernel security parameter adjustments to mitigate DDoS and spoofing attacks - Set timezone to Europe/Moscow - Update SSH configuration to use port 15722 and close the default port 22 - Enhance UFW rules to allow new SSH port and restrict access to essential services - Include checks for fail2ban status and debug output for verification
718 lines
24 KiB
YAML
718 lines
24 KiB
YAML
---
|
||
- name: Полная миграция ботов на новый сервер
|
||
hosts: new_server
|
||
become: yes
|
||
|
||
vars:
|
||
# Основная директория проекта
|
||
project_root: "/home/prod"
|
||
# Пользователь и группа
|
||
deploy_user: "deploy"
|
||
uid: "1001"
|
||
gid: "1001"
|
||
# Старый сервер для копирования данных
|
||
old_server: "root@77.223.98.129"
|
||
# Опция: пересоздавать папку /home/prod (по умолчанию — нет)
|
||
recreate_project: false
|
||
# Grafana настройки
|
||
grafana_admin_user: "{{ lookup('env', 'GRAFANA_ADMIN_USER') | default('admin') }}"
|
||
grafana_admin_password: "{{ lookup('env', 'GRAFANA_ADMIN_PASSWORD') | default('admin') }}"
|
||
|
||
tasks:
|
||
- name: Обновить SSH host key для избежания ошибок при переустановке
|
||
known_hosts:
|
||
path: ~/.ssh/known_hosts
|
||
name: "{{ ansible_host }}"
|
||
key: "{{ lookup('pipe', 'ssh-keyscan -t rsa,ecdsa,ed25519 ' + ansible_host) }}"
|
||
state: present
|
||
delegate_to: localhost
|
||
run_once: true
|
||
ignore_errors: yes
|
||
|
||
- name: Обновить кэш пакетов
|
||
apt:
|
||
update_cache: yes
|
||
|
||
- name: Установить необходимые пакеты
|
||
apt:
|
||
name:
|
||
- docker.io
|
||
- docker-compose
|
||
- make
|
||
- git
|
||
- python3-pip
|
||
- curl
|
||
- sshpass
|
||
- rsync
|
||
- vim
|
||
- zsh
|
||
- ufw
|
||
- htop
|
||
- iotop
|
||
- traceroute
|
||
- ncdu
|
||
- prometheus-node-exporter
|
||
- fail2ban
|
||
- tzdata
|
||
state: present
|
||
|
||
- name: Установить часовой пояс Europe/Moscow
|
||
timezone:
|
||
name: Europe/Moscow
|
||
|
||
- name: Проверить существование swap-файла
|
||
stat:
|
||
path: /swapfile
|
||
register: swap_file_stat
|
||
|
||
- name: Создать swap-файл (2GB)
|
||
command: fallocate -l 2G /swapfile
|
||
when: not swap_file_stat.stat.exists
|
||
|
||
- name: Установить правильные права на swap-файл
|
||
file:
|
||
path: /swapfile
|
||
mode: '0600'
|
||
owner: root
|
||
group: root
|
||
|
||
- name: Настроить swap-файл
|
||
command: mkswap /swapfile
|
||
when: not swap_file_stat.stat.exists
|
||
|
||
- name: Включить swap-файл
|
||
command: swapon /swapfile
|
||
when: not swap_file_stat.stat.exists
|
||
|
||
- name: Настроить swappiness = 10 (временно)
|
||
sysctl:
|
||
name: vm.swappiness
|
||
value: '10'
|
||
state: present
|
||
reload: yes
|
||
|
||
- name: Настроить swappiness = 10 (постоянно)
|
||
lineinfile:
|
||
path: /etc/sysctl.conf
|
||
regexp: '^vm\.swappiness\s*='
|
||
line: 'vm.swappiness = 10'
|
||
state: present
|
||
|
||
- name: Добавить swap-файл в /etc/fstab для автоматического монтирования
|
||
lineinfile:
|
||
path: /etc/fstab
|
||
line: '/swapfile none swap sw 0 0'
|
||
state: present
|
||
create: yes
|
||
|
||
# --- НАСТРОЙКА БЕЗОПАСНОСТИ ЯДРА ---
|
||
- name: Настроить параметры безопасности ядра
|
||
sysctl:
|
||
name: "{{ item.name }}"
|
||
value: "{{ item.value }}"
|
||
state: present
|
||
reload: yes
|
||
loop:
|
||
# Защита от DDoS
|
||
- { name: "net.ipv4.tcp_syn_retries", value: "2" }
|
||
- { name: "net.ipv4.tcp_synack_retries", value: "2" }
|
||
- { name: "net.ipv4.tcp_max_syn_backlog", value: "2048" }
|
||
- { name: "net.ipv4.tcp_fin_timeout", value: "15" }
|
||
- { name: "net.ipv4.tcp_keepalive_time", value: "1200" }
|
||
- { name: "net.ipv4.tcp_keepalive_intvl", value: "15" }
|
||
- { name: "net.ipv4.tcp_keepalive_probes", value: "5" }
|
||
- { name: "net.core.netdev_max_backlog", value: "1000" }
|
||
- { name: "net.core.somaxconn", value: "65535" }
|
||
# Защита от IP спуфинга
|
||
- { name: "net.ipv4.conf.all.accept_source_route", value: "0" }
|
||
- { name: "net.ipv4.conf.default.accept_source_route", value: "0" }
|
||
- { name: "net.ipv6.conf.all.accept_source_route", value: "0" }
|
||
- { name: "net.ipv6.conf.default.accept_source_route", value: "0" }
|
||
# Защита от фрагментации
|
||
- { name: "net.ipv4.conf.all.log_martians", value: "1" }
|
||
- { name: "net.ipv4.conf.default.log_martians", value: "1" }
|
||
- { name: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" }
|
||
- { name: "net.ipv4.icmp_ignore_bogus_error_responses", value: "1" }
|
||
- { name: "net.ipv4.tcp_syncookies", value: "1" }
|
||
- { name: "net.ipv4.conf.all.rp_filter", value: "1" }
|
||
- { name: "net.ipv4.conf.default.rp_filter", value: "1" }
|
||
# Для Docker
|
||
- { name: "kernel.pid_max", value: "65536" }
|
||
- { name: "kernel.threads-max", value: "4096" }
|
||
- { name: "vm.max_map_count", value: "262144" }
|
||
|
||
- name: Сохранить параметры безопасности в /etc/sysctl.conf
|
||
lineinfile:
|
||
path: /etc/sysctl.conf
|
||
regexp: "^{{ item.name }}\\s*="
|
||
line: "{{ item.name }} = {{ item.value }}"
|
||
state: present
|
||
loop:
|
||
# Защита от DDoS
|
||
- { name: "net.ipv4.tcp_syn_retries", value: "2" }
|
||
- { name: "net.ipv4.tcp_synack_retries", value: "2" }
|
||
- { name: "net.ipv4.tcp_max_syn_backlog", value: "2048" }
|
||
- { name: "net.ipv4.tcp_fin_timeout", value: "15" }
|
||
- { name: "net.ipv4.tcp_keepalive_time", value: "1200" }
|
||
- { name: "net.ipv4.tcp_keepalive_intvl", value: "15" }
|
||
- { name: "net.ipv4.tcp_keepalive_probes", value: "5" }
|
||
- { name: "net.core.netdev_max_backlog", value: "1000" }
|
||
- { name: "net.core.somaxconn", value: "65535" }
|
||
# Защита от IP спуфинга
|
||
- { name: "net.ipv4.conf.all.accept_source_route", value: "0" }
|
||
- { name: "net.ipv4.conf.default.accept_source_route", value: "0" }
|
||
- { name: "net.ipv6.conf.all.accept_source_route", value: "0" }
|
||
- { name: "net.ipv6.conf.default.accept_source_route", value: "0" }
|
||
# Защита от фрагментации
|
||
- { name: "net.ipv4.conf.all.log_martians", value: "1" }
|
||
- { name: "net.ipv4.conf.default.log_martians", value: "1" }
|
||
- { name: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" }
|
||
- { name: "net.ipv4.icmp_ignore_bogus_error_responses", value: "1" }
|
||
- { name: "net.ipv4.tcp_syncookies", value: "1" }
|
||
- { name: "net.ipv4.conf.all.rp_filter", value: "1" }
|
||
- { name: "net.ipv4.conf.default.rp_filter", value: "1" }
|
||
# Для Docker
|
||
- { name: "kernel.pid_max", value: "65536" }
|
||
- { 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
|
||
systemd:
|
||
name: prometheus-node-exporter
|
||
enabled: yes
|
||
state: started
|
||
|
||
- name: Проверить статус prometheus-node-exporter
|
||
command: systemctl status prometheus-node-exporter
|
||
register: node_exporter_status
|
||
changed_when: false
|
||
|
||
- name: Показать статус prometheus-node-exporter
|
||
debug:
|
||
var: node_exporter_status.stdout_lines
|
||
|
||
- name: Проверить, что node_exporter слушает на порту 9100
|
||
command: netstat -tulpn | grep 9100
|
||
register: node_exporter_port
|
||
changed_when: false
|
||
|
||
- name: Показать информацию о порте 9100
|
||
debug:
|
||
var: node_exporter_port.stdout_lines
|
||
|
||
- name: Обновить 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
|
||
systemd:
|
||
name: docker
|
||
enabled: yes
|
||
state: started
|
||
|
||
- name: Разрешить SSH (порт 22) перед включением UFW
|
||
ufw:
|
||
rule: allow
|
||
port: "22"
|
||
proto: tcp
|
||
|
||
- name: Разрешить новый SSH порт (15722) перед включением UFW
|
||
ufw:
|
||
rule: allow
|
||
port: "15722"
|
||
proto: tcp
|
||
|
||
- name: Настроить политику UFW по умолчанию
|
||
ufw:
|
||
policy: deny
|
||
direction: incoming
|
||
|
||
- name: Включить UFW (файрвол)
|
||
ufw:
|
||
state: enabled
|
||
|
||
- name: Открыть порты для сервисов
|
||
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: Проверить существование пользователя deploy
|
||
getent:
|
||
database: passwd
|
||
key: "{{ deploy_user }}"
|
||
register: user_exists
|
||
failed_when: false
|
||
|
||
- name: Создать группу deploy с GID 1001
|
||
group:
|
||
name: "{{ deploy_user }}"
|
||
gid: "{{ gid }}"
|
||
when: user_exists.ansible_facts.getent_passwd is not defined
|
||
|
||
- 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: Установить zsh как оболочку по умолчанию для существующего пользователя deploy
|
||
user:
|
||
name: "{{ deploy_user }}"
|
||
shell: /bin/zsh
|
||
when: user_exists.ansible_facts.getent_passwd is defined
|
||
|
||
- name: Скопировать SSH ключ с локальной машины для пользователя deploy
|
||
authorized_key:
|
||
user: "{{ deploy_user }}"
|
||
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||
state: present
|
||
|
||
- name: Настроить безопасный SSH
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^{{ item.regexp }}"
|
||
line: "{{ item.line }}"
|
||
backup: yes
|
||
loop:
|
||
- { regexp: "Port", line: "Port 15722" }
|
||
- { regexp: "PermitRootLogin", line: "PermitRootLogin no" }
|
||
- { regexp: "PasswordAuthentication", line: "PasswordAuthentication no" }
|
||
- { regexp: "PubkeyAuthentication", line: "PubkeyAuthentication yes" }
|
||
- { 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"
|
||
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
|
||
copy:
|
||
content: |
|
||
[sshd]
|
||
enabled = true
|
||
port = 15722
|
||
filter = sshd
|
||
logpath = /var/log/auth.log
|
||
maxretry = 3
|
||
bantime = 3600
|
||
findtime = 600
|
||
dest: /etc/fail2ban/jail.d/sshd.local
|
||
owner: root
|
||
group: root
|
||
mode: '0644'
|
||
|
||
- name: Создать конфигурацию Fail2ban для Nginx
|
||
copy:
|
||
content: |
|
||
[nginx-http-auth]
|
||
enabled = true
|
||
port = http,https
|
||
filter = nginx-http-auth
|
||
logpath = /var/log/nginx/error.log
|
||
maxretry = 3
|
||
bantime = 3600
|
||
findtime = 600
|
||
|
||
[nginx-limit-req]
|
||
enabled = true
|
||
port = http,https
|
||
filter = nginx-limit-req
|
||
logpath = /var/log/nginx/error.log
|
||
maxretry = 3
|
||
bantime = 3600
|
||
findtime = 600
|
||
dest: /etc/fail2ban/jail.d/nginx.local
|
||
owner: root
|
||
group: root
|
||
mode: '0644'
|
||
|
||
- name: Создать конфигурацию Fail2ban для Docker
|
||
copy:
|
||
content: |
|
||
[docker]
|
||
enabled = true
|
||
port = 2375,2376
|
||
filter = docker
|
||
logpath = /var/log/syslog
|
||
maxretry = 3
|
||
bantime = 3600
|
||
findtime = 600
|
||
dest: /etc/fail2ban/jail.d/docker.local
|
||
owner: root
|
||
group: root
|
||
mode: '0644'
|
||
|
||
- name: Включить и запустить Fail2ban
|
||
systemd:
|
||
name: fail2ban
|
||
enabled: yes
|
||
state: started
|
||
|
||
- name: Проверить статус Fail2ban
|
||
command: fail2ban-client status
|
||
register: fail2ban_status
|
||
changed_when: false
|
||
|
||
- name: Показать статус Fail2ban
|
||
debug:
|
||
var: fail2ban_status.stdout_lines
|
||
|
||
# --- НОВОЕ: Проверка портов ---
|
||
- name: Пауза на 30 секунд — дать контейнерам запуститься
|
||
pause:
|
||
seconds: 30
|
||
|
||
- name: Проверить, что порт 8080 (Telegram Bot) открыт
|
||
wait_for:
|
||
port: 8080
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 8081 (AnonBot) открыт
|
||
wait_for:
|
||
port: 8081
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 9090 (Prometheus) открыт
|
||
wait_for:
|
||
port: 9090
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 3000 (Grafana) открыт
|
||
wait_for:
|
||
port: 3000
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить, что порт 9100 (Node Exporter) открыт
|
||
wait_for:
|
||
port: 9100
|
||
host: "{{ ansible_host }}"
|
||
timeout: 30
|
||
state: started
|
||
|
||
- name: Проверить доступность Grafana API
|
||
uri:
|
||
url: "http://{{ ansible_host }}:3000/api/health"
|
||
method: GET
|
||
status_code: 200
|
||
register: grafana_health
|
||
retries: 5
|
||
delay: 10
|
||
|
||
|
||
- name: Закрыть старый SSH порт 22 в UFW (финальный шаг)
|
||
ufw:
|
||
rule: deny
|
||
port: "22"
|
||
proto: tcp
|
||
|
||
- name: Проверка запуска ботов завершена — всё работает 🟢
|
||
debug:
|
||
msg: "Все сервисы запущены и слушают нужные порты. SSH настроен на порт 15722, Fail2ban активен, параметры безопасности ядра применены. Порт 22 закрыт для безопасности."
|
||
|
||
# handlers для перезагрузки сервисов
|
||
handlers:
|
||
- name: reload ssh
|
||
systemd:
|
||
name: ssh
|
||
state: reloaded
|
||
|
||
- name: restart ufw
|
||
ufw:
|
||
state: reloaded |