Chienomi

NASを手作りしよう

Live With Linux::server

NASとは、ストレージサーバーの一種である。

市販NASの販売戦略としては主に2種類である。 ひとつは、USBディスクに対してネットワークアクセス可能なディスクというようなイメージのもの(USBウェブカムとネットワークカメラの関係のような)、もうひとつは1台簡潔のシンプルなストレージサーバーというようなイメージのもの。 1〜4ベイのホームユース向けのものは前者の、4〜8ベイのSOHO向けのものは後者のイメージを取ることが多い。

これはあくまでイメージ的なものであり、実態としてはまた違う。

わかりやすいように単純な2ベイのNASを考えてみよう。

システムストレージを別途持っているわけではないNASにおいては、インストールされているディスクに対してシステムを展開する必要がある。さらに、それらディスクをまとめてひとつのストレージとして扱えるようにする。

単純な考え方としては、2つのディスクに等しくパーティションを切り、LVMやmdによってディスクをまたいだボリュームを作る。 システムディスクにシステムをインストールするにはそのイメージをどこかに置かなくてはならないが、通常それはNAS内でストレージを別に持っている。

そしてデータボリュームを何かしらの、あるいは様々な方法で外部に提供する。 一般的にはCIFS, FTP, SFTP, AFP, iSCSIなどである。

また、場合によってはDLNAなどでファイルではなくコンテンツを提供する場合もある。

家庭内でのUSBディスクと比べると、

  • 複数台での同時利用が可能
  • 固定運用が可能
  • アクセス制御が可能

といったメリットがある。

NASといえばQNAPやSynology、あとは今はなきNetGearなどがあるが、基本的にそのシステムは割と簡単に構築できるサーバーであり、それほど複雑な、あるいは特異なシステムをしているわけではない。 Webインターフェイスなどいくらかの利点はあるが、実際はアプライアンスならではのコントロールのしづらさのほうがずっと大きく、NASを運用していてちゃんとしたサーバーのほうが使いでがあると感じるようになってきた。

そこで、ここでは今や入手性もよくない8ベイのNASを目指して自作する手順を紹介する。 今回の記事は特殊用途のPC自作と、Linuxホームサーバー構築の2つの話になる。

NASハードウェアを選定する

NASハードウェアの構成例

NASのハードウェアを構成する上で重要なのは

  • 必要なディスクを搭載可能
  • 省電力
  • 静音
  • コンパクト

である。

実は最後の「コンパクト」というのが最も難しく、NASはディスクを搭載できるギリギリのサイズの筐体を持っているため、普通にPCを自作するとNASほどコンパクトにはならない。

選択肢は多くはないが、NASを自作したいというユーザーに向けたPCケースというのが存在し、基本的にこれで構築していくことになる。

ただ、NAS向けPCケースは容量が小さいにも関わらず、大量のディスクを搭載するわけで、内部はかなり狭い作りになっている。作業難易度は高めだ。

NASやストレージサーバー向けのケースを多く販売しているのがSilver Stoneである。 Silver Stoneは数年前まですごく品質の低いケースを作っていたのだが、最近のは良い。 このため、選び方には少し気を遣う。

そして、事実上唯一の選択肢と言えるのがSilver StoneのDS380である。 4ベイならもう少し選択肢があるのだけど、8ベイだとない。

この「コンパクト」は全体的に足を引っ張る要素でもある。DS380も高いし、選択肢がないが、さらにスペースが非常に狭いMini-ITXケースであるため、パーツが全体的に割高だ。 これを捨てられるならだいぶ楽になるが、重要な要素でもある。

これを踏まえると、コンパクトを捨てない場合だいたい話が決まってくる。

Mini-ITXでSATA8ポートを狙うのは厳しいので、普通に4ポート、ないし6ポートのMini-ITXボードを選択する。 IntelでもAMDでも良いが、AMDだと選択幅がだいぶ狭くなるのでIntelになる場合が多い。

コンパクトにすると熱的に厳しいため、そもそも高性能なCPUを載せるのは現実的ではない。 処理性能を捨てていくならJ5040-ITXのようなオンボードプロセッサ製品を選択する道もあるが、普通のプロセッサを乗せればもう少し性能に期待できるようになる。ここらへんは熱、コスト、使い方などのバランスである。 なお、BtrfsやZFSはかなり重い処理も存在するので、NASだからCPUがいらないというわけではない。正直、Mini-ITXのNASに載せるレベルのCPUでは何であろうが足りない。

今回の例では最も安いCeleronではなくPentiumを選択した。 性能差はそれほどないが、いくらかマシではある。

メモリは結構必要だ。Btrfsが結構なメモリを必要とするし、ZFSはもっと必要とする。 Btrfsなら16GB、ZFSなら32GBは欲しい。 もし、12TBディスクで構成するつもりならそれでも足りないかもしれない。 一応、16GBあれば普通の動作では問題はない。

