Итак, в предыдущих записях по теме LAMP я не рассмотрел сам процесс настройки серверов. Восполним этот пробел. Будет много букв.
Настраивать LAMP на сервере будем при помощи Ansible. Для этого у меня подготовлен файл lamp.yml, который буде приведён ниже. Могу что-то упустить, но в принципе предыдущие статьи должны восполнить пробелы.
Итак, поехали.
Для облегчения себе жизни и нехранения паролей в открытом виде, восспользуемся входом на удалённые сервера по ключу. Для генерации пары ключей (открытый-закрытый), выполним команду:
ssh-keygen -t rsa -b 4069 # на запрос имени файла ключа, вводим имя ansible.key
После выполнения этой команды, создадутся 2 файла: открытый ключ ansible.key.pub и закрытый ключ ansible.key.
Теперь наш открытый (также его еще называют публичный — public) ключ необходимо доставить на управляемый сервер:
ssh-copy-id -i ansible.key.pub -o StrictHostKeyChecking=no admin@192.168.88.23
Ключ StrictHostKeyChecking=no скажет нашему клиенту не ругаться на незнакомые сервера. На запрос пароля пользователя admin, вводим его.
Кроме того, на нашей админской машине необходимо убедиться, что агент SSH запущен и дабавить наш закрытый ключ в его хранилище:
eval "$(ssh-agent -s)" ssh-add ansible.key
Далее пробуем подсоединиться к серверу, никаких дополнительных запросов быть не должно:
ssh admin@192.168.88.23
Если мы увидели командную строку удалённого сервера, то значить всё сделали правильно и можно двигаться дальше.
Теперь проверим, что Ansible также сможет работать с удаленной машиной, выполнив простую команду для просмотра её конфигурации:
ansible web-trusty -m setup >> trusty.txt
Чтобы после каждой перезагрузки нашей управляющей машины не добавлять ключ в хранилище агента заново, создадим вложенную папку ./key/ в папке с файлом lamp.yml и положим туда ключ ansible.key. Запомним это действие.
В файле inventory (также будет приведён ниже) создана группа prod_WEB в которую включён наш будущий lamp-сервер с ip-адресом 192.168.88.23 с присвоенным именем web-trusty. Также, в плэйбуке используется ряд переменных (например, путь до закрытого ключа в папке key), которые вынесены в отдельный файл prod_WEB (должен совпадать с именем группы в inventory), находящийся во вложенной папке ./group_vars/. Имейте в виду, что, в данном конкретном случае, это имя видно только для Ansible.
Файл inventory:
[prod_WEB] web-trusty ansible_host=192.168.88.21
Файл с переменными ./group_vars/prod_WEB:
--- ansible_user: admin ansible_ssh_private_key_file: ./keys/ansible.key app_user: "admin" http_host: "{{ ansible_fqdn }}" http_conf: "home.local.conf" http_port: "80" disable_default: true
Обратите внимание, что файл должен начинатья с трёх тире!!
Дабы передать в плэйбук при запуске значение переменной HOSTS, воспользуемся ключём —extra-vars, который позволяет заменить переменную, объявленную в тексте плэйбука, атакже переопределить вообще любую переменную нашего проекта. Имейте это в виду и пользуйтесь.
Итак, файл lamp.yml:
---
- name: LAMP servers install & configure
hosts: "{{ HOSTS | default('test_WEB') }}"
become: yes
# ниже закоментаренные переменные, которые мы перенесли в папку ./group_vars
# vars:
# app_user: "admin"
# http_host: "{{ ansible_fqdn }}"
# http_conf: "home.local.conf"
# http_port: "80"
# disable_default: true
tasks:
- name: Install LAMP stack for Ubuntu Trusty
block:
- name: Install LAMP Packages Ubuntu Trusty
apt: name={{ item }} update_cache=yes state=latest
loop: [ 'apache2', 'mysql-server', 'python-mysqldb', 'php5', 'php5-mysql', 'libapache2-mod-php5' ]
- name: Ensure Apache is running
service: name=apache2 state=started enabled=yes
- name: UFW - Allow HTTP on port {{ http_port }} (for trusty)
ufw:
rule: allow
port: "{{ http_port }}"
proto: tcp
when: ansible_distribution_release == "trusty"
- name: Install LAMP stack for Debian Bullseye
block:
- name: Install LAMP Packages Debian Bullseye
apt: name={{ item }} update_cache=yes state=latest
loop: [ 'apache2', 'default-mysql-server', 'python3-pymysql', 'php', 'php-mysql', 'libapache2-mod-php', 'php-mbstring', 'php-gd', 'php-dom' ]
- name: Ensure Apache is running
service: name=apache2 state=started enabled=yes
when: ansible_distribution_release == "bullseye"
- name: Install LAMP stack for RedHat
block:
- name: Install Apache (for RedHat)
yum: name={{ item }} state=latest
loop:
- httpd
- mariadb
- mariadb-server
- MySQL-python
- php
- php-pear
- php-gd
- php-xml
- php-mysqlnd
- php-mbstring
- name: Ensure Apache, MySQL and PHP is running (for RedHat)
service: name={{ item }} state=started enabled=yes
loop:
- httpd
- mariadb
- name: Ensure firewalld started & anabled on boot (for RedHat)
service: name=firewalld enabled=yes state=started
- name: Open port {{ http_port }} for tcp (for RedHat)
firewalld: port={{ http_port }}/tcp permanent=yes state=enabled
notify: Restart firewalld
when: ansible_os_family == "RedHat"
- name: Create document root
file:
path: "/var/www/{{ http_host }}"
state: directory
owner: "{{ app_user }}"
mode: '0755'
- name: Sets Up PHP Info Page
template:
src: "files/info.php"
dest: "/var/www/{{ http_host }}/info.php"
- name: Enable new site for Ubuntu/Debian
block:
- name: Set up Apache virtualhost (for Ubuntu/Debian)
template:
src: "files/apache2.conf.j2"
dest: "/etc/apache2/sites-available/{{ http_conf }}"
- name: Enable site (for Ubuntu/Debian)
shell: /usr/sbin/a2ensite {{ http_conf }}
- name: Disable default Apache site (for Ubuntu/Debian)
shell: /usr/sbin/a2dissite 000-default.conf
when: disable_default
notify: Restart Apache Debian
when: ansible_os_family == "Debian"
- name: Enable new site for RedHat
block:
- name: Turn on CONF.D folder scan
shell: sed -i 's/#IncludeOptional conf.d/IncludeOptional conf.d/g' /etc/httpd/conf/httpd.conf
- name: Set up Apache virtualhost for RedHat
template:
src: "files/apache2.conf.j2"
dest: "/etc/httpd/conf.d/{{ http_conf }}"
notify: Restart Apache RedHat
when: ansible_os_family == "RedHat"
handlers:
- name: Restart firewalld
service: name=firewalld state=restarted
- name: Restart Apache RedHat
service: name=httpd state=restarted
- name: Restart Apache Debian
service: name=apache2 state=restarted
Настройку MySQL я выполнял при помощи другого плэйбука (приводил его в отдельной записи здесь), по идее это всё надо делать с помощью ролей, но как сделал — так сделал. Содержимое mysql.yml ниже:
---
- name: Test playbook for initial installed MySQL
hosts: "{{ HOSTS | default('test_WEB') }}"
become: yes
vars:
mysql_root_password: "superpassword"
mysql_dbuser_password: "puperpassword"
tasks:
# MySQL Configuration
- name: Sets the root password (Centos 7)
mysql_user: name=root host={{ item }} password={{ mysql_root_password }}
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- localhost
when: ansible_os_family == "RedHat"
- name: Sets the root password (Debian/Ubuntu)
mysql_user: name=root host={{ item }} password={{ mysql_root_password }} login_unix_socket="/var/run/mysqld/mysqld.sock"
with_items:
- "{{ ansible_hostname }}"
- 127.0.0.1
- ::1
- localhost
when: ansible_os_family == "Debian"
- name: Copy .my.cnf file with root password credentials
template: src=files/my.cnf.j2 dest=/root/.my.cnf owner=admin mode=0600
- name: Removes all anonymous user accounts
mysql_user:
name: ''
host_all: yes
state: absent
login_user: root
login_password: "{{ mysql_root_password }}"
- name: Add dbuser for WordPress to MySQL config
mysql_user:
name: dbuser
password: "{{ mysql_dbuser_password }}"
host: localhost
priv: 'webdb.*:ALL,GRANT'
state: present
login_user: root
login_password: "{{ mysql_root_password }}"
Приведенные плэйбуки успешно отработали на Debian 11 Bullseye, Ubuntu Trusty и Centos 7, если что…
Содержимое вспомогательных файлов в папке files проекта приведу ниже.
info.php:
<?php phpinfo(); ?>
Шаблон конфигурации Apache apache2.conf.j2:
<VirtualHost *:{{ http_port }}> ServerAdmin webmaster@localhost ServerName {{ http_host }} ServerAlias www.{{ http_host }} DocumentRoot /var/www/{{ http_host }} <Directory /var/www/{{ http_host }}> Options -Indexes </Directory> <IfModule mod_dir.c> DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm </IfModule> </VirtualHost>
Шаблон конфигурации клиента MySQL my.cnf.j2:
[client] user=root password={{ mysql_root_password }}
В итоге, наши команды для отработки плэйбука будет выглядеть следующим образом:
ansible-playbook lamp.yml --extra-var HOSTS=prod_WEB ansible-playbook mysql.yml --extra-var HOSTS=prod_WEB
В приведенной команде, плэйбуки lamp.yml и mysql.yml применяются ко всей группе prod_WEB. Также, мы могли передать в переменную HOSTS и имя web-trusty. Результат был бы тем же.
…
PROFIT!!!!