👻

Raspberry Pi 4 ModelBでTimemachine用のNASを作ってみた

2021/12/02に公開

この記事はAkatsuki Advent Calendar2日目の記事です。
前回はrakurakuさんの初めてスクラムマスターを担当した時に大切にしようと思った1つの気づきでした。

さて、本題に入りたいと思うのですが、みなさんはPCのバックアップを定期的に取ってますか?
(お恥ずかしい話ですが...)僕はNoでした。
最近バックアップを取ることの重大さを実感する事件がいくつか起きたので、これを気にバックアップ用の環境をしっかり整えようと思いました。
単純にハードディスクなどを直接PCに繋いでTimeMachineを設定する...などでも良いのですが、机の上が多少かさばるのと他の機器でも利用出来るストレージが欲しい、かつ手元にRaspberry Pi 4 ModelBが眠っていたので、Raspberry PiでNASを作ることにしました。

構成

ハードウェア

ソフトウェア

  • samba
    • ファイルサーバーとして使用
  • avahi
    • TiemMachineではmDNSの仕組みを使って名前解決しているので、mDNSに対応させるために使用
  • Docker
    • 今回はsambaをdockerで立てて環境が汚れないようにします。(avahiは良いイメージが無かったので今回はそのままインストールします。)
  • CentOS7.9-2009

RaspberryPiの初期セットアップ

OSの選定

NASを準備するにあたって、もちろんHDD,Raspberry Pi制御用にOSが必要になります。
以下のようなNASでの使用に最適化されているOSもあるのですが、Raspberry Piの余ったリソースを他の事に使って有効活用したいため、今回は通常のLinuxを使いたいと思います。
https://zenn.dev/thisprogrammer/articles/17331c862bb8163f84c5
RedHat系のディストリビューションをあまり弄ったことが無かったので、今回は勉強も兼ねてCentOSを使っていきたいと思います。
バージョンは7.9-2009にしました。
CentOS8もRaspberryPi4向けのOSイメージが有志の方によって用意されているのですが、普段触る機会の多い、Amazon Linux2に(RedHat7/CentOS7をベースにしているらしい ※公式からベースは公開されていないので予測)出来るだけ合わせました。

OSイメージの書き込み

CentOS7.9-2009のRaspberryPi4用のイメージは以下のサイトからダウンロード出来ます。
http://ftp.yz.yamagata-u.ac.jp/pub/linux/centos-altarch/7.9.2009/isos/armhfp/
こちらのサイトのRaspberryPI-Minimal-4となっているものがRaspberryPi4用のイメージです。
イメージをダウンロードして、Raspbianのインストールなどと同じ用に、RaspberryPiImagerを使って書き込んでいきます。

use customからダウンロードしてきたOSイメージを選択し、書き込みます。
Write os image
書き込みが終わったら、実際にRaspberryPi上でOSを動かしていきます。

rootで初回ログイン

RaspberryPiにイメージを書き込んだSDカードを差し込み、動かしていきます。
電源を入れてしばらくするとloginを求められる画面が現れます。
パスワード設定してないけどどすれば良いの...!?となるかもしれませんが、デフォルトのrootパスワードが決まっていて以下のパスワードを利用すればログイン出来ます。

  • ユーザー名: root
  • password: centos
    ※パスワードはログイン後に変更しましょう

ユーザーの作成

rootのままで作業するのは何でも出来てしまって危険なので、念の為ユーザーを追加して進めていきます。

> useradd -m hoge
# hogeの部分は任意のユーザー名

また、デフォルトのままではsudoが出来ないのでsudoersに加えていきます

> visudo

エディターが開くので権限を追加していきます。

...
## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL
hoge ALL=(ALL) ALL

今回は全権限を付与してしまいましたが、セキュリティを考慮するのであれば、以下のmanページを見て最小の権限を持たせると良いでしょう。

https://linuxjm.osdn.jp/html/sudo/man5/sudoers.5.html

ネットワーク設定

Wifiに接続

各種パッケージやソフトウェアのインストールをしたり、LAN内からsshしたりするためにはもちろんインターネット、自宅内のLANに繋がっている必要があります。
今回はWifiを利用します。
この設定をNetworkManagerを使って行っていきます。
まず、以下コマンドで接続先のSSIDを確認します。

> nmcli dev wifi rescan # 利用可能なアクセスポイントのリストを更新
> nmcli dev wifi list # 利用可能なアクセスポイントを一覧表示
IN-USE  SSID                    MODE      CHAN  RATE        SIGNAL  BARS  SECURITY
        HOGE                    インフラ  44    540 Mbit/s  100     ▂▄▆█  WPA2
        FUGA                    インフラ  128   130 Mbit/s  84      ▂▄▆█  WPA1 WPA2
        FUGA2                   インフラ  11    130 Mbit/s  79      ▂▄▆_  WPA1 WPA2
        HOGE2                   インフラ  3     260 Mbit/s  62      ▂▄▆_  WPA2
....

次に接続したいSSIDのアクセスポイントに接続していきます。

> nmcli dev wifi connect MY-SSID password MY-PASSWORD

これでWifiに接続出来たかと思います。
外部のサイトにpingなどを打ってみて通っていればOKです!

※接続出来ない場合は以下を試してみてください。

  • Wifiが有効か確認する
> nmcli radio
WIFI-HW  WIFI  WWAN-HW  WWAN
有効     有効  有効     有効
# 無効になっていた場合は
> nmcli radio wifi on
  • 一度接続情報を消して接続し直してみる
> nmcli con delete MY-SSID
> nmcli dev wifi connect MY-SSID password MY-PASSWORD

参考:
https://unix.stackexchange.com/questions/420640/unable-to-connect-to-any-wifi-with-networkmanager-due-to-error-secrets-were-req
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/connecting-to-a-wi-fi-network-with-nmcli_managing-wi-fi-connections

必要なパッケージのインストール

初期状態ではインストール済みパッケージが古いままなので最初に更新していきます。
(結構時間かかります... コーヒーでも飲みながら待ちましょう!

> sudo yum -y update

Dockerをインストールする

ファイルサーバーとしてsambaを利用するのですが、環境を汚したくないためそれぞれのDockerを利用します。
そのためには、まずDockerをインストールしていくのですが、現状、CentOSかつarmv7lアーキテクチャでのdocker利用はstableバージョンではサポートされていないようです...
ただし、nightlyビルドにarmhfp(armv7l)のサポートが含まれており、こちらを利用することにしました。
https://raspberrypi.stackexchange.com/questions/85654/installing-docker-on-rpi-3b-with-centos#answer-113367

> sudo yum install -y yum-utils
> sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
> sudo yum-config-manager --disable docker-ce-stable
> sudo yum-config-manager --enable docker-ce-nightly

まず、docker-ceをインストールし、nightly buildを有効にします。
その後、armv7l用のバイナリをインストール出来るように、設定を弄っていきます。

sudo vim /etc/yum.repos.d/docker-ce.repo
[docker-ce-nightly]
name=Docker CE Nightly - armv7l
baseurl=https://download.docker.com/linux/centos/$releasever/armv7l/nightly
enabled=1
gpgcheck=1
gpgkey=https://download.docker.com/linux/centos/gpg

これでdockerをインストールする準備が完了したので、インストールすれば完了です!

sudo yum install -y docker

docker-composeをインストールする

https://docs.docker.com/compose/install/
上記公式サイトを参考にインストールしようと思ったのですが、公式ドキュメントに乗っている1.29.2をcurlでダウンロードする方法はNotFoundとなってしまいうまくいきませんでした...
そこでdocker-compose1.29.2のリリースページを見てみると

上記画像のような状態となっており、CentOS7 on Raspberry Piの場合

https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)

https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-armv7l

となってしまうので、当然存在しません。
なので、armv7のバイナリが存在する2.0.0以上を指定してダウンロードするか、Alternative install optionsで紹介されているpipを使った方法でインストールする必要があります。
しかし、docker-composeが依存しているcryptographyではCentOS7系をサポートしていないようで、インストールがうまくいかなかったので前者の方法で進めました。

