Ansible – система управления конфигурациями: знакомство
Исходный сайт представленного материала: r4ven.me
Приветствую!
В этой заметке мы с вами познакомимся с популярной open source системой управления конфигурациями с говорящим названием – Ansible🎻. Выполним установку и настройку🛠, составим инвентаризацию📋, научимся запускать плейбуки🚀, поговорим про Ansible facts🗂, узнаем, что такое Ansible console🖥 и напишем playbook📝 который правит конфиг sshd и копирует файлы на сервер. Будет познавательно😉!
Присоединяйтесь к нашему каналу в телеграм: t.me/r4ven_me, уведомления о новых постах приходят туда в день публикации. А если у вас есть вопросы или просто желание пообщаться по тематике – заглядывайте в чат: t.me/r4ven_me_chat.
Предисловие
Чтобы чуть лучше понимать суть происходящего, рекомендую прочитать мою теоретическую заметку📝 про системы управления конфигурациями (Cofiguration Management, CM). В ней дано описание термина, какие виды существуют, а также коротко рассказано про популярные реализации подобных систем и их отличия.
Возвращаясь к Ansible, с его помощью можно автоматизировать конфигурацию серверов путем описания желаемого состояния в удобном формате yaml. Стоит также отметить, что операции Ansible имеют свойство идемпотентности🙄. Это означает, что, если вы запускаете плейбук или задачу несколько раз, состояние системы не изменится после первого успешного выполнения.
Ну и прежде, чем мы продолжим углубляться перечислю основные сущности данной CM📒:
- Control node — управляющий сервер, на котором установлен Ansible и с которого запускаются команды и Playbooks с помощью SSH;
- Managed nodes — управляемые серверы, на которых Ansible выполняет задачи, не требуют установки Ansible на них;
- Inventory file — файл(ы) (обычно
inventory.yml
), содержащий список управляемых узлов и их групп для логического объединения. В нем указываются IP-адреса, DNS имена, порты и пользовательские переменные; - Configuration file — файл конфигурации Ansible (по умолчанию
ansible.cfg
), где задаются настройки, например, путь к файлу инвентаря, параметры SSH и другие параметры, позволяющие настроить поведение Ansible под конкретные нужды; - Variables — переменные, которые можно использовать для гибкой настройки задач и параметров. Переменные могут определяться на разных уровнях: в файле инвентаризации, плейбуке, ролях, командах и динамически собираться;
- Playbook — файл сценария в формате YAML, описывающий, какие задачи нужно выполнить на каких узлах;
- Facts (факты) — информация об управляемом сервере в виде системных переменных (например, тип и версия ОС, IP-адрес, версии пакетов и пр.), автоматически собираемая Ansible. Часто используются для описания условий выполнения задач (tasks);
- Task — отдельное задание, выполняемое на управляемом узле. Это атомарная инструкция (например, установка пакета), описанная с помощью Ansible module;
- Module — готовый модуль из библиотеки Ansible для выполнения конкретной задачи, например, копирование файла, управление сервисами, установка пакетов и пр.;
- Handler (обработчик) — задача, которая запускается только при изменении состояния (например, перезапуск сервиса), вызывается из задачи через параметр
notify
; - Template — файл шаблона (в формате Jinja2), который позволяет, например, создавать динамические файлы конфигурации с использованием переменных и конструкций, свойственным языкам программирования (фильтры, циклы, условные выражения и т.д.), тут можно утонуть;
- Role — структура файлов и директорий для удобной организации задач, шаблонов, файлов переменных для Playbook. По сути, это плейбук, раздробленный на отдельные файлы/папки для большего удобства и наглядности;
- Plugins – дополнения Ansible, расширяющие его функционал.
Установка Ansible в Debian / Ubuntu / Linux mint
Пример установки я буду показывать в среде дистрибутива Debian 12😎:
Т.к. Ansible работает по push принципу (т.е. все управление происходит с административного сервера), то и устанавливать его необходимо только на одной машине. На управляемых серверах понадобится установленный Python🐍 и доступ по SSH.
Подробнее про использование и настройку SSH в Linux, в т.ч. и работу с ключами, читайте в отдельной инструкции: SSH – Безопасное подключение к удалённым хостам: введение.
Все необходимые пакеты Ansible есть в стандартных репозиториях🗄. Поэтому просто открываем терминал и вводим команду:
sudo apt update && sudo apt install -y ansible sshpass
Также мы устанавливаем утилиту sshpass, которая понадобится для передачи пароля при соответствующей SSH аутентификации, а также получение полномочий через sudo💪.
Зависимостей много, поэтому установка займет некоторое время⏳.
Настройка Ansible – файл ansible.cfg
Переходим к начальной настройке. Для этого создаем необходимые директории и файл конфигурации. Открываем его любым текстовым редактором (я предпочитаю vim/neovim)🧑💻:
mkdir -p ~/ansible/{playbooks,roles,tmp} nvim ~/ansible/ansible.cfg
[defaults] home = ~/ansible/ ; основная директория Ansible local_tmp = ~/ansible/tmp/ ; локальная временная директория для выполнения задач inventory = ~/ansible/inventory.yml ; путь к файлу инвентаря с перечнем хостов playbook_dir = ~/ansible/playbooks/ ; директория, где хранятся плейбуки roles_path = ~/ansible/roles/ ; директория, где Ansible ищет роли remote_user = ivan ; пользователь, под которым Ansible подключается к хостам become_method = sudo ; метод повышения прав (sudo, su) become_user = root ; пользователь, от имени которого выполняются sudo команды gather_facts = True ; собирать факты о системе перед выполнением задач private_key_file = ~/ansible/id_ed25519 ; путь к приватному ключу для подключения по SSH host_key_checking = False ; отключает проверку ключей хоста SSH fact_caching = jsonfile ; кэширование фактов с использованием формата json fact_caching_connection = ~/ansible/tmp/ ; путь для хранения кэшированных фактов
Понравился мой конфиг Neovim? Можете с легкостью создать аналогичный по статье: Neovim – Установка и настройка редактора кода с элементами IDE всего в несколько команд.
Такой конфигурации достаточно, чтобы начать использовать Ansible👍. Этот файл определяет поведение Ansible по умолчанию, которое может быть переопределено в других местах: файлах инвентаризации, плейбуках, файлах переменных, командах или в других конфигах.
Если есть потребность изучить все доступные параметры файла конфигурации🤓, то его можно сгенерировать такой командой:
ansible-config init --disabled > ~/ansible/ansible.cfg.example
Файл хорошо прокомментирован🧐.
Подробнее про процесс конфигурации смотрите на оф. сайте: Ansible Configuration Settings.
Также для удобства, рекомендую сразу добавить переменную окружения, указывающую на наш дефолтный файл конфига:
export ANSIBLE_CONFIG="$HOME/ansible/ansible.cfg" # для создания переменной при входе в систему echo 'export ANSIBLE_CONFIG="$HOME/ansible/ansible.cfg"' >> ~/.profile
Замените ~/.profile
на файл загрузки окружения вашей оболочки. В моем случае используется интерактивная оболочка ZSH.
В таком случае можно будет пользоваться командами Ansible из любой директории без явного указания пути до файла с настройками😌.
Полный список доступных переменных окружения также смотрите в оф. доке: Environment Variables.
Инвентаризация – файл inventory.yml
Переходим к инвентаризации хозяйства, которым будем управлять. Для этого создаем файл инвентаря:
nvim ~/ansible/inventory.yml
И добавляем в него список наших серверов📋, которыми будем управлять. В моем примере 5 Linux серверов (3 – Debian, 2 – Ubuntu):
## HOSTS all: hosts: debian12-vpn: ansible_host: 192.168.122.93 ansible_port: 22 ansible_user: ivan ansible_ssh_private_key_file: ~/.ssh/id_ed25519 project: vpn debian12-dns: ansible_host: 192.168.122.201 ansible_port: 22 ansible_user: ivan ansible_ssh_private_key_file: ~/.ssh/id_ed25519 project: vpn debian12-monitoring: ansible_host: 192.168.122.30 ansible_port: 22 ansible_user: ivan ansible_ssh_private_key_file: ~/.ssh/id_ed25519 project: monitor ubuntu22-storage: ansible_host: 192.168.122.5 ansible_port: 22 ansible_user: ivan ansible_ssh_private_key_file: ~/.ssh/id_ed25519 # ansible_password: "Pa$w0rD" project: storage ubuntu22-backup: ansible_host: 192.168.122.249 ansible_port: 22 ansible_user: ivan ansible_ssh_private_key_file: ~/.ssh/id_ed25519 # ansible_become_password: "Pa$w0rD" project: storage ## GROUPS debian: hosts: debian12-vpn: debian12-dns: debian12-monitoring: ubuntu: hosts: ubuntu22-storage: ubuntu22-backup:
Не забудьте заменить параметры на свои 😉
Имейте в виду, что формат YAML отступозависимый. Это значит, что отступы являются частью синтаксиса, и даже один неправильный пробел приведет к ошибке.
Коротко опишу содержимое на примере сервера debian12-vpn:
debian12-vpn
– произвольное имя хоста в файле инвентаризации;ansible_host: 192.168.122.93
– адрес хоста (IP или DNS);ansible_port: 22
– порт подключения SSH;ansible_user: ivan
– пользователь SSH, с помощью которого выполняется подключение;ansible_ssh_private_key_file: ~/.ssh/id_ed25519
– путь до приватного SSH ключа (переопределяет значение изansible.cfg
);project: vpn
– пользовательская переменная для данного хоста.
Также обратите внимание, что после списка хостов идет список групп🖥🖥:
которые включают в себя хосты, разделенные по ОС (в моем случае). Группы также формируются произвольно, главное соблюдайте синтаксис.
Весь список доступных параметров подключения для файла inventory смотрите тут: Connecting to hosts: behavioral inventory parameters.
Наш файл инвентаря составлен, давайте посмотрим на его структуру такой командой:
ansible-inventory --graph
Эта визуализация особенно полезна, если у вас большая инфраструктура из сотен серверов, разбитых на группы📊.
Пишем первый плейбук: проверка доступности серверов с помощью модуля ping
В контексте Ansible модуль ping
не выполняет ping сервера в классическом понимании🤷♂️. Его задача произвести подключение к серверу по SSH, выполнить некоторые проверки (например наличие интерпретатора Python) и вернуть сообщение об успехе/ошибке👀.
Создаем файл плейбука в директории, которую мы обозначили в файле конфигурации:
nvim ~/ansible/playbooks/ping.yml
В самом простом виде плейбук выглядит так:
--- - name: Check connection hosts: all gather_facts: false tasks: - name: Ping ping:
hosts: all
– список хостов, на которых требуется выполнить плейбук (в данном примере на всех);gather_facts: false
– отключает сбор фактов (про них будет ниже);tasks
– блок со списком задач, выполняемых на управляемых хостах, в данном случае одна задача:ping
.
Сохраняем файл и запускаем плейбук:
ansible-playbook ./ansible/playbooks/ping.yml
При использовании команды ansible-playbook
путь до плейбуков нужно указывать явно. Чтобы не делать этого каждый раз, для удобства можно создать короткую функцию и вызывать ее в консоли (смотрите далее в статье).
В моем примере доступ до серверов настроен по ключам SSH. Поэтому проверка доступности выполнена успешно😎.
Если вы используете пароль (что не рекомендуется)😳 можете задать его в файле ansible.cfg
(параметр ansible_password
) или передать интерактивно с помощью ключа --ask-pass
(для этого мы устанавливали пакет sshpass
):
ansible-playbook ./ansible/playbooks/ping.yml --ask-pass
В случае каких-либо ошибок, Ansible выведет страшного вида красные сообщения⛔️. Например, при недоступности хоста по SSH такое:
Чтобы запустить плейбук на указанной группе серверов, можно их явно указать в команде через параметр -l
(limit):
ansible-playbook ./ansible/playbooks/ping.yml -l ubuntu
Для запуска плейбука от имени привилегированного пользователя💪 добавьте ключ -b
(become). В моем примере модуль ping запуститься от имени root:
ansible-playbook ./ansible/playbooks/ping.yml -b
В моей конфигурации серверов настроен беспарольный доступ к root через sudo
(т.к. у меня тестовый стенд🛠), поэтому все отработало корректно. Но если у вас доступ по паролю, его можно передать в файле ansible.cfg
(параметр ansible_become_password
, не рекомендуется) или ввести интерактивно, с помощью ключа --ask-become-pass
:
ansible-playbook ./ansible/playbooks/ping.yml -b --ask-become-pass
Ну а для безопасной автоматизации передачи паролей используется шифрование с помощью ansible-vault
, но это тема для отдельной статьи😉.
Если что, вот документация по модулю ping.
Ansible facts – модули setup
и debug
Как уже ранее говорилось, факты Ansible (facts) – это информация об управляемом сервере в виде системных переменных, таких как тип и версия ОС, IP-адрес, версии пакетов и пр., автоматически собираемая Ansible во время выполнения плейбуков (если активирован флаг gather_facts
) и команд🤯.
Давайте теперь соберем эти факты, чтобы понять, как они выглядят👨🏭. Для этого используется стандартный модуль setup. Выполняем:
ansible all -m setup
all
– тут логично представляет всех хостов из файла инвентаря. Тут также можно указать любой хост отдельно, список хостов через запятую или группу.
В зависимости от количества хостов, сбор фактов может занять какое-то время. В выводе команды вы увидите все собранные факты в формате json:
Факты можно фильтровать, например так:
ansible debian12-vpn -m setup -a 'filter=os_family,distribution_version'
Ранее в файле ansible.cfg
мы настроили кэширование фактов с помощью fact_caching
☝️.
Это значит, что собранные факты будут сохранятся в виде json
файлов во временной директории ~/ansible/tmp
, которую мы также обозначили в файле конфига:
ls -l ./ansible/tmp/
Часто необходимо получить значения только конкретных фактов или переменных. Это можно сделать с помощью модуля debug
🔨 в плейбуках или прямо в терминале.
Вот пример получения информации об OS, объеме диска /dev/sda1
, переменной project и выводе shell команды на сервере debian12-vpn в playbook:
nvim ./ansible/playbooks/debug.yml
--- - name: Debug hosts: debian12-vpn gather_facts: true become: true tasks: - name: Debug 1 debug: msg: "Example to use var: {{ ansible_facts.os_family }}" - name: Debug 2 debug: var: ansible_facts.distribution_version - name: Debug 3 debug: var: project - name: Shell 1 shell: cmd: whoami register: user_name - name: Debug 4 debug: var: user_name.stdout
nvim ./ansible/playbooks/debug.yml
Просмотр фактов с помощью команд в терминале:
В этом случае факты будут взяты из кэша.
ansible debian12-vpn -m debug -a 'var=ansible_facts.os_family,ansible_facts.distribution_version' ansible debian12-vpn -m debug -a 'var=ansible_facts.devices.keys()' ansible debian12-vpn -m debug -a 'var=ansible_facts.devices.sda.partitions.sda1.size'
Можно было заметить, что обращение к фактам происходит с помощью синтаксиса точки, как в Python (ansible написан на этом языке👌).
Подборную инфу по сбору фактов также смотрите на оф сайте: Discovering variables: facts and magic variables. Инфа по модулю debug тут.
Выполнение shell команд в терминале на нескольких серверах одновременно
С помощью Ansible и стандартного модуля shell
можно выполнять удаленные команды сразу на множестве серверов🧑💻💻💻💻. Это очень удобно для дебага или выполнения простых операций.
Удаленная команда передается в кавычках с помощью ключа -a
. Например, вывести список сетевых интерфейсов их IP адресов:
ansible all -m shell -a 'ip -br a'
Или выполнить команду из нашей Linux викторины🧐, которая выводит uptime сервера в формате Unix time:
ansible debian12-vpn,ubuntu22-storage -m shell -a 'date -d "$(uptime -s)" +%s'
Для запуска команд от имени привилегированного пользователя также используется -b
:
ansible all -m shell -a 'whoami' -b
Что такое Ansible console
В комплекте с Ansible идет такой полезные инструмент, как ansible-console
😏. Это интерактивная оболочка для выполнения команд на нескольких серверах. Похоже на команды модуля shell
, которые мы выполняли ранее, но способ взаимодействия немного другой:
ansible-console whoami
Для выхода введитеexit
или нажмите сочетание клавишCtrl+d
.
Пример использования модуля ping
группы debian:
ansible-console debian ping
setup filter=ansible_hostname
Для выполнения привилегированных команды, добавьте ключ -b
(но будьте осторожны!):
ansible-console debian -b whoami
При выполнении удаленных команд ansible-console
по умолчанию используется модуль command❗️. Он вызывает команды напрямую, поэтому некоторые shell
механизмы тут работать не будут. Для задействования shell укажите его явно:
shell echo $HOME
Документация Ansible прямо в терминале
У Ansible очень хорошая документация (правда на английском🙄) и она доступна даже из консоли с помощью утилиты ansible-doc
. Например, чтобы посмотреть описание и примеры использования модуля systemd выполните:
ansible-doc systemd
Вы попадете в режим просмотра less. Обычно примеры использования модулей в плейбуках находятся внизу документации:
Пример ansible playbook: правка конфига sshd и копирование SSH ключа
В качестве практики напишем плейбук📝, который:
- на всех серверах:
- изменит номер порта подключения SSH;
- отключит доступ по паролю на сервер по SSH;
- создаст директорию
~/.ssh
, если она не существует; - добавить новый публичный ssh ключ для авторизации по ключу.
- на серверах, у которых переменная “project” равна “vpn”:
ssh-keygen -t ed25519 -f ~/ansible/id_ed25519_new
nvim ./ansible/playbooks/sshd_config.yml
--- - name: Config sshd service and copy private key # имя/описание плейбука hosts: all # применять ко всем хостам gather_facts: false # не собирать факты (ускоряет выполнение) become: true # выполнять с повышением привилегий (sudo) force_handlers: true # выполнять обработчики даже в случае ошибки vars: - new_ssh_port: 4444 # новый номер порта SSH - user_name: "ivan" # имя пользователя, для которого добавляем SSH ключ - user_ssh_privkey: "/home/ivan/ansible/id_ed25519_new" # путь до приватного SSH ключа для пользователя - user_ssh_pubkey: "/home/ivan/ansible/id_ed25519_new.pub" # путь до публичного SSH ключа для пользователя tasks: - name: Change sshd port number lineinfile: path: /etc/ssh/sshd_config # путь к файлу конфигурации SSH regexp: "^Port" # регулярное выражение для поиска строки с портом line: "Port {{ new_ssh_port }}" # изменить порт на значение из переменной backup: true # создать бэкап файла sshd_config перед изменением notify: - Restart sshd # обработчик для перезапуска SSH при изменении tags: - ssh_server # тег для возможности выборочного запуска задачи - name: Disable sshd password auth lineinfile: path: /etc/ssh/sshd_config # путь к файлу конфигурации SSH regexp: '^PasswordAuthentication yes' # регулярное выражение для поиска строки line: 'PasswordAuthentication no' # отключаем аутентификацию по паролю notify: - Restart sshd # обработчик для перезапуска SSH tags: - ssh_server # тег для задачи SSH сервера - name: Create ssh directory if it does not exist file: path: "/home/{{ user_name }}/.ssh/" # путь к директории .ssh для пользователя state: directory # создать директорию, если не существует owner: "{{ user_name }}" # задать владельца group: "{{ user_name }}" # задать группу mode: 0700 # права доступа к директории tags: - ssh_client # тег для задач SSH клиента - name: Add user ssh public key lineinfile: path: "/home/{{ user_name }}/.ssh/authorized_keys" # путь к файлу authorized_keys line: "{{ lookup('file', '{{ user_ssh_pubkey }}') }}" # в качестве добавляемой строки использовать содержимое файла публичного ключа owner: "{{ user_name }}" # задать владельца group: "{{ user_name }}" # задать группу mode: 0600 # права доступа к файлу backup: true # создать бэкап файла перед изменением create: true # создать новый файл, если он не существует tags: - ssh_client # тег для задач SSH клиента - name: Copy user ssh private key copy: src: "{{ user_ssh_privkey }}" # путь к файлу на локальной машине dest: "/home/{{ user_name }}/.ssh/" # путь к директории на удаленном сервере, слэш обязателен owner: "{{ user_name }}" # задать владельца group: "{{ user_name }}" # задать группу mode: 0600 # права доступа к файлу backup: true # создать бэкап файла перед изменением when: project == "vpn" # выполнять только если у хоста переменная project = "vpn" tags: - ssh_client # тег для задач SSH клиента handlers: - name: Restart sshd systemd: name: sshd # название systemd сервиса SSH state: restarted # перезапуск сервиса
ВНИМАНИЕ❗️ Данный playbook меняет номер порта демона sshd и отключает парольный доступ к серверу по SSH. Крайне рекомендуется запускать необкатанные плейбуки в тестовых средах. Все действия вы выполняете на свой страх и ответственность. Я вас предупредил)
ansible-playbook ./ansible/playbooks/sshd_config.yml
Если все отработало корректно, то порт доступа SSH на удаленных серверах будет изменен. Не забудьте скорректировать номер порта в файле инвентаризации. Или верните старый номер порта подобной командой:
ansible-playbook ./ansible/playbooks/sshd_config.yml -e 'ansible_port=4444' -e 'new_ssh_port=22'
В ней переопределены переменная ansible_port
(из конфига ansible.cfg
), используемая для подключения к хостам, и кастомная переменная new_ssh_port
(из плейбука sshd_config.yml
), определяющая новый номер порта в плейбуке😶🌫️.
На всякий случай повторю, что плейбук также добавляет наш новый публичный (~/ansible/id_ed25519_new.pub
) ключ на сервера.
Возможно вы обратили внимание🧐, что в плейбуке используются теги🔖. С их помощью можно осуществлять выборочный запуск. Например, выполнить только те задачи, которых есть тег ssh_client
(ключ -t
или --tags
):
ansible-playbook ./ansible/playbooks/sshd_config.yml -t ssh_client
Или наоборот, игнорировать задачи (--skip-tags
):
ansible-playbook ./ansible/playbooks/sshd_config.yml --skip-tags ssh_server
Коротко про Ansible roles
Как говорилось в начале статьи, Ansible role – это структура файлов и директорий для удобной организации задач, шаблонов, файлов переменных для Playbook🚜. Создать шаблон роли можно такой командой:
ansible-galaxy init ./ansible/roles/base-config
./ansible/roles/base-config/ ├── README.md # документация роли ├── defaults/ # значения переменных по умолчанию (main.yml) ├── files/ # файлы, которые будут копироваться на целевые хосты ├── handlers/ # обработчики для уведомлений (main.yml) ├── meta/ # метаданные роли, включая зависимости (main.yml) ├── tasks/ # основные задачи роли (main.yml) ├── templates/ # шаблоны Jinja2, которые будут рендериться ├── tests/ # тесты для роли (inventory, test.yml) └── vars/ # переменные роли с более высоким приоритетом (main.yml)
В будущем, мы обязательно будем писать роли Ansible для различных задач!
Но и это уже совсем другая история)
Создаем функцию для удобного запуска плейбуков
Ранее я обещал функцию для удобного выполнения плейбуков. Она довольно проста, но полезна. Выполняем:
echo 'ap() {ansible-playbook ~/ansible/playbooks/"$@"}' >> ~/.profile source ~/.profile which ap
echo
– выводит строку (подробнее про вывод текста тут);'ap() {ansible-playbook ~/ansible/playbooks/"$@"}'
– строка, которая определяет функциюap
:ap()
— объявление функции с именемap
(имя произвольное);{ansible-playbook ~/ansible/playbooks/"$@"}
– тело функции, которая запускаетansible-playbook
, передавая ей все аргументы ("$@"
), например,ap playbook.yml --become
;>> ~/.profile
– добавляет строку в конец файла~/.profile
, чтобы функция автоматически загружалась при входе в систему (подробнее про перенаправление потоков тут).source ~/.profile
– загружает изменения из~/.profile
, активируя функциюap
в текущей сессии;which ap
– если функция определена успешно, это отобразит её как часть текущей оболочки.
ap ping.yml
Послесловие
Вот мы с вами и познакомились с таким крутым и полезным инструментом управления конфигурациями под названием Ansible😎. Базовые знания у нас есть, теперь осталось применить их на практике для решения рутинных задач😌. В планах написать плейбук по базовой настройке сервера Linux, установке и запуску различных сервисов, установке Arch linux на шифрованные разделы и много чего другого🤯.
Все файлы с примерами доступны в моем репозитории на GitHub.
Спасибо, что уделили время 😊. Если появились вопросы – приглашаю в наш дружелюбный Вороний чат 🚶♀️🐧🚶🐧🚶♂️🐧 в телеге 😅. Также обязательно подписывайтесь на основной телеграм канал: @r4ven_me, уведомления о новых материалах на сайте приходят туда в день публикации.
Полезные источники
- Файлы с примерами из статьи | GitHub
- Конфигурация ansible (EN) | docs.ansible.com
- Список переменных окружения Ansible (EN) | docs.ansible.com
- Составление инвентаризации Ansible | docs.ansible.com
- Список параметров подключения для файла inventory | docs.ansible.com
- Список фактов (ansible facts) | docs.ansible.com
- Документация по модулю debug | https://docs.ansible.com/
- Документация по модулю ping | https://docs.ansible.com/
- SSH – Безопасное подключение к удалённым хостам: введение | Вороний блог
- VIM – Консольный редактор: знакомство | Вороний блог
- ZSH – Интерактивная командная оболочка для Linux + Oh-My-Zsh | Вороний блог