自宅サーバー構築譚：Subversionをインストールして /etc をバージョン管理・Ubuntu 22.04

# 能書き

[自宅サーバー構築譚：基本構想](https://qiita.com/katz_engineer/items/cb592be44daa28a51d9b)に基づく自宅サーバー構築、[Ubuntu22.04LTSインストール](https://qiita.com/katz_engineer/items/1ffea0a145da7025e10d)の続きです。

```/etc```をバージョン管理します。但し私の個人的な好みで、GitではなくSubversionを使います。

[以前](https://qiita.com/katz_engineer/items/fefae5e3dc60fc8451a0)も同じ内容を書きましたが、22.04になってどうも勝手が変わったようなので、改めて記事を立てます。

# 準備

[前回](https://qiita.com/katz_engineer/items/1ffea0a145da7025e10d)の続きなので、実機のコンソールにrootでログインします。

## システムのアップデート

何はともあれスナップショット。これを気軽に実行できるのが zfs （及び btrfs ）の素晴らしい点です。そしてシステム全体のスナップショットを撮っておけば、何かあってもすぐに復旧できます。

ちなみに、システム関連なので対象は ```tank/ROOT/ubuntu``` だけです。それ以外については除外します。

```console
zfs snapshot tank/ROOT/ubuntu@$(date +%Y%m%d_%H%M%S)_before_universe
zfs snapshot tank/ROOT/ubuntu/var/lib/apt@$(date +%Y%m%d_%H%M%S)_before_universe
zfs snapshot tank/ROOT/ubuntu/var/lib/dpkg@$(date +%Y%m%d_%H%M%S)_before_universe
```

しかし[前回](https://qiita.com/katz_engineer/items/1ffea0a145da7025e10d)のままでは```apt-add-repository```コマンドは使えない模様。そんな時には下記コマンド、だそうです。

参考文献： [Ubuntu Linuxで、add-apt-repositoryしようとして「コマンドがない」って言われたら - CLOVER](https://kazuhira-r.hatenablog.com/entry/20160116/1452933387)

```console
apt install --yes software-properties-common
apt update
```

リポジトリuniverseを追加します。

```console
apt-add-repository universe
```

パッケージ関連の更新など。

```console
apt update
apt upgrade
```

## パッケージインストール前のスナップショット

スナップショットはガンガン撮りまくりましょう！HDDの逼迫は心配無用。内部的には差分管理と同じ形になっているので、そんなに消費しません。それでも問題になったら、その時に古いのを削除すればいいんです。

```console
zfs snapshot tank/ROOT/ubuntu@$(date +%Y%m%d_%H%M%S)_before_Subversion
zfs snapshot tank/ROOT/ubuntu/var/lib/apt@$(date +%Y%m%d_%H%M%S)_before_Subversion
zfs snapshot tank/ROOT/ubuntu/var/lib/dpkg@$(date +%Y%m%d_%H%M%S)_before_Subversion
```

スナップショットを確認します。さっきのアップデート前の物も一緒に見てみます。
Ubuntuは```apt```のタイミングで自動的にスナップショットを撮るようで、それが鬱陶しいので、```grep -v autozsys```で除外します。

```console
zfs list -t snapshot -S name -r tank/ROOT/ubuntu | grep -v autozsys | head -n3
```
オプション```-S```（Sは大文字）でスナップショット名の逆順を指定しているのがミソ。名前に日時を付けているので、新しい順に表示されます。説明記事を書いたりエビデンスを揃えたりする場合に便利です。

```console
# zfs list -t snapshot -S name -r tank/ROOT/ubuntu | grep -v autozsys | head -n3
NAME                                                 USED  AVAIL     REFER  MOUNTPOINT
tank/ROOT/ubuntu@20221228_170030_before_Subversion     0B      -     1.00G  -
tank/ROOT/ubuntu@20221228_165740_before_universe     288K      -     1013M  -
```

# Subversionインストール

## パッケージ

svnパッケージをインストール。

```console
apt install --yes subversion
```

インストールできたか確認します。

```console
svn --version | head -n2
```

表示内容は、例えば下記のようになります。

```console
# svn --version | head -n2
svn, version 1.14.1 (r1886195)
   compiled May 21 2021, 10:52:35 on x86_64-pc-linux-gnu
```

Subversion のバージョンは 1.14.1 ですか。何が変わったんでしょうね。少なくともレッドブックは……役に立たないとは言わないけど、細かい部分でかなり変わったんじゃないかと思うんだけど。思うんだけど！この手順では```man svn``` も ```info svn``` も表示されない… :sweat:

そして公式ページでは、ユーザーマニュアルはレッドブックでした。それもかなり古い。

実験的な機能は使わない方が良さそうだからまあいいか（バージョンアップで操作性や機能などが頻繁に変わるっぽい）

なお、失敗した場合のロールバックの方法については[以前の記事](https://qiita.com/katz_engineer/items/f3bd2f7af2ba49db156c)を参照して下さい。

## リポジトリ

今回はとにかく```/etc```のバージョン管理を開始するのが目標ですので、汎用的なプロジェクト用の設定は後日とします。

- 専用ユーザは作成しません。```/etc```バージョン管理はrootが行います。
- 汎用リポジトリの場所も用意しません。

汎用ではなく```/etc```の為のリポジトリの場所は、```/etc/.svn_repo```とします。

当然、svnの管理対象外とする設定を忘れてはなりません。その手順は後述。

```console
mkdir /etc/.svn_repo
svnadmin create /etc/.svn_repo/
```

# ```/etc```を作業コピーにする

```console
cd /tmp
mkdir etc
svn import etc file:///etc/.svn_repo/ -m "create project"
rmdir etc
svn co file:///etc/.svn_repo/ /etc
```

ちゃんと出来たか確認。

```console
ls -dl /etc/.svn
```

```/etc/.svn```ディレクトリが出来ていればOKです。例えば下記のように表示されればOK。

```console
# ls -dl /etc/.svn
drwxr-xr-x 4 root root 8 Dec 28 17:07 /etc/.svn
```

# バージョン管理

## 最初の一歩

ちょっと面倒な事になっています。

どうもOpenSSLがデフォルトでインストールされていて、その関係でしょうか、```/etc/ssl/certs```ディレクトリにルート証明書が既に沢山入っているのです。それだけなら良いんですが、1つだけ、ファイル名がUTF-8に変換できないとかいうとんでもないファイルがあります。

```console
# ls /etc/ssl/certs/NetLock*
'/etc/ssl/certs/NetLock_Arany_=Class_Gold=_F'$'\305\221''tan'$'\303\272''s'$'\303\255''tv'$'\303\241''ny.pem'
```

本当の所がどうなのかは知りません。知りたいとも思いませんし。とにかくこいつがあるとSubversionで処理できなくなります。

仕方が無いので削除してしまいます。

```console
rm /etc/ssl/certs/NetLock*
ls /etc/ssl/certs/*.0 | while read f; do echo -n $f$'\t'; readlink $f; done | grep NetLock | cut -f 1 | xargs -rt rm
sed -i -e"/NetLock/d" /etc/ca-certificates.conf.dpkg-old /etc/ca-certificates.conf
```

後は普通に登録します。

```console
cd /etc
svn add *
```

```console
ls *- | xargs -rt svn revert
```

```svn revert```の結果は下記のように表示されます。

※ 2023/04/22 いつの間にか除外ファイルが追加されるようになっていましたので、念の為に追記しておきます。

```console
# ls *- | xargs -rt svn revert
svn revert group- gshadow- passwd- shadow- subgid- subuid-
Reverted 'group-'
Reverted 'gshadow-'
Reverted 'passwd-'
Reverted 'shadow-'
Reverted 'subgid-'
Reverted 'subuid-'
```

Subversion管理から外したファイルを確認してみます。

```console
# svn st --no-ignore | grep -E "^(\?|I)"
?       .pwd.lock
?       .svn_repo
?       group-
?       gshadow-
?       passwd-
?       shadow-
?       subgid-
?       subuid-
```

```.pwd.lock``` については[以前調べました](https://qiita.com/katz_engineer/items/c9afdcb0e2355ed67ede#etc-%E7%AE%A1%E7%90%86%E9%96%8B%E5%A7%8B)。バージョン管理は不要です。どうも更新時に設定されるロックファイルらしい。という訳で無視します。

参考文献: [Re: What is /etc/.pwd.lock for ? - debian-user Jul 2005 by thread](https://lists.debian.org/debian-user/2005/07/msg02949.html)

さて、最初のcommitです。コミットメッセージは何でも良いんですが。

```console
svn ci -m "first commit"
```

どういう訳か部分的にリビジョン不一致を起こす模様。そのため下記コマンドも実行します。

```console
svn up /etc
```

## 確認

ログを表示させてみます。

```console
# svn log /etc
------------------------------------------------------------------------
r1 | root | 2023-01-03 14:36:56 +0900 (Tue, 03 Jan 2023) | 1 line

first commit
------------------------------------------------------------------------
```

余談ですが、```xmllint```コマンドがあれば、```--xml```オプションと組み合わせて色んな値を抽出する事が出来ます。```head```とか```sed```とかを組み合わせてビクビクしながら調整する必要はありません。が、現状ではインストールされていませんので、参考文献を示すだけにしておきます。

参考文献1: [俺様サーバー構築記 - Subversionサーバーの構築@デスクトップパソコン](https://qiita.com/katz_engineer/items/b893316b4d1bb7731e87)
参考文献2: [俺様サーバー構築記 - Subversionをインストールして /etc をバージョン管理@全機](https://qiita.com/katz_engineer/items/29bb4672f69e70944a80)

## 無視ファイル

現時点でSubversion管理下に無いファイルは、すべて無視ファイルとして登録します。

```console
svn propset svn:ignore -F <(svn st | cut -b9-) .
```

状態を確認します。

```console
# cd /etc
# svn st
 M      .
# svn di
Index: .
=================================================
--- .       (revision 1)
+++ .       (working copy)

Property changes on: .
_________________________________________________
Added: svn:ignore
## -0,0 +1,6 ##
+.pwd.lock
+.svn_repo
+group-
+gshadow-
+passwd-
+shadow-
```

これも```/etc```の変更ですのでcommitします。

```console
svn ci -m"set svn:ignore"
```

# 結

これで```/etc```をバージョン管理できるようになりました。個人的な好みでSubversionですが。
やったね:thumbsup_tone1: