Привет, коллеги! ?
Это статья - вторая часть небольшого сериала о деплое web-приложений.
Вот ссылка на первую часть - деплой проекта на Laravel на shared-хостинге с использованием GitHub. Вкратце содержание:
Содержание статьи
- создание приватного репозитория на GitHub и его "связь" с локальным репозиторием
- пуш проекта на GitHub
- клонирование репозитория с GitHub на shared-хостинг
- настройка символических ссылок (необходимо для Laravel приложений)
- настройка Composer
- работа с базой данных
- настройка .env, выполнение миграций, компиляция ассетов и рестарт очередей
Если в прошлой статье мы "ютились" в отдельном каталоге на shared-хостинге, то в этой части статьи мы будем работать на выделенном сервере (физическом или виртуальном).
Что же такое VPS? VPS (англ. virtual private server) - выделенный виртуальный сервер. Простыми словами это просто удаленный компьютер, который вам временно предоставили. Технически, каждый VPS представляет собой отдельно запущенную виртуальную машину на физическом сервере, но с точки зрения конечного пользователя, такой сервер ничем не отличается по своему функционалу и управлению от выделенного сервера.
На старте у нас будет неподготовленный сервер, и мы с нуля "накатим" операционную систему и необходимые инструменты для того, чтобы наше Laravel-приложение работало. Это называется настроить окружение.
В этой статье установим и настроим:
Nginx. Бесплатный и мощный веб-сервер с открытым исходным кодом. Nginx - это приложение, которое может принимать входящие запросы от пользователей (обычно через веб-браузер) и отвечать на них, отправляя запрошенные веб-страницы или другие данные.
Система управления базами данных. Будем использовать MySQL.
Для работы Laravel нам нужен PHP (PHP-FPM).
Далее поставим Composer.
Чтобы корректно работала frontend часть нам понадобится Node/npm.
Ну и Git.
Про Nginx, CGI и PHP-FPM
Nginx сам по себе не умеет обрабатывать PHP, и если вы направите его на index.php
, то в респонсе получите содержимое скрипта. Nginx может обслуживать статические файлы, такие как HTML, CSS и JavaScript, а для обработки PHP-скриптов ему нужна помощь.
CGI (Common Gateway Interface) - один из первых сценариев обработки php-скриптов сервером. В этом режиме каждый php-запрос выполняется отдельным процессом. Производительность сайта невысокая, так как на обработку скриптов требуется много ресурсов. Сейчас он используется редко и считается устаревшим.
Развитием CGI стал FastCGI. Была учтена медленная скорость CGI и применили циклическую обработку нескольких запросов одним процессом. FastCGI — экономит ресурсы сервера за счет сокращения количества запущенных процессов.
PHP-FPM (FastCGI Process Manager), "Менеджер процессов FastCGI". Это уже не протокол или интерфейс, а исполняемая программа, Linux пакет. Это компонент, который реализует протокол FastCGI и соединяет Nginx с нашим Laravel приложением.
По сути, PHP-FPM это балансировщик нагрузки, распределяющий работу между множеством интрефейсов (FastCGI).
Что у нас есть на старте
Кроме непреодолимого желания, у нас есть выделенный сервер и доступы к нему:
ip-адрес
логин (в моём случае
root
)пароль
Проект для разворачивания как и в предыдущей статье - демо админ-панели для проектов на Laravel - MoonShine.
Git репозитории: локальный и удаленный (приватный) на GitHub уже настроены и связаны (как это делали).
Установка операционной системы
Смотрим, есть ли операционная система на сервере. В моём случае это Ubuntu 20.04.
У моего провайдера есть возможность выбрать операционную систему через панель управления, возможно у вашего провайдера придется ставить операционную систему самостоятельно или брать дополнительную услугу.
Можно приступать! Копируем папку с проектом на сервер (шутка).
Открываем терминал и подключаемся к серверу. Вводим:
ssh имя_пользователя@ваш_ip_адрес
Вводим пароль. Видим, что приглашение для ввода поменялось - мы авторизованы.
![](https://habrastorage.org/getpro/habr/upload_files/201/d3e/a48/201d3ea48dc409655840c5219e0662de.jpg)
Создаём отдельного пользователя под проект
Хорошей практикой с точки зрения безопасности и управления доступом будет создание отдельного пользователя для каждого проекта что обеспечит изоляцию проектов на одном сервере.
Создадим пользователя localadmin
и настроим ему директорию:
useradd -G root -u 1000 -d /home/localadmin -m -k /etc/skel localadmin
Установим пароль для пользователя localadmin
:
passwd localadmin
Создадим для пользователя директорию .ssh
и файл authorized_keys
:
mkdir -p /home/localadmin/.ssh
touch /home/localadmin/.ssh/authorized_keys
Настроим владельца директорий и файлов (папку с проектом создадим позднее, тогда и установим права на неё):
chown -R localadmin:localadmin /home/localadmin
Настроим права доступа:
chmod 700 /home/localadmin/.ssh
chmod 644 /home/localadmin/.ssh/authorized_keys
Чтобы Linux не запрашивал каждый раз пароль при выполнении команд от имени суперпользователя (sudo
), выполним команду:
echo "localadmin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/localadmin
Входим в систему под созданным пользователем:
su - localadmin
Настройка подключения по SSH
Более удобно в дальнейшем подключаться к серверу по SSH:
1. Создадим SSH ключи на локальной машине:
выполните команду
ssh-keygen
в терминалеследуйте инструкциям для создания новой пары ключей (публичного и приватного)
по умолчанию ключи будут сохранены в директории:
Windows - С://Users/username/.ssh/id_rsa (или другой диск, на котором установлена Windows)
Linux - /home/username/.ssh/id_rsa
MacOS - /Users/username/.ssh/id_rsa
![](https://habrastorage.org/getpro/habr/upload_files/58b/fe2/a17/58bfe2a17a7778116e3118ba8c4d4352.png)
2. Добавим публичный ключ (*.pub
) на сервер:
отобразите содержимое публичного ключа на локальном рабочем месте:
cat ~/.ssh/id_rsa.pub
скопируйте содержимое публичного ключа
на сервере откройте файл
~/.ssh/authorized_keys
с помощью текстового редакторавставьте скопированный публичный ключ в конец файла
authorized_keys
. Убедитесь, что каждый ключ находится на новой строке.
Также можно отключить вход на сервер по паролю и разрешить только аутентификацию через SSH. Для этого нужно отредактировать файл конфигурации SSH на сервере:
sudo nano /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no
Продолжаем. На старте у нас чистая система и нужно все установить и настроить окружение с нуля.
Обновим все пакеты в системе. Нужно держать в актуальном состоянии компоненты операционной системы, чтобы её работа была безопасной и стабильной. Сначала обновляем список доступных пакетов:
sudo apt update
![](https://habrastorage.org/getpro/habr/upload_files/8d2/f85/211/8d2f85211f0cc0693c4f4da78d8ab019.jpg)
Затем можно обновить до последней версии все пакеты в системе:
sudo apt full-upgrade
![](https://habrastorage.org/getpro/habr/upload_files/369/58c/800/36958c800bb63704f3d557d1d9b378cb.png)
Nginx
Теперь можно переходить к установке веб-сервера Nginx:
sudo apt install nginx
![](https://habrastorage.org/getpro/habr/upload_files/e7e/d07/901/e7ed07901fb86e4be99a23ef9d685a4a.png)
Проверим, правильно ли установлен Nginx - перейдём в браузере на ip адрес сервера:
![](https://habrastorage.org/getpro/habr/upload_files/059/6c7/5d3/0596c75d37be9c2153c4d586800fe489.png)
Отлично, появилась стандартная страница Nginx. Чуть позднее разберемся как это работает.
Устанавливаем MySQL
Выполняем команду:
sudo apt install mysql-server
![](https://habrastorage.org/getpro/habr/upload_files/eb5/000/f32/eb5000f3295a272f393f5f53cb7b5037.png)
Видим, что MySQL 8 версии установлен.
MySQL поставляется с скриптом mysql_secure_installation
, который помогает установить некоторые настройки безопасности по умолчанию: установку пароля root, удаление анонимных пользователей, удаление тестовой базы данных и т.д.:
sudo mysql_secure_installation
Запускается диалог, в котором быстро настраивается СУБД:
Validate password component. Можно его не настраивать, но помним что пароль должен быть надёжным - длинный, буквы в разном регистре и т.д.
Remove anonymous users? Удаляем.
Disallow root login remotely? Соглашаемся - запрещаем удаленный вход в систему MySQL от имени пользователя root. Это является хорошей практикой безопасности. Пользователь root в MySQL обладает максимальными привилегиями и может выполнять любые операции с базой данных. Если злоумышленник получит доступ к учетной записи root, он может с нашей базой делать всё что захочет.
Remove test database and access to it? Удаляем тестовую базу данных.
Reload privilege tables now? Перезагружаем чтобы изменения применились
![](https://habrastorage.org/getpro/habr/upload_files/68a/a90/bae/68aa90bae5ef13048d4e8a863f0ea36d.png)
Создадим нового пользователя для базы данных проекта. В целях безопасности всегда нужно создавать отдельного пользователя для базы данных каждого проекта. Заходим в MySQL под root
:
sudo mysql -u root -p
и вводим пароль текущего пользователя системы. Вошли, проверяем, что приглашение изменилось на mysql>
.
![](https://habrastorage.org/getpro/habr/upload_files/b15/98a/efe/b1598aefe030e3a975d88eb47ae3f910.jpg)
Создаём пользователя:
CREATE USER 'имя_пользователя'@'localhost' IDENTIFIED WITH mysql_native_password BY 'пароль';
имя_пользователя
ипароль
устанавливаем свои!
Проверим, создан ли пользователь:
SELECT host, user FROM mysql.user\G;
![](https://habrastorage.org/getpro/habr/upload_files/4ce/2e4/a9c/4ce2e4a9cff6a9545f04ccf079e2ca79.png)
Теперь создаем базу данных для проекта:
CREATE DATABASE имя_базы;
![](https://habrastorage.org/getpro/habr/upload_files/7dd/ade/0ef/7ddade0ef8336b06a7e92c6f815920bb.jpg)
И даём пользователю доступ к базе:
GRANT ALL PRIVILEGES ON имя_базы.* TO 'имя_пользователя'@'localhost';
![](https://habrastorage.org/getpro/habr/upload_files/d96/011/33f/d9601133f5c6f90536113850e3e4a4ad.jpg)
Заканчивая работу по настройке MySQL, необходимо перезагрузить привилегии, чтобы все сделанные изменения вступили в силу. Не забывайте каждый раз перезагружать привилегии после внесения изменений:
FLUSH PRIVILEGES;
![](https://habrastorage.org/getpro/habr/upload_files/c66/5e4/8d1/c665e48d19df7b90dbdabcf44c1085e4.jpg)
База данных подготовлена.
В целях безопасности базы данных можно выполнить еще несколько настроек.
Дополнительные настройки безопасности:
Отключение удалённого подключения. В файле конфигурации MySQL (обычно my.cnf или my.ini) можно указать параметр bind-address и установить его значение на localhost или 127.0.0.1. Это ограничит доступ к MySQL только с локального сервера, и удаленное подключение будет невозможно.
Использование брандмауэра. Настройте брандмауэр на сервере, где установлен MySQL, чтобы блокировать входящие соединения на порт MySQL (обычно 3306) с удаленных IP-адресов.
Переходим к PHP-FPM.
Установка и настройка PHP-FPM
PHP-FPM ставим чтобы наш веб-сервер мог обрабатывать большое количество запросов одновременно.
Приложение, которое мы будем разворачивать, работает на Laravel 11 - нам понадобиться PHP 8.3 (самая свежая версия PHP на момент публикации статьи, или другую версию, в зависимости от вашего проекта):
sudo apt install php8.3-fpm
![](https://habrastorage.org/getpro/habr/upload_files/df0/ded/c6e/df0dedc6eff16e0239f6f7b0b1d1acc6.png)
Проверьте установленную версию PHP:
php -v
В ответ вы должны увидеть информацию о версии PHP
![](https://habrastorage.org/getpro/habr/upload_files/8fd/92d/bab/8fd92dbab59c4353dc8767cc8d0c398b.jpg)
И статус службы PHP-FPM:
sudo service php8.3-fpm status
![](https://habrastorage.org/getpro/habr/upload_files/6ab/b46/8c7/6abb468c7deba47bac0e4ed7b5c2ffb7.png)
Служба должна быть активной (запущенной)
Установка Git
Переходим к Git:
sudo apt install git
![](https://habrastorage.org/getpro/habr/upload_files/7b9/a09/702/7b9a09702ebc0edf9aeb88c94adaaf7a.jpg)
Проверяем:
git –version
![](https://habrastorage.org/getpro/habr/upload_files/0f2/b9f/b25/0f2b9fb25a86592cbc271856daa2bb3c.jpg)
Видим версию git.
C git всё достаточно легко, не так ли?
Установка Composer
Выполняем команду для загрузки установочного скрипта Composer:
curl -sS https://getcomposer.org/installer -o composer-setup.php
![](https://habrastorage.org/getpro/habr/upload_files/acd/a40/f92/acda40f928f97bd9212c411ab7dde833.jpg)
Проверяем что установщик не поврежден и не модифицирован всякими безобразниками:
HASH=$(curl -sS https://composer.github.io/installer.sig)
php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
![](https://habrastorage.org/getpro/habr/upload_files/3f4/2fc/6d2/3f42fc6d249e660d307a2f8ac30ede88.jpg)
Если всё ок и хэш совпал с эталонным, то появится сообщение - Installer verified
, значит, установочный файл можно использовать. Устанавливаем Composer:
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
![](https://habrastorage.org/getpro/habr/upload_files/ece/36a/db1/ece36adb157bca7fe43768e9795fd723.jpg)
Проверим:
composer --version
![](https://habrastorage.org/getpro/habr/upload_files/2f7/490/b75/2f7490b75d7bd3c0e56cf66a7c832760.jpg)
Удаляем файл composer-setup.php
:
php -r "unlink('composer-setup.php');"
Устанавливаем Node.js и npm
Выполняем:
curl -sL https://deb.nodesource.com/setup_current.x | sudo -E bash -
![](https://habrastorage.org/getpro/habr/upload_files/573/cdc/930/573cdc930779414f20bad46ab5239d08.png)
sudo apt install -y nodejs
![](https://habrastorage.org/getpro/habr/upload_files/b9f/4a2/2bb/b9f4a22bbfe853043e4c6a723bec1c89.png)
Проверяем:
node -v
npm -v
![](https://habrastorage.org/getpro/habr/upload_files/2c4/3c5/4dc/2c43c54dcf0a7ed05d27a3136e1affdf.jpg)
Ставим расширения для PHP
Для каждого проекта ставится свой набор расширений для PHP.
Вот самые популярные:
php-mysql
— позволяет PHP взаимодействовать с базами данных MySQL. Предоставляет функции и классы для подключения к MySQL, выполнения запросов и обработки результатов.
php-curl
— обеспечивает интеграцию с библиотекой cURL. cURL (Client URL) — это инструмент для работы с URL-адресами, который позволяет выполнять HTTP-запросы, обращаться к веб-серверам, загружать файлы и многое другое. Модуль php-curl позволяет PHP-скриптам использовать функциональность cURL для взаимодействия с внешними ресурсами, такими как API, веб-сервисы и другие серверы.
php-dom
— позволяет взаимодействовать с XML-документами через DOM API. Оно предоставляет функции и классы для работы с иерархической структурой дерева узлов.
php-zip
— позволяет читать/записывать сжатые ZIP-архивы и файлы внутри них.
php-intl
— предоставляет поддержку интернационализации (i18n) и локализации (l10n). Это расширение включает в себя библиотеку ICU (International Components for Unicode), которая обеспечивает мощные инструменты для работы с различными языками, региональными настройками и кодировками.
php-mbstring
— предоставляет поддержку многобайтовых строк (multibyte strings). Многобайтовые строки используются для представления символов, которые не могут быть закодированы в одном байте, таких как символы азбуки Морзе, китайские иероглифы, японские каны и многие другие.
php-soap
— обеспечивает поддержку для работы с SOAP (Simple Object Access Protocol). SOAP — это протокол для обмена структурированными информационными сообщениями в распределенной среде, использующий XML в качестве формата сообщений.
php-bcmath
— для произведения арифметических операций с произвольной точностью. Laravel использует эту библиотеку для генерации и проверки CSRF-токенов, а также для работы с денежными и другими числовыми значениями.
php-cli
— предоставляет возможность запускать PHP скрипты из командной строки. В контексте Laravel, может использоваться для выполнения команд Laravel Artisan.
php-common
— является одним из основных пакетов расширений PHP, который включает в себя общие и основные функции и библиотеки, необходимые для работы с PHP.
php-fpm
— альтернативный способ запуска PHP скриптов на веб-сервере, является отдельным процессом, который управляет выполнением PHP скриптов и обеспечивает более эффективное управление процессами PHP на сервере.
php-gd
— (Graphics Draw) для работы с изображениями. Позволяет создавать, редактировать и обрабатывать изображения в различных форматах, таких как JPEG, PNG, GIF и другие.
php-opcache
— для улучшения производительности PHP приложений путем кэширования скомпилированного PHP кода в памяти сервера. Это позволяет уменьшить время выполнения PHP скриптов, так как PHP код не нужно компилировать заново при каждом запросе.
php-readline
— делает работу с командной строкой более удобной и эффективной (автодополнение и история команд, перемещение курсора и т.д.)
php-xml
— для работы с XML (Extensible Markup Language) - создание XML документов, их парсинг, преобразование в другие форматы данных и т.д.
Я установил следующие:
sudo apt install php-mysql php-curl php-dom php-zip php-intl php-mbstring php-soap php-opcache
В вашем случае список модулей может отличаться. Если вы не уверены, какие модули уже установлены, выполнить команду php -m
.
Расширения для PHP будут установлены для той версии, которая используется на вашем сервере
Каталог проекта и настройка прав доступа
Давайте создадим директорию для проекта который будем деплоить:
sudo mkdir /var/www/moonshinedemo
![](https://habrastorage.org/getpro/habr/upload_files/075/470/d0e/075470d0ef223ed456eec7b52f4b4655.jpg)
Для того чтобы веб-сервер Nginx мог корректно работать с файлами и директориями нашего проекта на Laravel, он должен иметь правильные права доступа, чтобы обеспечить как безопасность, так и работоспособность приложения. При установке Nginx создаётся пользователь www-data
или nginx
(проверить можно в файле с конфигурацией /etc/nginx/nginx.conf
, директива user
). В моём случае пользователь Nginx - www-data
.
Общий подход настройки прав доступа для директории проекта заключается в том, чтобы установить владельца (пользователя и группу localadmin
) для полного контроля и дать права Nginx на чтение.
Делаем localadmin
владельцем директории проекта:
sudo chown -R localadmin:localadmin /var/www/moonshinedemo
Теперь настроим для Nginx. Владельца оставляем localadmin
, а группу установим www-data
:
sudo chown -R localadmin:www-data /var/www/moonshinedemo
Установим права на директорию проекта:
для директорий: 755 (чтение и выполнение для всех, запись для владельца)
для файлов: 644 (чтение и запись для владельца, чтение для остальных)
sudo find /var/www/moonshinedemo -type d -exec chmod 755 {} +
sudo find /var/www/moonshinedemo -type f -exec chmod 644 {} +
Наконец, отдельно для директорий storage и bootstrap/cache устанавливаем права доступа:
для директорий: 775 (чтение и выполнение для всех, запись для членов группы владельца)
для файлов: 664 (чтение и запись для членов группы владельца, чтение для остальных)
sudo find /var/www/moonshinedemo/storage -type d -exec chmod 775 {} +
sudo find /var/www/moonshinedemo/bootstrap/cache -type d -exec chmod 775 {} +
sudo find /var/www/moonshinedemo/storage -type f -exec chmod 664 {} +
sudo find /var/www/moonshinedemo/bootstrap/cache -type f -exec chmod 664 {} +
Теперь у Nginx есть право записывать данные в эти директории, что необходимо для кэширования и логирования.
Настройка Nginx
Если вы не знаете как работает Nginx, то предлагаю краткий экскурс.
Nginx сейчас выводит свою дефолтную страницу, давайте научимся влиять на поведение Nginx!
Nginx у нас "живет" в каталоге ../etc/nginx
:
sudo nano /etc/nginx/sites-available/default
Его конфиг по умолчанию находится в /sites-available
. Объясню отдельные строки конфига:
listen 80 default_server # web-сервер работает на 80 порту сервера
root /var/www/html # директория проекта
index index.html index.htm index.nginx-debian.html # варианты названий файлов-стартовых точек из директории проекта
![](https://habrastorage.org/getpro/habr/upload_files/a87/1c6/232/a871c6232d9affaab79e7dcdb47b9f84.png)
Создадим в каталоге проекта /var/www/moonshinedemo
файл для тестирования - index.php
:
touch /var/www/moonshinedemo/index.php
![](https://habrastorage.org/getpro/habr/upload_files/30d/658/996/30d6589965287ce9a6727ae1b334d6e8.jpg)
Теперь откроем этот файл с помощью редактора nano:
nano /var/www/moonshinedemo/index.php
Давайте что-нибудь оригинальное тут изобразим. Пусть будет
<?php
echo "Hello, поклонники Laravel!"";
?>
![](https://habrastorage.org/getpro/habr/upload_files/e5d/66f/008/e5d66f0087cd8f35b472fb26c1f88b08.jpg)
Жмем ctrl+s
(сохраняет файл) и ctrl+x
(закрыть редактор nano).
Теперь надо указать Nginx чтобы он искал проект в папке moonshinedemo
. Внесем изменения в конфиг:
sudo nano /etc/nginx/sites-available/default
Редактируем следующие строки:
root /var/www/moonshinedemo
index index.php
"Учим" Nginx как работать с php файлами. Раскомментируем строки:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}
![](https://habrastorage.org/getpro/habr/upload_files/dc9/d50/95d/dc9d5095d0c50994a0b181a96913bf56.png)
Чтобы изменения в конфигурацию применились, надо Nginx перезапустить:
sudo systemctl reload nginx
И проверяем работу, вводим ip-адрес:
![](https://habrastorage.org/getpro/habr/upload_files/ca5/1be/0f3/ca51be0f32b4f3363848940173c48781.jpg)
Всё работает, файл index.php
в /var/www/moonshinedemo
можно удалить.
rm /var/www/moonshinedemo/index.php
Клонируем проект из GitHub
Напоминаю, что мы работаем с приватным проектом, который настраивали в прошлой статье, для работы с ним нужно сгенерировать SSH-ключи на сервере и на локальном компьютере и указать публичные ключи в настройках GitHub репозитория. Если не знаете, как это делать, посмотрите в первой части статьи.
Переходим в каталог /var/www/
и клонируем проект из GitHub репозитория в каталог moonshinedemo
:
cd /var/www/moonshinedemo
![](https://habrastorage.org/getpro/habr/upload_files/aca/3bf/e12/aca3bfe12acccfafbe05720300f5cad3.jpg)
git clone git@github.com:CutCodes/CutCodeDeploy.git .
Проверим:
ls -la
![](https://habrastorage.org/getpro/habr/upload_files/088/29a/4cc/08829a4cc3b47bdd0fd2344998fcf953.jpg)
Всё ок, мы склонировали проект на сервер.
Остальные телодвижения
Обновляем зависимости:
composer install
![](https://habrastorage.org/getpro/habr/upload_files/835/949/f19/835949f19f9e81651d640579891aa18f.png)
Создаём .env из шаблона:
cp .env.example .env
Генерируем APP_KEY
, вносим настройки для работы с базой данных, переводим в прод, указываем APP_URL
, (смотрим как это делать в первой статье). После запускаем миграции:
php artisan migrate
![](https://habrastorage.org/getpro/habr/upload_files/aa6/5a6/d83/aa65a6d8391856569716267d0bee39e8.png)
Пересобираем ассеты:
npm install
npm run build
Создаем символическую ссылку для папки хранилища в публичной директории вашего проекта Laravel. Это позволяет обращаться к файлам, хранящимся в хранилище, через URL-адреса:
php artisan storage:link
![](https://habrastorage.org/getpro/habr/upload_files/bbc/f3f/da3/bbcf3fda3292669a9c0adaba96a3aeb2.png)
После того, как символическая ссылка создана, она не требует обновления при каждом деплое. Заново создать символическую ссылку нужно только если произошли изменения в структуре файлов или директорий, связанных с хранением файлов (например, изменение пути к директории
storage
).
В настройках Nginx указываем параметры из документации Laravel (Тейлор всё протестировал). Не забудьте поменять путь к проекту (root
):
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/moonshinedemo/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Инструкция
location /
с директивойtry_files $uri $uri/ /index.php?query_string;
в конфигурации Nginx для приложения на Laravel используется для обработки маршрутов и перенаправления всех запросов наindex.php
, где происходит дальнейшая обработка маршрутов приложения Laravel.Эта конфигурация позволяет обеспечить правильную маршрутизацию запросов в приложении Laravel, так как все запросы будут направлены на точку входа -
index.php
, где фреймворк Laravel может обработать их и вернуть соответствующий ответ.
Перезагружаем Nginx:
sudo systemctl reload nginx
Готово. Можно проверять!
![](https://habrastorage.org/getpro/habr/upload_files/1ea/32d/809/1ea32d809969059f8084dec0e4dba81e.png)
Дополнительные работы по Supervisor и Cron
Для продвинутых пользователей добавил информацию по установке и настройке Supervisor и Cron на ваш сервер. Полезные инструменты!
Supervisor
Зачем нам нужен Supervisor?
Очереди - неотъемлемая часть любого Laravel приложения. Не будем затрагивать тему как они работают, все это есть в документации. А Supervisor я добавил в статью при деплой потому, что если мы без него будем использовать queue:work
(обработчик очередей, который обрабатывает задачи, помещенные в очередь), то при перезапуске или сбое приложения обработчик перестанет работать! Тут нам и поможет Supervisor, это менеджер процессов, который работает в фоновом режиме (демон) и управляет другими процессами, такими как queue:work
. Supervisor который контролирует рабочие процессы и их количество, а также перезапустит процессы в случае сбоя.
Давайте установим Supervisor:
sudo apt install supervisor
Для настройки Supervisor необходимо создать конфигурационный файл для каждого процесса, которым вы хотите управлять. Перейдем в директорию Supervisor (обычно это /etc/supervisor/conf.d/
) и создадим конфигурационный файл для обработчика очередей Laravel - laravel-worker.conf
:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /путь-к-вашему-проекту/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/путь/к/лог-файлу/worker.log
Обновите Supervisor, чтобы он прочитал новый конфигурационный файл:
sudo supervisorctl reread
sudo supervisorctl update
Запустите обработчика очередей с помощью Supervisor:
sudo supervisorctl start laravel-worker
Теперь Supervisor будет управлять процессом обработки очередей Laravel и обеспечивать его непрерывную работу.
Сron
Cron - это стандартный инструмент в операционных системах Unix, который позволяет запускать задачи по расписанию. Эти задачи могут выполняться автоматически в определенное время или с определенной периодичностью.
В Laravel есть мощный функционал для планирования задач по расписанию, который называется scheduler. Также не буду перегружать статью про то как он работает, всё хорошо описано в документации.
Мы же с помощью Cron настроим чтобы каждую минуту выполнялась консольная команда Laravel schedule:run
, которая под капотом будет искать задачи, которые нужно выполнить прямо сейчас. Создаётся команда так:
php artisan make:command ResetCommand
При этом создается файл команды - app/Console/Commands/ResetCommand.php
Давайте разберем пример. На демо-проекте админки MoonShine - работает команда, которая ресетит базу данных и чистит пользовательские файлы чтобы они не копились. Демо проект размещен чтобы любой желающий мог попробовать MoonShine в деле и в том числе добавить свои пользовательские данные (создать статьи, добавить изображения и т.д.). Чтобы база данных не разрасталась, сделана команда по очистке:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
class ResetCommand extends Command
{
protected $signature = 'app:reset-console';
public function handle(): int //откатываем все миграции и наполяем БД исходными данными
{
$this->call('migrate:fresh', [
'--force' => true,
'--seed' => true
]);
File::cleanDirectory(storage_path('app/public')); //очищаем временные файлы
return self::SUCCESS; //возвращаем что команда выполнена
}
}
Чтобы команда выполнялась её нужно добавить в файле routes/console.php с указанием периодичности выполнения. Приготовлены такие функции, как ->daily()
, ->hourly()
, ->everyFifteenMinutes()
и т. д.:
<?php
use Illuminate\Support\Facades\Schedule;
Schedule::command('ResetCommand:cron')->everyFifteenMinutes();
Переходим на сервер. На Ubuntu 20.04 Сron обычно уже предустановлен по умолчанию. Вы можете проверить, установлен ли cron, с помощью следующих команд:
sudo dpkg -l | grep cron
Если Cron не установлен выполняем команду:
sudo apt install cron
После установки Cron будет автоматически запущен. Проверяем его статус с помощью команды:
sudo systemctl status cron
Настроим автозапуск Crone при загрузке системы:
sudo systemctl enable cron
Добавляем планировщика задач Laravel в Cron. Выполните команду crontab -e
, которая откроет файл редактирования текущих задач:
* * * * * cd /путь_к_вашему_проекту & php artisan schedule:run >> /dev/null 2>&1
Готово. Теперь Cron будет следить что планировщик задач Laravel (scheduler) запускается каждую минуту. А планировщик, в свою очередь, запускает команду для очистки базы данных каждые 15 минут.
Выводы
Деплой на VPS сервер выполнен! Этот процесс не сложнее деплоя на shared-хостинг, если делать всё пошагово, то проблем обычно не возникает. В среднем процесс создания окружения занимает минут 40-50. Сам в работе использую только VPS серверы, разной конфигурации, в зависимости от решаемых задач.
Для вашего комфорта подготовил шпаргалку с командами по настройке окружения, чтобы ничего не забыть, и не листать статью в поисках нужной строчки.
Настройка окружения на сервере
#Обновляем все пакеты в системе
sudo apt update
sudo apt full-upgrade
#Nginx
sudo apt install nginx
#MySQL
sudo apt install mysql-server
sudo mysql_secure_installation
sudo mysql -u root –p
CREATE USER 'имя_пользователя'@'localhost' IDENTIFIED WITH mysql_native_password BY 'пароль';
SELECT host, user FROM mysql.user\G;
CREATE DATABASE имя_базы;
GRANT ALL
PRIVILEGES ON имя_базы.* TO 'имя_пользователя'@'localhost';
FLUSH PRIVILEGES;
#PHP FPM
sudo add-apt-repository ppa:ondrej/php
sudo apt install php8.3-fpm
#Git
sudo apt install git
#Composer
curl -sS https://getcomposer.org/installer -o composer-setup.php
php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
php -r "unlink('composer-setup.php');"
#Node.js и npm
curl -sL https://deb.nodesource.com/setup_current.x | sudo -E bash -
sudo apt install -y nodejs
#Расширения для PHP
sudo apt install php-mysql php-curl php-dom php-zip php-intl php-mbstring php-soap php-opcache
-----------
#Настройка Nginx
Редактируем настройки
sudo nano /etc/nginx/sites-available/default
#Настройки Nginx для Laravel
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/директория/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_hide_header X-Powered-By;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
#Перезагрузка Nginx
sudo systemctl reload nginx
-----------
#Создаём директорию для проекта
sudo mkdir /var/www/директория
#Устанавливаем на директорию текущему пользователю и Nginx
sudo chown -R имя_пользователя:имя_пользователя /var/www/moonshinedemo
sudo chown -R имя_пользователя:www-data /var/www/moonshinedemo
sudo find /var/www/директория -type d -exec chmod 755 {} +
sudo find /var/www/директория -type f -exec chmod 644 {} +
sudo find /var/www/директория/storage -type d -exec chmod 775 {} +
sudo find /var/www/директория/bootstrap/cache -type d -exec chmod 775 {} +
sudo find /var/www/директория/storage -type f -exec chmod 664 {} +
sudo find /var/www/директория/bootstrap/cache -type f -exec chmod 664 {} +
-----------
#Деплой приложения
#Копируем проект:
git clone git@github.com:ссылка_на_проект.git .
#Обновляем зависимости:
composer install
#Создаём .env из шаблона:
cp .env.example .env
#Генерируем APP_KEY:
php artisan key:generate
#Вносим информацию в файл .env (база данных, прод, APP_URL)
#Запускаем миграции:
php artisan migrate
#Пересобираем ассеты:
npm install
npm run build
Что дальше?
Варианты деплоя на самые популярные виды хостинга мы рассмотрели. В следующей статье будем разбираться, как можно (и нужно) автоматизировать деплой. Подписывайтесь на мой блог, чтобы не пропустить!
К первой части статьи было достаточно много комментариев, в том числе по дополнению статьи, так что жду активную обратную связь и в этот раз.
Данил Щуцкий, автор проекта CutCode.