Автоматизация 50+ VPS за 10 минут: Ansible-playbook без следов

Автоматизация VPS Хостинги

Ручная настройка серверного стека через SSH или запуск разрозненных bash-скриптов на каждом отдельном хосте — это потеря времени и гарантированный источник ошибок. При масштабировании PBN-сеток, развертывании дроп-серверов под арбитражные лендинги или подготовке фермы вебхуков для ботов требуется воспроизводимый инструмент оркестрации.

Оркестрация через Ansible позволяет настраивать десятки удаленных VPS одной командой с локального компьютера. Инструмент не требует установки агентского ПО на целевые серверы и работает поверх стандартного протокола SSH.

Стандартные руководства из сети часто предлагают дефолтный стек, отдающий заглушку «Welcome to Nginx» при любом сканировании по IP-адресу. Ниже представлен инженерный плейбук, который разворачивает стек LEMP, автоматически определяет окружение и сбрасывает сетевые соединения при прямом обращении к серверу без доменного имени.

Подготовка инвентаря (hosts.ini) и изоляция переменных

Перед запуском сценария необходимо передать Ansible список целевых серверов и сопоставить каждому хосту его доменное имя.

Создайте файл инвентаря hosts.ini на локальной машине:

[webservers]
192.168.1.10 ansible_user=root domain=site1.com
192.168.1.11 ansible_user=root domain=site2.com
192.168.1.12 ansible_user=root domain=site3.com

Через переменную domain в конфигурационные файлы Nginx и задачи выпуска SSL автоматически подставляется целевое имя сайта.

Требование к доступу: подключение выполняется по SSH-ключам. Убедитесь, что ваш публичный ключ ed25519 предварительно добавлен на все серверы группы в файл ~/.ssh/authorized_keys.

Готовый Playbook: LEMP, Drop Connection и динамический сокет PHP

Создайте файл deploy.yml. Этот сценарий обновляет систему, устанавливает Nginx, PHP-FPM, MariaDB, настраивает фаервол, конфигурирует виртуальный хост и отключает дефолтные ответы сервера.

Защита от краша: Скрипт не фиксирует жестко версию PHP (например, 8.1), а определяет её динамически на целевом сервере. Это гарантирует, что Nginx не остановится с ошибкой при развертывании на разных версиях ОС (Ubuntu 20.04, 22.04 или 24.04).

---
- name: Hardened LEMP Deployment
  hosts: webservers
  become: yes
  tasks:
    - name: Обновление кэша apt и системы
      apt:
        update_cache: yes
        upgrade: dist

    - name: Установка Nginx, PHP, MySQL и Certbot
      apt:
        name: 
          - nginx
          - mariadb-server
          - php-fpm
          - php-mysql
          - certbot
          - python3-certbot-nginx
          - ufw
        state: present

    - name: Определение версии PHP "на лету"
      shell: php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;"
      register: php_version_output
      changed_when: false

    - name: Блокировка прямого обращения по IP (Drop Connection)
      copy:
        dest: /etc/nginx/sites-available/default
        content: |
          server {
              listen 80 default_server;
              listen [::]:80 default_server;
              server_name _;
              return 444; # Сброс соединения без ответа
          }
      notify: Reload Nginx

    - name: Создание конфига Nginx для домена
      copy:
        dest: "/etc/nginx/sites-available/{{ domain }}"
        content: |
          server {
              listen 80;
              server_name {{ domain }} www.{{ domain }};
              root /var/www/{{ domain }};
              index index.php index.html;
              location / {
                  try_files $uri $uri/ /index.php?$args;
              }
              location ~ \.php$ {
                  include snippets/fastcgi-php.conf;
                  fastcgi_pass unix:/var/run/php/php{{ php_version_output.stdout }}-fpm.sock;
              }
          }
      notify: Reload Nginx

    - name: Активация домена и создание директории
      file:
        src: "/etc/nginx/sites-available/{{ domain }}"
        dest: "/etc/nginx/sites-enabled/{{ domain }}"
        state: link
    
    - name: Создание корневой папки сайта
      file:
        path: "/var/www/{{ domain }}"
        state: directory
        owner: www-data
        group: www-data

    - name: Настройка фаервола UFW
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - '22'
        - '80'
        - '443'

    - name: Выпуск SSL Let's Encrypt (Только если DNS обновлен)
      command: certbot --nginx -d {{ domain }} -d www.{{ domain }} --non-interactive --agree-tos -m admin@{{ domain }}
      ignore_errors: yes

  handlers:
    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded

Архитектурные особенности сценария:

  • Динамический сокет PHP-FPM: сценарий не фиксирует версию PHP жестко в коде (например, 8.1 или 8.3), а определяет установленную версию на лету. Это предотвращает сбои Nginx при развертывании на разных версиях ОС (Ubuntu 20.04, 22.04 или 24.04).

  • Защита от сетевых сканеров (return 444): при обращении по прямому IP-адресу Nginx мгновенно разрывает TCP-соединение без отправки HTTP-заголовков сервера, скрывая факт наличия сайта от ботнетов.

Команда для запуска:

ansible-playbook -i hosts.ini deploy.yml

Модели сбоя: узлы отказа при массовом развертывании

Рассинхронизация глобального DNS (сбой Certbot)

Если A-записи доменов добавлены незадолго до запуска плейбука, глобальные DNS-серверы могут не успеть обновиться. В этом случае Certbot завершится с ошибкой валидации домена.

  • Защита: директива ignore_errors: yes предотвращает остановку сценария. Без нее аварийное завершение Certbot на первом же недоступном домене прервет выполнение плейбука на всех остальных серверах.

  • Порядок действий: разверните базовую инфраструктуру, дождитесь обновления DNS (обычно 2–4 часа) и запустите плейбук повторно для завершения выпуска SSL.

Лимиты Let’s Encrypt API (Rate Limiting)

При одновременном запросе более 50 сертификатов с одного IP-адреса управляющей машины API центра сертификации может временно заблокировать запросы за превышение частоты обращений.

  • Защита: параметр serial: 10 в заголовке сценария ограничивает параллельное выполнение, прогоняя задачи пакетами по 10 хостов.

Сценарии применения: сетки сайтов и арбитражная инфраструктура

Чек-лист: запуск автоматизации через Ansible

  • На все целевые серверы скопирован публичный SSH-ключ ed25519.

  • Сформирован файл hosts.ini с сопоставлением IP-адресов и целевых доменов.

  • Проверено делегирование доменов и корректность A-записей в DNS.

  • Выполнен тестовый пинг доступности хостов: ansible webservers -i hosts.ini -m ping.

  • Запущен сценарий развертывания с контролем параллелизма (serial: 10).

Что делать дальше: следующие шаги

Оцените статью
autoparse.tech
Добавить комментарий