xxxcaqui.log

ツッコミお待ちしています

ApacheのSSL設定

ApacheSSLの設定をしていきます。

サーバ証明書を作成する方法は各認証局に従ってください。
その際に必要なCSRの作り方はSSL用のCSRを作成するをご覧ください。

前提

秘密鍵・証明書の移動とパーミッション設定

ファイルの移動

秘密鍵や証明書はどこにあっても読み込みさえ出来れば問題ないのですが、わかりやすいディレクトリに移動しておきます。

$ sudo ln -s /etc/pki/tls/private/ /etc/ssl/private
$ sudo mv somewhere/key.pem /etc/ssl/private/key.pem
$ sudo mv somewhere/cert.pem /etc/ssl/certs/cert.pem
$ sudo mv somewhere/chain.pem /etc/ssl/certs/chain.pem

パーミッションの設定

秘密鍵が他のユーザから読めると困るので、パーミッションを変更しておきます。*1

$ sudo chmod 400 /etc/ssl/private/key.pem
$ sudo chown apache:apache /etc/ssl/private/key.pem
$ sudo chown apache:apache /etc/ssl/certs/cert.pem
$ sudo chown apache:apache /etc/ssl/certs/chain.pem

Apacheの設定

mod_sslをインストール

$ sudo yum install -y mod_ssl

ssl.confの設定

#/etc/httpd/conf.d/ssl.conf
<VirtualHost *:443>
  SSLCertificateKeyFile /etc/ssl/private/key.pem
  SSLCertificateFile /etc/ssl/certs/cert.pem
  SSLCertificateChainFile /etc/ssl/certs/chain.pem
</VirtualHost>

Apacheの再起動

$ sudo service httpd restart

2013-07-16追記:AWSを使っている場合

AWSを使っている場合はSecurity Groupの設定でHTTPS(443)を許可しないとHTTPS通信ができません。

EC2インスタンス上でnetstatとか叩いて443をLISTENしててもインスタンスにリクエストが届かないので注意!*2

さいごに

これでSSL通信が可能になります。

Passenger等を使用している場合も、Passenger側に設定を行う必要はありません。

*1:そもそも、秘密鍵のパーミッションが644とかだとSSL出来なかった気もする。未確認。

*2:こんなことで3時間くらいハマってた。泣きたい。

SSL用のCSRを作成する

SSLサーバ証明書を申請するときに必要になるCSR(Certificate Signing Request)を作成します。*1

環境

  • Amazon Linux AMI 2013.03.1

CSRって?

簡単に言うと、サーバ証明書の申し込み用紙です。

サーバ証明書は「このドメインはこのサーバで合ってるよー!」ということを証明するためのものなので、申請にあたっては

の2点が必要になります。

これらの2点(とその他諸々の情報)を所定の形式に従ってまとめたものがCSRです。

具体的には次のような形式になります。

-----BEGIN CERTIFICATE REQUEST-----
MIIBnTCCAQYCAQAwXTELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIw
EAYDVQQDEwlsb2NhbGhvc3QxJzAlBgkqhkiG9w0BCQEWGGFkbWluQHNlcnZlci5l
eGFtcGxlLmRvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr1nYY1Qrll1r
uB/FqlCRrr5nvupdIN+3wF7q915tvEQoc74bnu6b8IbbGRMhzdzmvQ4SzFfVEAuM
MuTHeybPq5th7YDrTNizKKxOBnqE2KYuX9X22A1Kh49soJJFg6kPb9MUgiZBiMlv
tb7K3CHfgw5WagWnLl8Lb+ccvKZZl+8CAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GB
AHpoRp5YS55CZpy+wdigQEwjL/wSluvo+WjtpvP0YoBMJu4VMKeZi405R7o8oEwi
PdlrrliKNknFmHKIaCKTLRcU59ScA6ADEIWUzqmUzP5Cs6jrSRo3NKfg1bd09D1K
9rsQkRc9Urv9mRBIsredGnYECNeRaK5R1yzpOowninXC
-----END CERTIFICATE REQUEST-----

「-----BEGIN CERTIFICATE REQUEST-----」や「-----END CERTIFICATE REQUEST-----」も含めてCSRなので、認証局への申請時には注意してください。

CSRの作成

OpenSSLのインストール

OpenSSLは既にインストールされていることが多いと思いますが、入っていない場合はここでインストールします。

$ sudo yum install -y openssl-devel

プライベートキーの作成

$ openssl genrsa -out foo.pem 2048

-outで指定したファイル名の秘密鍵が生成されます。

$ ls
foo.pem

なお、ビット長(上記コマンド例では2048)は認証局によって異なります。*2

ここで作成した秘密鍵を認証局から発行されるサーバ証明書と一緒に後で使用します。

CSR本体の作成

$ openssl req -new -key foo.pem -out foo.csr

Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Kanagawa
Locality Name (eg, city) [Default City]:Yokohama
Organization Name (eg, company) [Default Company Ltd]:Foo
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your hostname) []:example.com
Email Address []:example@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$ ls
foo.csr  foo.pem

-outで指定したファイル名のCSRが生成されているはずです。

*1:予想はしていましたが、CSRググるとCorporate Social Responsibilityばっかり出てきて鬱陶しいです。

*2:ただ、今だとほとんどの認証局が2048bitだとは思います。

RailsアプリをEC2にデプロイしてみる。

タイトルの通り、RailsアプリをAWSのEC2で動かしてみます。

前提

環境

  • Amazon Linux AMI 2013.03.1

想定

  • デプロイするアプリケーションの名前は「pic_share」。
  • DBはEC2上にインストールしたPostgreSQLを使う。

EC2側の設定

ユーザ周りの設定

EC2インスタンスを立ちあげ、ローカルマシンから

$ scp -i ~/.ssh/hogehoge.pem ~/.ssh/id_rsa.pub ec2-user@ec2_server:~

EC2インスタンスにログイン後、

$ sudo passwd
$ sudo su
# useradd rails
# visudo
# passwd rails
# mkdir --mode 700 /home/rails/.ssh
# mv id_rsa.pub /home/rails/.ssh/authorized_keys
# chmod 600 /home/rails/.ssh/authorized_keys
# chown -R rails:rails /home/rails/.ssh

これで、ssh rails@ec2_serverできますよっと。

Ruby周りの設定

Amazon Linuxでrbenvを使ってRuby2.0を入れてみた。」のように、rbenvを使ってRubyを入れます。
ここでは、とりあえずRuby1.9.3とBundlerを入れておきます。

$ rbenv install 1.9.3-p429
$ rbenv global 1.9.3-p429
$ gem install bundler

Web/Appサーバ周りの設定

WebサーバとAppサーバをインストールしておきます。

$ sudo yum install -y gcc-c++ libcurl-devel httpd-devel
$ gem install passenger
$ source ~/.bash_profile
$ passenger-install-apache2-module

passenger-install-apache2-moduleの指示に従って、Apacheの設定ファイルに以下の内容を追記します。

#/etc/httpd/conf/httpd.conf
LoadModule passenger_module /home/rails/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/passenger-4.0.5/libout/apache2/mod_passenger.so
PassengerRoot /home/rails/.rbenv/versions/1.9.3-p429/lib/ruby/gems/1.9.1/gems/passenger-4.0.5
PassengerDefaultRuby /home/rails/.rbenv/versions/1.9.3-p429/bin/ruby

また、apacheの実行ユーザを変更します。

#/etc/httpd/conf/httpd.conf
user rails
group rails

そして、自動起動設定。

$ sudo /sbin/chkconfig httpd on

まだ、アプリケーションが置かれているディレクトリが存在しないため、DocumentRoot等の設定はデプロイ後に行うことにします。

DB周りの設定

今回はPostgreSQLを使用します。

$ sudo yum install -y postgresql postgresql-devel postgresql-server postgresql-libs
$ sudo service postgresql initdb
$ sudo /sbin/chkconfig postgresql on
$ sudo service postgresql start

PostgreSQLのユーザとテーブルを作り、パスワードを設定します。

$ sudo su - postgres
$ createuser -a pic_share
$ createdb -E UTF8 -O pic_share pic_share_production
$ psql -c "alter user pic_share with password 'hogehoge'"
$ exit

PostgreSQLの設定ファイルを編集します。

#/var/lib/pgsql9/data/pg_hba.conf
local  all  all  md5
$ sudo sudo service postgresql reload

ローカル側でデプロイの準備

Capistrano設定

$ gem install capistrano capistrano_colors
$ capify .
#config/deploy.rb
require "bundler/capistrano"
load "deploy/assets"

# Git repository                                                                                                                            
set :scm,         "git"
set :repository,  "git@github.com:user_name/repo_name.git"
set :branch,      "master"

ssh_options[:forward_agent] = true
default_run_options[:pty]   = true

# Server setting
ec2 = "ec2-x-x-x-x.ap-northeast-1.compute.amazonaws.com"
role :web, ec2
role :app, ec2
role :db,  ec2, :primary => true

set :application, "pic_share"
set :user, "rails"
set :use_sudo, false
set :deploy_to, "/home/#{user}/#{application}"
set :rails_env, "production"
default_run_options[:shell] = '/bin/bash --login'
#Gemfile
gem 'sqlite3', group: [:development, :test]
gem 'pg', group: :production
gem 'therubyracer', :platforms => :ruby
#config/database.yml
production:
  adapter: postgresql
  database: pic_share_production
  username: pic_share
  password: hogehoge
  encoding: utf8
$ cap deploy:setup
$ cap deploy
$ cap deploy:migrate

EC2側の設定

最後にApacheのDocumentRootを先ほどデプロイしたディレクトリに設定します。

<VirtualHost *:80>
  ServerName ec2-x-x-x-x.ap-northeast-1.compute.amazonaws.com
  DocumentRoot /home/rails/pic_share/current/public
</VirtualHost>
$ sudo service httpd restart

さいごに

以上、EC2でRailsを走らせるための一部始終でした。
特別なことは何もしていませんが、最初から最後まで通してやると地味にいろいろ引っかかって疲れるため、まとめてみました。

つかれた。

GithubにあるプライベートリポジトリをCapistranoでデプロイ

やりたいことはタイトルの通りです。

ここでは、RailsアプリをEC2にデプロイするつもりで書いていきます。
サーバ側の環境構築(SSHやユーザ関連の設定、DBのインストールなど)は終わっている前提で。

Capistranoの理解に関しては割と自信がないので、ツッコミお待ちしています。

結論

初めに、出来上がるdeploy.rbを載せてしまいます。

#config/deploy.rb
require "bundler/capistrano"
load "deploy/assets"

# Git repository
set :scm,         "git"
set :repository,  "git@github.com:foo/bar.git"
set :branch,      "master"

ssh_options[:forward_agent] = true
default_run_options[:pty]   = true

# Server setting
ec2 = "ec2-x-x-x-x.ap-northeast-1.compute.amazonaws.com"
role :web, ec2
role :app, ec2
role :db,  ec2, :primary => true

set :application, "app_name"
set :user, "server_user_name"
set :use_sudo, false
set :deploy_to, "/home/#{user}/#{application}"
set :rails_env, "production"
default_run_options[:shell] = '/bin/bash --login'

deploy.rbで何をやっているのか

上のdeploy.rbの記述内容のうち、ほとんどはCapistranoではおなじみのものだと思います。

今回のプライベートリポジトリ関連のキモを簡単に説明していきます。

set :repository, "git@github.com:foo/bar.git"

デプロイするコードが置かれているGithubのリポジトリを指定します。

この引数をGitプロトコルではなくHTTPSで指定するとソースの取得に失敗するので注意してください。

ssh_options[:forward_agent] = true

ssh_options[:forward_agent]をtrueに設定すると、デプロイ先サーバがGithubからgit cloneする際にCapistranoコマンドを実行したユーザの秘密鍵が使われます。

