Search 

Install Nginx and Multiple PHP Version on MacOS

Nam Hoai Nguyen
Nam Hoai Nguyen
Set up Nginx and Multiple PHP versions on MacOS. In the end, you will have a robust, clean, and fast local web development environment on Mac’s Intel or Apple Silicon Chipsets.
Verified it’s working on MacOS Soloma (14.0)

Software needs to install:

  • Xcode, VS Code & Homebrew (required)
  • Multiple PHP Version (Required)
  • Xdebug (Optional - But highly recommend)
  • Nginx & SSL (Required)
  • MySQL (Optional)
  • Mailhog (Optional)

Setup: Xcode, VS Code & Homebrew

Before starting you need a few tools installed to take the stress out of the setup process
You will be using the terminal a lot coming up (I like iTerm2)
1# Install XCode
2xcode-select --install
3
4# Install Homebrew
5/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
6
7# Install VS Code
8brew install --cask visual-studio-code
9
10# Install OpenSSL (If you need configuration https for domain
11brew install openssl
12
13# Install wget
14brew install wget

Setup

Installing multiple PHP Version

Some PHP version needs to be included on the default core tab homebrew. Use tap shivammathur/php
1brew tap shivammathur/php
2
3# Install PHP Version 
4brew install shivammathur/php/[email protected]
5brew install shivammathur/php/[email protected]
6brew install shivammathur/php/[email protected]
All PHP versions are using port 9000. We need to change the port for each PHP version to avoid conflict. Path file is "$(brew --prefix)/etc/<php_version>/php-fpm.d/www.conf"
Example for PHP 7.4:
1# Open www.conf 
2code "$(brew --prefix)/etc/php/7.4/php-fpm.d/www.conf"
1# default
2user = _www
3group = _www
4listen = 127.0.0.1:9000
5
6# change to
7user = <your_username>
8group = staff
9listen = 127.0.0.1:9074
Before starting php-fpm, if you want to make edits to a php.ini file now in this time. For example, you might want to increase upload_max_file_size and post_max_file_size to 10M
1# Backup PHP.ini
2cp "$(brew --prefix)/etc/php/7.4/php.ini" "$(brew --prefix)/etc/php/7.4/php.ini.orig"
3code "$(brew --prefix)/etc/php/7.4/php.ini"
Once you are ready, start up php-fpm for each version
1brew services start [email protected]
2brew services start [email protected]
3brew services start [email protected]
Check that you have the configuration correctly
1sudo lsof -i -n -P|grep php-fpm
Alias multiple PHP Version
1echo "alias php74=\"$(brew --prefix)/opt/[email protected]/bin/php\"" >> ~/.zshrc
2echo "alias php81=\"$(brew --prefix)/opt/[email protected]/bin/php\"" >> ~/.zshrc
3echo "alias php82=\"$(brew --prefix)/opt/[email protected]/bin/php\"" >> ~/.zshrc
Once you reload your bash file, you can access each alias from the Mac Command line.
1php74 -v
2php81 -v
3php82 -v
Switch between multiple PHP Version
1function phpv() {
2    brew unlink php
3    brew link --overwrite --force "php@$1"
4    php -v
5}

Xdebug

1brew link --overwrite --force [email protected] # Switch to PHP 8.2
2pecl install xdebug
P/S: If you want to install xdebug for “PHP” ≥ 8.0. You need to install xdebug version 3.1.6 due to the new version only supports “PHP” ≥ 8.1. You can see it on the xdebug homepage
1pecl install xdebug-3.1.6

Installing Nginx

Installing Nginx
1# Install nginx
2brew install nginx
3# Start nginx
4sudo nginx
5# Test nginx
6curl http://localhost:8080
Change default Nginx configuration
1code "$(brew --prefix)/etc/nginx/nginx.conf"
1# REPLACE #user nobody;
2user <your-username> staff;
3
4# NEXT, ADD THE FOLLOWING TO THE http {} block
5http {
6	...
7	server_names_hash_bucket_size 512;
8}
9
10# UPDATE INSIDE server {} block
11
12server {
13	...
14  listen 80 default_server;
15  server_name _;
16}
17
18# ADD FastCGI gateway to PHP-FPM
19location ~ \.php$ {
20  try_files $uri =404;
21  fastcgi_pass 127.0.0.1:9081; # Using PHP 8.1
22  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
23  include fastcgi_params;
24}
25
26# ADD Some Basic Security Header
27add_header X-Frame-Options "SAMEORIGIN";
28add_header X-XSS-Protection "1; mode=block";
29add_header X-Content-Type-Options "nosniff";
30
31# SET Charset UTF-8
32charset utf-8;
33
34# ALLOW LARGE FILE UPLOAD
35http {
36  ...
37  client_max_body_size 100M;
38}
By Default Nginx root folder is $(brew --prefix)/var/www/
If you want to change the root folder
1server {
2	...
3	root <absolute-path>
4}
Check the PHP code to make sure everything is working. In the root document nginx, create a new file index.php
1<?php echo phpinfo(); ?>
Reload Nginx to apply the new config
1sudo nginx -s reload
Go to http://localhost to see the result
To add more servers you can go to the nginx servers directory: "$(brew --prefix)/etc/nginx/servers"
Using SSL
Installing mkcert
1brew install mkcert
2brew install nss # if you use Firefox
3mkdir "$(brew --prefix)/etc/nginx/ssl"
4cd "$(brew --prefix)/etc/nginx/ssl"
5mkcert -install
6mkcert localhost
Change default configuration Nginx
1code "$(brew --prefix)/etc/nginx/nginx.conf"
1server {
2  http2 on;
3  listen 443 ssl;
4  listen [::]:443 ssl;
5  server_name localhost;
6  ssl_certificate      /opt/homebrew/etc/nginx/ssl/localhost.pem;
7  ssl_certificate_key  /opt/homebrew/etc/nginx/ssl/localhost-key.pem;
8  ssl_ciphers          HIGH:!aNULL:!MD5;
9}
Auto redirect HTTPS
1server {
2  listen 80 default_server;
3  server_name _;
4  return 301 https://$host$request_uri;
5}

