如何迁移解析应用程序在Ubuntu 14.04服务器解析

解析是移动后端即服务平台,正在关闭在2017年一月;幸运的是,已经解析发布了一个开源的API叫做解析服务器。解析服务器正在积极发展,并很可能吸引了大量开发者社区。它可以被部署到一个范围运行的Node.js和MongoDB环境。本指南的重点是现有的预解析应用程序迁移到解析服务器在Ubuntu 14.04上运行的独立实例。

介绍

Parse是一个移动后端服务平台,自2013年起由Facebook拥有。2016年1月,Parse宣布其托管服务将于2017年1月28日完全关闭。

幸运的是,解析也发布了一个开源的API服务器 ,以托管服务的API兼容,称为解析服务器 Parse Server正在积极开发中,似乎可能吸引大型开发者社区。 它可以部署到运行Node.js和MongoDB的一系列环境中。

本指南专注于将先前存在的Parse应用程序迁移到在Ubuntu 14.04上运行的Parse Server的独立实例。 它使用TLS / SSL加密所有连接,使用由Let's Encrypt提供的证书,一个新的证书颁发机构提供免费证书。 它包括DigitalOcean和Ubuntu 14.04特定的一些细节,但应广泛适用于运行最近Debian派生的GNU / Linux发行版的系统。

警告:强烈建议这个程序首先与应用程序的开发或测试版采用了面向用户的应用程序的生产尝试之前测试。 它还强烈建议您请阅读本指南与官方迁移文档

先决条件

本指南基于如何在Ubuntu 14.04运行解析服务器 它需要以下:

  • 一个Ubuntu 14.04服务器上,使用非root配置的sudo用户
  • Node.js 5.6.x
  • MongoDB 3.0.x
  • 指向服务器的域名
  • 要迁移的Parse应用程序

目标服务器应该有足够的存储空间来处理所有应用程序的数据。 由于Parse会压缩数据,因此他们正式建议您至少配置托管应用程序使用的存储空间的10倍。

第1步 - 安装让我们加密和检索证书

Let's Encrypt是一个新的证书颁发机构,提供了一种获取免费TLS / SSL证书的简单方法。 因为证书是必要的,以确保数据的MongoDB的同时迁移和你的解析服务器API终点,我们将通过检索一个具有开始letsencrypt客户端。

安装让我们加密和依赖

您必须拥有或控制您希望使用证书的注册域名。 如果您还没有注册域名,您可以向其中一个域名注册商(例如Namecheap,GoDaddy等)注册一个域名。

如果你还没有准备好,一定要创建一条A记录指向你自己的域名服务器的公网IP地址。 这是必需的,因为Let's Encrypt验证您拥有它为其颁发证书的域。 例如,如果你想获得一个证书example.com ,该域必须解析到服务器的验证过程工作。

有关此过程的详细信息,请参阅如何设置主机名与DigitalOcean怎么点从常见的域名注册商DigitalOcean域名服务器

通过确保在开始gitbc包安装:

sudo apt-get -y install git bc

接下来,克隆letsencrypt从GitHub到库中/opt/letsencrypt /opt/目录是不是从发行版的官方包仓库安装软件提供一个标准的位置:

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

更改为letsencrypt目录:

cd /opt/letsencrypt

检索初始证书

运行letsencrypt的独立插件:

./letsencrypt-auto certonly --standalone

系统会提示您回答几个问题,包括您的电子邮件地址,同意服务条款以及证书的域名。 完成后,您会收到类似以下内容的注释:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/your_domain_name/fullchain.pem. Your cert will expire
   on 2016-05-16. To obtain a new version of the certificate in the
   future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

注意证书的路径和到期日期,在示例输出中突出显示。 您的证书文件现在应该在现有/etc/letsencrypt/ your_domain_name /

设置让我们加密自动续订

警告:您可以安全地完成本指南,而不必担心证书更新,但你需要解决它的任何长寿命的生产环境。

