Разработка на WordPress по-человечески, с использованием GIT

Как обычно ведётся разработка на WordPress?
Одним из двух способов:
1) Полностью на удалённом сервере
1.1 Устанавливаем wordpress на удалённом сервере
1.2 Закрываем доступ к нему через .htaccess и .htpasswd чтобы посторонние не лезли, пока он не готов
1.3 Подключаемся к сайту по FTP через FileZilla и вручную создаём тему дизайна
2) На локальном сервере, с последующей одноразовой выгрузкой
2.1 Устанавливаем wordpress на локальной машине
2.2 Через /etc/hosts прописываем строчку, чтобы адрес будущего сайта указывал на локальную машину
2.3 Разрабатываем сайт на локальной машине, обращаясь к ней по адресу будущего сайта
2.4 По готовности выгружаем сайт на боевой сервер через ftp и mysql

Однако, любой разработчик, имеющий опыт командной работы над сайтом с обменом кодом посредством git, давно привычен к гораздо лучшему. Разработка “по-человечески”, с использованием удалённого git-репозитория имеет множество плюсов.

Но начать разрабатывать сайты на wordpress с использованием git-а на разных машинах не так просто, как хотелось бы.
Путём долгих поисков и большого количества набитых шишек я создал алгоритм разработки сайтов на wordpress с использованием git и минимальными проблемами.

Итак, какова задача:
1. Получить возможность работать с WordPress посредством репозитория git, выгружать изменения в удалённый репозиторий, работать командой.
2. Не иметь проблем с доменными именами, чтобы wordpress на разных доменных именах работал “как родной”, хоть на site.ru, хоть на site.local
3. Иметь возможность синхронизировать базу данных на локальном и удалённом сайте без ручных манипуляций с mysqldump и более удобно, чем с помощью тормозных wordpress-плагинов.
4. При этом, не помещать в репозиторий изображения с изменёнными размерами (помещать picture.jpeg, но не помещать picture-130×230.jpeg), и, при этом, не иметь проблем с такими изображениями на “боевом” сервере.
5. Заодно, чтобы 2 раза не вставать, нужно чтобы наш сайт был максимально защищён от взломов.

Системные требования:
Для реализации задуманного нам понадобится:
1. Операционная система Gnu/Linux на вашем ПК. Если у вас Windows, или MacOS можно установить Linux в виртуальной машине, так как разработка в Linux всё равно будет гораздо удобнее.
2. Удалённый web-сервер на Linux, с возможностью ssh-доступа, возможностью прописать свой публичный ключ, установленным там git,

Создание папок проекта

1. Выберем любое место, которое удобно, например /var/www и создадим там папку проекта, допустим mysite.local. В дальнейшем я буду называть эту папку “папка проекта
2. В этой папке создадим папку www (в неё мы будем класть wordpress)
3. Также, рядом создадим папку mysqldump (в неё скрипт обмена данными будет складывать копии базы)

В результате у вас должна получиться примерно такая структура:
/var/www/mysite.local
/var/www/mysite.local/www
/var/www/mysite.local/mysqldump

4. Создадим файл mysqldump/.gitkeep:

apt-get install git ssh

Этот файл понадобится для того, чтобы папка mysqldump добавилась в репозиторий, при том, что её содержимое (кроме этого файла) в репозиторий добавлено не будет.

Установка WordPress и необходимых плагинов

1. Установим wordpress на локальный сервер в папку www, которую вы создали ранее, зададим ему произвольное доменное имя, например mysite.local.
1.1. Пропишем это доменное имя в /etc/hosts
1.2. Настроим веб-сервер, чтобы доменное имя указанное в /etc/hosts вело к папке www, куда установлен wordpress)
1.3. Создадим базу данных, желательно назвать её так же, как вы назовёте базу на удалённом сервере. Поскольку, при использовании shared-хостинга, именование баз данны будет ограничено, у вас может не получиться создать на удалённом сервере базу с любым названием.
1.4. Проведём стандартную установку WordPress
2. Установим необходимые плагины:
2.1. Limit login attempts – для ограничения попыткой логина и защиты от брутфорса
2.2. Anti-Malware Security and Brute-Force Firewall – плагин позволяющий проводить сканирование файлов на наличие вредоносных скриптов, а также, включающий свою защиту от брутфорса (придётся зарегистрироваться для обновления определений вирусов)
2.3. WangGuard – защита от массовой регистрации спам-пользователей (если у вас на сайте будет открыта регистрация для всех)
2.4. Wordfence Security – мощная система безопасности для WordPress (придётся зарегистрироваться)

