Перейти к содержимому

31.05.2013

Web-разработка с использованием nginx, php-fpm, node.js на Mac OS X.

nginxКак известно, в комплекте с Mac OS X идет веб-сервер apache и php. Но как быть, если мы хотим использовать node.js, да не просто как отдельный сервер, висящий на отдельном порту, а иметь возможность проксировать http-запросы как к нему, так и к php. Небольшая инструкция по замене штатного httpd/php-module на связку nginx+php-fpm+node.js ниже.

Начнем по порядку.

1. Отключение загрузки httpd при старте системы.

В Mac OS httpd, как впрочем и многие другие демоны и сервисы, грузится как LaunchDaemon. Все управление осуществляется через launchctl.

# Так можно загрузить httpd. Ключик -w делает эту загрузку перманентной, то есть после презагрузки компа сервис загрузится автоматически.
kostik@KOsTIK: ~> sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

# Ну а так соответственно можно остановить http, а благодаря ключу -w он не будет больше загружаться автоматически при старте системы.
kostik@KOsTIK: ~> sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

2. Установка Nginx.

Есть несколько способов установить Nginx:

  • Установка из исходников
  • Установка через macports
  • Установка через homebrew

Лично я как-то перешел с macports на homebrew, поэтому выбрал третий вариант. Тем более, что в brew доступна версия 1.4.1 и даже 1.5.0, а в macports только 1.4.1. Но, правда для меня это не принципиально, главное что там уже есть поддержка проксирования веб-сокетов.

Установка из homebrew крайне проста.

kostik@KOsTIK: ~> brew search nginx
nginx

kostik@KOsTIK: ~> brew info nginx
nginx: stable 1.4.1, devel 1.5.0, HEAD
http://nginx.org/
https://github.com/mxcl/homebrew/commits/master/Library/Formula/nginx.rb
==> Dependencies
Required: pcre
==> Options
--with-debug
  Compile with support for debug log
--with-gunzip
  Compile with support for gunzip module
--with-passenger
  Compile with support for Phusion Passenger module
--with-spdy
  Compile with support for SPDY module
--with-webdav
  Compile with support for WebDAV module
==> Caveats
Docroot is: /usr/local/var/www

The default port has been set to 8080 so that nginx can run without sudo.

If you want to host pages on your local machine to the wider network you
can change the port to 80 in: /usr/local/etc/nginx/nginx.conf

You will then need to run nginx as root: `sudo nginx`.

You should reload nginx:
    launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

kostik@KOsTIK: ~> brew install nginx --with-spdy
==> Downloading http://nginx.org/download/nginx-1.4.1.tar.gz
Already downloaded: /Library/Caches/Homebrew/nginx-1.4.1.tar.gz
==> Patching
patching file conf/nginx.conf
==> ./configure --prefix=/usr/local/Cellar/nginx/1.4.1 --with-http_ssl_module --with-pcre --with-ipv6 --sbin-path=/usr/local/Cellar/nginx/1.4.1/bin/nginx --with-cc-opt=-I/usr/local/include --with-ld-opt=-L/usr/local/lib --conf-path=/usr/local/etc/nginx/nginx.conf --pid-path=/usr/local/var/run/nginx.pid --lock-path=/usr/local/var/run/nginx.lock --http-client-bo
==> make
==> make install
==> Caveats
Docroot is: /usr/local/var/www

The default port has been set to 8080 so that nginx can run without sudo.

If you want to host pages on your local machine to the wider network you
can change the port to 80 in: /usr/local/etc/nginx/nginx.conf

You will then need to run nginx as root: `sudo nginx`.

To have launchd start nginx at login:
    ln -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents
Then to load nginx now:
    launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
==> Summary
  /usr/local/Cellar/nginx/1.4.1: 7 files, 948K, built in 16 seconds

Не знаю, как в macports, а в homebrew что прекрасно, это то, что в комплекте с самим nginx’ом идет уже готовый plist для launchd, поэтому можно сразу прописать автостарт демона при загрузке ОС. Сделать это можно командами, указанными brew:

kostik@KOsTIK: ~> ln -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents
kostik@KOsTIK: ~> launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

Однако, если вы хотите повесить nginx на 80 порт, это потребует запуска демона из-под рута. Для этого необходимо немного подправить этот plist и положить его в папку системных LaunchDaemons. Поскольку мы будем запускать его как демона, а поставляемый plist предназначен для запуска nginx из-под пользователя и под управлением launchd, надо удалить в plist строчки про отключение демонизации. Вот подправленный файлик и команды для запуска как LaunchDaemon:




  
    Label
    ksdaemon.ru.nginx
    RunAtLoad
    
    KeepAlive
    
    ProgramArguments
    
        /usr/local/opt/nginx/bin/nginx

    
    WorkingDirectory
    /usr/local
  

