NFS

提供: ArchWiki
2024年4月19日 (金) 18:34時点におけるKusanaginoturugi (トーク | 投稿記録)による版 (→‎サーバー設定: 英語版より記事を追加)
ナビゲーションに移動 検索に移動

関連記事

Wikipedia より:

Network File System (NFS) はローカルストレージにアクセスするのと同じようにネットワーク上のファイルにクライアントコンピュータでアクセスできるようにする分散ファイルシステムおよびそのプロトコルである。1984年に Sun Microsystems によって開発された。
ノート:
  • NFS は暗号化されません。機密情報を扱うときは KerberosTinc などの暗号化プロトコルを使って NFS をトンネル化してください。
  • Samba とは異なり、NFS にはデフォルトでユーザー認証がありません。クライアントのアクセスは IP アドレスやホストネームで制限します。
  • NFS では、クライアントとサーバーの両方で ユーザー および/または ユーザーグループ ID が同じであることを期待しています(Kerberos を使用していない場合)。#idmapping を有効化するか、/etc/exportsanonuid/anongidall_squash を一緒に使用して UID/GID を手動で上書きしてください。
  • NFS は POSIX ACLs をサポートしていません。NFS サーバーは引き続き ACL を強制しますが、クライアントはそれらを見たり変更したりすることができません。

インストール

クライアントとサーバーどちらでも必要なのは nfs-utils パッケージのインストールだけです。

ノート: クライアント・サーバーの時計を一致させるために全てのノードで時刻同期デーモンを使うことが強く推奨されます。全てのノードで時計が正確でないと、NFS は望ましくない遅延を生じさせる可能性があります。NTP システムを使ってサーバーとクライアントの両方をインターネット上の正確な NTP サーバーに同期させることが推奨されています。

サーバー設定

NFS サーバーにはエクスポート (共有ディレクトリ) のリストが必要で、/etc/exports に定義します。/etc/exports に定義する NFS 共有はいわゆる NFS ルートからの相対パスになります。セキュリティ上、NFS ルートを定義するときはサーバーのルートファイルシステム下の専用のディレクトリツリーを使用して、ユーザーからマウントポイントへのアクセスを制限すると良いでしょう。バインドマウントを使用して共有マウントポイントから実際のファイルシステム上のディレクトリにリンクします。

下の例では以下の設定を使用します:

  1. NFS ルートは /srv/nfs
  2. エクスポートは /srv/nfs/music/mnt/music にバインドマウントする。
# mkdir -p /srv/nfs/music /mnt/music
# mount --bind /mnt/music /srv/nfs/music

サーバーを再起動してもマウントされるように、バインドマウントを fstab に追加:

/etc/fstab
/mnt/music /srv/nfs/music  none   bind   0   0
ノート:
  • NFS にはサーバーのファイルシステムのパーミッションが適用されるため、接続するユーザーに適当な権限があることを確認してください。
  • ZFS ファイルシステムの場合、バインドマウントの使い方が特殊です。ZFS#バインドマウントを見てください。

CIDR によるアドレス指定またはホストネームを使ってマウントを許可するクライアントマシンを制限するには /etc/exports に以下のように共有ディレクトリを追加:

/etc/exports
/srv/nfs       192.168.1.0/24(rw,fsid=root,crossmnt)
/srv/nfs/music 192.168.1.0/24(rw) # Use whatever export options you see fit

サーバー実行中に /etc/exports を変更した場合は再度エクスポートしないと変更が適用されないので注意してください:

# exportfs -rav

利用可能なオプションについて詳しくは exports(5) を参照してください。

ヒント: IP の範囲を CIDR 表記に変換するツールとして ip2cidr が存在します。
ノート: エクスポート先が tmpfs ファイルシステムの場合、fsid=1 オプションが必要です。

Custom export root

Shares may be relative to the so-called NFS root. A good security practice is to define a NFS root in a discrete directory tree which will keep users limited to that mount point. Bind mounts are used to link the share mount point to the actual directory elsewhere on the filesystem. An NFS root used to be mandatory for NFSv4 in the past; it is now optional (as of kernel 2.6.33 and nfs-utils 1.2.2, which implement a virtual root).

Consider this following example wherein:

  1. The NFS root is /srv/nfs.
  2. The export is /srv/nfs/music via a bind mount to the actual target /mnt/music.
# mkdir -p /srv/nfs/music /mnt/music
# mount --bind /mnt/music /srv/nfs/music
ノート: ZFS filesystems require special handling of bindmounts, see ZFS#Bind mount.

To make the bind mount persistent across reboots, add it to fstab:

/etc/fstab
/mnt/music /srv/nfs/music  none   bind   0   0

Add directories to be shared and limit them to a range of addresses via a CIDR or hostname(s) of client machines that will be allowed to mount them in /etc/exports, e.g.:

/etc/exports
/srv/nfs        192.168.1.0/24(rw,fsid=root)
/srv/nfs/music  192.168.1.0/24(rw,sync)
/srv/nfs/home   192.168.1.0/24(rw,sync)
/srv/nfs/public 192.168.1.0/24(ro,all_squash,insecure) desktop(rw,sync,all_squash,anonuid=99,anongid=99) # map to user/group - in this case nobody

When using NFSv4, the option fsid=root or fsid=0 denotes the "root" export; if such an export is present, then all other directories must be below it. The rootdir option in the /etc/nfs.conf file has no effect on this. The default behavior, when there is no fsid=0 export, is to behave the same way as in NFSv3.

In the above example, because /srv/nfs is designated as the root, the export /srv/nfs/music is now mountable as MyServer:/music via NFSv4 – note that the root prefix is omitted.

ヒント:
  • For NFSv3 (not needed for NFSv4), the crossmnt option makes it possible for clients to access all filesystems mounted on a filesystem marked with crossmnt and clients will not be required to mount every child export separately. Note this may not be desirable if a child is shared with a different range of addresses.
  • Instead of crossmnt, one can also use the nohide option on child exports so that they can be automatically mounted when a client mounts the root export. Being different from crossmnt, nohide still respects address ranges of child exports. Note that the option is also NFSv3-specific; NFSv4 always behaves as if nohide was enabled.
  • The insecure option allows clients to connect from ports above 1023. (Presumably only the root user can use low-numbered ports, so blocking other ports by default creates a superficial barrier to access. In practice neither omitting nor including the insecure option provides any meaningful improvement or detriment to security.)
  • Use an asterisk (*) to allow access from any interface.

It should be noted that modifying /etc/exports while the server is running will require a re-export for changes to take effect:

# exportfs -arv

To view the current loaded exports state in more detail, use:

# exportfs -v

For more information about all available options see exports(5).

ヒント: ip2cidr is a tool to convert IP address ranges to correctly structured CIDR specifications.
ノート: If the target export is a tmpfs filesystem, the fsid=1 option is required.


サーバーを起動する

nfs-server.service起動有効化してください。

その他

任意のサーバー設定

高度な設定オプションは /etc/nfs.conf で設定できます。単純な構成の場合はファイルを編集する必要はありません。

特定のインターフェイスあるいは IP からのアクセスに NFS を制限

デフォルトでは nfs-server.service を起動すると /etc/exports とは関係なく全てのネットワークインターフェイスから接続を待機します。待機する IP あるいはホストネームを定義することで挙動を変更できます:

/etc/nfs.conf
[nfsd]
host=192.168.1.123
# Alternatively, you can use your hostname.
# host=myhostname

変更を適用するには nfs-server.service再起動してください。

NFSv4 の ID マッピングが有効になっていることを確認

idmapd が動作していても、マッピングが完全には有効になっていないことがあります。/sys/module/nfsd/parameters/nfs4_disable_idmappingN になっている場合、以下のコマンドを実行することで有効にできます:

# echo "N" | sudo tee /sys/module/nfsd/parameters/nfs4_disable_idmapping

変更を永続化するにはモジュールオプションで設定してください:

/etc/modprobe.d/nfsd.conf
options nfsd nfs4_disable_idmapping=0

ファイアウォール設定

ファイアウォールを通過してアクセスできるようにするには、デフォルト設定の場合 tcp と udp のポート 111, 2049, 20048 を開放する必要があります。rpcinfo -p を使ってサーバーで使用しているポートを確認してください。この設定を iptables でするには、/etc/iptables/iptables.rules を編集して以下の行を含めるようにしてください:

/etc/iptables/iptables.rules
-A INPUT -p tcp -m tcp --dport 111 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 2049 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 20048 -j ACCEPT
-A INPUT -p udp -m udp --dport 111 -j ACCEPT
-A INPUT -p udp -m udp --dport 2049 -j ACCEPT
-A INPUT -p udp -m udp --dport 20048 -j ACCEPT

NFSv3 と、上記の rpc.statdlockd の固定ポートを使用している場合は、それらも設定に追加してください:

/etc/iptables/iptables.rules
-A INPUT -p tcp -m tcp --dport 32765 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 32803 -j ACCEPT
-A INPUT -p udp -m udp --dport 32765 -j ACCEPT
-A INPUT -p udp -m udp --dport 32803 -j ACCEPT

v4 以上だけを使う構成の場合、開く必要があるのは tcp ポート 2049 だけです。したがって、必要な行は一行だけになります:

/etc/iptables/iptables.rules
-A INPUT -p tcp -m tcp --dport 2049 -j ACCEPT

変更を適用するために、iptables サービスを再起動してください。

クライアント設定

NFSv4 で Kerberos を使用する場合、nfs-client.target起動有効化する必要があります。rpc-gssd.service が起動します。しかしながら、glibc のバグ (FS#50663) が原因で、現在 rpc-gssd.service は起動に失敗します。サービスに "-f" (foreground) フラグを追加することで起動できます:

# systemctl edit rpc-gssd.service
[Unit]
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStart=
ExecStart=/usr/sbin/rpc.gssd -f

Linux からマウントする

NFSv3 の場合、次のコマンドを使ってサーバーのエクスポートされたファイルシステムを表示:

$ showmount -e servername

NFSv4 の場合、root NFS ディレクトリをマウントして利用できるマウントを確認:

# mount server:/ /mountpoint/on/client

そしてサーバーの NFS エクスポートルートは省略してマウント:

# mount -t nfs -o vers=4 servername:/music /mountpoint/on/client

マウントが失敗する場合はサーバーのエクスポートルートを含めて見て下さい (Debian/RHEL/SLES では必須、ディストリビューションによっては -t nfs ではなく -t nfs4):

# mount -t nfs -o vers=4 servername:/srv/nfs/music /mountpoint/on/client
ノート: サーバーの名前は (IP アドレスではなく) ホストネームを指定する必要があります。それ以外だとリモート共有がハングアップします。

/etc/fstab を使う

クライアントを立ち上げたときにいつでも NFS 共有が使えるように、常に稼働させているサーバーでは fstab を利用すると便利です。/etc/fstab ファイルを編集して、設定に合わせて適切な行を追加してください。また、サーバーの NFS エクスポートルートは省略します。

/etc/fstab
servername:/music  /mountpoint/on/client  nfs   rsize=8192,wsize=8192,timeo=14,_netdev 0 0
ノート: マウントオプションについては nfs(5)mount(8) を参照してください。

マウントオプションの説明は以下の通り:

rsize と wsize
rsize はサーバーから読み込むときに使用されるバイト数の値です。wsize はサーバーに書き込むときのバイト数の値です。どちらもデフォルトは 1024 ですが、8192 などと値を高く設定することでスループットを改善できます。この値は汎用ではありません。値を変更した後にテストを行うことを推奨します、#パフォーマンスチューニングを見てください。
timeo
timeo は RPC タイムアウトの後に再送信を行うまで待機する時間の値です (10分の1秒単位)。最初にタイムアウトした後、再試行する度にタイムアウトの値は2倍になっていき、最大60秒になるか正式なタイムアウトになります。遅いサーバーやトラフィックの多いネットワークに接続する場合、このタイムアウトの値を増やすことでパフォーマンスが改善されるかもしれません。
_netdev
_netdev オプションは共有をマウントする前にネットワークが立ち上がるまで待機するようシステムに通知するオプションです。systemd は NFS がこのオプションを使うことを想定していますが、どんな形式のネットワークファイルシステムであれ、このオプションを使うことはグッドプラクティスと言えます。
minorversion
NFS バージョン 4.1 の Windows Server 2012 (Essentials) の共有をマウントするときは minorversion=1 を使います。
ノート: 6番目のフィールド (fs_passno) をゼロ以外の値に設定すると予期しない挙動が発生することがあります。例えば systemd で自動マウントしたときにチェックの待機が行われなくなります。

systemd で /etc/fstab を使う

systemd の automount サービスを使う方法もあります。接続が遮断されたり、復帰した時に素早くネットワークデバイスを再マウントするため、_netdev よりも好ましいと思われます。さらに、autofs の問題も解決します、下の例を見て下さい:

/etc/fstab
servername:/home  /mountpoint/on/client  nfs  noauto,x-systemd.automount,x-systemd.device-timeout=10,timeo=14,x-systemd.idle-timeout=1min 0 0

systemd が fstab の変更に気づくようにクライアントを再起動する必要があります。もしくは、systemd をリロードして mountpoint-on-client.automount を再起動して /etc/fstab の設定を再読み込みしてください。

ヒント:
  • 上記の noauto はアクセスされるまで NFS 共有をマウントしません: いますぐに利用できるようにしたいときは auto を使って下さい。
    ネットワークが立ち上がってなかったり利用できないことが理由でマウントが失敗する問題が発生するときは、NetworkManager-wait-online.service有効にします: このサービスは有効化される前に network.target の全てのリンクが利用可能になることを保証します。
  • users マウントオプションはユーザーによるマウントを許可しますが、noexec などのオプションも含まれているので注意してください。
  • x-systemd.idle-timeout=1min オプションは NFS 共有が1分間使われなかったときに自動的にアンマウントします。ネットワークから突然切断する可能性があるノートパソコンなどで有用です。
  • NFS のせいでシャットダウンや再起動に時間がかかってしまうときは、NetworkManager-wait-online.service有効化して NFS ボリュームがアンマウントされる前に NetworkManager が終了しないようにしてください。それでもシャットダウンが長すぎる場合 x-systemd.requires=network.target マウントオプションを追加してみてください。
ノート: サーバーでも同じ方法で systemd で NFS 共有を自動マウントすると、データの量が多かった場合にフリーズする可能性があります。

autofs を使う

複数のマシンを NFS で接続したい場合は autofs を使うのが便利です。サーバーだけでなくクライアントにもなることができます。他の簡単な方法よりもこの方法が推奨される理由は、サーバーの電源が落とされた時に、クライアントがNFS 共有を見つけられないことについてエラーを投げないからです。詳しくは autofs#NFS ネットワークマウント を見て下さい。

ヒントとテクニック

パフォーマンスチューニング

NFS の性能を完全に発揮するには、ネットワーク設定にあわせて rsizewsize マウントオプションを調整する必要があります。

最近の Linux カーネル (2.6.18 以上) ではメモリの容量によって NFS サーバーが使用できる I/O のサイズ (最大ブロックサイズ) が変わります。最大は 1M (1048576バイト) で、NFS クライアントがより大きな rsizewsize を必要としている場合でもサーバーの最大ブロックサイズが使われます [1]nfsd を起動する前に /proc/fs/nfsd/max_block_size に書き込むことでサーバーのデフォルト最大ブロックサイズを変更できます。例えば、以下のコマンドは昔のデフォルトの IO サイズであった 32k に設定します:

# echo 32767 > /proc/fs/nfsd/max_block_size

変更を永続化するには systemd-tmpfile を作成してください:

/etc/tmpfiles.d/nfsd-block-size.conf
w /proc/fs/nfsd/max_block_size - - - - 32768

systemd-networkd で共有を自動マウント

systemd-networkd を使っている場合、起動時に nfs がマウントされないことがあります。以下のようなエラーが表示されます:

mount[311]: mount.nfs4: Network is unreachable

解決方法は簡単です。systemd-networkd-wait-online.service有効化して、ネットワークが完全に設定されるまで待機するように systemd を設定してください。サービスが平行して起動しなくなるので起動時間は多少長くなります。

自動マウントの処理

ローカルのワイヤレスネットワークから nfs 共有を使う必要があるノートパソコンでこの設定は役に立ちます。nfs ホストが到達できない状態になったとき、nfs 共有はアンマウントされ、hard マウントオプションを使っている際にシステムフリーズが起こらなくなります。https://bbs.archlinux.org/viewtopic.php?pid=1260240#p1260240 を参照。

NFS のマウントポイントが /etc/fstab に正しく記述されていることを確認してください:

/etc/fstab
lithium:/mnt/data          /mnt/data         nfs noauto,noatime,rsize=32768,wsize=32768 0 0
lithium:/var/cache/pacman  /var/cache/pacman nfs noauto,noatime,rsize=32768,wsize=32768 0 0

noauto マウントオプションは起動時に自動的に共有をマウントしないように systemd に命じます。これを設定していないとネットワーク上に共有が存在するかどうかわからないのに systemd が共有をマウントしようとしてブート中にブランクスクリーンで止まってしまいます。

root 以外のユーザー user で NFS 共有をマウントするには fstab にエントリを追加する必要があります。

cron を使って NFS ホストが到達可能なチェックする auto_share スクリプトを作成:

/usr/local/bin/auto_share
#!/bin/bash

function net_umount {
  umount -l -f $1 &>/dev/null
}

function net_mount {
  mountpoint -q $1 || mount $1
}

NET_MOUNTS=$(sed -e '/^.*#/d' -e '/^.*:/!d' -e 's/\t/ /g' /etc/fstab | tr -s " ")$'\n'b

printf %s "$NET_MOUNTS" | while IFS= read -r line
do
  SERVER=$(echo $line | cut -f1 -d":")
  MOUNT_POINT=$(echo $line | cut -f2 -d" ")

  # Check if server already tested
  if [[ "${server_ok[@]}" =~ "${SERVER}" ]]; then
    # The server is up, make sure the share are mounted
    net_mount $MOUNT_POINT
  elif [[ "${server_notok[@]}" =~ "${SERVER}" ]]; then
    # The server could not be reached, unmount the share
    net_umount $MOUNT_POINT
  else
    # Check if the server is reachable
    ping -c 1 "${SERVER}" &>/dev/null

    if [ $? -ne 0 ]; then
      server_notok[${#Unix[@]}]=$SERVER
      # The server could not be reached, unmount the share
      net_umount $MOUNT_POINT
    else
      server_ok[${#Unix[@]}]=$SERVER
      # The server is up, make sure the share are mounted
      net_mount $MOUNT_POINT
    fi
  fi
done

スクリプトに実行権限を付与:

# chmod +x /usr/local/bin/auto_share

cron エントリか systemd タイマーを作成して、共有サーバーにアクセスできるか1分ごとに確認するようにしてください。

Cron

# crontab -e
* * * * * /usr/local/bin/auto_share

systemd/タイマー

以下のユニットを作成:

# /etc/systemd/system/auto_share.timer
[Unit]
Description=Check the network mounts

[Timer]
OnCalendar=*-*-* *:*:00

[Install]
WantedBy=timers.target
# /etc/systemd/system/auto_share.service
[Unit]
Description=Check the network mounts

[Service]
Type=simple
ExecStart=/usr/local/bin/auto_share

作成したら auto_share.timer有効化してください。

systemd で起動時にマウント

systemd のユニットファイルを使って起動時に NFS 共有をマウントすることも可能です。クライアントに NetworkManager がインストール・設定されている場合はユニットファイルは必要ありません。#NetworkManager dispatcher を見て下さい。

/etc/systemd/system/auto_share.service
[Unit]
Description=NFS automount
After=syslog.target network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/auto_share

[Install]
WantedBy=multi-user.target

auto_share.service有効化してください。

NetworkManager dispatcher を使う

上で説明している方法に加えて、ネットワークの状態が変わった時にスクリプトを実行するよう NetworkManager を設定することもできます。

NetworkManager-dispatcher サービスを有効化・起動してください。

ネットワーク状態の変化にあわせてネットワーク上の共有をマウントする一番簡単な方法は auto_share スクリプトにシンボリックリンクを作成することです:

# ln -s /usr/local/bin/auto_share /etc/NetworkManager/dispatcher.d/30-nfs.sh

ただし、特定の場合では、ネットワーク接続が無効になった後にアンマウントが実行され、KDE Plasma アプレットがフリーズしたりすることがあります。

以下のスクリプトを使うことでネットワーク接続が切れる前に NFS 共有を安全にアンマウントすることができます:

/etc/NetworkManager/dispatcher.d/30-nfs.sh
#!/bin/bash

# Find the connection UUID with "nmcli con show" in terminal.
# All NetworkManager connection types are supported: wireless, VPN, wired...
WANTED_CON_UUID="CHANGE-ME-NOW-9c7eff15-010a-4b1c-a786-9b4efa218ba9"

if [[ "$CONNECTION_UUID" == "$WANTED_CON_UUID" ]]; then

    # Script parameter $1: NetworkManager connection name, not used
    # Script parameter $2: dispatched event
    
    case "$2" in
        "up")
            mount -a -t nfs4,nfs
            ;;
        "pre-down");&
        "vpn-pre-down")
            umount -l -a -t nfs4,nfs >/dev/null
            ;;
    esac
fi

スクリプトに実行可能属性を付与:

# chmod +x /etc/NetworkManager/dispatcher.d/30-nfs.sh

/etc/NetworkManager/dispatcher.d/pre-down にシンボリックリンクを作成して pre-down イベントをキャッチ:

# ln -s /etc/NetworkManager/dispatcher.d/30-nfs.sh /etc/NetworkManager/dispatcher.d/pre-down.d/30-nfs.sh

上記のスクリプトは別の接続で別の共有をマウントするように修正することができます。

NetworkManager#dispatcher を使って CIFS 共有のマウントを処理を参照。

トラブルシューティング

NFS/トラブルシューティングを参照してください。

参照