Homebrew 安裝 Nginx、PHP71 筆記

在 macOX Sierra 透過 brew 指令安裝 php71(帶有 php-fpm)及 nginx
Install NGINX with PHP71 on Mac OS Sierra with Homebrew.

前言 Prologue

臨時有需要讓 localhost 透過使用 ngrok 的對外服務,以測試 webhook 功能,BUT nginx 就在這個時候出問題了。
本來以為是用了 Laravel Valet 的關係,但即使是停用 Valet,修改 hosts 或重建 nginx.conf 都於事無補,只好從安裝 PHP 到 Nginx 重新做起。

環境 Environment

  • macOS Sierra: 10.12.5
  • homebrew: 1.3.1

Install Commandline Tools

1
$ xcode-select —install

Install Homebrew

1
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Check Installation

1
$ brew doctor

Update Brew and Packages

1
$ brew update && brew upgrade

Install brew services

1
$ brew tap homebrew/services

安裝 DNSMasq

DNSMasq is used to resolve all domains that end with .dev to 127.0.0.1.
DNSMasq 將 .env 結尾的網址對應到 127.0.0.1,就不需要再修改 /etc/hosts 檔案

安裝 Install

1
$ brew install dnsmasq

配置 Configure

檔案 /usr/local/etc/dnsmasq.conf 內容

1
2
address=/.dev/127.0.0.1
listen-address=127.0.0.1

檔案 /etc/resolver/dev 內容

1
nameserver 127.0.0.1

startstoprestart DNSMasq

1
2
3
$ sudo brew services start dnsmasq
$ sudo brew services stop dnsmasq
$ sudo brew services restart dnsmasq

測試 Testing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig testing.dev @127.0.0.1
dig testing.dev @127.0.0.1

; <<>> DiG 9.8.3-P1 <<>> testing.dev @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21966
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;testing.dev. IN A

;; ANSWER SECTION:
testing.dev. 0 IN A 127.0.0.1

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Aug 27 22:39:50 2017
;; MSG SIZE rcvd: 45

安裝 PHP-FPM

Install php71

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$ brew tap homebrew/dupes && \
$ brew tap homebrew/php

$ brew install php71
==> Installing php71 from homebrew/php
==> Downloading https://homebrew.bintray.com/bottles-php/php71-7.1.1_12.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring php71-7.1.1_12.sierra.bottle.tar.gz
==> Caveats
The php.ini file can be found in:
/usr/local/etc/php/7.1/php.ini

✩✩✩✩ Extensions ✩✩✩✩

If you are having issues with custom extension compiling, ensure that
you are using the brew version, by placing /usr/local/bin before /usr/sbin in your PATH:

PATH="/usr/local/bin:$PATH"

PHP71 Extensions will always be compiled against this PHP. Please install them
using --without-homebrew-php to enable compiling against system PHP.

✩✩✩✩ PHP CLI ✩✩✩✩

If you wish to swap the PHP you use on the command line, you should add the following to ~/.bashrc,
~/.zshrc, ~/.profile or your shell's equivalent configuration file:

export PATH="$(brew --prefix homebrew/php/php71)/bin:$PATH"

✩✩✩✩ FPM ✩✩✩✩

To launch php-fpm on startup:
mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/php71/homebrew.mxcl.php71.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php71.plist

The control script is located at /usr/local/opt/php71/sbin/php71-fpm

OS X 10.8 and newer come with php-fpm pre-installed, to ensure you are using the brew version you need to make sure /usr/local/sbin is before /usr/sbin in your PATH:

PATH="/usr/local/sbin:$PATH"

You may also need to edit the plist to use the correct "UserName".

Please note that the plist was called 'homebrew-php.josegonzalez.php71.plist' in old versions
of this formula.

With the release of macOS Sierra the Apache module is now not built by default. If you want to build it on your system
you have to install php with the --with-httpd24 option. See brew options php71 for more details.

To have launchd start homebrew/php/php71 now and restart at login:
brew services start homebrew/php/php71
==> Summary
🍺 /usr/local/Cellar/php71/7.1.1_12: 344 files, 39.7M

配置 Configure

編輯檔案 /usr/local/etc/php/7.1/php-fpm.d/www.conf

1
2
user = YOUR_USERNAME
group = staff

測試 Testing

啟動 php-fpm

1
$ sudo brew services start php71

Show running processes

1
lsof -Pni4 | grep LISTEN | grep php

安裝 NGINX

Install NGINX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ brew tap homebrew/nginx

$ brew install nginx
==> Downloading https://homebrew.bintray.com/bottles/nginx-1.12.1.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring nginx-1.12.1.sierra.bottle.tar.gz
==> Caveats
Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:
brew services start nginx
Or, if you don't want/need a background service you can just run:
nginx
==> Summary
🍺 /usr/local/Cellar/nginx/1.12.1: 23 files, 1MB

