orangeProse別館

orangeProse(本ブログ)の補助

Herokuチートシート:ネイキッドドメインとメール送信まで

f:id:hidex7777:20140915194425j:plain

さいきん、自サイトをHerokuで運用するようになったので、忘れないように自分用にメモ。

方針は次の通り:

  • アプリサーバにはUnicornを使う
  • ネイキッドドメインで運用(www.foobar.comじゃなくてfoobar.comで)
  • メールを送信する(ActionMailerを使う)
  • ドメイン維持(年980円ぐらい?)以外は無料で
  • いちおうMXレコードの登録まではやったたけど受信がめんどくせーのでやるならMandrill(メールのプラグイン)のAPIを各自見てくだしゃんせ

Heroku用にGemfileを書く

ruby '2.0.0'

gem 'rails', '4.0.5'

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
  gem 'unicorn'
end

gemのアップデート。

$ bundle install --without production
$ bundle update
$ bundle install
$ git commit -a -m "Update Gemfile.lock for Heroku"

--without productionはremembered optionなのでコマンドに保存される。

Unicornの設定

$ touch config/unicorn.rb
$ vi config/unicron.rb

worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

config/environments/production.rb

config.assets.compile = true

データベースの設定

config/database.yml

production:
  adapter: postgresql
  encoding: unicode
  # database: db/production.sqlite3
  pool: 5
  # timeout: 5000

Procfileとforemanでのテスト

./Procfile

web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb

Unicornがローカル開発環境にインストールされている必要があるけど)

ローカル環境の環境変数を./.envに。

$ echo "RACK_ENV=development" >> .env
$ echo "PORT=3000" >> .env
$ echo ".env" >> .gitignore
$ git add .gitignore
$ git commit -m "add .env to .gitignore"

foremanでテスト

$ gem install foreman
$ foreman start

ログインする

$ heroku login

または

$ heroku auth:login

ログアウトする

$ heroku logout

または

$ heroku logout

アプリを作成してデプロイ

$ heroku create foobar

または

$ heroku create

からの

$ git push heroku master
$ heroku run rake db:migrate
$ heroku ps:scale web=1
$ heroku ps
$ heroku open

サブドメイン名をリネームする

$ heroku rename foobar

必要ないけど。いちおう。

デプロイに失敗したときは

$ rake assets:precompile
$ git add .
$ git commit -m "add precompiled assets for Heroku"
$ git push heroku master

デプロイ時のエラーを取得

$ heroku logs

または

$ heroku logs --tail

実行環境の確認

$ heroku run console
Ruby console for foobar.herokuapp.com
>> Rails.env
=> "production"
>> Rails.env.production?
=> true

SSLを使う場合

config/environments/production.rb

FooBar::Application.configure do
(…)
  config.force_ssl = true
(…)
end
$ git commit -a -m "add SSL in production"
$ git push heroku
$ heroku run rake db:migrate

本番データベースをリセットする

$ heroku pg:reset DATABASE
$ heroku run rake db:migrate

アプリを強制再起動する

$ touch foo
$ git add foo
$ git commit -m "foo"
$ git push horoku

再度デプロイすればいいということ。

どのアカウントでログインしているのか

$ heroku auth:whoami

CloudFlareでネイキッドドメイン

CloudFlareドメインを入れろと言われたら、自分のドメインを入力(例としてここではfoobar.comとする)。スキャンがはじまる。

DNS Records for foobar.com:

CNAME foobar.com is an alias of hoge.fuga.com ACTIVE

みたいに書いてある画面の設定アイコンをクリック。というか、あとでも設定できる。DNS Zone設定で、CNAMEのfoobar.comのValueをfoobar.herokuapp.comにすればよい。

ネームサーバを変えろと言われるので、お名前ドットコムとかの、自分のドメインを管理しているネームサーバを言われたとおりに変える。

http://foobar.comでアクセスできるのを確認する。

ネイキッドドメインの方針。

  • www.foobar.comにアクセスしたらfoobar.comにリダイレクトする。
  • foo.foobar.comのような存在しないサブドメインも同様。

DNS Zoneを次のように設定:

  • CNAME www foobar.herokuapp.com
  • CNAME * foobar.herokuapp.com

My websitesのページで設定アイコンをクリックしてPage Rulesを選択。

f:id:hidex7777:20140915202746p:plain

無料なら3パターンまでルールを登録できる。

Add new ruleで*.foobar.com

Forwarding http://foobar.com

Forwarding type Permanent 301

(参考記事)

メールを送れるようにする

まずGmailから直接送れるか、試してみる

Gmail使って大量メール一斉送信をすると、そっこーでアカウントロックされるとのことなので、一通でも無理なのか、試してみる。

開発環境と同じ設定を書いてみる。

ActionMailerでは

default from: 'FooBar <foobar@gmail.com>'

みたいに、gmailから送信されたことにしている。

confib/environments/producution.rb

  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :enable_starttls_auto => true,
    :address => 'smtp.gmail.com',
    :port => '587',
    :domain => 'smtp.gmail.com',
    :authentication => 'plain',
    :user_name => 'foobar@gmail.com',
    :password => 'foobar'
  }

ダメだった。

一通でも、不正なログインで、ブロック。親切設計のGoogle

プラグインを使う

2014.09.10時点で使用できるメールプラグイン(SMSを除く)

  • Mandrill(月12000通無料)(Mandrill.comにログインしたら1時間250通のリミットもあるようなことが書いてあった)
  • Mailgun(1日300通無料=月9000通)
  • Mail2Webhookβ(受信メールをWEBアプリへのPOSTとして扱うプラグイン
  • CloudMailIn(月200通)
  • SendGrid(1日200通無料=月6000通)
  • Postmark(月10000通無料)

第一候補がMandrillで第二候補がPostmark。

けっきょくMandrillでよさげだったので、ここではMandrillだけ紹介する。

Mandrill

$ heroku addons:add mandrill:starter

でもプロヴィジョンできるけれどもドキュメントみながらやりたいのでHerokuのアドオンページからログインする。

(Oh...クレカ登録してなかったからハネられた…)

Mandrillのドキュメントを見ながら進める。

MANDRILL_APIKEYというのが使えるようになっているはずなので、確認する。

$ heroku config:get MANDRILL_APIKEY
foobarfoobarfoobarfoob

$ heroku config -s
↑これで環境変数が見られる。ユーザ名も記録しておいたほうがよい。

開発環境でテスト。Foremanで.envにMANDRILL_APIKEYを書いておく(↓の設定ファイルを使うならユーザ名も必要か)。

MANDRILL_APIKEY=foobarfoobarfoobarfoob

設定サンプルを見ながらconfig/environments/production.rbを書き換える。

  config.action_mailer.raise_delivery_errors = false
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :enable_starttls_auto => true,
    :address => 'smtp.mandrillapp.com',
    :port => '587',
    :domain => 'heroku.com',
    :authentication => 'plain',
    :user_name => ENV['MANDRILL_USERNAME'],
    :password => ENV['MANDRILL_APIKEY']
  }

できた。Gmailで受信すると、送信者名の隣に「経由」って出てなんとなく嫌だけど仕方がない。

受信もする場合:MXレコードの設定

http://mandrill.com/にユーザ名(heroku config -sで分かる)とパスワード(APIキーがパスワード)でログインできるので、ログインしてみる。

Inboundセクションで、ドメインを入力できるので自分のドメインを入れる。

DNSでMXを設定してないのでinvalidと出ている。

DNS Settings]ボタンをクリックすると、DNSサーバ名が2つ表示される。

別タブでCloudFlare開く。

自分のドメインDNS Settingsを開く。

TypeをMX、Nameを自分のドメインに、ValueをMandrillのサーバ、Priorityを10。

もう一行に、もう一つのMandrillサーバ名入れて、Priorityを20。

[I'm done]なんちゃらボタンを押す。

Mandrillに戻って[Test]ボタンを押すとvalidになる。

ActionMailerのコード(差出人のところ)を書き換える。

default from: 'FooBar <info@foobar.com>'

このドメインへの送信(こっちからすれば、受信)は、InboundにあるRoutesを設定する。

アプリに対するPOSTデータとして送信されるので、うまいことフックするアプリを書く。

APIドキュメントを参照されたし。

(参考記事)