您可能已经注意到,您的Let's Encrypt证书将在90天后到期。 这是Let's Encrypt方法的一个故意功能,旨在最小化受损证书在出现问题时可以存在的时间。

让我们加密仍处于测试阶段。 计划有更好的自动更新功能,但是在此期间,您将不得不手动重复证书检索过程,或使用预定的脚本为您处理它。 自动化这一过程的详细信息在如何使用让我们在Ubuntu 14.04加密安全Nginx的 ,特别是在部分设置自动续约

第2步 - 配置MongoDB进行迁移

Parse为现有应用程序提供了一个迁移工具。 为了使用它,我们需要打开MongoDB到外部连接,并用来自Let's Encrypt的TLS / SSL证书的副本来保护它。 通过结合启动fullchain1.pemprivkey1.pem到一个新的文件/etc/ssl

sudo cat /etc/letsencrypt/archive/domain_name/{fullchain1.pem,privkey1.pem} | sudo tee /etc/ssl/mongo.pem

在更新您的Let's Encrypt证书后,您必须重复上述命令。 如果配置让我们加密证书的自动更新,请记住包括此操作。

确保mongo.pemMongoDB的用户所拥有,并且仅可由它的主人:

sudo chown mongodb:mongodb /etc/ssl/mongo.pem
sudo chmod 600 /etc/ssl/mongo.pem

现在,打开/etc/mongod.confnano (或您选择的文本编辑器):

sudo nano /etc/mongod.conf

在这里,我们将做几个重要的更改。

首先,寻找bindIp在该行net:段,并告诉MongoDB中通过改变所有地址听127.0.0.10.0.0.0 在下面,将SSL配置添加到同一部分:

/etc/mongod.conf
# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongo.pem

接下来,在# security ,启用客户端授权:

/etc/mongod.conf
# security
security:
  authorization: enabled

最后,迁移工具要求我们在设置failIndexKeyTooLong参数为false

/etc/mongod.conf

setParameter:
  failIndexKeyTooLong: false

注:空格是在MongoDB中的配置文件,这是基于显著YAML 复制配置值时,请确保保留缩进。

退出并保存文件。

重新启动前mongod服务,我们需要添加一个用户与admin的角色。 连接到正在运行的MongoDB实例:

mongo --port 27017

创建管理员用户并退出。 请务必使用强密码所需的用户名和密码 ,以取代sammy