安裝測試 Testing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## Start Nginx
$ sudo brew services start nginx

## Check if Nginx is running on default port
$ curl -IL http://127.0.0.1:8080
curl -IL http://127.0.0.1:8080
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Sun, 27 Aug 2017 14:59:30 GMT
Content-Type: text/html
Content-Length: 274
Last-Modified: Sat, 26 Aug 2017 14:05:36 GMT
Connection: keep-alive
ETag: "59a18030-112"
Accept-Ranges: bytes

Stop Nginx

1
$ sudo brew services stop nginx

配置 Configure

建立目錄 Create directories

1
2
3
4
$ mkdir -p /usr/local/etc/nginx/sites-available && \
$ mkdir -p /usr/local/etc/nginx/sites-enabled && \
$ mkdir -p /usr/local/etc/nginx/conf.d && \
$ mkdir -p /usr/local/etc/nginx/ssl

配置檔案 nginx.conf

刪除預設檔案

1
$ rm /usr/local/etc/nginx/nginx.conf

建立新檔 $ vim /usr/local/etc/nginx/nginx.conf 內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
worker_processes  1;

error_log /var/log/nginx/error.log;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

#sendfile on;
sendfile off;

#keepalive_timeout 65;
keepalive_timeout 1;

index index.html index.php;