MySQL

Installing MySQL
1brew install mysql
2brew services start mysql
3
4# mysql secure installation
5mysql_secure_installation
Configuration MySQL
1code "$(brew --prefix)/etc/my.cnf"
1# Default Homebrew MySQL server config
2[mysqld]
3# Only allow connections from localhost
4bind-address = 127.0.0.1
5mysqlx-bind-address = 127.0.0.1
6
7innodb_buffer_pool_instances=8
8innodb_buffer_pool_size=4G
9innodb_buffer_pool_chunk_size=512M
10max_allowed_packet=1024M
11sort_buffer_size=256M
12max_connections=1024
13default_authentication_plugin=mysql_native_password
14
15innodb_ft_min_token_size=2
16
17# Add mode only if needed
18sql_mode = "ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
19
20# Set Default Charset
21character-set-server=utf8
22collation-server=utf8_general_ci

PHPMyAdmin

1brew install phpmyadmin
Configuration Nginx to allow “PHPMyAdmin”
1location /phpmyadmin {
2	alias /opt/homebrew/share/phpmyadmin;
3	index index.php index.html index.htm;
4	location ~ \.php$ {
5	  fastcgi_split_path_info ^(.+\.php)(/.+)$;
6	  fastcgi_read_timeout 300;
7	  fastcgi_pass 127.0.0.1:9081;
8	  fastcgi_param SCRIPT_FILENAME $request_filename;
9	  include fastcgi_params;
10	}
11}
Go to https://localhost/phpmyadmin

MailHog

1brew install mailhog
2brew services start mailhog
3
4# start with
5mailhog
Now, you can access MailHog at http://localhost:8025.
Send a test email and check MailHog
1echo "Test email from Postfix" | mail -s "Test Email" [email protected]
Next, update each php.ini file with the following, if you have multiple versions of PHP, and then restart php-fpm. Note, test@localhost should be used but will be overridden by any PHP scripts that run
1sendmail_path = /opt/homebrew/opt/mailhog/bin/MailHog sendmail test@localhost

ElasticSearch (Need to install Magento 2)

From Magento Version ≥ 2.4, It has changed MySQL search to Elasticsearch.
Install Elasticsearch & OpenJDK
1brew tap elastic/tap
2brew install elastic/tap/elasticsearch-full
3brew install openjdk@17
Symlink OpenJDK so the system Java wrappers can find it. This information is also displayed as a Homebrew “caveat” after installing OpenJDK.
1sudo ln -sfn /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
Change .zshrc
1export ES_JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/<openjdk-version>/libexec/openjdk.jdk/Contents/Home
Modify elasticsearch.plist to use the OpenJDK
1# homebrew.mxcl.elasticsearch-full.plist
2<key>EnvironmentVariables</key>
3<dict>
4  <key>ES_JAVA_HOME</key>
5  <string>/opt/homebrew/Cellar/openjdk@17/<openjdk-version>/libexec/openjdk.jdk/Contents/Home</string>
6</dict>
Run & Test Elasticsearch
1elasticsearch # option -d to run detach
2
3curl -s http://localhost:9200
Troubleshooting
Check more on Gist

Dnsmasq

To save yourself the fuss of editing your hosts file constantly you can use dnsmasq
1brew install dnsmasq
1echo 'address=/.test/127.0.0.1' > /opt/homebrew/etc/dnsmasq.conf
2sudo mkdir -v /etc/resolver
3sudo bash -c 'echo "nameserver 127.0.0.1" > /etc/resolver/test'
Start or restart “dnsmasq” (Need to sudo)
1sudo brew services start dnsmasq
Confirm “dnsmasq” is working with a ping TLDs, one at a time
1ping -c 1 test.test