Дата публикации: 19.02.2024 в 10:55

Как установить Nginx, MySQL (MariaDB) и/или PostgreSQL, Redis и несколько версий PHP (+ XDebug) на MacOS. БОНУС: Удобный GUI для управления

Alexey BubnovAlexey Bubnov
0 комментария

Рекомендую тем, у кого MacOS и не очень много ресурсов чтобы запускать несколько контейнеров Docker Compose для каждого сайта или кто хочет запустить сразу несколько сайтов (каждый nginx контейнер будет пытаться слушать 80/443 порт и у вас не получится иметь несколько проектов запущенными одновременно).

Кто не хочет читать и хоть немного разбираться, может просто воспользоваться Sail, Herd, Valet, DBngin.

Статья навеяна Install Nginx & Multiple PHP Versions on macOS 13 Ventura с моими дополнениями.

Я буду рассматривать установку на Apple silicon чипы, в оригинале статьи есть примеры установки на старые Mac (x86/64).

  1. Xcode & Homebrew & openSSL & wget
  2. MySQL (MariaDB)
  3. PostgreSQL
  4. Несколько версий PHP
  5. Xdebug
  6. Nginx
  7. Dnsmasq
  8. Mailpit
  9. Redis
  10. meilisearch
  11. Бонус (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:

Теперь, когда нам не нужны сервисы для разработки, мы просто останавливаем их. И память, и процессор освобождаются полностью!

brew services stop --all

Ура, все работает!


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

ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай
ОбщайсяРазвивайсяУчисьРаботай