Linux, MacOS: NFS/Autofs 설정

NFS 에 관한 글은 이전에도 몇번 쓴 적이 있는데, 이 글은 리눅스와 맥OS(iOS 포함) 를 아울러 총정리하는 글이 되겠다. 이전에 쓴 글에서, 가능한한 MacOS 에서는 Samba 를 사용하는 편이 낫겠다고 했었다. 지금도 그 의견엔 동의한다. 단, GUI 파일 관리자의 기능을 쓰지 않고 Autofs 등을 사용한다는 전제가 필요하긴 하다.
우분투 18.04 이하에선 시험은 안해봤지만, 삼바 smb2 프로토콜을 사용하면, 리눅스 파일 매니저에선 삼바 서버에 접근을 하지 못했었다. MacOS Finder 에선 어떤지는 모르겠다.
그러나, 이 문제는 (아마도) Autofs 로는 충분히 해결이 가능하므로, 삼바를 쓴다면 이 방식을 권하고 싶다. (누구한테?)

이 글에선, MacOS 를 기준으로, 리눅스 NFS 서버에 접근하는 방식을 정리해본다. 리눅스에선 별 신경을 쓰지 않아도 잘 연결이 된다.

NFS 와 UID/GID

NFS 사용 시 가장 신경써야 할 부분은, 내가 접속하려는 서버의 UID 와 내 PC 의 UID 가 같아야 한다는 점이다.
사실, 서버/클라이언트 UID 가 ‘같아야 한다’라기 보다는, ‘접속한 서버의 디렉토리 접근권한이 있을 경우에만 읽고 쓰기가 가능하다’라고 표현해야 더 맞을 듯 하다.
보통 리눅스에서는, 기본 사용자의 UID 로 1000을 부여한다. NFS 로 접속한 디렉토리도, UID 1000 을 가진 사용자에게 접근 권한이 주어졌을 때만 읽고 쓰기가 가능해진다. 서버도 리눅스고, 클라이언트도 리눅스면 이게 전혀 문제가 되지 않는다.
물론, 사용자가 다수가 되면 조금은 복잡한 방식을 취해야 하겠으나(아래에 서술할 방법이 약간은 이런 방식이다.), 개인이 쓸 때는 아무런 문제가 없다.

다만! MacOS 를 사용하고, NFS 에 ‘읽기’만이 아니라 ‘쓰기’까지 해야 한다면, 다소 복잡한 설정이 필요해진다.
MacOS 는, 아래에도 언급되어 있지만, 기본 사용자의 UID 가 501 이다. 따라서 이 상태로 NFS 에 접속한다면, UID 1000 이 생성한 파일들을 자유롭게 사용할 수가 없다.
그럼, NFS 서버에서 해당 디렉토리의 소유권을 501 로 바꾸면 되지 않을까? 물론 그래도 된다. 그러나 그렇게 되면, 리눅스 기기로 그 NFS 에 접근했을 때는 똑같은 권한 문제가 발생하게 된다.

이 미묘한 문제를 해결하기 위해, 사람들은 여러가지 편법을 사용하는 모양이다.
몇가지 방법을 소개해보자면 이렇다.

MacOS 에서, UID 1000 을 갖는 사용자를 새로 만든다.
  -> 왜 그런지는 모르지만, MacOS 로그인 화면에 사용자가 제대로 표시되지 않는다. 로그인하려면 사용자 ID 를 입력해줘야 한다. 사용에는 별다른 문제는 없는 듯 하다.

NFS 서버에서, anonuid=1000,anongid=1000 설정을 준다.
 -> 가장 인기있는(?) 해결 방법.

새로운 그룹을 만들고, setgid 로 그룹 허가권을 준다?
  -> 이 글에서 사용해볼 방법!


/etc/exports 형식/선택사항 설명

다른 설명에 앞서, 먼저 가장 기본이라 할 수 있는 /etc/exports 의 형식 및 선택사항에 관해 정리하고자 한다.

