タグ「heroku」が付けられているもの

色々考えた結果、herokuを使うのが一番手軽だと思い、Ghostをデプロイしてみることにしました。 file storage問題は既に取り組まれていて、storage moduleでfile以外の方法も使えるようになったようです。 具体的には、Ghost S3 Storageというのがあるようです。 個人的には、mongodbをバックエンドにしたstorageとかできないかなと期待します。

さて、Ghostをherokuにデプロイする簡単な方法はないか調べたところ、 https://github.com/cobyism/ghost-on-heroku というのがありました。 これは便利と思って早速試そうとしたところ、メール機能の有料アドオンを使う設定になっていて それを外す方法が分かりませんでした。

そこで、通常の方法でデプロイすることにしようと思いました。 参考にしたサイトはhttp://www.autodidacts.io/host-a-ghost-blog-on-heroku/です。 ところが、作業を開始してから思いの外手順が多いことに気づき、 作業メモの利用価値が低くなってしまいそうでした。 これでは再利用性がなくなってしまいます。

そこで、方針を戻して、ghost-on-herokuをforkすることにしました。 有料アドオンを使っているところをやめて、GMailでメール機能を使えるようにします。 Ghostのソースを調べると思っていたように、NodeMailerが使われていたため、簡単そうです。 ghost-on-herokuをみようみまねで編集して、ボタンひとつでデプロイできるようにしました。

こちらです。

https://github.com/dai-shi/ghost-on-heroku

ボタンひとつでデプロイできます。動作確認はこれからですが。

このherokuのテンプレート機能便利だと思いました。他にも使えそうです。

node.jsのデプロイ先としてはherokuを使うことが多いのですが、 他にはどういう候補があるのか調べてみようと思いました。 昔の記事を見ると手軽に使えそうだった、Nodejitsu, AppFog, Node Ninjaなど 使えなくなった(もしくは、以前より使いにくくなった)ものもあります。 また、最近Ghostを試してみたいと思ったのですが、 herokuがサポートされていない(ファイルアクセスができない)こともあり、 他の候補を調べてみることにしました。

条件は、無料で使えるプランがある(一定期間でも)ことです。 網羅はできていないと思います。順不同です。 実際に試したわけではなく、サイトから得られる情報をまとめただけです。

flow.ch

Flow App Engineは、Java, PHP, Ruby, Node.js, Python or .NET (Beta) を動作させることができて、dockerのイメージも動かせるそうです。 各種データベースも用意されているとのこと。 webベースのdashboardで簡単に操作できるようです。

free trialは14日間です。pricingは、usage-basedとfixedの2種類とのこと。

modulus.io

Modulusは、Node.js,PHP, Javaが使えます。Meteorがサポートされているのも特徴のようです。 modulusというコマンドをインストールして、デプロイ作業をするようです。 その他必要そうなものはひと通り揃っているように見えます。

sign upすると30日間使える$15分のクレジットがもらえるようです。 しかし、一番安い構成でも月に$28.80になるので、30日連続運用はできないことになります。

dotCloud

dotCloudは、Python, Java, Node.js, PHPが使えるようです。 デフォルトはMySQLですが、他のストレージのadd-onもあります。MongoDBもMongoSoupというのがあるようです。 特徴的なのは、プラットフォームへのアクセスで、 CLIのツールと、Webコンソールと、REST APIが用意されているとのこと。

Sign up for Freeとありますが、実際無料でどこまで使えるか分かりませんでした。 一番小さい構成では、月$9.90のようです。

cloud.google.com

Google Cloud Platformは、IaaSに近い感じですが、 Cloud Launcherを使って簡単にStackを構成できるようです。MEANも使えるようです。

Free trialでは、$300分を60日間使えるそうです。

bluemix

IBM Bluemixは、OSSのCloud FoundryをベースとしたPaaSです。 色々使えるようですが、一例として、Node.js, PHP, Python, Rubyがあげられています。

フリートライアルでは、30日間使えるそうです。

現在、アプリ開発コンテストが開催中とのこと。

まとめ

残念ながら、期間限定なしでfreeで使えるサービスは見つけられませんでした。 freemiumは最近は流行りではないのでしょうかね。 herokuもfreeの範囲が狭まることになりましたし、厳しい情勢です。

Gunosy RSSのURL変更その他

  • 投稿日:
  • by

久しぶりにgunosy-rssのコードをいじりました。

まず、URLを変更しました。新しいURLは、

http://gunosy-rss.axlight.com/

です。以前のURLでアクセスした場合は301 Redirectされます。 RSSリーダーがちゃんとURLを書き換えてくれればよいのですが、 おそらくすべてのRSSリーダー/アグリゲータが対応しているということはないでしょう。

今後、旧URLではアクセスできなくなることがあるかもしれません。 というのも、herokuの無料枠で動かしているのですが、その条件が変わるためです。 将来的にDNSでアクセス先を変更したりすることを想定してのことです。

しかし、当面はそんな面倒なことをするつもりはありません。 とりあえず、無料枠で動かし続けるためには、6時間スリープさせればよいようなので、 rssのttlを設定してみました。今後RSSリーダー/アグリゲータがttl正しく解釈してくれれば、朝の5時以降と夕方の5時以降に取得するようになるはずです。 しかし、これはもっと早く実装しておけばよかったですね。 ちょっと様子を見た感じだとアクセス頻度がだいぶ減ったように思います。 503 Retry-Afterが返ることも減ったようですし、本家Gunosyへのアクセス負荷も下がるかもしれません。

JavaScriptのDateのタイムゾーンが手元とherokuで異なっていて、はまりました。 ちょっとスマートでない方法で解決したのと、もともとのコードがスマートでないので見苦しいですが、ttlの算出周りに興味があればコードを見てみてください。 たぶんきっともっといい書き方があるはずです。

他にも今から見ると書き直したい部分があったり、そもそもライブラリのアップデータもしたいのですが、そこまでモチベーションがわきません。まあそのうち、ついでがあれば。


5/24追記。

タイムゾーンを設定する方法がありました。

$ env TZ=Asia/Tokyo node app.js

これでコードはシンプルになりました。

https://github.com/dai-shi/gunosy-rss

突然ですが、例えば、githubにリポジトリを置いて、herokuにデプロイするというケースは多いのではないでしょうか? そういうときは大抵、

$ git push master origin
$ git push master heroku

と2つコマンドを打つことになると思います。 それぞれ、git remoteでoriginとherokuが設定されているとして。

これが、一発で済むと楽ではないですか? もちろんローカルでshell scriptを書いてもいいかもしれませんが、 例えば、githubにはPUSH権限があるけど、herokuにはPUSH権限がないような ユーザがいるケースでは、どうでしょう? そういう場合に、githubからherokuに自動でデプロイできたら便利でしょう。

いくつか解決法はあるようですが、CodeShipというのを使ってみました。

http://blog.codeship.io/2013/10/02/how-to-deploy-a-ruby-on-rails-app-from-bitbucket-to-heroku.html

チュートリアルに沿って言われたとおりに設定するだけでできるようになりました。 どうやら、双方にアクセスするための鍵を登録して、 さらにPUSH時のhookを登録することで実現しているみたいです。 鍵の元はCodeShipにあるわけなので、CodeShip側に悪意があればいろいろできちゃいそうですが。

CodeShipはデプロイだけではなく、テストもまわせるなど、使いこなせばいろいろできそうです。

facebook-node-sdkを使って、簡単なFacebook Graph APIの呼び出しをしていたのですが、不思議なエラーがでてました。

(#5) Unauthorized source IP address

というエラーです。

stackoverflowでも複数のスレッドで話題になっていました。IPが変わってしまっていて、エラーになっているということは分かりました。

herokuを使うと、デプロイしてから何時間か経つとIPアドレスが変わるようです。そこで、access tokenを同じものを使い続けると上記エラーがでるので、access tokenを取得し直す必要があります。

これは、OAuthExceptionのときに再取得するようにすればいいのですが、少しはまりました。access tokenを取得するAPIを呼ぶ時に事前にaccess tokenをクリアしておく必要がありました。そうしないと、access tokenを再取得しようとするときに上記のエラーが出ました。Facebook側の問題か、ライブラリ側の問題か難しいところですが、とりあえずは自分で回避するしかないです。

参考までにサンプルコードを載せておきます。

FB.api('hoge/feed', function(res) {
  if (res && res.error && res.error.type === 'OAuthException') {
    FB.setAccessToken(null);
    FB.api('oauth/access_token', {
      client_id: process.env.FACEBOOK_APP_ID,
      client_secret: process.env.FACEBOOK_SECRET,
      grant_type: 'client_credentials'
    }, function(res) {
      if (!res || res.error) {
        console.log('error occurred when getting access token:', res && res.error);
        cb(res);
        return;
      }
      FB.setAccessToken(res.access_token);
      FB.api('hoge/feed', cb);
    });
  } else {
    cb(res);
  }
});

今回はapplication access tokenを使う時に起こったエラーですが、普通のuser access tokenでも同じかもしれません(未確認)。


5/2追記。

上記のコードでも回避できずにエラーになったことが一度だけありました。再度調査中ですがその後再現しないので解決できないです。

5/6追記。

その後安定して動いています。前回の一度起こったエラーはたまたま別の要因があったと思っておきましょう。

RSS Pipesは、JavaScriptでフィルターを書く、RSSアグリゲーターです。

フィルターJavaScriptはブラウザ上で誰でも書くことができます。すなわち、バグ入りのコードや、悪意のあるコードも書くことができます。 そのような不正なコードにどう対処するかがポイントになります。

RSS PipesはNode.jsで動いています。Node.jsにはvmというモジュールがあって、サンドボックス環境を作ることができます。 Node.jsを使ったことがある方は分かると思いますが、モジュールを書いてrequireするとexportsしたもの以外は名前が衝突しません。 これはrequireでモジュールをロードする時にサンドボックス環境で評価しているからです。 RSS Pipesでもこの仕組みを使ってJavaScriptのコードを評価しています。 よって、ブラウザ上から入力されたJavaScriptコードによって、サーバ側のNode.jsにアクセスされることはありません。

ところが、vmモジュールのマニュアルをよく読むと書いてあるように、このモジュールを使うことで安全になるわけではありません。安全にコードを走らせるためにはサブプロセスを使うように、と書いてあります。

どういうことかと言うと、Node.jsはシングルスレッドで動作するため、vmでサンドボックス環境を作ったとしてもそこで使用されるリソース(CPUパワーやメモリ)を制限することはできず、リソースを不用意に使われてしまう可能性があります。簡単な例では、

while(true) {}

というJavaScriptを走らせるとNode.js全体が固まってしまいます。 とは言っても、herokuで動いているRSS Pipesでサブプロセスを使うわけにはいきません。(もしかして、使うこと自体はできるのかも?)

そこで、無限ループを判定するような仕組みをいれています。 先ほどの例では、

while(true) {
  counter++;
}

のようにして、counterが一定値を越えた場合に強制的に止めればよいのです。これで、どの程度の危険が回避できたかは定かではありません。正確にCPUの使用率を測っているわけでもありませんし、メモリについてはノータッチです。それでも、無限ループで固まることは回避できているので、少なくとも悪意のないコードでしたら、問題のない範囲と思っています。

将来的に、vmモジュールのサンドボックス環境でリソース制限までしてくれるようにはならないでしょうかね。ちょっと興味あります。

Gunosy RSS はオープンソースで提供されています。ライセンスの範囲内で自由に使うことができます。

慣れている人は説明なしですぐにできると思いますが、どれだけ簡単にできるかを示すため手順を書いておきます。

前提:

  • herokuのアカウントがあること(なければ作る)
  • heroku toolbeltがインストールされ、SSH鍵が登録済であること
  • GitHubのアカウントがあること(なければ作る)
  • gitがインストールされていること

まず、GitHubからソースコードを取得します。

https://github.com/dai-shi/gunosy-rss

にアクセスして、右上のForkボタンを押して、自分のリポジトリにします。自分のリポジトリのページに行ってリポジトリのURLを確認します。 仮に、git@github.com:<username>/gunosy-rss.gitだったとします。

% git clone git@github.com:<username>/gunosy-rss.git

をコマンドラインで実行するとダウンロードされます。

% cd gunosy-rss

でディレクトリを移動します。

次に、herokuにアプリケーションを作ります。

% heroku apps:create <appname>

を実行するだけです。<appname>は省略も可能です。 作ったアプリケーションの情報を確認するため、

% heroku apps:info

とします。そこで表示される、Git URLとWeb URLが重要です。 それぞれ、git@heroku.com:<appname>.gitとhttp://<appname>.herokuapp.com/だったとします。

% heroku config:set SITE_PREFIX=http://<appname>.herokuapp.com/

として、環境変数を登録します。

% git remote add heroku git@heroku.com:<appname>.git

として、リモートリポジトリを登録します。

% git push heroku

として、herokuにアップロードして、完了です。 http://<appname>.herokuapp.com/<gunosyid>.rssでRSSフィードが生成されます。

いかがでしょう?


補足

実は、GitHubのアカウント作らずForkもしなくても、上記のことはできます。ですが、せっかくなのでpull requestが送れるようにForkするのが、GitHubらしいのではないでしょうか。

herokuのアプリケーション情報を表示するところでは、

% heroku apps:info --app <appname>

とする必要があるかもしれません。