Внесение изменений в код для полноценной работы с разными доменами

1. Создадим в корне сайта файл wp-domains.php

Содержимое файла:

$ ls ~/.ssh/id_rsa.pub

Важно в начале файла в список доменов $domains_enabled включить все домены, на которых будет работать сайт. Это нужно потому, что wordpress, при редактировании страниц, вписывает в текст абсолютные ссылки на страницы и объекты вашего сайта. А ссылки эти могут включать в себя любые домены из тех, на которых может работать сайт. Чтобы, кликнув по ссылке на странице локального сайта, не перейти на боевой, или наоборот, функция в конце, завёрнутая в ob_start, перед выдачей заменит все ссылки на другие домены вашим текущим доменом.

2. Подключим этот файл в начале файлов: wp-config.php, wp-load.php

$ ssh-keygen

Теперь нужно проверить ваш сайт, работает ли он как следует с данными изменениями.

Настройка git

1. Создадим файл .gitignore в папке проекта, и запишем в него следующий код:

ssh-keygen

Изображения (папка uploads) мы не будем исключать из репозитория, потому что, по сути, изображения являются частью сайта, а не просто загружаемым пользователем контентом. При изменении изображений на удалённом сервере (на боевом) мы также будем добавлять их в репозиторий с помощью инструмента rgit, описанного далее

2. Инициализируем репозиторий, добавим в него все файлы и закоммитим

cd /var/www/mysite.local

3. Создадим удалённый репозиторий где-нибудь, где вам это доступно.
Вам нужен репозиторий, доступный и с вашей машины, и с “боевого” сервера.
Варианты:
а) Создать репозиторий на github.com – легко и удобно, минус в том что там он будет публичным
б) Создать репозиторий на bitbucket.com – почти как гитхаб, только лучше, ведь в нём можно создавать приватные репозитории
в) Создать репозиторий на каком-то своём сервере, пусть даже на самом боевом.

Выбирайте что вам по душе, я же буду рассказывать про третий вариант, так как он даёт наибольшую гибкость и независимость.

Я буду считать, что для создания репозитория, как и для хостинга вашего сайта на wordpress у вас есть сервер, купленный, например на vscale.io (цены там сравнимы с ценами на shared-хостинг, от 200 рублей в месяц), и на этом сервере вы царь и бог.
3.1. Создадим пользователя git и перейдём в него:

cd /c/server/mysite.local

3.2. Создадим папку для нового bare-репозитория, и внутри неё репозиторий:

touch ./mysqldump/.gitkeep

3.3. Добавим доступ по ssh к пользователю git без пароля
Выполняем на вашей домашней машине (от имени вашего пользователя):
Если у вас ещё нет ssh-ключа, то создадим его:

<?php
//Проверим, не запускался ли данный скрипт ранее:
if (defined("WP_DOMAINS_INITIALIZED")) return;
define("WP_DOMAINS_INITIALIZED", 1);
 
//Домены на котором может работать сайт, локальные и удалённые,
//*********************************
//*** УКАЖИТЕ ЗДЕСЬ СВОИ ДОМЕНЫ ***
//*********************************
$domains_enabled = array(
    "mysite.local",
    "www.mysite.local",
    "mysite-test.hosting.ru",
    "mysite.ru",
    "www.mysite.ru"
);
 
//Добавим в массив $_SERVER все необходимые для проверки ключи,
//которых там может не быть
$_SERVER = array_replace(
    array(
        "HTTPS"=>"", "HTTP_HTTPS"=>"", "REQUEST_SCHEME"=>"", "SERVER_PORT"=>""
    ),
    $_SERVER
);
 
//Проверим, используется ли https?
$https =
    ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
        || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off')
        || $_SERVER['REQUEST_SCHEME'] == 'https'
        || $_SERVER['SERVER_PORT'] == 443) ? true : false;
 
//Составим адрес хоста
$site_addr = ($https ? "https://" : "http://") . $_SERVER['HTTP_HOST'] . "/";
 
//Заменим адрес хоста на тот, что мы вычислили
if (!defined("WP_HOME")) define("WP_HOME", $site_addr);
if (!defined("WP_SITEURL")) define("WP_SITEURL", $site_addr);
 
//Добавим обработчик выдачи сайта, который будет заменять во всех ссылках
//домены на текущий домен
ob_start(function($data) use ($domains_enabled, $https) {
    $current_host = $_SERVER['HTTP_HOST'];
    $replace = array();
    $scheme = $https ? "https" : "http";
    foreach($domains_enabled as $domain)
    {
        if ($current_host == $domain) continue;
        $replace["http://$domain/"] = "$scheme://$current_host/";
        $replace["https://$domain"] = "$scheme://$current_host";
        $replace["//$domain/"] = "//$current_host/";
        $replace["//$domain"] = "//$current_host";
    }
    return str_replace(array_keys($replace), array_values($replace), $data);
});

Выведем содержимое ключа

<?php require_once(__DIR__ . "/wp-domains.php");

В результате в консоль будет выдана простыня символов, представляющая собой ваш публичный ssh-ключ,
выглядеть она будет примерно так:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLuC89TPgs4pX1TjRxsDKZUpBalOC3KS71bUnt/XKx3tFvDqMag0xQpdVCHwWcj1/Q+m//56w9DYTOGXXGBysnNNwIk4oifv6X4voZ/rL0/Aulaxyr+zJX4bJpXqxxeSNVLdqqTOlg84+kqrtSAzx1wAiByV4awZU5RSA+U0P225P9R0BMoBA1rD7+9+b3NBYDYDSk0X8+OjS6HDgqntY9OiMMBV3GvPw+cQd4ha9RM8tou8ZrgTRRNCt7gxO1Oxfn0D7P+8UyZenu3EyIWwnVovhCuSelyaw3WnICEDFxJ3ZLBg42M2TGOLveSheVyRgal1HLVdX9e+mu+Vp5zpH1 user@LinuxPc

Этот текст надо скопировать, после чего на сервере, где будет жить репозиторий, создать файл ~/.ssh/authorized_keys и вставить туда скопированный текст.
Запускаем на удалённой машине от имени пользователя git:

/www/wp-content/ai1wm-backups/
www/wp-content/wflogs/
*.log
*.sql
*.sql.gz
error-logs.txt

Откроется текстовый редактор, где надо вставить скопированный текст, и сохранить файл, нажав Ctrl+O. Выход – Ctrl+X
3.4. Добавим данный репозиторий как удалённый (remote) в ваш локальный репозиторий.
Если ваш сервер имеет адрес mysite.ru,а репозиторий mysite.git, то команда будет такой:
(Запускать нужно с вашей локальной машины из папки с репозиторием)

$ git init
$ git add .
$ git commit -m "Initial commit"

3.5. Выгрузим все изменения из вашего локального репозитория в удалённый:

ls ~/.ssh/id_rsa.pub

4. Настроим сайт на боевом сервере:

4.1. Дадим пользователю вашего боевого сайта беспарольный доступ к репозиторию git:
Допустим, пользователя зовут remoteuser:
Выполняем на машине боевого сервера:
Если ещё нет ssh-ключа:

ssh-keygen -t rsa -b 4096 -o -a 100

Выведем публичный ключ:

cat ~/.ssh/id_rsa.pub

Данный ключ нужно записать туда же, куда вы записывали свой личный ключ 3.3.

4.2. Склонируем репозиторий в папку /var/www/mysite.ru:

ssh myuser@myserver.ru

4.3. Создадим базу данных с тем же логином и паролем, что на локальном сервере, загрузим в неё дамп базы с локального сервера
Это остаётся вам в качестве домашнего задания 🙂

5. Создадим полезные в работе скрипты:

5.1. Скрипт в корне проекта скрипт rgit – предназначен для дистанционного выполнения команд git на удалённом сервере.
Можно было бы навесить хуки гита для автоматического обновления боевого сайта, однако, в случае с WordPress это будет неудобно, потому что сайт могут править и на боевом сервере, устанавливать там плагины, обновлять сам wordpress. А когда сайт заработает, то не просто “могут” а “обязательно будут”.

На вашей локальной машине создадим скрипт rgit в папке проекта:

su
su www-data

В файл добавим следующий код (разумеется, логин пользователя, адрес сервера, и папку вашего проекта на сервере нужно поменять):

sudo su www-data

Делаем этот скрипт выполняемым:

nano ~/.ssh/authorized_keys

Теперь любую команду git-а, которую вы можете запустить в локальном репозитории, вы также можете запустить и в удалённом, никуда не подключаясь и не переходя, практически не меняя команды, только вместо “git” вы будете начинать команду с “./rgit”.
Например:

Где нужно выполнить команду Команды
Локальный сервер git pull git push git reset –hard git checkout mybranch
Удалённый сервер ./rgit pull ./rgit push ./rgit reset –hard ./rgit checkout mybranch

Как и было сказано, команда отличается только началом.
Что нам это даёт: мы можем находясь в локальном репозитории командовать также и удалённым.
Пример работы:

ssh www-data@myserver.com

Здесь мы коммитим изменения в локальном репозитории, после чего, коммитим изменения в удалённом, добавляя загруженную пользователем картинку, после чего выгружаем с удалённого репозитория изменения в origin соединяем их с нашими изменениями на локальном, и, выгрузив локальные изменения в origin, скачиваем их в удалённый репозиторий.

5.2. Скрипт mysqltool.php
Этот скрипт гораздо больше по объёму, поэтому его нужно скачать из репозитория https://github.com/MihanEntalpo/WordpressGitTools/blob/master/mysqltool.php
Данный скрипт предназначен для удобных операций с базой данных, локальной и удалённой. С помощью него вы в одну команду сделаете дамп базы на локальном или удалённом сервере, выгрузите локальную базу на удалённый сервер, или загрузите базу с удалённого сервера на локальный. И всё это без колдовства с mysql, mysqldump, ssh ручным вводом паролей и команд.
Примеры команд:
Снять образ локальной базы данных:

# adduser git
# su git

Снять образ удалённой базы данных:

mkdir /home/git/mysite.git
cd /home/git/mysite.git
git init --bare

Снять образ удалённой базы данных, и загрузить её вместо локальной базы.

mkdir -p ~/.ssh

Снять образ локальной базы данных, и загрузить её вместо удалённой базы.

$ nano /home/git/.ssh/authorized_keys

Запросить справку по работе со скриптом можно вызвав его без параметров, либо командой:

$ git remote add origin git@mysite.ru:mysite.git

С помощью данного инструмента можно значительно облегчить себе работу с базой данных. Когда вы что-то меняли на “боевом” сервере, то перед началом работы на локальном можно выполнить ./mysqltool.php pull, а по окончанию работы, после выгрузки изменений в файлах через git, можно выгрузить и базу данных с помощью ./mysqltool.php push

5.3. Скрипт ./gcb
Данный скрипт предназначен для упрощения работы с ветками. Данный скрипт также можно взять из репозитория: https://github.com/MihanEntalpo/WordpressGitTools/blob/master/gcb
Эксплуатация:
Получить список локальных и удалённых веток, узнать текущую ветку:

$ git push

Создать новую ветку, причём как в локальном так и в удалённом репозитории, чтобы команда git push, запущеная в другой ветке нежели master выгружала изменения в аналогичную ветку на сервере.

ssh-keygen

Переключиться на существующую ветку:

cat ~/.ssh/id_rsa.pub

5.4. Добавим все эти скрипты в репозиторий и выгрузим их в удалённый репозиторий:

$ cd /var/www
$ git clone git@mysite.ru:mysite.git mysite.ru

Итоги:

В результате данной инструкции можно перейти на разработку на wordpress с использованием git в команде, перестать мучаться с выгрузкой по FTP, и с ручным переносом баз данных.
Остаются правда некоторые неудобства, связанные, опять же, с базой, в частности: при работе командой нужно заранее связываться друг с другом и предупреждать о том, кто выгружает базу данных, а кто её себе загрузит, так как частично базу изменить нельзя, только полностью одним махом.
Тем не менее, способ вполне рабочий, и сильно облегчает жизнь. Может и вам пригодится.


So, what do you think ?