Блокнот — это базовый текстовый редактор, который с самого начала был включен в комплект Windows. За последние три десятилетия он претерпел постепенные улучшения, но новейшая бета-версия предлагает значительный шаг вперед в удобстве использования и функциях. Тем не менее, любой, кто установил альтернативы Блокноте, вероятно, будет настороженно относиться к этой новости, поскольку легко уменьшить привлекательность этого быстрого минималистичного инструмента и создать раздутое приложение. Microsoft слишком далеко зашла с новой бета-версией? Только вы можете сами судить об этом вопросе ощущений. Читать
Архив метки: Software
Установка FFmpeg в Ubuntu 20.04
ffmpeg — мощный инструмент для конвертирования файлов в большинстве известных видеоформатов. Программа ffmpeg не имеет графического интерфейса, однако позволяет выполнять задачи, перед которыми другие видеоконвертеры попросту бессильны.
Ниже рассмотрим, как установить ffmpeg в Ubuntu 20.04 из официальных репозиториев, а также с использованием snap-пакета. А затем поговорим о том, как с его помощью переконвертировать небольшое видео из одного формата в другой.
Как распаковать Zip файл в Linux

Zip — это один из самых распространенных и наиболее популярных способов создания сжатых архивных файлов. Это также один из самых старых форматов архивных файлов, он был создан в 1989 году. Поскольку он широко используется, вы будете регулярно сталкиваться с zip-файлами.
В одном из предыдущих уроков я показал, как заархивировать папку в Linux. В этом кратком руководстве для начинающих я покажу вам, как распаковывать файлы в Linux. Читать
Настройка репликации PostgreSQL в контейнерах Docker
Мы рассмотрим процесс поднятия двух контейнеров с PostgreSQL и настройки репликации данных между ними. Использовать будем систему на базе Linux, однако, сам процесс настройки Docker и репликации не зависит от операционной системы.
Подготовка компьютера
На компьютере, где мы будем запускать наш кластер баз данных должен быть установлен Docker. Также мы сразу рассмотрим развертывание нужной нам инфраструктуры в docker-compose. Для установки необходимой одноименной платформы смотрим инструкцию Установка Docker на Linux.
После мы можем переходить к поднятию контейнеров.
Запуск контейнеров с СУБД
Как говорилось выше, мы будем поднимать наши контейнеры с помощью docker-compose.
Создадим каталог, в котором будем работать:
mkdir -p /opt/docker/postgresql
Переходим в него:
cd /opt/docker/postgresql
Создаем файл для docker-compose:
vi docker-compose.yml
---
services:
postgresql_01:
image: postgres
container_name: postgresql_01
restart: always
volumes:
- /data/postgresql_01:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgres024
postgresql_02:
image: postgres
container_name: postgresql_02
restart: always
volumes:
- /data/postgresql_02/:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgres024
* рассмотрим некоторый опции подробнее:
- postgresql_01/postgresql_02 — названия для сервисов, контейнеры для которых мы будем поднимать.
- image — образ, из которого будут создаваться контейнеры. В данном примере мы берем официальный образ postgres.
- container_name — имя, которое будет присвоено контейнеру после его запуска. В нашем примере это postgresql_01 и postgresql_02.
- restart — режим перезапуска. Говорит, в каких случаях наш контейнер должен стартовать.
- volumes — хорошим тоном для работы базы данных в контейнере является проброс каталога хостового компьютера внутрь контейнера. Таким образом, после удаления контейнера данные останутся на компьютере. В нашем примере в каталоге /data будут созданы каталоги postgresql_01 и postgresql_02, которые будут прокинуты в каталог /var/lib/postgresql/data контейнера.
- environment — для первого запуска необходима инициализация базы данных. Без пароля системы выдает ошибку. Поэтому мы задаем переменную среды POSTGRES_PASSWORD.
Запускаем наши контейнеры:
docker-compose up -d
Мы должны увидеть:
Creating postgresql_02 ... done
Creating postgresql_01 ... done
А если вывести список контейнеров:
docker ps
… мы должны увидеть наши два.
Теперь можно переходить к настройке репликации.
Настройка репликации
Условимся, что первичный сервер или master будет в контейнере с названием postgresql_01. Вторичный — postgresql_02. Мы будем настраивать потоковую (streaming) асинхронную репликацию.
Настройка на мастере
Подключаемся к контейнеру docker:
docker exec -it postgresql_01 bash
Заходим под пользователем postgres:
su - postgres
Создаем пользователя, под которым будем подключаться со стороны вторичного сервера:
createuser --replication -P repluser
* в данном примере будет создаваться учетная запись repluser с правами репликации.
Система потребует ввода пароля. Придумываем его и набираем дважды.
Выходим из-под пользователя postgres:
exit
Выходим из контейнера:
exit
Открываем конфигурационный файл postgresql.conf:
vi /data/postgresql_01/postgresql.conf
Приводим к следующием виду некоторые параметры:
wal_level = replica
max_wal_senders = 2
max_replication_slots = 2
hot_standby = on
hot_standby_feedback = on
* где
- wal_level указывает, сколько информации записывается в WAL (журнал операций, который используется для репликации). Значение replica указывает на необходимость записывать только данные для поддержки архивирования WAL и репликации.
- max_wal_senders — количество планируемых слейвов;
- max_replication_slots — максимальное число слотов репликации (данный параметр не нужен для postgresql 9.2 — с ним сервер не запустится);
- hot_standby — определяет, можно или нет подключаться к postgresql для выполнения запросов в процессе восстановления;
- hot_standby_feedback — определяет, будет или нет сервер slave сообщать мастеру о запросах, которые он выполняет.
Посмотрим подсеть, которая используется для контейнеров с postgresql:
docker network inspect postgresql_default | grep Subnet
В моем случае, ответ был:
"Subnet": "172.19.0.0/16",
Теперь открываем файл:
vi /data/postgresql_01/pg_hba.conf
И добавляем строку после остальных «host replication»:
host replication all 172.19.0.0/16 md5
* в данном примере мы разрешили подключение пользователю replication из подсети 172.19.0.0/16 с проверкой подлинности по паролю.
Перезапустим докер контейнер:
docker restart postgresql_01
Настройка на слейве
Выполним настройку вторичного сервера. Для начала, удалим содержимое рабочего каталога вторичной базы:
rm -r /data/postgresql_02/*
* в данном примере мы удалим все содержимое каталога /data/postgresql_02.
Мы должны быть уверены, что в базе нет ничего важного. Только после этого стоить удалять данные.
Заходим внутрь контейнера postgresql_02:
docker exec -it postgresql_02 bash
Выполняем команду:
su - postgres -c "pg_basebackup --host=postgresql_01 --username=repluser --pgdata=/var/lib/postgresql/data --wal-method=stream --write-recovery-conf"
* где postgresql_01 — наш мастер; /var/lib/postgresql/data — путь до каталога с данными слейва.
Система должна запросить пароль для пользователя repluser — вводим его. Начнется процесс репликации, продолжительность которого зависит от объема данных.
Проверка
Смотрим статус работы мастера:
docker exec -it postgresql_01 su - postgres -c "psql -c 'select * from pg_stat_replication;'"
Смотрим статус работы слейва:
docker exec -it postgresql_02 su - postgres -c "psql -c 'select * from pg_stat_wal_receiver;'"
Источник: https://www.dmosk.ru/miniinstruktions.php?mini=postgresql-replication-docker
Ansible: Сбор произвольной информации на хостах с помощью Ansible custom facts. Вывод информации в формате *.json.
На чем было опробовано:
- Ansible 2.9.18
- Hyper-V на Windows 10 Pro.
- Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
- Node 1: CentOS Linux release 7.9.2009 (Core).
- Node 2: CentOS Linux release 7.9.2009 (Core).
- Node 3: CentOS Linux release 7.9.2009 (Core).
- Node 4: CentOS Linux release 7.9.2009 (Core).
1. Задача.
К примеру, нам требуется с помощью внедрения custom facts для Ansible организовать сбор версий контейнеров, запущенных на серверах, а так же сбор версий некоторого программного обеспечения на серверах, которое имеет файл с указанием версии в своём каталоге /ecp/po/version.txt.
Собранная информация должна формироваться в json-формат.
Дополнительно требуется рассмотреть средства визуализации информации в удобном виде (opensource web-приложения).
2. Решение задачи.
Решение будет состоять из нескольких этапов:
- загрузка и выполнение скрипта на узлах с целью получить json файлы;
- выгрузка файлов json с узлов;
- склеивание узловых файлов json в один сводный файл;
- просмотр сводного файла.
В системе Ansible есть возможность собирать системную информацию, которая собирается в виде фактов с помощью встроенного модуля setup.
Со сбором стандартных переменных по умолчанию всё предельно ясно, но что делать, если мы хотим сформировать наши собственные переменные на всех хостах, чтобы в дальнейшем использовать их в нашем коде?
Для этого существует возможность добавления Custom facts, что делается следующим образом:
- на любом хосте, контролируемом Ansible, создаётся каталог
/etc/ansible/facts.d; - внутри каталога размещаются один либо несколько файлов с расширением
*.fact, напримерcustom.fact; - файлы возвращают данные в формате json.
Создаем инвентарь test-servers.inventory на 4 тестовых сервера:
# mcedit /ansible/test-servers.inventory
С таким содержимым:
[test_servers]
server1 ansible_ssh_host=192.168.0.39 ansible_ssh_user=root
server2 ansible_ssh_host=192.168.0.30 ansible_ssh_user=root
server3 ansible_ssh_host=192.168.0.31 ansible_ssh_user=root
emachines ansible_ssh_host=192.168.0.12 ansible_ssh_user=root
Создаем специальный custom.fact файл для загрузки на узлы, который, по сути, является скриптом для выполнения некоторого комплекса действий на удалённом узле.
По замыслу будут собираться некоторые переменные и заворачиваться в разметку json.
#!/bin/bash
file_po="/etc/po/version.txt"
host_name=$(hostname)
ecp_ver=$(awk -F: '/rel_ver/{print $2}' $file_po)
docker_info=$(docker ps --format ' {{json .Names}}: {{json .Image}}, ' | paste -sd'n' | sed '$ s/.$//')
jp="/$host_name.json"
echo "{" > $jp
echo ""Информация об узлах": {" >> $jp
echo ""$host_name": {" >> $jp
if test -f "$file_po"; then
echo ""Софт": {" >> $jp
echo ""Версия чего-то": "$ecp_ver"" >> $jp
echo "}" >> $jp
echo "," >> $jp
fi
echo ""Докеры на узле": {" >> $jp
echo "$docker_info" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
echo "}" >> $jp
Создаём специальный playbook custom-facts-fetch.yml, содержащий сценарий /ansible/files/custom.fact для узла, возвращающий некоторый файл json на Ansible master сервер с каждого узла:
---
- name: "Cбор Ansible custom facts"
hosts: all
tasks:
- name: "Удаление предыдущей версии Ansible custom facts файлов на узле"
file:
state: "absent"
path: "/etc/ansible/facts.d/"
- name: "Создание Ansible custom fact каталога"
file:
path: "/etc/ansible/facts.d"
state: "directory"
mode: 0766
- name: "Загрузка на узлы Ansible custom fact файлов"
copy:
src: "/ansible/files/custom.fact"
dest: "/etc/ansible/facts.d/custom.fact"
mode: +x
- name: "Объявление служебной переменной для Ansible custom fact"
debug: "var=ansible_local"
notify:
- reload facts
- name: "Перезагрузка facts"
setup: "filter=ansible_local"
- name: "Подготовка списка файлов *.json для выгрузки с узла"
find:
paths: "/"
recurse: "no"
patterns: "*.json"
register: "files_to_copy"
- name: "Выгрузка файлов *.json с узла на Ansible master сервер"
fetch:
src: "{{ item.path }}"
dest: "/ansible/json"
with_items: "{{ files_to_copy.files }}"
Напишем скрипт custom-facts-fetch-PLAY.sh для запуска playbook на целевом inventory:
#!/bin/bash.
ansible-playbook /ansible/custom-facts-fetch.yml -i /ansible/test-servers.inventory
Сделаем файл скрипта исполняемым:
# chmod +x custom-facts-fetch-PLAY.sh
И запустим его.
Ответ:

После успешной отработки playbook на сервере Ansible master появится каталог /ansible/json с подкаталогами ‘имя_узла‘:

В каждом из которых будет находиться json файл вида имя_узла.json:




Содержимое json файла первого узла emachines:

Содержимое json файла второго узла server1:

Содержимое json файла третьего узла server2:

Содержимое json файла четвертого узла server3:

Получилось несколько файлов json, по файлу с каждого целевого узла.
Сколько узлов мы задействовали для Ansible custom facts, столько и json файлов и будет.
В первом файле emachines.hamsterden.loc.json не имеется фрагмент с названием «Версия чего-то‘, по втором файле cos7client1.hamsterden.loc.json такой фрагмент имеется, а так как в custom.fact реализована проверка на фактическое наличия файла /ecp/po/version.txt.
К примеру, наличие файла /ecp/po/version.txt бывает только у серверов типа «web-server». Так как скрипт «сам учитывает» тип сервера, то можно смело применять custom.fact на все целевые серверы и файл json всегда будет генерироваться корректно для каждого типа серверов.
Для создание сводного json файла по всем файлам со всех узлам, воспользуемся утилитой jq.
Ссылка на официальный сайт утилиты: https://stedolan.github.io/jq/.
Установка утилиты:
# yum install jq -y
План работ с файлами:
file1.json + file3.json + file3.json + file4.json = final_result_po.json
Создадим make-final-json-file.sh скрипт:
# mcedit /ansible/make-final-json-file.sh
#!/bin/bash
#создание каталогов для обработки файлов
mkdir -p /ansible/json/temp
mkdir -p /ansible/json-ready
#каталог куда Ansible кладет скачанные json файлы с узлов
ja="/ansible/json"
#временный каталог куда Ansible складывает все json файлы из всех каталогов узлов перед сведением информации в единый файл json
jrt="/ansible/json/temp"
#каталог куда Ansible помещает сводный json файл со всей добытой информацией по узлам
jr="/ansible/json-ready"
#обработка файлов и удаление временных промежуточных результатов
cp -i $(find /$ja -iname "*.json") $jrt
cd $jrt
jq -s '.[0] * .[1] * .[2] * .[3]' *.json > "$jrt"/temp.json
cat "$jrt"/temp.json | sed 's/{}/"нет докеров"/' > "$jr"/final_result_po.json
#удаление временных каталогов и файлов
rm -rf $jrt
rm -rf $ja
Сделаем файл скрипта исполняемым:
# chmod +x /ansible/make-final-json-file.sh
Результатом работы скрипта будет сводный json файл всех четырёх final_result_po.json в каталоге /ansible/json_ready на Ansible master сервере:

Текстовый файл:
{
"Информация об узлах": {
"cos7client1.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.11.2"
},
"Докеры на узле": {
"wordpress-compose_nginx_1": "nginx:latest",
"wordpress-compose_wordpress_1": "wordpress:php7.4-fpm-alpine",
"wordpress-compose_pma_1": "phpmyadmin/phpmyadmin",
"wordpress-compose_mysql_1": "mariadb"
}
},
"cos7client2.hamsterden.loc": {
"Софт": {
"Версия чего-то": "10.2.1"
},
"Докеры на узле": "нет докеров"
},
"cos7client3.hamsterden.loc": {
"Софт": {
"Версия чего-то": "9.3.4"
},
"Докеры на узле": "нет докеров"
},
"emachines.hamsterden.loc": {
"Докеры на узле": {
"onlyoffice": "onlyoffice/documentserver",
"funny_heisenberg": "onlyoffice/documentserver"
}
}
}
}
Если открыть final_result_po.json файл в браузере Mozilla Firefox, то информация будет корректно визуализирована в удобно читаемом виде:

Задача выполнена!
X. Оригиналы источников информации.
- golinuxcloud.com «Working with Ansible facts | Create custom facts with examples».
- github.com «Ansible local fact example».
- medium.com «Custom facts for Ansible».
- otus.ru «Ansible: формируем переменные на всех хостах с Custom facts».
- mydailytutorials.com «Working with Ansible facts – retrieving facts».
- adyxax.org «Ansible custom factsAnsible custom facts».
- Источник: https://hamsterden.ru/ansible-collecting-arbitrary-information-on-all-hosts-with-custom-facts/
Ansible: Часть 5. Настройка защищенных плейбуков.
На чем было опробовано:
- Ansible 2.9.18
- Hyper-V на Windows 10 Pro.
- Сервер Ansible: CentOS Linux release 7.9.2009 (Core).
- Node 1: CentOS Linux release 7.9.2009 (Core).
- Node 2: CentOS Linux release 7.9.2009 (Core).
- Node 3: CentOS Linux release 7.9.2009 (Core).
1. Введение.
Как установить и первоначально настроить Ansible описано здесь:
Ссылка: «Ansible: Часть 1. Описание, установка и первоначальная настройка.»
Так как простые задачи для Ansible реально простые, в буквальном смысле слова, то я принял решение вынести их в отдельную инструкцию:
Ссылка: «Ansible: Часть 2. Примеры простых задач.»
Рассмотрим структуру и правила написания таких сценариев более подробно.
Ссылка: «Ansible: Часть 3. Сценарии (плейбуки) — Playbooks.»
По данной ссылке я создам небольшую подборку самых интересных и типовых плейбуков, которые могут пригодиться вам в повседневной работе.
Ссылка: «Ansible: Часть 4. Практические примеры плейбуков.»
2. Ansible Vault для хранения конфиденциальных данных.
Если ваши плейбуки Ansible содержат конфиденциальные данные, такие как пароли, ключи API и учетные данные, важно обеспечить их безопасность с помощью шифрования. Ansible предоставляет ansible-vault для шифрования файлов и переменных.
Несмотря на то, что любой файл данных Ansible, а также двоичные файлы, возможно зашифровать изначально, чаще для шифрования переменных файлов, содержащих конфиденциальные данные, используется ansible-vault. После шифрования файла с помощью этого инструмента вы сможете выполнять, редактировать или просматривать его, только предоставив соответствующий пароль, указанный при первом шифровании файла.
2.1. Создание нового зашифрованного файла.
Вы можете создать новый зашифрованный файл Ansible с помощью:
# ansible-vault create credentials.yml
Эта команда выполнит следующие действия:
- Сначала вам будет предложено ввести новый пароль. Вам нужно будет указывать этот пароль при каждом доступе к содержимому файла, будь то редактирование, просмотр или просто запуск плейбука или команд с использованием его значений.
- Затем откроется редактор командной строки по умолчанию, чтобы вы могли заполнить файл требуемым содержимым.
- Наконец, когда вы закончите редактирование,
ansible-vaultсохранит файл как зашифрованный.
2.2. Шифрование существующего файла.
Чтобы зашифровать существующий файл Ansible, вы можете использовать следующую команду:
# ansible-vault encrypt credentials.yml
Эта команда запросит у вас пароль, который вам нужно будет вводить при каждом доступе к файлу credentials.yml.
2.3. Просмотр содержимого зашифрованного файла.
Если вы хотите просмотреть содержимое файла, который ранее был зашифрован с помощью ansible-vault, и вам не нужно изменять его содержимое, вы можете использовать команду:
# ansible-vault view credentials.yml
Она предложит вам указать пароль, который вы выбрали при первом шифровании файла с помощью ansible-vault.
2.4. Редактирование зашифрованного файла.
Чтобы изменить содержимое файла, который ранее был зашифрован с помощью ansible-vault, выполните:
# ansible-vault edit credentials.yml
Эта команда предложит вам указать пароль, который вы выбрали при первом шифровании файла credentials.yml. После проверки пароля откроется редактор командной строки по умолчанию с незашифрованным содержимым файла, что позволит вам внести нужные изменения. По завершении вы можете сохранить и закрыть файл, как обычно, и обновленное содержимое будет сохранено и зашифровано.
Если вы хотите навсегда расшифровать файл, ранее зашифрованный с помощью ansible-vault, вы можете сделать это с помощью следующего синтаксиса:
# ansible-vault decrypt credentials.yml
Эта команда предложит вам ввести тот пароль, который использовался при первом шифровании файла. После проверки пароля содержимое файла будет сохранено на диск в виде незашифрованных данных.
3. Использование нескольких паролей.
Ansible поддерживает для хранилища несколько паролей, сгруппированных по разным идентификаторам. Это полезно, если вы хотите иметь выделенные пароли хранилища для различных сред – для разработки, тестирования и производства.
Чтобы создать новый зашифрованный файл с пользовательским идентификатором хранилища, включите параметр --vault-id вместе с меткой и расположением, где ansible-vault может найти пароль для этого хранилища. Метка может быть любой, а расположение может быть либо prompt (что означает, что команда должна предложить вам ввести пароль), либо путь к файлу паролей.
# ansible-vault create --vault-id dev@prompt credentials_dev.yml
Это создаст новый идентификатор по имени dev, который использует prompt для получения пароля. Комбинируя этот метод с файлами переменных группы, вы сможете создать отдельные хранилища для каждой среды приложения:
# ansible-vault create --vault-id prod@prompt credentials_prod.yml
Мы использовали dev и prod в качестве идентификаторов хранилищ, чтобы продемонстрировать, как вы можете создавать отдельные хранилища для каждой среды. Самостоятельно вы можете создать столько хранилищ, сколько захотите, и использовать любой ID.
Теперь, чтобы просмотреть, отредактировать или расшифровать эти файлы, вам необходимо предоставить тот же ID хранилища и источник пароля вместе с командой ansible-vault:
# ansible-vault edit credentials_dev.yml --vault-id dev@prompt
4. Использование файла паролей.
Если вам нужно автоматизировать процесс инициализации серверов в Ansible с помощью стороннего инструмента, вам потребуется способ ввода пароля хранилища без его запроса. Вы можете сделать это, используя файл паролей через ansible-vault.
Файл паролей может быть простым текстовым файлом или исполняемым скриптом. Если файл является исполняемым, выходные данные, созданные ним, будут использоваться в качестве пароля хранилища. В противном случае в качестве пароля хранилища будет использоваться необработанное содержимое файла.
Чтобы применить файл паролей в ansible-vault, необходимо указать путь к файлу паролей при выполнении любой из команд vault:
# ansible-vault create --vault-id dev@path/to/passfile credentials_dev.yml
Ansible не различает контент, который был зашифрован с помощью prompt, и простой файл пароля при условии, что входной пароль один и тот же. С практической точки зрения это означает, что файл можно зашифровать, используя prompt, а затем создать файл пароля для хранения того же пароля, который использовался в методе prompt. Также верно и обратное: вы можете зашифровать содержимое, используя файл паролей, а затем использовать метод prompt, предоставляя тот же пароль при запросе Ansible.
Для большей гибкости и безопасности, чтобы не хранить свой пароль в текстовом файле, вы можете использовать скрипт Python для получения пароля из других источников.
Официальный репозиторий Ansible содержит несколько примеров сценариев, которые вы можете использовать для справки при создании своего скрипта под потребности вашего проекта.
5. Запуск плейбука с зашифрованными данными.
Каждый раз, когда вы запускаете плейбук, в котором используются данные, ранее зашифрованные с помощью ansible-vault, вам нужно будет указывать пароль хранилища в команде playbook.
Если вы использовали параметры по умолчанию и prompt при шифровании данных плейбука, вы можете использовать опцию --ask-vault-pass, чтобы Ansible запрашивал пароль:
# ansible-playbook myplaybook.yml --ask-vault-pass
Если вы использовали файл пароля вместо prompt, вы должны использовать опцию --vault-password-file:
# ansible-playbook myplaybook.yml --vault-password-file my_vault_password.py
Если вы используете данные, зашифрованные с помощью ID, вам нужно указать тот же ID хранилища и источник пароля, который вы использовали при первом шифровании данных:
# ansible-playbook myplaybook.yml --vault-id dev@prompt
Если вы используете файл пароля с ID, вы должны указать метку, а затем полный путь к файлу пароля в качестве источника:
# ansible-playbook myplaybook.yml --vault-id dev@vault_password.py
Если ваш play использует несколько хранилищ, вы должны добавить параметр --vault-id для каждого из них в произвольном порядке:
# ansible-playbook myplaybook.yml --vault-id dev@vault_password.py --vault-id test@prompt --vault-id ci@prompt
6. Оригиналы источников информации.
- selectel.ru «Система управления конфигурацией Ansible».
- dmosk.ru «Инструкция по установке и запуску Ansible на CentOS».
- dmosk.ru «Что такое ansible».
- 8host.com «Как работать с Ansible: простая удобная шпаргалка».
- habr.com «Автоматизируем и ускоряем процесс настройки облачных серверов с Ansible. Часть 1: Введение».
- kamaok.org.ua «Установка и использование Ansible на Centos7».
- Источник: https://hamsterden.ru/ansible-vault-playbooks/