つまり、「cap deployを実行するユーザの公開鍵がデプロイ先サーバとGithubの両方に登録されている必要がある」代わりに「デプロイ先サーバにGithub接続用の鍵ペアを新規作成→公開鍵をGithubに登録」という作業が不要になります。

また、同じこと以下のようにも書けます。

set :ssh_options, { forward_agent: true }

default_run_options[:pty] = true

Capistranoでは、Github上のコードをデプロイ先のホストへ持ってくるため、git cloneします。
このときの git clone がデプロイ先ホストからGithubへの初めての接続である場合、以下のようなエラーメッセージが出てデプロイに失敗します。

[host :: err] Host key verification failed.
[host :: err] fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.

このエラーメッセージが表示されているとき、GithubへのSSH接続に際して「Are you sure you want to continue connecting (yes/no)?」みたいな確認*1が行われています。

そこで、default_run_options[:pty] = true を指定しておくことによって、この質問にyesと答えて先へ進むことができます*2

さいごに

プライベートリポジトリにあるコードをデプロイする方法をググってみたところ、情報が少なかったので「俺がまとめてやるぜー!」と意気込んでまとめてみましたが、いざ書いてみると全然大したことしてない感じになってしまいました。

書き終わってから「もしかして、まとめるまでもないくらい簡単に設定できるからエントリが書かれてないだけなのでは?」と思いましたが、せっかく書いたので公開しておきます。

間違ってたらごめんね☆

*1:よく見るやつです。

*2:たぶん。結果的にうまく動いたものの、なぜうまく動いたのかわからない。それらしいドキュメントもソースも見当たらなくてぐぬぬ。教えてエロい人。

Spree2.0のローカライズ(2)

前回のSpree2.0のローカライズ(1)に引き続き、Spree2.0のローカライズを行なっていきます。

前回、問題になっていたJavaScriptの件はIssuesに書いたら修正してくれました☆*1

ゾーンの設定

Web上の管理画面から設定していきます。
国にJapanを指定します。

f:id:xxxcaqui:20130527171814p:plain

配送方法の設定

同じく、Web上の管理画面から設定していきます。
先ほど登録したゾーン(Japan)を指定するのを忘れないように。

f:id:xxxcaqui:20130527172054p:plain

都道府県の設定

国(Japan)を選んでから、都道府県を追加します。
面倒なのでとりあえずは1つか2つでいいです。

f:id:xxxcaqui:20130527172434p:plain

商品を表示する

デフォルト設定でSpreeをインストールすると、商品等のサンプルデータが一緒に入りますが、日本語化を行うとそれらの商品がショップ画面に表示されなくなります。

f:id:xxxcaqui:20130527175413p:plain

また、この状態で商品を新規作成しても、その商品が表示されません。

これらの商品を表示するためには、商品に「発売開始日・入荷日」を設定します。

f:id:xxxcaqui:20130531034520p:plain

「発売開始日・入荷日」の日付が設定されていない場合および未来に設定されている場合、その商品はショップ画面に表示されません。*2*3

まとめ

Spreeを日本語化するにあたって引っかかりやすい箇所はこんな感じだと思います。
全然、丁寧な感じじゃなくてすみません。

そして、間違いがあればツッコミお願いします。
逆に僕に答えられることなら答えたいと思います。

ともにコメント欄までよろしくお願いします。

今後

とりあえず日本語化するところまではできましたが、

  • いちいち都道府県設定をするのが面倒。
  • 国内向けサイトの場合、配送先住所の選択欄に「国名」とかいらない。
  • 氏名の順序が「firstname familyname」になっている。
  • 住所も欧米風
  • 特定商品取引法の表示とか

などなど、変更したいところが結構あるので、このあたりを簡単に変更できるようにしたい。再利用可能な形で!

*1:spree/spree_i18nのmasterと3-0-stableに修正適用済みです。

*2:いちいち発売開始日を設定しなければならないのは面倒じゃね?

*3:というわけで、発売開始日が空欄の場合にも表示するようにプルリ送ってみた。たぶんリジェクトされる。