installページのurlを以下に書き換えてインストールしていきます。

> sudo curl -L https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-armv7" -o /usr/local/bin/docker-compose
> sudo chmod +x /usr/local/bin/docker-compose

これでDocker周りの準備は完了です。

ストレージの準備

NASにするためには、もちろん保存先のストレージが必要です。
今回はHDDを2台用意し、ミラーリング(RAID1)構成にして冗長性を高めたいと思います。
まずはTime Machine用にパーティションを作成します。

Time Machine用パーティションの作成

RaspberryPiのシステムを一旦シャットダウンし、HDDを繋げて行きましょう。
繋げた直後のディスクは以下のような状態になっています。

> sudo parted -l
番号  開始  終了  サイズ  ファイルシステム  名前  フラグ

エラー: /dev/sda: ディスクラベルが認識できません。
モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sda: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:

エラー: /dev/sdb: ディスクラベルが認識できません。
モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sdb: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: unknown
ディスクフラグ:

モデル: SD SD16G (sd/mmc)
ディスク /dev/mmcblk0: 31.3GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:

番号  開始    終了    サイズ  タイプ   ファイルシステム  フラグ
 1    4194kB  304MB   300MB   primary  fat16             boot, lba
 2    304MB   816MB   512MB   primary  linux-swap(v1)
 3    816MB   31.3GB  30.5GB  primary  ext4

LinuxではHDDのデバイス名は見つかった順にsda, sdbとsdに後にアルファベット順になるように割り振られていくようです。
(ちなみに、パーティションを切るとsda1,sda2...のようにデバイス名の後に数値が割り振られていきます。)

https://eng-entrance.com/linux-partition#i-3
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/storage_administration_guide/persistent_naming

なので、今回追加したHDDは/dev/sda, /dev/sdbになります。
parted -lの結果をよく見てみると下記エラーが出てしまっています。

エラー: /dev/sda: ディスクラベルが認識できません。

この状態では対話モードでデバイスの情報を表示、パーティションの作成などが出来ないので、まずはディスクラベルを設定していきます。
partedの対話モードを使って、ラベルの設定をしていきます。

> sudo parted /dev/sda
GNU Parted 3.1
/dev/sdb を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) > help mklabel
mklabel,mktable ラベルの種類  新しいラベル(パーティションテーブル)を作る
	ラベルの種類は次のうちから選びます: aix, amiga, bsd, dvh, gpt, mac, msdos, pc98, sun, loop

ラベルの種類は次のうちから選びます: aix, amiga, bsd, dvh, gpt, mac, msdos, pc98, sun, loop

と出ますが、msdos(MBR: Master Boot Record)とgpt(GUID Partition Table)以外は古くから使われているものがほとんどで、2つのうちから選べば良いようです。
で、この2つの違いなのですが以下の記事がわかりやすいかと思います。

https://jp.minitool.com/partition-disk/mbr-vs-gpt-guide.html
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/installation_guide/ch-partitions-x86

簡単にまとめると

  • パーティション容量の最大値が違う
    • MBRは最大2TB(512Bセクタで)
    • GPTは8ZiB(ゼビバイト: 2^{70}バイト, 上限まで使える人は現代に居ないと思うので上限なしと捉えて良さそうですね...笑)
  • プライマリパーティションの数
    • MBRは最大4つまで(4つ以上使いたい場合は1つを拡張パーティションとし、論理パーティションを切る)
    • GPTは最大128
      今回は4TBのHDDを使っているのでgpt方式を使います。
(parted) > mklabel gpt
(parted) > p
モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sdb: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:

番号  開始  終了  サイズ  ファイルシステム  名前  フラグ

これでパーティション作成が出来るようになりました!
さっそく作っていきましょう。
パーティションを切る前にどの容量でパーティションをどの数切るか決める必要があります。
今回はTimeMachine用のもののみ用意したいと思います。
TimeMachine用のパーティション容量なのですが、保存する容量x3倍ほどの容量にしている人が多そうでした。
私の場合、バックアップ容量が280GBほどだったので今回は800GBをTimeMachine用に割り当てたいと思います。
mkpartを使ってパーティションを作成します。

sudo parted /dev/sda
GNU Parted 3.1
/dev/sda を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) > help mkpart
 mkpart パーティションの種類 [ファイルシステムの種類] 開始 終了
        パーティションを作る

	パーティションの種類は次のうちのどれかとなります: プライマリ、論理、拡張
        ファイルシステムの種類は次のうちから選びます: btrfs, nilfs2, ext4, ext3, ext2, fat32, fat16, hfsx, hfs+,
        hfs, jfs, swsusp, linux-swap(v1), linux-swap(v0), ntfs, reiserfs, hp-ufs, sun-ufs,
        xfs, apfs2, apfs1, asfs, amufs5, amufs4, amufs3, amufs2, amufs1, amufs0, amufs,
        affs7, affs6, affs5, affs4, affs3, affs2, affs1, affs0, linux-swap,
        linux-swap(new), linux-swap(old)
        START と END は、ディスク上の位置を 4G や 10% などで表わします。負の値はディスクの終わりからの値になります。例えば、-1s
        は、最後のセクタを指します。

        mkpart はパーティションだけ作り、新しいファイルシステムは作りません。ファイルシステムの種類を指定すると、正しいIDが設定されます。

(parted) > mkpart timemachine 0% 20%
(parted) > p
モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sda: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:

番号  開始    終了   サイズ  ファイルシステム  名前         フラグ
 1    1049kB  800GB  800GB                     timemachine

800/4000 = 0.2なので0%, 20%を指定すると800GB分のパーティションが作成されます。
ファイルシステムはフォーマット時に指定するのでここでは指定してません。
次にフォーマットを行います。
ファイルシステムもいくつか種類があり、悩みどころですが、比較的動作が安定しているらしいext4を選びました。
こちらの記事を参考に状況に応じたものを選ぶと良いでしょう。

https://qiita.com/sion_cojp/items/c8e015db39ddbf43012e

フォーマットを行うには、mkfsコマンドを使用します。
詳細はこちらで確認出来ます!

https://linuxjm.osdn.jp/html/util-linux/man8/mkfs.8.html

今回はext4でフォーマットを行うので、以下のコマンドを打ち込みます。

(parted) > quit
> sudo mkfs -t ext4 /dev/sda1

先程作成したパーティションに対してフォーマットを行うので、フォーマットしたいドライブの末尾に1を指定しています。
番号はparted -lなどで確認しましょう。
/dev/sdaのみパーティションが完了している状態なので、2台ある場合は、残りのHDDにも同様の手順を踏めばストレージの準備は完了です!

RAID1構成にする

冗長性を高めるため、今回はHDDを2台用意し、RAID1構成にしたいと思っています。
先程までで、HDD2台に対して同様のパーティションが出来ているはずです。

> sudo parted -l
モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sda: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:

番号  開始    終了   サイズ  ファイルシステム  名前         フラグ
 1    1049kB  800GB  800GB   ext4              timemachine


モデル: WDC WD40 EZAZ-00SF3B0 (scsi)
ディスク /dev/sdb: 4001GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ:

番号  開始    終了   サイズ  ファイルシステム  名前         フラグ
 1    1049kB  800GB  800GB   ext4              timemachine

この2つのパーティションに対してRAID1を構成します。
これにはmdadmコマンドを使用し、mdデバイスを作成します。

初期状態では入っていないのでまずはインストール

> sudo yum install -y mdadm

https://www.ioss.jp/sohodiy/mdadm8-1_5.php
上記のCREATEモードを使うとmdデバイスを新規作成出来ます。

