Mikimemo

個人的な技術・開発メモやポエム

CentOS6にApache + RVM + UnicornでGitlab4.2構築

GitlabGithubオープンソースクローンで
プライベートリポジトリをつくることはもちろん、
ユーザ管理や公開鍵管理などをWebブラウザ上からできる、おされなツールです。

さらに、プロジェクト毎にWallやWikiが使えたり、ブランチのネットワークグラフを表示したり、マージリクエストの管理などもできます。


最近構築する機会があったのでメモ

# ただし、5.0へのメジャーアップデートでGitoliteが必要なくなるらしく、もっと簡単にインストールが済むようになるかもです。

とりあえず現時点の手順です。
極力手間をかけず、メンテもしやすいような感じで構成してみました。
メモ程度に残していたログを都合よくまとめただけなので、へんなとこあるかもです。
あしからず。

公式の手順はこちら
gitlabhq/installation.md at 4-2-stable · gitlabhq/gitlabhq · GitHub

必要そうなパッケージインストール

[mikito@nya ~]$ sudo yum -y install libyaml-devel openssl-devel gdbm-devel readline-devel ncurses-devel libffi-devel redis libxml2-devel libxslt-devel libicu-devel curl git-core openssh-server postfix

Redis起動、自動起動設定

[mikito@nya ~]$ sudo /etc/init.d/redis
[mikito@nya ~]$ sudo chkconfig redis on
[mikito@nya ~]$ chkconfig --list redis
redis 0:off 1:off 2:on 3:on 4:on 5:on 6:off

データベース設定(MySQL

[mikito@nya ~]$ mysql -u root -p
mysql> create user 'gitlab_user'@'localhost' identified by '*******'
mysql> CREATE DATABASE IF NOT EXISTS `gitlab_db` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `gitlab_db`.* TO 'gitlab_user'@'localhost';

System User作る

[mikito@nya ~]$ sudo adduser -r -s /bin/sh -c 'git' -d /home/git -m git
[mikito@nya ~]$ sudo adduser -r -s /bin/sh -c 'gitlab' -d /home/gitlab -m gitlab
[mikito@nya ~]$ sudo chmod g+rx /home/git
[mikito@nya ~]$ sudo usermod -a -G git gitlab

gitlabユーザのSSH Key作ってコピーしとく

[mikito@nya ~]$ sudo -u gitlab -H ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
[mikito@nya ~]$ sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
[mikito@nya ~]$ sudo chmod 0444 /home/git/gitlab.pub

Gitolite設定

[mikito@nya ~]$ sudo su - git -s /bin/bash # gitユーザで作業
[git@nya ~]$ git clone -b gl-v320 https://github.com/gitlabhq/gitolite.git gitolite
[git@nya ~]$ mkdir /home/git/bin
[git@nya ~]$ sh -c 'printf "%b\n%b\n" "PATH=\$PATH:/home/git/bin" "export PATH" >> /home/git/.profile'
[git@nya ~]$ sh -c 'gitolite/install -ln /home/git/bin'
[git@nya ~]$ sh -c "PATH=/home/git/bin:$PATH; gitolite setup -pk /home/git/gitlab.pub"
[git@nya ~]$ chmod 750 /home/git/.gitolite/
[git@nya ~]$ chmod -R ug+rwX,o-rwx /home/git/repositories/
[git@nya ~]$ find /home/git/repositories -type d -print0 | xargs -0 chmod g+s

list of known hostsに追加とかcloneチェックとか

[mikito@nya ~]$ sudo su - gitlab -s /bin/bash # gitlabユーザで作業
[gitlab@nya ~]$ ssh git@localhost
The authenticity of host '[127.0.0.1]:2222 ([127.0.0.1]:2222)' can't be established.
RSA key fingerprint is 24:11:23:ff:35:72:9f:e0:5e:36:5f:c4:f9:4d:c7:f8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[127.0.0.1]:2222' (RSA) to the list of known hosts.
PTY allocation request failed on channel 0
hello gitlab, this is git@nya running gitolite3 v3.2-gitlab-patched-0-g2d29cf7 on git 1.7.1
...

実際に管理用のリポジトリcloneしてみる

[gitlab@nya ~]$ git clone git@localhost:gitolite-admin.git gitolite-admin
Initialized empty Git repository in /home/gitlab/gitolite-admin/.git/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
[gitlab@nya ~]$ ls
gitolite-admin
[gitlab@nya ~]$ rm -rf gitolite-admin/

Git設定

[gitlab@nya gitlab]$ git config --global user.name "Gitlab"
[gitlab@nya gitlab]$ git config --global user.email "gitlab@gitlab.mikinya.net"

RVM & Gemインストール

[gitlab@nya ~]$ curl -L --insecure https://get.rvm.io | bash -s stable --ruby
[gitlab@nya ~]$ source .bash_profile
[gitlab@nya ~]$ rvm install 1.9.3
[gitlab@nya ~]$ gem install bundler --no-rdoc --no-ri
[gitlab@nya ~]$ gem install charlock_holmes --version '0.6.9' --no-rdoc --no-ri
[gitlab@nya ~]$ rvm gemset create gitlab
[gitlab@nya ~]$ rvm use 1.9.3@gitlab --default

Gitlabインストール

[gitlab@nya ~]$ git clone https://github.com/gitlabhq/gitlabhq.git gitlab
[gitlab@nya ~]$ cd gitlab/
[gitlab@nya gitlab]$ git checkout 4-2-stable
[gitlab@nya gitlab]$ chmod -R u+rwX log/
[gitlab@nya gitlab]$ chmod -R u+rwX tmp/
[gitlab@nya gitlab]$ mkdir gitlab-satellites
[gitlab@nya gitlab]$ cp config/gitlab.yml.example config/gitlab.yml
[gitlab@nya gitlab]$ vim config/gitlab.yml # host名とか設定
[gitlab@nya gitlab]$ cp config/database.yml.mysql config/database.yml
[gitlab@nya gitlab]$ vim config/database.yml

database.yml

#
# PRODUCTION
#
production:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: gitlab_db
  pool: 5
  username: gitlab_user 
  password: "***********"
  # host: localhost
  # socket: /tmp/mysql.sock

unicorn設定

[gitlab@nya gitlab]$ cp config/unicorn.rb.example config/unicorn.rb
[gitlab@nya gitlab]$ vim config/unicorn.rb

unicorn.rb

# uncomment and customize to run in non-root path
# note that config/gitlab.yml web path should also be changed
# ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"

app_dir = "/home/gitlab/gitlab/"
worker_processes 2
working_directory app_dir

# Load app into the master before forking workers for super-fast
# worker spawn times
preload_app true

# nuke workers after 30 seconds (60 is the default)
timeout 30

# listen on a Unix domain socket and/or a TCP port,

#listen 8080 # listen to port 8080 on all TCP interfaces
#listen "127.0.0.1:8080"  # listen to port 8080 on the loopback interface
#listen "#{app_dir}/tmp/sockets/gitlab.socket"
listen      "127.0.0.1:8080", :tcp_nopush => true

pid "#{app_dir}/tmp/pids/unicorn.pid"
stderr_path "#{app_dir}/log/unicorn.stderr.log"
stdout_path "#{app_dir}/log/unicorn.stdout.log"

# http://www.rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
if GC.respond_to?(:copy_on_write_friendly=)
  GC.copy_on_write_friendly = true
end


before_fork do |server, worker|
  # the following is highly recomended for Rails + "preload_app true"
  # as there's no need for the master process to hold a connection
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  ##
  # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
  # immediately start loading up a new version of itself (loaded with a new
  # version of our app). When this new Unicorn is completely loaded
  # it will begin spawning workers. The first worker spawned will check to
  # see if an .oldbin pidfile exists. If so, this means we've just booted up
  # a new Unicorn and need to tell the old one that it can now die. To do so
  # we send it a QUIT.
  #
  # Using this method we get 0 downtime deploys.

  old_pid = "#{server.config[:pid]}.oldbin"

  if File.exists?(old_pid) && server.pid != old_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
      # someone else did our job for us
    end
  end
end

after_fork do |server, worker|
  # Unicorn master loads the app then forks off workers - because of the way
  # Unix forking works, we need to make sure we aren't using any of the parent's
  # sockets, e.g. db connection

  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
  # Redis and Memcached would go here but their connections are established
  # on demand, so the master never opens a socket
end

フックの設定

[gitlab@nya gitlab]$ cp /home/gitlab/gitlab/lib/hooks/post-receive /home/git/.gitolite/hooks/common/post-receive
[gitlab@nya gitlab]$ chown git:git /home/git/.gitolite/hooks/common/post-receive

gemインストール、Migration & Setup

[gitlab@nya gitlab]$ bundle install --deployment --without development test postgres
[gitlab@nya gitlab]$ bundle exec rake gitlab:setup RAILS_ENV=production

Applicationチェック

[gitlab@nya gitlab]$ bundle exec rake gitlab:env:info RAILS_ENV=production
[gitlab@nya gitlab]$ bundle exec rake gitlab:check RAILS_ENV=production

それっぽいのが出ればOKかと

起動スクリプト設定

[mikito@nya ~]$ sudo -E curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-2-stable/init.d/gitlab
[mikito@nya ~]$ sudo vim /etc/init.d/gitlab #RVMの環境変数の設定を追加

/etc/init.d/gitlab

#! /bin/bash

# GITLAB
# Maintainer: @randx
# App Version: 4.0

### BEGIN INIT INFO
# Provides:          gitlab
# Required-Start:    $local_fs $remote_fs $network $syslog redis-server
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: GitLab git repository management
# Description:       GitLab git repository management
### END INIT INFO

#
# set rvm environment valiables.
#
export PATH=/home/gitlab/.rvm/gems/ruby-1.9.3-p392@gitlab/bin:/home/gitlab/.rvm/gems/ruby-1.9.3-p392@global/bin:/home/gitlab/.rvm/rubies/ruby-1.9.3-p392/bin:/home/gitlab/.rvm/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/gitlab/bin
export GEM_HOME=/home/gitlab/.rvm/gems/ruby-1.9.3-p392@gitlab
export GEM_PATH=/home/gitlab/.rvm/gems/ruby-1.9.3-p392@gitlab:/home/gitlab/.rvm/gems/ruby-1.9.3-p392@global
export BUNDLE_PATH=
export MY_RUBY_HOME=/home/gitlab/.rvm/rubies/ruby-1.9.3-p392
export IRBRC=/home/gitlab/.rvm/rubies/ruby-1.9.3-p392/.irbrc

set -u
set -e

APP_ROOT="/home/gitlab/gitlab"
DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production"
PID_PATH="$APP_ROOT/tmp/pids"
UNICORN_PID="$PID_PATH/unicorn.pid"
SIDEKIQ_PID="$PID_PATH/sidekiq.pid"
STOP_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:stop"
START_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:start"
NAME="unicorn"
DESC="Gitlab service"

check_pid(){
  if [ -f $UNICORN_PID ]; then
    PID=`cat $UNICORN_PID`
    SPID=`cat $SIDEKIQ_PID`
    STATUS=`ps aux | grep $PID | grep -v grep | wc -l`
  else
    STATUS=0
    PID=0
  fi
}

start() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    # Program is running, exit with error code 1.
    echo "Error! $DESC $NAME is currently running!"
    exit 1
  else
    if [ `whoami` = root ]; then
      sudo -u gitlab -H bash -l -c "nohup bundle exec unicorn_rails $DAEMON_OPTS  > /dev/null  2>&1 &"
      sudo -u gitlab -H bash -l -c "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
      echo "$DESC started"
    fi
  fi
}

