2014年2月19日水曜日

Mac OS X MavericksにApacheとPHPをインストールしてWebアプリの開発環境を作ってみる

Mac OS XはPHPなWebプログラミング環境として最適だ!


わざわざオイラが言うまでもなく、皆様ご存じのことと思います。Mac OS XはPHPなWebプログラミングをやるなら最高の環境だ。

なぜか。

それは、ApacheとPHPがプリインストールされてるから(`・ω・´)b

そう。特別なことは何もしなくても、Macを買ってきたらターミナルを開いて

sudo apachectl start

とタイプすればApacheが起動(*1)する。以前のバージョンのMac OS Xでは「Web共有」なんて名前で簡単にできたみたいなので、それよりはちょっと難易度が上がっているけどもまあ簡単だよね。

同様に

sudo apachectl stop

とタイプすればApacheが停止するし、

sudo apachectl restart

とタイプすればApacheが再起動する。

で、Apacheが起動した状態でWebブラウザを起動し「http://localhost」にアクセスすれば、おなじみの「It Works!」をその目に焼き付けることができる。


PHPを使うには一手間必要で、

sudo vi /private/etc/apache2/httpd.conf

して(*2)、118行目付近にある

#LoadModule php5_module libexec/apache2/libphp5.so

の先頭にある「#」を

LoadModule php5_module libexec/apache2/libphp5.so

のように削除して保存し、apacheを再起動すると有効になる。

ちなみにドキュメントルートは「/Library/WebServer/Documents/」だし、ログは「/private/var/log/apache2/」に出力される。コンフィグ類は「/private/etc/apache2/」(*3)にある。

で、この状態でphpinfoを表示させるだけの簡単なプログラム

<?php
phpinfo();

をドキュメントルート内に「phpinfo.php」などといった適当な名前で保存した後、Webブラウザから「http://localhost/phpinfo.php」にアクセスすると、PHPが動作しているのが確認できるはず。


でもバージョン古くね?……じゃあどうすんのさ!


まあ、これで一応事足りるといえばそうなのだけれど、動いているPHPが「5.4.17」とちょっと古いよね。5.4系の最新は「5.4.25」(*4)だし。

それに、5.3系や5.5系、どれだけニーズがあるかは知らないけど5.6系が使いたい……って場合はこのままではムリ。

じゃあどうするの?……って話になるよねー。homebrewを使ったりする方法もあるみたいなんだけど、個人的にはOS X 10.6/10.7/10.8/10.9向けのバイナリパッケージを提供している下記のサイトをオススメしたい。


何故オススメなのかというと、

  • ApacheはMac OS Xにインストールされているものをそのまま使うよ!
  • PHPはMac OS Xにインストールされているものとは別にインストールするよ!
  • インストールコマンドはワンライナーだよ!
  • 5.4.x以外に5.3.xや5.5.x、アルファ版だけど5.6.xもいけるよ!
  • 本家のリリースとイコールではないけど、比較的新しめのバージョンが使えるよ!

という点がオススメポインツなのです。

Apacheは既存のものをそのまま使うのでディスク容量の節約になるし、Apacheの起動/停止なんかは手慣れた手順でいける。PHPは上書きしないから、環境を壊すことがないため何かあってもすぐに戻せる。

インストールもワンライナーで簡単だし、豊富なバージョンから選べるし。最新じゃないかもしれないけど新しめなバージョン(*5)が使えるし。このエントリを書いている時点では下記のバージョンが用意されている。


……ほら、好きになってきたでしょ?

それではインストールしてみましょうか!


早速インストールしてみようぜ!

まず「One Line Installation」のところから、インストールしたいバージョンを選ぶ。オイラは5.5系を選んだから、

curl -s http://php-osx.liip.ch/install.sh | bash -s 5.5

とターミナルからタイプする。

途中で「Password:」というプロンプトが出た場合は、ログインユーザのパスワードを入力。ダウンロードなどが始まるので、しばし待つ(*6)。

インストールが一段落すると、Apacheが再起動されて使えるようになる。時間はかかるもののすごく簡単。



もし、コマンドラインからもプリインストールされたPHPでなくて今回インストールしたPHPを使いたい……というニーズがあるなら、「Frequently Asked Questions」の「Why does php -v on the command line still show my old version?」に書いてある内容を熟読すること(*7)。

具体的には「~/.profile」なんかに「export PATH=/usr/local/php5/bin:$PATH」って1行を追加しろ……ってだけ。これでコマンドラインからも使えるようになる。追記した後はsourceなり「.」なりで再読込させるのをお忘れなく。

ちなみにアンインストール方法は……


先に進む前に、アンインストール方法を書いておこう。後で必要になるかもしれないからね。アンインストールについては「Uninstall」という項目に書いてある。

とりあえず「/usr/local/php5*」と「/usr/local/packager」のディレクトリ全体と、「/etc/apache2/other/」内にある「+php-osx.conf 」(*8)を削除すればOK。

前述のサイトには「/private/etc/apache2/httpd.conf」の編集(*9)と、「/etc/apache2/other/+entropy-php.conf」の削除もしろと書いてある。状況に応じてチェックしておくとよさげ。

ちなみにアップデート方法は……


ついでにアップデートする方法を書いておこう。

……といったものの、これといった情報がサイトには書いていない。ので、個人的にはアンインストールした後にもう一度新規インストール……って方法をとっている。

一緒にインストールされるpackagerとかを使えばもっとお手軽にアップデートできそうな気はするんだけども、環境壊したりしたくないし、確実に最新のリリースが適用できるので前述の方法でアップデートしてる(*10)。

-----------------------------------------
[2014/07/11 01:00 追記]

アップデート方法なんだけど、インストールの時にタイプしたコマンドをそのまま実行すればよさげっぽい。
バージョンが変わったとき(PHP5.5から5.6にするとか)も同じでいけるんじゃないかな〜って。
-----------------------------------------

使いやすいようにカスタマイズしてみる


これで終わりなんだけども、どうせだったらもうちょっと使いやすくしてみようと思う。というのも、ドキュメントルートやコンフィグの置き場所がすべて「sudo」しないといけないような場所にあるので、そのままだとすごく使いにくいと思うので。

まずは自分専用のディレクトリ構成を準備


ってことで、まず下記のようなディレクトリ構造を自分のホームディレクトリに作成してみた。


apache2ってのが必要な奴をまとめてつっこむディレクトリで、その中のconfって奴がApacheのコンフィグファイル置き場。logsはログの出力先で、showcaseの中にあるpublic_htmlってディレクトリがドキュメントルートとして使う……という形。

こんな感じでホームディレクトリに全部まとめておいておくことで、いちいちsudoしなくても良くなるし、プリインストールされたコンフィグとできるだけ混ざらないようにできる……って利点があると思っている。

まあ、このあたりは完全にお好み次第なんだけど。

httpd.confを書き換えてみる


まずは「/private/etc/apache2/httpd.conf」を書き換える。手元の環境での編集前後でdiffを取ったのがこちら。

$ diff /private/etc/apache2/httpd.conf.original /private/etc/apache2/httpd.conf
56,58c56,58
< LoadModule authn_dbm_module libexec/apache2/mod_authn_dbm.so
< LoadModule authn_anon_module libexec/apache2/mod_authn_anon.so
< LoadModule authn_dbd_module libexec/apache2/mod_authn_dbd.so
---
> #LoadModule authn_dbm_module libexec/apache2/mod_authn_dbm.so
> #LoadModule authn_anon_module libexec/apache2/mod_authn_anon.so
> #LoadModule authn_dbd_module libexec/apache2/mod_authn_dbd.so
63c63
< LoadModule authz_dbm_module libexec/apache2/mod_authz_dbm.so
---
> #LoadModule authz_dbm_module libexec/apache2/mod_authz_dbm.so
68,74c68,74
< LoadModule cache_module libexec/apache2/mod_cache.so
< LoadModule disk_cache_module libexec/apache2/mod_disk_cache.so
< LoadModule mem_cache_module libexec/apache2/mod_mem_cache.so
< LoadModule dbd_module libexec/apache2/mod_dbd.so
< LoadModule dumpio_module libexec/apache2/mod_dumpio.so
< LoadModule reqtimeout_module libexec/apache2/mod_reqtimeout.so
< LoadModule ext_filter_module libexec/apache2/mod_ext_filter.so
---
> #LoadModule cache_module libexec/apache2/mod_cache.so
> #LoadModule disk_cache_module libexec/apache2/mod_disk_cache.so
> #LoadModule mem_cache_module libexec/apache2/mod_mem_cache.so
> #LoadModule dbd_module libexec/apache2/mod_dbd.so
> #LoadModule dumpio_module libexec/apache2/mod_dumpio.so
> #LoadModule reqtimeout_module libexec/apache2/mod_reqtimeout.so
> #LoadModule ext_filter_module libexec/apache2/mod_ext_filter.so
76,77c76,77
< LoadModule filter_module libexec/apache2/mod_filter.so
< LoadModule substitute_module libexec/apache2/mod_substitute.so
---
> #LoadModule filter_module libexec/apache2/mod_filter.so
> #LoadModule substitute_module libexec/apache2/mod_substitute.so
85,88c85,88
< LoadModule expires_module libexec/apache2/mod_expires.so
< LoadModule headers_module libexec/apache2/mod_headers.so
< LoadModule ident_module libexec/apache2/mod_ident.so
< LoadModule usertrack_module libexec/apache2/mod_usertrack.so
---
> #LoadModule expires_module libexec/apache2/mod_expires.so
> #LoadModule headers_module libexec/apache2/mod_headers.so
> #LoadModule ident_module libexec/apache2/mod_ident.so
> #LoadModule usertrack_module libexec/apache2/mod_usertrack.so
92,98c92,98
< LoadModule proxy_module libexec/apache2/mod_proxy.so
< LoadModule proxy_connect_module libexec/apache2/mod_proxy_connect.so
< LoadModule proxy_ftp_module libexec/apache2/mod_proxy_ftp.so
< LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
< LoadModule proxy_scgi_module libexec/apache2/mod_proxy_scgi.so
< LoadModule proxy_ajp_module libexec/apache2/mod_proxy_ajp.so
< LoadModule proxy_balancer_module libexec/apache2/mod_proxy_balancer.so
---
> #LoadModule proxy_module libexec/apache2/mod_proxy.so
> #LoadModule proxy_connect_module libexec/apache2/mod_proxy_connect.so
> #LoadModule proxy_ftp_module libexec/apache2/mod_proxy_ftp.so
> #LoadModule proxy_http_module libexec/apache2/mod_proxy_http.so
> #LoadModule proxy_scgi_module libexec/apache2/mod_proxy_scgi.so
> #LoadModule proxy_ajp_module libexec/apache2/mod_proxy_ajp.so
> #LoadModule proxy_balancer_module libexec/apache2/mod_proxy_balancer.so
101,102c101,102
< LoadModule dav_module libexec/apache2/mod_dav.so
< LoadModule status_module libexec/apache2/mod_status.so
---
> #LoadModule dav_module libexec/apache2/mod_dav.so
> #LoadModule status_module libexec/apache2/mod_status.so
107c107
< LoadModule dav_fs_module libexec/apache2/mod_dav_fs.so
---
> #LoadModule dav_fs_module libexec/apache2/mod_dav_fs.so
113,114c113,114
< LoadModule speling_module libexec/apache2/mod_speling.so
< LoadModule userdir_module libexec/apache2/mod_userdir.so
---
> #LoadModule speling_module libexec/apache2/mod_speling.so
> #LoadModule userdir_module libexec/apache2/mod_userdir.so
118c118
< #LoadModule php5_module        libexec/apache2/libphp5.so
---
> #LoadModule php5_module libexec/apache2/libphp5.so
120a121,122
> LoadModule php5_module /usr/local/php5/libphp5.so
>
460c462
< Include /private/etc/apache2/extra/httpd-mpm.conf
---
> #Include /private/etc/apache2/extra/httpd-mpm.conf
466c468
< Include /private/etc/apache2/extra/httpd-autoindex.conf
---
> #Include /private/etc/apache2/extra/httpd-autoindex.conf
469c471
< Include /private/etc/apache2/extra/httpd-languages.conf
---
> #Include /private/etc/apache2/extra/httpd-languages.conf
472c474
< Include /private/etc/apache2/extra/httpd-userdir.conf
---
> #Include /private/etc/apache2/extra/httpd-userdir.conf
481c483
< Include /private/etc/apache2/extra/httpd-manual.conf
---
> #Include /private/etc/apache2/extra/httpd-manual.conf
501c503,505
< Include /private/etc/apache2/other/*.conf
---
> #Include /private/etc/apache2/other/*.conf
>
> Include /Users/foobar/apache2/conf/*.conf

何を意図してるか/やっているかというと、

  1. 使わないモジュールをロードしない
  2. libphp5.soの読み込みパスを変更(追加)
  3. httpd.conf以外のコンフィグを読み込まない
  4. ホームディレクトリ内に作ったディレクトリからコンフィグを読み込ませる

といった感じ。いずれも必須というわけではなく、「ぼくのかんがえたさいきょうのかいはつかんきょう」を実現するためのものなので、お望みの構成になるよう各自好きにやればいいんじゃね?

ちなみにボクは「/private/etc/apache2/httpd.conf」を直接編集するんじゃなくて、そいつを「~/apache2/conf/httpd.conf.hayaedited」的なファイル名でコピー(*11)してからコピーした方を編集。前者のほうは別な名前にリネームしてとって置いて、後者のファイルを前者のファイル名でシンボリックリンクをはる形にしている。

バーチャルホストの設定を追加してみる


先のhttpd.confはあくまで最低限の設定。必要設定を別ファイルにまとめておく。

オイラは「~/apache2/conf/localhost.conf」というファイルを新規作成し、そこに必要な記述をまとめて書いている。具体的には下記の通り。

Listen 443

DirectoryIndex index.html index.htm index.php

<IfModule mod_php5.c>
  AddType application/x-httpd-php .php .inc
</IfModule>

<VirtualHost *:80>
    ServerName localhost
    ErrorLog  "/path/to/homedir/apache2/logs/error.log"
    LogLevel warn
    CustomLog "/path/to/homedir/apache2/logs/access.log" combined

    DocumentRoot "/path/to/homedir/apache2/showcase/public_html"
    <Directory "/path/to/homedir/apache2/showcase/public_html">
        AllowOverride All
        Options All
        <Limit GET POST>
            Order allow,deny
            Allow from localhost
        </Limit>
        <LimitExcept GET POST>
            Order deny,allow
            Deny from all
        </LimitExcept>
    </Directory>
</VirtualHost>

<VirtualHost *:443>
    ServerName localhost
    ErrorLog  "/path/to/homedir/apache2/logs/error.log"
    LogLevel warn
    CustomLog "/path/to/homedir/apache2/logs/access.log" combined

    #   SSL Engine Switch:
    SSLEngine on
    SSLCertificateFile    /path/to/homedir/apache2/conf/server.crt
    SSLCertificateKeyFile /path/to/homedir/apache2/conf/server.key

    DocumentRoot "/path/to/homedir/apache2/showcase/public_html"
    <Directory "/path/to/homedir/apache2/showcase/public_html">
        AllowOverride All
        Options All
        <Limit GET POST>
            Order allow,deny
            Allow from localhost
        </Limit>
        <LimitExcept GET POST>
            Order deny,allow
            Deny from all
        </LimitExcept>
    </Directory>
</VirtualHost>

「/path/to/homedir/」のところは各自の環境に合わせて書き換えること(*12)。

何を意図してるか/やっているかというと、

  1. index.phpの有効化などPHP関連で必要な設定
  2. バーチャルホストの設定(http用とhttps用)

といった感じ。ここら辺はお好みでどうぞ。

自己署名SSLサーバ証明書を作ってみる


前述の通りhttpsが使えるようにしておきたいので、SSLサーバ証明書を作ってみる。とはいえ、たかだか開発環境にちゃんとした証明書はもったいないので「オレオレ証明書」という名前で親しまれている自己署名なSSLサーバ証明書を作る。

オイラは「~/apache2/conf/」に「gen_cert.sh」というシェルスクリプトを作って、そいつを実行するだけで必要な処理が完結するようにしている。中身はこんな感じ。
#!/bin/bash
openssl dgst -md5 /var/log/system.log > ./rand.dat
openssl genrsa -des3 -rand ./rand.dat 1024 > server.key
openssl rsa -in ./server.key -out ./server.key
openssl req -new -days 365 -key ./server.key -out server.csr
openssl req -in ./server.csr -key ./server.key -x509 -out ./server.crt
rm ./rand.dat ./server.csr

2行目で乱数ファイルを作り、3行目で秘密鍵を作成。4行目で秘密鍵をパスなしに変換し、5行目でCSR(Certificate Signing Request)を作成。6行目で秘密鍵を使ってCSRに基づいたSSLサーバ証明書を作成し、7行目で不要なファイルを削除している。

まあ、これだけのスクリプト。一度作っておくと便利。ちなみに実行した結果は下記の通り。括弧の所は自分で入力するところなので、各自自分の環境に合わせて入力すべし。

$ sh ./gen_cert.sh
59 semi-random bytes loaded
Generating RSA private key, 1024 bit long modulus
................++++++
....................................++++++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase:(ここで適当なパスフレーズを入力)
Verifying - Enter pass phrase:(ここで適当なパスフレーズを入力)
Enter pass phrase for ./server.key:(ここで適当なパスフレーズを入力)
writing RSA key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:(JPなどと入力)
State or Province Name (full name) [Some-State]:(Tokyoなどと入力)
Locality Name (eg, city) []:(エンターキーを押す)
Organization Name (eg, company) [Internet Widgits Pty Ltd]:(適当に入力)
Organizational Unit Name (eg, section) []:(エンターキーを押す)
Common Name (e.g. server FQDN or YOUR name) []:(localhostと入力)
Email Address []:(エンターキーを押す)

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:(エンターキーを押す)
An optional company name []:(エンターキーを押す)

これで「~/apache2/conf/」に「server.key」と「server.crt」の2ファイルができているはず。

php.iniを書き換えてみる


最後にphp.iniの編集、すなわちPHPの設定をおこなってみる。php.ini自体は「/usr/local/php5/lib/php.ini」に存在する。

……のだけれども、これはそのままにしておく。代わりに「/usr/local/php5/php.d/」配下にいろいろなコンフィグが詰まっているので、こちらの中にある必要な物だけを編集する形にしておく。

こちらも例によって編集したいコンフィグを「~/apache2/conf/」にコピーし、元々あったファイルはリネームして取っておく。で、コピーしたファイルを編集して、そのファイルへのシンボリックリンクを元のディレクトリに作成する……という流れにしている。

こうしておけば、再インストールしたときでも簡単にコンフィグを戻せる(*13)。

オイラの場合は「99-liip-developer.ini」を書き換えてみた。変更前後のdiffは下記の通り。

$ diff ./99-liip-developer.ini.original ./99-liip-developer.ini
14,16c14,16
< date.timezone = Europe/Zurich
< date.default_latitude  = 47.38
< date.default_longitude =  8.5244
---
> date.timezone = Asia/Tokyo
> ;date.default_latitude  = 47.38
> ;date.default_longitude =  8.5244
79a80,143
>
>
>
> [mbstring]
> ; language for internal character representation.
> ; http://php.net/mbstring.language
> mbstring.language = Japanese
>
> ; internal/script encoding.
> ; Some encoding cannot work as internal encoding.
> ; (e.g. SJIS, BIG5, ISO-2022-*)
> ; http://php.net/mbstring.internal-encoding
> mbstring.internal_encoding = UTF-8
>
> ; http input encoding.
> ; http://php.net/mbstring.http-input
> mbstring.http_input = pass
>
> ; http output encoding. mb_output_handler must be
> ; registered as output buffer to function
> ; http://php.net/mbstring.http-output
> mbstring.http_output = pass
>
> ; enable automatic encoding translation according to
> ; mbstring.internal_encoding setting. Input chars are
> ; converted to internal encoding by setting this to On.
> ; Note: Do _not_ use automatic encoding translation for
> ;       portable libs/applications.
> ; http://php.net/mbstring.encoding-translation
> mbstring.encoding_translation = Off
>
> ; automatic encoding detection order.
> ; auto means
> ; http://php.net/mbstring.detect-order
> mbstring.detect_order = "SJIS,EUC-JP,JIS,UTF-8,ASCII"
>
> ; substitute_character used when character cannot be converted
> ; one from another
> ; http://php.net/mbstring.substitute-character
> mbstring.substitute_character = none;
>
> ; overload(replace) single byte functions by mbstring functions.
> ; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),
> ; etc. Possible values are 0,1,2,4 or combination of them.
> ; For example, 7 for overload everything.
> ; 0: No overload
> ; 1: Overload mail() function
> ; 2: Overload str*() functions
> ; 4: Overload ereg*() functions
> ; http://php.net/mbstring.func-overload
> mbstring.func_overload = 0
>
> ; enable strict encoding detection.
> mbstring.strict_detection = Off
>
> ; This directive specifies the regex pattern of content types for which mb_output_handler()
> ; is activated.
> ; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)
> ; mbstring.http_output_conv_mimetype=
>
> [iconv]
> iconv.input_encoding = UTF-8
> iconv.internal_encoding = UTF-8
> iconv.output_encoding = UTF-8

何を意図してるか/やっているかというと、

  1. タイムゾーンの設定を変更
  2. mbstring/iconv関連の設定を追加

といった感じ。ここら辺はお好みでどうぞ。

そんでもって「50-extension-xdebug.ini」。こちらは「xdebug.idekey」の設定を追加した。一応変更前後のdiffを下記に書いておく。

$ diff ./50-extension-xdebug.ini.original ./50-extension-xdebug.ini
12a13,14
>
> xdebug.idekey = "IDEKEY"

PHP関連の設定はこれで終わり。

後はEnjoy Hacking!


これで必要な設定は終わったので、後はApacheを再起動すればOK。あなたのMacが素敵なWebアプリ開発環境になりました!オメデトウ!

このエントリに書いていることはあくまで最低限……というか現状ボクが必要な物だけなので、必要に応じて加筆修正すること。もちろんボクみたいにとりあえずこれでスタートして、後で必要に応じて修正していくスタイルでもいいだろうけど。どちらにせよ、apacheの起動/停止/再起動以外は「sudo」使わないでもできるようになっているはずなので、いろいろやりやすいと思う。

あ、あと、ここに書いてあることを鵜呑みにしてコピペしないこと。ちゃんとどうしてそうやってるのか、何をやってるのかを把握した上でやらないと、後で泣くはめになるかもよ?間違いが含まれてるかもしれないし!(*14)

-----------------------------------------
[2014/07/11 01:00 追記]

今回はApacheをインストールしたのだけれど、「Mac OS X MavericksにMySQLをインストールしてみる」というエントリでMySQLをインストールしている。合わせて読むと幸せになれるかもよ!

で、今回インストールしたApacheの起動や終了なんかを簡単におこなうためのシェルスクリプトをそのエントリの最後で紹介しているので、それが必要な人もそっちのエントリをチェックしてみてね!
-----------------------------------------


*1:「Password:」というプロンプトが表示されたら、ログインユーザのパスワードを入力してエンター
*2:別にviを使う必然性は内ので、emacsでもなんでも好きなエディタで編集すればいいじゃない!
*3:php.iniについては「/private/etc/」に配置すればOK
*4:このエントリを書いている時点ではね
*5:バージョンの更新は不定期っぽいので、タイミングによってはアレかも(^^ゞ
*6:環境にもよるだろうけど、手元の環境では10分弱ほどかかった
*7:これ以外にも変なところでハマりたくないならFAQのところは熟読しておくべき
*8:packagerについては他で使う予定があるなら削除しなくていい
*9:LoadModulesのところ、libphp5.soのパスをデフォルトに戻せ……という指示
*10:もっと良い方法をご存じなら是非教えてプリーズ
*11:ファイル名は何でもいいんだけど
*12:ようは「~/apache2」のパスね
*13:再インストール時に削除する運用にしているからねぇ……
*14:間違っている箇所や「ここはこうしたほうがいい!」という部分があったら教えてプリーズ

0 件のコメント:

コメントを投稿