> mdadm --create --help
Usage:  mdadm --create device --chunk=X --level=Y --raid-devices=Z devices

 This usage will initialise a new md array, associate some
 devices with it, and activate the array.   In order to create an
 array with some devices missing, use the special word 'missing' in
 place of the relevant device name.

 Before devices are added, they are checked to see if they already contain
 raid superblocks or filesystems.  They are also checked to see if
 the variance in device size exceeds 1%.
 If any discrepancy is found, the user will be prompted for confirmation
 before the array is created.  The presence of a '--run' can override this
 caution.

 If the --size option is given then only that many kilobytes of each
 device is used, no matter how big each device is.
 If no --size is given, the apparent size of the smallest drive given
 is used for raid level 1 and greater, and the full device is used for
 other levels.

 Options that are valid with --create (-C) are:
  --bitmap=          -b : Create a bitmap for the array with the given filename
                        : or an internal bitmap if 'internal' is given
  --chunk=           -c : chunk size in kibibytes
  --rounding=           : rounding factor for linear array (==chunk size)
  --level=           -l : raid level: 0,1,4,5,6,10,linear,multipath and synonyms
  --parity=          -p : raid5/6 parity algorithm: {left,right}-{,a}symmetric
  --layout=             : same as --parity, for RAID10: [fno]NN
  --raid-devices=    -n : number of active devices in array
  --spare-devices=   -x : number of spare (eXtra) devices in initial array
  --size=            -z : Size (in K) of each drive in RAID1/4/5/6/10 - optional
  --data-offset=        : Space to leave between start of device and start
                        : of array data.
  --force            -f : Honour devices as listed on command line.  Don't
                        : insert a missing drive for RAID5.
  --run              -R : insist of running the array even if not all
                        : devices are present or some look odd.
  --readonly         -o : start the array readonly - not supported yet.
  --name=            -N : Textual name for array - max 32 characters
  --bitmap-chunk=       : bitmap chunksize in Kilobytes.
  --delay=           -d : bitmap update delay in seconds.
  --consistency-policy= : Specify the policy that determines how the array
                     -k : maintains consistency in case of unexpected shutdown.
> sudo mdadm --create /dev/md0 --level=raid1 --name=timemachine --raid-devices=2 /dev/sda1 /dev/sdb1
# --level
## raidのレベルを指定する。次から選ぶ: linear, raid0, 0, stripe, raid1, 1, mirror, raid4, 4, raid5, 5, raid6, 6, multipath, mp
# --raid-devises
## raidを構成するデバイス数とデバイスを指定する。

上記コマンド実行後、/dev/md0にmdデバイスが作成されているはずです。