기본 형태는 다음과 같다.

# 형식
서버디렉토리 접근가능IP영역(선택사항)

# 실제 적용예
/storage/nfs 192.168.100.0/27(rw,root_squash,no_subtree_check,async,insecure)

접근 가능 IP 영역은 CIDR 형식으로 써주는게 좋다. 다른 글에서도 언급했지만, 여기서 서브넷을 살짝 조정함으로 보안(?) 효과를 노릴 수도 있다. 아니면, /etc/hosts.deny 에 명시하는 방법도 있겠다. hosts.deny 는 그렇게 좋은 방법은 아니라고들 하지만..

rw :
읽고 쓰기가 가능하게 설정.

root_squash :
이게 man page 에는 이렇게 ‘어렵게’ 쓰여져 있다.

Map requests from uid/gid 0 to the anonymous uid/gid. Note that this does not apply to any other uids or gids that might be equally sensitive, such as user bin or group staff.

uid/gid 0 은, root 의 uid 이다. 이걸 이제야 알았다.
문자 그대로 해석하면, ‘uid/gid 가 0 이라면, 이걸 anonymous uid/gid 로 바꾼다.’ 라는 뜻이 된다. 이건 또 뭔 얘기?
다시 풀어보면 이렇다. 이렇게 설정하면, nfs 디렉토리에 root 는 ‘쓰기’가 불가능한 상태가 된다는 뜻이다. 읽기는 가능하지만(Permission 에 따라 다르긴 해도), 쓸 수는 없다.
이로 인해 문제가 하나 있긴 했는데..

no_subtree_check:
이건 설명을 봐도 뭔 얘긴지 알 수가 없다. 그냥 이렇게 쓰라는게 권장사항이라 생각하련다.

async:
역시 자세한 사항은 알 수 없는데, 이렇게 쓰면 조금 더 원활하게 사용할 수 있다고 하니, 그래야지 뭐.

insecure:
리눅스/맥OS/iOS 만 사용하면 이 부분은 없어도 된다.
오직 Android, 그 중에서도 nPlayer 를 위한 선택사항.

참고로, secure 로 설정했다면, macOS 에선 mount 시에 resvport 를 넣어줘야만 한다.

VPN 을 사용한다면?

nfs 서버를, VPN 으로 연결한 후에도 사용한다면, 위 설정만으로는 부족하다.
Bridged VPN 이라면 문제가 없겠지만, Wireguard 처럼 LAN 영역과 다른 대역으로 VPN IP 가 부여된다면, NFS 접근은 원천 차단된다.

예를 들어, 위의 예처럼 서버 영역은 192.168.100.0/27 인데, VPN 으로 부여받은 IP 는 10.0.0.0/24 라면, 10.0.0.0/24 구간에서는 192.168.10.0/27 로 접근을 하지 못한다. ping 이나 ssh 는 VPN 에서 설정하기에 따라서 자동 Routing 이 되지만, nfs 는 그렇질 못하다.

이를 위해서, /etc/exports 에 두 네트웍 환경 설정을 모두 넣어줘야 한다.

# 형식
디렉토리 LAN대역(옵션) VPN대역(옵션)

# 실제 용례
/storage/nfs 192.168.100.0/27(rw,root_squash,no_subtree_check,async,insecure) 10.0.0.0/24(rw,root_squash,no_subtree_check,async,insecure)

NFS 서버(리눅스/Debian 계열) 설정: anonuid=1000 사용

예전에 쓴 글 참고. 다만, MacOS/iOS 를 위해 선택사항 부분은 조금 달리해줘야 한다.
또, IP/Subnet 은 192.168.1.0/24 로 해도 되고, 적절한 서브넷을 넣어주면 된다.
만약 서브넷이 달라지면 당연히, 접속이 불가능하게 된다.

또는, 특정 주소만 지정할 수도 있다. 192.168.0.2 에는 이런 설정, 192.168.0.3 에는 저런 설정. 등등.

/etc/exports
...
# MacOS 용
/mnt/NFS_Share/test_dir 192.168.1.0/255.255.255.0(rw,root_squash,no_subtree_check,anonuid=1000,anongid=1000,async,insecure)

# Linux 용
/mnt/NFS_Share/test_dir 192.168.1.0/255.255.255.0(rw,root_squash,no_subtree_check,async,insecure)

MacOS, 특히 iOS 를 위해 insecure 를 추가했다. 이걸 붙이지 않을 경우, MacOS 에서 마운트 할 때는 resvport 를 붙여줘야 한다.
anonuid, anongid 의 역할은, Client 의 UID/GID 가 무엇이든, 1000 으로 강제하게 한다. 이 부분이 없다면, MacOS 에서 소유권 문제가 발생하여 파일 접근이 어려워진다.
리눅스에선 대부분 이 값은 필요없으나, 클라이언트의 UID 가 1000 이 아니라면 넣어줄 필요가 있다.

MacOS 클라이언트에서 마운트는 이런 식으로 한다.
(MacOS Finder 에서 마운트를 할 수도 있는데, nfc 옵션을 줄 수가 없기에 한국어 사용에 문제가 생긴다.)

sudo mount -t nfs -o rw,nfc,resvport,intr,soft,proto=tcp,rwsize=65536,retrans=3,nfsvers=3,locallocks 192.168.0.51:/mnt/NFS_Share/test_dir  /private/nfs-test-group/

그런데, iOS, 더 정확히 nPlayer 에서는 resvport 선택사항을 붙여줄 수가 없다. (그 결과 연결이 되지 않는다.) 따라서, iOS(nPlayer) 에서도 NFS 를 사용하고 싶다면, 서버에 insecure 를 반드시 추가해줘야 한다.
— nPlayer 는 insecure 를 붙이지 않아도 제대로 인식하고 잘 작동한다.
다시 말해, 서버 설정에 insecure 가 없다면 클라이언트에 resvport 를 붙인다. 서버 설정에 insecure 가 있다면 클라이언트에 resvport 를 붙이지 않는다.

선택사항 간단한 설명

  • nfc : 한국어를 사용하려면 반드시 필요
  • resvport : /etc/exports 에서 insecure 를 하지 않았을 경우 필요
  • proto=tcp : udp 가 아닌 tcp 로 연결하도록 설정
  • rwsize : MacOS 에서 마운트할 때는 이 값이 필요. 리눅스는 없어도 최대값으로 된다고 어디선가 본 듯도..? 실제로 쿠분투에서 값을 달리해서 큰 파일을 복사해봤으나 설정 안했을 때와 65536 일 때가 거의 같았다.
  • nfsvers = 3 : NFS3 을 사용하게함. NFS4 는 MacOS 에서 lock 의 문제가 있다.
  • locallocks : MacOS 에서만 필요. 이 값이 없으면 Finder 에서 열었을 때 제대로 반응하지 않거나, 아예 열리지 않거나, 반응 속도가 상당히 느려지는 문제가 있다. CLI 로만 작업할 때는 이런 문제가 없는 듯도 하다.

이렇게 설정하면 MacOS 에서 사용할 때도 큰 문제는 없다. 다만, Finder 에서 정렬이 이상해지는 문제는 있고, 어딘지 모르게 애매한 상황이 발생하기도 한다.
그러나, 이 설정이 간단히 쓰기 위한 최선의 방법이라 여겨진다.

그런데, anonuid=1000,anongid=1000 의 의미는 무엇일까?
이건, NFS 로 접속한 사용자의 UID/GID 를 무시하고, 무조건 1000 으로 간주하라는 뜻이 된다. 저게 없다면, NFS 접속 디렉토리에서 파일을 생성했을 때 그 파일은 UID 501 의 소유가 된다. 그러나, anonuid=1000 이 있을 경우, 생성된 파일은 1000 의 소유가 된다. UID/GID 1000 이 MacOS 내에 있든, 없든 관계가 없다.

