Развертывание приложения Node.js с помощью Systemd и Nginx
Arch Linux, VPS | Комментировать запись
При развертывании веб-приложения может возникнуть желание просто использовать те же настройки, которые были использованы в процессе разработки, то есть запустить в терминале ruby app.rb или node server.js. Это очень легко и удобно; кроме того, можно использовать screen, tmux or nohup, чтобы сервер продолжал работать даже тогда, когда SSH-сессия оборвалась. Но это очень опасно: что, если сервер выйдет из строя, а администратора не будет на месте, чтобы перезапустить его?
Некоторые используют для этих целей forever и crontab. В данном руководстве представлен другой подход, более ошибкоустойчивый и в то же время более сложный. При помощи демона systemd (доступен в Arch и Fedora) можно управлять веб-приложениями (логами, аптаймом, ресурсами и безопасностью) через контрольные группы (cgroups).
В данном руководстве используется простое приложение Node.js, но его действия применимы к большинству других приложений (Ruby, Python и т.д.). Для приложений PHP рекомендуется использовать более специализированные LAMP stack или LEMP stack.
Руководство приводит команды для Fedora и Arch; во избежание путаницы везде сделаны необходимые пометки. Если же таковой пометки нет – команда подходит для обеих систем. Кроме того, рекомендуется полностью прочесть руководство, прежде чем приступить к его выполнению, чтобы получить представление о том, к какому результату оно приводит и подходит ли оно в вашей ситуации.
Предварительные требования к системе
- Демон systemd. Серверы Arch Linux и Fedora поставляются с ним по молчанию.
- Nginx как обратный прокси http и сервер WebSocket.
- Git (для установки nvm и загрузки приложения).
- Root-доступ к серверу. Можно также войти в систему как обычный пользователь с расширенными привилегиями и выполнять все команды через sudo, su – или sudo su.
Установка пакетов
Arch:
# pacman -Sy
# pacman -S nginx git
Fedora:
# yum install nginx git
Предварительные требования к приложению
Настройки, перечисленные в данном разделе, можно изменить по собственному усмотрению, но они должны быть хорошо продуманы и установлены заранее.
Пользователь
Приложение должно работать на собственной учетной записи пользователя. Выберите имя (для простоты запоминания оно должно повторять имя приложения или как-либо отсылать к нему). В данном руководстве используется srv-node-sample.
# useradd -mrU srv-node-sample
Порт
Во избежание конфликта выберите сложный номер порта. В данном случае используется порт 15301.
Настройка приложения
Для начала установите все необходимое для запуска приложения. В случае с Node.js (а также Ruby, Python и т.д.) есть два варианта: использовать файлы среды выполнения системы или пользовательскую установку (например, nvm, rbenv, RVM, virtualenv и т.п.).
При использовании ноды системы
Arch:
# pacman -S nodejs
Fedora:
# yum install nodejs
Для пользовательской установки
Эту установку нужно выполнить в домашнем каталоге приложения, то есть в /home/srv-node-sample, потому проще всего войти в сеть как ранее созданный пользователь для приложения:
# su srv-node-sample
$ cd
$ curl https://raw.github.com/creationix/nvm/master/install.sh | sh
$ source ~/.nvm/nvm.sh
$ nvm install 0.10
$ nvm alias default 0.10
Затем запишите, куда был установлен бинарный файл node.
$ which node
/home/srv-node-sample/.nvm/v0.10.22/bin/node
Развертывание приложения
Оставаясь в системе как пользователь srv-node-sample, разверните код (это всего лишь пример, ваш код, конечно, может отличаться):
$ git clone git@server.company.tld:user/repo.git .
$ npm install
$ grunt deploy
В данном руководстве используется следующий пример приложения:
js
var http = require('http');
http.createServer(function(req, res) {
res.end('<h1>Hello, world.</h1>');
}).listen(15301);
Вернитесь в учетную запись root:
$ exit
Настройка Nginx
Данное руководство лишь вкратце охватывает необходимые настройки; за дополнительной информацией обращайтесь к мануалу Nginx.
В блок server (виртуальный хост Nginx) поместите следующее:
location / {
proxy_pass http://localhost:15301/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Затем настройте демон:
# systemctl enable nginx
# systemctl restart nginx
Настройка Systemd
В /etc/systemd/system/node-sample.service создайте файл service для приложения.
В него нужно внести несколько переменных:
- [node binary] – это выход оператора which node пользователя srv-node-sample (смотрите раздел «Настройка приложения»), то есть путь /usr/bin/node или the ~/.nvm/…
- [main file] – главный файл приложения. В данном случае это index.js.
- Не забудьте заменить srv-node-sample именем своего приложения!
[Service]
ExecStart=[node binary] /home/srv-node-sample/[main file]
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-sample
User=srv-node-sample
Group=srv-node-sample
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
Запустите сервис:
# systemctl enable node-sample
# systemctl start node-sample
Использование Systemd
Состояние
# systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago
Main PID: 7213 (node)
CGroup: name=systemd:/system/node-sample.service
└─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod...
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
Логи
# journalctl -u node-sample
-- Logs begin at Thu 2013-11-21 19:05:17 UTC, end at Fri 2013-11-22 01:12:15 UTC. --
Nov 22 01:12:15 d02 systemd[1]: Starting node-sample.service...
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
Nov 22 01:12:30 d02 node-sample[7213]: Sample message from application
Перезапуск, остановка и т.п.
Принудительная перезагрузка:
# systemctl restart node-sample
Остановка приложения
# systemctl stop node-sample
Приложение будет автоматически перезапущено в случае ошибки.
# systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:12:15 UTC; 35s ago
Main PID: 7213 (node)
CGroup: name=systemd:/system/node-sample.service
└─7213 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod...
Nov 22 01:12:15 d02 systemd[1]: Started node-sample.service.
# kill 7213
# systemctl status node-sample
node-sample.service
Loaded: loaded (/etc/systemd/system/node-sample.service; enabled)
Active: active (running) since Fri 2013-11-22 01:54:37 UTC; 6s ago
Main PID: 7236 (node)
CGroup: name=systemd:/system/node-sample.service
└─7236 /home/srv-node-sample/.nvm/v0.10.22/bin/node /home/srv-nod...
Nov 22 01:54:37 d02 systemd[1]: node-sample.service holdoff time over, sch...t.
Nov 22 01:54:37 d02 systemd[1]: Stopping node-sample.service...
Nov 22 01:54:37 d02 systemd[1]: Starting node-sample.service...
Nov 22 01:54:37 d02 systemd[1]: Started node-sample.service.
Как видите, PID изменился, а значит, приложение было остановлено и перезапущено.
Веб-сокеты
Если приложение использует веб-сокеты (websockets), внесите в конфигурации Nginx следующие строки:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
После этого нужно перезапустить Nginx:
# systemctl reload nginx
Готово!
Tags: Arch Linux, Fedora, Git, Linux, NGINX, Node.js, NVM, systemd, VPS