今のMini-ITXマザーボードであればM.2スロットを持っているのが普通だ。 これによりSATAポートが制限されるかもしれないが、どのみちSATAポートは拡張カードで補うので、システムを別ディスクに分けられるほうが大きい。 NASとしては128GBもあれば十分だが、多少余らせておけば使いみちは広がる。

そして適合する電源を用意し、PCI Express接続のSATA3カードを用意する。

これで組み上げればNASハードウェアは完成だ。 もちろん、これはキット状態で、別途ディスクも必要になる。

システムの方針を決める

最大の決定はBtrfsにするか、ZFSにするか、である。

なぜこの2択なのか、だが、ローカルなFSで、なおかつ8ディスクにも及ぶ環境であれば、これ以外の選択肢はあまり賢いとは言い難い。

QNAPはBtrfsを遅い、不安定などと批判しているが、それははるか昔の話であって、まるで現実を見ていない。BtrfsについてはBtrfsを13年使ったのでその経験の話で解説した。

また、QNAPはスナップショットボリュームが同一のボリューム上にあるのは安全ではないと主張するが、これはあまり意味がない。QNAPのNASはmdによるdm-raidの上にLVMを構築している。 QNAPのスナップショットはLVMスナップショットだが、LVMのスナップショットはLVの一種であり、スナップショット元のLVとは同一のVG上にある。つまり、ディスクとしてもパーティションとしても同一のものの上にあるため、サブボリュームの一種となるBtrfsと安全性は変わらない。 違うとすれば、Btrfsがファイルシステムレベルであり、LVMがブロックデバイスレベルであるということだ。つまり、Btrfsはファイルシステムそのものが破損した場合、スナップショットもろともダメになるが、LVMではファイルシステムが破損しても大丈夫である。 その代わり、Btrfsでは起こり得ない「LVMの破損」というリスクをもう一枚増やしているとも言える。そしてそれは、そこまでありえないことではない。

また、LVMスナップショットは長期的に保存していけるようなものではない。 LVMのスナップショットは作成した瞬間には何も作らない。作成したあと、ブロックレベルでオリジナルのデータが変更されたら、変更される前のデータを保存する。つまり、スナップショットは大きくなっていく。負荷も大きい。

Btrfsのスナップショットは、一種のハードリンクのようなものである。スナップショットをとった後、変更を加えなければそれらは同じファイルであり、変更すれば別ファイルになる。100MBのファイルのうちの1バイトを変更した場合、100MB使用量が増加する。シンプルな分かなり扱いやすい。

また、QNAPはファイルシステム、LVM、あるいはQNAPシステム自体に問題が発生した場合に、リカバリーが非常に面倒である。LVMの知識を要求されるのも、かなりしんどい。

それでもLVMを好むというのなら止めはしないが、少なくとも私の考えとは相容れない。 10年くらいLVMとよろしくやっていたが、柔軟に運用したいホームシステムではなじまないと私は思っている。

なお、今回最終的に採用して紹介する方法では、単純にBtrfsでなくExt4やXFSを使う方法も選択可能だ。Btrfsのほうが無難だと思うが。

Experimentalなものを恐れないのならばHAMMER2を選択するというのもあるだろう。ただし、これはアプライアンスNASを避けたい理由と結局変わらないため、私としては推奨できない。

現実的に考えられるのは次のようなものだ。

  • Linux MD(RAID5)+Btrfs
  • Linux MD(RAID6)+Btrfs
  • Linux Btrfs RAID1
  • Linux Btrfs RAID10
  • Solaris ZFS RAID-Z
  • Illumos ZFS RAID-Z
  • FreeBSD ZFS RAID-Z

BtrfsでRAID5/6を選択するのは、安定性が求められる(データ損失させるわけにいかない)NASでは無理な話だ。 RAID1やRAID10は8台でやるのはしんどいだろうから、RAID5/6を使いたい。RAID-Zならraidz1あるいはraidz2だ。 8台でraidz3はやりすぎ感がある。

柔軟性でいえばBtrfsだが、ファイルシステム単独で信頼できるRAID5、あるいはRAID6を構築できるZFSにも魅力がある。 熱心に開発されているBtrfsのほうは最新を追いかけたいので、Linuxシステムを採用する場合は可変のシステムと考えたほうが良く、一方ZFSは最新を追いかけづらいため、ある程度枯れたシステムとして運用する方針になる。 これはもし仮にLinuxでZFSを使う場合でも同様である。

枯れたシステムにするのであれば、OpenIndianaのような更新しづらいシステムであっても最初に構築できればそんなに問題はない。

だが、個人的には最新の状態をキープしているほうが楽だと思う。 今回の場合、システムはM.2 SSD上に独立しているため、システムを作り直すことは困難ではない。 とはいえ、私なら結局はArchlinuxだ。

NASといえども、システムに何らかの調整を加えたいことはある。Rubyで書いたユーティリティを走らせたいことだってある。 結局、最新が維持されているほうが楽なのだ。

となれば、SSD上にArchlinuxを導入し、インストールされている全HDDをパーティションレスなmdデバイスとしてRAID5、あるいはRAID6を構築し、その上にBtrfs(meta single/data single)を構築する。 Btrfsからは1つのブロックデバイスにしか見えないため、meta mirrorできないのが痛いが、現状Btrfsでは解決し難い問題である。

また、NASに備わるような機能を賄う方法として、システム及びストレージの暗号化も行う。

基本システムのインストール

Archlinuxの基本インストール手順の「間に」必要な作業が挟まるので注意が必要。

まず、GPTでフォーマットされたM.2ディスクに2つのパーティションを切る。 1つ目はESPだから500MBくらいあれば十分。 また、swapを必要とする場合(必要であるはずだ)さらにもうひとつswapも切る必要がある。 ここでは/dev/nvme0n1を次のようなレイアウトにしたとする

パーティション番号 マウントポイント サイズ ファイルシステム
p1 /boot 512MB FAT32
p2 swap 32GB None
p3 / * None

Manjaroでは/boot/efiに切っている(最小限)が、面倒が少ないよう、/bootに切ることにした。

パーティションとファイルシステムの用意ができたら、暗号化デバイスを用意する。 今回、swapはハイバネーションをしない、ランダムなパスワードを使うものにするので、特に事前に何かをする必要はない。

p3に関してはLUKSを使うので準備が必要。 といっても難しいことではなく、

# cryptsetup luksFormat /dev/nvme0n1p3
# cryptsetup luksOpen /dev/nvme0n1p3 cryptroot
# mkfs.ext4 -L ArchNAS /dev/mapper/cryptroot

といった感じ。 システムパーティションはExt4にしたが、ここはお好みで良い。 システムスナップショットが欲しいならBtrfsもアリ。

また、ここで入力したパスフレーズと解除時のパスフレーズはキーボードレイアウトが異なる可能性がある。 ArchwikiではmkinitcpioのHOOKSとしてkeymapencryptより先に書けば良いとしているが、そうなっているManjaroでもUSレイアウトでの入力が必要だったりする。 この点に留意しておいたほうが良い。

ここまでできたらインストールの準備を始める。 /mntをインストールターゲットにするが、bootパーティションが必要になるので、その準備も必要。

# mount /dev/mapper/cryptroot /mnt
# mkdir /mnt/boot
# mount /dev/nvme0n1p1 /mnt/boot

あとは通常通りにインストールするが、通常のインストール作業が終わっても作業は終わりではないのでリブートしてはいけない。

インストールシステムの/etc/mkinitcpio.confHOOKSについて、blockの前にkeyboard keymapを、blockの後ろにencryptを入れる。 これができたら(インストールシステム上で)

# mkinitcpio -p linux

としてイメージを再生成する。 続いて/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULTに次のような記述を追加する。

creyptdevice=UUID=<DEVICE_UUID>:<MAPNAME> root=/dev/mapper/<MAPNAME>

DEVICE_UUIDはp3パーティションのUUIDで、blkidによって確認できる。 MAPNAMEはluksOpenの最後の引数に与える名称で、被らず、一致していればなんでも良い。

ここでひとつの話。 ReadyNASなんかは、キーファイルを使い、USBディスクで解除するようになっている。 この構成だとパスフレーズ入力がいるのでディスプレイレスで使うNASとしてはちょっとめんどくさいように思える。

しかしである。キーUSBを使う方法は、侵入者はキーUSBを発見すればデータにアクセスできるため、洗いざらい盗まれると暗号化は破られてしまうのだ。 そのため、安全とは言い難く、パスフレーズ入力のほうが私はおすすめできる。

続いて暗号化swapの準備だ。Archlinuxだと、/etc/crypttabにswapの行があるため、アンコメントしてデバイス名を書くだけ。 /dev/nvme0n1p2とか書くのは危険なので、UUIDを使うこと。

# <name>  <device>     <password>     <options>
cryptswap      UUID=00000000-aaaa-bbbb-cccc-xxxxxxxxxxxx    /dev/urandom   swap,cipher=aes-cbc-essiv:sha256,size=256

で、/etc/fstabにswapエントリを追加する。

/dev/mapper/cryptswap   swap      swap   defaults,noatime 0 2

これでブートしてシステムを起動できるようになった。 一回リブートしてインストールシステムで起動してから続きをしても良い。

ディスクの用意

まずキーファイルの準備。 /etc/secretがなければ作るところから。

# mkdir /etc/secret
# dd if=/dev/urandom of=/etc/secret/hdd.key.bin bs=512 count=8

blkidもしくはparted -lを用いてHDDのデバイスを確定させていく。ここでは/dev/sdaのような名前を使ってもいいが、/dev/disk/by-id/dev/disk/by-uuidを使うほうが安全。

そして、各ディスクに対してフォーマットしていく。

