--- - 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 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: Переключиться на root для начальной настройки set_fact: ansible_user: root - 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 state: present - 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: Настроить политику 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 - name: Проверить существование пользователя deploy getent: database: passwd key: "{{ deploy_user }}" register: user_exists failed_when: false - name: Переключиться на пользователя deploy meta: reset_connection - 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: "PermitRootLogin", line: "PermitRootLogin no" } - { regexp: "PasswordAuthentication", line: "PasswordAuthentication no" } - { regexp: "PubkeyAuthentication", line: "PubkeyAuthentication yes" } notify: reload ssh - 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: Клонировать основной репозиторий 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: Скопировать 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 }}" # --- НОВОЕ: Проверка портов --- - 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: Проверка запуска ботов завершена — всё работает 🟢 debug: msg: "Все сервисы запущены и слушают нужные порты." # handlers для перезагрузки сервисов handlers: - name: reload ssh systemd: name: ssh state: reloaded - name: restart ufw ufw: state: reloaded