В этой статье я покажу, как организовать простейший автодеплой на сервере. Для автодеплоя через 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);

После того, как вы узнали вашего пользователя, выполняем следующие шаги:

  1. Генерируем SSH-ключ для этого пользователя

sudo -u имя_этого_пользователя ssh-keygen -t rsa

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

  1. Добавляем bitbucket.org в known_hosts

ssh-keyscan -H bitbucket.org >> /путь/где/лежит/папка/.ssh/known_hosts
  1. Добавляем наш публичный ключ для этого пользователя в Bitbucket

Для начала выводим ключ терминале, копируем

cat /путь/где/лежит/папка/.ssh/id_rsa.pub

и добавляем в Bitbucket —  Personal settings->SSH keys->Add key.

  1. Создаем 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)


  1. eyeDM
    00.00.0000 00:00
    +1

    Какая же дичь. Ну серьёзно.

    Когда мы запускаем git pull с помощью PHP, команда выполняется не из root пользователя. Поэтому Bitbucket не распознает наш SSH-ключ. Из-за этого возникает ошибка доступа, если репозиторий закрытый.

    Какая прелесть.


    1. websitedev Автор
      00.00.0000 00:00
      -1

      Это не дичь, это действительно так. Попробуйте запулить из под PHP ключом рута.


      1. init0
        00.00.0000 00:00

        Я полагаю, что автор комментария назвал "дичью" то, что вы работает с git под рутом (иначе откуда эти ожидания, что подтянется ssh ключ именно его).


        1. websitedev Автор
          00.00.0000 00:00

          Ну пусть будет не рут, а другой пользователь. От этого суть не меняется.


          1. saboteur_kiev
            00.00.0000 00:00
            +1

            Вы реально не понимаете в чем суть?
            PHP Запускается от того пользователя которым вы запускаете. Поэтому совершенно ОЧЕВИДНО, что ssh ключ нужно настраивать для того пользователя, под которым вы работаете. Ни рут ни что-то еще в этом контексте не должен упоминаться в принципе. Если вы не можете контролировать свои действия и понимать под каким юзером вы запускаете программы, это как бы и есть дичь. К этому и претензия.


            Ваша же фраза выглядит как
            я вот сижу под пользователем USER, но когда запускаю php "myscript", оно выполняется не от рута.
            Дичь же?


          1. FanatPHP
            00.00.0000 00:00

            Суть не меняется, но проект под рутом дичью быть не перестает. Прямо каким-то ЛОР-ом из дремучих нулевых повеяло.


            1. websitedev Автор
              00.00.0000 00:00

              Согласен


  1. toxa82
    00.00.0000 00:00

    А почему бы для сайта не сделать отдельного пользователя? Настроить чтоб nginx от него работал, и git тоже. И не надо будет так веселиться с правами.


    1. websitedev Автор
      00.00.0000 00:00

      Да, тоже можно. Но разве это не займет больше времени, чем мой вариант?


      1. toxa82
        00.00.0000 00:00

        Ну у меня нет, у меня все так изначально настроено, у каждого сайта свой пользователь, даже если он один на ВПС. Так проще обновлять, зашел на сервер по ключам под этим пользователем, перешел в нужную папку и набрал git pull (ну или заходить под рутом и переключаться на нужного юзера если несколько сайтов и лень всем делать ключи и настраивать Патти). Ну и деплой по вэбхуку мне бы точно было проще настроить, только реализовать метод контроллера с нужными действиями.


        1. websitedev Автор
          00.00.0000 00:00

          Супер


    1. FanatPHP
      00.00.0000 00:00

      Ну он и делает примерно то же самое.
      Ну точнее он выясняет, под каким пользователем работает php-fpm, и дальше создает ключ для этого пользователя. В целом, система немного гибче получается. У интерактивного пользователя свой ключ, у какого-нибудь www-data — свой.


      1. toxa82
        00.00.0000 00:00

        А в чем гибкость? Придется извращаться с правами на файлы чтоб обновлять. И как я помню у www-data нет домашней директории, куда он ключи сохраняет и git конфиг? Как по мне лучше отдельный пользователь, не надо так веселится с правами и конфигами. Всё настраивается под него, и удобно работать, сайт создаёт файлы под тем же пользователем (загрузка, генерация, и т.п.). Удобно редактировать кронтаб для этого пользователя и запускать консольные скрипты находясь в нужной директории нужным пользователем.


        1. FanatPHP
          00.00.0000 00:00

          Да, вы правы.


        1. websitedev Автор
          00.00.0000 00:00

          Ну почему нет домашней директории. Для www-data ключ создается в /var/www, там и можно конфиг файл гита создать.


          1. toxa82
            00.00.0000 00:00
            +1

            Когда несколько сайтов как по мне безопасней когда каждый под своим пользователем, если какой-то взломают, то хоть до других по файловой системе не доберуться. Ну и еще мелочь: на www-data нельзя переключиться sudo -u www-data -i. Особенно если много нужно сделать в файлах мне например неудобно каждый раз писать sudo -u www-data mcedit .... Но это на любителя. У меня в хозяйстве один такой сайт, так админ заказчика настоял. Радует что ковыряться на том сервере приходится раз в год.


            1. websitedev Автор
              00.00.0000 00:00

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


            1. FanatPHP
              00.00.0000 00:00

              Вот да. Тем более, что делается это элементарно (о чем я узнал только на старости лет): www-data добавляется в группу пользователя и домашней папочке ставится 750. Учитывая что fpm и так под юзером, получается полное разграничение.


  1. z0rg
    00.00.0000 00:00
    +1

    Для это существует bitbucket pipelines, а не велосипеды через хуки


  1. Urichalex
    00.00.0000 00:00

    Писать скрипт который будет обновлять по хттп запросу. Играть с секурностью. Дебажить...

    Или написать несколько строк пайплайна в том же битбаккете