Рекомендую тем, у кого MacOS и не очень много ресурсов чтобы запускать несколько контейнеров Docker Compose для каждого сайта или кто хочет запустить сразу несколько сайтов (каждый nginx контейнер будет пытаться слушать 80/443 порт и у вас не получится иметь несколько проектов запущенными одновременно).
Кто не хочет читать и хоть немного разбираться, может просто воспользоваться Sail, Herd, Valet, DBngin.
Статья навеяна Install Nginx & Multiple PHP Versions on macOS 13 Ventura с моими дополнениями.
Я буду рассматривать установку на Apple silicon чипы, в оригинале статьи есть примеры установки на старые Mac (x86/64).
- Xcode & Homebrew & openSSL & wget
- MySQL (MariaDB)
- PostgreSQL
- Несколько версий PHP
- Xdebug
- Nginx
- Dnsmasq
- Mailpit
- Redis
- meilisearch
- Бонус (GUI)
Xcode & Homebrew & openSSL & wget
Перед запуском вам необходимо установить несколько системных инструментов, без которых дальнейшая установка невозможна.
Xcode
xcode-select install
Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
Соглашаемся на все что предлагает Homebrew.
OpenSSL
brew install openssl
Wget
brew install wget
Также рекомендую установить пару утилит:
Продвинутый htop
brew install htop
Консольный файловый менеджер Midnight Commander
brew install mc
MySQL (MariaDB)
Я буду ставить MariaDB, в оригинальной статье ставится MySQL и вы можете брать команды оттуда.
Кстати, для MySQL был установщик для MacOS когда вы управляли сервером прямо из системных настроек, но я больше не нашел его на сайте https://www.mysql.com/downloads/.
brew install mariadb
brew services start mariadb
Проверить что MariaDB успешно работает можно командой:
sudo mysql -u root
Далее, вы можете внести необходимые настройки в /opt/homebrew/etc/my.cnf. Я рекомендую добавить настройки ограничения доступа:
[mysqld] bind-address = 127.0.0.1 mysqlx-bind-address = 127.0.0.1
Желательно полностью удалить предыдущие настройки MySQL/MariaDB, иначе могут быть проблемы!
Теперь защищаем наш сервер баз данных паролем и внесем некоторые настройки безопасности:
mariadb-secure-installation
brew services restart mysql
PostgreSQL
Для многих проектов я использую PostgreSQL, по этому ставлю и её:
brew install postgresql
brew services restart postgresql
И проверим установку:
psql postgres
postgres=# \du
Несколько версий PHP
Добавляем внешний репозиторий с последними версиями PHP:
brew tap shivammathur/php
И ставим нужные нам версии PHP:
8.3 для новых проектов, 8.2 для старых, иногда мне нужен 7.4 так что ставлю и его
brew install shivammathur/php/php@7.4
brew install shivammathur/php/php@8.2
brew install shivammathur/php/php@8.3
Делаем основной версией 8.3:
brew unlink php
brew link --overwrite --force php@8.3
(позже мы настроим возможности использовать любые версии php).
Теперь нам необходимо настроить php-fpm чтобы все версии могли работать одновременно и слушать разные порты.
Правим файлы:
Здесь и далее заменяем alex на ваше имя пользователя
/opt/homebrew/etc/php/7.4/php-fpm.d/www.conf
user = alex group = staff listen = 127.0.0.1:9074
/opt/homebrew/etc/php/8.2/php-fpm.d/www.conf
user = alex group = staff listen = 127.0.0.1:9082
/opt/homebrew/etc/php/8.3/php-fpm.d/www.conf
user = alex group = staff listen = 127.0.0.1:9083
Таким образом каждая версия PHP будет слушать свой порт и мы сможем для каждого сайта настроить свою версию в nginx!
Теперь можно запустить наши сервисы php-fpm:
brew services start php@7.4
brew services start php@8.2
brew services start php@8.3
Проверяем что все запущенно и все работает:
sudo lsof -i -n -P|grep php-fpm
Как видим ни один из сервисов не мешает другим и слушает свой порт. Когда появится PHP 8.4 мы просто повесим его на 9084 порт.
Добавим в консоль также алиасы для различных версий php, для того в файле .zshrc добавим следующие строки
alias php74="/opt/homebrew/opt/php@7.4/bin/php" alias php82="/opt/homebrew/opt/php@8.2/bin/php" alias php83="/opt/homebrew/opt/php@8.3/bin/php"
После перезапуска терминала проверяем установку:
php74 -v ; php82 -v ; php83 -v ; php -v
Как видим, по умолчанию используется версия PHP 8.3. Для изменения php по умолчанию просто выполните:
brew unlink php
brew link --overwrite --force php@7.4
Xdebug
Для каждой версии PHP вы можете установить Xdebug (только для 7.4 уже не получится):
brew link --overwrite --force php@8.2
pecl uninstall -r xdebug
pecl install xdebug
brew link --overwrite --force php@8.3
pecl uninstall -r xdebug
pecl install xdebug
В наших файлах конфига появилась настройка XDebug. Давайте немного донастроим:
Не забываем удалить строчку zend_extension="xdebug.so" в начале файла конфига
/opt/homebrew/etc/php/8.2/php-fpm.d/www.conf
[xdebug] zend_extension="xdebug.so" xdebug.mode=debug xdebug.client_port=9002 xdebug.idekey=PHPSTORM
/opt/homebrew/etc/php/8.3/php-fpm.d/www.conf
[xdebug] zend_extension="xdebug.so" xdebug.mode=debug xdebug.client_port=9003 xdebug.idekey=PHPSTORM
Ну и перезапускаем наши php-fpm:
sudo killall php-fpm
Смотрим что у нас получилось на данный момент:
brew services list
Отлично, все сервисы запущены и работают!
Nginx
Ну куда же без Nginx:
brew install nginx
brew services start nginx
Пробуем открыть http://localhost:8080/
Давайте немного донастроим Nginx /opt/homebrew/etc/nginx/nginx.conf
charset utf-8;
Если вы, как и я, любите давать локальным серверам длинные названия, то добавьте следующее в блок http {}:
server_names_hash_bucket_size 512;
Затем сделайте эти обновления внутри блока server {}:
listen 80; server_name localhost; index index.php;
Затем добавьте шлюз FastCGI в php-fpm на сервере по умолчанию. Лучше всего использовать последнюю установленную версию php. Для других серверов вы можете установить версию PHP в соответствии с требованиями проекта.
location ~ \.php$ { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_pass 127.0.0.1:9083; fastcgi_split_path_info ^(.+\.php)(/.+)$; }
Затем добавьте некоторую базовую защиту к вашему серверу по умолчанию:
add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff";
Ну и проверим настройки нашего свежего Nginx:
nginx -t
Должно быть примерно так:
nginx: the configuration file /opt/homebrew/etc/nginx/nginx.conf syntax is ok nginx: configuration file /opt/homebrew/etc/nginx/nginx.conf test is successful
Перезапускаем сервер nginx:
brew services restart nginx
Далее отредактируйте реальный файл index.html, используемый nginx - замените index.html на index.php:
mv /opt/homebrew/var/www/index.html /opt/homebrew/var/www/index.php
И добавим небольшой php код в новый файл /opt/homebrew/var/www/index.php:
< ?php phpinfo(); ? >
Теперь открываем http://localhost/index.php.
Dnsmasq
Чтобы постоянно не искать и не править hosts, мы создадим свой TLD *.localhost (и *.test).
По умолчанию, в новых MacOS, hosts заблокирован от редактирования и надо перезагружаться в специальном режиме чтобы его изменить.
brew install dnsmasq
echo '\naddress=/.test/127.0.0.1' >> /opt/homebrew/etc/dnsmasq.con
echo '\naddress=/.localhost/127.0.0.1' >> /opt/homebrew/etc/dnsmasq.conf
sudo mkdir -v /etc/resolver
sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'
sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/localhost'
Можем запускать сервис:
sudo brew services start dnsmasq
Проверяем наши домены:
ping -c 3 test.test
ping -c 3 test.localhost
Mailpit
Современные веб-приложения немыслимы без отправки почты.
В оригинальной статье предлагается установить MailHog, но он более не поддерживается и не разрабатывается, и я предлагаю переходить на Mailpit.
brew install mailpit
brew services start mailpit
Добавляем Mailpit как сервис SMTP в системный postfix:
/etc/postfix/main.cf
# Mailpit myhostname = localhost relayhost = [0.0.0.0]:1025
И проверим отправку почты:
echo "Test email from Postfix" | mail -s "Test Email" hi@example.com
Можем открыть http://localhost:8025/ и увидеть интерфейс вашего личного почтового сервиса и увидеть одно входящее письмо:
Если в PHP вы используете отправку почты функцией mail(), то необходимо настроить в файле конфига PHP (я приведу пример для PHP 8.3, для других версий настраивается аналогично):
/opt/homebrew/etc/php/8.3/php.ini
sendmail_path = /opt/homebrew/bin/mailpit sendmail
Сохраняем и перезапускаем php:
sudo killall php-fpm
Проверяем отправку почты:
php -r "mail('test@test.ru','Test subject','Test');"
И видим наше сообщение в списке не прочитанных в веб-интерфейсе: http://0.0.0.0:8025.
Redis
Можно использовать Memcached, но мне больше нравится Redis, устанавливается все максимально просто, буквально парой команд:
brew install redis
brew services start redis
Мы закончили настройку всех необходимых сервисов и можем проверить все ли они работают корректно:
brew services list
meilisearch
В своих проектах, в качестве драйвера Laravel Scout, чаще всего, я использую meilisearch, потому что он в разы проще чем ElasticSearch и его функционала вполне достаточно для поиска (Даже MoonShine для поиска по сайту и документации использует Algola, а это аналогичный поисковый движок).
brew install meilisearch
brew services start meilisearch
Никаких настроек для локальной разработки не требуется, сервис уже работает и вы можете открыть веб-интерфейс по адресу http://localhost:7700/.
Для демонстрации работы поиска давайте скачаем фал с данными для поиска https://www.meilisearch.com/movies.json и загрузим его в наш поиск:
cat ~/Downloads/movies.json | gzip | curl -X POST 'http://localhost:7700/indexes/movies/documents?primaryKey=id' --data-binary @- -H 'Content-Type: application/json' -H 'Content-Encoding: gzip'
Теперь, открыв в браузере http://localhost:7700/ и выбрав индекс movies, вы сможете попробовать поиск по базе 30к+ фильмов:
Обратите внимание, что поиск идет с исправлением ошибок и вполне с учетом морфологии!
Русский язык также в списке поддерживаемых!
Бонус
Я люблю всяческие красивые штучки и поэтому предпочитаю не набирать каждый раз brew services start|restart|stop ... каждого отдельного сервиса, я предпочитаю использовать удобные GUI:
- Cakebrew для работы с пакетами.
- И brew-services-menubar для работы с сервисами.
Теперь, когда нам не нужны сервисы для разработки, мы просто останавливаем их. И память, и процессор освобождаются полностью!
brew services stop --all
Ура, все работает!
В данной статье я рассмотрел установку основных компонентов нашего локального сервера разработки, в следующей статье я покажу как установить дополнительный инструментарий!