2013/06/03

RHEL 5 安裝 Indefero

http://www.indefero.net

Indefero 是一個 Web 介面 Git 的前端工具,類似 Gitorious。
簡單說,它就是類似 Google Code 那樣的原始碼管理系統。
其實它可以接管 Git、Subversion、Mercurial、Monotone 等 SCM 軟體。
Indefero 是使用 PHP 撰寫的,搭配 Pluf 框架。



【Setup Indefero with Git in RHEL 5.x】

[修改 /etc/hosts]

127.0.0.1    indefero

[MySQL 資料庫]
資料庫版本:MySQL 5.x
資料庫帳號:indefero
資料庫密碼:indefero
資料庫名稱:indefero

mysql -u root -p
mysql> create database indefero;
mysql> ALTER DATABASE indefero CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> grant all privileges on indefero.* to indefero@localhost identified by 'indefero';

[相關使用者]

手動新增的使用者:git
httpd 預設的使用者:apache

[相關路徑]
/home/git/repositories
/home/git/.ssh
/var/www/html/indefero
/var/www/html/pluf

[1]安裝 Pluf 框架

Pluf:http://www.pluf.org

Pluf 需要至少 5.2.4 版本以上的 PHP,RHEL 5.x 附帶的通常都很舊。
RHEL 5.x 需要的 rpm 套件可以去這找:http://rpms.famillecollet.com

先使用 yum 安裝必須的 PHP 套件:

yum install php-pear
yum install php-pear-Mail php-pear-Mail-Mime php-pear-mail_mime

下載 Pluf 原始檔到 /var/www/html 并解壓縮,完成。

[2]安裝 Indefero

前往:http://projects.ceondo.com/p/indefero/

下載 Indefero 原始檔到 /var/www/html,解壓縮,然後執行:

cd /var/www/html/indefero
cp src/IDF/conf/idf.php-dist src/IDF/conf/idf.php
cp src/IDF/conf/path.php-dist src/IDF/conf/path.php

確認 MySQL 資料庫與資料庫使用者。

修改 src/IDF/conf/idf.php:

$cfg['git_repositories'] = '/home/git/repositories/%s.git';
$cfg['git_remote_url'] = 'git://indefero/%s.git';
$cfg['git_write_remote_url'] = 'git@indefero:%s.git';
$cfg['send_emails'] = false;
$cfg['mail_backend'] = 'smtp';
$cfg['mail_host'] = 'localhost';
$cfg['mail_port'] = 25;
$cfg['url_base'] = 'http://indefero';
$cfg['url_media'] = 'http://indefero/media';
$cfg['url_upload'] = 'http://indefero/media/upload';
$cfg['upload_path'] = '/var/www/html/indefero/www/media/upload';
$cfg['upload_issue_path'] = '/var/www/html/indefero/attachments';
# 超過 40 個字元就可以
$cfg['secret_key'] = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd';
# Database configuration
$cfg['db_login'] = 'indefero';
$cfg['db_password'] = 'indefero';
$cfg['db_database'] = 'indefero';
$cfg['db_server'] = 'localhost';
$cfg['db_version'] = '5.1';
$cfg['db_table_prefix'] = 'indefero_';
$cfg['db_engine'] = 'MySQL';
# 如果有碰到 open_basedir restriction error,
# 執行 cp /etc/mime.types /home,并開啟以下設定:
#$cfg['idf_mimetypes_db'] = '/home/mime.types';

修改 src/IDF/conf/path.php:

# 如果沒有特殊修改,使用預設的相對路徑即可。

開始安裝:

cd /var/www/html/indefero/src
# 以下命令進行測試安裝
php /var/www/html/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -i -d -u
# 以下命令進行實際安裝
php /var/www/html/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -i -d

建立 /var/www/html/indefero/www/bootstrap.php:

require '/var/www/html/indefero/src/IDF/conf/path.php';
require 'Pluf.php';
Pluf::start('/var/www/html/indefero/src/IDF/conf/idf.php');
Pluf_Dispatcher::loadControllers(Pluf::f('idf_views'));

$user = new Pluf_User();
$user->first_name = '管理者姓氏';
$user->last_name = '管理者名字'; // Required! 必須!
$user->login = '管理者帳號'; // must be lowercase! 全部小寫!
$user->email = '管理者信箱';
$user->password = '管理者密碼';
$user->administrator = true;
$user->active = true;
$user->create();
print "Bootstrap ok\n";


建立管理者:

php /var/www/html/indefero/www/bootstrap.php

順利執行完成後,可以刪除或改名 bootstrap.php 檔。

建立 /etc/httpd/conf.d/indefero:

# 請自行把 [ ] 換成 < >
[virtualhost *:80]
    ServerName indefero
    DocumentRoot /var/www/html/indefero/www
    ErrorLog logs/indefero-error_log
    CustomLog logs/indefero-access_log common
[/VirtualHost]
[directory /var/www/html/indefero/www]  
    AllowOverride All
[/Directory]

在 /var/www/html/indefero/www 內補一個 .htaccess:

Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) /index.php/$1

重新啟動 Apache:

service httpd restart

連到 http://indefero 登入看看。

[3]設定 Git Repositories

Indefero 原始檔的 doc 資料夾下,有完整的設定說明檔(doc/syncgit.mdtext)。

建立使用者用以控制 Indefero 的 Git Repositories:

useradd git
mkdir /home/git/repositories
mkdir -p /home/git/.ssh
touch /home/git/.ssh/authorized_keys
chown -R git.git /home/git
chmod 0700 /home/git/.ssh
chmod 0600 /home/git/.ssh/authorized_keys

把 httpd 的控制者加到 Git Repositories 控制者的群組:

usermod -a -G git apache

確認系統可以執行 python 程式,因為後面需要執行 scripts/gitserver.py。

python -v

重新修改 src/IDF/conf/idf.php 內的設定:

