Поиск по сайту:

Как развернуть приложение 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