如何部署与Nginx的在Ubuntu 14.04一Meteor.js应用

部署Nginx的和MongoDB在Ubuntu 14.04一Meteor.js应用。本教程介绍如何构建和部署使用Meteor框架您的JavaScript应用程序的生产就绪版本。

关于Meteor.js

Meteor.js是JavaScript的一个框架,允许Web开发人员编写一次JavaScript代码和重用客户端和服务器端。 这可能是由于Meteor独特的构建过程(阅读更多关于构建应用程序代码和代码共享 )。 这也解决了需要发展模式 ,开发代码和调试和生产方式之间有着复杂的部署过程中的问题,即是面向公众的版本的应用程序足够安全。 Meteor框架为客户端代码和服务器代码以及开发和生产密切相关提供了一种方法。 这可能是客户端开发人员开始处理服务器端代码的最简单方法!

要看到这个动作,你可能要查看的介绍视频上Meteor的网站。

Meteor.js允许您开发项目,如网站(Web应用程序),基于HTML5的Web浏览器应用程序(使用AppCache)或移动应用程序(通过与PhoneGap集成)。 所有你需要的是Javascript和HTML的知识。 Meteor包括MongoDB的(一个的NoSQL数据库)。支持气氛的主机套餐,可为您的应用程序更是加快发展提供完整的基石。

在本教程结尾处,我们将有:

  • 安装Meteor.js
  • 以生产就绪格式创建包含整个Meteor应用程序的部署包(减去Web服务器和数据库后端)
  • 安装Nginx的为我们的网络服务器通过HTTP请求Meteor
  • 安装MongoDB作为我们的数据库引擎
  • 管理我们的应用Upstart
  • 为Meteor数据库配置每日数据库备份

在本教程中,如果你没有自己的应用程序Meteor是,您可以使用来自该“待办事项列表”的示例应用程序Meteor网站

在你开始之前

你应该有:

  • 独立开发的计算机上现有的Meteor应用程序(可以查看例如“待办事项列表”的应用在这里 ,在本教程后面提供的说明)
  • 新鲜的Ubuntu 14.04服务器; 现有的Meteor安装应该在大多数情况下工作
  • root权限执行命令的服务器
  • 更新的软件包列表。 执行:

    apt-get更新

  • 与你实际使用的域名替换todos.net(或保留它,如果你没有一个域,将使用IP地址代替)

  • 与应用程序的名称替换待办事项 (不包括.NET)

第1步 - 设置Nginx Web服务器

我们将安装和设置Nginx,因为它允许我们用SSL加密网络流量,这是Meteor的内置Web服务器不提供的一个功能。 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证书和密钥已经,您现在应该创建一个使用这个自签名证书上的Nginx创建自签署的SSL证书教程 请记住,你会想从配置文件使用相同的名称,如todos.key作为密钥名称,todos.pem作为证书名称。 虽然自签名证书适合测试,但建议使用商业签名的证书进行生产使用。 自签名证书将引发连接到ssl_stapling的Nginx警告,以及Web浏览器中的安全警告。

当您完成创建或获取您的证书,请确保您有todos.pemtodos.key上述文件。

接下来,我们应该禁用默认vhost:

rm /etc/nginx/sites-enabled/default

并启用我们的Meteorvhost:

ln -s /etc/nginx/sites-available/todos /etc/nginx/sites-enabled/todos

测试vhost配置是否无错(如果您有自签名证书,您将看到与ssl_stapling相关的错误;这是可以的):

nginx -t

如果一切看起来不错,我们可以应用对Nginx的更改:

nginx -s reload

在这一点上,你可以使用你的Web浏览器访问https://开头todos.net(或IP地址)。 它会告诉我们502网关错误 这是好的,因为我们还没有Meteor运行!

第二步 - 设置MongoDB数据库

我们将从常规的Ubuntu存储库安装MongoDB。 标准配置应该很好。 无需身份验证即可连接到数据库,但只能从localhost进行连接。 这意味着没有外部连接是可能的,因此数据库是安全的,只要我们没有不受信任的用户对系统的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而Meteor0.8.3要求Node.js的0.10.29或更新版本)。

执行以下操作以使用Node.js添加PPA,然后按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 package manager):

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

现在,我们准备创建Upstart服务来管理我们的Meteor应用程序。 Upstart将在启动时自动启动应用程序,并在死亡时重新启动Meteor。 你可以阅读更多关于创建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必须是有效的SMTP地址 ,如果你打算使用Meteor的电子邮件软件包。 您可以使用MailGun(由Meteor推荐),本地邮件服务器等。

我们可以在文件中看到,日志将被保存到/home/ todos / todos .log.此文件将不会旋转随时间增长 这是一个好主意,保持眼睛。 理想情况下,应该不会有很多内容(错误)。 或者,您可以设置日志轮换或替换>>>为了覆盖,而不是追加到它的结束了整个文件Upstart脚本的结尾。

不要启动这项服务,因为我们没有实际的Meteor应用程序文件到位!

第五步 - 部署Meteor应用程序

可选:如果您还没有Meteor项目

如果你还没有一个Meteor项目,并希望使用演示应用程序,这不是一个问题!

做你的家用电脑或开发的Linux服务器上的这一步。命令可能取决于您的操作系统。 移至您的主文件夹:

cd ~

首先安装Meteor的开发版本:

curl https://install.meteor.com | /bin/sh

然后创建一个从一个实例的应用程序,名为待办事项列表

meteor create --example todos

现在输入您的应用程序的目录,您可以继续:

cd todos

所有Meteor项目

现在是从Meteor应用程序创建生产版本捆绑包的时候了。 以下命令应您的家用电脑或开发的Linux服务器 ,无论您的应用程序Meteor住上执行。 转到您的项目目录:

cd /app/dir

并执行:

meteor build .

这将创建像一个存档文件todos.tar.gz在目录/app/dir 将此文件复制到你的~目录上的Droplet。

scp todos.tar.gz root@todos.net:~

现在回到你的Droplet。创建一个项目目录,归档项目文件移动到它。 请注意,这是我们以前创建的, 不是根主文件夹项目用户主文件夹:

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

第六步 - Showtime

在这一点上,我们拥有运行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