include /usr/local/etc/nginx/sites-enabled/*;
}

啟動並測試 Nginx Start and Test Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## Start Nginx
$ sudo brew services start nginx

## Check if Nginx is running on default port
$ curl -IL http://localhost
curl -IL http://localhost
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Sun, 27 Aug 2017 15:12:35 GMT
Content-Type: text/html
Content-Length: 274
Last-Modified: Sat, 26 Aug 2017 14:05:36 GMT
Connection: keep-alive
ETag: "59a18030-112"
Accept-Ranges: bytes

設定 SSL Setup SSL

Generate 4096 bit RSA keys and the self-sign the certificates

1
$ openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=State/L=Town/O=Office/CN=localhost" -keyout /usr/local/etc/nginx/ssl/localhost.key -out /usr/local/etc/nginx/ssl/localhost.crt

RSA keys 存放在資料夾 /usr/local/etc/nginx/ssl

建立 Virtual Hosts 網站檔案

檔案 /usr/local/etc/nginx/sites-available/default 內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name localhost;
root /YOUR/DOCUMENT/ROOT;

access_log /var/log/default.access.log main;
error_log /var/log/nginx/default.error.log debug;

location / {
include /usr/local/etc/nginx/conf.d/php-fpm;
}

location = /info {
allow 127.0.0.1;
deny all;
rewrite (.*) /.info.php;
}

error_page 404 /404.html;
error_page 403 /403.html;
}

檔案 /usr/local/etc/nginx/sites-available/default-ssl 內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server {
listen 443;
server_name localhost;
root /YOUR/DOCUMENT/ROOT;

access_log /var/log/nginx/default-ssl.access.log main;
error_log /var/log/nginx/default-ssl.error.log debug;

ssl on;
ssl_certificate ssl/localhost.crt;
ssl_certificate_key ssl/localhost.key;

ssl_session_timeout 5m;

ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

location / {
include /usr/local/etc/nginx/conf.d/php-fpm;
}

location = /info {
allow 127.0.0.1;
deny all;
rewrite (.*) /.info.php;
}

error_page 404 /404.html;
error_page 403 /403.html;
}

檔案 /usr/local/etc/nginx/conf.d/php-fpm 內容

1
2
3
4
5
6
7
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

Activate Virtual Hosts

sites-enabled 目錄下建立 Symbolic link。將要 enable 的 virtal host 指向 sites-available 目錄內的 virtal host config file。

1
2
$ ln -sfv /usr/local/etc/nginx/sites-available/default /usr/local/etc/nginx/sites-enabled/default
$ ln -sfv /usr/local/etc/nginx/sites-available/default-ssl /usr/local/etc/nginx/sites-enabled/default-ssl

測試 Testing

建立 /YOUR/DOCUMENT/ROOT/info.php 內容

1
2
3
<?php
phpinfo();
?>

重新啟動 Nginx 並測試

1
2
3
4
5
6
7
8
9
10
$ sudo brew services restart nginx

$ curl -IL http://localhost/info.php
curl -IL http://localhost/info.php
HTTP/1.1 200 OK
Server: nginx/1.12.1
Date: Sun, 27 Aug 2017 15:24:46 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/7.1.8

安裝其他 Libraries

1
$ brew install php71-mcrypt php71-imagick

brew info 查看 PHP 及其相關 Libraries 的資訊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
$ brew info php71
homebrew/php/php71: stable 7.1.8 (bottled), HEAD
PHP Version 7.1
https://php.net
Conflicts with:
php53 (because different php versions install the same binaries.)
php54 (because different php versions install the same binaries.)
php55 (because different php versions install the same binaries.)
php56 (because different php versions install the same binaries.)
php70 (because different php versions install the same binaries.)
php72 (because different php versions install the same binaries.)
/usr/local/Cellar/php71/7.1.8_20 (349 files, 39.5MB) *
Poured from bottle on 2017-08-26 at 16:34:27
From: https://github.com/Homebrew/homebrew-php/blob/master/Formula/php71.rb
==> Dependencies
Required: freetype ✔, gettext ✔, icu4c ✔, jpeg ✔, libpng ✔, libxml2 ✔, unixodbc ✔, readline ✔, openssl ✔
Optional: enchant ✘, gmp ✘, webp ✘, homebrew/apache/httpd24 ✔, homebrew/apache/httpd22 ✘
==> Requirements
Optional: postgresql ✘
==> Options
--with-cgi
Enable building of the CGI executable (implies --without-fpm)
--with-debug
Compile with debugging symbols
--with-enchant
Build with enchant support
--with-gmp
Build with gmp support
--with-homebrew-curl
Include Curl support via Homebrew
--with-homebrew-libressl
Include LibreSSL instead of OpenSSL via Homebrew
--with-homebrew-libxml2
Include Libxml2 support via Homebrew
--with-homebrew-libxslt
Include LibXSLT support via Homebrew
--with-httpd22
Enable building of shared Apache 2.2 Handler module
--with-httpd24
Enable building of shared Apache 2.4 Handler module
--with-imap
Include IMAP extension
--with-libmysql
Include (old-style) libmysql support instead of mysqlnd
--with-mssql
Include MSSQL-DB support
--with-pdo-oci
Include Oracle databases (requries ORACLE_HOME be set)
--with-pear
Build with PEAR
--with-phpdbg
Enable building of the phpdbg SAPI executable
--with-postgresql
Build with postgresql support
--with-thread-safety
Build with thread safety
--with-webp
Build with webp support
--without-bz2
Build without bz2 support
--without-fpm
Disable building of the fpm SAPI executable
--without-ldap
Build without LDAP support
--without-legacy-mysql
Do not include the deprecated mysql_ functions
--without-mysql
Remove MySQL/MariaDB support
--without-pcntl
Build without Process Control support
--without-unixodbc
Build without unixODBC support
--HEAD
Install HEAD version
==> Caveats
The php.ini file can be found in:
/usr/local/etc/php/7.1/php.ini

✩✩✩✩ Extensions ✩✩✩✩

If you are having issues with custom extension compiling, ensure that you are using the brew version, by placing /usr/local/bin before /usr/sbin in your PATH:

PATH="/usr/local/bin:$PATH"

PHP71 Extensions will always be compiled against this PHP. Please install them using --without-homebrew-php to enable compiling against system PHP.

✩✩✩✩ PHP CLI ✩✩✩✩

If you wish to swap the PHP you use on the command line, you should add the following to ~/.bashrc, ~/.zshrc, ~/.profile or your shell's equivalent configuration file:
export PATH="$(brew --prefix homebrew/php/php71)/bin:$PATH"

✩✩✩✩ FPM ✩✩✩✩

To launch php-fpm on startup:
mkdir -p ~/Library/LaunchAgents
cp /usr/local/opt/php71/homebrew.mxcl.php71.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php71.plist

The control script is located at /usr/local/opt/php71/sbin/php71-fpm

OS X 10.8 and newer come with php-fpm pre-installed, to ensure you are using the brew version you need to make sure /usr/local/sbin is before /usr/sbin in your PATH:

PATH="/usr/local/sbin:$PATH"

You may also need to edit the plist to use the correct "UserName".

Please note that the plist was called 'homebrew-php.josegonzalez.php71.plist' in old versions of this formula.

With the release of macOS Sierra the Apache module is now not built by default. If you want to build it on your system you have to install php with the --with-httpd24 option. See brew options php71 for more details.

To have launchd start homebrew/php/php71 now and restart at login:
brew services start homebrew/php/php71

後記 Epilogue

如果 $ curl -IL http://127.0.0.1:8080 出現 curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused,請記得檢查

  1. php-fpm 是不是啟動
  2. nginx 是否有 restart
  3. /usr/loca/etc/php/7.1/php-fpm.d/www.confusergroup 是否正確設定
  4. /usr/local/etc/nginx/conf.d/php-fpm 檔案是否建立

參考資料 References