MeteorをCentOSにデプロイする

Meteorで作成したアプリケーションを自分のサーバにデプロイしたが、Ubuntuに対するデプロイ情報はネットにあったもののCentOSにデプロイする方法がほとんどなかったのでシェアしてみる。

80番ポートには既にhttp-proxyでapacheやnodeのサーバにルーティングしているので、http-proxyでMeteorのアプリケーションにもルーティング出来るようにした。

## 環境
さくらVPS CentOS 6.5 64bit
Meteor 1.0
NodeJS v0.10.29
MongoDB v2.6.5

## Meteorのデプロイ

####ローカルでの作業
開発環境(macでもなんでも)でアプリケーションが出来上がるとそのmeteorプロジェクトをパッケージ化する。

なお、あらかじめCentOSにはMeteorをインストールしているものとする。

```
$ meteor build [アプリケーションのあるパス]
```

もしくはmeteorプロジェクトのディレクトリ内で

```
$ meteor build .
```


すると以下のファイルが出来る。

```
[アプリケーション名].tar.gz
```


これをFTPクライアントなりなんなりでCentOSの任意の場所にコピーする。

####リモート

今回は以下のディレクトリにコピーしたので、

```
/var/www/[アプリケーション名]/[アプリケーション名].tar.gz
```

これを展開する。

```
$ tar -zxf [アプリケーション名].tar.gz
```

すると、bundleというディレクトリができるので、次のようにパッケージをいくつかインストールする。
この際いくつかwarningが出るかもしれないが、とりあえず支障はないので放置しておく。

```
$ cd bundle/programs/server
$ npm install
```

これで本来は完了なはずなのだが、bundleに戻って以下のコマンドを打つとエラーが出てきてしまう。

```
$ node main.js
```

```
/****/****/bundle/programs/server/node_modules/fibers/future.js:173
throw(ex);
^
Error: /home/****/bundle/programs/server/npm/npm-bcrypt/node_modules/bcrypt/build/Release/bcrypt_lib.node: invalid ELF header
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at bindings (/home/****/bundle/programs/server/npm/npm-bcrypt/node_modules/bcrypt/node_modules/bindings/bindings.js:74:15)
at Object.<anonymous> (/home/****/bundle/programs/server/npm/npm-bcrypt/node_modules/bcrypt/bcrypt.js:1:97)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
```

どうやらmacでは正常に動いていたはずのbcryptがlinuxではなぜか上手く動いていないようなので、インストールし直してみる。
また、Meteorがbcryptを```bundle/programs/server/npm/npm-bcrypt/node_modules```にコピーしているみたいなので、それも上書きする。

```
$ cd bundle/programs/server
$ npm install bcrypt
$ cp -r bundle/programs/server/node_modules/bcrypt bundle/programs/server/npm/npm-bcrypt/node_modules
```

これでMeteorに対する処理は終わり。

README内にあるコマンドを打つとアプリケーションが立ち上がる。

１行目は先の作業で終えているから必要ない。  

Meteorには環境変数がいくつかあって、
MONGO_URLでmongoの指定、
ROOT_URLでホストの指定、
MAIL_URLでメールサーバの指定などが出来る。
READMEにはないが、POOTでポートの指定も可能。

```
$ (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
```


## Mongoのインストール

ここはmongoの公式サイトにあるので説明は簡単に。

```
$ vi /etc/yum.repos.d/mongodb.repo
```
で以下を貼り付けて、

```
[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1
```

次のコマンドでmongoをインストール。

```
$ sudo yum install -y mongodb-org
```

mongoのadminを設定するなどしてからデータの保存場所を確保する。

```
$ sudo mkdir /data/db_mongo (この場所は任意)
$ sudo chown 'mongod:mongod' /data/db_mongo
```

今作成したdbの保存場所を示すパスを指定して、mongoを立ち上げる。

```
$ mongod --dbpath /data/db_mongo
```

ここでアプリケーション用のDBを作成し、セキュリティ上データベースにadminユーザを作成する。

```
$ mongo

$ db.createCollection("[コレクションの名前]");
$ use [コレクションの名前]
$ db.createUser('[ユーザ名]','[パスワード]');
```

## http-proxyでルーティング

まずはhostとportの整理を。

|        ホスト        | ポート |用途|
|:--------------------:|:------:|:--------------------------------:|
|      example.com     |   80   | http-proxyによるプロキシサーバー |
| 127.0.0.1(localhost) |  3100  |     Meteorのアプリケーション     |
| 127.0.0.1(localhost) |  27017 |              MongoDB             |

http-proxyの説明はhttp://qiita.com/ytakzk/items/e4422555549b069e3d90
この辺で説明しているので見ていただくとして、以下のように設定する。

```js:proxy.js
var http = require('http');
var httpProxy = require('http-proxy');

// apacheのサーバ(別アプリケーションのために立てている)
var apacheProxy = new httpProxy.createProxyServer({
    target: {
    host: 'localhost',
    port: 8081
}});

// ghostのサーバ(別アプリケーションのために立てている)
var ghostProxy = new httpProxy.createProxyServer({
    target: {
    host: 'localhost',
    port: 6666
}});

// meteorのサーバ(今回に必要なもの)
var meteorProxy = new httpProxy.createProxyServer({
    target: {
    host: '127.0.0.1',
    port: 3100
}});

// ルーティング
var server = http.createServer(function ( req, res ) {
    var proxy;
    if (req.headers.host == 'example1.com') {
        proxy = apacheProxy.web( req, res );
    } else if (req.headers.host == 'example2.com') {
        proxy = ghostProxy.web( req, res );
    } else if (req.headers.host == 'example.com') {
        proxy = meteorProxy.web( req, res, function(err) {
	  console.log(err);
	});
    } else {
        res.writeHead(404);
        res.end();
    }
});

// websocket
server.on( 'upgrade', function( req, socket, head ) {
    meteorProxy.ws( req, socket, head );
});

server.listen(80, function(){
  process.setuid(500);
});
console.log('It Works!');
```

## iptablesの設定

iptablesにポート3100を追加する。

```
$ sudo vi  /etc/sysconfig/iptables
```

以下の１行を追加

```
-A SERVICES -p tcp --dport 3100 -j ACCEPT
```

## 最終的なデプロイ
npmでforeverをインストールしておく。(割愛)  

まずはプロキシサーバーを起動

```
$ sudo forever start proxy.js
```

mongoをバックグラウンドで起動

```
$ sudo mongod --fork --dbpath /data/db_mongo --logpath /var/log/mongodb/db.log
```

meteorのアプリケーションを起動

```
$ export MONGO_URL='mongodb://[先に作成したdbのユーザ名]:[先に作成したdbのユパスワード]@127.0.0.1:27017/[コレクション名]'
$ export ROOT_URL='http://127.0.0.1'
$ export PORT=3100
$ forever start main.js
```

## 再デプロイの手順
これまでと手順は一緒。
開発環境でtarファイルを作って同じ作業を繰り返せば良い。
プロキシサーバーやmongoはすでに立っているからそれは必要ないけど。
シェルで以下を走らせれば一発で再デプロイ終了。

```
$ tar -zxf [アプリケーション名].tar.gz
$ (cd bundle/programs/server & npm install bcrypt)
$ cp -r bundle/programs/server/node_modules/bcrypt bundle/programs/server/npm/npm-bcrypt/node_modules

$ export MONGO_URL='mongodb://user:password@host:port/databasename'
$ export ROOT_URL='http://example.com'
$ export MAIL_URL='smtp://user:password@mailhost:port/'
$ export MAIL_URL='smtp://postmaster%40wasabihunt.com:ebeeb40a2355e809ee691f817b4d3c81@smtp.mailgun.org:587'
$ forever restart main.js
```

## 実際のプロダクト
実際にMeteorで作ったプロダクトがこちら。
といってもまだβ版に過ぎないけども。
http://wasabihunt.com/

以上！