$cfg['git_repositories'] = '/home/git/repositories/%s.git';
$cfg['git_remote_url'] = 'git://indefero/%s.git';
$cfg['idf_plugin_syncgit_path_gitserve'] = '/var/www/html/indefero/scripts/gitserve.py';
$cfg['idf_plugin_syncgit_path_authorized_keys'] = '/home/git/.ssh/authorized_keys';
$cfg['idf_plugin_syncgit_sync_file'] = '/tmp/SYNC-GIT';

# Remove the git repositories which do not have a corresponding project
# This is run at cron time
$cfg['idf_plugin_syncgit_remove_orphans'] = false;

# git account home dir
$cfg['idf_plugin_syncgit_git_home_dir'] = '/home/git'; 

# where are going to be the git repositories
$cfg['idf_plugin_syncgit_base_repositories'] = '/home/git/repositories'; 

使用 git 的身份加入一下 Cron job:

* * * * * php /var/www/html/indefero/scripts/gitcron.php


安裝 git-daemon:
yum install git-daemon

制作一個 Git Daemon 寫在 /etc/event.d/local-git-daemon:
start on startup
stop on shutdown
exec /usr/bin/git-daemon \
--user=git --group=git \
--verbose \
--reuseaddr \
--base-path=/home/git/repositories/ \
/home/git/repositories/
respawn

啟動:
start local-git-daemon


使用網友寫的 git-daemon,編寫到 /etc/init.d/git-daemon:
(http://projects.ceondo.com/p/indefero/page/git-daemon-sysV-InitScript/)

#!/bin/sh
### BEGIN INIT INFO
# Provides: git-daemon
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $network $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: git-daemon service
# Description: git-daemon makes git repositories available via the git
# protocol.
### END INIT INFO

# Author: Benjamin Graham "bman@duuit.com"

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/git-core
DESC="git-daemon service"
NAME=git-daemon
DAEMON=/usr/bin/$NAME
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Fallback options values, we use these when
# the /etc/default/git-daemon file does not exist
RUN=no
USER=git
GROUP=git
REPOSITORIES="/home/git/repositories/"

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# If ADVANCED_OPTS is empty, use a default setting
if [ "x$ADVANCED_OPTS" == "x" ];
then
    ADVANCED_OPTS="--base-path=$REPOSITORIES $REPOSITORIES"
fi

DAEMON_ARGS="--syslog --reuseaddr \
$ADVANCED_OPTS"

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null || return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --background --make-pidfile -- $DAEMON_ARGS || return 2

return 0
}

#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}

case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;

esac
/etc/default/git-daemon

# Defaults for the git-daemon initscript

# Set to yes to start git-daemon
RUN=yes

# Set to the user and group git-daemon should run as
USER=git
GROUP=git

# Set the base path and the directory where the repositories are.
REPOSITORIES="/home/git/repositories/"

# Provide a way to have custom setup.
#
# Note, when ADVANCED_OPTS is defined the REPOSITORIES setting is ignored,
# so take good care to specify exactly what git-daemon have to do.
#
# Here is an example from the man page:
#ADVANCED_OPTS="--verbose --export-all \
# --interpolated-path=/pub/%IP/%D \
# /pub/192.168.1.200/software \
# /pub/10.10.220.23/software"
ADVANCED_OPTS="/usr/lib/git-core/git-daemon \ 
--verbose --base-path=/home/git/repositories \
 /home/git/repositories"

啟動:

chmo a+x /etc/init.d/git-daemon
/etc/init.d/git-daemon start
service httpd restart



【關于 /home/git/repositories】

Git 其實可以 init 一個 bare repository(裸倉儲庫),bare repository 預設允許任何人 push。
實際的 Git 命令是:
cd some_directory && git init --bare

Indefero(大部分相似的系統)正是利用這個 Git 命令幫助使用者建立專案的 Repository。
Indefero 會根據使用者 create project 時給的 project name,
到 /home/git/repositories 內,建立 project_name.git 這種類型的資料夾,
再切換到該資料夾內,使用 git init --bare 初始化這個 Repository。



【版本升級】

備份舊的 Pluf 與 Indefero 資料夾:

cp -r pluf pluf_backup
cp -r indefero indefero_backup

備份舊的 Indefero 資料庫:

mysqldump -u indefero -p --databases indefero > indefero_backup.sql

下載最新的 Pluf 與 Indefero 原始檔,並解壓縮取代掉原本的資料夾。
然後執行資料庫升級:

cd /home/git/public_html/indefero/src
# 測試升級動作
$ php /home/git/public_html/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d -u
# 執行升級動作
$ php /home/git/public_html/pluf/src/migrate.php --conf=IDF/conf/idf.php -a -d 

重啟 Apache 檢查:
service httpd restart 



【錯誤修正】

[idf_plugin_syncgit_base_repositories]
http://projects.ceondo.com/p/indefero/issues/198/

[Getting Write Access to Git Repositories]
http://www.openflow.org/wk/index.php/Git

Reference:
01. http://projects.ceondo.com/p/indefero/page/Installation/
02. http://code.google.com/hosting/
03. https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools
04. http://www.pluf.org/doc/install.html
05. http://zx-1986.blogspot.com/2010/08/git-manual.html

2013/06/02

RHEL 6 安裝 Gitlab [Old]

Gitlab(a.k.a. Gitlabhq)

Gitlab 是一套以 gitolite 爲基礎的 Git Hosting Website,
Gitlab 是用 Ruby on Rails 框架開發的,需要合適的 Ruby 環境。

作業系統:RHEL 6.0 i386

[前置安裝]

wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm && rpm -i *.rpm

# yum remove gitosis

yum groupinstall "Development Tools"
yum install libxml2-devel libxslt-devel  libxml2 libxslt
yum install git openssl zlib subversion
yum install sqlite sqlite-devel 
yum install mysql++-devel mysql++ 
yum install readline readline-devel compat-readline5 
yum install libcurl libcurl-devel libstdc++ libstdc++-devel libstdc++-docs compat-libstdc++-33 curl
yum install gcc-c++ patch zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison iconv-devel sudo
yum install libicu 

# http://pkgs.org/download/libicu-devel
wget http://mirror.centos.org/centos/6/os/i386/Packages/libicu-devel-4.2.1-9.el6.i686.rpm
rpm -ivh libicu-devel-4.2.1-9.el6.i686.rpm

yum install python-pip
pip-python install pygments

yum install redis
chkconfig redis on
service redis start

[安裝 Ruby]

# using RVM to install Ruby
# install RVM in system wide

su - 

curl -L get.rvm.io | bash -s stable
source ~/.bash_profile
rvm requirements
rvm install 1.9.2
rvm use 1.9.2 --default

which ruby
which gem

[設定 Gitolite]

adduser -r -s /bin/sh -c 'git version control' -U -m git
adduser -c 'gitlab system' -U -m gitlab

usermod -a -G git gitlab
usermod -a -G rvm gitlab
usermod -a -G rvm git

chmod 755 /home/git
chmod 755 /home/gitlab

logout & login

sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
sudo -H -u git git clone http://github.com/gitlabhq/gitolite /home/git/gitolite

sudo -u git sh -c 'echo -e "PATH=\$PATH:/home/git/bin\nexport PATH" > /home/git/.profile'
sudo -u git -i -H /home/git/gitolite/src/gl-system-install
cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
chmod 777 /home/git/gitlab.pub

sudo -u git -H sed -i 's/0077/0007/g' /home/git/share/gitolite/conf/example.gitolite.rc
sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gl-setup -q /home/git/gitlab.pub"

chmod -R g+rwX /home/git/repositories/
chown -R git:git /home/git/repositories/

# check if gitolite works
# If you CAN NOT clone gitolite-admin repository - DONT PROCEED INSTALLATION
su - gitlab
git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
rm -rf /tmp/gitolite-admin 
exit

http://sitaramc.github.com/gitolite/
http://sitaramc.github.com/gitolite/rpmdeb.html
http://sitaramc.github.com/gitolite/add.html

[設定 Gitlab]

gem install charlock_holmes
gem install bundler

su - gitlab

cd /home/gitlab
git clone http://github.com/gitlabhq/gitlabhq.git gitlab

cd gitlab
cp config/gitlab.yml.example config/gitlab.yml # using default website setting
cp config/database.yml.sqlite config/database.yml # using SQLite as database

bundle install --without development test --deployment

bundle exec rake gitlab:app:setup RAILS_ENV=production
bundle exec rake gitlab:app:status RAILS_ENV=production

bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes
bash /home/gitlab/gitlab/resque.sh

bundle exec rails s -e production # test running
bundle exec rails s -e production -d # test running as a daemon

測試網址
http://localhost:3000

預設的帳號密碼
admin@local.host / 5iveL!fe

https://github.com/gitlabhq/gitlabhq/blob/stable/doc/installation.md
http://dl.dropbox.com/u/936096/debian_ubuntu.sh

[設定 Nginx]

yum install nginx

su - gitlab
cd ~/gitlab
cp config/unicorn.rb.orig config/unicorn.rb
bundle exec unicorn_rails -c config/unicorn.rb -E production -D

exit

編輯 /etc/nginx/nginx.conf,在 http { 後加入以下內容:

# 注意修改 YOUR_SERVER_IP 與 YOUR_SUBDOMAIN

upstream gitlab {
    server unix:/home/gitlab/gitlab/tmp/sockets/gitlab.socket;
}

server {
    listen YOUR_SERVER_IP:80;
    server_name YOUR_DOMAIN;
    root /home/gitlab/gitlab/public;

    # individual nginx logs for this gitlab vhost
    access_log  /var/log/nginx/gitlab_access.log;
    error_log   /var/log/nginx/gitlab_error.log;

    location / {
    # serve static files from defined root folder;.
    # @gitlab is a named location for the upstream fallback, see below
    try_files $uri $uri/index.html $uri.html @gitlab;
    }

    # if a file, which is not found in the root folder is requested, 
    # then the proxy pass the request to the upsteam (gitlab unicorn)
    location @gitlab {
      proxy_redirect     off;
      # you need to change this to "https", if you set "ssl" directive to "on"
      proxy_set_header   X-FORWARDED_PROTO http;
      proxy_set_header   Host              YOUR_SUBDOMAIN:80;
      proxy_set_header   X-Real-IP         $remote_addr;

      proxy_pass http://gitlab;
    }

}

編輯 /etc/init.d/gitlab

#! /bin/bash
### 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

DAEMON_OPTS="-c /home/gitlab/gitlab/config/unicorn.rb -E production -D"
NAME=unicorn
DESC="Gitlab service"
PID=/home/gitlab/gitlab/tmp/pids/unicorn.pid
RESQUE_PID=/home/gitlab/gitlab/tmp/pids/resque_worker.pid

case "$1" in
  start)
        CD_TO_APP_DIR="cd /home/gitlab/gitlab"
        START_DAEMON_PROCESS="bundle exec unicorn_rails $DAEMON_OPTS"
        START_RESQUE_PROCESS="./resque.sh"

        echo -n "Starting $DESC: "
        if [ `whoami` = root ]; then
          sudo -u gitlab sh -l -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS"
        else
          $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS
        fi
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        kill -QUIT `cat $PID`
        kill -QUIT `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  restart)
        echo -n "Restarting $DESC: "
        kill -USR2 `cat $PID`
        kill -USR2 `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  reload)
        echo -n "Reloading $DESC configuration: "
        kill -HUP `cat $PID`
        kill -HUP `cat $RESQUE_PID`
        echo "$NAME."
        ;;
  *)
        echo "Usage: $NAME {start|stop|restart|reload}" >&2
        exit 1
        ;;
esac

exit 0

避免 SSH 主機信任問題

su - gitlab
ssh git@YOUR_DOMAIN

The authenticity of host 'YOUR_DOMAIN (YOUR_IP)' can't be established.  
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)? 

# 回答 yes 表示信任該主機

注意!目前 Gitlab 有一個 README 顯示 utf8 的 bug
https://github.com/gitlabhq/gitlabhq/issues/725#issuecomment-5669823

測試啓動

chmod +x /etc/init.d/gitlab
/etc/init.d/nginx restart
/etc/init.d/gitlab restart

設定開機啓動

yum install postfix
chkconfig postfix on
chkconfig nginx on
echo "/etc/init.d/gitlab start" >> /etc/rc.local

Reference:
http://zx-1986.blogspot.com/2011/11/gitlabhq.html
http://zx-1986.blogspot.com/2011/11/gitlabhq-in-redhat.html

Redhat 安裝 Gitlabhq [Old]

這是舊的筆記,請前往:
http://zx-1986.blogspot.com/2012/03/setup-gitlab-in-rhel-6.html

this note was out of date! please check the update version:
http://zx-1986.blogspot.com/2012/03/setup-gitlab-in-rhel-6.html

作業系統:RHEL 6.0 i386

cd /opt 

wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm && rpm -i *.rpm

yum groupinstall "Development Tools" # thanks for http://dejant.blogspot.com
yum install libxml2-devel libxslt-devel # thanks for http://dejant.blogspot.com
yum install git libxml2 libxslt sqlite sqlite-devel openssl zlib mysql++-devel mysql++ readline-devel compat-readline5 readline libcurl libcurl-devel libstdc++ libstdc++-devel libstdc++-docs compat-libstdc++-33

yum install python-pip
pip-python install pygments
# yum install python-setuptools
# easy_install pygments

adduser gitlabhq
passwd gitlabhq
visudo
#  gitlabhq    ALL=(ALL)    NOPASSWD: ALL

sudo bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
# using sudo for multi-users installed!
# logout, then login as root again

rvm install 1.9.2  
rvm --default use 1.9.2
ruby --version

echo "gem: --no-rdoc --no-ri" > ~/.gemrc
gem update --system  
gem install bundler

echo $rvm_path/src/$(rvm tools strings) 
rvm @global gem install ruby-debug19 -- --with-ruby-include=$rvm_path/src/$(rvm tools strings)
exit

su - gitlabhq
ssh-keygen -t rsa

sudo yum install gitosis

sudo adduser -r -s /bin/sh -c 'git version control' -U -m git
sudo usermod -a -G git gitlabhq
sudo usermod -a -G rvm gitlabhq

sudo -H -u git gitosis-init < /home/gitlabhq/.ssh/id_rsa.pub

sudo chmod 755 /home/git
sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

cd ~
git clone https://github.com/gitlabhq/gitlabhq.git

cd gitlabhq
vim Gemfile # :%s/git:/https:/g
vim Gemfile.lock # :%s/git:/https:/g

sudo su -

cd /home/gitlabhq/gitlabhq
bundle install # run the "bundle install" as "root" to avoid the permission issue at first time

