NewRelicでSinatraアプリを監視

NewRelicでSinatraアプリの監視を始めたのでメモ。
NewRelic Sinatra support

Gemfile:

source "https://rubygems.org"

gem "sinatra"
gem "newrelic_rpm"

config.ru:

$:.unshift(File.expand_path("../lib", __FILE__))
 
require "sinatra_app"
require "newrelic_rpm"

NewRelic::Agent.after_fork(:force_reconnect => true)
 
 run SinatraApp.new

newrelic.yml:

ダウンロードしてconfig/newrelic.ymlに配置。

$ cd /path/to/sinatra
$ mkdir -p config
$ mv -i /path/to/newrelic.yml config/.

Redmineインストール

プロジェクト管理にRedmineを導入したのでインストールのメモ。
MySQLがインストール済であることが前提です。

Redmine用データベース作成

パスワードは適当に生成しておきます。

$ ruby -e 'l=("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a;p Array.new(8){l[rand(l.size)]}.join'

db/user作成

$ mysql -uroot -p
mysql> create database redmine;
mysql> grant all privileges on redmine.* to redmine@localhost identified by "secret";
mysql> status
--------------
/usr/local/mysql/bin/mysql  Ver 14.14 Distrib 5.5.31, for Linux (x86_64) using  EditLine wrapper

Connection id:      112
Current database:   
Current user:       root@localhost
SSL:            Not in use
Current pager:      stdout
Using outfile:      ''
Using delimiter:    ;
Server version:     5.5.31-log Source distribution
Protocol version:   10
Connection:     Localhost via UNIX socket
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
UNIX socket:        /tmp/mysql.sock
Uptime:         31 days 15 hours 38 min 10 sec

Threads: 2  Questions: 82196  Slow queries: 0  Opens: 1291  Flush tables: 1  Open tables: 64  Queries per second avg: 0.030
--------------
mysql> quit

latin1とかになっている場合はutf8に変更しておきます。

my.cnf:

[mysqld]
character-set-server = utf8
skip-character-set-client-handshake
collation-server = utf8_general_ci
init-connect = SET NAMES utf8

[mysql]
default-character-set = utf8

設定ファイルの場所がわからない場合は以下のコマンドで調べられます。

$ mysql --help|grep /etc/my.cnf

Redmineインストール

ダウンロード/解凍/配置

$ cd /usr/local/src
$ wget -c http://rubyforge.org/frs/download.php/76933/redmine-2.3.1.tar.gz
$ tar zxvf redmine-2.3.1.tar.gz
$ mv -i redmine-2.3.1 /var/lib/redmine
$ cd /var/lib/redmine
$ mkdir public/plugin_assets

DB設定

$ cp config/database.yml.example config/database.yml
$ vi config/database.yml

database.yml:

production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: secret
  encoding: utf8

メール設定

$ vi config/configuration.yml

configuration.yml:

default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      enable_starttls_auto: true
      address: "smtp.gmail.com"
      port: 587
      domain: "smtp.gmail.com"
      authentication: :plain
      user_name: "foo@gmail.com"
      password: "secret"

rmagick_font_path: /usr/share/fonts/ipa-pgothic/ipagp.ttf

gemインストールとマイグレーション

$ bundle install --without development test postgresql sqlite --path vendor/bundle
$ bundle exec rake generate_secret_token
$ bundle exec rake db:migrate RAILS_ENV=production

Passengerインストール

Nginxもあわせてインストールされる。

$ gem install passenger
$ passenger-install-nginx-module

Nginx設定

ディレクトリ作成

/usr/local/nginxにインストールした前提です。
ssl.crtssl.keyはHTTPのみの場合は必要ありません。
redmine.example.comは読み替えて下さい。

$ mkdir -p /usr/local/nginx/conf/conf.d
$ mkdir -p /usr/local/nginx/vhosts/redmine.example.com/{logs,ssl.crt,ssl.key}

証明書配置

$ mv server.chained.crt /usr/local/nginx/vhosts/redmine.example.com/ssl.crt/.
$ mv server.key /usr/local/nginx/vhosts/redmine.example.com/ssl.key/.

今回は買った証明書を利用していますが、自己署名証明書を利用する場合は別途作成して下さい。

$ openssl genrsa -des3 -out server.key 1024
$ openssl rsa -in server.key -out server.key
$ openssl req -new -x509 -out server.crt -key server.key -days 365

Nginx設定

conf/nginx.conf:

passenger_rootpassenger_rubyは環境によって異なります。
passenger-install-nginx-moduleした時に表示されるのでそれを使って下さい。

user nginx nginx;
worker_processes 2;
worker_priority 0;
worker_rlimit_nofile 8192;

error_log logs/error.log notice;
pid logs/nginx.pid;

events {
  multi_accept off;
  worker_connections 1024;
  use epoll;
}

http {
  include mime.types;
  default_type application/octet-stream;

  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

  log_format ltsv "time:$time_iso8601"
                  "\thost:$remote_addr"
                  "\txff:$http_x_forwarded_for"
                  "\tmethod:$request_method"
                  "\tpath:$request_uri"
                  "\tstatus:$status"
                  "\tua:$http_user_agent"
                  "\treq_size:$request_length"
                  "\treq_time:$request_time"
                  "\tres_size:$bytes_sent"
                  "\tbody_size:$body_bytes_sent"
                  "\tapp_time:$upstream_response_time";

  sendfile on;
  server_tokens off;
  keepalive_timeout 10;
  index index.html index.htm;
  error_page 500 502 503 504 /50x.html;

  passenger_root /usr/local/lib/ruby/gems/1.9.1/gems/passenger-4.0.5;
  passenger_ruby /usr/local/bin/ruby;

  include conf.d/*.conf;
}

conf/conf.d/redmine.example.com.conf:

server {
  listen 443 ssl;
  server_name redmine.example.com;
  root /var/lib/redmine/public;
  index index.html index.htm;
 
  access_log /usr/local/nginx/vhosts/redmine.example.com/logs/ssl_access.log ltsv;
  error_log /usr/local/nginx/vhosts/redmine.example.com/logs/ssl_error.log info;
 
  ssl on;
  ssl_certificate /usr/local/nginx/vhosts/redmine.example.com/ssl.crt/server.chained.crt;
  ssl_certificate_key /usr/local/nginx/vhosts/redmine.example.com/ssl.key/server.key;
 
  ssl_session_timeout 5m;
 
  ssl_protocols SSLv2 SSLv3 TLSv1;
  ssl_ciphers HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers on;
 
  location / {
    try_files $uri @proxy_to_rails;
  }
 
  location @proxy_to_rails {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto https;
    proxy_redirect off;
 
    # for Passenger
    passenger_enabled on;
  }
}

Nginx起動

$ /usr/local/nginx/sbin/nginx -t
$ /usr/local/nginx/sbin/nginx

herokuでsinatraアプリをデプロイしてみた

久々に使いたくなってさわってみたら忘れてたのでメモ。

herokuコマンドインストール

gemでインストールしたらHeroku Toolbelt使えって言われたのでダウンロードしてインストール。
foremanとかも一緒に入るみたいです。

$ gem install heroku
...
...
 !    The `heroku` gem has been deprecated and replaced with the Heroku Toolbelt.
 !    Download and install from: https://toolbelt.heroku.com
 !    For API access, see: https://github.com/heroku/heroku.rb

SSH鍵再登録

SSHの鍵も新しい鍵にしていたので登録しなおします。

$ heroku login
$ heroku keys:clear
$ heroku keys:add

簡単なSinatraアプリを作る

Gemfile:

source "https://rubygems.org"

gem "sinatra"

Procfile:

web: bundle exec rackup config.ru -p $PORT

sample.rb:

require "bundler/setup"
require "sinatra/base"

class Sample < Sinatra::Base
  get "/" do
    "Hello Heroku"
  end
end

config.ru:

$:.unshift(File.dirname(__FILE__))

require "sample"

run Sample

.gitignore:

.bundle

ローカルで起動してみる:

$ foreman start

デプロイしてみる

$ git init
$ git add .
$ git commit -m "first commit"
$ heroku create
$ git remote -v
$ git push -u heroku master
$ heroku open

BitbucketとJenkinsを連携する

以下はJenkinsの認証にJenkinsのユーザデータベースを使ってます。

Jenkins実行ユーザのSSH鍵作成

以下はrootユーザにて実行。

ssh-keygen -t rsa
mv -i ~/.ssh /var/lib/jenkins/.
chown -R jenkins. /var/lib/jenkins

Bitbucketに公開鍵を登録

Manage account>Ssh keysから作成した公開鍵を登録する。

bitbucketユーザ作成

Jenkinsの管理>ユーザの管理>ユーザ作成にてbitbucketユーザを作成し、グローバルセキュリティの設定から権限を設定する。
開発者>bitbucket>設定>APIトークンの表示でAPIトークンをメモしておく。

Jenkinsプロジェクトの設定変更

ビルド・トリガ>リモートからビルドの認証トークンを設定してメモっておく。

Bitbucket設定

Bitbucketのリポジトリ設定のServicesにてJenkinsをAdd Serviceして以下の項目を入力してSave。

Endpoint: https://bitbucket:APIトークン@Jenkins用vhostのURI
Project name: Jenkinsで設定しているプロジェクト名
Token: 認証トークン

simplecovのカバレッジをJenkinsから参照する

simplecov, simplecov-rcovインストール

group :development, :test do
  gem 'simplecov'
  gem 'simplecov-rcov'
end
$ bundle install

spec_helper.rb編集

以下を追加(先頭):

require "simplecov"
require "simplecov-rcov"
SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
SimpleCov.start do
  add_filter "spec"
  add_filter "vendor"
end

Jenkinsプロジェクトの設定変更

ビルド後の処理>Publish Rcov report:
(Ruby metrics pluginが必要)

coverage/rcov

RSpecのテスト結果をJenkinsから参照する

ci_reporterインストール

Gemfile:

group :development, :test do
  gem 'ci_reporter'
end
$ bundle install

Rakefile変更

Rakefileに以下を追加:

require 'ci/reporter/rake/rspec'

Jenkinsプロジェクトの設定変更

ビルド>シェルの実行:

export PATH=$PATH:/usr/local/bin
which bundle || gem install bundler
bundle install --path vendor/bundle
bundle exec rake ci:setup:rspec spec

ビルド後の処理>JUnitテスト結果の集計:

spec/reports/*.xml