use admin
db.createUser({
  user: "sammy",
  pwd: "password",
  roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
exit

重新启动mongod服务:

sudo service mongod restart

第2步 - 从解析迁移应用程序数据

现在您有一个可远程访问的MongoDB实例,您可以使用Parse迁移工具将应用程序的数据传输到您的服务器。

为迁移工具配置MongoDB凭据

我们将从本地连接到我们的新管理员用户开始:

mongo --port 27017 --ssl --sslAllowInvalidCertificates --authenticationDatabase admin --username sammy --password

应提示您输入先前设置的密码。

连接后,选择数据库的名称以存储应用程序的数据。 例如,如果你要迁移名为待办事项应用程序,你可以使用todo 您还需要选择一个名为解析用户的另一强密码。

mongo外壳,给这个用户访问database_name

use database_name
db.createUser({ user: "parse", pwd: "password", roles: [ "readWrite", "dbAdmin" ] })

启动数据迁移过程

在浏览器窗口中,登录到Parse,然后打开应用程序的设置。 常规下,找到迁移按钮,单击它:

解析应用程序设置:常规:迁移

将提示您输入MongoDB连接字符串。 使用以下格式:

mongodb://parse:password@your_domain_name:27017/database_name?ssl=true

例如,如果您使用的是域example.com ,与用户parse ,密码foo和数据库名为todo ,您的连接字符串应该是这样的:

mongodb://parse:foo@example.com:27017/todo?ssl=true

不要忘了?ssl=true结尾,否则连接失败。 在对话框中输入连接字符串,如下所示:

解析应用程序:迁移对话框

点击开始迁移 您应该会看到将Parse托管数据库的快照复制到服务器的进度对话框,然后在拍摄快照后同步新数据。 该过程的持续时间将取决于要传送的数据的量,并且可以是实质的。

解析应用程序:迁移进度

解析应用程序:迁移过程

验证数据迁移

一旦完成,迁移过程将进入验证步骤。 不要最终完成迁移。 您首先要确保数据已实际传输,并测试Parse Server的本地实例。

解析应用程序:完成迁移,等待完成

返回到您的mongo外壳,并检查您的本地数据库。 通过访问数据库名称并检查它包含的藏品开始:

use database_name
show collections
Todo
_Index
_SCHEMA
_Session
_User
_dummy
system.indexes

您可以通过检查特定集合的内容.find()方法:

db.ApplicationName.find()
> db.Todo.find()
{ "_id" : "hhbrhmBrs0", "order" : NumberLong(1), "_p_user" : "_User$dceklyR50A", "done" : false, "_acl" : { "dceklyR50A" : { "r" : true, "w" : true } }, "_rperm" : [ "dceklyR50A" ], "content" : "Migrate this app to my own server.", "_updated_at" : ISODate("2016-02-08T20:44:26.157Z"), "_wperm" : [ "dceklyR50A" ], "_created_at" : ISODate("2016-02-08T20:44:26.157Z") }

您的具体输出将有所不同,但您应该会看到应用的数据。 满足条件后,退出mongo并返回到shell:

exit

第3步 - 安装和配置解析服务器和PM2

使用MongoDB中的应用程序数据,我们可以继续安装Parse Server本身,并与系统的其余部分集成。 我们会给解析服务器专用的用户,并使用名为PM2工具来配置它并确保它始终运行。

在全局安装解析服务器和PM2

使用npm安装parse-server程序,在pm2进程管理器,和他们的依赖,在全球范围:

sudo npm install -g parse-server pm2

创建专用解析用户和主目录

而不是运行的parse-server根目录sudo用户,我们将创建一个系统用户名为解析

sudo useradd --create-home --system parse

现在设置解析密码:

sudo passwd parse

系统将提示您输入密码两次。

现在,使用su命令成为解析用户:

sudo su parse

更改解析的主目录:

cd ~

写入或迁移云代码文件

创建云代码目录:

mkdir -p ~/cloud

编辑/home/parse/cloud/main.js

nano ~/cloud/main.js

出于测试目的,您可以粘贴以下内容:

/home/parse/cloud/main.js
Parse.Cloud.define('hello', function(req, res) {
  res.success('Hi');
});

或者,您可以通过从您的应用程序的设置在仪表盘解析云代码部分复制其迁移您的应用程序定义的任何云代码。

退出并保存。

检索键和写/home/parse/ecosystem.json

PM2是一个功能丰富的进程管理器,很受开发商的Node.js。 我们将使用pm2工具来配置我们的parse-server实例并保持运行在长期。

您需要检索应用程序的某些键。 在分析仪表盘,单击应用程序设置其次是安全和键

解析仪表板:应用程序设置:安全和密钥

这些中,只需要在应用程序的ID主密钥 其他(客户端的JavaScript,.NET和REST API密钥) 可能需要支持旧的客户端版本,但是,如果设置,将所有请求是必需的。 除非您有理由相信,否则您应该只使用应用程序ID和主密钥开始。

有了这些钥匙准备出手,编辑一个新的文件/home/parse/ecosystem.json

nano ecosystem.json

粘贴以下内容,更改配置值以反映您的MongoDB连接字符串,应用程序ID和主密钥:

{
  "apps" : [{
    "name"        : "parse-wrapper",
    "script"      : "/usr/bin/parse-server",
    "watch"       : true,
    "merge_logs"  : true,
    "cwd"         : "/home/parse",
    "env": {
      "PARSE_SERVER_CLOUD_CODE_MAIN": "/home/parse/cloud/main.js",
      "PARSE_SERVER_DATABASE_URI": "mongodb://parse:password@your_domain_name:27017/database_name?ssl=true",
      "PARSE_SERVER_APPLICATION_ID": "your_application_id",
      "PARSE_SERVER_MASTER_KEY": "your_master_key",
    }
  }]
}

所述env对象用于设置环境变量。 如果您需要配置其他键, parse-server也认识到以下变量:

  • PARSE_SERVER_COLLECTION_PREFIX
  • PARSE_SERVER_CLIENT_KEY
  • PARSE_SERVER_REST_API_KEY
  • PARSE_SERVER_DOTNET_KEY
  • PARSE_SERVER_JAVASCRIPT_KEY
  • PARSE_SERVER_DOTNET_KEY
  • PARSE_SERVER_FILE_KEY
  • PARSE_SERVER_FACEBOOK_APP_IDS

退出并保存ecosystem.json

现在,运行该脚本pm2

pm2 start ecosystem.json
...
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Process launched
┌───────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name      │ id │ mode │ pid  │ status │ restart │ uptime │ memory      │ watching │
├───────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ parse-wrapper │ 0  │ fork │ 3499 │ online │ 0       │ 0s     │ 13.680 MB   │  enabled │
└───────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

现在告诉pm2保存此进程列表:

pm2 save
[PM2] Dumping processes

进程列表pm2正在运行的分析用户现在应该被存放在/home/parse/.pm2

现在,我们需要确保parse-wrapper我们在前面定义的过程ecosystem.json在每次重新启动服务器时恢复。 幸运的是, pm2可以生成并在其自身的安装的脚本。

退出常规sudo用户:

exit

告诉pm2安装初始化脚本的Ubuntu,使用运行作为解析用户/home/parse作为其主目录:

sudo pm2 startup ubuntu -u parse --hp /home/parse/
输出
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Generating system init script in /etc/init.d/pm2-init.sh
[PM2] Making script booting at startup...
[PM2] -ubuntu- Using the command:
      su -c "chmod +x /etc/init.d/pm2-init.sh && update-rc.d pm2-init.sh defaults"
 System start/stop links for /etc/init.d/pm2-init.sh already exist.
[PM2] Done.

第4步 - 安装和配置Nginx

我们将使用Nginx的网络服务器提供一个反向代理 parse-server ,这样我们就可以服务于解析API安全地通过TLS / SSL。

安装nginx包:

sudo apt-get install -y nginx

开放/etc/nginx/sites-enabled/defaultnano (或您选择的编辑器):

sudo nano /etc/nginx/sites-enabled/default

将其内容替换为以下内容:

/ etc / nginx / sites-enabled / default
# HTTP - redirect all requests to HTTPS
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}

# HTTPS - serve HTML from /usr/share/nginx/html, proxy requests to /parse/
# through to Parse Server
server {
        listen 443;
        server_name your_domain_name;

        root /usr/share/nginx/html;
        index index.html index.htm;

        ssl on;
        # Use certificate and key provided by Let's Encrypt:
        ssl_certificate /etc/letsencrypt/live/your_domain_name/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_domain_name/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

        # Pass requests for /parse/ to Parse Server instance at localhost:1337
        location /parse/ {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://localhost:1337/;
                proxy_ssl_session_reuse off;
                proxy_set_header Host $http_host;
                proxy_redirect off;
        }

        location / {
                try_files $uri $uri/ =404;
        }
}

退出编辑器并保存文件。 重新启动Nginx以使更改生效:

sudo service nginx restart
 * Restarting nginx nginx
   ...done.

第5步 - 测试解析服务器

在这个阶段,你应该有以下:

  • 由Let's Encrypt提供的TLS / SSL证书
  • MongoDB,使用Let's Encrypt证书保护
  • parse-server端口1337 解析用户下运行,与您的应用程序所期望的按键配置
  • pm2管理parse-server过程中, 分析用户之下,启动脚本重新启动pm2开机
  • nginx ,安全的让我们的加密证书,并配置代理服务器连接到https:// your_domain_name /parseparse-server实例

现在应该可以测试读取,写入,并使用云代码执行curl

注: curl与测试或开发应用程序时使用本节的命令应该是无害的。 在将数据写入生产应用程序时要小心。

使用POST写入数据

你需要给curl几个重要的选项:

选项 描述
-X POST 设置请求类型,这将否则默认为GET
-H "X-Parse-Application-Id: your_application_id " 发送识别应用程序中的头parse-server
-H "Content-Type: application/json" 发送一个报头,它可以让parse-server知道会JSON格式的数据
-d '{ json_data } 发送数据本身

把这些都放在一起,我们得到:

curl -X POST \
  -H "X-Parse-Application-Id: your_application_id" \
  -H "Content-Type: application/json" \
  -d '{"score":1337,"playerName":"Sammy","cheatMode":false}' \
  https://your_domain_name/parse/classes/GameScore
示例输出
{"objectId":"YpxFdzox3u","createdAt":"2016-02-18T18:03:43.188Z"}

使用GET读取数据

由于curl发送GET默认请求,我们不提供任何数据,你应该只需要发送应用程序ID以读取一些样本数据回:

curl -H "X-Parse-Application-Id: your_application_id" https://your_domain_name/parse/classes/GameScore
示例输出
{"results":[{"objectId":"BNGLzgF6KB","score":1337,"playerName":"Sammy","cheatMode":false,"updatedAt":"2016-02-17T20:53:59.947Z","createdAt":"2016-02-17T20:53:59.947Z"},{"objectId":"0l1yE3ivB6","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T03:57:00.932Z","createdAt":"2016-02-18T03:57:00.932Z"},{"objectId":"aKgvFqDkXh","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T04:44:01.275Z","createdAt":"2016-02-18T04:44:01.275Z"},{"objectId":"zCKTgKzCRH","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T16:56:51.245Z","createdAt":"2016-02-18T16:56:51.245Z"},{"objectId":"YpxFdzox3u","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T18:03:43.188Z","createdAt":"2016-02-18T18:03:43.188Z"}]}

执行示例云代码

一个简单的POST,没有实际数据https:// your_domain_name /parse/functions/hello将运行hello()中定义的函数/home/parse/cloud/main.js

curl -X POST \
  -H "X-Parse-Application-Id: your_application_id" \
  -H "Content-Type: application/json" \
  -d '{}' \
  https://your_domain_name/parse/functions/hello
示例输出
{"result":"Hi"}

如果您已经迁移,而不是自己的自定义云代码,可以利用公知功能测试main.js

第6步 - 为您的应用程序配置解析服务器并完成迁移

您的下一步将是更改您的客户端应用程序本身以使用Parse Server API端点。 请参考官方文档上使用SDK的解析与解析服务器。 您将需要适用于您的平台的最新版本的SDK。 由于与curl为主的上面的测试,使用该字符串的服务器网址:

https://your_domain_name/parse

返回在浏览器中解析仪表盘和迁移标签:

解析应用程序:迁移过程

点击按钮敲定

解析迁移完成对话框

您的应用现在应该已迁移。

结论和后续步骤

本指南提供了将Parse托管应用程序迁移到单个Ubuntu系统上的Parse Server安装的功能性起点,例如DigitalOceanDroplet。 我们描述的配置应该足够用于具有适度用户基础的低流量应用。 托管较大的应用程序可能需要多个系统在API端点之间提供冗余数据存储和负载平衡。 即使是小项目也可能涉及我们没有直接解决的基础设施考虑。

除了阅读官方解析服务器文档和跟踪GitHub的问题,为项目在进行故障诊断时,您不妨探讨以下主题: