2012年3月23日金曜日

AWS 上の Rails 環境

「クラウド上に Rails 環境を作るのであれば Heroku じゃないの?」という疑問が聞こえてきそうですが、欲しかった環境が ruby 1.8.x + Rails 2.3.5 (かつ Bundler の恩恵を受けていないアプリケーション?)だったので、heroku で動かすには苦労しそうだとプロの意見もいただいたので、AWS に白羽の矢を立てた次第です。

んで、以下は AWS の Linux AMI に rails 環境を作った記録です:

…と思ったんですが、結局、昔書いた Openskip の環境構築の手順のほとんどそのままで動かせました。違いは
  • 今回は rvm 環境を先に用意した
  • Amazon Linux AMI がデフォルトで用意しているパッケージが少ないのでいろいろ yum install した
    • patch, make, gcc,...
    • git
    • mailx (/bin/mail コマンド)
    • mysql-server
    • *-devel (ここは CentOS でも一緒か…)
  • インストールした gem は同じだけれどバージョンがちょっと違う
くらいです。
当たり前と言えば当たり前ですね、Amazon Linux AMI が CentOS 類似OSなので。

Amazon EC2 を使ってみる

手元で改修したプログラムの動作を見てもらおうと思ったときに、これまでは手元でしか動かせなかったので直接会った時にしかどんな感じで動くのか見てもらえませんでした。
これだと会えないと開発の機会がなくなります。困ります。

ということで、
「インターネット上にテスト環境が欲しい!」
と思い、Amazon EC2 の無料使用範囲を利用してテスト環境(ステージング環境?)を作ってみることにしました。

初めの一歩

多分このドキュメントなんだと思います:
Get Started with EC2 with a Linux/UNIX Instance

手順として
  1. サインアップ
  2. インスタンス(仮想マシン)の作成と起動
  3. インスタンスへのアクセス
  4. インスタンスの terminate 
となっています。

サインアップ

サインアップは普通にweb上のサービスを利用する感じで進みます。途中、ケータイへ Amazon さんから自動着信&webページに表示された4桁の番号入力を求められるのが普通でない感じ。
サインアップが終わると、AWS Management Console というWebサイトが使えるようになると思います。このWebサイトでインスタンスの管理(作成、起動、一時停止、停止などなど)を行えます。

あ。ssh の鍵生成はこのタイミングでやっておくとよいと思います。

インスタンスの作成と起動

インスタンスの作成のプロセスも、Web上のクリックぽちぽちで進められます。
今回は Quick Launch Start のウィザードを使って、AMI Linux 2011.9 x86_64 を立ち上げてみました。
Amazon Linux AMI についてのドキュメント を読んでみると、
Amazon Linux AMI is similar to CentOS in file system layout and package management. Applications built for CentOS should run without recompilation on the Amazon Linux AMI.
と書いてあって、「CentOS と同様のファイル構造とパッケージ管理」というところを重視して思わず選びました。手元の環境(CentOS 6 on VMware & Thinkpad)に近い方が楽だと思ったので…。
Quick だとほとんど選ぶことは無いのですが、インスタンスのタイプが micro (= 無料使用範囲で使えるインスタンス)であることだけはしっかりと確認しました。

インスタンスの起動はAWS management console から行います。これも「クリックぽち」です。

インスタンスへのアクセス…の前に

インスタンスが持っているFQDNの確認と、セキュリティグループの概念の理解が(多分)必要です。

インスタンスのFQDNを確認するには、AWS management conslole から確認します。これがないとsshできませんし…。

セキュリティグループは、「ネットワークの口に存在するファイアウォール(のルールセット)」に相当するものだと思っています。
定義するものはファイアウォールルールそのもので、そのルールをセキュリティグループとしてまとめ、各インスタンスにどのセキュリティグループに属させるかを設定します。
複数の同様のサーバを運用する場合にセキュリティグループが威力を発揮しそうです。今は一台なので、OS上でiptables を走らせても(セキュリティレベルと言う意味では)あまり変わりないかもしれません。

インスタンスへのアクセス 

SSH の鍵があって、FQDN が分かっていれば、後は ssh コマンドを走らせるだけです。
…が、一度引っかかりました。AWS management console で生成した ssh の秘密鍵をダウンロードするんですが、そのパーミッションを 6xx から 400 にしないといけません。秘密鍵ですもんね。
普段 ssh-keygen で作ると自動的に 400 だと思いますが、ダウンロードファイルだから普通のパーミッションになってました。

インスタンスのterminate

「停止」と言う言葉を使わずに terminate と書いたのは、ちょっと悲しい体験をきちんと伝えたかったからです…。

停止っていうと、僕の中では再開できるものだったんです。が、ご存知の通り、インスタンスを terminate するとそのインスタンス上のデータは破棄され、再利用することはできません。
"Get started" を読むと Note として、
You cannot restart a terminated instance. However, you can launch additional instances of the same AMI.
と書いてあるのでちゃんと読めという話なんですが、ドキュメントの手順どおり terminate してパニックになりました。

「このインスタンスをしばらく使わないから課金されない状態にしたいわー」と言うときはインスタンスに対する操作として stop というのがあるので、そちらを使うと start ←→ stop を行き来できます。


こんな感じで Amazon EC2 に Linux サーバを立てて、その上で rails の環境を動かしています。
立ち上がった Linux サーバはいろいろひどい状況なので、もう少しマトモな環境にしていかねば…。

2012年3月8日木曜日

vmware tools の仕業?

昨日せっかくどうでもいいことでハマッタので、ブログに書いておこうと思います。

3/4 に CentOS の yum upgrade (多分このとき 6.0 → 6.2になる)を行い、3/6 に VMware Player の 4.0.2 へのアップグレードと VMware tools の再インストールをしたのですが、3/7 に
「VMware ゲストOSの画面を全画面表示したときに、ウィンドウ領域全体で描画されない(800x600になる)」
という事態になりました。

開発なんてやってられない狭さなので時間をかけてでも解決させたわけですが、結論から言うと
  • インストールされているはずの /usr/lib/xorg/modules/drivers/vmwlegacy_drv.so (from xorg-x11-drv-vmware パッケージ)が無かった
  • /etc/X11/xorg.conf の設定で、device identifier "Videocard0" に対する driver が "vesa" になっていた
というところが原因らしく、それぞれ
  • xorg-x11-drv-vmware の再インストール( yum reinstall )
  • driver を "vmware" に変更
    • man vmware すると VMware SVGA video driver についてのマニュアルが立ち上がるのは知らなかった…
ということをやって元通りの環境を奪回しました。

/etc/X11/xorg.conf 辺りが関わっているので、ゲストOS上の操作が何か関わっているはずで、vmware-tools-config.pl あたりが怪しそうな予感だけはあります。追跡しないけれど。

…あ。VMware player の再インストール(4.0.0 へのダウングレード)しちゃったけど、次のアップグレードが怖いなっと。

2012年2月9日木曜日

小さな commit ベースで仕事すること

一応、rails プロジェクトを作るときに一番最初に git init && git . && git commit して、rails プロジェクト全体を git でコントロールできるようにしてはいました。

が。

実際のところ、commit したことはこれまでありません。「ある程度の状態にしてから…」とかダメな事を考えています。

で、今どうなっているかというと、
  • 今まで何したか良く覚えていない
  • 次に何をすればいいのか良く覚えていない
という状態です。まさに、昨日の自分は他人。

コードレビューをしてもらえる機会ができそうなんですが、その時に「何を思って問題にどう対処したのか」を説明できない悪寒がひしひしと忍び寄っています。
こういう時に変な完璧主義が出てきて、一から作り直したい症候群になるんですよね。まぁ、今作っているのは習作なので何度でも一からやり直せばいいと思うんですけど…。

…みたいなことを、たまたま本を読んでいたタイミングで思うのです。


2012年1月6日金曜日

devise でメールアドレス以外を認証に使う

先ほどメールアドレスで認証するサンプルが作れたのですが、今、考えている状況に
  • メールアドレスが確定しない状況(変更可能な状況)
  • そもそも持っていない可能性もある状況
  • 将来的に外部認証と組み合わせる時にメールアドレスを強制できない状況
が含まれるので、メールアドレス以外をユーザIDとして使う方法が必要になりました。

今の時代は恵まれているので、しっかり誰かが道を作ってくれています。
http://ja.asciicasts.com/episodes/210-customizing-devise
http://d.hatena.ne.jp/kaorumori/20110824/1314168534

config/initializers/devise.rb にて
config.authentication_keys = [ :username ]
元々の設定値は :email になっています。

