Как развернуть приложение Meteor.js в Ubuntu 14.04 с помощью Nginx
О Meteor.js
структурирование кода приложения и совместное использование кода). Это также решает проблему необходимости сложного процесса развертывания между режимом разработки, в котором разработчики кодируют и отлаживают, и рабочим режимом, достаточно безопасным для общедоступной версии приложение. Платформа Meteor позволяет тесно связать клиентский код и серверный код, а также разработку и производство. Вероятно, это самый простой способ для клиентских разработчиков начать работу над серверным кодом!
Чтобы увидеть это в действии, вы можете просмотреть вступительное видео на веб-сайте Meteor.
Meteor.js позволяет разрабатывать такие проекты, как веб-сайт (веб-приложение), приложение веб-браузера на основе HTML5 (с использованием AppCache) или мобильное приложение (посредством интеграции с PhoneGap). Все, что вам нужно, это знание Javascript и HTML. Meteor включает поддержку MongoDB (база данных NoSQL). В Atmosphere размещаются пакеты, которые могут предоставить полные строительные блоки для вашего приложения, чтобы еще больше ускорить разработку.
В конце этого урока у нас будет:
- Установлен Meteor.js
- Создан пакет развертывания, содержащий все приложение Meteor в готовом для производства формате (без веб-сервера и серверной части базы данных)
- Установил Nginx в качестве нашего веб-сервера для передачи HTTP-запросов в Meteor.
- Установил MongoDB в качестве механизма базы данных
- Управлял нашим приложением с помощью Upstart
- Настроено ежедневное резервное копирование базы данных Meteor.
В этом руководстве, если у вас еще нет собственного приложения Meteor, вы можете использовать пример приложения \Todo List с веб-сайта Meteor.
Прежде чем вы начнете
Вы должны иметь:
-
An existing Meteor app on a separate development computer (you can view the example “Todo List” app here; instructions are provided later in the tutorial)
-
A fresh Ubuntu 14.04 server; existing Meteor installations should work in most cases
-
root access to the server to execute commands
-
Updated package lists. Execute:
apt-get update
-
Replace todos.net with the domain name you are actually using (or leave it if you don’t have a domain and will be using an IP address instead)
-
Replace todos (without .net) with the name of your application
Шаг 1 — Настройка веб-сервера Nginx
Мы установим и настроим Nginx, потому что он позволяет нам шифровать веб-трафик с помощью SSL — функции, которую не предоставляет встроенный веб-сервер Meteor. Nginx также позволит нам обслуживать другие веб-сайты на том же сервере, а также фильтровать и регистрировать трафик.
В нашей конфигурации мы защитим наш сайт сертификатом SSL и перенаправим весь трафик с HTTP на HTTPS. Мы также будем использовать несколько новых методов обеспечения безопасности для повышения безопасности соединения SSL.
Для установки Nginx выполняем:
apt-get install nginx
Создайте файл конфигурации виртуального хоста в /etc/nginx/sites-available
.
Ниже приведен аннотированный файл конфигурации, который мы можем создать как /etc/nginx/sites-available/todos
со следующим содержимым. Пояснения ко всем параметрам конфигурации включены в комментарии в файле:
server_tokens off; # for security-by-obscurity: stop displaying nginx version
# this section is needed to proxy web-socket connections
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# HTTP
server {
listen 80 default_server; # if this is not a default server, remove "default_server"
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/html; # root is irrelevant
index index.html index.htm; # this is also irrelevant
server_name todos.net; # the domain on which we want to host the application. Since we set "default_server" previously, nginx will answer all hosts anyway.
# redirect non-SSL to SSL
location / {
rewrite ^ https://$server_name$request_uri? permanent;
}
}
# HTTPS server
server {
listen 443 ssl spdy; # we enable SPDY here
server_name todos.net; # this domain must match Common Name (CN) in the SSL certificate
root html; # irrelevant
index index.html; # irrelevant
ssl_certificate /etc/nginx/ssl/todos.pem; # full path to SSL certificate and CA certificate concatenated together
ssl_certificate_key /etc/nginx/ssl/todos.key; # full path to SSL key
# performance enhancement for SSL
ssl_stapling on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
# safety enhancement to SSL: make sure we actually use a safe cipher
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK';
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
add_header Strict-Transport-Security "max-age=31536000;";
# If your application is not compatible with IE <= 10, this will redirect visitors to a page advising a browser update
# This works because IE 11 does not present itself as MSIE anymore
if ($http_user_agent ~ "MSIE" ) {
return 303 https://browser-update.org/update.html;
}
# pass all requests to Meteor
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # allow websockets
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-For $remote_addr; # preserve client IP
# this setting allows the browser to cache the application in a way compatible with Meteor
# on every applicaiton update the name of CSS and JS file is different, so they can be cache infinitely (here: 30 days)
# the root path (/) MUST NOT be cached
if ($uri != '/') {
expires 30d;
}
}
}
Если вы хотите адаптировать файл конфигурации к своим потребностям и получить дополнительные пояснения, ознакомьтесь с этим руководством по виртуальным хостам Nginx.
Как видно из файла конфигурации виртуального хоста, Nginx будет ожидать действительный сертификат SSL и ключ в /etc/nginx/ssl
. Нам нужно создать этот каталог и защитить его:
mkdir /etc/nginx/ssl
chmod 0700 /etc/nginx/ssl
Затем мы можем создать файлы, содержащие сертификат (и сертификат цепочки, если требуется) и ключ в местах, которые мы определили в конфигурации выше:
- сертификат:
/etc/nginx/ssl/todos.pem
- ключ:
/etc/nginx/ssl/todos.key
Если у вас еще нет SSL-сертификата и ключа, вам следует создать самозаверяющий сертификат с помощью этого руководства по созданию самозаверяющих SSL-сертификатов для Nginx. Помните, что вы захотите использовать те же имена из файла конфигурации, например, todos.key в качестве имени ключа и todos.pem в качестве имени сертификата. Хотя самозаверяющий сертификат подходит для тестирования, рекомендуется использовать коммерческий подписанный сертификат для производственного использования. Самоподписанный сертификат вызовет предупреждения Nginx, связанные с ssl_stapling, и предупреждение системы безопасности в веб-браузере.
Когда вы закончите создание или получение сертификата, убедитесь, что у вас есть файлы todos.pem
и todos.key
, упомянутые выше.
Далее мы должны отключить виртуальный хост по умолчанию:
rm /etc/nginx/sites-enabled/default
И включите наш Meteor vhost:
ln -s /etc/nginx/sites-available/todos /etc/nginx/sites-enabled/todos
Проверьте, что конфигурация vhost не содержит ошибок (вы увидите ошибку, связанную с ssl_stapling, если у вас есть самозаверяющий сертификат; это нормально):
nginx -t
Если все выглядит хорошо, мы можем применить изменения к Nginx:
nginx -s reload
На этом этапе вы можете использовать свой веб-браузер для посещения https://todos.net (или вашего IP-адреса). Он покажет нам 502 Bad Gateway. Это нормально, потому что у нас пока нет запущенного Meteor!
Шаг второй — настройка базы данных MongoDB
Мы установим MongoDB из обычного репозитория Ubuntu. Стандартная конфигурация должна подойти. Для подключения к базе данных не требуется аутентификация, но подключение возможно только с локального хоста. Это означает, что никакие внешние подключения невозможны, и, следовательно, база данных безопасна, пока у нас нет ненадежных пользователей с доступом по SSH к системе.
Установите пакет сервера MongoDB:
apt-get install mongodb-server
Это все, что нам нужно сделать, чтобы запустить MongoDB. Чтобы убедиться, что доступ с внешних хостов невозможен, мы выполняем следующее, чтобы убедиться, что MongoDB привязан к 127.0.0.1. Проверьте с помощью этой команды:
netstat -ln | grep -E '27017|28017'
Ожидаемый результат:
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:28017 0.0.0.0:* LISTEN
unix 2 [ ACC ] STREAM LISTENING 6091441 /tmp/mongodb-27017.sock
Чтобы иметь доступ к ежедневным резервным копиям на случай, если что-то пойдет не так, мы можем дополнительно установить простую команду в качестве ежедневного задания cron. Создайте файл /etc/cron.d/mongodb-backup
:
@daily root mkdir -p /var/backups/mongodb; mongodump --db todos --out /var/backups/mongodb/$(date +'\%Y-\%m-\%d')
Шаг 3 — Установка приложения Meteor
Во-первых, нам нужно установить Node.js. Поскольку для Meteor обычно требуется более новая версия Node.js, чем та, что доступна в стандартном репозитории, мы будем использовать собственный PPA-репозиторий (на момент написания статьи Ubuntu 14.04 предоставляет nodejs=0.10.25~dfsg2-2ubuntu1, а Meteor 0.8 .3 требуется Node.js 0.10.29 или новее).
Выполните следующее, чтобы добавить PPA с Node.js, и подтвердите, нажав Enter:
add-apt-repository ppa:chris-lea/node.js
Выход:
Evented I/O for V8 javascript. Node's goal is to provide an easy way to build scalable network programs
More info: https://launchpad.net/~chris-lea/+archive/ubuntu/node.js
Press [ENTER] to continue or ctrl-c to cancel adding it
gpg: keyring `/tmp/tmphsbizg3u/secring.gpg' created
gpg: keyring `/tmp/tmphsbizg3u/pubring.gpg' created
gpg: requesting key C7917B12 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmphsbizg3u/trustdb.gpg: trustdb created
gpg: key C7917B12: public key "Launchpad chrislea" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
OK
Теперь мы должны обновить кеш репозитория, после чего мы можем установить Node.js и npm (менеджер пакетов Node.js):
apt-get update
apt-get install nodejs
Хорошей практикой является запуск нашего приложения Meteor от имени обычного пользователя. Поэтому мы создадим нового системного пользователя специально для этой цели:
adduser --disabled-login todos
Выход:
Adding user `todos' ...
Adding new group `todos' (1001) ...
Adding new user `todos' (1001) with group `todos' ...
Creating home directory `/home/todos' ...
Copying files from `/etc/skel' ...
Changing the user information for todos
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
Шаг четвертый — настройка Upstart
Теперь мы готовы создать этот учебник.
Создайте файл /etc/init/todos.conf
. Еще раз, это аннотировано в строке:
# upstart service file at /etc/init/todos.conf
description "Meteor.js (NodeJS) application"
author "Daniel Speichert <daniel@speichert.pro>"
# When to start the service
start on started mongodb and runlevel [2345]
# When to stop the service
stop on shutdown
# Automatically restart process if crashed
respawn
respawn limit 10 5
# we don't use buil-in log because we use a script below
# console log
# drop root proviliges and switch to mymetorapp user
setuid todos
setgid todos
script
export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export NODE_PATH=/usr/lib/nodejs:/usr/lib/node_modules:/usr/share/javascript
# set to home directory of the user Meteor will be running as
export PWD=/home/todos
export HOME=/home/todos
# leave as 127.0.0.1 for security
export BIND_IP=127.0.0.1
# the port nginx is proxying requests to
export PORT=8080
# this allows Meteor to figure out correct IP address of visitors
export HTTP_FORWARDED_COUNT=1
# MongoDB connection string using todos as database name
export MONGO_URL=mongodb://localhost:27017/todos
# The domain name as configured previously as server_name in nginx
export ROOT_URL=https://todos.net
# optional JSON config - the contents of file specified by passing "--settings" parameter to meteor command in development mode
export METEOR_SETTINGS='{ "somesetting": "someval", "public": { "othersetting": "anothervalue" } }'
# this is optional: http://docs.meteor.com/#email
# commented out will default to no email being sent
# you must register with MailGun to have a username and password there
# export MAIL_URL=smtp://postmaster@mymetorapp.net:password123@smtp.mailgun.org
# alternatively install "apt-get install default-mta" and uncomment:
# export MAIL_URL=smtp://localhost
exec node /home/todos/bundle/main.js >> /home/todos/todos.log
end script
В этом файле конфигурации следует обратить внимание на параметр METEOR_SETTINGS
. Если вы используете meteor --settings config.json
при запуске режима разработки Meteor, вам следует вставить содержимое config.json
в качестве переменной в METEOR_SETTINGS
.
MAIL_URL
должен быть действительным URL-адресом SMTP, только если вы планируете использовать пакет электронной почты Meteor. Вы можете использовать MailGun (как рекомендует Meteor), локальный почтовый сервер и т. д.
Как видно из файла, журнал будет сохранен в /home/todos/todos.log.
Этот файл не будет ротироваться и БУДЕТ РАСТАТЬ со временем. Это хорошая идея, чтобы следить за этим. В идеале в нем не должно быть много контента (ошибок). При желании вы можете настроить ротацию журнала или заменить >>
на >
в конце скриптов Upstart, чтобы перезаписать весь файл, а не добавлять его в конец.
Пока не запускайте эту службу, так как у нас еще нет реальных файлов приложения Meteor!
Шаг пятый — развертывание приложения Meteor
Необязательно: если у вас еще нет проекта Meteor
Если у вас еще нет проекта Meteor и вы хотели бы использовать демо-приложение, это не проблема!
Сделайте следующий шаг на своем домашнем компьютере или на сервере Linux для разработки. Команды могут различаться в зависимости от вашей ОС. Перейдите в свою домашнюю папку:
cd ~
Сначала установите разрабатываемую версию Meteor:
curl https://install.meteor.com | /bin/sh
Затем создайте приложение из примера под названием Todo List:
meteor create --example todos
Теперь войдите в каталог вашего приложения, и вы готовы продолжить:
cd todos
Все проекты Метеор
Пришло время создать пакет рабочей версии из нашего приложения Meteor. Следующие команды должны быть выполнены на вашем домашнем компьютере или сервере разработки Linux, где бы ни находилось ваше приложение Meteor. Перейдите в каталог вашего проекта:
cd /app/dir
И выполните:
meteor build .
Это создаст архивный файл вида todos.tar.gz
в каталоге /app/dir
. Скопируйте этот файл в свой каталог ~
в вашей капле.
scp todos.tar.gz root@todos.net:~
Теперь вернитесь к своей капле. Создайте каталог проекта и переместите в него архивный файл проекта. Обратите внимание, что это домашняя папка пользователя проекта, которого мы создали ранее, а не ваша корневая домашняя папка:
mkdir /home/todos
mv todos.tar.gz /home/todos
Перейдите в каталог проекта и распакуйте его:
cd /home/todos
tar -zxf todos.tar.gz
Взгляните на README проекта:
cat /home/todos/bundle/README
В комплект входит файл README
с содержимым:
This is a Meteor application bundle. It has only one external dependency:
Node.js 0.10.29 or newer. To run the application:
$ (cd programs/server && npm install)
$ export MONGO_URL='mongodb://user:password@host:port/databasename'
$ export ROOT_URL='http://example.com'
$ export MAIL_URL='smtp://user:password@mailhost:port/'
$ node main.js
Use the PORT environment variable to set the port where the
application will listen. The default is 80, but that will require
root on most systems.
Find out more about Meteor at meteor.com.
Этот рецепт отражен в нашем файле /etc/init/todos.conf
. В README упоминается еще одна вещь, которую нам нужно сделать.
Теперь нам нужно установить некоторые необходимые модули npm. Чтобы иметь возможность собрать некоторые из них, нам также нужно установить g++ и сделать:
apt-get install g++ make
cd /home/todos/bundle/programs/server
npm install
Вы должны увидеть такой вывод:
npm WARN package.json meteor-dev-bundle@0.0.0 No description
npm WARN package.json meteor-dev-bundle@0.0.0 No repository field.
npm WARN package.json meteor-dev-bundle@0.0.0 No README data
> fibers@1.0.1 install /home/todos/bundle/programs/server/node_modules/fibers
> node ./build.js
`linux-x64-v8-3.14` exists; testing
Binary is fine; exiting
underscore@1.5.2 node_modules/underscore
semver@2.2.1 node_modules/semver
source-map-support@0.2.5 node_modules/source-map-support
└── source-map@0.1.29 (amdefine@0.1.0)
fibers@1.0.1 node_modules/fibers
Причина, по которой нам нужно это сделать, заключается в том, что наш пакет приложений не содержит модулей и библиотек, зависящих от платформы.
Мы почти готовы запустить приложение, но так как мы работали с файлами от имени пользователя root, и они должны принадлежать пользователю todos
, нам нужно обновить владельца файла каталог проекта:
chown todos:todos /home/todos -R
Шаг шестой — шоу-тайм
На данный момент у нас есть все необходимое для запуска нашего приложения Meteor:
- Среда Node.js установлена
- Приложение установлено в каталоге своего проекта
- Служба Upstart, настроенная для запуска приложения
- База данных MongoDB
- Прокси-сервер Nginx перед нашим приложением Meteor для обеспечения шифрования SSL
Чтобы запустить наше приложение, давайте выполним эту команду из каталога проекта:
start todos
Теперь вы сможете просматривать свое приложение в браузере по адресу https://todos.net.
Повторное развертывание приложения
Когда вы вносите изменения в режиме разработки (а вы это сделаете, ведь мы же разработчики!), вы можете просто повторить Пятый шаг (начиная с meteor build
) и пройти большую часть шагов до тех пор, пока restart команду todos
, которая перезагрузит ваше приложение через Upstart.
Таким образом, вы можете отправить новую версию без простоев. Клиенты (посетители вашего веб-сайта) автоматически получат новую версию кода и обновят свою страницу — в этом волшебство Meteor!
Если вы хотите проверить это, вы можете внести простое изменение в текст на странице todos/client/todos.html
в разрабатываемой копии приложения на домашнем компьютере или сервере разработки.
Сервер разработки:
Строить:
meteor build /app/dir
Загрузить:
scp todos.tar.gz root@todos.net:/home/todos
Рабочий сервер:
Расширять:
tar -zxf /home/todos/todos.tar.gz
Переместите в папку проекта:
cd /home/todos/bundle/programs/server
Обновите модули npm (вы можете увидеть несколько предупреждений):
npm install
Перезапустите приложение:
restart todos
Поиск неисправностей
Если что-то пойдет не так, вот несколько советов, где искать проблемы:
- Проверьте
/home/todos/todos.log
, если ваше приложение запускается и закрывается; он должен выдать соответствующее сообщение об ошибке (например, в случае ошибки программирования). - Проверьте
/var/log/nginx/error.log
, если вы видите ошибку HTTP вместо своего приложения. - Проверьте
/var/log/mongodb/mongodb.log
, если считаете, что с базой данных может возникнуть проблема.
Наконец, проверьте, все ли службы запущены:
status todos
service nginx status
status mongodb