cd /usr/local/rvm/gems/ruby-1.9.2-p290/bundler/gems
mv ./* /tmp

exit

bundle install # run the "bundle install" as "gitlabhq" to make sure all gems in gitlabhq/ grant to "gitlabhq"
bundle exec rake db:setup RAILS_ENV=production
bundle exec rake db:seed_fu RAILS_ENV=production

vim config/gitosis.yml  # 檢查內容與路徑
rails s -e production # 啟動測試服務器

測試網址
http://localhost:3000

預設的帳號密碼
admin@local.host / 5iveL!fe

# 設定 Nginx

sudo su -
yum remove httpd
gem install passenger
passenger-install-nginx-module

# 選擇 1. Yes: download, compile and install Nginx for me. (recommended)
# passenger-install-nginx-module 會自動下載并編譯安裝 Nginx,預設裝到 /opt/nginx

vim /opt/nginx/conf/nginx.conf

---
user gitlabhq;
 
server {
  listen 80;
  server_name YOUR_IP_ADDRESS;
  root /home/gitlabhq/gitlabhq/public;
  passenger_enabled on;
}
---

/opt/nginx/sbin/nginx # start Nginx server
/opt/nginx/sbin/nginx -s stop # stop Nginx server

Reference:
http://isitruby19.com/linecache19
https://github.com/carlhuda/bundler/issues/1356
https://github.com/mark-moseley/linecache/issues/8
https://github.com/gitlabhq/gitlabhq/issues/66
https://github.com/gitlabhq/gitlabhq/issues/34
https://github.com/gitlabhq/gitlabhq/issues/84
https://github.com/gitlabhq/gitlabhq/issues/141

Ubuntu 安裝 Gitlabhq [Failed]

這是無效的筆記,請前往:
http://zx-1986.blogspot.com/2012/03/setup-gitlab-in-rhel-6.html

it does NOT WORK! please check the update version:
http://zx-1986.blogspot.com/2012/03/setup-gitlab-in-rhel-6.html

在 Ubuntu 11.04 Server 安裝 Gitlabhq

THIS IS NOT WORK!

su -
export http_proxy="your_proxy"
export https_proxy="your_proxy"
apt-get update && apt-get upgrade

# 設定 Ruby 環境

apt-get install git-core curl gcc checkinstall make build-essential 
apt-get install libxml2-dev libxslt-dev sqlite3 libsqlite3-dev libcurl4-openssl-dev libreadline5-dev libc6-dev libssl-dev libmysql++-dev zlib1g-dev
bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)
source /etc/bash.bashrc
rvm install 1.9.2
rvm install 1.9.3
rvm --default use 1.9.2
gem update --system
echo "gem: --no-rdoc --no-ri" > ~/.gemrc

注意:使用的是 rvm 管控下的 Ruby 1.9.2 與其搭配的 rubygems

# 安裝 Gitosis

apt-get install git gitosis
adduser --system --shell /bin/sh --gecos 'git version control' --group --disabled-password --home /home/git git
ssh-keygen -t rsa
sudo -H -u git gitosis-init < ~/.ssh/id_rsa.pub
chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update
# 安裝 Gitlabhq
cd /opt
pip install pygments
apt-get install python-setuptools
easy_install pygments
apt-get install libsqlite3-dev
gem install bundler
git clone https://github.com/gitlabhq/gitlabhq.git
cd gitlabhq
vim Gemfile # :%s/git:/https:/g
vim Gemfile.lock # :%s/git:/https:/g
echo $rvm_path/src/$(rvm tools strings) 
rvm @global gem install ruby-debug19 -- --with-ruby-include=$rvm_path/src/$(rvm tools strings)
bundle install
bundle exec rake db:setup RAILS_ENV=production
bundle exec rake db:seed_fu RAILS_ENV=production
vim /opt/gitlabhq/config/gitosis.yml  # 檢查內容與路徑
rails s -e production # 啟動測試服務器
測試網址 http://localhost:3000 預設的帳號密碼 admin@local.host / 5iveL!fe # 安裝 Nginx
apt-get autoremove apache2*
dpkg --purge apache2*
apt-get install nginx
gem install passenger
passenger-install-nginx-module

# 選擇 1. Yes: download, compile and install Nginx for me. (recommended)
# passenger-install-nginx-module 會自動下載并編譯安裝 Nginx,預設裝到 /opt/nginx
設定 Nginx 當作 Gitlabhq 的 Server
vim /opt/nginx/conf/nginx.conf

===
user root;

server {
  listen 80;
  server_name gitlabhq;
  root /opt/gitlabhq/public;
  passenger_enabled on;
}
===

Reference:
http://isitruby19.com/linecache19
https://github.com/carlhuda/bundler/issues/1356
https://github.com/mark-moseley/linecache/issues/8
https://github.com/gitlabhq/gitlabhq/issues/66
https://github.com/gitlabhq/gitlabhq/issues/34
https://github.com/gitlabhq/gitlabhq/issues/84
https://github.com/gitlabhq/gitlabhq/issues/141

2013/05/22

Git 使用手冊

本篇文章以 Markdown 編寫,較佳的閱讀體驗請前往:
http://zx1986.github.io/blog/using-git.html

[Git][1] 是一套版本控制系統(Version Control System),
常用在對程式碼或文件進行版本管理及協作。
從前比較常用的版本控制系統是 SVN(Subversion),
但 SVN 是中央式的,而 Git 是分散式的,
且 Git 比 SVN 強大、先進許多。

我簡單解釋版本控制的概念,請想像一下:

你電腦內的資料夾類似一個書櫃,書櫃裡有許多書(檔案),
偶而有新書進來(新增檔案),有舊書捐出去(刪除檔案),
有時候會在某些書上作筆記、寫心得、畫畫(檔案內容變動)。

你在書櫃的側邊貼上一張「大大的白紙」,對書櫃裡的所有變動作紀錄。

紀錄新書擺入的時間,擺放的位置,甚至後面加個註記:『購於網路拍賣』;
紀錄舊書清除的時間,原本的位置,加個註記:『捐給讀書會』;
紀錄某書寫入筆記的時間,筆記的內容,心得或隨手塗鴉;
紀錄 ......

你可以把這張書櫃側邊貼著的「大大白紙」想像成版本控制系統(Git),
而且版本控制系統(Git)做的記錄會更鉅細靡遺。

當你對一個資料夾啟用 Git 進行追蹤管理與控制時(Git 初始化時),
Git 程式會在該資料夾底下新增一個名為「.git」的隱藏資料夾,
「.git」類似於前面提到那張「大大的白紙」,裡面紀錄了檔案的變化史。
Git 會對該資料夾內所有的檔案與其底層的所有資料夾進行紀錄追蹤,
而追蹤、記錄的結果都會儲存到「.git」這個資料夾內。

不過,Git 並不會主動記錄,必須是由使用者操作它去執行記錄的動作。
使用者類似史官的角色,而 Git 則是書寫史冊的工具。

Git 背後的運作方式是非常聰明而複雜的,
它的功能也不僅僅在於記錄(還有恢復、合併、差異處理等等)。

團隊合作時,同樣一個文件,在你手上跟在他人手上,可能有不一樣的變化史。
當你的檔案要與他人的合併時,內容有出入的地方,Git 會協助進行處理。
(例如開發同一個程式,你寫的 code 可能被他人改動,或反之。)

### 安裝與設定 Git

Ubuntu 底下安裝 Git 非常簡單,只要在終端機執行:
sudo apt-get install git-core git-doc
接着,建議執行以下指令,將系統預設編輯器設定為 Vim:
sudo update-alternatives --config editor
每個使用者帳號都會有自己的 Git 設定檔,通常是:
~/.gitconfig
例如我的設定檔內容是:
[user]
name = 張旭
email = zx1986@gmail.com

[color]
diff = auto
初始化 Git
(資料夾內會多出一個名為 .git 的隱藏資料夾):
git init
之後只要每次修改或新增檔案後,
執行以下兩個指令,Git 就會做一次紀錄:
git add 修改或新增的檔案名
git commit -m '關於此次修改的描述訊息'
可以開一個新的資料夾進行練習:
mkdir test
cd test
touch hello
git init
git add hello
git commit -m 'hello, Git!'
好了,您已經開始在使用 Git 啦!

### Git 輔助說明

需要注意,Git 不會把空的資料夾加入控管,
例如 log、cache 這類資料夾,我們通常不會想要追蹤裏面的檔案,
但還是需要這個資料夾存在,可以在底下建立一個隱藏檔,例如 .gitkeep:
cd log
tocuh .gitkeep
在跟「.git」同一層的目錄中,可以建立一個 .gitignore 檔案。
.gitignore 用來設定「不希望被 Git 控管的檔案與資料夾」。
一個簡單的 .gitignore 內容可以是這樣:
cache/
log/*.log
tmp/
*.tmp
*.swp
*.o
*.so
*.a
*.exe
*~
執行 `git help` 會顯示常用的 Git 指令與簡單說明:
add        Add file contents to the index
bisect     Find by binary search the change that introduced a bug
branch     List, create, or delete branches
checkout   Checkout a branch or paths to the working tree
clone      Clone a repository into a new directory
commit     Record changes to the repository
diff       Show changes between commits, commit and working tree, etc
fetch      Download objects and refs from another repository
grep       Print lines matching a pattern
init       Create an empty git repository or reinitialize an existing one
log        Show commit logs
merge      Join two or more development histories together
mv         Move or rename a file, a directory, or a symlink
pull       Fetch from and merge with another repository or a local branch
push       Update remote refs along with associated objects
rebase     Forward-port local commits to the updated upstream head
reset      Reset current HEAD to the specified state
rm         Remove files from the working tree and from the index
show       Show various types of objects
status     Show the working tree status
tag        Create, list, delete or verify a tag object signed with GPG
在 Git 指令後加上 -h 參數,能夠查詢該指令詳細的用法,例如:
git add -h
git commit -h
git pull -h
git push -h
要查詢更完整的指令手冊,則執行:`git help 指令名稱`

### 練習 Git

我推薦一個非常棒的線上練習:[Try Git](http://try.github.io)

這是由線上學習網站 [Code School](http://codeschool.com) 開發的,
他們還有一個 Git Real 的系列課程,我也非常推薦,
但 Git Real 系列課程是需要收費的。

Try Git 會帶着你練習基礎的 Git 指令,
畫面上半部是簡單明瞭的指令與情境說明,
畫面中間是一個模擬的 Console 端介面,
畫面下半部是當前情境下資料夾內的狀況。
雖然內容都是英文,但用字遣詞並不難,
就當成是玩電動闖關,邊玩邊學。

當進行到 Remote Repositories 這個關卡時,
如果對 Repository、Local、Remote 不大瞭解,
可以再回來這,繼續閱讀後面的內容。

### 關於 Git Repository 與 Branch

被 Git 所管理的專案,就是 Git Repository(倉儲)。
簡單點說,一個含有「.git」的資料夾,就是一個 Git Repository。
而一個 Git Repository 內,可以建立很多 Branch(分支),
不同的分支代表不同的變化史。

分支是可以任意建立、刪除、合併的。

Git Repository 裡預設的 Trunk Branch(主幹)稱為「master」,
其他的 Branch(分支)則由使用者自行命名,
master 這個 branch 也是可以被改成其他名字的。
(其實 Git 的世界並沒有 Trunk 這種講法,那是 SVN 的習慣,
在 Git 的世界,應該說那是“一個被叫做 master 的 branch”。)

Git 是一個分散式的版本控制系統,不同於 SVN 的 Server/Client 架構,
Git 不需要像 SVN 必須有一個 Repository Server 作為主要的倉儲伺服器。
Git 預設就可以使用 ssh 互相進行 Repository 傳輸了。

當使用 git clone 指令從遠端複製一個 Git Repository 到本地端電腦上時,
遠端的 Git Repository 通常稱為「origin」,「origin」可能有若干的 branch。
本地端 Git Repository 沒有特別的名稱,本地端也有自己的 branch。

`git remote -v` 指令可以查詢當前 Git Repository 的遠端來源。

假設一個簡單的應用情境:

假設遠端的電腦叫做 Remote;本地端的電腦叫做 Local。
Remote 上面有一個 Git Repository 資料夾叫做 remote_repository。

要將 remote_repository 複製到 Local 並命名為 local_repository,
在 Local 執行:
Local$ git clone 「Remote 使用者帳號@Remote 位址」:「remote_repository 在 Remote 上的路徑」   local_repository
如果您執行過 scp 指令,相信對這個 git clone 格式會覺得很熟悉。

複製完成(git clone)後,Local 與 Remote 已經可以分開獨立工作了。
Git 不必拘泥於一定要把修改過的檔案存回當初取得檔案的地方。
Remote 可以在 remote_repository 裡發展它的檔案;
Local 可以在 local_repository 裡發展它的檔案。

等到哪天 Remote 突然想取得並合併 Local 發展的檔案,
可以在 Remote 上執行:
Remote$ git pull 「Local 使用者帳號@Local 位址」:「local_repository 在 Local 上的路徑」
當然,如果 Local 想取得與合併其他人發展的檔案,
可以在 Local 上執行:
Local$ git pull 「使用者帳號@位址」:「路徑」

* 補充說明

git fetch - Download objects and refs from another repository.
git merge - Join two or more development histories together.
git pull - Fetch from and merge with another repository or a local branch.

`git pull` 等於先執行了 `git fetch`,然後再自動執行 `git merge` 。
[有前輩建議][4]少用 `git pull`,改用 `git fetch` 搭配 `git merge` 。
[也有前輩建議][5]應當多使用 `git rebase` 或 `git pull --rebase` 。

### SVN 式的往日時光

之前,我在不同的電腦上修改程式:研究室的電腦、宿舍的電腦、筆記型電腦。
因此我在研究室的一台主機上架了 SVN 伺服器,程式主要版本儲存在 SVN 伺服器上。
每當在不同的電腦進行程式編輯時,會先從 SVN 伺服器上抓最新版本的程式下來。
編輯告一段落後,再把修改過的程式上傳回 SVN 伺服器。
程式集中在一台 SVN 伺服器上,要編輯時從上面更新下來,編輯完再更新回去。

從 SVN 轉換到 Git 時,會很習慣於從前 SVN 那種模式:

1. 使用 svn checkout 從 SVN 伺服器將整個 Repository 複製到本機端。
2. 本機端對 Repository 的內容進行編輯、修改、新增、刪除等等。
3. 使用 svn update 檢查 SVN 伺服器有沒有其他更新與自己修改的內容有衝突。
4. 解決內容衝突的情況。
5. 使用 svn commit 將自己本機端的所有修改上傳到 SVN 伺服器。

怎麼用 Git 做到類似 SVN 那樣的情形?
有個簡單的方法。

首先,選定一台要當 Repository Server 的機器,假設叫 Server。
在 Server 開一個空的資料夾,假設叫 origin,並切換到該資料夾下。
Server$ mkdir origin
Server$ cd origin
在空資料夾底下執行:
Server$ git init --bare
這個動作會產生一個 [Bare Git Repository][2],
該資料夾下會產生:
branches/
config
description
HEAD
hooks/
info/
objects/
refs/
本地端的電腦,假設叫 Local。
Local 上一個叫 local_project 的資料夾要上傳到 Server 進行統一管理。

切換到該資料夾底下,執行:
Local$ git add .
Local$ git commit -a -m 'initialization'
Local$ git remote add origin 「Server 使用者帳號@Server 位址」:「Server 上 origin 資料夾的路徑」
Local$ git push origin master
完成以後,其他的電腦就可以使用以下指令,
從 Server 上的 origin 複製 local_project 的內容:
Other$ git clone 「Server 使用者帳號@Server 位址」:「Server 上 origin 資料夾的路徑」 「自訂的資料夾名稱」
其他電腦要將其修改的內容傳回 Server,可以執行:
Other$ git push origin master

### Git Repository Hosting

Git Repository 除了使用 git 協定或 ssh 協定,
還可以使用 http、https 等方式傳輸、瀏覽、管理。
如果不想要用簡單的 Bare Git Repository 架設 Repository Server,
有些 Open Source 的工具可以選擇:

- [Gitosis](https://github.com/res0nat0r/gitosis)
- [Gitorious](http://gitorious.org/)
- [Gitlab](http://gitlab.org/)

全世界最知名的 Git Repository Hosting 網站:

- [Github](https://github.com/)

中國大陸版的 Github:

- [GitCafe](https://gitcafe.com/)

Github 與 GitCafe 都非常棒,
它們的使用教學也有很多 Git 技巧可以參考:

https://help.github.com/
https://gitcafe.com/GitCafe/Help

GitCafe 的 Git [作弊表][3]。

_Git Cheating Sheet_

git init         # 將當前資料夾進行 Git 初始化

git add .        # 將當前資料夾內所有檔案加入 Git 追蹤(tracking 或 staging)
git add 檔案名稱 # 把當前資料夾內某個檔案加入 Git 追蹤(tracking 或 staging)

git status       # 查詢從上一次 commit 到現在,資料夾裡有哪些變化,各個檔案處於什麼狀況

git commit -a         # 將目前的變動送繳 Git 進行紀錄,會進入編寫修改訊息的畫面
git commit -a -m "*"  # commit 時直接寫入修改訊息,不進入編寫修改訊息的畫面

git tag v1.0          # 將當前 commit 過後的檔案版本命名為 v1.0

git diff                             # 比較所有檔案的內容與上一次 commit 時有何差異
git diff v1.0 v2.0                   # 比較 v1.0 與 v2.0 兩個版本間所有檔案的內容
git diff v1.0:檔案名稱 v2.0:檔案名稱 # 比較 v1.0 與 v2.0 兩個版本間某個檔案的內容

git log                         # 查詢所有版本的修改狀況,顯示各版本的 hash 編號
git log -p                      # 查詢哪幾行被修改
git log --stat --summary        # 查詢每個版本間變動的檔案跟行數

git show v1.0                   # 查詢 v1.0 版裡的修改內容
git show v1.0:檔案名稱          # 查詢某個檔案在 v1.0 時的內容

git show HEAD          # 看此版本修改的資料
git show HEAD^         # 看此版本前一版的修改的資料
git show HEAD^^        # 看此版本前前一版的修改的資料

git grep "*" v1.0      # 查詢 0.01 版裡頭有沒有某些內容
git grep "*"           # 查詢現在的版本裡有沒有某些內容

git branch                # 查看現有的分支
git branch 分支名稱       # 建立新的分支
git branch 分支名稱 v1.0  # 依照 v1.0 版本裡的內容來建立一個分支
git branch -d 分支名稱    # 刪除某個分支

git merge 某個分支名稱    # 將當前所在的分支與某個分支合併,如果出現衝突,會紀錄在有衝突的檔案中

git checkout master       # 切換到主幹上
git checkout 分支名稱     # 切換到某個分支上

git checkout HEAD         # 將所有檔案恢復到上次 commit 的狀態
git checkout -- 檔案名稱  # 將某個檔案恢復到上次 commit 的狀態

git reset --hard 某個版本的 hash 編號   # 整個 Repository 恢復到某個版本的狀態

git count-objects     # 分析 Git 資料庫狀況,計算鬆散的物件
git gc                # 維護 Git 資料庫,重組物件
git fsck --full       # 應該是類似 Git 磁碟重組之類的東西

Reference:
http://github.com/schacon/whygitisbetter
http://git-scm.com/documentation
http://gitcafe.com/riku/GitTips
http://gitimmersion.com/
http://gitref.org
http://rypress.com/tutorials/git/

[1]: http://git-scm.com/
[2]: http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/
[3]: https://gitcafe.com/GitCafe/Help/blob/master/Git/Git_Cheat_Sheet.md
[4]: http://longair.net/blog/2009/04/16/git-fetch-and-merge
[5]: http://ihower.tw/blog/archives/3843

2013/05/19

安裝 Percona XtraDB Cluster

本篇文章以 Markdown 編寫,較佳的閱讀體驗請前往:
http://zx1986.github.io/blog/setup-percona-xtradb-cluster.html

## 背景知識

#### Codership

[Codership][1] 是一家成立於 2007 年的公司,公司的 Founder 都是 Database 專家。
Codership 致力於研究及實做高擴展性且快速的資料庫同步機制(Replication),
並帶頭制定了名爲 WSREP 的 API 標準,
且根據這套 API 實做了 Galera 同步器(Replicator)。

#### WSREP(Write Set REPlication)

[WSREP][2] 是一個爲 DBMS(DataBase Management System)設計的 API 標準,
它爲 DBMS 類型的應用程式建立了一個 Replication 介面(Interface),
這個介面位於 DBMS 軟體與 Replication Servcie Provider(即 Replicator)之間。
[WSREP Group][3] 是討論與建立這個標準的開放性羣組。

> WSREP API defines a set of application callbacks and replication library calls necessary to implement synchronous writeset replication of transactional databases and similar applications. It aims to abstract and isolate replication implementation from application details.

#### Galera Replicator

[Galera][4] 是一套根據 WSREP 標準實做出來的 Replication 函式庫。
Galera 的運作架構可以參考[它們的說明][5]。大致的原則是:
當對 Cluster 中其中一個節點做寫入(Write)時,
Galera 會自動將寫入動作 Replicate 到 Cluster 其他的節點上。

> Galera implements WSREP pluggable interface, and can provide several replication modes and topologies, including the ultimate Synchronous Multi-Master replication.

#### MySQL Galera Cluster

傳統的 [MySQL Server][6] 只要打上 WSREP 的 Patch,支援了 WSREP 介面,
再搭配使用 Galera 函式庫,調整好設定檔,就可以組出一個 Cluster。

> MySQL/Galera cluster uses Galera library for the replication implementation. To interface with Galera replication, we have enhanced MySQL server to support replication API definition in the wsrep API project.

#### MariaDB Galera Cluster

相較於 MySQL 要額外打 Patch,
MariaDB 直接推出包好的 [MariaDB Galera Cluster][7],
MariaDB 還針對不同的 Linux 發佈版提供了[套件庫][8]。
它是 Percona XtraDB Cluster 之外的另一個選擇。

#### Percona XtraDB Cluster(PXC)

Percona 是一家專業的 MySQL 顧問與技術公司,
他們有一個很知名的 MySQL Blog:[MySQL Performance][9];
Percona 也開發了許多知名的[資料庫工具與軟體][10]。

XtraDB 是 Percona 基於 InnoDB 改良出來的一個資料庫引擎。
在 XtraDB 引擎的基礎上,Percona 發佈了一個修改過的 MySQL:Percona Server,
而 Percona XtraDB Cluster 則是 Percona Server + Galera Library 的整合產品。
Percona XtraDB Cluster 的資料庫同步機制是靠 Galera 完成。

## 安裝 Percona XtraDB Cluster

最新的 XtraDB 安裝檔:
[Percona XtraDB Cluster][11]
[XtraBackup][12]

以 Red Hat 環境(RHEL,Cent OS)爲例。

rpm -Uhv http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
yum install Percona-XtraDB-Cluster-server Percona-XtraDB-Cluster-client percona-xtrabackup
vim /etc/my.cnf

[mysqld]
wsrep_provider=/usr/lib64/libgalera_smm.so
wsrep_cluster_name=叢集的名稱
wsrep_cluster_address=gcomm://節點一的位址,節點二的位址,節點三的位址
wsrep_slave_threads=4
wsrep_sst_method=rsync
binlog_format=ROW
default_storage_engine=InnoDB
innodb_autoinc_lock_mode=2
innodb_locks_unsafe_for_binlog=1

service mysql start --wsrep-cluster-address="gcomm://"
mysql -e "CREATE FUNCTION fnv1a_64 RETURNS INTEGER SONAME 'libfnv1a_udf.so'"
mysql -e "CREATE FUNCTION fnv_64 RETURNS INTEGER SONAME 'libfnv_udf.so'"
mysql -e "CREATE FUNCTION murmur_hash RETURNS INTEGER SONAME 'libmurmur_udf.so'"
mysqladmin -u root password '12345678'
service mysql stop
service mysql start
mysql -u root -p
mysql> show status like 'wsrep_%';

以上是第一個節點的設定,其他節點只要重複到啓動 MySQL 那個步驟,
並將啓動的指令改爲:`service mysql start`

* `--wsrep-cluster-address="gcomm://"` 參數代表初始化一個全新的叢集!

#### SST

> State Snapshot Transfer is the full copy of data from one node to another.

SST 是 State Snapshot Transfer 的縮寫,指的是 PXC 各節點間同步資料的方式。
可以在 /etc/my.cnf 中透過 wsrep_sst_method 參數來設定。
PXC 有三種同步方式,分別是:

* wsrep_sst_method=mysqldump

> If you use mysqldump SST it should be the same as this mysql client connection address plus you need to set wsrep_sst_auth variable to hold user:password pair. The user should be privileged enough to read system tables from donor and create system tables on this node. For simplicity that could be just the root user. Note that it also means that you need to properly set up the privileges on the new node before attempting to join the cluster.

* wsrep_sst_method=rsync

> If you use rsync SST, wsrep_sst_auth is not necessary unless your SST script makes use of it.

* wsrep_sst_method=xtrabackup

> If you use xtrabackup as SST method, it will use /usr/bin/wsrep_sst_xtrabackup provided in Percona-XtraDB-Cluster-server package. And this script also needs user password if you have a password for root@localhost.

要使用 [xtrabackup 當作 SST method][13] 時,
需要設定 Database 的 root password 到 /etc/my.cnf 內,
例如:`wsrep_sst_auth=root:12345678`

PXC 官方手冊:
http://www.percona.com/doc/percona-xtradb-cluster/installation.html
http://www.percona.com/doc/percona-xtradb-cluster/manual/bootstrap.html

PXC 專有名詞:
http://www.percona.com/doc/percona-xtradb-cluster/glossary.html

Reference:
http://www.mysqlperformanceblog.com/2013/01/29/how-to-start-a-percona-xtradb-cluster/
http://www.percona.com/files/presentations/WEBINAR-percona-xtradb-cluster-installation-and-setup.pdf

[1]: http://www.codership.com/company/
[2]: https://launchpad.net/wsrep/
[3]: https://launchpad.net/wsrep-group/
[4]: https://launchpad.net/galera/
[5]: http://www.codership.com/products/galera_replication/
[6]: http://www.codership.com/products/mysql_galera/
[7]: https://downloads.mariadb.org/mariadb-galera/
[8]: https://downloads.mariadb.org/mariadb/repositories/
[9]: http://www.mysqlperformanceblog.com
[10]: http://www.percona.com/software
[11]: http://www.percona.com/downloads/Percona-XtraDB-Cluster/LATEST/
[12]: http://www.percona.com/downloads/XtraBackup/LATEST/
[13]: http://serverfault.com/questions/389190/xtrabackup-for-sst-with-xtradb-cluster

2013/01/14

Apache 的 Proxy 設定

http://httpd.apache.org/docs/2.4/mod/mod_proxy.html

Forward Proxy:ProxyRequests
Reverse Proxy:ProxyPass