# cryptsetup luksFormat --key-file=/etc/secret/hdd.key.bin /dev/sda

すべてのディスクがフォーマットし終わったら、/etc/crypttabに全部のディスク分記載する。

# <name>  <device>     <password>     <options>
hdd1      UUID=00000000-1111-2222-3333-xxxxxxxxxxxx    /etc/secret/hdd.key.bin luks,nofail

nofailをつけてないと、ディスクがおかしくなったり、取り外したときに回復するのが困難になる。

ここで一旦再起動してすべてのディスクが暗号化され、また自動でオープンされるかを確認するのがおすすめ。

/dev/mapper/hdd*にオープンしたディスクが揃う状態になるので、RAIDを構成する。

# mdadm --create --verbose --level=5 --metadata=1.2 --chunk=512 --raid=devices=8 /dev/md0 /dev/mapper/hdd*

構成されたら設定ファイルを更新してアレイを構築。

# mdadm --detail --scan >> /etc/mdadm.conf
# mdadm --assemble --scan

構築まで完了したら、Btrfsを載せる。

# mkfs.btrfs -L MyCustomNAS /dev/md0

Btrfsをマウントする場所を作る。個人的には適当な場所がないので、/dskというディレクトリを作ってやっている。

# mkdir -p /dsk/nas

スナップショットを使うためにはサブボリュームが必要なので一旦マウントする。

# mount -o noatime,compress=lzo,nospace_cache /dev/md0 /dsk/nas

サブボリュームを作る。

# cd /dsk/nas
# btrfs subvolume create main

fstabに記載。こちらもnofailをつけないと面倒なことになる。 他は好み。HDDだとlzoつけたほうが高速な可能性が高い。

LABEL=MyCustomNAS    /dsk/nas    btrfs  noatime,compress=lzo,nospace_cache,subvol=main,nofail

これで完了。

サーバーセットアップ

再起動すれば単体で見ればNASとして稼働する状態になった。 一回pacman -Syuしてアップデートを済ませたら再起動すると良いだろう。 また、この際必要なパッケージは入れておくといい。vim, vim-plugins, zsh, grml-zsh-config, viあたりは入れておかないとしんどいパッケージだ。

最初にSSHをセットアップすると良い。さすがにbaseには入っていない(base-develには含まれている)ので導入が必要。

# pacman -S openssh
  • アドレス制御するのにIPv6だと面倒
  • 非力なCPUなので、AES-NIを使う
  • OpenSSHでのログインは基本禁止にする

という方針で/etc/ssh/sshd_configを設定。

AddressFamily inet
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
DenyUsers *

ローカルなアドレスからのみ公開鍵認証を受け付ける。

Match Address 192.168.0.0/16,10.0.0.0/8
  DenyUsers root
  AuthenticationMethods publickey

まだrootしかユーザーがいないので、機能しない設定だ。だが、一旦起動しておこう。

# systemctl start sshd
# systemctl enable sshd

ユーザーを作る。 PC側とUID, GID, ユーザー名を一致させておくことを強く推奨する。 一方、メンテナンスユーザーではないのでルート権限への道は与えない。

# useradd -U -m -s /bin/zsh john

メンテナンスユーザーも作っておく。他のシステムと重複しないようにしたほうが良い。

# useradd -u 2000 -g wheel -m maintainer

base-develを入れていないならsudoを入れて、visudo/etc/sudoersを編集、%wheelの部分をアンコメントする。これでmaintainerユーザーで入ればrootを使わずにメンテナンス作業ができるようになる。

maintainerにはそこそこ強固なパスフレーズを設定する。

# passwd maintainer

一般ユーザーも後々のことを考えるとちゃんとしたパスフレーズを設定しておいたほうが良い。

そして、PC側でSSH鍵を最低2つ生成しておく。maintainer用(パスフレーズ強固)とユーザーSFTP用(パスフレーズなし)である。なし、と言ったけれど、システムが暗号化されていない(起動時アクセスに制限がない)Windowsのようなシステムではちゃんと設定したほうがいい。 ユーザーのログインキーはあってもなくても良い。maintainersudo -u john zsh -lとかすれば良いからだ。

OpenSSHについての初歩的なところがわからない人は別記事にて。

もしユーザーPCが複数あるならそれぞれで鍵を生成し、NASに登録する必要がある。

さて、ここでなぜSSHのセットアップを優先するのかという話をしよう。

主には作業の快適性の問題である。 一般的に、こうしたサーバーをセットアップする段階で、完全な作業環境を構築することはない。 構築し終わったら、ディスプレイからも外して隅に置いてしまうことが多いから、仮置きの状態でしっかりとセットアップしたくないためだ。 そのため、コンピュータ自体の性能という意味も含めて、普段使っているPCから作業したほうが効率がいい。

また、今回の場合NASにXを入れていないので、vconsole上で作業することになるが、これが著しく快適性が低い。 ブラウザで情報を確認しながら、とか、manpage見ながら、ということもあるだろうから、ちゃんとXのある環境で作業したほうが良い。

そうした意味でSSHのセットアップができていれば作業が一気に楽になる。 これはクラウドの場合は必須になってくる。

また、SSHのセットアップさえできればSSHFSを使ってファイルアクセスもちゃんとできるようになるので、SSHさえ準備できればもう実用的な状態なのだ。

共有 with SSH

前述のとおり、ファイルアクセスはSSHFSを使うことで事実上、要求は完全に満たされる。

さて、まずはjohnユーザーの設定をしよう。 johnユーザーは管理者であるあなた自身である。あなたはどのPCでもjohnという名前のアカウントを使っているし1、データはjohn所有になっている。UIDは1000、GIDも1000である。

先にjohnユーザーのNAS用の鍵をつくり、それをauthorized_keysに登録する作業を済ませているはずだ。 johnはNASのストレージへのアクセスが全面的に可能だ。では準備しよう。

前提として、今まで何もいじっていないので、NASの/dsk/nasroot:root 755である。 これで良く、ここから変更してはならない。 その下にユーザーレベルで書くことができるディレクトリを用意する。

# mkdir /dsk/nas/local
# chown john:john /dsk/nas/local

続いて/etc/ssh/sshd_configにjohnのアクセスを記載しよう。 先程のMatchセクションよりも前に記載する必要がある。 ついでに条件ももう少し絞ろう。

Match User john Address 192.168.10.0/24
  AuthenticationMethods publickey
  ChrootDirectory /dsk/nas
  ForceCommand internal-sftp

これでjohnはSSHFSを使ってNASストレージをマウントできるようになった。むしろそれしかできない。 言っといてなんだが、私はroでSSHFSをマウントして、rrsyncでアップデートするという方式を取っているので、こういう制限はしていない。メインユーザーは普通にアクセスできるようにしていて、鍵パスフレーズも使っている。

Windowsの場合はなかなかめんどくさい。

基本的にはsshfs-winを使えば良い。 今までのものと比べれば画期的といっていいくらいには優れたソリューションだ。

しかし、OpenSSHを使わないこのソフトウェアはSSHFSとは比べ物にならないほど出来が悪い。 公開鍵認証は~/.ssh/id_rsaに決め打ちされている。 これは、「決め打ちされている」と「RSA固定である」で最悪だ。もちろん、~/.ssh/configもリスペクトしない。

パスワード認証を許す場合はこれでさほど問題がないのだが、脆弱なWindowsのために脆弱なシステム構成をするなど、セキュリティ意識がある人であれば許せない行いだ。

比較的マシな(?)ソリューションとしては、Windows側でOpenSSHの設定を済ませ、その上で

> ssh -N -L 2200:localhost:22 nas

とかやって接続を確立し、\\sshfs\localhost!2200に接続するという方法である。 localhostのSSH接続は常時パスワード認証が通せるので、無駄なSSH接続をもう一段(ループバックインターフェイスで)噛ませることでOpenSSHの認証を利用している。

だが、この場合SFTPのみという制約は機能しない。これだからWindowsは。

これに加えてさらなる別のユーザーの運用も考えてみよう。 それは、あなたの妹かもしれないし、Androidデバイスかもしれない。

mikanは文書ファイルにアクセスすることができるが、書き込み権限はない。 シンプルで、単に/dsk/nas/local/docにchrootすればいいだけに見えるが、ChrootDirectoryroot:rootなディレクトリである必要があるため、そうはいかない。

そこでmikan用のディレクトリを用意してあげよう。事前にusersグループは用意したとする。

# useradd -g users -m -s /bin/nologin -u 2500 mikan
# mkdir -p /srv/sftp/mikan/doc
# chown mikan:users /srv/sftp/mikan/doc

fstabにbindマウントを記載する。(この後即時マウントするにはmount /srv/sftp/mikan/doc) /dsk/nasのマウントより後にすること。

/dsk/nas/local/doc    /srv/sftp/mikan/doc    none    bind,nofail 0 0

mikan用のものを/etc/ssh/sshd_configにも書く。

Match User mikan Address 192.168.10.0/24
  AuthenticationMethods publickey
  ChrootDirectory /srv/sftp/mikan
  ForceCommand internal-sftp

続いてyuzuはストレージ全域に読み取り専用でアクセスでき、写真フォルダにアップロードすることもできる。

/dsk/nas/localjohn所有なので、yuzuユーザーを作ってそこに追加してやるだけでいい。

Match User john,yuzu Address 192.168.10.0/24
  AuthenticationMethods publickey
  ChrootDirectory /dsk/nas
  ForceCommand internal-sftp

写真フォルダにはyuzuがアップロードするスペースがある。そういうディレクトリを作れば良い。

# mkdir -p /dsk/nas/local/photo/yuzu
# chown -R john:john /dsk/nas/local/photo
# chown yuzu:root /dsk/nas/local/photo/yuzu

yuzuがアップロードしたところには他の人は見れないようにしたいなら、yuzu:root 700にすればいいだけだ。 管理者のあなたが見ないのは、紳士協定を結ぼう。

ponkanはAndroidデバイスである。Nova Video PlayerでNAS上の動画を視聴しようというわけだ。 Nova Video PlayerはSFTPアクセスができ、非常に便利だが、公開鍵認証の機能がない。 要領はmikanと同じだが、ponkanはパスワード認証を許すようにしないといけない。 そのため、アクセスできるディレクトリの内容はできるだけ制限するようにしよう。

Match User ponkan Address 192.168.10.0/24
  AuthenticationMethods password
  ChrootDirectory /srv/sftp/ponkan
  ForceCommand internal-sftp

bindマウントとパーミッションで可視性をコントロールするのは難しくないが、それを管理するのは割と大変になる。 このファイルは見えるけどこのファイルは見えない、なんてするのは大変なので、ちゃんとポリシーを作ってコントロールしたほうが良い。 だから、Windowsのアクセスのやわさを理由に制限する、なんてのは無駄な手間になるからしたくないところだ。

なお、私は「Windowsはセキュアでなくプライバシー的な意味でも信用できないので、Windowsからグローバルファイルにアクセスはさせない」というポリシーを採用している。そのため、Windowsからの共有で困ったことはない。 どうしても必要なら、SSHでログインしてLinux上でアクセスし、その結果をWindowsのディスプレイ上に出している。 音楽系のソフトウェアはeメールでリンクを送ってくることがすごく多いので、そのeメールにかかれているリンク(eメールへのアクセスもWindowsからはできないようにしている)をWindows上で取得するときなどにこの方法を使っている。

共有 with SMB/CIFS

私はWindowsでWindowsの共有を使ってファイルを共有したいと思ったことが一度もないので、それをする意味があるとも特に思わないけれど、どうしてもそんなことがしたい人はArchwikiを見ると良い。 NASをArchlinuxにしたので、解決策はすべてArchwikiにある。

デバイスやソフトウェアがSMB/CIFSのみをサポートしているという状況は普通に考えられるだろう。 このような場合には有効だ。 また、Windowsにおいて録画データを直接NASに書きたいというような場合にも有効である。

共有の方針についてだが、まずSMB/CIFSの認証プロセスはSSHのように堅固なものではない、ということを考えるべきだ。 これは件の「Windowsは」とかいう話ではなく、そもそもSSHは本当に堅固なセキュリティであり、これに匹敵する(これで実現可能なレベルの)セキュリティを確保する方法などないに等しい。

だから、SMB/CIFSに限った話ではなく、これがFTPだったりNFSだったりしても同じである。

SMB/CIFSファイル共有においては、ルートディレクトリは「共有ディレクトリルート」として常に存在するもので、SFTPにおけるChrootDirectory相当の動作をデフォルトで記述可能である。また、同設定のような制限もないため、すべてを共有するのではなく限定して共有することを前提に考えることが可能だ。

この場合、既存のディレクトリのコンテンツを共有するのならここまでと同様の方法でbindマウントを使ってもいいが、あくまでSMB/CIFS用の共有であるということなら、それ用にsubvolumeを切るというのも手。 ここらへんはより運用寄りの話になる。

ただ、現実的にはNASを共有するよりも、共有したいコンテンツをPC上に複製し、XDG PUBLIC Directoryに置いてNemo Shareなどで限定的にシェアするほうが扱いやすい。

その他の共有

DLNA

私の経験的にDLNA共有はあまり良い結果になっていないので、アドバイスできない。

Androidデバイスで動画を見たいからDLNAをためそう、というのは結構やったのだが、結局SFTPのほうが良い結果になっている。

FTP

FTPはクライアントが充実しているという利点があり、また難点であるセキュリティ面もLANにアクセスが限定されていればそれほど考慮しなくていいため悪くないが、一方でサーバーセットアップはそんなに楽ではなく、またFTP自体がアクセス効率がよくなく、ファイルシステムとしてアクセスするのにあまり適していない。

FTPユーザーがシステムユーザーに結びつくかどうかはサーバーソフトウェアによるが、管理は比較的細かく行うことができる。

トータルではあまりおすすめはしづらい。

NFSv4

アクセスそのものはUnixに最適化されており、Unix/Linux系プラットフォームでは適している、かのように思われる。

だが、実際はNFSはかなり問題が多く、扱いが楽ではない。うかつにシャットダウンしたら面倒なことになったりするし、SFTP(SSHFS/gvfs-sftp)以上にツリーにアクセスできないときが厄介だ。

最大の問題であるセキュリティはLAN内であれば問題は小さいが、意外と益が少ない。

AFP

AFP共有を有効にするにはNetatalkを使う。

/etc/afp.confを編集してnetatalk.serviceを有効にするだけなので結構簡単。 単純にファイル共有という意味ではMacからであってもSFTPのほうが便利だが、TimeMachineなど、Mac上の機能の利便性からAFPが使えると便利な場面もある、ようだ。 私はMac持ってないので知らないが。

WebDAV

クライアントの都合であれば使いどころが広がるWebDAV。 ローカルネットワーク内で必要となることは多くはないが、構築するのもアリな部類。

通常、Apacheを使う。 ファイルサーバーでNginxを使う理由はあまりないだろうから、Apacheを使えばいいと思うが、Nginxでもnginx-mainline-mod-dav-extを使って構築可能。 ただ、どちらかというと、Nginxをリバースプロキシとして、ApacheをWebDAV用に使ったほうが合理的。

限定的なインターフェイスによるアップロード管理

私のお仕事でよく扱う(というより例示する)ケースでは、家族が写真フォルダを共有するというものがある。 これが、単純に全ユーザー共有されている写真フォルダであるという意味であれば、単純に共有すれば良い。 つまり、familyグループを作って、写真フォルダをroot:family775にするということだ。

他の人がアップロードしたフォルダであっても編集(移動したりリネームしたり)できるようにしたいということであれば、写真フォルダに対してchrootする形で、誰が利用する場合でも同じユーザーでアクセスするようにすれば良い。

難しいのはアップロードすることはできるが、移動や削除などの編集はできないようにしたい場合だ。 その場合はそれ専用のインターフェイスを用意する必要がある。比較的簡単なのはrrsync -wo -no-delで使う方法だ。 ただし、rsyncでやる必要があるから、コマンドを打たなければならない問題と、Windowsではさらにハードルが高いという問題がある。

自作の良さを活かす

このNASは自作であるためにシステム面の縛りがなく、Archlinuxを導入することができている。 そのために、追加のソフトウェアの導入も楽で、自分が好きなように構成できる。

もしこのNASを常時起動している前提であれば、サーバーとしての動作が可能だ。 これくらいのシステムだと、HDDを含めてアイドル時100Wを超える程度。HDDの消費電力が小さくないこともあり、ちょっと悩んでしまうくらいだが、つけっぱなしも不可能ではない。

計算力がそれほど高くないサーバーを常時つけっぱなしにする意味というのは実のところ薄いが、通知サーバーとして使ったり、あるいはSystemd Timerを使って定期ジョブを実行したりするのに適している。 サーバーの活用方法というのは発想次第なので、考えれば使いみちもあるだろう。

だが、実のところ、私としては近年はあまりこのような常時稼働するサーバーの必要性を感じていない。

実際の話として、私はNASの他にストレージサーバーとしてProLaint Microserver(メモリ2GBで非常に性能が低いもの)と自作PC(A10-7870Kの、以前メインで使っていたもの)という2台を持っているのだが、その活躍度合いは「微妙」なのである。

A10のほうはかろうじてデスクトップとして使える程度、ProLiantはデスクトップ利用は現実的でない程度の性能だが、計算系の処理を任せるのは厳しすぎる。この2台は比較的静かで(A10のほうは最近随分うるさくなってしまったが)、バックグラウンドでの稼働をさせやすいほうではあるが、そのようなジョブ自体があまりないのだ。

通知サーバーのような役割は、昔であればかなり重要であった。wgetやcurlでステータスを取得して、必要であれば携帯電話にメールをしたり、あるいは音を鳴らして警告したりといった役割だ。 これは、友人や意中の人と掲示板やメールで連絡を取り合っていたような時代ではとても有効だったが、今であればメッセージングアプリ(私ならTelegramやDiscord)でメッセージをもらえばいいだけで、あまり意味がない。

仮に通知サーバーが必要になる要素があったとしても、VPSで賄うほうがずっと良い。ConoHa VPSの1ヶ月のミニマムの料金は682円で、これは普通のサーバーの1ヶ月の電気代よりも安い。

また、mmfft9のキューサーバーなどとして使うことも考えられるが、このような分散コンピューティングのキューサーバーを自宅で必要とする状況では、特に別途中央集権的なホストは必要としていなくて、そもそも一番処理能力の高いコンピュータは作業が終わるまでずっと回されるだろうということを考えると、そのホストにキューサーバーをもたせるほうが効率的なのだ。

唯一現実的に使っている方法として、A10はダウンロードジョブを任せることがある。 結構なデータ量のダウンロードが必要になったり、あるいはそもそも帯域があまりなかったりで長時間(数日)に渡ってダウンロードジョブを回さないといけないことがあり、なおかつそれをするために手元になんのデータがあるかを照合する必要があったりして、A10にまかせている。 これで数日に渡るジョブでPCが中断できないという事態を避けられる。「ダウンロード実行中だから原神がやれない」みたいなことを避けられるわけだ。