anonuid=1000, anongid=1000 으로 인해, UID 501 인 사용자도 저 디렉토리를 맘대로 읽고, 쓸 수가 있게 된다.

locallocks 는 또 어떤 역할을 하게 되나?
리눅스 클라이언트는 GUI 환경에서도 마운트된 NFS 디렉토리를 열었을 때 아무런 문제가 없는데, MacOS 파인더로 NFS 디렉토리를 열면 오작동이 발생한다. 파일을 열었을 때 바로 반응이 오지 않고 몇십초쯤 지연이 생긴 후에 열린다거나, 간혹 마운트가 끊겨버리기도 한다. locallocks 를 붙여주면 이런 현상이 사라진다.

.DS_Store files 생성 방지

MacOS 는, 각 디렉토리에 .DS_Store 라는 파일을 만든다. 여러가지 정보를 담고 있는 파일이라는데, 네트웍 디렉토리에는 굳이 필요하질 않은 듯 하다.
이 파일의 생성을 막기 위해 다음 명령을 내려준다.

defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE

그나마 간편하게 사용하려면 여기서 만족하면 된다.
아래는.. 그저 괜한 치기(稚氣)랄까. 또는 지식과 노동력 낭비랄까.
아니면, 불타는 학구열(學究熱)일지도.


NFS 서버(리눅스/Debian 계열) 설정: setgid 사용.

이 방법에서는, 서버와 각 클라이언트에 공통으로 존재하는 그룹(nfs 라 가정)을 만들어놓고, 그 그룹에 SGID 를 설정하여, 사용자가 아닌 그룹으로 소유권을 해결하려고 한다.

/etc/exports 설정은 위와 같다.

# Linux 용
/mnt/NFS_Share/test_dir 192.168.1.0/255.255.255.0(rw,root_squash,no_subtree_check,async,insecure)

여기에, 서버에서 파일 하나를 더 손봐줘야 한다.

/etc/default/nfs-kernel-server 설정

이 부분도 역시 MacOS 를 위한 설정이다. Linux 계열에선 별 무리가 없는 듯 하다.
일단 저 파일을 열고, RPCMOUNTDOPTS=" --manage-gids" 항목을 주석처리한다. 그래야 NFS 클라이언트에서 무리없이 작동이 된다.

이게 뭐에 관련된 내용일까? 정확한 지식이 없어서 내용 파악은 불가하다. 게다가, 이 옵션을 붙이는 게 맞는 건지, 아니면 이 옵션 자체가 버그 처리된 건지에 대한 의견도 있다. (우분투 관련 버그리포트 페이지에 이런 내용이 있다.)
다만, 무식한 와중에 추측을 해보면 이렇다. MacOS 사용자는 보통 20여개가 넘는 그룹에 참가를 하게 된다. MacOS 에서 id 명령을 내리면 이런 결과가 나온다.

$ id
uid=501(macuser) gid=20(staff) groups=20(staff),2001(nfs),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),704(com.apple.sharepoint.group.4),706(com.apple.sharepoint.group.6),707(com.apple.sharepoint.group.7),708(com.apple.sharepoint.group.8),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),703(com.apple.sharepoint.group.3),705(com.apple.sharepoint.group.5),702(com.apple.sharepoint.group.2)

이 중, nfs 는 후술할 nfs 그룹이니, 그것을 뺀다고 해도 총 가입 그룹수는 22개가 된다. 헌데, nfs 는 가입 그룹 수에 16개까지 제한이 있다고 한다. (man page 를 읽어봐도, 정확히 무슨 내용인지는 모르겠다.)
아무튼, 적어도 데비안 계열 nfs 에서는 저 설정을 빼줘야 MacOS 에서 제대로 작동한다. 리눅스 클라이언트도, 만약 그룹이 16개를 넘어가면 조정이 필요할런지도 모르겠다. 우분투의 경우, 기본 가입 그룹은 8개 정도 밖에 되지 않는다.