> sudo mdadm --detail --scan
ARRAY /dev/md0 metadata=1.2 name=localhost:timemachine UUID=8e11373e:qqqq53e8:3333e957:e78f0496
> sudo mdadm --detail /dev/md0
/dev/md0:
           Version : 1.2
     Creation Time : Sun Nov 28 05:16:19 2021
        Raid Level : raid1
        Array Size : 781271040 (745.08 GiB 800.02 GB)
     Used Dev Size : 781271040 (745.08 GiB 800.02 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Sun Nov 28 05:20:11 2021
             State : clean, resyncing
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : bitmap

     Resync Status : 2% complete

              Name : localhost:timemachine  (local to host localhost)
              UUID : 44e1373e:bc2c53e8:39a5e957:16160496
            Events : 46

    Number   Major   Minor   RaidDevice State
       0       8        1        0      active sync   /dev/sda1
       1       8       17        1      active sync   /dev/sdb1

ここで、ファイルフォーマットに移りたいところですが、CentOS7では作成したmdデバイスが再起動後に勝手にmd127に書き換わってしまう問題があるようなので、/etc/mdadm.confを更新しておきます。

> sudo sh -c "mdadm --detail --scan >> /etc/mdadm.conf"
# リダイレクトの場合、実行ユーザーに権限が無いとsudoでも弾かれてしまうのでshのcオプションで実行する

https://dan-project.blog.ss-blog.jp/2016-07-16

mdデバイスもフォーマットする必要があるので、先程と同じくextfでフォーマットします。

> mkfs -t ext4 /dev/md0

linuxにはドライブレターの仕組みが無いので、デバイスを認識しただけでは、読み書きが出来ません。
作成したドライブで読み書き出来るようにマウントしていきます。
マウントには名前そのままmountコマンドが利用出来ます。
今回は/timemachineというディレクトリを作成してマウントします。

> sudo mkdir /timemachine
> sudo mount /dev/md0 /timemachine
> mount | grep timemachine
...
/dev/md0 on /timemachine type ext4 (rw,relatime,seclabel)

作成後の状態のままだと、マウントしたディレクトリに書き込み権限がなく、バックアップを保存出来なくなってしまうので、所有権をユーザー(hoge)へ変更しておきます。
このフローによってマウント先のディレクトリへの読み書きが可能になります。

> ls -l / | grep time
drwxr-xr-x.   3 root root  4096 121 14:37 timemachine
> sudo chown -R hoge:hoge /timemachine
> ls -l / | grep time
drwxr-xr-x.   3 hoge hoge  4096 121 14:37 timemachine
# もちろん sudo chmod 666 /timemachine でも動きます

これでストレージの準備が完了しました!

Sambaの起動

さて、ようやく保存先のファイルサーバーの準備に取り掛かっていきます。
構成でも述べたように、出来るだけ環境を汚したくないのでDockerで動かすようにしたいと思います。
sambaのDocker ImageはいくつかDockerHubに公開されていて、中でもdperson/sambaが有名なようです。
RaspberryPiでも動くarmアーキテクチャ用のイメージもあるようなので、今回はこれを利用していきたいと思います。
対応するタグはarmhfになります。
https://hub.docker.com/layers/dperson/samba/armhf/images/sha256-ba2b01e5a3298c5a743bc38d3c98407fc39d23a2fe4044308d9fa1f64d8c1e53?context=explore

https://github.com/dperson/samba#configuration
https://www.samba.org/samba/docs/current/man-html/vfs_fruit.8.html
sambaをTimeMachineに対応させるにはvfs_fruitというAppleのSMBと互換性を高めてくれるモジュールが必要なようです。
上記を参考にTimeMachine用のsambaの設定ファイルを作成し、コンテナに反映させられるようにします。

[TimeMachine]
  path = /timemachine
  writable = yes
  guest ok = yes
  vfs objects = catia fruit streams_xattr
  fruit:resource = file
  fruit:metadata = netatalk
  fruit:encoding = native
  fruit:locking = netatalk
  fruit:time machine = yes
  fruit:aapl = yes
  fruit:advertise_fullsync = true
version: "3"
services:
    samba:
        container_name: sambad
        image: dperson/samba:armhf
        restart: always
        volumes:
            - /timemachine:/timemachine:z
	    - ~/timemachine_smb.conf:/timemachine_smb.conf
        ports: # sambaで使用するポート、開いておく必要あり。
            - 139:139
            - 445:445
        environment:
            - TZ=Asia/Tokyo
            - USERID=1000 # hogeのユーザーid
            - GROUPID=1000 # hogeのグループid
        command: >
                -w "WORKGROUP" # sambaのワークスペース設定
                -S # SMB2未満のバージョンを無効化する
		-I /timemachine_smb.conf # confファイルをincludeさせる
		

SELinuxの設定によってうまく共有出来ないので一旦無効化します。
※セキュリティ的にあまり良く無いので、有効化した状態で設定を通すようにしたほうが良いです。今回は一旦無効化して対応し、他のタイミングでsambaとSELinuxの共存設定について調査、記事にまとめようと思います...
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-managing_confined_services-samba-configuration_examples
設定する際はこの辺りが参考になるかもしれません。(docker使う場合はそのままでは駄目そうです)

> sudo satenforce 0
> sudo getenforce
Permissive

これでsambaの準備が出来たので動かしていきましょう。

> docker-compose up -d
[+] Running 2/2
 ⠿ Network yoshitomoyasuno_default  Created 
 ⠿ Container sambad                 Started
> docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                                 PORTS                                                     NAMES
eac9490f2bf8        dperson/samba:armhf   "/sbin/tini -- /us..."   About a minute ago   Up About a minute (health: starting)   0.0.0.0:139->139/tcp, 137-138/udp, 0.0.0.0:445->445/tcp   sambad
> docker logs sambad
smbd version 4.14.5 started.
Copyright Andrew Tridgell and the Samba Team 1992-2021
daemon_ready: daemon 'smbd' finished starting up and ready to serve connections

上記のように特にエラーが発生していなければファイルサーバーの準備完了です!

mDNSの準備

さて、ようやく最後のステップです。
TimeMachineへバックアップを取れるようにするためには、TimeMachineの設定画面でNASを選択出来る必要があります。
TimeMachineではこのファイルサーバーの名前解決にmDNSを使っています。
mDNSとはマルチキャスト通信を利用して小さなローカルネットワーク上で名前解決を行う仕組みのことで、この仕組を使うことによって、DNSサーバーの用意、設定などを特にしなくてもバックアップ先のサーバーを発見出来る訳です。
MacOSの実装ではBonjourと呼ばれているようです。
このmDNSに対応させるためにavahiというソフトウェアを使います。

https://ja.wikipedia.org/wiki/マルチキャストDNS

まず、avahiもデフォルトでは入っていないので入れていきます。

> sudo yum install -y avahi
> sudo systemctl start avahi-daemon

この状態でも{ラズパイのホスト名}.localでの名前解決は可能なのですが、TimeMachineで利用するためにはもう少し設定が必要になります。

TimeMachineでmDNSを使えるようにするには、Bonjourの要件をいくつか満たしている必要があるようです。
こちらでApple公式でどのような設定にすべきか解説しています。
https://developer.apple.com/library/archive/releasenotes/NetworkingInternetWeb/Time_Machine_SMB_Spec/index.html#//apple_ref/doc/uid/TP40017496-CH1-SW1
概要

  • _smb._tcpポート445でsmbが利用可能である。
  • _adisk._tcp。のmDNSサービスレコードを登録および公開出来る。
    • adVNにボリュームの名前を設定する。※sambaの共有名(今回はTimeMachine)と一緒にする必要があります。
    • AirDiskVolumeFlags(adVF)の値を0x82に設定する。
      この設定を参考にavahiの設定ファイルを作っていきます。
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
 <name replace-wildcards="yes">%h</name>
 <service>
   <type>_smb._tcp</type>
   <port>445</port>
 </service>
 <service>
   <type>_adisk._tcp</type>
   <txt-record>dk0=adVN=TimeMachine,adVF=0x82</txt-record>
 </service>
</service-group>

この設定を反映させるとTimeMachineの設定画面でこんな感じでディスクを選択出来るようになります。

このままバックアップ設定を進めると無事にバックアップが開始されました!

まとめ

無事バックアップの作成まで完走出来ました。
途中はまりどころが何度もあり、長々と手法を書いてしまったので少し読みにくい感じになっているかもしれません...
ハマったところを列挙すると

  • Dockerインストール出来ない
    • 解決法: nightly buildを使う
  • docker-composeインストール出来ない
    • 解決法: 2.0.0以上のものを指定する
  • sambaにアクセスない...
    • 解決法: 書き込み権限、SELinuxの権限を確認する
  • TimeMachineから接続先が見えない
    • 解決法: avahiでTimeMachine用の設定を行う

こんなところでしょうか。(ほぼ全てですね...)
時間に間に合わなかった

  • SELinuxと共存する設定
  • sambaの認証がうまくいかない

は引き続き課題として調べていきたいと思います。

また、今回利用したHDDケースはハードウェアでのRAID構成も可能なため、ソフトウェアRAIDとハードウェアRAIDでどのくらいスループットの差が出るのかも測ってみたいですね。
今回やってみた感想としてはNASは複数の知識(ネットワーク、ストレージ)が必要だったので、特にLinux周りの知識が深まって良かったと思います。
普段何気なく使ってる製品も自作してみると結構楽しいかつ勉強にもなるので、NASに限らず作ってみることがオススメです。

Discussion