FreeNAS 9.3 jail の /etc などをバージョン管理

こういうネタになると美学とか哲学とか書きたい事は色々ありますが、そういうのはひとまず置いときます。

# バージョン管理ツールの選択

実績と安定の Subversion でも良いのですが。jail の中で使用したいので、母艦（prison というのが正式でしょうか？）でも管理できるように、最近流行の分散型バージョン管理システムを使いたい。でも git は好きになれないんですよね、と思って探したら面白いものを発見。今回は fossil というのを使ってみます。wikiとかチケット管理も出来るようですし、システムとしても軽いようですし、 /etc などの管理にはもってこいでしょう。

## fossil の紹介

日本語の紹介記事もいくつか見つかります。

[Fossil を個人的な Wiki ＋プロジェクト管理ツールとして使う - ヤルキデナイズドだった](http://d.hatena.ne.jp/uasi/20110504/1304440859)
[Fossilを使ってみた。 - Block Rockin’ Codes](http://jxck.hatenablog.com/entry/20100714/1279124776)

これで見栄えの調整などが可能なら言う事は無いんですけどね…。誰か作りませんか？この分野はまだまだ始まったばかりのようなので、今なら世界に名を売るチャンスです。

## fossil 案内

[Fossil Quick Start](http://www.raythebm.net/room_fu/fossil/translate/quickstart.wiki.htm)
とても助かります:joy:

# 導入

## 前準備

まずは環境の整備とか、必要なモノのインストールとか。

* jail を作成してIPアドレスを割り当て、bindを設定して名前解決できるようにする。
* 作成した jail 内で fossil をインストール。 ``` pkg install fossil ```  
  その最後のメッセージ:

```
Message from fossil-1.34,2:
After each upgrade do not forget to run the following command:

fossil all rebuild
```

メッセージに従って実行 ``` fossil all rebuild ```してみたが、特に何も無さそう。
何も表示されませんでした。

## 管理用ディレクトリ作成

管理作業の為のディレクトリ ```/root/manage``` と、リポジトリ用ディレクトリ ```/root/repository``` を作成。

```
root@shigure:~ # pwd
/root
root@shigure:~ # mkdir manage
root@shigure:~ # mkdir repository
root@shigure:~ # ls -l
total 46
-rw-r--r--  2 root  wheel   965 Jul 11  2014 .cshrc
-rw-r--r--  1 root  wheel  3072 Mar 23 01:49 .fossil
-rw-------  1 root  wheel   198 Mar 19 02:11 .history
-rw-r--r--  1 root  wheel   148 Jul 11  2014 .k5login
-rw-r--r--  1 root  wheel   296 Jul 11  2014 .login
-rw-r--r--  2 root  wheel   253 Jul 11  2014 .profile
drwxr-xr-x  2 root  wheel     2 Mar 23 23:01 manage
drwxr-xr-x  2 root  wheel     2 Mar 23 23:01 repository
```

## 管理の為の工夫

### 管理対象ファイルはハードリンク

/etc 内の必要ファイルをハードリンク。実験ですので、まずはわかりやすい passwd と group をバージョン管理してみましょう。

```
# pwd
/root/manage
# mkdir etc
# cd etc
# ln /etc/passwd passwd
# ln /etc/group group
# ls -l
total 15
-rw-r--r--  2 root  wheel   463 Apr  3  2015 group
-rw-r--r--  2 root  wheel  1594 Apr  3  2015 passwd
```

まぁ、乱暴なのは承知の上です。特に ```passwd``` と ```group``` なんかは、こんなコトしたら事故が怖い…。くれぐれも、ここで直接編集などしないでください。

### 管理対象ディレクトリは unionfs

ディレクトリのハードリンクは出来ない、というかしちゃいけません。その理由などは調べてみてください。理由はともかく、結論として禁止されているコトをどうやって実現するか。ここで目を付けたのが unionfs でした。

しかしこの unionfs は、jail では実行できません。少なくとも FreeBSD では。

```
# pwd
/root/manage
# mkdir usr_local_etc
# mount -t unionfs /usr/local/etc usr_local_etc
mount_unionfs: /root/manage/usr_local_etc: : Operation not permitted
```

その理由は下記Webページに詳しい。
[jail内でのmountAdd - 英語とプログラミング気まぐれ日記](http://d.hatena.ne.jp/BigFatCat/20110306/1299399174)

```
# lsvfs
Filesystem                              Num  Refs  Flags
-------------------------------- ---------- -----  ---------------
zfs                              0x000000de    21  jail, delegated-administration
nfs                              0x0000003a     0  network
devfs                            0x00000071     7  synthetic, jail
nullfs                           0x00000029     5  loopback, jail
cd9660                           0x000000bd     0  read-only
msdosfs                          0x00000032     0
ufs                              0x00000035     0
unionfs                          0x00000041     0  loopback
procfs                           0x00000002     6  synthetic, jail
tmpfs                            0x00000087     3
```

…というわけで、unionfsにはjailフラグが立っていません。残念。それでどうするか、ですが。私は諦めました:disappointed: 諦めて、母艦で作業します。どなたかいい方法を思い付いたらご教示ください。

```
# pwd
/mnt/tank/jails/《マシン名》/root/manage
# mount -t unionfs /mnt/tank/jails/《マシン名》/usr/local/etc usr_local_etc
# mount | grep unionfs
<above>:/mnt/tank/jails/《マシン名》/usr/local/etc on /mnt/tank/jails/《マシン名》/root/manage/usr_local_etc (unionfs, local)
```

この後、jail の方のshellで様子を確認。

```
# pwd
/root/manage
# ls usr_local_etc/
bash_completion.d       periodic                pkg.conf.sample
man.d                   pkg                     rc.d
pcbsd.conf              pkg.conf                ssl
```

ちょっとイタズラして、確認してみました。

```
# echo test >usr_local_etc/test.txt
# echo test2 >/usr/local/etc/test2.txt
# ls -il /usr/local/etc/test*
13717 -rw-r--r--  1 root  wheel  5 Mar 26 23:07 /usr/local/etc/test.txt
13718 -rw-r--r--  1 root  wheel  6 Mar 26 23:10 /usr/local/etc/test2.txt
# ls -il usr_local_etc/test*
13717 -rw-r--r--  1 root  wheel  5 Mar 26 23:07 usr_local_etc/test.txt
13718 -rw-r--r--  1 root  wheel  6 Mar 26 23:10 usr_local_etc/test2.txt
# rm /usr/local/etc/test.txt
# rm usr_local_etc/test2.txt
# ls usr_local_etc/test*
ls: No match.
# ls /usr/local/etc/test*
ls: No match.
```

いい感じです。

# バージョン管理の開始

ここから先は fossil の使い方になります。

## fossil リポジトリ作成

```
# pwd
/root/repository
# fossil new manage
project-id: e667a0c9bd4515b509fea53de48c0515ae0da652
server-id:  a52d17c28cfb62d2eacbdadbb6226a58986a30df
admin-user: root (initial password is "206891")
```

ここで最初の管理ユーザとそのパスワードが表示されます。最初の管理ユーザとパスワードです。大事なコトなので2回言いました。

## /root/manage のバージョン管理を開始

ごく当たり前の開始手順ですので解説無しで。

```
# fossil open /root/repository/manage
project-name: <unnamed>
repository:   /root/repository/manage
local-root:   /root/manage/
config-db:    /root/.fossil
project-code: e667a0c9bd4515b509fea53de48c0515ae0da652
checkout:     825caca81b522e02516feba0047d203f2a5ea296 2016-03-27 05:21:51 UTC
tags:         trunk
comment:      initial empty check-in (user: root)
check-ins:    1
# fossil add etc usr_local_etc
ADDED  etc/group
ADDED  etc/passwd
ADDED  usr_local_etc/bash_completion.d/_pkg.bash
ADDED  usr_local_etc/man.d/perl5.20.conf
ADDED  usr_local_etc/pcbsd.conf
ADDED  usr_local_etc/periodic/daily/411.pkg-backup
ADDED  usr_local_etc/periodic/daily/490.status-pkg-changes
ADDED  usr_local_etc/periodic/security/410.pkg-audit
ADDED  usr_local_etc/periodic/security/460.pkg-checksum
ADDED  usr_local_etc/periodic/weekly/400.status-pkg
ADDED  usr_local_etc/pkg.conf
ADDED  usr_local_etc/pkg.conf.sample
ADDED  usr_local_etc/pkg/repos/FreeBSD.conf
ADDED  usr_local_etc/rc.d/fossil
ADDED  usr_local_etc/rc.d/git_daemon
ADDED  usr_local_etc/rc.d/pbid
ADDED  usr_local_etc/rc.d/svnserve
ADDED  usr_local_etc/ssl/cert.pem
ADDED  usr_local_etc/ssl/cert.pem.sample
# fossil commit
```

ここでviが起動しますので、コミットメッセージを入力。今回は初めてなので、かなり豪華なメッセージを入力してみました。おわかりと思いますが、実際に入力したのは冒頭の # 無しの部分のみです。

```
initial import
* The directory "usr_local_etc" is "/usr/local/etc"
* The file "etc/group" is a hard-link to "/etc/group"
* The file "etc/passwd" is the same
# Enter a commit message for this check-in. Lines beginning with # are ignored.
#
# user: root
# tags: trunk
#
# ADDED      etc/group
# ADDED      etc/passwd
# ADDED      usr_local_etc/bash_completion.d/_pkg.bash
# ADDED      usr_local_etc/man.d/perl5.20.conf
# ADDED      usr_local_etc/pcbsd.conf
# ADDED      usr_local_etc/periodic/daily/411.pkg-backup
# ADDED      usr_local_etc/periodic/daily/490.status-pkg-changes
# ADDED      usr_local_etc/periodic/security/410.pkg-audit
# ADDED      usr_local_etc/periodic/security/460.pkg-checksum
# ADDED      usr_local_etc/periodic/weekly/400.status-pkg
# ADDED      usr_local_etc/pkg.conf
# ADDED      usr_local_etc/pkg.conf.sample
# ADDED      usr_local_etc/pkg/repos/FreeBSD.conf
# ADDED      usr_local_etc/rc.d/fossil
# ADDED      usr_local_etc/rc.d/git_daemon
# ADDED      usr_local_etc/rc.d/pbid
# ADDED      usr_local_etc/rc.d/svnserve
# ADDED      usr_local_etc/ssl/cert.pem
# ADDED      usr_local_etc/ssl/cert.pem.sample
```

これでvi終了。ものすごく余談ですが、入力内容を保存して終了する為のviコマンドは2つあります。

* :wq
* ZZ

後者は意外と知られていないようなので…

```
./ci-comment-EBE601C17F3D.txt: 28 lines, 1132 characters
./usr_local_etc/ssl/cert.pem contains invalid UTF-8. Use --no-warnings or the "encoding-glob" setting to disable this warning.
Commit anyhow (a=all/c=convert/y/N)? a
```

なんだかよくわからなくてとりあえず a にしてしまいましたが、問題ありましたかねぇ…御存知の方、お手数ですがご指摘いただけると助かります。

## fossil サーバ起動！

```
# pwd
/root
# fossil server repository/manage
Listening for HTTP requests on TCP port 8080
```

ここでプロンプトは帰ってきません。fossilコマンドが実行しっぱなしになります。停止は普通に Ctrl-C です、公式にそうなってるようで。または & でバックグラウンド実行させて、```kill``` で終了でも可。

ブラウザで http://《マシンIPアドレス》:8080/ にアクセスします。
アクセスしましたが…

> Unnamed Fossil Project / Home

…うん。イヤな予感はしたんだ…。プロジェクト名は Unnamed だそうです。ま、後はログインして適当に設定ごちゃごちゃいじれば色々できます。

何よりすげぇなぁと思ったのがログイン画面。通りすがりの為にそこまでするか、というか、そうかこの手があったか、というか。私には衝撃でした。衝撃の画面は、各自お確かめください。

というわけで、プロジェクト名は Admin>Configuration で変更できる模様。素晴らしい事に日本語も半角空白も受け付けてくれます。やった！:+1: