Изменить 'sync_letsencrypt_certs_from_storm.yml'

This commit is contained in:
administrator
2026-08-17 14:25:36 +03:00
parent 13273964e1
commit cd4d8188a4
+51 -20
View File
@@ -1,16 +1,16 @@
--- ---
- name: Универсальная динамическая синхронизация всех SSL-сертификатов Let's Encrypt # ==============================================================================
hosts: mail_servers # ЭТАП 1: Сбор сертификатов с хоста storm.bit-it.ru на ваш ПК
# ==============================================================================
- name: Безопасный сбор всех SSL-сертификатов с эталонного хоста
hosts: storm.bit-it.ru
become: true become: true
vars: vars:
local_tmp_dir: "/tmp/ansible_certs" local_tmp_dir: "/tmp/ansible_certs"
# Имя вашего старого сервера, как оно записано в файле inventory Ansible # По умолчанию пустой список означает: обрабатываем ВСЕ найденные домены
source_host_inventory_name: "old_server" target_certs: []
tasks: tasks:
- name: БЛОК АВТОМАТИЧЕСКОГО СБОРА (Выполняется на сервере-источнике) - name: Динамический поиск папок доменов
block:
- name: Динамический поиск только папок доменов (игнорируем README и файлы)
ansible.builtin.find: ansible.builtin.find:
paths: "/etc/letsencrypt/live" paths: "/etc/letsencrypt/live"
file_type: directory file_type: directory
@@ -18,43 +18,66 @@
excludes: "all,README" excludes: "all,README"
register: found_live_dirs register: found_live_dirs
- name: Формирование чистого списка доменов - name: Формирование списка доменов с учетом фильтрации
ansible.builtin.set_fact: ansible.builtin.set_fact:
dynamic_domains: "{{ found_live_dirs.files | map(attribute='path') | map('basename') | list }}" dynamic_domains: >-
{% if target_certs | length > 0 %}
{{ found_live_dirs.files | map(attribute='path') | map('basename') | intersect(target_certs) | list }}
{% else %}
{{ found_live_dirs.files | map(attribute='path') | map('basename') | list }}
{% endif %}
cacheable: true
- name: Создание локальной структуры папок на управляющей машине (Ansible Host) - name: Проверка, что список доменов для переноса не пуст
ansible.builtin.meta: end_play
when: dynamic_domains | length == 0
comment: "Скрипт остановится, если переданных доменов нет на сервере-источнике"
- name: Вывод списка доменов, выбранных для синхронизации
ansible.builtin.debug:
msg: "Будут синхронизированы следующие сертификаты: {{ dynamic_domains }}"
- name: Создание изолированной папки на вашем ПК
ansible.builtin.file: ansible.builtin.file:
path: "{{ local_tmp_dir }}/{{ item }}" path: "{{ local_tmp_dir }}/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0700'
delegate_to: localhost delegate_to: localhost
run_once: true
loop: [ 'archive', 'live', 'renewal' ] loop: [ 'archive', 'live', 'renewal' ]
- name: Скачивание папок archive (сохраняем оригиналы файлов) - name: Скачивание папок archive на ваш ПК
ansible.builtin.fetch: ansible.builtin.fetch:
src: "/etc/letsencrypt/archive/{{ item }}/" src: "/etc/letsencrypt/archive/{{ item }}/"
dest: "{{ local_tmp_dir }}/archive/{{ item }}/" dest: "{{ local_tmp_dir }}/archive/{{ item }}/"
flat: false flat: false
loop: "{{ dynamic_domains }}" loop: "{{ dynamic_domains }}"
- name: Скачивание конфигураций обновления renewal - name: Скачивание конфигураций обновления renewal на ваш ПК
ansible.builtin.fetch: ansible.builtin.fetch:
src: "/etc/letsencrypt/renewal/{{ item }}.conf" src: "/etc/letsencrypt/renewal/{{ item }}.conf"
dest: "{{ local_tmp_dir }}/renewal/{{ item }}.conf" dest: "{{ local_tmp_dir }}/renewal/{{ item }}.conf"
flat: true flat: true
loop: "{{ dynamic_domains }}" loop: "{{ dynamic_domains }}"
- name: Скачивание папок live (копируем исходное содержимое) - name: Скачивание папок live на ваш ПК
ansible.builtin.fetch: ansible.builtin.fetch:
src: "/etc/letsencrypt/live/{{ item.0 }}/{{ item.1 }}.pem" src: "/etc/letsencrypt/live/{{ item.0 }}/{{ item.1 }}.pem"
dest: "{{ local_tmp_dir }}/live/{{ item.0 }}/{{ item.1 }}.pem" dest: "{{ local_tmp_dir }}/live/{{ item.0 }}/{{ item.1 }}.pem"
flat: true flat: true
loop: "{{ dynamic_domains | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}" loop: "{{ dynamic_domains | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}"
delegate_to: "{{ source_host_inventory_name }}"
run_once: true
- name: БЛОК НАКАТЫВАНИЯ И АДАПТИВНОГО ПЕРЕЗАПУСКА (Выполняется на удаленных хостах) # ==============================================================================
# ЭТАП 2: Раскатка сертификатов с вашего ПК и ПОЛНАЯ ЗАЧИСТКА ХВОСТОВ
# ==============================================================================
- name: Раскатка SSL-сертификатов с ПК на целевые хосты и зачистка
hosts: mail_servers
become: true
vars:
local_tmp_dir: "/tmp/ansible_certs"
source_host_inventory_name: "storm.bit-it.ru"
tasks:
- name: Основной блок выполнения раскатки
block: block:
- name: Сбор информации о запущенных сервисах на целевом хосте - name: Сбор информации о запущенных сервисах на целевом хосте
ansible.builtin.service_facts: ansible.builtin.service_facts:
@@ -103,7 +126,7 @@
force: true force: true
loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}" loop: "{{ hostvars[source_host_inventory_name]['dynamic_domains'] | product(['cert', 'chain', 'fullchain', 'privkey']) | list }}"
- name: Автоматический перезапуск активных веб- и почтовых служб (только если они запущены) - name: Автоматический перезапуск активных веб- и почтовых служб
ansible.builtin.systemd: ansible.builtin.systemd:
name: "{{ item }}" name: "{{ item }}"
state: restarted state: restarted
@@ -115,3 +138,11 @@
when: when:
- ansible_facts.services[item + '.service'] is defined - ansible_facts.services[item + '.service'] is defined
- ansible_facts.services[item + '.service'].state == 'running' - ansible_facts.services[item + '.service'].state == 'running'
always:
- name: Полное удаление секретных ключей с ПК администратора
ansible.builtin.file:
path: "{{ local_tmp_dir }}"
state: absent
delegate_to: localhost
run_once: true