「俺様サーバー構築記 - 基本方針」以来構築を続けてきた俺様パソコン環境ですが、サーバマシンにSubversionをインストールし、クライアントマシンにも svn+ssh でアクセスできるように設定しました。
これらを基盤として、/etc
をバージョン管理します。こういう事は Etckeeper が定番のようで、ArchLinux にも Etckeeper のパッケージがあります。但しこれは Git などの今時の分散バージョン管理ツールだけが対象でした。Subversion は対象外。残念です。
分散バージョン管理は個人的に不勉強ですので、これからの勉強を改めて誓うとして、今回は Subversion を利用したバージョン管理を独自に工夫します。
序
Subversion サーバはデスクトップマシンに立ててあります。
参考文献:俺様サーバー構築記 - Subversionサーバーの構築@デスクトップパソコン
ノートパソコンからは svn+ssh でアクセスできるように準備しています。但し、今回は root ユーザからアクセスするようにするので、後程その設定を追加します。
参考文献:俺様サーバー構築記 - Subversion + Dropbear @ノートパソコン
/etc
バージョン管理については EtcManager という名前のプロジェクトにします。短縮名は etcmgr とし、Subversion プロジェクト等はこの短縮名で用意します。
作業の流れ
- Subversion リポジトリに etcmgr プロジェクトを作成
- client0 マシンから etcmgr にアクセスするユーザとして root_client0 を用意
- etcmgr プロジェクトのセキュリティを設定
- client0 マシンの
/etc
のバージョン管理を開始 - pacman フックを作成
etcmgr
プロジェクトの初期設定
Subversion リポジトリに etcmgr プロジェクトを作成します。
これは最初に1度だけ実施し、以降は各マシン毎のサブフォルダを作成していきます。
# /srv/svn/createprj.sh etcmgr
Edit svnserve.conf and authz in the directory /srv/svn/repo/etcmgr/conf as needed.
The file passwd is in the directory /srv/svn/conf, edit it as needed, too.
他のプロジェクトと違い、セキュリティ設定を厳しくします。基本的には各マシンの root ユーザからアクセスしますが、それ以外のユーザはアクセスを禁止します。読み出しも禁止。
その為の下準備として、 /srv/svn/repo/etcmgr/conf
以下の設定ファイルを操作します。不要なコメントも全部削除しておきます。
# cd /srv/svn/repo/etcmgr/conf
# sed -i -e "s:^\(authz-db[[:space:]]*=\).*$:\1 $(pwd)/authz:" -e "s:^\(password-db[[:space:]]*=\).*$:# \1:" svnserve.conf
# cat >authz <<___
> [aliases]
>
> [groups]
>
> [/]
> * = rw
>
> ___
# rm passwd
結果として、各ファイルの内容は下記の通りとなります。
# cat svnserve.conf
[general]
anon-access = none
auth-access = write
# password-db =
authz-db = /srv/svn/repo/etcmgr/conf/authz
realm = Project etcmgr
# cat authz
[aliases]
[groups]
[/]
* = rw
# cat passwd
cat: passwd: No such file or directory
root_client0 ユーザ
プロジェクト etcmgr にアクセスする Subversion ユーザ名は下記の通りとします。クライアントマシンの root ユーザから下記ユーザ名で Subversion にアクセスする形になります。
- root_<マシン名>
当然サーバにも(そしてクライアントにも)登録されていないユーザとなるので、以前調査したサーバマシンに登録されていないユーザを Subversion アクセスできるように設定する方法を利用します。
なお、下記で、 taro はサーバ側に Dropbear アクセスできる一般ユーザであり、サーバの IP アドレスは 10.0.1.121 です。
# cd
# mkdir .ssh
# cd .ssh
# dropbearkey -t ecdsa -s 256 -f id_dropbear_svn | tee >(tail -n+2 | head -n1 >authorized_keys_svn)
Generating 256 bit ecdsa key, this may take a while...
Public key portion is:
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBB13AN+v0oUvaeS23hsP4Ak8nzn8GVqMk+3SEPed1bzd2YRAKKNbOGRtVtuCcQnkILI5WWqMTzB03JRUomhZxVY= root@client0
Fingerprint: sha1!! 8c:3f:25:d6:d0:89:28:3a:74:d6:a6:6c:ee:9e:e5:0b:5b:0c:99:d6
# su taro
$ cat authorized_keys_svn | dbclient -p 60022 10.0.1.121 "mkdir /tmp/root_key; cat >/tmp/root_key/authorized_keys_svn"
$ exit
exit
# cd /tmp/root_key
# source /etc/subversion/basic.conf
# SVN_USER=$(cat authorized_keys_svn | cut -d" " -f3 | tr @ _)
# cat >>$SVN_HOME/.ssh/authorized_keys <<___
> command="svnserve -tr $SVN_REPO --tunnel-user=$SVN_USER",no-port-forwarding,no-agent-forwarding,no-pty $(cat authorized_keys_svn)
> ___
# cd
# rm -r /tmp/root_key
ちなみに authorized_keys
へ追加された行は下記のようになります。参考まで。
# tail -n1 $SVN_HOME/.ssh/authorized_keys
command="svnserve -tr /srv/svn/repo --tunnel-user=root_client0",no-port-forwarding,no-agent-forwarding,no-pty ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBB13AN+v0oUvaeS23hsP4Ak8nzn8GVqMk+3SEPed1bzd2YRAKKNbOGRtVtuCcQnkILI5WWqMTzB03JRUomhZxVY= root@client0
Subversion のセキュリティ
client0 マシンのディレクトリは root_client0 ユーザだけが読み書き出来るようにします。まぁ、気休めですね。/etc
ディレクトリは、読むだけなら誰でも読めますし。マシン外から読めないようにしておくのは正しいですが。
# cat >>$SVN_REPO/etcmgr/conf/authz <<___
> [/client0]
> root_client0 = rw
> * =
>
> ___
トンネルスキーム設定
/root/.subversion
を svn コマンドに作成させてから config ファイルを修正します。
# svn --version >/dev/null
# sed -i -e"/\[tunnels\]/a ssh = dbclient -l svn -i $HOME/.ssh/id_dropbear_svn -p 60022" $HOME/.subversion/config
/etc
管理開始
(2019/08/24 修正ここから)
.pwd.lock
と .updated
は、バージョン管理は不要です。どうも更新時に設定されるロックファイル等で、特に後者は ArchLinux に特有のファイルっぽい。という訳で無視設定にします。
参考文献1: Re: What is /etc/.pwd.lock for ? - debian-user Jul 2005 by thread
参考文献2: karol 2014-07-31 00:12:19 - [SOLVED] /etc/.updated? - System Administration - ArchLinux Forums
が、普通に svn propset svn:ignore
すると .updated
はエラーになります。理由がよくわかりません。そのため一捻りした結果が下記になります。
# svn mkdir --parents svn+ssh://10.0.1.121/etcmgr/$(hostname)/etc -m "Prepare the target directory /etc"
Host '10.0.1.121' is not in the trusted hosts file.
(ecdsa-sha2-nistp256 fingerprint sha1!! c9:c0:6f:79:53:a6:17:b2:27:82:ee:a3:c9:a0:92:23:db:0d:fc:82)
Do you want to continue connecting? (y/n) y
Committing transaction...
リビジョン 1 をコミットしました。
# svn co svn+ssh://10.0.1.121/etcmgr/$(hostname)/etc /etc
リビジョン 1 をチェックアウトしました。
# svn propset svn:ignore -F - /etc <<___
> .pwd.lock
> .updated
> ___
属性 'svn:ignore' を '/etc' に設定しました
# svn add /etc/*
〈省略〉
A /etc/zfs/zpool.d/iostat
A /etc/zfs/zpool.d/test_progress
A /etc/zfs/zpool.d/enc
# svn ci /etc -m "initial commit"
〈省略〉
追加しています etc/zfs/zpool.d/vendor
追加しています etc/zfs/zpool.d/w_proc
追加しています etc/zfs/zpool.d/w_ucor
ファイルのデータを送信しています ..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................done
Committing transaction...
リビジョン 2 をコミットしました。
(2019/08/24 修正ここまで)
Subversion リポジトリのセキュリティ設定により、異なるユーザ taro ではファイル一覧を見る事も出来ません。
$ whoami
taro
$ svn list svn+ssh://10.0.1.121/etcmgr | wc -l
0
$ svn list svn+ssh://10.0.1.121/etcmgr/$(hostname)
svn: E170001: Authorization failed
pacman フック
pacman を使った時に、自動的に commit されるようにします。ただ、これは良し悪しだと考えています。pacman -Syu
の時など自動的に commit してくれるのは助かりますが、新しいパッケージをインストールした時に自動 commit されると、メッセージに覚書を残せなくなります。そこの所を良く検討して判断して下さい。その辺の制御は、下記の etcmgr-pre-install.hook
における [Trigger] Operation の設定である程度は制御できると思います。
(2019/08/10 追加ここから)
[Trigger] Operation = Update だけにすれば良いようです。
(2019/08/10 追加ここまで)
自動 commit する場合、その為のシェルスクリプトをクライアントマシンに作成して /opt/etcmgr/bin
に置きます。
(2019/09/22 修正ここから)
GnuPG によるパッケージの暗号化がどうとかで、 /etc/pacman.d/gnupg
ディレクトリに UNIX ソケットが生成される事があるようです。 Subversion はこれを処理できないのでエラーが発生します。
svn: E200007: パス '/etc/pacman.d/gnupg/S.gpg-agent' のノード種別はサポートされていません
svn: E200007: Unsupported node kind for path '/etc/pacman.d/gnupg/S.gpg-agent'
これを避ける為に、管理対象ファイル追加の処理においてフィルタを設定します。
#!/bin/bash
ETC_DIR="$1"
if [[ -z "$ETC_DIR" ]]; then
echo "$(basename $0) <dirname>"
exit 1
fi
exec &> >(tee >(systemd-cat -t etcmgr))
cd "$ETC_DIR"
SVN_STATUS=$(svn st)
if [[ -z "$SVN_STATUS" ]]; then exit; fi
echo "auto commit $ETC_DIR when done pacman command${2+: }$2"
echo "$SVN_STATUS" | grep "^?" | cut -b9- | xargs -I{} find {} -type f -or -type d -or -type l | xargs -r svn add
echo "$SVN_STATUS" | grep "^!" | cut -b9- | xargs -r svn rm
svn ci -m "auto commit when done pacman command${2+: }$2"
(2019/09/22 修正ここまで)
これ、 svn+ssh://10.0.1.121/etcmgr/autocommit.sh
として Subversion に登録してしまった方が良いかも知れません…
そして /opt/etcmgr/bin/autocommit.sh
が出来たら、pacman のフックを作成します。
参考文献:2.2 フック - 2 設定 - pacman - ArchWiki
(2019/09/27 修正ここから)
Operation = Install
と Operation = Remove
はコメントアウトして、Upgrade の際だけ自動 commit されるようにします。
パッケージのインストールや削除の際には手動で svn commit
しましょう。適切なコメントを残す必要もありますので。
更に、pacman は事前と事後にフックを設定できるようです。念の為に両方用意した方が良いでしょう。
# etcmgr pre-install hook
[Trigger]
# Operation = Install
Operation = Upgrade
# Operation = Remove
Type = File
Target = etc/*
[Action]
Description = etcmgr: pre-transaction commit
When = PreTransaction
Exec = /opt/etcmgr/bin/autocommit.sh /etc pre-transaction
AbortOnFail
# etcmgr post-install hook
[Trigger]
# Operation = Install
Operation = Upgrade
# Operation = Remove
Type = File
Target = etc/*
[Action]
Description = etcmgr: post-transaction commit
When = PostTransaction
Exec = /opt/etcmgr/bin/autocommit.sh /etc post-transaction
試してみます。
# pacman -Syu --noconfirm --noprogressbar
〈省略〉
:: トランザクション前のフックを実行...
(1/2) Remove DKMS modules
==> dkms remove zfs/0.8.1 -k 5.2.9-arch1-1-ARCH
(2/2) etcmgr: pre-transaction commit
auto commit /etc when done pacman command: pre-transaction
送信しています .updated
ファイルのデータを送信しています .done
Committing transaction...
リビジョン 27 をコミットしました。
〈省略〉
:: トランザクション後のフックを実行...
〈省略〉
(13/24) etcmgr: post-transaction commit
auto commit /etc when done pacman command: post-transaction
A fonts/conf.avail/05-reset-dirs-sample.conf
A fonts/conf.avail/09-autohint-if-no-hinting.conf
A fonts/conf.avail/35-lang-normalize.conf
A systemd/pstore.conf
D dbus-1/system.d/org.freedesktop.UPower.conf
送信しています X11/xinit/xinitrc.d/50-systemd-user.sh
削除しています dbus-1/system.d/org.freedesktop.UPower.conf
追加しています fonts/conf.avail/05-reset-dirs-sample.conf
追加しています fonts/conf.avail/09-autohint-if-no-hinting.conf
追加しています fonts/conf.avail/35-lang-normalize.conf
送信しています fonts/conf.avail/40-nonlatin.conf
送信しています fonts/conf.avail/45-generic.conf
送信しています fonts/conf.avail/45-latin.conf
送信しています fonts/conf.avail/60-generic.conf
送信しています fonts/conf.avail/60-latin.conf
送信しています fonts/conf.avail/65-nonlatin.conf
送信しています fonts/fonts.conf
送信しています fonts/fonts.dtd
送信しています ld.so.cache
送信しています mail.rc
送信しています pacman.d/gnupg/pubring.gpg
送信しています pacman.d/gnupg/tofu.db
送信しています pacman.d/gnupg/trustdb.gpg
送信しています profile.d/vte.sh
送信しています services
送信しています ssl/misc/tsget.pl
送信しています systemd/networkd.conf
追加しています systemd/pstore.conf
送信しています systemd/system.conf
送信しています systemd/user.conf
ファイルのデータを送信しています ........................done
Committing transaction...
リビジョン 28 をコミットしました。
〈省略〉
# export LESSCHARSET=dos
# journalctl -at etcmgr
〈省略〉
9月 25 21:34:44 honoka etcmgr[14200]: auto commit /etc when done pacman command: pre-transaction
9月 25 21:34:44 honoka etcmgr[14200]: 送信しています .updated
9月 25 21:34:44 honoka etcmgr[14200]: ファイルのデータを送信しています .done
9月 25 21:34:44 honoka etcmgr[14200]: Committing transaction...
9月 25 21:34:44 honoka etcmgr[14200]: リビジョン 27 をコミットしました。
9月 25 22:21:46 honoka etcmgr[113921]: auto commit /etc when done pacman command: post-transaction
9月 25 22:21:47 honoka etcmgr[113921]: A fonts/conf.avail/05-reset-dirs-sample.conf
9月 25 22:21:47 honoka etcmgr[113921]: A fonts/conf.avail/09-autohint-if-no-hinting.conf
9月 25 22:21:47 honoka etcmgr[113921]: A fonts/conf.avail/35-lang-normalize.conf
9月 25 22:21:47 honoka etcmgr[113921]: A systemd/pstore.conf
9月 25 22:21:47 honoka etcmgr[113921]: D dbus-1/system.d/org.freedesktop.UPower.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています X11/xinit/xinitrc.d/50-systemd-user.sh
9月 25 22:21:48 honoka etcmgr[113921]: 削除しています dbus-1/system.d/org.freedesktop.UPower.conf
9月 25 22:21:48 honoka etcmgr[113921]: 追加しています fonts/conf.avail/05-reset-dirs-sample.conf
9月 25 22:21:48 honoka etcmgr[113921]: 追加しています fonts/conf.avail/09-autohint-if-no-hinting.conf
9月 25 22:21:48 honoka etcmgr[113921]: 追加しています fonts/conf.avail/35-lang-normalize.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/40-nonlatin.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/45-generic.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/45-latin.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/60-generic.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/60-latin.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/conf.avail/65-nonlatin.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/fonts.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています fonts/fonts.dtd
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています ld.so.cache
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています mail.rc
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています pacman.d/gnupg/pubring.gpg
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています pacman.d/gnupg/tofu.db
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています pacman.d/gnupg/trustdb.gpg
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています profile.d/vte.sh
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています services
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています ssl/misc/tsget.pl
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています systemd/networkd.conf
9月 25 22:21:48 honoka etcmgr[113921]: 追加しています systemd/pstore.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています systemd/system.conf
9月 25 22:21:48 honoka etcmgr[113921]: 送信しています systemd/user.conf
9月 25 22:21:49 honoka etcmgr[113921]: ファイルのデータを送信しています ........................done
9月 25 22:21:49 honoka etcmgr[113921]: Committing transaction...
9月 25 22:21:49 honoka etcmgr[113921]: リビジョン 28 をコミットしました。
# svn log -r 27:HEAD /etc
------------------------------------------------------------------------
r27 | root_honoka | 2019-09-25 21:28:55 +0900 (2019年09月25日 (水)) | 1 line
auto commit when done pacman command: pre-transaction
------------------------------------------------------------------------
r28 | root_honoka | 2019-09-25 22:15:59 +0900 (2019年09月25日 (水)) | 1 line
auto commit when done pacman command: post-transaction
------------------------------------------------------------------------
(2019/09/27 修正ここまで)
(2019/08/13 修正ここから)
journalctl
の不穏なメッセージ「svn: E200007: パス '/etc/pacman.d/gnupg/S.gpg-agent' のノード種別はサポートされていません」は発生しなくなった筈です。
(2019/08/13 修正ここまで)
結
Etckeeper 風に、 /etc
を Subversion で管理するようにしました。
今回はノートパソコンに導入しましたが、サーバマシンでも同様の手順で実施できると思います。
やったね