stop() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    ## Program is running, stop it.
    kill -QUIT `cat $UNICORN_PID`
    sudo -u gitlab -H bash -l -c "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1 &"
    rm "$UNICORN_PID" >> /dev/null
    echo "$DESC stopped"
  else
    ## Program is not running, exit with error.
    echo "Error! $DESC not started!"
    exit 1
  fi
}

restart() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    echo "Restarting $DESC..."
    kill -USR2 `cat $UNICORN_PID`
    sudo -u gitlab -H bash -l -c "mkdir -p $PID_PATH && $STOP_SIDEKIQ  > /dev/null  2>&1 &"
    if [ `whoami` = root ]; then
      sudo -u gitlab -H bash -l -c "mkdir -p $PID_PATH && $START_SIDEKIQ  > /dev/null  2>&1 &"
    fi
    echo "$DESC restarted."
  else
    echo "Error, $NAME not running!"
    exit 1
  fi
}

status() {
  cd $APP_ROOT
  check_pid
  if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then
    echo "$DESC / Unicorn with PID $PID is running."
    echo "$DESC / Sidekiq with PID $SPID is running."
  else
    echo "$DESC is not running."
    exit 1
  fi
}

## Check to see if we are running as root first.
## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html
if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root"
    exit 1
fi

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  reload|force-reload)
        echo -n "Reloading $NAME configuration: "
        kill -HUP `cat $PID`
        echo "done."
        ;;
  status)
        status
        ;;
  *)
        echo "Usage: sudo service gitlab {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac

exit 0

Gitlab起動、自動起動設定

[mikito@nya ~]$ sudo chmod +x /etc/init.d/gitlab
[mikito@nya ~]$ sudo service gitlab start
[mikito@nya ~]$ sudo chkconfig gitlab on
[mikito@nya ~]$ chkconfig --list gitlab
gitlab 0:off 1:off 2:on 3:on 4:on 5:on 6:off

VirtualHost設定、Apache反映

[mikito@nya ~]$ sudo vim /etc/httpd/conf/httpd.conf

httpd.confに以下を追加

NameVirtualHost *:80

<VirtualHost *:80>
  ServerName gitlab.mikinya.net
  DocumentRoot /home/gitlab/gitlab/public
  ProxyPass / http://127.0.0.1:8080/
  ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

Apache反映

[mikito@nya ~]$ sudo /etc/init.d/httpd graceful