さらに、app/views/devise/session/new.html.erb および app/views/devise/registrations/new.html.erb にて、:username 用の text_field を追加します。

この辺り(テキストフィールド欄の追加)は見よう見まねで何とかなったのですが…。
上記の2つの記事では「既に存在しているユーザのフィールド(username)の値を認証に使う」というものでしたが、username の値を登録したいと思って regisrations/new.html.erb に単純にテキストフィールドを追加したらハマりました。

コンソールログをきちんと読め、という話なのですが、
WARNING: Can't mass-assign protected attributes: username
というログが出てきます。
app/models/user.rb で、attr_accessible に :username を追加してあげる必要があったようです。
こんな記事を見つけました。
http://trwtnb.blogspot.com/2009/11/rubyrails-warning-cant-mass-assign.html

おまけ

email フィールドに unique 制約があるので(適当なメールアドレスをでっち上げればいいだけなんですが…)、user テーブルを何度も作り直しました。
ってことで、 rake db:migrate:reset をおぼえた!

2011年12月12日月曜日

devise を使う

ちょっと前に Rails + OmniAuth + OAuth on Twitter/Facebook でユーザ認証のサンプルを作ってみたのですが、認証に関する便利な仕組みとして Devise というのを知ったのでそちらを使ってみることにしました。

なお、OmniAuth との連携については wiki ページに情報があります。
最終的には OmniAuth との連携の形に持っていきたいと思います。

まず最初に

https://github.com/plataformatec/devise の Installation の項目にある部分:
  • Devise の gem のインストール
  • Gemfile への追記: gem 'devise'
  • rails g devise:install
  • rails g devise user
  • rails g devise:views
までを行いました。
"rails g devise:install" の後にメッセージが出ます。要約すると:
  1. config.action_mailer.default_url_options を設定せよ
    • config/environments/development.rb だと、"{ :host => 'localhost:3000' }" とか
  2. config/routes.rb にて、root_url を設定(root :to を定義)せよ
    • トップページを表現する適当な controller を用意して、"...#index" とかにしておけば良いはず
  3. app/views/layouts/application.html.erb (つまり global_layout)で notice, alert が表示されるようにせよ
    • こんな感じ。"<p class="notice"><%= notice %></p>"
  4. heroku 上にデプロイする場合には、config/application.rb にて config.asset.initialize_on_precompile = false を宣言せよ
の4点です。
この devise:install 時のメッセージに従って作業すると1/3位の設定が終わります。

もう一つの準備

とりあえず「認証によって保護されるリソース」 を考えないと認証の意味が無いので、todo モデルを作っておきます。
rails g scaffold todo summary:string content:text importance:integer rake db:migrate
この todo を、認証した user だけがアクセスできるようにします。

リソースの保護

リソース todo へのアクセスを認証で制御するには、
  1. app/controllers/todos_controller.rb の修正
    • before_filter :authenticate_user!
  2. routes.rb の修正
    • devise_for :users
とします。
また、ログイン情報入力のための画面を用意した場合、
  • ログインしていないなら、ログイン情報入力画面
  • ログイン済みなら、 ログイン後のトップ画面
のような構成を作りたいと思います。
このような時には devise で提供されている current_user メソッドを使って、
class PortalController < ApplicationController
  def index
    if current_user
      redirect_to :user_root
      return
    end
  end
end
のようなことができます。

2011年12月11日日曜日

rails 環境の準備

何度やっても覚えないので覚えないことにしました。
  1. rvm use 1.9.2@rails3
    • (もちろん 1.9.2 の ruby とか rails3 の gemset は用意しておくべし)
  2. rails new APP_NAME
  3. vi APP_NAME/.rvmrc : 以下の内容で作成
    • rvm use 1.9.2@rails3
  4. cd APP_NAME
  5. vi Gemfile : 以下の内容を追記
    • gem 'therubyracer'
    • gem 'rspec-rails'
  6. bundle install (上記の gem は rails3 gemset に既にインストールされているので必要無し)
  7. rails g rspec:install
  8. rm public/index.html
  9. git init
  10. git add .
  11. git commit
これで、新しい rails アプリを立ち上げて、rspec を使うようにして、git 配下に置く事ができます。

文書にしてみて分かったこと → スクリプトにすれば良いのだ…。