From 7b8e1a233d64d5951df714d6dd7c76feac73bca9 Mon Sep 17 00:00:00 2001 From: "Eric G. Wolfe" Date: Wed, 15 Jan 2014 17:57:45 -0500 Subject: [PATCH] Gitlab CB v6.4.0 * Bump gitlab-shell to v1.8.0 * Bump gitlab to 6.4.0 * Remove stale nginx config file * Default recipe changes - Update gitlab-shell config to point at /usr/local/bin/redis-cli - Fix permissions on .ssh/authorized_keys - Add rack_attack file - Add precompile assets execute - Add logrotate dependency and configuration --- CHANGELOG.md | 12 ++ README.md | 23 ++-- attributes/default.rb | 9 +- files/default/rack_attack.rb | 17 +++ files/default/rhel.nginx.default.conf | 3 - metadata.rb | 4 +- recipes/default.rb | 43 +++++++- templates/default/gitlab.init.erb | 145 ++++++++++++++++--------- templates/default/shell_config.yml.erb | 2 +- 9 files changed, 179 insertions(+), 79 deletions(-) create mode 100644 files/default/rack_attack.rb delete mode 100644 files/default/rhel.nginx.default.conf mode change 100644 => 100755 templates/default/gitlab.init.erb diff --git a/CHANGELOG.md b/CHANGELOG.md index d6ca322..65a7a21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## v6.4.0 + + * Bump gitlab-shell to v1.8.0 + * Bump gitlab to 6.4.0 + * Remove stale nginx config file + * Default recipe changes + - Update gitlab-shell config to point at /usr/local/bin/redis-cli + - Fix permissions on .ssh/authorized_keys + - Add rack_attack file + - Add precompile assets execute + - Add logrotate dependency and configuration + ## v6.1.21 * Add node['database']['userhost'] attribute, fixes #57 diff --git a/README.md b/README.md index ccd4e30..5243204 100644 --- a/README.md +++ b/README.md @@ -43,19 +43,20 @@ in accordance with the [Filesystem Hierarchy Standard (FHS) version 2.3](http:// - Thanks to Fletcher Nichol for his awesome ruby\_build cookbook. This ruby\_build LWRP is used to build Ruby 1.9.3 for gitlab. -* [redisio](http://ckbk.it/redisio) +* [redisio](http://community.opscode.com/cookbooks/redisio) - Thanks to Brian Bianco for this Redis cookbook. * Opscode, Inc cookbooks - - [git](http://ckbk.it/git) - - [build-essential](http://ckbk.it/build-essential) - - [sudo](http://ckbk.it/sudo) - - [nginx](http://ckbk.it/nginx) - - [openssh](http://ckbk.it/openssh) - - [perl](http://ckbk.it/perl) - - [xml](http://ckbk.it/xml) - - [zlib](http://ckbk.it/zlib) - - [database](http://ckbk.it/database) + - [git](http://community.opscode.com/cookbooks/git) + - [build-essential](http://community.opscode.com/cookbooks/build-essential) + - [sudo](http://community.opscode.com/cookbooks/sudo) + - [nginx](http://community.opscode.com/cookbooks/nginx) + - [logrotate](http://community.opscode.com/cookbooks/logrotate) + - [openssh](http://community.opscode.com/cookbooks/openssh) + - [perl](http://community.opscode.com/cookbooks/perl) + - [xml](http://community.opscode.com/cookbooks/xml) + - [zlib](http://community.opscode.com/cookbooks/zlib) + - [database](http://community.opscode.com/cookbooks/database) Attributes @@ -102,7 +103,7 @@ Attributes * `gitlab['certificate_databag_id']` - Encrypted databag name containing certificate file, CA bundle, and key. Default nil - - See [certificate cookbook](http://ckbk.it/certificate) for further information. + - See [certificate cookbook](http://community.opscode.com/cookbooks/certificate) for further information. * `gitlab['backup_path']` - Path in file system where backups are stored. Default `gitlab['app_home'] + backups/` diff --git a/attributes/default.rb b/attributes/default.rb index dc7683f..8932e56 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -30,12 +30,12 @@ # Set github URL for gitlab default['gitlab']['git_url'] = 'git://github.com/gitlabhq/gitlabhq.git' -default['gitlab']['git_branch'] = '6-1-stable' +default['gitlab']['git_branch'] = '6-4-stable' # gitlab-shell attributes default['gitlab']['shell']['home'] = node['gitlab']['home'] + '/gitlab-shell' default['gitlab']['shell']['git_url'] = 'git://github.com/gitlabhq/gitlab-shell.git' -default['gitlab']['shell']['git_branch'] = 'v1.7.1' +default['gitlab']['shell']['git_branch'] = 'v1.8.0' # Database setup default['gitlab']['database']['type'] = 'mysql' @@ -47,11 +47,14 @@ default['gitlab']['database']['username'] = 'gitlab' default['gitlab']['database']['userhost'] = 'localhost' +# Ruby setup +include_attribute 'ruby_build' +default['ruby_build']['upgrade'] = 'sync' default['gitlab']['install_ruby'] = '1.9.3-p484' default['gitlab']['install_ruby_path'] = node['gitlab']['home'] default['gitlab']['cookbook_dependencies'] = %w[ build-essential zlib readline ncurses git openssh - redisio::install redisio::enable xml ruby_build + logrotate redisio::install redisio::enable xml ruby_build ] # Required packages for Gitlab diff --git a/files/default/rack_attack.rb b/files/default/rack_attack.rb new file mode 100644 index 0000000..1d10a53 --- /dev/null +++ b/files/default/rack_attack.rb @@ -0,0 +1,17 @@ +# 1. Rename this file to rack_attack.rb +# 2. Review the paths_to_be_protected and add any other path you need protecting +# + +paths_to_be_protected = [ + "#{Rails.application.config.relative_url_root}/users/password", + "#{Rails.application.config.relative_url_root}/users/sign_in", + "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session.json", + "#{Rails.application.config.relative_url_root}/api/#{API::API.version}/session", + "#{Rails.application.config.relative_url_root}/users" +] + +unless Rails.env.test? + Rack::Attack.throttle('protected paths', limit: 10, period: 60.seconds) do |req| + req.ip if paths_to_be_protected.include?(req.path) && req.post? + end +end diff --git a/files/default/rhel.nginx.default.conf b/files/default/rhel.nginx.default.conf deleted file mode 100644 index 607268c..0000000 --- a/files/default/rhel.nginx.default.conf +++ /dev/null @@ -1,3 +0,0 @@ -# Managed by chef -# This file was overwritten by cookbook-gitlab's default recipe -# See /etc/nginx/sites-available/gitlab.conf for gitlab's server config \ No newline at end of file diff --git a/metadata.rb b/metadata.rb index 54575b4..9f67d51 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,10 +4,10 @@ description 'Installs/Configures gitlab' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) name 'gitlab' -version '6.1.21' +version '6.4.0' %w[ build-essential zlib readline ncurses git openssh redisio xml - ruby_build certificate database mysql + ruby_build certificate database logrotate mysql nginx postgresql apt ].each do |cb_depend| depends cb_depend end diff --git a/recipes/default.rb b/recipes/default.rb index 92aa2e2..bd3f4ec 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -45,11 +45,6 @@ package pkg end -# symlink redis-cli into /usr/bin (needed for gitlab hooks to work) -link '/usr/bin/redis-cli' do - to '/usr/local/bin/redis-cli' -end - # Add a git user for Gitlab user node['gitlab']['user'] do comment 'Gitlab User' @@ -72,6 +67,13 @@ mode '0700' end +file "#{node['gitlab']['home']}/.ssh/authorized_keys" do + owner node['gitlab']['user'] + group node['gitlab']['group'] + mode '0600' +end + +# Drop off git config template "#{node['gitlab']['home']}/.gitconfig" do source 'gitconfig.erb' owner node['gitlab']['user'] @@ -185,6 +187,13 @@ ) end +# Copy file rack_attack.rb +cookbook_file "#{node['gitlab']['app_home']}/config/initializers/rack_attack.rb" do + owner node['gitlab']['user'] + group node['gitlab']['group'] + mode '0644' +end + # create log, tmp, pids and sockets directory %w{ log tmp tmp/pids tmp/sockets public/uploads }.each do |dir| directory File.join(node['gitlab']['app_home'], dir) do @@ -196,6 +205,25 @@ end end +# Precompile assets +execute 'gitlab-bundle-precompile-assets' do + command 'bundle exec rake assets:precompile RAILS_ENV=production' + cwd node['gitlab']['app_home'] + user node['gitlab']['user'] + group node['gitlab']['group'] + environment('LANG' => 'en_US.UTF-8', 'LC_ALL' => 'en_US.UTF-8') + only_if { Dir["#{node['gitlab']['app_home']}/public/assets/*"].empty? } +end + +# logrotate gitlab-shell and gitlab +logrotate_app 'gitlab' do + frequency 'weekly' + path ["#{node['gitlab']['app_home']}/log/*.log", + "#{node['gitlab']['shell']['home']}/gitlab-shell.log"] + rotate 52 + options %w[compress delaycompress notifempty copytruncate] +end + # create gitlab-satellites directory directory File.join(node['gitlab']['home'], 'gitlab-satellites') do user node['gitlab']['user'] @@ -296,17 +324,20 @@ ) end +# Install nginx include_recipe 'nginx' +# Enable gitlab site nginx_site 'gitlab' do enable true end +# Disable default site nginx_site 'default' do enable false end -# Enable and start unicorn_rails and nginx service +# Enable and start unicorn and sidekiq service service 'gitlab' do action [:enable, :start] end diff --git a/templates/default/gitlab.init.erb b/templates/default/gitlab.init.erb old mode 100644 new mode 100755 index c2695ca..063e574 --- a/templates/default/gitlab.init.erb +++ b/templates/default/gitlab.init.erb @@ -1,4 +1,4 @@ -#!/bin/sh +#! /bin/sh # GITLAB # Maintainer: @randx @@ -15,36 +15,44 @@ # Description: GitLab git repository management ### END INIT INFO + +### +# DO NOT EDIT THIS FILE! +# This file will be overwritten on update. +# Instead add/change your variables in /etc/default/gitlab +# An example defaults file can be found in lib/support/default/gitlab +### + + ### Environment variables RAILS_ENV="production" -# Script variable names should be lower-case not to conflict with internal -# /bin/sh variables such as PATH, EDITOR or SHELL. +# Script variable names should be lower-case not to conflict with +# internal /bin/sh variables such as PATH, EDITOR or SHELL. app_root="<%= @gitlab_app_home %>" app_user="<%= @gitlab_user %>" -unicorn_conf="$app_root/config/unicorn.rb" pid_path="$app_root/tmp/pids" socket_path="$app_root/tmp/sockets" web_server_pid_path="$pid_path/unicorn.pid" sidekiq_pid_path="$pid_path/sidekiq.pid" - - -### Here ends user configuration ### - +# Read configuration variable file if it is present +test -f /etc/default/gitlab && . /etc/default/gitlab # Switch to the app_user if it is not he/she who is running the script. if [ "$USER" != "$app_user" ]; then sudo -u "$app_user" -H -i $0 "$@"; exit; fi -# Switch to the gitlab path, if it fails exit with an error. +# Switch to the gitlab path, exit on failure. if ! cd "$app_root" ; then echo "Failed to cd into $app_root, exiting!"; exit 1 fi + ### Init Script functions +## Gets the pids from the files check_pids(){ if ! mkdir -p "$pid_path"; then echo "Could not create the path $pid_path needed to store the pids." @@ -63,12 +71,29 @@ check_pids(){ fi } +## Called when we have started the two processes and are waiting for their pid files. +wait_for_pids(){ + # We are sleeping a bit here mostly because sidekiq is slow at writing it's pid + i=0; + while [ ! -f $web_server_pid_path -o ! -f $sidekiq_pid_path ]; do + sleep 0.1; + i=$((i+1)) + if [ $((i%10)) = 0 ]; then + echo -n "." + elif [ $((i)) = 301 ]; then + echo "Waited 30s for the processes to write their pids, something probably went wrong." + exit 1; + fi + done + echo +} + # We use the pids in so many parts of the script it makes sense to always check them. # Only after start() is run should the pids change. Sidekiq sets it's own pid. check_pids -# Checks whether the different parts of the service are already running or not. +## Checks whether the different parts of the service are already running or not. check_status(){ check_pids # If the web server is running kill -0 $wpid returns true, or rather 0. @@ -85,9 +110,16 @@ check_status(){ else sidekiq_status="-1" fi + if [ $web_status = 0 -a $sidekiq_status = 0 ]; then + gitlab_status=0 + else + # http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html + # code 3 means 'program is not running' + gitlab_status=3 + fi } -# Check for stale pids and remove them if necessary +## Check for stale pids and remove them if necessary. check_stale_pids(){ check_status # If there is a pid it is something else than 0, the service is running if @@ -95,7 +127,7 @@ check_stale_pids(){ if [ "$wpid" != "0" -a "$web_status" != "0" ]; then echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran." if ! rm "$web_server_pid_path"; then - echo "Unable to remove stale pid, exiting" + echo "Unable to remove stale pid, exiting." exit 1 fi fi @@ -108,7 +140,7 @@ check_stale_pids(){ fi } -# If no parts of the service is running, bail out. +## If no parts of the service is running, bail out. exit_if_not_running(){ check_stale_pids if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then @@ -117,86 +149,92 @@ exit_if_not_running(){ fi } -# Starts Unicorn and Sidekiq. +## Starts Unicorn and Sidekiq if they're not running. start() { check_stale_pids + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then + echo -n "Starting both the GitLab Unicorn and Sidekiq" + elif [ "$web_status" != "0" ]; then + echo -n "Starting GitLab Sidekiq" + elif [ "$sidekiq_status" != "0" ]; then + echo -n "Starting GitLab Unicorn" + fi + # Then check if the service is running. If it is: don't start again. if [ "$web_status" = "0" ]; then echo "The Unicorn web server already running with pid $wpid, not restarting." else - echo "Starting the GitLab Unicorn web server..." # Remove old socket if it exists rm -f "$socket_path"/gitlab.socket 2>/dev/null - # Start the webserver - bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV" + # Start the web server + RAILS_ENV=$RAILS_ENV script/web start & fi # If sidekiq is already running, don't start it again. if [ "$sidekiq_status" = "0" ]; then echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting" else - echo "Starting the GitLab Sidekiq event dispatcher..." - RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start - # We are sleeping a bit here because sidekiq is slow at writing it's pid - sleep 2 + RAILS_ENV=$RAILS_ENV script/background_jobs start & fi + # Wait for the pids to be planted + wait_for_pids # Finally check the status to tell wether or not GitLab is running - status + print_status } -# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them. +## Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them. stop() { exit_if_not_running + + if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then + echo -n "Shutting down both Unicorn and Sidekiq" + elif [ "$web_status" = "0" ]; then + echo -n "Shutting down Sidekiq" + elif [ "$sidekiq_status" = "0" ]; then + echo -n "Shutting down Unicorn" + fi + # If the Unicorn web server is running, tell it to stop; if [ "$web_status" = "0" ]; then - kill -QUIT "$wpid" & - echo "Stopping the GitLab Unicorn web server..." - stopping=true - else - echo "The Unicorn web was not running, doing nothing." + RAILS_ENV=$RAILS_ENV script/web stop fi # And do the same thing for the Sidekiq. if [ "$sidekiq_status" = "0" ]; then - printf "Stopping Sidekiq job dispatcher." - RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop & - stopping=true - else - echo "The Sidekiq was not running, must have run out of breath." + RAILS_ENV=$RAILS_ENV script/background_jobs stop fi - # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script. - while [ "$stopping" = "true" ]; do + while [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; do sleep 1 check_status - if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then - printf "." - else + printf "." + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then printf "\n" break fi done + sleep 1 # Cleaning up unused pids rm "$web_server_pid_path" 2>/dev/null # rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid. - status + print_status } -# Returns the status of GitLab and it's components -status() { +## Prints the status of GitLab and it's components. +print_status() { check_status if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then echo "GitLab is not running." return fi if [ "$web_status" = "0" ]; then - echo "The GitLab Unicorn webserver with pid $wpid is running." + echo "The GitLab Unicorn web server with pid $wpid is running." else - printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n" + printf "The GitLab Unicorn web server is \033[31mnot running\033[0m.\n" fi if [ "$sidekiq_status" = "0" ]; then echo "The GitLab Sidekiq job dispatcher with pid $spid is running." @@ -204,10 +242,11 @@ status() { printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n" fi if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then - printf "GitLab and all it's components are \033[32mup and running\033[0m.\n" + printf "GitLab and all its components are \033[32mup and running\033[0m.\n" fi } +## Tells unicorn to reload it's config and Sidekiq to restart reload(){ exit_if_not_running if [ "$wpid" = "0" ];then @@ -215,17 +254,16 @@ reload(){ exit 1 fi printf "Reloading GitLab Unicorn configuration... " - kill -USR2 "$wpid" + RAILS_ENV=$RAILS_ENV script/web reload echo "Done." echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..." - RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop - echo "Starting Sidekiq..." - RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start - # Waiting 2 seconds for sidekiq to write it. - sleep 2 - status + RAILS_ENV=$RAILS_ENV script/background_jobs restart + + wait_for_pids + print_status } +## Restarts Sidekiq and Unicorn. restart(){ check_status if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then @@ -235,7 +273,7 @@ restart(){ } -## Finally the input handling. +### Finally the input handling. case "$1" in start) @@ -251,7 +289,8 @@ case "$1" in reload ;; status) - status + print_status + exit $gitlab_status ;; *) echo "Usage: service gitlab {start|stop|restart|reload|status}" diff --git a/templates/default/shell_config.yml.erb b/templates/default/shell_config.yml.erb index d86a1a7..70dabbf 100644 --- a/templates/default/shell_config.yml.erb +++ b/templates/default/shell_config.yml.erb @@ -20,7 +20,7 @@ auth_file: <%= node['gitlab']['home'] + "/.ssh/authorized_keys"%> # Redis settings used for pushing commit notices to gitlab redis: - bin: /usr/bin/redis-cli + bin: /usr/local/bin/redis-cli host: 127.0.0.1 port: 6379 # socket: /tmp/redis.socket # Only define this if you want to use sockets