여기까지 완료했으면, 이제 공통으로 사용할 그룹을 만들 차례다.
이 그룹은 nfs 를 사용할 모든 컴퓨터에서 만들어줘야 한다. 서버, 클라이언트(들) 모두.

GID 를 지정하여 그룹 만들기

# MacOS
sudo dscl . -create /Groups/nfs gid 2001
(GUI '사용자 및 그룹'에서 그룹을 먼저 만들고, 고급 옵션에서 GID 를 변경해도 된다.)

# Linux
sudo groupadd nfs -g 2001

해당 그룹에 사용자 추가하기

# MacOS
GUI 로, '시스템 환경설정' - '사용자 및 그룹' - 왼쪽 하단 '그룹'에서 nfs 를 택하고, 원하는 사용자 추가.

# Linux (NFS 서버, NFS 클라이언트 모두)
usermod -a -G groupname username
ex>
sudo usermod -a -G nfs userX

꼭 GID 가 2001 일 필요는 없다. 모든 시스템에서 비어있는 GID 를 택하면 된다.

디렉토리 소유권(Ownership) 및 권한(Permission) 변경

이 작업은 NFS 서버에서 해준다.

# 소유권 변경
sudo chown 1000:2001 /mnt/NFS_Share/test_dir

# 권한 변경 (디렉토리만 찾아서 setgid 권한 부여)
sudo -i
find /mnt/NFS_Share/ -type d -exec chmod 2775 {} \;

# macOS 에선 umask 도 수정해야 한다.(우분투는 기본이 002 이다.)
sudo launchctl config user umask 002

setgid 에 관해서는 예전에 쓴 글 우분투; 디렉토리 공유(setgid) 참고.

** chmod -R g+s ??
그냥 이렇게 하면 안되나?? 라고 생각했다면 큰 오산이다.
이렇게 되면, 모든 ‘파일’을 찾아 그룹에 setgid 설정을 한다. setgid 설정이 필요한 곳은 ‘디렉토리’이지 ‘파일’이 아니다.
만약, 저런 실수를 했다면  chmod -R g-s 를 해서 원상태로 돌아온 뒤, 다시 위의 find 명령을 내려줘야 한다.

서버 작업 끝.
이제 위에 있는 mount 명령을 사용하여 NFS 에 연결하면.. 큰 문제는 없이 Finder 에서도 파일을 읽고 쓸 수 있다.

** MacOS 에서 문제가 있다면?
아직 긴 시간 사용해본 게 아니라서 정확하지는 않으나, Finder 에서 NFS 디렉토리를 열고 작업하다보면, 하위 디렉토리 파일을 열었을 때 Finder 디렉토리가 상위로 이동하는 경우가 있다. 예를 들어, Finder 에서 /nfs/aaa/bbb/ccc.txt 파일을 열었는데, Finder 는 /nfs/aaa/bbb/ 에 머물러 있는 게 아니고, /nfs/aaa 로 디렉토리를 이동하기도 한다.
감수해야할 문제로 보인다.

** KDE Dolphin 에선 setgid 가 무시된다?
터미널에서 cp 명령을 쓸 때나, mc 로 복사 시, 또는 GUI 로 Double Commander 를 쓸 때는 잘 되는데, 돌핀으로 복사를 하면 원 그룹이 그대로 유지가 된다. 물론, 파일을 새로 생성을 하면 setgid 가 제대로 작동을 하긴 하는데..
다른 환경(Gnome, Xfce 등등)에선 시험해보지 못해 모르겠다.

……
그런데, 이렇게 쓸 때마다 mount 명령을 수동으로 내려줘야 하나??
물론, 그렇지 않다. Linux 에서건, MacOS 에서건, 자동으로 마운트되게끔 설정해줄 수가 있다. GUI 환경 파일관리자인 Nautilus(Gnome) 나, Dolphin(KDE Plasma) 등엔 이 비슷한 기능이 내장되어 있긴 한데, ‘자동’으로 되지는 않고, 사용자가 마운트를 명시(해당 디렉토리를 클릭함으로써)해줘야 하는 불편함이 있다.
이 불편함을 해소하려면, Autofs 를 사용하면 된다.

어쨌든, 서버 설정은 이제 끝이다.
이제 클라이언트 설정이 남아있다.


우분투 클라이언트용 Autofs 설정

우분투 계열에서는 위 글 설정대로하면 별 무리가 없다.

MacOS 클라이언트용 Autofs 설정

따로 설치할 필요는 없다. 기본 설치가 되어 있다.
필요한 파일은 두가지다.
/etc/auto_master, /etc/auto_xxx.
이 중, auto_master 는 기본 파일이고, auto_xxx 파일은 사용자 필요에 따라 생성하는 파일이다. 이름도 마음대로 지어줄 수 있다.

/etc/auto_master
# Automounter master map
#
+auto_master		# Use directory service
/net			-hosts		-nobrowse,hidefromfinder,nosuid
/home			auto_home	-nobrowse,hidefromfinder
/Network/Servers	-fstab
/-			-static

# 위 내용은 기본값이고, 아래를 추가한다.
/nfs autofs_nfs

/nfs 는 MacOS 에서 /nfs 디렉토리를 NFS 용 디렉토리로 사용하겠다는 뜻이다.
autofs_nfs 는, /etc/autofs_nfs 파일에 NFS 관련 내용을 모두 넣겠다는 의미다. 이렇게 따로 파일을 만들지 않고, /etc/auto_master 파일에 해당 내용을 넣어도 된다.

/etc/autofs_nfs

Dir1 -fstype=nfs,rw,nfc,intr,soft,proto=tcp,rwsize=65536,retrans=3,nfsvers=3,dsize=65536,locallocks 192.168.0.55:/mnt/House/Dir1
Dir2 -fstype=nfs,rw,resvport,nfc,intr,soft,proto=tcp,rw,resvportsize=65536,retrans=3,nfsvers=3,dsize=65536,locallocks 192.168.0.55:/mnt/House/Dir2

....

맨 앞의 Dir1 은 MacOS 의 /nfs/Dir1 을 뜻한다. fstype=nfs 는 네트웍 프로토콜을 nfs 를 사용하겠다는 의미고, 이하는 mount -o 사용시 선택사항과 동일하다.
물론, 마운트 포인트인 /nfs/Dir1, /nfs/Dir2 등은 미리 만들어져 있어야 한다.

**
원래는 /nfs/Dir1 -fstype=nfs,.... 이렇게 작성하고 /etc/auto_master 에 추가해야 하지만, 파일을 하나 만들어서 그 안에 해당 내용을 넣을 수도 있다.
이걸 전문 용어(?)로는 Direct/Indirect 방식이라고 한다는데..

어찌됐든, 이 정도면 큰 어려움없이 MacOS 에서도 리눅스 NFS 서버를 사용할 수 있다.
Samba 를 쓴다면, -fstype=nfs 대신, -fstype=cifs 로 하고, 적절한 옵션을 넣어주면 (아마도) 잘 되리라… (되기야 하겠지만, 또 다른 꽃삽질이 기다리고 있을 지도 모르겠다.) 

쓰기 싫어(?) 억지로 몸을 배배꼬며 쓴 글이라 여기저기 구멍이 있을 수도 있다. 혹여라도 누군가 이 글을 보고 따라할 생각이라면.. 뭔가 제대로 작동하지 않을 수도 있다는 걸 염두에 두시길.

3 Comments
  1. Avatar
    • 아무도안

안녕하세요. 글 남겨주셔서 고맙습니다.