ラベル さくらのvps の投稿を表示しています。 すべての投稿を表示
ラベル さくらのvps の投稿を表示しています。 すべての投稿を表示

2013/02/15

VPS複数台をL2TP/IPSec(xl2tpd+openswan)で接続 on CentOS 6

複数台のVPS(さくらのVPS)を、L2TP/IPSecでVPN接続することにしましたので、
自分用メモとして記事にします。今回は、とりあえず2点間接続を行います。
尚、3点間以上も同じ手順でクライアントを追加していくだけです。
(ちなみに目的は、MongoDBでReplicaSet、Shardingを行う為だったりしますw)
  • L2TPの実装: xl2tpd
  • IPSecの実装: openswan
    (昔はFreeS/WanというIPSecの実装があったそうですが、開発が止まっていて・・・。
    そこから派生して現在の主流となっているのが、openswanなんだそうです。なるほど。
サーバは、さくらのVPS (Cent OS 6.x 64bit) です。

記事の内容は試行錯誤の結果であり、間違っている可能性もあります。
もしご指摘、アドバイス等ありましたら、よろしくお願いします m(_ _)m

今回、以下の内容については、
を参考にさせていただきました。(感謝です!! m(_ _)m♪!)


まず、サーバ/クライアント共通の環境構築から。


はじめに、必要なパッケージをインストールします。
既に入っているものも多いかと思いますが...念の為。

$ sudo yum install gcc gmp gmp-devel flex bison libpcap-devel ppp
ところで、この記事では行いませんが・・・
openswanは
NSS(Mozillaによる証明書ライブラリ)による証明書認証に対応しています。後々から証明書に対応できるよう、NSSをインストールしておきましょう。
$ sudo yum install nss nss-devel nss-tools
(実際のところ、VPNを実運用するには、文字列だけでの認証では心許ないです。)

次に、openswanをソースコードからビルドしてインストールします。
(執筆時の最新版は、openswan-2.6.38です。 Amazon S3から配布されているんですね〜。
また...余談ですが、
openswanのサイトには自己署名の証明書が使われているようで、SSLエラーとなりました。ご注意を。)
$ wget https://s3-ap-northeast-1.amazonaws.com/openswanjp/openswan-2.6.38.tar.gz
$ tar zxf openswan-2.6.38.tar.gz
$ cd openswan-2.6.38/
ここでも、後々から証明書を使えるようにNSSサポートを有効にしておきましょう。
ドキュメント(docs/README.nss)によると、Makefile.incのオプションを弄るそうです。
$ vi Makefile.inc
~~~~
# Support for NSS crypto library (does not requires HAVE_THREADS)
# USE_LIBNSS uses pthreads by default.
USE_LIBNSS?=true
~~~~
(372行目付近に2箇所ありますが、USE_LIBNSS?をtrueにしておきます。)

あとはmakeしてインストールです。
$ make programs
$ sudo make install
次に、xl2tpdをビルドしてインストールします。
(執筆時の最新版は、xl2tpd-1.3.1です。ちなみに...EPELリポジトリからインストールする方法もありです。)
$ cd ..
$ wget https://github.com/xelerance/xl2tpd/archive/v1.3.1.tar.gz -O xl2tpd-v1.3.1.tar.gz
$ tar zxf xl2tpd-v1.3.1.tar.gz
$ cd xl2tpd-1.3.1/
$ make
$ sudo make install
さらに、起動用のコマンドをコピーしておきます。
$ su
# cp packaging/fedora/xl2tpd.init /etc/init.d/xl2tpd
# chmod +x /etc/init.d/xl2tpd
(※以降、シンタックスハイライトの都合上、コマンド文の色が黒色ですが、特にお気になさらずに(汗;))
また、/usr/local/sbin にインストールされたので、/usr/sbinからリンクを張ります。 
 # ln -s /usr/local/sbin/xl2tpd /usr/sbin/xl2tpd
サービスも登録しておきます。
 # chkconfig --add xl2tpd
# chkconfig --add ipsec
# chkconfig xl2tpd on
# chkconfig ipsec on
これでインストールは完了です。
(ここまで、サーバ側、クライアント側ともに同じです。)




次に、サーバ側の設定です。


まず、xl2tpd(L2PT)の設定を行なっていきます。
# mkdir /etc/xl2tpd
# cp examples/xl2tpd.conf /etc/xl2tpd/
# cp examples/ppp-options.xl2tpd /etc/ppp/options.xl2tpd
# vi /etc/xl2tpd/xl2tpd.conf
~~~~
[global]
[lnsdefault]
;ip range = 192.168.1.128-192.168.1.254
ip range = 192.168.253.128-192.168.253.254
;local ip = 192.168.1.99
local ip = 192.168.253.1
name = %L2TPNAME%
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
(%L2TPNAME%は適当に。以降使っていきます。
ここで指定したip rangeの範囲が、VPN上でクライアントに割り当てられます。
またlocal ipがVPN上でのサーバのプライベートIPアドレスとなります。)
# vi /etc/ppp/options.xl2tpd
name %L2TPNAME%
ms-dns ns1.dns.ne.jp
ms-dns ns2.dns.ne.jp
#ms-dns 192.168.1.1
#ms-dns 192.168.1.3
#ms-wins 192.168.1.2
#ms-wins 192.168.1.4
#noccp
auth
nobsdcomp
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
persist
#proxyarp
connect-delay 5000
refuse-pap
refuse-chap
require-mschap-v2
logfile /var/log/xl2tpd.log
(ns*.dns.ne.jpは、さくらのDNSです。それ以外のDNSサーバを使っている場合は、変更してください。
ただし、今回の場合、ms-dnsは要らないかもしれないです・・・。
 pppの各オプションの意味はググって
ドキュメントを探すか、man pppdで参照できます。)

chap-secrets(ユーザ認証)の設定も行います。
また大事なファイルなので、root以外の閲覧ができないよう権限を設定します。
# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" *
(%USERNAME%%CHAP-PASSWORD%も適当に。といっても管理は大切に。)
# chmod 600 /etc/ppp/chap-secrets

次に、openswan(IPSec)の設定を行なっていきます。
# vi /etc/ipsec.conf
version2.0

config setup
    dumpdir=/var/run/pluto/
    nat_traversal=yes    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
    oe=off
    protostack=netkey
    nhelpers=0
    plutostderrlog=/var/log/pluto

include /etc/ipsec.d/l2tp-psk.conf
次に、Pre-shared Key(共有鍵)の設定も行います。
また、こちらも大事なファイルなので、権限設定します。

# vi /etc/ipsec.secrets<
%SERVER-IPADDRESS% %any : PSK "%PSK-PASSWORD%"
(%SERVER-IPADDRESS%は、サーバのグローバルIPアドレスです。)
# chmod 600 /etc/ipsec.secrets
さらに、L2PTを扱う設定も行います。
# cp /etc/ipsec.d/examples/lt2p-psk.conf /etc/ipsec.d/
# vi /etc/ipsec.d/l2tp-psk.conf
conn L2TP-PSK-NAT
    rightsubnet=0.0.0.0/0
    also=L2TP-PSK-noNAT

conn L2TP-PSK-noNAT
    forceencaps=yes
    authby=secret
    pfs=no
    auto=add
    keyingtries=3
    rekey=yes
    dpddelay=40
    dpdtimeout=130
    dpdaction=clear
    ikelifetime=8h
    keylife=1h
    type=transport
    left=%SERVER-IPADDRESS%
    leftnexthop=%defaultroute
    leftprotoport=17/1701
    right=%any
    rightprotoport=17/%any

#conn passthrough-for-non-l2tp
#    type=passthrough
#    left=YourServerIP
#    leftnexthop=YourGwIP
#    right=0.0.0.0
#    rightsubnet=0.0.0.0/0
#    auto=route
最後に、sysctl.confを変更します。
# /etc/sysctl.conf
~~~~
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
~~~~
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
# sysctl -p
あとは起動して・・・<
# service xl2tpd start
# service ipsec start
動作確認を行います。
# ipsec verify
エラーが出ていなければ、とりあえず問題ないということで。
iptablesも設定しておきます。
# vi /etc/sysconfig/iptables
*filter
~~~~
-P FORWARD DROP
-A INPUT -p udp -m udp --dport 1701 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A INPUT -p udp -m udp --dport 500 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A INPUT -p udp -m udp --dport 4500 -i eth0 -d %SERVER-IPADDRESS% -j ACCEPT
-A FORWARD -i ppp+ -o ppp+ -s 192.168.253.0/24 -d 192.168.253.0/24 -j ACCEPT
-A FORWARD -i ppp+ -o eth0 -s 192.168.253.0/24 -j ACCEPT
-A FORWARD -i eth0 -o ppp+ -d 192.168.253.0/24 -m state --state RELATED,ESTABLISHED -j ACCEPT
COMMIT
*nat
-A POSTROUTING -s 192.168.253.0/24 -j MASQUERADE
COMMIT
(参考元: http://www.manabii.info/2012/08/debian-gnu-linux-l2tp-ipsec-vpn-nat.html)
また、必要に応じて、VPN間でアクセス可能なポートなどを設定するといいかもしれません。


# service iptables restart
これでサーバ側の設定は完了です。


さて...次はクライアント側の設定です。


まずは、xl2tpd(L2TP)の設定を行なっていきます。
# mkdir /etc/xl2tpd
# cp examples/xl2tpd.conf /etc/xl2tpd/
# vi /etc/xl2tpd/xl2tpd.conf
[global]

[lac L2TP1]
lns = %SERVER-IPADDRESS%
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd.conn-1
length bit = yes

;[lns default]
;ip range = 192.168.1.128-192.168.1.254
;local ip = 192.168.1.99
;require chap = yes
;refuse pap = yes
;require authentication = yes
;name = LinuxVPNserver
;ppp debug = yes
;pppoptfile = /etc/ppp/options.xl2tpd
;length bit = yes
(lns defaultのセクションはすべてコメントアウトします。
L2TP1は、xl2tpd-controlで接続する際の接続名になります。そのままでも構いません。
次に、こちらもサーバ側と同じようにchap-secretsの設定を行います。
また、root以外の閲覧ができないよう権限を設定します。
# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" *
# chmod 600 /etc/ppp/chap-secrets
さらに接続設定を行います。
# vi /etc/ppp/options.xl2tpd.conn-1
name %USERNAME%
noauth
crtscts
mtu 1410
mru 1410
nodefaultroute
lock
#proxyarp
logfile /var/log/xl2tpd.conn-1.log
(どうもこのnoauthが引っ掛かりますが...これを他に変更すると動かないという。
サーバのほうはauthにしていますし、実際認証は行われているのですが・・・。
pppdのドキュメントによれば、noauthは"相手に認証を要求しない"オプションなので、サーバ側に対する話なのか? でもそもそも、CHAPだとサーバから認証を開始しますから...。(イマイチ...よくわかりませんw))


次に、openswan(IPSec)の設定を行なっていきます。
# vi /etc/ipsec.conf
config setup
    dumpdir=/var/run/pluto/
    nat_traversal=yes
    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
    oe=off
    protostack=netkey
    nhelpers=0
    plutostderrlog=/var/log/pluto
~~~~
include /etc/ipsec.d/connection.conf
# vi /etc/ipsec.d/connection.conf
conn %PEER_L2TP%
    authby=secret
    pfs=no
    rekey=yes
    keyingtries=3
    type=transport
    left=%CLIENT-IPADDRESS%
    leftprotoport=17/1701
    right=%SERVER-IPADDRESS%
    rightprotoport=17/1701
    auto=add
(%PEER_L2TP%は、ipsec autoで接続する際の接続名になります。そのままでも構いません。
%CLIENT-IPADDRESS%は、クライアント側のグローバルIPアドレスです。%defaultrouteでもいいかも。
)

またサーバ側と同じ形式でPre-shared Keyを設定します。
# vi /etc/ipsec.secrets
%CLIENT-IPADDRESS% %any : PSK "%PSK-PASSWORD%"
(%SERVER-IPADDRESS%は、サーバのグローバルIPアドレスです。)
# chmod 600 /etc/ipsec.secrets
最後にこちらも、sysctl.confを変更します。
# /etc/sysctl.conf
~~~~
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
~~~~
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
# sysctl -p
サーバ側と同様にサービスを起動して・・・
# service xl2tpd start
# service ipsec start
ipsec_setup: Starting Openswan IPsec U2.6.38/xxx
・・・とここで...(´・ω・`)
いつまで経ってもスクリプトが終了しない(ターミナルの制御が戻らない)現象が。
どうやら今回は、新調したサーバですのでエントロピープールが足りないようです。
そんなことがあるんですね〜・・・w
# cat /proc/sys/kernel/random/entropy_avail 6
確かに足りないw そんな時には・・・なんか処理をしてもらいます。
# find /# cat /proc/sys/kernel/random/entropy_avail
499
(`・ω・´)シャキーンw これでOKですね。
気を取り直して...

設定確認を行います。
# ipsec verify
問題なければ・・・
いよいよ、IPSecの接続を行います。
# ipsec auto --up PEER_L2TP
続けて、L2TPの接続を開始します。(これでppp0が作成されます。)
# echo "c L2TP1" > /var/run/xl2tpd/l2tp-control

接続確認をしてみましょう。
まずは、クライアント側→サーバ側へping。
# ping 192.168.253.1
・・・ OKでした。
サーバ側→クライアント側へping。
# ping 192.168.253.128
・・・ダブルOK\(^o^)/(←

ちなみに、ifconfigをクライアント側で実行すると、こんな感じに表示されます。
# ifconfig
eth0      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx
          inet addr:133.242.142.23  Bcast:133.242.143.255  Mask:255.255.254.0
          inet6 addr: xxxx::xxxx:xxx:xxxx:xxxx/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:xxxxxx errors:0 dropped:0 overruns:0 frame:0
          TX packets:xxxxxx errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:xxxx (xx MiB)  TX bytes:xxxx (xx MiB)

lo        (略)

ppp0      Link encap:Point-to-Point Protocol
          inet addr:192.168.253.128  P-t-P:192.168.253.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1410  Metric:1
          RX packets:19 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:2540 (2.4 KiB)  TX bytes:1504 (1.4 KiB)
(この設定では、クライアント側のppp0のinet addrは、
VPN上でのプライベートIPアドレスとなっているはずです。
また、P-t-Pは、VPN上でのサーバのプライベートIPアドレスとなります。)


以上です。
今回はこれでとりあえず開通させることができましたw

他サイトを参考にさせていただき...。この記事は一応整理した後に書きました。
ただ...実際のところは、何かと嵌ってしまったり(´・ω・`)...
ログファイル(/var/log/secure、/var/log/pluto、/var/log/xl2tpd、/var/log/xl2tpd.conn-1.log あたり)や、設定ファイルとにらめっこしながら、1日以上...試行錯誤していました(^^;)ゞ(笑)
うまくいくときは、すんなり行くんでしょうけどね...(;´д`)トホホ…。

ちなみに...1つ注意しておきたいのですが、ipsec auto --up して接続したときにエラーになると、一旦、ipsec auto --downしないと、再接続しようとしても何も表示されない...ということがありました。
...当然なのかもしれないですが、注意です(><)

あとは...このままで実用するとセキュリティがどうかと思うこともありますので、また設定をさらに弄っていこうと思いますw (X.509証明書認証も。)
ご指摘などありましたら、宜しくお願いします m(_ _)m
今回は以上ということで...それではっ。

[追記]
本記事中には反映していませんが、早速、証明書(X.509)認証に変更してみました。
こちらは大変すんなりと行きましたε-(´∀`*)♪ 本記事の最初のほうに書いたとおり、openswanのビルドを行う際にNSSを有効にしておくと・・・あとは証明書を作成して設定を行うだけです。
NSSでの証明書作成/openswanへの設定はこちらがとても参考になりました:
→ openswanでIPsec VPN(トランスポート・X.509認証) [Fedora14]  (感謝♪)

[2013/04/04 修正]
鍵まわりの問題により、一定時間で接続が切断される不具合があったため、pppまわりの設定を修正しました。

[2013/05/01 追記]
クライアントに割り当てるプライベートIPアドレスの範囲はサーバ側の/etc/xl2tpd/xl2tpd.confで設定しますが、
このプライベートIPアドレスをクライアントごとに固定としたい場合は...
双方の /etc/ppp/chap-secrets で、以下のように指定します。

# vi /etc/ppp/chap-secrets
"%USERNAME%" "%L2TPNAME%" "%CHAP-PASSWORD%" "192.168.253.128"

(この例では、192.168.253.128が割り当てられる。)

2013/02/10

Hello, Jenkins. GitLab+Jenkins+perl(Mojolicious)でCIをしてみた

こたつ最高(>ω<)♪ こたつで丸くなっております、Masanoriです(笑)

公開しているプロジェクトではTravis-CIを使わせていただいていたりするのですが
今回は、自前のGitLabで管理しているプロジェクトにもCIを...ということで...

Jenkinsをインストールして、GitLab上のGitリポジトリ、
および nginx(リバースプロキシとして...)と組み合わせる話(※自分用メモ)です。
また、
Jenkinsを用いて、perl(Mojolicious)のプロジェクトをテストします。
(加えて、CPANモジュールの一時的な自動インストールも行えるようにします。[追記: 2013/02/11])


※尚...Gitlabには、Gitlab CIというシンプルなソフトウェアが提供されており、通常はそちらを使うと良いと思います。今回は Jenkinsを使うこととしました。
Jenknsをちゃんと使ってみたかった!という動機がw
  • サーバはいつも通りのCentOSです。JDKなどもセットアップ済みです。
  • nginxをリバースプロキシとして、Jenkinsを /jenkins 下で動作させます。
    (毎度お断りしておきますが、以下にある設定内容は実際の運用サーバとは異なります。)
  • プロジェクトはすでにGitLabで作成済みで運用中、nginxも運用中です。
以下、
madroom project: Gitoliteに触れずにGitLabのhookからJenkins側でビルドする
を参考にさせていただきました。感謝! m(_ _)m♪
(Gitoliteを弄らない方法になっています。)


まずはJenkinsのウェブサイトからRPMをダウンロードしてインストール。
(LTS版もあるみたいですが、最新のJenkins-1.500を選択。)
$ wget http://pkg.jenkins-ci.org/redhat/jenkins-1.500-1.1.noarch.rpm
$ sudo rpm -ivh jenkins-1.500-1.1.noarch.rpm
これでJenkinsのインストールは完了です。とても楽ちんでありがたいですね。

次にJenkinsからGitリポジトリへアクセスできるよう鍵を作ります。
(今回はサーバ上でなくクライアント上で作って転送したほうが、GitLabでの登録がうまく行くそうです。)
$ ssh-keygen
Enter file in which to save the key (~~~): id_rsa_jenkins
Enter passphrase (empty for no passphrase): (空)
Enter same passphrase again: (空)
作成した鍵は、/var/lib/jenkins/.ssh/ 下に置いておきます。

さらに /var/lib/jenkins/.ssh/config を記述します。
$ sudo vi /var/lib/jenkins/.ssh/config
Host example.com
    User gitolite
    Port xx
    Hostname example.com
    IdentityFile /var/lib/jenkins/.ssh/id_rsa_jenkins
またknown_hostsも手動で記述しておきますw
$ sudo vi /var/lib/jenkins/.ssh/known_hosts
[example.com]:xx,[xxx.xx.xxx.xxx]:xx ssh-rsa ~~~~
次にJenkinsの設定ファイル(/etc/sysconfig/jenkins)を開いて
ポート設定およびディレクトリパスを変更します。

$ sudo vi /etc/sysconfig/jenkins
~~~~
# JENKINS_PORT="8080"
JENKINS_PORT="8888"
~~~~
#JENKINS_ARGS=""
JENKINS_ARGS="--prefix=/jenkins"
さらにnginxの設定ファイルにリバースプロキシのための設定を追加しておきます。
$ sudo vi /etc/nginx/nginx.conf
http {
    ~~~~
    upstream Jenkins.backend {
        server 127.0.0.1:8888;
    }
 ~~~~
    server {
        ~~~~
        location ~ ^/jenkins.* {
                proxy_pass      http://Jenkins.backend
                break;
        }
        ~~~~
    }
}
次に、Gitlabにブラウザからアクセスし、Jenkinsのユーザアカウントを作成します。
またCIを行うプロジェクトの"Reporter"権限をそのアカウントに対し設定します。

さらに、プロジェクトのWebHooks画面で JenkinsのURL (http://example.com/jenkins/git/notifyCommit?url=gitolite@example.com:xxx/yyy.git)
を登録しておきます。

また、作成したアカウントでGitlabにログインして、
さきほど作成した公開鍵を登録します。


次に...Jenkinsを起動します。
$ sudo service jenkins start
これでブラウザからアクセスできるようになっているはずです。 http://example.com/jenkins

早速、"新規ジョブ作成"へ進....
...といいたいところですが、その前に...Git Pluginのインストールです。
これがWebのUIで取得〜適用まで可能になってるんですね〜...素晴らしいです! (ちょっと違うところでは、TracとかRedmineもそうなってきてますが、手軽でありがたいことですw
 以下スクリーンショット付きですw)


まず、"Jenkinsの管理"をクリック。
"プラグインの管理"をクリック。
"利用可能"タブをクリックして...
"Git Plugin"にチェックを入れ、"再起動せずにインストール"をクリック。
(※"Git Server Plugin"などありますが、またこれとは別です。
 "Git Plugin"だけ、フィルタをかけてもうまくヒットしないときがありました。 "高度な設定タブで、設定をいじったり、何回か更新処理を実行した後に正しく表示されました。)

(それにしても...他にも色々おもしろそうなプラグインがwktk)

"インストール完了後、ジョブがなければ〜再起動"にチェックを入れて待ちます。
インストールが終われば、ダッシュボードから再度、"Jenkins"の管理をクリックし、 "システムの設定"をクリックします。

"Git plugin" セクションの"Global Config user.name Value"と、
 "Global Config user.email Value"を入力し、"保存"をクリック。


次に、再度ダッシュボードに戻り、
"新規ジョブ作成"をクリック。
ジョブ名を入力し"フリースタイル・プロジェクトのビルド"を選択。
"OK"をクリック。

"Git"にチェックを入れ "Repositories"の
"Repository URL"に ssh://~なURLを入力して・・・

さらに、"ビルド・トリガ"セクションの "SCMをポーリング"にチェックを入れ "保存"をクリックします。

また最後であれですが..Jenkinsで認証を設定しておきましょう(※最初にやるべきか(汗;
"Jenkinsの管理"→"グローバルセキュリティの設定"から、設定できます。
 [追記:2013/02/11]
"アクセス制御"セクションの "行列による権限設定"を選択して、表を編集することで、非ログインユーザーによる閲覧をブロックすることが可能です。
(※尚、"ログイン済みユーザーに許可"のほうを選択してしまうと、非ログインユーザでも閲覧はできますので注意。)
尚、このグローバルセキュリティの設定ですが、設定ミスによりアクセスできなくなった場合は、
一時的に無効化しましょう (→ Jenkins パスワードのリセット方法 - エンジニアきまぐれTips (感謝♪))


さらにもし必要ならば、別途、nginx側などで閲覧認証をつけてください。

これでプロジェクトを取り込む設定は、ひとまず完了です。

あとは、GitLab上でTest Hookを実行するか、リポジトリにプッシュすれば
Jenkins側で、ひとまずビルドが走ります.........



さて、これではまだ、テストケースを実行して評価することができません。

今回CIを実施したいプロジェクトは、
perlのMojoliciousというWAFで開発しているWebアプリケーションなのですが、
これをJenkinsでテストできるよう設定したいと思います。

Tatsuya Blog » PerlのテストコードをJenkinsで動かすのページを
参考にさせていただきました。感謝です m(_ _)m♪
  • 但し、今回の記事では、テスト実行の際、一時的にCPANモジュールを自動インストールできるようにしておきます
    インストールされるモジュールは、Makefile.PLに定義します。
  • テストスクリプト(t/*.t)とMakefile.PLについては、作成済みです。
    Makefile.PLは、以前の記事: Travis CIでPerl(Mojolicious)アプリケーションを自動テストを参照。
    また、Mojoliciousでのテストスクリプトの書き方は、Test::Mojoなどを参考に。
まず cpanmを Jenkins用に、
Jenkinsのホームディレクトリ(/var/lib/jenkins)下へインストールします。

$ sudo -u jenkins mkdir /var/lib/jenkins/bin
$ cd /var/lib/jenkins/bin
$ sudo -u jenkins curl -LOk https://raw.github.com/miyagawa/cpanminus/master/cpanm
$ sudo chmod +x ./cpanm

次に、cpanmで、TAP::Formatter::JUnit をインストールします。
$ sudo cpanm TAP::Formatter::JUnit

次に、Jenkins上のプロジェクトの設定画面を開きます。


ここでは、"ビルド"セクションで、"シェルの実行"を選び、
"シェルスクリプト"欄に次のコマンドを記述します。
/var/lib/jenkins/bin/cpanm -l dlibs --installdeps .
prove -Idlibs/lib/perl5 -b --formatter=TAP::Formatter::JUnit -lvr t > test_results.xml
(最初にcpanmを使って、dlibsフォルダ下にモジュールを自動ダウンロードしています。
尚、proveコマンドについては、詳細なログが不要であれば-v オプションを取り除くといいです。
オプションについて詳しくは...prove についてのおさらいを参照するとよいでしょう。(感謝♪))


さらに、"テスト後の処理"セクションで、"JUnitテスト結果の集計"を選び、
 "テスト結果XML"欄に次のファイル名を入力します。
test_results.xml
"保存"ボタンをクリックして設定完了です。

あとはプッシュすれば、ビルドが自動的に行われ、テスト結果が生成されます。
また手動でもビルド実行が可能です。

無事通過(PASS)したテスト。Jenkinsでは青色のマークが表示されます。
通知設定などはまた別途行ってください。
それにしても...Jenkinsおじさん、ステキですwww

[2013/02/18 追記]
今回の続きとして...Jenkinsへスレーブを追加してみました。
Masanoriのプログラミング日誌++: Jenkinsのスレーブノードを追加してみた

2012/08/06

Gitlabの導入 (Unicorn+nginxでサブディレクトリへ配置)

Gitlab 2.7をCentOS 6.2でインストールしてみることにしました。
nginx+Rails+Unicornで動作させます。
  • もはや言い訳のようになっていますが、試行錯誤の結果の自分用メモです (汗;)
    試行錯誤の結果、適当にやってみているところ、
    また、環境依存の箇所もありますのでご了承おねがいします
    m(_ _;)m
  • 従いまして、もし参考にしていただける場合は、お手数をお掛けしますが、
    一度このページの末尾まで全て目を通されることをおすすめします。
  • Gitlabのドキュメントでは、socketファイルを用いてnginxとUnicornを通信させていますが、この記事では、ポートを指定させて動作させます。
  • 本記事では、GitLabをサブディレクトリに配置して動作させます。
  • GitとGitoliteは以前に導入済みです:
    http://masanoriprog.blogspot.jp/2012/06/gitgitolite.html

作業の前にvisudoを実行し、secure_pathに/usr/local/binを追加しておきます。
(参照: http://blog.bungu-do.jp/archives/3525)
$ su
# visudo 
~~~~
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/local/bin/:/usr/bin
~~~~
さて..まずはGitlabのためのユーザアカウントを作成します。
また、作成したアカウントをgitoliteのグループに所属させます。

# useradd gitlab
# usermod -G gitolite gitlab
次に、Gitのリポジトリディレクトリのパーミッションを変更しておきます。
(gitoliteグループに対して読み書き実行の許可をあたえます。)

# chmod -R g+rwx /pathto/repositories/
次に、GitlabアカウントがGitoliteに接続するためのSSH鍵生成と設定を行います。
とりあえず、gitlabユーザになるために一旦suします。
# su gitlab
$ ssh-keygen -t rsa -P "" -f ~/.ssh/gitadmin 
$ vi ~/.ssh/config
Host    localhost
HostName        localhost
User    gitolite
IdentityFile    ~/.ssh/gitadmin 
$ chmod 0600 ~/.ssh/config
$ git config --global user.name "gitadmin"
$ git config --global user.email "gitadmin@example.com"
$ exit
この作成したgitlabアカウントと鍵で
Gitolite上のgitolite-adminへアクセスできるよう設定しておきます。

(いつも管理してるクライアントPCからやると楽です。)
Gitlabのドキュメントでは、サーバ上でgitoliteをgit cloneして最初に鍵ファイルを設定して登録しています・・・
が...今回は、運用中のシステムのセキュリティの設定上面倒なこともあり、このようにしています。
本来であればドキュメント通りが正しいですのでそちらの方法で行なってください。
CLIENT $ git clone gitolite@example.com:gitolite-admin
CLIENT $ cd gitolite-admin/
CLIENT $ touch keydir/gitlab.pub
CLIENT $ vi keydir/gitlab.pub 
ssh-rsa ~~~~ gitlab@~~ #gitadmin.pubの中身をコピペ
CLIENT $ vi conf/gitolite.conf 
repo    gitolite-admin
        RW+     =   gitolite gitlab #gitlabを追加しておく
CLIENT $ git add .
CLIENT $ git commit
CLIENT $ git push
次に、Gitlabをgitlabアカウントのルートディレクトリへgit cloneしてきます。
# cd /home/gitlab/
# sudo -H -u gitlab git clone -b stable git://github.com/gitlabhq/gitlabhq.git gitlab
# cd gitlab/
# sudo -u gitlab mkdir tmp 
# sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml
GitlabでSQLiteを使うための設定を適用しておきます。
# sudo -u gitlab cp config/database.yml.sqlite config/database.yml
必要なものをインストールしていきます。
# easy_install pygments
# gem install bundler
# bundle
・・・とここでエラー(´・ω・`)
~~~~ ~~~~
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
        /usr/local/bin/ruby extconf.rb
checking for main() in -licui18n... no
which: no brew in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/masanori/bin)
checking for main() in -licui18n... no

***************************************************************************************
*********** icu required (brew install icu4c or apt-get install libicu-dev) ***********
***************************************************************************************
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/usr/local/bin/ruby
--with-icu-dir
--without-icu-dir
--with-icu-include
--without-icu-include=${icu-dir}/include
--with-icu-lib
--without-icu-lib=${icu-dir}/lib
--with-icui18nlib
--without-icui18nlib
--with-icui18nlib
--without-icui18nlib

Gem files will remain installed in /usr/local/lib/ruby/gems/1.9.1/gems/charlock_holmes-0.6.8 for inspection.
Results logged to /usr/local/lib/ruby/gems/1.9.1/gems/charlock_holmes-0.6.8/ext/charlock_holmes/gem_make.out
An error occured while installing charlock_holmes (0.6.8), and Bundler cannot continue.
Make sure that `gem install charlock_holmes -v '0.6.8'` succeeds before bundling.
libicuが無いっぽいのでインストール。
# wget http://mirror.centos.org/centos/6/os/x86_64/Packages/libicu-4.2.1-9.1.el6_2.x86_64.rpm
# rpm -ivh libicu-4.2.1-9.1.el6_2.x86_64.rpm
# wget http://mirror.centos.org/centos/6/os/x86_64/Packages/libicu-devel-4.2.1-9.1.el6_2.x86_64.rpm
# rpm -ivh libicu-devel-4.2.1-9.1.el6_2.x86_64.rpm
# rm ./libicu-devel-*

もう一回、bundleを実行...
# bundle 
~~~ 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from httparty:
When you HTTParty, you must party hard!
うまくいった。続いて...Gemのインストール。
# sudo -u gitlab -H bundle install --without development test --deployment
DBのセットアップ。
# sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
構成のテストを行います。
# sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
rake aborted!
Connection refused - Unable to connect to Redis on 127.0.0.1:6379
Tasks: TOP => gitlab:app:status => environment
(See full trace by running task with --trace)
(´・ω・`)・・・まずRedis入ってなかったorz
# yum install redis
~~~
Installed:
  redis.x86_64 0:2.4.10-1.el6                                                
Complete!
# service redis start
はい。 もう一丁、テスト実行
# sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production 
Starting diagnostic
config/database.yml............exists
config/gitlab.yml............exists
/home/git/repositories/............missing
rake aborted!
unexpected return
Tasks: TOP => gitlab:app:status
(See full trace by running task with --trace)

(´・ω・`)まあそりゃーな。無いもんな。
実はうちの環境では、/home/git/repositories/下にリポジトリを置いていないのです・・・
ということでGitlabの設定変更。

# vi config/gitlab.yml
~~~
git_host:
  admin_uri: git@localhost:gitolite-admin
  base_path: /pathto/repositories/  # host: localhost
  git_user: git
~~~
再度、テスト実行。
# sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production 
Starting diagnostic
config/database.yml............exists
config/gitlab.yml............exists
/var/lib/gitolite/repositories/............exists
/var/lib/gitolite/repositories/ is writable?............YES
ssh: connect to host localhost port 22: Connection refusedfatal: The remote end hung up unexpectedly
Can clone gitolite-admin?............YES
UMASK for .gitolite.rc is 0007? ............NOrake aborted!
unexpected return
Tasks: TOP => gitlab:app:status
(See full trace by running task with --trace)



まず、うちの環境ではSSHのポートを22番から変更しているため
接続できていないということ・・・。
なので再度、Gitlabの設定(gitlab.yml)を変更しておきます。
# vi config/gitlab.yml
~~~~
git_host:
  admin_uri: gitolite@localhost:gitolite-admin
  base_path: /pathto/repositories/
  host: example.com #ホスト名もちゃんと設定しておく。
  git_user: git
  upload_pack: true
  receive_pack: true
  port: 22 #コメントアウトを外してポート番号を変更。
~~~~
同時に、GitlabユーザのSSH設定のほうも変更しておきます。
# vi /home/gitlab/.ssh/config 
Host    localhost
HostName        localhost
User    gitolite
IdentityFile    ~/.ssh/gitadmin
Port    22
また、.gitolite.rc内のUMASKを書き換えろとのこと。やってなかったので・・・
うちの環境では、/var/lib/gitolite/下にありますのでそれを書き換えます。
# cp /var/lib/gitolite/.gitolite.rc  /var/lib/gitolite/.gitolite.rc.backup
# vi /var/lib/gitolite/.gitolite.rc
$REPO_UMASK = 0007; #0077の箇所を0007にしておく 
これで...もう一度、テスト実行。
# sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
bundle exec rake gitlab:app:status RAILS_ENV=production
Starting diagnostic
config/database.yml............exists
config/gitlab.yml............exists
/var/lib/gitolite/repositories/............exists
/var/lib/gitolite/repositories/ is writable?............YES
remote: Counting objects: 31, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 31 (delta 7), reused 0 (delta 0)
Receiving objects: 100% (31/31), 3.10 KiB, done.
Resolving deltas: 100% (7/7), done.
Can clone gitolite-admin?............YES
UMASK for .gitolite.rc is 0007? ............YES


OKですね〜。

データベースに初期データを登録します。
# sudo -u gitlab bundle exec rake db:setup RAILS_ENV=production
# sudo -u gitlab bundle exec rake db:seed_fu RAILS_ENV=production
このとき、初期ユーザ名とパスワードが表示されるのでメモを。
さて、デーモン起動させてみましょう。
#  sudo -u gitlab bundle exec rails s -e production -d
=> Booting Thin
=> Rails 3.2.5 application starting in production on http://0.0.0.0:3000
お。OKっぽいですねw 続いて...Resqueプロセスを起動させてみます。 
# ./resque.sh
では今後は、Unicornで。
# sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb 
# sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
次にGitlabをサブディレクトリ下で動作させるために
設定ファイル(config.ru)を変更します。

(config.ruを開いて、run ~~ の一行を次のように囲みます。)
# vi config.ru 
require ::File.expand_path('../config/environment',  __FILE__)
map ActionController::Base.config.relative_url_root || "/" do
        run Gitlab::Application
end
また、バックエンドとなるUnicornをサービスさせるポートを定義するために
Unicornのスクリプトファイル(unicorn.rb)を変更します。
# vi config/unicorn.rb 
~~~~
#listen "#{app_dir}/tmp/sockets/gitlab.socket" #コメントアウトする
listen 8081 #Unicornをサービスさせるポート番号を指定
~~~~
さらに、すでに稼働させているnginxの設定ファイル(nginx.conf)に
Gitlabのためのリバースプロキシ設定を追加しておきます。

$ su

# vi /etc/nginx/nginx.conf

upstream gitlab {
    server 127.0.0.0:8081; #Unicornのポート番号を指定
}
~~~~
server {
    ~~~~
    location ~ ^/gitlab/(.*) { #Gitlabを配置するディレクトリを指定
        proxy_redirect off;
        proxy_pass http://gitlab;
        break;
    }
}

nginxの実行アカウントをgitlabグループに所属させておきましょう。

# usermod -G gitlab nginx

そして、nginxを再起動。
# service nginx restart

さらにgitlabをServiceにするために
/etc/init.d/gitlab を作成しておきましょう。

(Source: https://github.com/gitlabhq/gitlabhq/blob/stable/doc/installation.md)
# vi /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 --path /gitlab" #Gitlabを配置するディレクトリを指定
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
スクリプトのパーミッションを変更。
# chmod +x /etc/init.d/gitlab
自動起動を有効にしておきます。
# chkconfig --add gitlab
# chkconfig gitlab on
あとはサービスを実行するだけ。
# service gitlab start
これで・・・
http://example.com/gitlab/ にアクセスすると・・・


うまく行ったようです♪

追記: このままではpublic/uploads/下にアップロードするファイルに
アクセスすることができませんでした。
ということで・・・nginxの設定ファイル(nginx.conf)に修正を...。
# vi /etc/nginx/nginx.conf 
~~~~
        location ~ ^/gitlab/uploads/(.*) {
                #静的ファイル
                rewrite ^/gitlab/uploads/(.*) /$1;
                root    /home/gitlab/gitlab/public/uploads/;
                index   index.html;
                ssi     off;
                break;
        }
        location ~ ^/gitlab/(.*) {
                proxy_pass      http://gitlab;
                break;
        }
~~~~
さらに、/home/gitlab/ のパーミッションに
# chmod g+x /home/gitlab/
しておく。以上です。

これで静的ファイルはnginxから直接レスポンスされるようになります。
たぶんこんな感じでOKなはずです。たぶん(汗;←

2012/06/24

Git+Gitoliteを使い始める

実は今までまともにGitを使ったことが無い(git cloneくらいしかないw)ので
この機会に実際にGitを使い初めて学んでみることにしました。
慣れてきたらSVNから徐々に移行していきたいつもりです。

尚、この記事は私のメモが目的であり、
申し訳ありませんがあまり役に立たないかもしれません。ご了承ください(汗;)
参考になる情報をお探しの方は、この記事の最後にある参考ページを。

さて、まずは...手始めにサーバ上でGitをインストールします。
server: $ sudo yum install git
さらに、リポジトリとユーザ管理を容易にしてくれる gitoliteをインストール。
server: $ sudo yum install gitolite
このとき、インストールと同時に、gitoliteというユーザがサーバ上に追加されます。

さて..gitoliteはユーザを認証鍵で識別するため、そのための鍵を作る必要があります。
(参照:この仕組みについては、gitoliteはどうやってユーザを判別しているか - SELECT * FROM life;が参考になりました。)
ですので、クライアントとなるPCで・・・
まず、gitolite用にいつもとは別の鍵を作成します。
client: $ ssh-keygen -t rsa 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hoge/.ssh/id_rsa): ~/.ssh/gitoliteEnter passphrase (empty for no passphrase): #空でEnter
Enter same passphrase again: #空でEnter
Your identification has been saved in /home/hoge/.ssh/gitolite.
Your public key has been saved in /home/hoge/.ssh/gitolite.pub.
The key fingerprint is:
〜〜〜〜
The key's randomart image is:
〜〜〜〜
これで、"gitolite"と"gitolite.pub"というファイルが、~/.ssh/下に生成されます。

さらにこの鍵を使うために、~/.ssh/configへ記述をしておきます。
client: $ vi ~/.ssh/config 
HOST git.example        USER            gitolite
        HOSTNAME        example.com        PORT            22        IDENTITYFILE    ~/.ssh/gitolite
こんな感じで。git.exampleは識別名なので何でも構いません。(あとで利用)
HOSTNAMEとPORTは、それぞれサーバのアドレスとSSHポート番号を指定します。

あとは、gitolite.pubをサーバの/tmp/あたりに転送します。(SCPか何かで適当に。)
client: $ scp ~/.ssh/gitolite.pub hoge@example.com:/tmp/gitolite.pub
今度はサーバ側で、アップロードしたファイルのパーミッションを変更。
server: # chmod a+r /tmp/gitolite.pub
さらに、gitoliteとしてログインしなおし...gitoliteの設定を行ないます。
server: $ su - gitolite 
server: $ gl-setup /tmp/gitolite.pub
The default settings in the rc file (/var/lib/gitolite/.gitolite.rc) are fine for most
people but if you wish to make any changes, you can do so now.
hit enter... #Enterキーで続行。#続けて.gitolite.rcがエディタで開きますが、気にせずそのまま閉じます。creating gitolite-admin...
Initialized empty Git repository in /var/lib/gitolite/repositories/gitolite-admin.git/
creating testing...
Initialized empty Git repository in /var/lib/gitolite/repositories/testing.git/
[master (root-commit) 〜] gl-setup /tmp/gitolite.pub 2 files changed, 8 insertions(+), 0 deletions(-)
 create mode 100644 conf/gitolite.conf
 create mode 100644 keydir/gitolite.pub 
server : $ exit
このとき、サーバ上に、"testing"というサンプルのリポジトリと、
"gitolite-admin"というリポジトリが自動生成されます。

このgitolite-admin リポジトリは、Gitolite管理用リポジトリとなります。
なぜかというと・・・・ここに対して設定ファイルをコミットしていくことで
Gitoliteの設定変更(Gitリポジトリの生成といった管理操作も!)ができるという仕組みなのです。面白いですね!!

さて今度はクライアント側から、この"gitolite-admin"リポジトリをgit cloneしてみます。
適当なディレクトリへcloneします。これでcloneされたローカルリポジトリが生成されるわけですね。
(アドレスは実際のサーバアドレスは指定しません。
git.exampleとしているように、先程設定した識別名を指定します。)
client: $ cd ~
client: $ git clone ssh://git.example/gitolite-admin
git cloneが成功しました。
試しに新しいリポジトリでも作ってみます...(ここではrepo1というリポジトリを作ってみる。)
cloneされたディレクトリ下にある conf/gitlite.conf をエディタで開き、記述を追加します。
client: $ cd gitolite-admin/
client: $ vi conf/gitolite.conf  
repo    gitolite-admin
        RW+     =   gitolite
repo    testing
        RW+     =   @all
#以下...追加
repo    repo1
        RW+     =   @all
そして...ローカルリポジトリへのコミット
client: $ git add .
client: $ git commit 
エディタが起動して、コミットログを編集する画面になるので、以下のように先頭の#を削除して終了。
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
 On branch master
 Changes to be committed:
   (use "git reset HEAD <file>..." to unstage)
        modified:   conf/gitolite.conf 
ローカルリポジトリへのコミットが実行されます。 
[master 21e408a]  On branch master  Changes to be committed:    (use "git reset HEAD <file>..." to unstage)
 1 files changed, 2 insertions(+), 0 deletions(-)
最後にローカルリポジトリをサーバへプッシュします。
client: $ git push
サーバ側で作業することなくこれだけでリポジトリが追加されます。
なんだこれは便利www

あとは他のユーザをgitoliteに追加するとか、
RedmineにGitリポジトリを設定するとかあるのですが、それはまた (^^)/♪



参考にさせていただいたサイト(感謝♪!):

2012/04/30

nginxをリバースプロキシとしてSubsonicを構築する

SubsonicをVPS上で稼働させることにしました。
そのままポート割り当てて公開してもいいのですが、
折角ですからSubsonicのオレオレ証明書ではなく、
nginxで利用している正規のSSL証明書を使うために、
nginxによるリバースプロキシを通してみることに。

Subsonicに一つのポートを割り当てて単独で動作させるのではなく、
nginxで動作しているサーバの"subsonic/"ディレクトリ下を割り当てることにします。

Java環境は導入済なので・・・

まずは...Subsonicをrpmパッケージでインストールします。
(2012/04/30現在の最新は、subsonic-4.6)

http://www.subsonic.org/pages/download.jsp
$ cd ~
$ wget http://downloads.sourceforge.net/project/subsonic/subsonic/4.6/subsonic-4.6.rpm
$ sudo rpm -ivh subsonic-4.6.rpm
これだけで自動的にSubsonicが動作しはじめます。お手軽です。


自動エンコードに必要なライブラリ類をyumでインストール。

$ sudo yum -y install lame flac faad2 vorbis-tools ffmpeg
(参照: http://sourceforge.net/apps/mediawiki/subsonic/index.php?title=Transcoders


次に、Subsonicの設定
を変更します。(/etc/sysconfig/subsonic)
$ sudo vi /etc/sysconfig/subsonic 
SUBSONIC_ARGS="--port=8100 --max-memory=100 --context-path=/subsonic"
こんな感じで、Subsonicのポート番号と、パスを指定しておきます。


さらに...nginxの設定に、Subsonicへのリバースプロキシを追加。

$ sudo vi /etc/nginx/nginx.conf

upstream Subsonic.backend {
server 127.0.0.1:8081;
}
server {
        listen       80;
        〜〜〜
        location ~ ^/subsonic(\/|).* {
                if ($server_port = 80){
                        rewrite (.*) https://$http_host$request_uri last;
                        break;
                }
                proxy_pass      http://Subsonic.backend;
                proxy_redirect  http://$http_host/subsonic/  https://$http_host/subsonic/;
                break;

        }
}
基本的には、proxy_passでSubsonicのアドレスを指定するだけなのでシンプルですね。
ここでは、HTTPでアクセスしたときにHTTPSへリダイレクトする記述と、
proxy_directを使って、Subsonicがリダイレクトさせようとしたときに
HTTPSへリダイレクトされるように記述をしておきました。


あとは、Subsonicとnginxの設定を反映させて・・・

$ sudo service subsonic restart
$ sudo service nginx restart

ブラウザからアクセスしてみます。
(http//〜〜〜/subsonic/)


とりあえず、うまく動作しているようです。


参考にさせていただきました。(感謝♪)

2012/02/22

nginxをEPELから導入して最新版上書き&モジュール導入

nginxをEPELから導入したいと思います。
最新版は1.0.12ですが、EPELには最新版がありません。
また、nginxのモジュールの組み込みにはビルドしなおす必要があります。

だったら完全にソースから...となるのですが、それはそれでinit.dの準備などなど面倒です。
そのため、EPELからnginx-0.8.55-1を取得して...これを基に、
nginx-1.0.12と、モジュール ngx_cache_purge-1.5 を適用します。

今回は...
http://sakuratan.biz/archives/4582 と
http://sakura.off-soft.net/centos/apache-nginx-1-reverse-proxy-install.html

を参考にさせていだきます。感謝♪
(参考というか大半写しですね...自分用のメモを兼ねているのでお許しを m(_ _)m
以下の内容を参考にされる方は、そのまえに上記のサイトをじっくりお読みください。

前準備にパッケージをインストール。
$ sudo yum --enablerepo=epel install make automake gcc gcc-c++ rpm-build spawn-fcgi pcre-devel zlib-devel openssl-devel libxslt-devel GeoIP-devel gd-devel

次にEPELからnginxのSource RPMをダウンロード。
nginxの最新版は1.0.12なわけですが、ここにあるのは0.8.55-1。
http://dl.fedoraproject.org/pub/epel/5/SRPMS/repoview/nginx.html
$ wget http://dl.fedoraproject.org/pub/epel/5/SRPMS/nginx-0.8.55-1.el5.src.rpm
インストール。
$ sudo rpm -ivh nginx-0.8.55-1.el5.src.rpm
警告: グループ mockbuild は存在しません - root を使用します

とりあえず、このエラーは無視で構わないそうです。

次は、このインストールしたnginxに対して
最新版のnginxとモジュールで上書きをします。


まずはインストールしたソースディレクトリへ移動して...
$ su
# cd /usr/src/redhat/SOURCES
nginxの最新版(1.0.12)のパッケージをダウンロード。
# wget http://nginx.org/download/nginx-1.0.12.tar.gz
次に、ngx_cache_purge モジュールの最新版(1.5)のパッケージをダウンロード。
# wget http://labs.frickle.com/files/ngx_cache_purge-1.5.tar.gz
さらに、SPECファイルを編集します。
SPECディレクトリへ移動して、nginx.specをエディタで開きます。

# cd /usr/src/redhat/SPECS
# cp nginx.spec nginx.spec.org
# vi nginx.spec
11行目付近:バージョン番号を変更。
Version:        1.0.12

42行目付近:モジュールのパッケージファイル名を追加。
Source10:   ngx_cache_purge-1.5.tar.gz

51行目付近:パッチのための記述をコメントアウト。
#Patch0:     nginx-auto-cc-gcc.patch

60行目付近:同様にコメントアウト。
#%patch0 -p0

61行目付近:ビルド前処理としてモジュールパッケージを展開する記述を追加。
%setup -T -D -a 10

69行目付近:文字コードを設定する記述を追加しておきます。
export LANG='ja_JP.UTF-8'

106行目付近:モジュールを追加しているため、ここの記述も書き換え。
    --with-cc-opt="%{optflags} $(pcre-config --cflags)" \
    --with-cc-opt="%{optflags} $(pcre-config --cflags)" \
    --add-module=%{_builddir}/nginx-%{version}/ngx_cache_purge-1.5
make %{?_smp_mflags}

110行目付近:モジュールのドキュメントファイルの名前を変更する記述を追加。
mv ngx_cache_purge-1.5/CHANGES ngx_cache_purge-1.5/CHANGES.ngx_cache_purge
mv ngx_cache_purge-1.5/README.md ngx_cache_purge-1.5/README.ngx_cache_purge

168行目付近:モジュールのドキュメントファイルをnginxに追加。
%doc ngx_cache_purge-1.5/CHANGES.ngx_cache_purge ngx_cache_purge-1.5/README.ngx_cache_purge

これで上書きします。

あとは・・・ビルド。
# rpmbuild -bb nginx.spec
〜〜〜
書き込み完了: /usr/src/redhat/RPMS/x86_64/nginx-1.0.12-1.x86_64.rpm
書き込み完了: /usr/src/redhat/RPMS/x86_64/nginx-debuginfo-1.0.12-1.x86_64.rpm
実行中(%clean): /bin/sh -e /var/tmp/rpm-tmp.56019
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd nginx-1.0.12
+ rm -rf /var/tmp/nginx-1.0.12-1-root-root
+ exit 0

ビルドが終わったようです。
あとは、今できあがったパッケージをインストールします。
# cd ../RPMS/x86_64/
# rpm -Uvh nginx-1.0.12-1.x86_64.rpm

これで完了ですね。

pacoでパッケージインストール管理

paco(pacKAGE oRGANIZER)を使うと、
Linuxでmake installによってソースからパッケージをインストールする際に
インストールしたソフトウェアを管理することができるそうです。
基本的にyumやaptitudeを使っているので...知りませんでした・・・。

ということで、yumから、pacoをインストールします。

$ sudo yum install paco
Installed:
  paco.i386 0:2.0.9-7.el5               paco.x86_64 0:2.0.9-7.el5              
OKですね。

実際の使い方は...
パッケージのアーカイブを展開してconfigure、makeをした後、
"sudo make install"をする際に、
$ sudo paco -D make install
のようにpacoを通して行えばいいようです。
("-D"オプションは、pacoで管理する際のパッケージ名に、
現在のカレントディレクトリ名を使うことを意味する。)

詳しくは...
make install"したソフトウェアを管理できる超便利ツール「Paco」 - RX-7乗りの適当な日々
に書いてくださっているので、そちらを。(感謝♪!)


2012/01/15

USVNにTracインストール機能を無理やりつけてみる


結局、Subversionのウェブ管理インターフェースは、
方針を変え、USVN(http://www.usvn.info/)を利用することにしました。
(インストールしたバージョンは最新版の1.0.5。)
私以外...複数人でのソフトウェア開発に利用したいと考えているので、
SVNについてもWebブラウザから利用できるインターフェースは必須なのです。

で・・・今回は、そこにTracも使いたいというお話です。
(SubminはTracとの連携に対応していますが、
USVNはTracに関しては特に連携などは一切考えられていないようです。)


結果から出すとこんな感じになりました。
プロジェクト管理画面のアクション欄に、ボタンが一つ増えています。
(プラスマークのボタンを押すと、Tracプロジェクトを作成。
 既にプロジェクトがある場合は、フォルダアイコンが表示されます。)
USVN 1.0.5 (なんちゃってTracインストール機能追加版w)
Tracは、インタアクトによる日本語版を導入させていただきました。
(執筆時点の最新版は、Trac-0.12.2.ja1)
http://www.i-act.co.jp/project/products/products.html
$ wget http://www.i-act.co.jp/project/products/downloads/Trac-0.12.2.ja1.zip
$ unzip Trac-0.12.2.ja1.zip
$ cd Trac-0.12.2.ja1
$ python ./setup.py install
こういう変更をした...という備忘録のために...
以下の通り、記録しておきます。
(今回は、記録が一番の目的のため、詳しいコメントなどは記載していません m(__)m)


念の為、言い訳と前置きを(><;)
  • 今回、思いっきり(<適当に手当り次第に>)、USVNのPHPスクリプトを弄っています。
    (USVNのバージョン:1.0.5)
  • 環境:
    • USVNのパス: /var/usvn
    • Subversionリポジトリのパス: /var/svn
  • 弄るにあたって、APIドキュメントなど資料はサーバが落ちているのかアクセスできず、情報を得られませんでした。
  • 幸い、モデル化がきちんと行われており構造がわかりやすく、拡張を考えた作りになっていました。
  • 但し、PHPは未だ...まともにコードを書いたことがなく、
    当然...使われているフレームワーク(有名なZend...)も殆ど知識がなく、
    さらに悪いことに...作業を急いでいるために、(おっと...言い訳ばっかりだwww)
    今回はじっくり時間をかけてソースコードを読んで...とは行けず
    ...ある意味"やっつけ"です。
  • モデルに...全然なってません。パラメータ...ベタ打ちラララ♪ですww(笑)
  • 文字列のローカライズ...やってません(といってもリンクくらいだけど)
  • 以上の点の理由もふくめて、このページのコードの動作や、記載内容を実行した結果について、
    一切保証できません。(責任も負えません。あしからず。)
  • そういうわけで、恐らく・・・随分ひどい書き換えになっていますww今回については...どうか目をつぶってやってください(^^;)) (←←
    (また機会があれば...もっとちゃんとTracと連携する機能もつけてみたいな...と思ったりしてます。(お?←)

では...USVNのプロジェクト管理画面に
Tracプロジェクトを作成するためのリンクを設けていきます。

<USVNのディレクトリ>/library/USVN/Project.php:
getTracPath、getTracURL、installTracというメソッドを追加しています。

        public static function getTracPath($project_name)
        {
                $tracdir = Zend_Registry::get('config')->trac->path.DIRECTORY_SEPARATOR.$project_name;
                if(is_dir($tracdir)){
                        return $tracdir;
                }else{
                        return NULL;
                }
        }

        public static function getTracURL($project_name)
        {
                $tracdir = Zend_Registry::get('config')->trac->path.DIRECTORY_SEPARATOR.$project_name;
                if(is_dir($tracdir)){
                        return Zend_Registry::get('config')->trac->url.$project_name;
                }else{
                        return NULL;
                }
        }

        public static function installTrac($project_name)
        {
                $table = new USVN_Db_Table_Projects();
                $project = $table->fetchRow(array('projects_name = ?' => $project_name));
                if ($project === null) {
                        throw new USVN_Exception(T_("Project %s doesn't exist."), $project_name);
                }
                if (!is_null(USVN_Project::getTracPath($project_name))) {
                        throw new USVN_Exception(T_("Trac was already installed in project %s ."), $project_name);
                }
                $arg = "";
                $res = 0;
                $cmd = 'sudo ' . Zend_Registry::get('config')->trac->tracadminscriptpath . " '".$project_name."'";
                exec($cmd, $arg, $res);
                return $res;
        }

<USVNのディレクトリ>/app/controllers/ProjectadminController.php:
installtracActionメソッドを追加しています。

        public function installtracAction()
        {
                USVN_Project::installTrac(str_replace(USVN_URL_SEP, '/', $this->getRequest()->getParam('name')));
                $this->_redirect("/admin/project/");
        }

<USVNのディレクトリ>/app/views/scripts/projectadmin/index.phtml:
プロジェクト管理画面に、Tracのインストールリンクを追加します。(尚、インストール済みなら、Tracを表示させるリンクに切り替わります。)
<?= $this->ACLLink($project->name) ?>
という記述がありますので、これの下あたりにでも、
<?= $this->tracLink('name', $project->name, $tracLinkText) ?>
を記述します。

<USVNのディレクトリ>/app/helpers/TracLink.php:
リンクを出力するコードです。
<?php
class USVN_View_Helper_TracLink {
    public function tracLink($param, $name, $confirmText)
    {
        $tracURL = USVN_Project::getTracURL($name);
        $front = Zend_Controller_Front::getInstance();
        $view = Zend_Controller_Action_HelperBroker::getExistingHelper('viewRenderer')->view;
        if(is_null($tracURL)){
                $confirmText = "Do you really install the Trac for this project?";
                $img = $view->img("add.png", 'Install Trac');
                return $view->urlConfirm(array('action' => 'installTrac', $param => $name),  $img, sprintf($confirmText, $name));
        }else{
                $img = $view->img("folder.png", "Access to trac.");
                return '<a href="' . $tracURL. '">' . $img .'</a>';
}
    }
}
<USVNのディレクトリ>/config/config.ini:
一応、Tracのパス、URLなどの設定をconfig.iniで行うようにしています。
trac.path = "/var/trac/"
trac.url = "http://example.com/trac/"
trac.tracadminscriptpath = "/var/usvn/trac-project-make.sh"
書き換えはこんなところです。
(1画面にボタンをつけたくらいで、何か他に画面をつけたわけでもないので・・・少ないです。)

ところで・・・trac-adminでプロジェクトを作成するのって、
sudoしないといけないんですね(汗;)

Apacheの実行権限だけで行けるんじゃないかと思ってたのですが、ダメでしたw
...ということで・・・
Apacheを動作させているユーザアカウントから
sudoをできるようにしてみたいと思います。
つまり、PHPスクリプトなどからsudoを実行できるようにします。
(もちろん、sudoをApacheから実行できることについて、セキュリティ上の懸念は大いにあります。
今回、最低限対策はしますが、sudoをできてしまうことは当然、少なからず安全性が下がります
実際に同じようなことをされる場合は、十分理解している場合にのみ行なってください。
もちろん、私は一切の責任を負えません。あしからず。)


ということで・・・Tracプロジェクトを作成するための
シェルスクリプトを作成します。
(これをUSVNからsudoをつけて実行させます。USVNと同じディレクトリに保存しておきます。)
# cd /var/usvn/
# touch trac-project-make.sh
# vi trac-project-make.sh   
#! /bin/sh
PROJECTNAME=`echo $1 | sed -e "s/[^0-9a-zA-Z\-\_]*//g"`
/usr/local/bin/trac-admin /var/trac/$PROJECTNAME initenv $PROJECTNAME sqlite:db/trac.db svn /var/svn/$PROJECTNAME
chown apache:apache /var/trac/$PROJECTNAME/ -R 
(1行目はシェルのパス、2行目がパラメータの処理、
3行目でtrac-adminを実行してプロジェクトを作り、
4行目でそのパーミッションを調整しています。)


作成したスクリプトは所有者を変更してApache用のユーザに。実行権限もつけます。
# chown apache:apache trac-project-make.sh
# chmod apache u+x
 次にvisudoコマンドを実行して、sudoを実行できるユーザの定義を追加します。
# visudo
具体的には末尾に以下のような行を追加します:

apache ALL = NOPASSWD: /var/usvn/trac-project-make.sh
Defaults:apache !requiretty
(こうすることで、端末を持たないApache向けユーザ"apache"にパスワード無しでのsudoを許すものの、
先程作成したスクリプト以外にはsudoが使えないようになります。これは最低限の安全策です。)

Tracの認証は、Apacheへの設定ファイルによりこんな感じに。
(ちょうど、USVNがhtpasswdファイルを作ってくれますのでそれを利用。)
<Location /trac>
   SetHandler mod_python
   PythonHandler trac.web.modpython_frontend
   PythonOption TracEnvParentDir /***/
   SetEnv PYTHON_EGG_CACHE /var/www/.egg-cache
</Location>
<locationMatch "/[[:alnum:]]+/login">
   AuthType Basic
   AuthName "Trac authorization."
   AuthUserFile /****/.htpasswd
   Require valid-user
</locationMatch>
以上となります。

追記: USVNでsvnコマンドのパスが通っていない問題は
(CentOSの場合) /etc/sysconfig/httpd に
PATHを記述する。http://d.hatena.ne.jp/masahi6/20090720/1248081907

2012/01/08

さくらのVPSへSubversion1.7.2+Submin2.0.2を導入


さくらのVPS(CentOS 5.7 final)に、
Subversion1.7.2と、Submin2.0.2を導入してみました。

■この記事の内容は、Masanoriのメモ帳へまとめました:
さくらインターネット/さくらのVPSのメモ - Masanoriのメモ帳

以下は右往左往しながら試した結果です(^^;)
ライブラリなどのパスはそれぞれ環境によって異なる場合もあるかと思いますので
参考程度にしてください。
また、細かいところ、もっと色々つまづいたのですが...それは端折ってます((>ω<;)

[補足]
  • Apache: 2.2.21
  • さくらのVPSにはデフォルトでPython 2.4がインストールされていますが、
    これでは古いので、こちらのとおり Python 2.7をソースからビルドし、
    /usr/local/bin/python2.7/ へインストールして共存させている環境です。
まず、前準備としてライブラリをyumでインストール。
$ sudo yum install swig openssl-devel libtool python-devel
SQLiteも入れておく。記事執筆時の最新版です。
$ cd ~
$ wget  http://www.sqlite.org/sqlite-autoconf-3070900.tar.gz
$ tar vxf sqlite-autoconf-3070900.tar.gz
$ cd sqlite-autoconf-3070900
$ ./configure
$ make
$ sudo make install
$ cd ..
Subversionをインストールします。(2011/12/29 現在最新版:1.7.2)
尚、Subversionの古いバージョンがインストールされている場合は、yum eraseで削除しておきます。
$ cd ~
$ wget http://ftp.kddilabs.jp/infosystems/apache/subversion/subversion-1.7.2.tar.bz2
$ tar vxf subversion-1.7.2.tar.bz2
$ cd subversion-1.7.2
$ ./configure  \
> --prefix=/usr/local/svn \
> --with-apxs=/usr/sbin/apxs \
> --with-apr=/usr/bin/apr-1-config \
> --with-apr-util=/usr/bin/apu-1-config \
> --with-neon=/usr/include/neon \
> --with-swig=/usr/bin/swig --without-jdk
$ make
$ make install
次に、SubversionのPython用モジュールをビルドしてインストールします。
$ make swig-py
$ sudo make install-swig-py
これに、Python2.7のライブラリディレクトリ上へシンボリックリンクを張ります。
$ sudo ln -s /usr/local/lib/svn-python /usr/local/lib/python2.7/site-packages/svn-python
$ sudo ln -s /usr/local/lib/svn-python/svn /usr/local/lib/python2.7/site-packages/svn
$ sudo ln -s /usr/local/lib/svn-python/libsvn /usr/local/lib/python2.7/site-packages/libsvn
次に、Subversionの初期設定。
リポジトリ用のディレクトリを作成し、リポジトリを作ります。
ディレクトリの権限の設定も。

$ sudo mkdir /var/svn
$ sudo chown -R apache:apache /var/svn
$ svnadmin create /var/svn/test

次に、WSGI(mod_wsgi)のインストール。
ここではmod_wsgi 3.3をインストールします。
$ cd ~
$ wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
$ tar vxf mod_wsgi-3.3.tar.gz
$ cd mod_wsgi-3.3
$ ./configure --with-apxs=/usr/sbin/apxs --with-python=/usr/local/bin/python2.7
$ make
$ sudo make install

次に、共有ライブラリのパスを設定
$ sudo vi /etc/ld.so.conf
”/usr/local/lib ”を追加しておきます。記述しました。
include ld.so.conf.d/*.conf
/usr/local/lib
次に、mod_pythonのインストール
mod_pythonが既に2.4に向けて入っていたのですが、これをインストールし直します。
$ wget http://archive.apache.org/dist/httpd/modpython/mod_python-3.3.1.tgz
$ tar vxf mod_python-3.3.1.tgz
$ cd mod_python-3.3.1
$ ./configure --with-apxs=/usr/sbin/apxs
$ make
$ sudo make install
そして、Submin2のインストール。最新版のSubmin2.0.2。
$ wget http://supermind.nl/submin/current/submin-2.0.2.tar.gz
$ tar zxvf submin-2.0.2.tar.gz
$ cd submin-2.0.2
$ sudo python setup.py install
続いて、Submin2の初期設定を行ないます
submin2-adminを用いて、/var/lib/subminに対して環境を作成します。
このとき入力するメールアドレスは、パスワードリセットに使うらしく、
後から変更もできるのでとりあえず正しいものを。
$ sudo python submin2-admin /var/lib/submin initenv your@email.address
 Please provide a location for the Subversion repositories. For new Subversion
repositories, the default setting is ok. If the path is not absolute, it will
be relative to the submin environment. If you want to use an existing
repository, please provide the full pathname to the Subversion parent
directory (ie. /var/lib/svn).
Path to the repository? [svn]> /var/svn //Subversionのリポジトリパスを入力
Please provide a location for the git repositories. For new git repositories,
the default setting is ok. If the path is not absolute, it will be relative to
the submin environment. If you want to use an existing repository, please
provide the full pathname to the git parent directory (ie. /var/lib/git).
Path to the git repositories? [git]>
Please provide a location for the parent dir of Trac environments. For a new
installation, the default setting is ok. If you don't want to use Trac, the
default setting is also ok. For existing Trac environments, please provide
the full path.
Path to trac environment? [trac]>
Please provide a hostname that can be used to reach the web interface. This
hostname will be used in communication to the user (a link in email, links
in the web interface).
Hostname? [~~]> example.com //ホスト名を入力
The HTTP path tells Submin where the website is located relative to the root.
This is needed for proper working of the website. Submin will be accesible
from <http base>/submin, Subversion will be accessible from <http base>/svn.
If you use Trac, it will be accessible from <http base>/trac.
HTTP base? [/]>
Apache file created: /var/lib/submin/conf/apache.cgi.conf
   Please include this in your apache config. Also make sure that you have
   the appropriate modules installed and enabled. Depending on your choices,
   these may include: mod_dav_svn, mod_authz_svn, mod_wsgi, mod_dbd,
   mod_authn_dbd and mod_python

Apache file created: /var/lib/submin/conf/apache.wsgi.conf
   Please include this in your apache config. Also make sure that you have
   the appropriate modules installed and enabled. Depending on your  choices,
   these may include: mod_dav_svn, mod_authz_svn, mod_wsgi, mod_dbd,
   mod_authn_dbd and mod_python 

さらに、Apacheの設定(httpd.conf)で...
次のモジュールをLoadModuleさせます:
mod_dav_svn, mod_authz_svn, mod_wsgi, mod_dbd, mod_authn_dbd and mod_python

これで準備完了か・・・ということで、
http://****/submin/submin.cgi へブラウザからアクセス・・・。

が、500エラー
Apacheのエラーログ:

 [Fri Dec 30 01:41:45 2011] [error] [client ***.***.**.**] ImportError: No module named submin.dispatch.cgirunner
 [Fri Dec 30 01:41:45 2011] [error] [client ***.***.**.**] Premature end of script headers: submin.cgi
submin.dispatch.cgirunnerがロードできていないそうで。

確認のため、
/var/lib/submin/cgi-bin/submin.cgi
直接実行すると、ちゃんと実行される。(エラー画面のHTMLが出力される)

となると...Apache側で実行している設定がおかしいのか。
/var/lib/submin/cgi-bin/submin.cgiを書き換える。

# vi /var/lib/submin/cgi-bin/submin.cgi

もう・・・この際なんで適当にw
#!/usr/bin/env python
import sys
print print "Content-Type:text/html; charset=UTF-8\n\n"
print sys.path
sys.exit()
としてしまう。

そして、再度アクセス・・・

['/usr/lib/python2.4/site-packages/Genshi-0.6-py2.4.egg',
 '/usr/lib/python2.4/site-packages/Trac-0.11.6.ja1-py2.4.egg', '/usr/lib64/python24.zip', '/usr/lib64/python2.4', '/usr/lib64/python2.4/plat-linux2',
 '/usr/lib64/python2.4/lib-tk', '/usr/lib64/python2.4/lib-dynload', '/usr/lib64/python2.4/site-packages',
 '/usr/lib64/python2.4/site-packages/Numeric', '/usr/lib64/python2.4/site-packages/gtk-2.0', '/usr/lib/python2.4/site-packages']
・・・はい。そうですか...そうですか...www
python2.4のほうを・・・。PATHも設定したはずなのにね。

というわけで、Apacheが渡す環境変数の値(env)をどうにかすべきなんだろうけども...
(ちなみにApacheは、suからservice httpd startで実行させてる)
...面倒くさいので、とりあえず、
# vi /var/lib/submin/cgi-bin/submin.cgi
submin.cgiを次のように書きかえてしまう。pythonのパスを直接指定。
#!/usr/local/bin/python2.7
from submin.dispatch.cgirunner import run
run() 
そして、http://****/submin/submin.cgi へ再度、ブラウザからアクセス・・・。

・・・お。