В этой статье я покажу, как организовать простейший автодеплой на сервере. Для автодеплоя через Bitbucket Webhooks и PHP не нужно использовать какие-то сложные решения.
Для начала можно подумать, что git pull
выполняется через PHP с помощью этого куска кода:
exec('cd /путь/к/корневой/папке && git pull origin master');
Но во время выполнения этого кода возникает ошибка доступа, даже, если SSH-ключ вашего текущего пользователя добавлен в Bitbucket.
Когда мы запускаем git pull
с помощью PHP, команда выполняется не от имени вашего пользователя. Поэтому Bitbucket не распознает наш SSH-ключ. Из-за этого возникает ошибка доступа, если репозиторий закрытый.
Функция exec
выполняет команды от имени стандартного пользователя вашего веб-сервера. В Nginx это обычно www-data
. Самый простой способ узнать пользователя от имени которого выполняются PHP скрипты, выполнять этот кусок кода и смотреть в браузере:
$result = exec('whoami');
var_dump($result);
После того, как вы узнали вашего пользователя, выполняем следующие шаги:
Генерируем SSH-ключ для этого пользователя
sudo -u имя_этого_пользователя ssh-keygen -t rsa
Путь, где лежит папка .ssh и сгенерированный ключ будет показываться во время генерации ключа.
Добавляем bitbucket.org в known_hosts
ssh-keyscan -H bitbucket.org >> /путь/где/лежит/папка/.ssh/known_hosts
Добавляем наш публичный ключ для этого пользователя в Bitbucket
Для начала выводим ключ терминале, копируем
cat /путь/где/лежит/папка/.ssh/id_rsa.pub
и добавляем в Bitbucket — Personal settings->SSH keys->Add key.
Создаем Webhook
Заходим в репозиторий нашего проекта, потом в Repository settings->Webhooks->Add Webhook.
Прописываем название вебхука, ссылку на которую он должен триггериться и событие, при котором должен произойти автодеплой.
Нужно обратить внимание, что вебхук отправляет POST запрос. Если ваш URL настроен на GET запросы, вебхук не будет работать. Bitbucket не показывает ошибку, если ссылка настроена на GET запросы, но и деплой не происходит.
PHP скрипт можно дополнять по необходимости. Можно кроме выполнения git pull
ещё мигрировать базу и выполнять другие команды. Вебхуки передают данные во время обращения к вашей ссылке. Эти данные вы можете обработать и сделать необходимые проверки.
Ошибки, которые могу возникнуть
Ошибка #1
Если владелец ваших файлов проекта пользователь root
, тогда Git может выдать такую ошибку "fatal: detected dubious ownership in repository".
Помогает рекурсивное изменение владельца папки на пользователя, от имени которого выполняются PHP скрипты.
chown -R имя_вашего_пользователя:root /путь/к/корневому/директорию/проекта
Еще можно в конфигах Git добавить эту настройку:
[safe]
directory = /путь/к/корневому/директорию/проекта
Для этого нужно создать .gitconfig
файл в домашнем директории вашего пользователя и в нем прописать эти настройки. Это тот директорий, где лежит ваша недавно сгенерированная папка .ssh
. Эти настройки будут применяться, когда Git запустится от имени этого пользователя.
Ошибка #2
Ещё может возникнуть ошибка "fatal: empty ident name not allowed"
Для решения ошибки Git предлагает выполнить эти команды, чтобы добавить ваше имя и почту:
git config --global user.email ""
git config --global user.name ""
Но эти команды задают глобальные настройки, а нам нужно задавать настройки именно для нашего пользователя. Для этого мы заходим в уже созданный для нашего пользователя .gitconfig
файл и добавляем следующие настройки:
[user]
name = ваше_имя
email = ваша_почту
После этого команда git pull
со стороны PHP должна работать.
Комментарии (20)
toxa82
00.00.0000 00:00А почему бы для сайта не сделать отдельного пользователя? Настроить чтоб nginx от него работал, и git тоже. И не надо будет так веселиться с правами.
websitedev Автор
00.00.0000 00:00Да, тоже можно. Но разве это не займет больше времени, чем мой вариант?
toxa82
00.00.0000 00:00Ну у меня нет, у меня все так изначально настроено, у каждого сайта свой пользователь, даже если он один на ВПС. Так проще обновлять, зашел на сервер по ключам под этим пользователем, перешел в нужную папку и набрал git pull (ну или заходить под рутом и переключаться на нужного юзера если несколько сайтов и лень всем делать ключи и настраивать Патти). Ну и деплой по вэбхуку мне бы точно было проще настроить, только реализовать метод контроллера с нужными действиями.
FanatPHP
00.00.0000 00:00Ну он и делает примерно то же самое.
Ну точнее он выясняет, под каким пользователем работает php-fpm, и дальше создает ключ для этого пользователя. В целом, система немного гибче получается. У интерактивного пользователя свой ключ, у какого-нибудь www-data — свой.toxa82
00.00.0000 00:00А в чем гибкость? Придется извращаться с правами на файлы чтоб обновлять. И как я помню у www-data нет домашней директории, куда он ключи сохраняет и git конфиг? Как по мне лучше отдельный пользователь, не надо так веселится с правами и конфигами. Всё настраивается под него, и удобно работать, сайт создаёт файлы под тем же пользователем (загрузка, генерация, и т.п.). Удобно редактировать кронтаб для этого пользователя и запускать консольные скрипты находясь в нужной директории нужным пользователем.
websitedev Автор
00.00.0000 00:00Ну почему нет домашней директории. Для
www-data
ключ создается в /var/www, там и можно конфиг файл гита создать.toxa82
00.00.0000 00:00+1Когда несколько сайтов как по мне безопасней когда каждый под своим пользователем, если какой-то взломают, то хоть до других по файловой системе не доберуться. Ну и еще мелочь: на www-data нельзя переключиться sudo -u www-data -i. Особенно если много нужно сделать в файлах мне например неудобно каждый раз писать sudo -u www-data mcedit .... Но это на любителя. У меня в хозяйстве один такой сайт, так админ заказчика настоял. Радует что ковыряться на том сервере приходится раз в год.
websitedev Автор
00.00.0000 00:00Кстати, есть решение, чтобы переключаться на пользователя, для которого не предусмотрен логин.
FanatPHP
00.00.0000 00:00Вот да. Тем более, что делается это элементарно (о чем я узнал только на старости лет): www-data добавляется в группу пользователя и домашней папочке ставится 750. Учитывая что fpm и так под юзером, получается полное разграничение.
Urichalex
00.00.0000 00:00Писать скрипт который будет обновлять по хттп запросу. Играть с секурностью. Дебажить...
Или написать несколько строк пайплайна в том же битбаккете
eyeDM
Какая же дичь. Ну серьёзно.
Когда мы запускаем
git pull
с помощью PHP, команда выполняется не изroot
пользователя. Поэтому Bitbucket не распознает наш SSH-ключ. Из-за этого возникает ошибка доступа, если репозиторий закрытый.Какая прелесть.
websitedev Автор
Это не дичь, это действительно так. Попробуйте запулить из под PHP ключом рута.
init0
Я полагаю, что автор комментария назвал "дичью" то, что вы работает с
git
под рутом (иначе откуда эти ожидания, что подтянется ssh ключ именно его).websitedev Автор
Ну пусть будет не рут, а другой пользователь. От этого суть не меняется.
saboteur_kiev
Вы реально не понимаете в чем суть?
PHP Запускается от того пользователя которым вы запускаете. Поэтому совершенно ОЧЕВИДНО, что ssh ключ нужно настраивать для того пользователя, под которым вы работаете. Ни рут ни что-то еще в этом контексте не должен упоминаться в принципе. Если вы не можете контролировать свои действия и понимать под каким юзером вы запускаете программы, это как бы и есть дичь. К этому и претензия.
Ваша же фраза выглядит как
я вот сижу под пользователем USER, но когда запускаю php "myscript", оно выполняется не от рута.
Дичь же?
FanatPHP
Суть не меняется, но проект под рутом дичью быть не перестает. Прямо каким-то ЛОР-ом из дремучих нулевых повеяло.
websitedev Автор
Согласен