diff --git a/Cheffile b/Cheffile index dc8c403..1bc6075 100644 --- a/Cheffile +++ b/Cheffile @@ -46,8 +46,7 @@ cookbook "nginx", cookbook "ruby", :git => "git@github.com:express42-cookbooks/ruby.git" -cookbook "redmine", - :git => "git@github.com:express42-cookbooks/redmine.git" +cookbook "redmine", :path => 'inhouse-cookbooks/redmine' cookbook "runit", :git => "git@github.com:express42-cookbooks/runit.git" diff --git a/Cheffile.lock b/Cheffile.lock index 00fd45f..65dff8d 100644 --- a/Cheffile.lock +++ b/Cheffile.lock @@ -28,13 +28,6 @@ GIT specs: postgresql (0.2.3) -GIT - remote: git@github.com:express42-cookbooks/redmine.git - ref: master - sha: d050e49e9de3f6c4d3f945fd858d3a5c8c079c7f - specs: - redmine (2.0.0) - GIT remote: git@github.com:express42-cookbooks/ruby.git ref: master @@ -125,6 +118,11 @@ PATH specs: fake (0.1.0) +PATH + remote: inhouse-cookbooks/redmine + specs: + redmine (2.0.0) + DEPENDENCIES apt (>= 0) base (>= 0) diff --git a/Vagrantfile b/Vagrantfile index b6ad5af..f4dfa9f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -3,6 +3,7 @@ Vagrant.configure("2") do |config| main.vm.box = "ubuntu12.04-chef11-chruby" main.vm.hostname = "etalon" config.vm.network :forwarded_port, guest: 8080, host: 7070 + config.vm.network :forwarded_port, guest: 80, host: 7071 main.vm.provider :virtualbox do |vb| vb.customize ["modifyvm", :id, "--memory", "2048"] end diff --git a/inhouse-cookbooks/redmine/Cheffile b/inhouse-cookbooks/redmine/Cheffile new file mode 100644 index 0000000..07f265c --- /dev/null +++ b/inhouse-cookbooks/redmine/Cheffile @@ -0,0 +1,15 @@ +#!/usr/bin/env ruby +#^syntax detection + +site 'http://community.opscode.com/api/v1' + +cookbook 'chef-client' +cookbook 'apt' +cookbook 'apache2', '>= 1.0.0' +cookbook 'git' +cookbook 'sqlite' +cookbook 'mysql' +cookbook 'rails' +cookbook 'passenger_apache2' +cookbook 'rvm' +cookbook 'redmine', :git => 'https://github.com/agencyrepublic/chef-redmine' \ No newline at end of file diff --git a/inhouse-cookbooks/redmine/README.rdoc b/inhouse-cookbooks/redmine/README.rdoc new file mode 100644 index 0000000..28e9a8f --- /dev/null +++ b/inhouse-cookbooks/redmine/README.rdoc @@ -0,0 +1,60 @@ += DESCRIPTION: + +Installs Redmine, a Ruby on Rails ticket tracking and wiki tool. + += REQUIREMENTS: + +== Platform: + +Tested on Ubuntu 9.04, uses the Opscode Apache2 cookbook which is Ubuntu/Debian specific. + +== Cookbooks: + +Opscode cookbooks (http://github.com/opscode/cookbooks/tree/master) + +* git +* sqlite +* mysql +* rails +* passenger_apache2 +* apache2 + += ATTRIBUTES: + +* redmine[:dl_id] - download id on the rubyforge page, needs to be updated on new redmine releases. +* redmine[:version] - release version of redmine to use. +* redmine[:dir] - directory where redmine will be installed. +* redmine[:db][:type] - type of database to use, default is sqlite. mysql or postgresql can be used, but the recipe will need to modified, and the next three attributes adjusted. +* redmine[:db][:user] - database user to connect as, default is redmine. +* redmine[:db][:password] - password for the user, default is a random string generated with OpenSSL::Random.random_bytes. +* redmine[:db][:hostname] - hostname of database server, default is localhost. + += USAGE: + +Including this recipe in a run_list, role or on a node will install Redmine as a Passenger application under Apache2. + + include_recipe "redmine" + +You'll probably want to customize it to fit your environment, as a site-cookbook, especially if you want to use something besides sqlite as the database backend. The attributes file has database_master commented out as an example start on using a node search to determine a database host. See the Chef wiki regarding searches for more information. + + http://wiki.opscode.com/display/chef/Search+Indexes + += LICENSE and AUTHOR: + +Author:: Joshua Timberman () +Copyright:: 2009, Opscode, Inc. + +Updated by Agency Republic in December 2012 for use with Redmine 2.x + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/inhouse-cookbooks/redmine/Vagrantfile b/inhouse-cookbooks/redmine/Vagrantfile new file mode 100644 index 0000000..1de16be --- /dev/null +++ b/inhouse-cookbooks/redmine/Vagrantfile @@ -0,0 +1,36 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant::Config.run do |config| + config.vm.box = "lucid64" + config.vm.box_url = "http://files.vagrantup.com/lucid64.box" + + # Forward guest port 80 to host port 8080 + config.vm.forward_port 80, 8080 + + config.vm.provision :chef_solo do |chef| + chef.json = { + :mysql => { + :server_root_password => 'banana', + :server_repl_password => 'banana', + :server_debian_password => 'banana', + :bind_address => '127.0.0.1' + }, + :redmine => { + :db => { + :type => 'mysql', + :user => 'root', + :password => 'banana' + } + } + } + chef.cookbooks_path = ["cookbooks"] + chef.add_recipe "apt" + chef.add_recipe "apache2" + chef.add_recipe "mysql" + chef.add_recipe "mysql::server" + chef.add_recipe "rvm" + chef.add_recipe "rails" + chef.add_recipe "redmine" + end +end \ No newline at end of file diff --git a/inhouse-cookbooks/redmine/attributes/default.rb b/inhouse-cookbooks/redmine/attributes/default.rb new file mode 100644 index 0000000..4b88776 --- /dev/null +++ b/inhouse-cookbooks/redmine/attributes/default.rb @@ -0,0 +1,37 @@ +# Cookbook Name:: redmine +# Attributes:: redmine +# +# Copyright 2009, Opscode, Inc +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +require 'openssl' + +pw = String.new + +while pw.length < 20 + pw << OpenSSL::Random.random_bytes(1).gsub(/\W/, '') +end + +set[:redmine][:dir] = "/srv/redmine-#{redmine[:version]}" + +default[:redmine][:dl_id] = "76589" +default[:redmine][:version] = "2.1.4" + +default[:redmine][:db][:type] = "postgresql" +default[:redmine][:db][:user] = "redmine" +default[:redmine][:db][:password] = pw +default[:redmine][:db][:hostname] = "localhost" +default[:redmine][:user] = "redmine" +default[:redmine][:ruby_version] = "1.9.3-p448" + diff --git a/inhouse-cookbooks/redmine/metadata.rb b/inhouse-cookbooks/redmine/metadata.rb new file mode 100644 index 0000000..261d182 --- /dev/null +++ b/inhouse-cookbooks/redmine/metadata.rb @@ -0,0 +1,11 @@ +maintainer "Opscode, Inc." +maintainer_email "cookbooks@opscode.com" +license "Apache 2.0" +description "Installs and configures redmine as a Rails app with unicorn" +version "2.0.0" + +recipe "redmine", "Installs and configures redmine under unicorn" + +%w{ ubuntu debian }.each do |os| + supports os +end diff --git a/inhouse-cookbooks/redmine/recipes/default.rb b/inhouse-cookbooks/redmine/recipes/default.rb new file mode 100644 index 0000000..1ea5431 --- /dev/null +++ b/inhouse-cookbooks/redmine/recipes/default.rb @@ -0,0 +1,132 @@ +# +# Author: Joshua Timberman +# Cookbook Name:: redmine +# Recipe:: default +# +# Copyright 2008-2009, Joshua Timberman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +user = node[:redmine][:user] + +%w(libpq5 libpq-dev imagemagick libmagickwand-dev).each { |p| package p } + +user user do + supports :manage_home => true + shell "/bin/bash" + home "/home/#{user}" +end + +ruby_install node[:redmine][:ruby_version] do + action :install +end + +ruby_set node[:redmine][:ruby_version] do + username user +end + +bash "install_redmine" do + cwd "/srv" + user "root" + code <<-EOH + wget http://rubyforge.org/frs/download.php/#{node[:redmine][:dl_id]}/redmine-#{node[:redmine][:version]}.tar.gz + tar xf redmine-#{node[:redmine][:version]}.tar.gz + chown -R #{user} redmine-#{node[:redmine][:version]} + EOH + not_if { ::File.exists?("/srv/redmine-#{node[:redmine][:version]}/Rakefile") } +end + +link "/srv/redmine" do + to "/srv/redmine-#{node[:redmine][:version]}" +end + +template "/srv/redmine/Gemfile" + +execute "/opt/chruby/bin/chruby-exec #{node[:redmine][:ruby_version]} -- bundle install" do + user user + cwd "/srv/redmine" + environment "HOME" => "/home/#{user}" +end + +execute "/opt/chruby/bin/chruby-exec #{node[:redmine][:ruby_version]} -- rake generate_secret_token" do + user user + environment "HOME" => "/home/#{user}" + cwd "/srv/redmine" +end + +template "/srv/redmine-#{node[:redmine][:version]}/config/database.yml" do + source "database.yml.erb" + owner "root" + group "root" + variables :database_server => node[:redmine][:db][:hostname] + mode "0664" +end + +sysctl( + "kernel.msgmax" => "65536", + "kernel.shmall" => "4294967296", + "kernel.shmmax" => "68719476736", + "kernel.msgmnb" => "65536", + "vm.swappiness" => "0", + "vm.overcommit_memory" => "0", + "fs.file-max" => "1048576" +) + +postgresql "main" do + databag "db" + configuration( + :version => "9.1", + :resources => { + :shared_buffers => "32MB", + :max_connections => 10 + } + ) + hba_configuration( + [ + { :type => "host", :database => "all", :user => "all", :address => "127.0.0.1/32", :method => "trust" }, + ] + ) +end + +execute "/opt/chruby/bin/chruby-exec #{node[:redmine][:ruby_version]} -- rake db:create db:migrate RAILS_ENV='production'" do + user user + environment "HOME" => "/home/#{user}" + cwd "/srv/redmine-#{node[:redmine][:version]}" + not_if { ::File.exists?("/srv/redmine-#{node[:redmine][:version]}/db/schema.rb") } +end + +template "/srv/redmine/config/unicorn.rb" do + source 'unicorn.rb.erb' + owner user + group user + variables( + :application_directory => "/srv/redmine", + :listen => "*:8080", + :worker_processes_num => 2, + :user => user, + :timeout => 180 + ) +end + +runit_service "#{user}_rails" do + run_restart false + template_name "redmine" + options :home_path => "/home/#{user}", + :app_path => "/srv/redmine", + :target_user => user, + :target_ruby => 'default', + :target_env => 'production' +end + +nginx_site "redmine" diff --git a/inhouse-cookbooks/redmine/templates/default/Gemfile.erb b/inhouse-cookbooks/redmine/templates/default/Gemfile.erb new file mode 100644 index 0000000..d8cc08a --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/Gemfile.erb @@ -0,0 +1,32 @@ +source 'http://rubygems.org' + +gem 'rails', '3.2.8' +gem "jquery-rails", "~> 2.0.2" +gem "i18n", "~> 0.6.0" +gem "coderay", "~> 1.0.6" +gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] +gem "builder", "3.0.0" +gem "unicorn" +gem "net-ldap", "~> 0.3.1" + +# Database gems +platforms :mri, :mingw do + group :postgresql do + gem "pg", ">= 0.11.0" + end +end + +gem "ruby-openid", "~> 2.1.4", :require => "openid" +gem "rack-openid" + +local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") +if File.exists?(local_gemfile) + puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v` + instance_eval File.read(local_gemfile) +end + +# Load plugins' Gemfiles +Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| + puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` + instance_eval File.read(file) +end diff --git a/inhouse-cookbooks/redmine/templates/default/database.yml.erb b/inhouse-cookbooks/redmine/templates/default/database.yml.erb new file mode 100644 index 0000000..b94ae01 --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/database.yml.erb @@ -0,0 +1,12 @@ +# MySQL (default setup). Versions 4.1 and 5.0 are recommended. +# +# Get the fast C bindings: +# gem install mysql +# (on OS X: gem install mysql -- --include=/usr/local/lib) +# And be sure to use new-style password hashing: +# http://dev.mysql.com/doc/refman/5.0/en/old-client.html + +production: + adapter: postgresql + database: redmine + encoding: utf8 diff --git a/inhouse-cookbooks/redmine/templates/default/port_redmine.erb b/inhouse-cookbooks/redmine/templates/default/port_redmine.erb new file mode 100644 index 0000000..609c59b --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/port_redmine.erb @@ -0,0 +1,2 @@ +# Redmine +-A FWR -p tcp -m tcp --dport 3000 -j ACCEPT \ No newline at end of file diff --git a/inhouse-cookbooks/redmine/templates/default/redmine.conf.erb b/inhouse-cookbooks/redmine/templates/default/redmine.conf.erb new file mode 100644 index 0000000..142ebc8 --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/redmine.conf.erb @@ -0,0 +1,24 @@ +# Generated by Chef for <%= node[:fqdn] %> +# Local modifications will be overwritten. +# + +server { + listen 80; + + root /srv/redmine/public; + + location / { + try_files /maintenance.html $uri @redmine_unicorn; + } + + location @redmine_unicorn { + proxy_pass http://127.0.0.1:8080; + 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; + } + + error_log /var/log/nginx/redmine-error.log; + access_log /var/log/nginx/redmine-access.log; +} + diff --git a/inhouse-cookbooks/redmine/templates/default/settings.yml.erb b/inhouse-cookbooks/redmine/templates/default/settings.yml.erb new file mode 100644 index 0000000..5006445 --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/settings.yml.erb @@ -0,0 +1,142 @@ +# redMine - project management software +# Copyright (C) 2006-2007 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# DO NOT MODIFY THIS FILE !!! +# Settings can be defined through the application in Admin -> Settings + +app_title: + default: Redmine +app_subtitle: + default: Project management +welcome_text: + default: +login_required: + default: 0 +self_registration: + default: '2' +lost_password: + default: 1 +attachment_max_size: + format: int + default: 5120 +issues_export_limit: + format: int + default: 500 +activity_days_default: + format: int + default: 30 +per_page_options: + default: '25,50,100' +mail_from: + default: redmine@example.net +bcc_recipients: + default: 1 +plain_text_mail: + default: 0 +text_formatting: + default: textile +wiki_compression: + default: "" +default_language: + default: en +host_name: + default: localhost:3000 +protocol: + default: http +feeds_limit: + format: int + default: 15 +diff_max_lines_displayed: + format: int + default: 1500 +enabled_scm: + serialized: true + default: + - Subversion + - Darcs + - Mercurial + - Cvs + - Bazaar + - Git +autofetch_changesets: + default: 1 +sys_api_enabled: + default: 0 +commit_ref_keywords: + default: 'refs,references,IssueID' +commit_fix_keywords: + default: 'fixes,closes' +commit_fix_status_id: + format: int + default: 0 +commit_fix_done_ratio: + default: 100 +# autologin duration in days +# 0 means autologin is disabled +autologin: + format: int + default: 0 +# date format +date_format: + default: '' +time_format: + default: '' +user_format: + default: :firstname_lastname + format: symbol +cross_project_issue_relations: + default: 0 +notified_events: + serialized: true + default: + - issue_added + - issue_updated +mail_handler_api_enabled: + default: 0 +mail_handler_api_key: + default: +issue_list_default_columns: + serialized: true + default: + - tracker + - status + - priority + - subject + - assigned_to + - updated_on +display_subprojects_issues: + default: 1 +default_projects_public: + default: 1 +sequential_project_identifiers: + default: 0 +# encodings used to convert repository files content to UTF-8 +# multiple values accepted, comma separated +repositories_encodings: + default: '' +# encoding used to convert commit logs to UTF-8 +commit_logs_encoding: + default: 'UTF-8' +ui_theme: + default: '' +emails_footer: + default: |- + You have received this notification because you have either subscribed to it, or are involved in it. + To change your notification preferences, please click here: http://hostname/my/account +gravatar_enabled: + default: 0 diff --git a/inhouse-cookbooks/redmine/templates/default/sv-redmine-log-run.erb b/inhouse-cookbooks/redmine/templates/default/sv-redmine-log-run.erb new file mode 100644 index 0000000..c17845d --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/sv-redmine-log-run.erb @@ -0,0 +1,4 @@ +#!/bin/sh +LOG_FOLDER=/var/log/runit/<%= @service_name %>/ +mkdir -p $LOG_FOLDER +exec svlogd -tt $LOG_FOLDER diff --git a/inhouse-cookbooks/redmine/templates/default/sv-redmine-run.erb b/inhouse-cookbooks/redmine/templates/default/sv-redmine-run.erb new file mode 100644 index 0000000..77ed8fa --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/sv-redmine-run.erb @@ -0,0 +1,31 @@ +#!/bin/sh +set -e +ulimit -n 8192 + +HOME_PATH=<%= @options[:home_path] %> +APP_PATH=<%= @options[:app_path] %> +TARGET_USER=<%= @options[:target_user] %> +TARGET_RUBY=<%= @options[:target_ruby] == "default" ? "`cat /home/$TARGET_USER/.ruby-version`" : @options[:target_ruby] %> +RAILS_ENV=<%= @options[:target_env] %> +UNICORN_NAME=<%= @options[:unicorn_name] ? @options[:unicorn_name] : "unicorn" %> +UNICORN_PID_FILE=$APP_PATH/tmp/pids/$UNICORN_NAME.pid +CHRUBY_BIN=/opt/chruby/bin/chruby-exec + +test -f $UNICORN_PID_FILE && UNICORN_PID=`cat $UNICORN_PID_FILE` || UNICORN_PID=-1 + +cd $APP_PATH +EXISTING_PID=`pgrep -f 'unicorn_rails master'` && test "$EXISTING_PID" = "$UNICORN_PID" || HOME=$HOME_PATH chpst -u $TARGET_USER $CHRUBY_BIN $TARGET_RUBY -- bundle exec unicorn_rails -c config/$UNICORN_NAME.rb -E $RAILS_ENV + +# forward signals received in this wrapper to the Unicorn process: +for sig in HUP USR1 USR2 QUIT TERM QUIT +do + trap 'kill -'$sig' $(cat $UNICORN_PID_FILE)' $sig +done + +# loop forever while Unicorn has its pid file +while ( test -e $UNICORN_PID_FILE && ps -p `cat $UNICORN_PID_FILE` > /dev/null ) || ( test -e $UNICORN_PID_FILE.oldbin && ps -p `cat $UNICORN_PID_FILE.oldbin` > /dev/null ) +do + sleep 1 +done + + diff --git a/inhouse-cookbooks/redmine/templates/default/unicorn.rb.erb b/inhouse-cookbooks/redmine/templates/default/unicorn.rb.erb new file mode 100644 index 0000000..0c573e7 --- /dev/null +++ b/inhouse-cookbooks/redmine/templates/default/unicorn.rb.erb @@ -0,0 +1,43 @@ +WORK_DIR = "<%= @application_directory %>" +<% if @prefix -%> +PREFIX = "<%= @prefix -%>-" +<% else -%> +PREFIX = "" +<% end -%> +worker_processes <%= @worker_processes_num %> +working_directory WORK_DIR +user "<%= @user %>" +preload_app true +timeout <%= @timeout %> +#listen "#{WORK_DIR}/tmp/sockets/unicorn.sock", :backlog => 4096 +listen "<%= @listen %>", :backlog => 4096 + +pid "#{WORK_DIR}/tmp/pids/#{PREFIX}unicorn.pid" + +stderr_path "#{WORK_DIR}/log/#{PREFIX}unicorn.stderr.log" +stdout_path "#{WORK_DIR}/log/#{PREFIX}unicorn.stdout.log" + +before_exec do |_| + ENV["BUNDLE_GEMFILE"] = "#{WORK_DIR}/Gemfile" +end + +before_fork do |server, worker| + old_pid = "#{WORK_DIR}/tmp/pids/#{PREFIX}unicorn.pid.oldbin" + if File.exists?(old_pid) && server.pid != old_pid + begin + #Process.kill("QUIT", File.read(old_pid).to_i) + sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU + Process.kill(sig, File.read(old_pid).to_i) + rescue Errno::ENOENT, Errno::ESRCH + # someone else did our job for us + end + end + + defined?(ActiveRecord::Base) and + ActiveRecord::Base.connection.disconnect! +end + +after_fork do |server, worker| + defined?(ActiveRecord::Base) and + ActiveRecord::Base.establish_connection +end diff --git a/roles/redmine.rb b/roles/redmine.rb index d64ddd4..ff8fd64 100644 --- a/roles/redmine.rb +++ b/roles/redmine.rb @@ -1,6 +1,6 @@ name "redmine" description "Install and configure redmine" -run_list "recipe[runit]", "recipe[postgresql]", "recipe[ruby]", "recipe[redmine]" +run_list "recipe[runit]", "recipe[postgresql]", "recipe[ruby]", "recipe[nginx]", "recipe[redmine]" default_attributes( )