Help us understand the problem. What is going on with this article?

Redmine on unicorn+nginx Chef cookbook

More than 5 years have passed since last update.

redmineをunicorn+nginxで動かすためのchef用のCookbookです。http://t.nzk.me/entry/2012/12/28/144730で紹介されている手順を元に作成しています。

前提条件

  • OS: Ubuntu 12.04
  • DB: mysql

    mysqlについては、chefにより自動的なインストールが可能ですが、このcookbookでは、mysqlパッケージ自体のインストールは含んでいません。mysqlのインストールについては、別のcookbookを使用する必要があります。

  • Redmine: 2.3.1

  • chef-solo

変更が必要なファイル

chef-repo/nodes/redmine.example.com.jsonを環境に合わせて編集してください。

download-urlについて

redmineパッケージをダウンロードするURLを指定します。

run_listについて

mysql::serverについては、このcookbookには含まれていません。以下のコマンドで事前にmysqlインストール用のcookbookを導入してください。

knife cookbook site install mysql

実行手順

chefを実行する端末から、OSインストール直後のサーバ(sshで接続出来る必要はあります)に対してredmineをインストールする場合、以下のコマンドでredmineの起動可能な状態まで自動的に設定されます(たぶん)。

knife solo prepare redmine.exampl.ecom
knife solo cook redmine.example.com

nginxとunicornの起動は以下の通りです。

sudo /etc/init.d/unicorn start
sudo /etc/init.d/nginx start

関連ファイル

  • chef-repo/nodes/redmine.example.com.json

    インストールするホスト毎の設定ファイルです。

  • chef-repo/cookbooks/redmine-unicorn-nginx/recipes/default.rb

    redmineパッケージをダウンロードし、インストールするためのレシピです。必要なパッケージも自動的に取得します。unicorn及びnginxのインストール、設定も行いますが、mysqlパッケージのインストールは含まれていないため、事前に別のcookbookを用意する必要があります。

  • chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/database.yml.erb

    redmineがデータベースに接続するための設定ファイルです。mysqlを前提としています。

  • chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/initd_unicorn.erb

    uncornを起動するための設定ファイルです。http://www.mk-mode.com/octopress/2013/01/23/unicorn-start-script/を参考にさせて頂きました。

  • chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/nginx.conf.erb

    nginxの設定ファイルです。

  • chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/virtual.vconf.erb

    nginxの設定ファイルです。

  • chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/unicorn.rb.erb

    unicornの設定ファイルです。

/chef-repo/nodes/redmine.example.com.json
{
    "mysql": {
        "server_root_password": "password",
        "server_repl_password": "password",
        "server_debian_password": "password"
    },
    "redmine": {
        "db_user": "redmine",
        "db_server": "localhost",
        "db_password": "password",
        "download-url": "http://rubyforge.org/frs/download.php/76933/redmine-2.3.1.tar.gz"
    },
    "nginx": {
        "server_name": "redmine.example.com"
    },
    "run_list": [
        "mysql::server",
        "mysql::client",
        "redmine-unicorn-nginx"
    ]
}
chef-repo/cookbooks/redmine-unicorn-nginx/recipes/default.rb
# -*- coding: utf-8 -*-

execute "echo \"CREATE DATABASE redmine character set utf8\" | mysql -u root -p#{node['mysql']['server_root_password']}" do
  returns [0, 1]
end
execute "echo \"CREATE USER '#{node['redmine']['db_user']}'@'#{node['redmine']['db_server']}' IDENTIFIED BY '#{node['redmine']['db_password']}'\" | mysql -u root -p#{node['mysql']['server_root_password']}" do
  returns [0, 1]
end

execute "echo \"GRANT ALL PRIVILEGES ON redmine.* to #{node['redmine']['db_user']}\" | mysql -u root -p#{node['mysql']['server_root_password']}"

# ruby 1.9.3で動作させる場合の設定です。必須ではありません。
#apt_package "ruby1.9.3" do
#  action :install
#end

#execute "" do
#  command <<-EOH
#update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.9.3 500 \
#                    --slave   /usr/bin/ri   ri   /usr/bin/ri1.9.3 \
#                    --slave   /usr/bin/irb  irb  /usr/bin/irb1.9.3 \
#                    --slave   /usr/bin/erb  erb  /usr/bin/erb1.9.3 \
#                    --slave   /usr/bin/rdoc rdoc /usr/bin/rdoc1.9.3
#  EOH
#end

#execute "update-alternatives --set ruby /usr/bin/ruby1.9.3"

base_name = File.basename(node['redmine']['download-url'])

remote_file "redmine-archive" do
  source "#{node['redmine']['download-url']}"
  path "/usr/local/#{base_name}"
  not_if do
    File.exists?("/usr/local/#{base_name}")
  end
end

execute "tar zxvf #{base_name}" do
  cwd "/usr/local"
end

dir_name = base_name.gsub(/^(.+?)(\.tar\.gz)|(\.zip)$/, "\\1")

link "/usr/local/redmine" do
  to "/usr/local/#{dir_name}"
end

template "database.yml" do
  path "/usr/local/redmine/config/database.yml"
end

apt_package "make" do
  action :install
end

apt_package "ruby-dev" do
  action :install
end

apt_package "rake" do
  action :install
end

apt_package "libxml2-dev" do
  action :install
end

apt_package "libxslt-dev" do
  action :install
end

apt_package "libmagickwand-dev" do
  action :install
