Статьи

Как правильно развернуть веб-приложения через SFTP с помощью Git

Эта статья была рецензирована Хайдаром Кюлекси и Верном Анчетой . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!


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

Вы можете легко загрузить свои файлы на SFTP-сервер, используя настольный клиент с открытым исходным кодом, например, Filezilla . Те, кто использовал это, знают, что этот процесс громоздок и раздражает, поскольку он не позволяет нам автоматизировать наш процесс развертывания, и нам всегда нужно загружать весь проект, даже если мы изменили только часть файлов нашей кодовой базы ,

Абстрактное изображение, символизирующее загрузку - форма облака, сделанная из светящихся бирюзовых пикселей, а перед ней или внутри нее стрелка, указывающая вверх

Пакет PHPSECLIB ( PHP Scuure C ommunications Lib rary) имеет отличный API для рутинных задач SFTP: он использует некоторые необязательные расширения PHP, если они доступны, и в противном случае использует внутреннюю реализацию PHP. Вам не нужно никаких дополнительных расширений PHP, чтобы использовать этот пакет, подойдут расширения по умолчанию, которые упакованы с PHP. В этой статье мы сначала рассмотрим различные функции PHPSECLIB — SFTP , включая, но не ограничиваясь, загрузку или удаление файлов. Затем мы рассмотрим, как мы можем использовать Git в сочетании с этой библиотекой для автоматизации нашего процесса развертывания SFTP.

Установка PhpSecLib

composer require phpseclib/phpseclib

Это установит самую последнюю стабильную версию библиотеки через Composer .

Аутентификация

По умолчанию аутентификация по паролю используется для подключения к вашему SFTP-серверу. Криптографическая пара ключей более безопасна, потому что вместо пароля используется закрытый ключ, который, как правило, намного сложнее взломать . Используя phpseclib , вы можете подключиться к вашему SFTP-серверу любым из следующих способов аутентификации:

  1. Ключ RSA
  2. Защищенный паролем ключ RSA
  3. Имя пользователя и пароль ( не рекомендуется )

Ключ RSA

Мы предполагаем, что у вас уже есть безопасный ключ RSA . Если вы не знакомы с созданием безопасной пары ключей RSA, вы можете прочитать эту статью . Для объяснения видео вы можете обратиться к разделу Создание и использование ключей SSH с серверов для хакеров.

Чтобы войти на удаленный сервер с использованием аутентификации по ключу RSA :

 namespace App;

use phpseclib\Crypt\RSA;
use phpseclib\Net\SFTP;

$key = new RSA();
$key->loadKey(file_get_contents('privatekey'));

//Remote server's ip address or hostname
$sftp = new SFTP('192.168.0.1');

if (!$sftp->login('username', $key)) {
    exit('Login Failed');
}

Защищенный паролем ключ RSA

Если ваши ключи RSA защищены паролем, не беспокойтесь. PHPSECLIB заботится об этом конкретном случае использования:

 namespace App;

use phpseclib\Crypt\RSA;
use phpseclib\Net\SFTP;

$key = new RSA();
$key->setPassword('your-secure-password');
$key->loadKey(file_get_contents('privatekey'));

//Remote server's ip address or hostname
$sftp = new SFTP('192.168.0.1');

if (!$sftp->login('username', $key)) {
    exit('Login Failed');
}

Имя пользователя и пароль

Кроме того, чтобы войти на удаленный сервер, используя имя пользователя и пароль (мы не рекомендуем эту практику):

 namespace App;

use phpseclib\Net\SFTP;

//Remote server's ip address or hostname
$sftp = new SFTP('192.168.0.1');

if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

Для других опций, таких как Без аутентификации или Многофакторной аутентификации, пожалуйста, обратитесь к документации .

Загрузка и удаление файлов

Большая часть процесса развертывания включает загрузку файлов на сервер. Загрузка файлов по сути означает передачу содержимого локального файла в удаленный файл. В приведенном ниже примере создается файл index.phpЭто фиктивный файл :

 namespace App;

use phpseclib\Crypt\RSA;
use phpseclib\Net\SFTP;

$key = new RSA();
$key->loadKey(file_get_contents('privatekey'));

//Remote server's ip address or hostname
$sftp = new SFTP('192.168.0.1');

if (!$sftp->login('username', $key)) {
    exit('Login Failed');
}

$sftp->put('index.php', 'This is a dummy file');

По умолчанию put Содержимое сбрасывается прямо в удаленный файл. В реальном сценарии вам нужно извлечь содержимое локальных файлов и выгрузить их в удаленный файл:

 $contents = file_get_content('path/to/local/file');
$sftp->put('index.php', $contents);

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

 //Deleting a single file. This does not delete directories.
$sftp->delete('index.php');

//Deleting directories and files recursively
$sftp->delete('dir_name', true);

Автоматизация развертывания с помощью Git

Git широко признан в качестве отраслевого стандарта инструментов управления версиями. Используя возможности Git, мы можем сэкономить некоторое время и пропускную способность, загружая только те файлы, которые изменились с момента последней загрузки. Используя SFTP API PHPSECLIB , мы попытаемся развернуть наши файлы на нашем SFTP-сервере.

Я разделил весь процесс развертывания на несколько шагов ниже, чтобы лучше объяснить каждый из них. Как только мы пройдем все этапы, мы соберем все вместе.

Некоторые основы Git

Во-первых, нам нужно понять некоторые конкретные команды Git, которые помогут нам в процессе развертывания. Мы создадим класс, который поможет нам выполнять задачи, связанные с Git. Команды Git выполняются из командной строки — для этого мы будем использовать компонент Process . Компонент обеспечивает уровень абстракции для выполнения команд оболочки и заботится о тонких различиях между различными платформами. Вы можете обратиться к его документации для получения дополнительной информации. Сейчас мы напишем код, специфичный для извлечения файлов, добавленных, измененных или удаленных между двумя заданными коммитами.

 <?php

namespace App;

use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;

class Git 
{
    public function diffFiles($start_commit, $end_commit)
        {
        //Get new and modified files
        $process = new Process("git diff --name-only --diff-filter=AM $start_commit $end_commit");

        $process->setTimeout(3600);
        $process->setWorkingDirectory('/path/to/local/repository');
        $process->run();

        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

    //Extract all file paths from the process output
        $files["added"] = array_unique(
        array_merge($files["added"], 
        array_filter(explode("\n", $process->getOutput()), 'strlen'))
    );

    //Get deleted files
        $process = new Process("git diff-tree --diff-filter=D --name-only -t $start_commit $end_commit");

        $process->setTimeout(3600);
        $process->setWorkingDirectory('/path/to/local/repository');
        $process->run();

        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }

        $files["deleted"] = array_filter(explode("\n", $process->getOutput()), 'strlen');

        return $files;
    }
}

Получить содержимое файла при определенной фиксации

Git хранит исторические данные о данном хранилище в скрытой папке .git Чтобы продолжить процесс развертывания, нам нужно извлечь содержимое файлов, записанных Git, в указанный коммит. Мы добавим еще один метод в класс Git

 public function getContent($commit, $file)
{
    //Get contents of a file at a specific commit
    $process = new Process("git show \"$commit:$file\"");

    $process->setTimeout(3600);
    $process->setWorkingDirectory('path/to/repository');
    $process->run();

    if (!$process->isSuccessful()) {
        throw new ProcessFailedException($process);
    }

    return $process->getOutput();
}

Развертывание файлов

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

  1. Получать добавленные, измененные и удаленные файлы между двумя коммитами
  2. Передача новых и измененных файлов на сервер SFTP
  3. Удалить файлы, которые были удалены между двумя коммитами

Теперь, когда мы понимаем, чего нам нужно достичь, давайте вложим это в код:

 $files = $git->diffFiles($start_commit, $end_commit);

if(count($files['added']) > 0) {
    foreach($files['added'] as $file) {
        $content = $git->getContent($end_commit, $file);

        //Ensure a directory exists - if it doesn't create it recursively.
        if (!$sftp->file_exists(dirname($file))) {
            $sftp->mkdir(dirname($path), -1, true);
        }

        $sftp->put('/path/to/remote/file', $content);
    }
}

if(count($files['deleted']) > 0) {
    foreach($files['deleted'] as $file) {

        if ($sftp->file_exists($file)) {
            $sftp->delete($file, true);
        }

    }
}

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

Выполнение удаленных команд

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

 $sftp->exec("your-remote-command-here");

Как и в случае с SSH , вызов метода execexec Чтобы выполнить несколько команд без потери состояния:

 $sftp->exec(
    "php artisan up" . PHP_EOL
    "composer dump-autoload -o" . PHP_EOL
    "php artisan optimize"
);

Класс phpseclib\Net\SFTPphpseclib\Net\SSH Вы можете использовать полный API-интерфейс класса SSH Для всесторонней реализации SSHпредыдущий учебник .

Управление разрешениями

Разрешения — это базовая система защиты файла. Нам нужно назначить некоторые определенные права пользователям или группам пользователей для файлов на сервере, чтобы предотвратить потенциальные атаки.

Установка разрешений для одного файла возвращает разрешения для нового файла в случае успеха или false в случае ошибки:

 $sftp->chmod(0777, 'path/to/remote/file');

Кроме того, вы можете рекурсивно установить разрешения для всех файлов в каталоге:

 $sftp->chmod(0777, 'path/to/remote/file', true);

Ниже приведена сводка наиболее важных методов, касающихся прав доступа к файлам в классе SFTP

метод Случай использования
chgrp($filename, $gid, $recursive = false) Изменяет файл или группу каталогов.
chown($filename, $uid, $recursive = false) Изменяет владельца файла или каталога.
truncate($filename, $new_size) Усекает файл до заданной длины.
touch($filename, $time = null, $atime = null) Устанавливает время доступа и изменения файла. Если файл не существует, он будет создан.

Скачивание файлов

Используя PHPSECLIB , мы также можем загружать с сервера такие вещи, как файлы резервных копий или пользовательский носитель:

 //Gets the remote file's contents
$content = $sftp->get('path/to/remote/file');

//Downloads and saves to the local file
$sftp->get('path/to/remote/file', 'path/to/local/file');

Если файл отсутствует локально, он будет создан автоматически для вас.

альтернативы

  1. git-deploy-php — простой инструмент на основе PHP, который развертывает ваши измененные файлы на ваших серверах SFTP. Он автоматически передаст вам файлы для указанных коммитов.
  2. PHPloy — еще один инструмент развертывания на основе PHP для передачи файлов на SFTP-серверы. Он имеет больше функций, таких как откат, поддержка нескольких серверов и субмодулей и многое другое. Недостатком является слишком большая вовлеченность в ручную настройку для запуска развертывания.
  3. Deploy-Tantra — автоматически развертывает ваши репозитории на SFTP-серверах, когда вы отправляете в указанную ветку. Преимущество — более управляемый рабочий процесс. Недостатком является коммерческий.

Вывод

В этой статье мы представили конкретный способ, помогающий автоматизировать процесс развертывания SFTP-серверов, и рассмотрели параметры конфигурации, необходимые для начала работы.

Как вы развертываете на своих серверах SFTP? Можете ли вы придумать некоторые продвинутые способы развертывания? Кто они такие? Дайте нам знать об этом в комментариях!