はじめに

この記事は、Linux サーバ間で NFS 共有フォルダをマウントしているものの、「cp: cannot create regular file '...': Permission denied」や「rsync: mkstemp failed: Operation not permitted (1)」といったエラーでファイルがコピーできずに困っているシステム管理者・エンジニアを対象にしています。
記事を読み終えると、NFS の「権限エラー」の本質的な原因である UID/GID の不一致を見極め、idmapd・anonuid/anongid・Squash 設定を正しく調整して、マウント先にスムーズにファイルをコピーできるようになります。

前提知識

  • Linux の基本コマン(mount, cp, rsync, chmod, chown)が使える
  • /etc/exports での NFS エクスポート設定経験
  • UID/GID、chmod ビット、mask 計算の意味をある程度理解している

なぜ NFS だけ「パーミッション denied」が出やすいのか

NFS(Network File System)は、サーバ側のファイルシステムを「まるでローカルディスクのように」見せるプロトコルです。しかし、「見せ方」は UID/GID の数字そのまでなため、次の 2 つの条件が揃うと書き込めなくなります。

  1. クライアント側のユーザー UID ≠ サーバ側の所有者 UID
  2. サーバ側で「all_squash」や「root_squash」が有効で、匿名 UID(通常は 65534=nobody)に強制されている

結果、クライアント側で root や一般ユーザーがファイルを作成しようとしても、サーバ側では「nobody」として処理され、ディレクトリのパーミッションが 755 だと書き込めず「Permission denied」が出るというわけです。

切り分けから解決まで:実践編

ステップ1:現状の UID/GID を確認する

まず、クライアントサーバの両方で、操作したいユーザーと共有ディレクトリの所有者を確認します。

Bash
# クライアント側 $ id kazu uid=1005(kazu) gid=1005(kazu) groups=1005(kazu) # サーバ側 $ id kazu uid=2005(kazu) gid=2005(kaz) groups=2005(kazu) $ ls -ld /export/share drwxr-xr-x 2 kazu 2005 4096 Jun 1 14:00 /export/share

この例では、UID が 1005 ≠ 2005 で不一致です。これが「コピーできない」根本原因です。

ステップ2:サーバ側の /etc/exports を読み解く

次に、サーバ側のエクスポート設定を確認しましょう。

/export/share 192.0.2.0/24(rw,async,no_subtree_check,all_squash,anonuid=99,anongid=99)
  • all_squash:「誰が来ても匿名ユーザーに強制」
  • anonuid/anongid=99:匿名ユーザーを 99(nobody)に固定

この状態でクライアントが「kazu(UID1005)」として接続しても、サーバ側では「UID99」で書き込もうとするため、ディレクトリの owner が 2005 では書き込めない、という構図です。

ステップ3:ID マッピングデーモン(idmapd)を使う(推奨)

UID/GID の数字を揃えられない場合(大規模 LDAP 環境など)は、ID マッピングで解決します。

  1. サーバ・クライアント両方で /etc/idmapd.conf を編集
[General]
Domain = local.domain

[Mapping]
Nobody-User = nobody
Nobody-Group = nogroup
  1. サービスを再起動
Bash
# CentOS/RHEL sudo systemctl restart nfs-idmapd # Ubuntu/Debian sudo systemctl restart nfs-common
  1. /etc/exportsall_squash を外し、代わりに root_squash のみ残す
/export/share 192.0.2.0/24(rw,async,no_subtree_check,root_squash)
  1. マウントし直すと、クライアント UID1005 → サーバ UID1005 のまま接続できるため、書き込み可能になります。

ステップ4:数字を揃えるのが早い場合(小規模環境)

LDAP や中央認証を使っていない小規模環境なら、UID/GID を単純に揃えるのが最速です。

Bash
# サーバ側 $ sudo usermod -u 1005 kazu $ sudo groupmod -g 1005 kazu $ sudo find /export -user 2005 -exec chown -h 1005:1005 {} \;

マウントし直して cp してみると、今度はエラーなくコピーできます。

ステップ5: Squash 設定を見直す(root 書き込みが必要な場合)

バックアップスクリプトなど、root で書き込みたいケースでは、以下のどちらかを選びます。

  • セキュリティ重視:root_squash 維持+ anonuid=0(root)にして、root に書き込ませる
  • 完全信任:no_root_squash 設定(LAN 内のみ推奨)
# 例:no_root_squash(完全信任)
/export/share 192.0.2.0/24(rw,async,no_subtree_check,no_root_squash)

ハマりポイント:マウントオプション「vers」も影響する

NFSv4 以降では ID マッピングが必須ですが、クライアントが「vers=3」でマウントしていると idmapd が効かないことがあります。マウントオプションを見直しましょう。

Bash
$ sudo mount -t nfs -o vers=4,sec=sys server:/export/share /mnt

解決策まとめ

  1. UID/GID の不一致を「id コマンド」で可視化する
  2. /etc/exportsall_squashanonuid/anongid の組み合わせを見直す
  3. 大規模環境 → idmapd 利用、小規模環境 → UID/GID 揃える
  4. root 書き込みが必要 → no_root_squash または anonuid=0
  5. 念のため NFS バージョン(vers=3/4)も確認

まとめ

本記事では、Linux で「NFS マウント先にファイルがコピーできない」問題の真の原因である UID/GID の不一致を特定し、

  • idmapd を使った ID マッピング
  • UID/GID 数字揃え
  • all_squash / root_squash / no_root_squash の使い分け

という 3 パターンの解決策を紹介しました。
正しく設定すれば、今まで「Permission denied」で断念していたバッチもバックアップも、スムーズに動作します。

次回は「NFSv4 + Kerberos 認証」でセキュアな環境を構築する方法を解説予定です。

参考資料