end

#apt_package "graphicsmagick-libmagick-dev-compat" do
#  action :install
#end

execute "gem install bundler" do
  cwd "/usr/local/redmine"
end

execute "bundle install" do
  cwd "/usr/local/redmine"
end

execute "bundle check" do
  cwd "/usr/local/redmine"
end

execute "rake generate_secret_token" do
  cwd "/usr/local/redmine"
end

execute "rake db:migrate" do
  environment(
              "RAILS_ENV" => "production"
              )
  cwd "/usr/local/redmine"
end

directory "/usr/local/redmine/public/plugin_asserts" do
  mode 777
end

execute "gem install unicorn"

# /usr/local/redmine/Gemfileにgem "unicorn"の記述が無いと、unicornの起動に失敗するため、gem "unicorn"の記述を追加します。
ruby "adding unicron text into redmine/Gemfile." do
  code <<-EOC
f = open("/usr/local/redmine/Gemfile", "r")
t = open("/tmp/redmine-uniconr-nginx-Gemfile.new", "w")

if f.grep(/^gem \"unicorn\"/).empty? then
  f.seek 0
  f.each do |line|
    if line =~ /^source .+/ then
      t.write line
      t.write "gem 'unicorn'\n"
    else
      t.write line
    end
  end
end

f.close
t.close
  EOC
end

execute "mv /tmp/redmine-uniconr-nginx-Gemfile.new /usr/local/redmine/Gemfile"

template "unicorn.rb" do
  path "/usr/local/redmine/config/unicorn.rb"
end

apt_package "nginx" do
  action :install
end

template "nginx.conf" do
  path "/etc/nginx/nginx.conf"
end

template "virtual.vconf" do
  path "/etc/nginx/conf.d/virtual.conf"
end

template "initd_unicorn" do
  path "/etc/init.d/unicorn"
  mode 755
end
chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/initd_unicorn.erb
#!/bin/sh

PATH=/bin:/usr/bin:/usr/local/bin

# move to project root directory
NAME=unicorn
ENVIROMENT=production

ROOT_DIR=/usr/local/redmine

PID="${ROOT_DIR}/tmp/pids/unicorn.pid"
CONF="${ROOT_DIR}/config/unicorn.rb"

start()
{
    cd $ROOT_DIR
    if [ -e $PID ]; then
        echo "$NAME already started";
        exit 1;
    fi
    echo "start $NAME";
    bundle exec unicorn_rails -c ${CONF} -E ${ENVIROMENT} -D -p 5001
}

stop()
{
    if [ ! -e $PID ]; then
        echo "$NAME not started";
        exit 1;
    fi
    echo "stop $NAME";
    kill `cat ${PID}`
    rm -f $PID
}

graceful_stop()
{
    if [ ! -e $PID ]; then
        echo "$NAME not started";
        exit 1;
    fi
    echo "stop $NAME";
    kill -QUIT `cat ${PID}`
    rm -f $PID
}

reload()
{
    if [ ! -e $PID ]; then
        echo "$NAME not started";
        start
        exit 0;
    fi
    echo "reload $NAME";
    kill -USR2 `cat ${PID}`
}

restart()
{
    if [ ! -e $PID ]; then
        echo "$NAME not started";
        start
        exit 0;
    fi
    echo "restart $NAME";
    stop
    start
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    graceful_stop)
        graceful_stop
        ;;
    reload)
        reload
        ;;
    restart)
        reload
        ;;
    *)
        echo "Syntax Error: release [start|stop|graceful_stop|reload|restart]"
        ;;
esac
chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/nginx.conf.erb
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_ruby /usr/bin/ruby;

    upstream redmine {
        server 127.0.0.1:5001;
    }

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}


#mail {
#   # See sample authentication script at:
#   # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#   # auth_http localhost/auth.php;
#   # pop3_capabilities "TOP" "USER";
#   # imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#   server {
#       listen     localhost:110;
#       protocol   pop3;
#       proxy      on;
#   }
# 
#   server {
#       listen     localhost:143;
#       protocol   imap;
#       proxy      on;
#   }
#}
chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/unicorn.rb.erb
worker_processes 2

listen File.expand_path("tmp/sockets/unicorn.sock", ENV['RAILS_ROOT'])
pid File.expand_path("tmp/pids/unicorn.pid", ENV['RAILS_ROOT'])

timeout 60

preload_app true

stdout_path File.expand_path("log/unicorn.stdout.log", ENV['RAILS_ROOT'])
stderr_path File.expand_path("log/unicorn.stderr.log", ENV['RAILS_ROOT'])

GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
        Process.kill(sig, File.read(old_pid).to_i)
      rescue Errno::ENOENT, Errno::ESRCH
      end 
    end 

    sleep 1
  end 

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
chef-repo/cookbooks/redmine-unicorn-nginx/templates/default/virtual.vconf.erb
server {
  listen 80;
  server_name <%= node[:nginx][:server_name] %>;

  access_log /var/log/nginx/redmine_access.log;
  error_log /var/log/nginx/redmine_error.log;

  proxy_connect_timeout 60;
  proxy_read_timeout    60;
  proxy_send_timeout    60;

  # auth_basic "Secret Area";
  # auth_basic_user_file "/home/www/rails/redmine/.htpasswd";

  location / {

    root /usr/local/redmine/public;
    if (-f $request_filename){
      break;
    }

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://redmine;
    proxy_redirect off;
  }
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away