だが、A10がやっているタスクというのは本当にそれくらいで、ちょっと前まではリビングに置いてあって、Amazon prime videoを見たりYouTubeを見るのに使ったりもしていたが、現在はその役割は別のPCになったのでそれすらない。

ローカルサーバーの使いみちは、それぞれの想像力次第でなんでも、ではあるが、そもそもファイルサーバー以外のローカルサーバーの必要性は時代とともに減少している。

さらなる拡張

自作NASであるひとつのメリットとして、特にストレージを自身のみで構成する制約はない、ということが挙げられる。 事実、前述のA10とProLiantはその2台で合計12台のHDDを1つのストレージにしている。

この話をするとBtrfsのメリットが活きてくる。

方法はいくつか考えられ、これが考慮事項になる。

まず、前述の1台構成の場合、8台それぞれのDM CryptデバイスでひとつのMD RAIDであり、1ブロックデバイスのBtrfsを構成した。 ここではこれにリモートブロックデバイスがはさまる。選択肢はNBD, iSCSI, AoEだが、AoEはBtrfsがうまく動作しないので、現実的にはiSCSI一択である。

そして、iSCSIを使うとして現実的にはおおまかに2通りの方法がある。

  • それぞれのホストでLUKS+RAID5を編成し、RAIDデバイスをiSCSIで配信、ホストあたり1つのブロックデバイスとしたBtrfsを作る
  • それぞれのホストで生デバイス、またはLUKSデバイスをiSCSIで編成し、すべてのディスクからなるRAIDを編成、1つのブロックデバイスからなるBtrfsを作る

後者の方法をとるにはすべてのホストのディスクが同じ容量である必要がある。 そのかわり、全ディスクを通じて1台だけのパリティディスクという編成が可能。

個人的には前者のほうがおすすめだ。Btrfsは問題なく異なる容量のデバイスで利用でき、singleの場合でも複数のデバイスに公平に配分される。

なお、RAIDにしない場合や、RAID1または10で良い場合は生デバイス、またはLUKSデバイスを配信し、それらをBtrfsで使えば良い。

「誰がLUKSを持つべきか」は処理能力による。 LUKSは当然ながら暗号化処理であるため、そこで計算力が求められる。そのため、あまりにも暗号計算能力が低いホストではアクセス速度を低下させる要因にもなる。 だが、これは単純にCPUパワーだけで考えられるわけではない。 ArchlinuxではLUKSのデフォルトのCipherはaes-xts-plain64である。つまり、AES256, SHA256, /dev/urandomが利用される。 このうちAES256部分についてはAES-NIが効くため、必ずしもプロセッサパワーが重要であるとは限らない。 ただ、SHA256の計算は軽いものではないため、あまりに非力なプロセッサではここがボトルネックになる可能性もある。

また、通常の起動シーケンスでは/etc/crypttabによるdm-cryptの処理、及び/etc/mdadm.confによるdm-raidの処理はiSCSIイニシエータの処理よりも先にくるため、iSCSIで配信されるのが生デバイスやLUKSデバイスである場合、オープンからマウントまでの処理、およびアンマウントからクローズまでの処理はスクリプトで書くなどする必要がある。

ローカルキャッシュ

過去の記事でちらっと言っているが、私はローカルキャッシュSSDを使う運用にしている。

これは、NASを常時使うわけではなく、よく使うデータ(音楽とか、見てる途中のビデオとか)を置いておいたり、処理中のデータを置いておいたりするものだ。 2.5インチのSATA SSDを使っていて、ワークルームのメインPCでは2TB、寝室のPCでは1TBを使っている。 このほか、2TBのUSB SSDもある。

特に書き込み時の一時置き場としては不可欠でReadyNASのトラブルと、その中身に踏み込むで述べたようにHDDにランダム書き込みをするとHDDの消耗も激しいし、パフォーマンスも落ちるからできるだけシーケンシャルにしたい。 そこで、完成したデータになるまでローカルキャッシュのSSD上に置くようにして、データがリードオンリーで十分な状態になったらrsync/rrsyncを使ってアップロードする。

私がworldと呼んでいるストレージ系は64TBの容量があるのだが、これだけデータがあればアクセスには強い局所性がある。 だからよく使うデータは手許に置いておけば、常時NASを起動させておく必要がない(電力的にも、HDDの寿命的にも大きい)し、アクセスも速くて快適。

私のローカルキャッシュは手動運用で、以前は自作のFUSE-FSで処理していたのだが、「アクセスに基づくキャッシュ」だと必要としているのが分かりきっているのにNASなしでは動作しない(音楽フォルダなら既に再生した曲しかないから)ということが多いので手動のほうがよかった。

書き換えの多いデータについては基本的にローカルキャッシュでもなくシステムディスク上に置いていて、複数マシンで複製して冗長性をもたせている。 方法は基本的にはクラウドドライブによる同期か、Mercurialである。 「いつまで経っても書き換えの激しいデータ」というのはだいぶ限定的なので、これは特に困らない。