kostik@KOsTIK: ~> sudo cp ksdaemon.ru.nginx.plist /System/Library/LaunchDaemons
kostik@KOsTIK: ~> sudo chown root:wheel /System/Library/LaunchDaemons/ksdaemon.ru.nginx.plist
kostik@KOsTIK: ~> sudo launchctl load /System/Library/LaunchDaemons/ksdaemon.ru.nginx.plist

Если использовать macports, nginx ставится так же одной командой: sudo port install nginx.

Опустим процесс настройки nginx. Он такой же как везде. Тонкости настройки проксирования будут показаны позже.

3. Установка node.js

Это, пожалуй, самый простой пункт, потому что готовый установочный пакет можно скачать прямо на сайте ноды: nodejs.org/download. Качаем, ставим.

4. Php-fpm у нас уже есть, так что ничего ставить дополнительно не надо.

5. Проксирование запросов к php-fpm в nginx.

Здесь все как всегда: в настройках виртуального хоста прописываем обращение к fastcgi.

kostik@KOsTIK: ~> vim /etc/nginx/vhost.d/project-host.conf 
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

Можно, кстати, сразу повесить nginx на стандартный, 80 порт, потому как апачи уже остановлен.

6. Теперь сделаем, чтобы php-fpm запускался при старте системы.

Для этого надо написать plist-файлик для launchd. А так как запускать php-fpm нужно от рута (это если оставить в конфиге переключение на nobody или же на www), то этот plist нужно так же положить в папку системных демонов.

Вот мой вариант plist для запуска php-fpm





  
    Label
    ksdaemon.ru.php-fpm
    RunAtLoad
    
    KeepAlive
    
    ProgramArguments
    
       /usr/sbin/php-fpm
       -c
       /private/etc/php.ini
       -y
       /private/etc/php-fpm.conf
    
    WorkingDirectory
    /usr
  


Ну и положим этот файлик куда надо и загрузим.


kostik@KOsTIK: ~> sudo cp ksdaemon.ru.php-fpm.plist /System/Library/LaunchDaemons/
kostik@KOsTIK: ~> sudo chown root:wheel /System/Library/LaunchDaemons/ksdaemon.ru.php-fpm.plist
kostik@KOsTIK: ~> sudo launchctl load /System/Library/LaunchDaemons/ksdaemon.ru.php-fpm.plist

Теперь у нас при загрузке Mac OS автоматом стартуют nginx и php-fpm.

7. Проксирование веб-сокет запросов.

Осталось настроить проксирование веб-сокет запросов к node.js (для тех, кому это нужно) и настроить автостарт node.js, опять же, если это необходимо.

Для проксирования веб-сокетов надо прописать в конфиге виртуального хоста, ну или же всего веб-сервера, если он у вас один, следующее:

kostik@KOsTIK: ~> vim /etc/nginx/vhost.d/project-host.conf 

    # websockets
    location /socket/ {
       proxy_pass      http://127.0.0.1:5000/;
       proxy_http_version      1.1;
       proxy_set_header        Upgrade $http_upgrade;
       proxy_set_header        Connection $connection_upgrade;
    }

Теперь все запросы по адресу http://your-server/socket/* будут проксироваться на адрес http://127.0.0.1:5000/, на котором мы запустим ноду.

8. Для автостарта ноды надо так же написать plist и положить его в LaunchAgents.

Вот мой вариант plist для автозапуска node.js




  
    Label
    ksdaemon.ru.node-js
    RunAtLoad
    
    KeepAlive
    
    ProgramArguments
    
       /usr/local/bin/node
       /Users/kostik/Projects/my-project/index.js
    
    WorkingDirectory
    /usr
  


Ну и положим этот файлик куда надо и загрузим. Поскольку ноду нет необходимости запускать от рута, то положим ее в пользовательские LaunchAgents


kostik@KOsTIK: ~> cp ksdaemon.ru.node-js.plist ~/Library/LaunchAgents/
kostik@KOsTIK: ~> launchctl load ~/Library/LaunchAgents/ksdaemon.ru.node-js.plist

Если кому надо, можно скачать мои готовые plist’ы:
ksdaemon.ru.nginx.plist
ksdaemon.ru.php-fpm.plist
ksdaemon.ru.node-js.plist

Ну вот собственно и все. Теперь сам не забуду, а может и еще кому-то пригодится 🙂