Комьюнити, привет.
В продолжение темы по организации сетевого доступа решил поэкспериментировать с протоколом NFS, актуальность которого сложно переоценить в контексте linux окружения selfhosted сервисов на наших хомлабах.
Идея была в том, чтобы для уже существующих сетевых директорий на базе протокола samba настроить параллельный доступ через NFS протокол, тем самым получить преимущества NFS для linux окружения и удобство доступа для остальных ОС.
Краткое содержание:
- Настройка директории в Proxmox и монтирование в LXC с NFS-сервером
- Настройка NFS-сервера в привилегированном LXC
- Настройка подключения сетевой директории к клиентской машине на базе Proxmox c возможностью монтирования в unprivileged LXC контейнер
Версии ПО:
PVE 9.0.10
nfs-kernel-server 1:2.8.3-1
nfs-common 1:2.8.3-1
Общая схема того, что будем реализовывать

Требования к рабочей среде
- Установка NFS-server возможна только в хостовую ОС гипервизора или в привилегированный LXC
- При установке в привилегированный LXC необходимо внести изменения в конфигурационный файл LXC с хоста PVE /etc/pve/lxc/ID_LXC.conf (ID_LXC - id вашего LXC)
2.1 Открыть в редакторе:
nano /etc/pve/lxc/ID_LXC.conf
2.2 Добавить строку:
lxc.apparmor.profile: unconfined
где
unconfined- отключение системы контроля доступа AppArmor, контейнер получает почти полный доступ к хосту.
2.3 Разрешить запуск LXC внутри контейнера.
features: nesting=1
где
nesting- обеспечивает возможность создавать пространства имён для обеспечения запуска терминала, без этого терминал работать не будет.
Настройка директории в Proxmox и монтирование в LXC с NFS-сервером
Исходим из того, что у вас уже создан привилегированный LXC контейнер, подключен диск к гипервизору PVE и создан storage. В моём случае это жёсткий HDD_USB_1Tb смонтированный в качестве Directory, который я полностью отдал под нужды сетевого хранилища (NAS).
- Создать директорию
mkdir -p /mnt/HDD_USB_1Tb/share - Изменить владельца дирекории
chown 101000:101000 /mnt/HDD_USB_1Tb/share
где
101000:101000- uid и gid соответствующий будущему пользователю nfs 1000:1000 в LXC (uid_proxmox=uid_lxc+100000, gid_proxmox=gid_lxc+100000) - Изменить права дирекории
chmod 2775 /mnt/HDD_USB_1Tb/share
где
2- это setgid, все новые файлы и подкаталоги, созданные внутри такого каталога, наследуют группу родительского каталога (для порядка и предупреждения возможных проблем)
775- полный доступ для владельца директори (первый бит7) и группы (второй бит7), а для всех остальных пользователей только чтение (последний бит5). - Проверить
ls -lh
drwxrwsr-x 8 101000 101000 4.0K Nov 4 21:39 share - Смонтировать директорию в LXC с будущим NFS-сервером (выполнить в Proxmox)
pct set ID_LXC -mp0 /mnt/HDD_USB_1Tb/share,mp=/mnt/share
где:
ID_LXC- ID вашего LXC с NFS-сервером
-mp0- точка монтирования (если к LXC уже примонтированы другие директории, то указывается любой свободный номер точки монтирования -mp1, -mp2, …)
При монтировании получите предупреждение:
explicitly configured lxc.apparmor.profile overrides the following settings: features:nesting
Его можно игнорировать (профиль apparmor игнорирует опцию nesting, которая установлена для работоспособности консоли в привилегированном LXC).
Настройка NFS-сервера в привилегированном LXC
Справка
Если требуется контроль доступа к сетевой директории посредством владельца и группы, то на NFS-сервере должны быть созданы 1 к 1 (uid, main gid, secondary gid) все пользователи, которые будут подключаться со стороны клиентов. Таким образом NFS-сервер будет сверять подключившегося клиента со списком известных ему пользователей и предоставлять соответствующий доступ. В противном случае NFS-сервер отнесёт любого клиента в категорию other, даже если у него будет членство в группе (
в случае, если группа добавлена, как вторичная группа).
Пример:
Разрешения сетевой NFS-дирекории:
drwxrwsr-x 8 101000 101000 4.0K Nov 4 21:39 share
- Неизвестный NFS-серверу клиент получит разрешения на чтение и запись, соответствующие группе 101000(owner):
uid=3000(test) gid=101000(owner) groups=101000(owner),3000(test)
Эксперименты показали, что сервер может сопоставить основную (main gid) группу неизвестного ему пользователя с группой в директории и в случае совпадения будут применены соответствующие разрешения. - Неизвестный NFS-серверу клиент будет отнесён в other и получит разрешение только на чтение, т.к. на NFS-сервере не создан точно такой же пользователь с идентичным набором uid и gid:
uid=3000(test) gid=3000(test) groups=3000(test),101000(owner)
Эксперименты показали, что сервер не может сопоставить вторичные группы для несуществующего на сервере пользователя.
Для наглядности визуализировал, как это работает:
Настройка
- Установить NFS-сервер в LXC:
apt install nfs-kernel-server -y - Проверить статус службы nfs-server:
systemctl status nfs-server
Если возникает ошибка nfsdctl: lockd configuration failure, то это указывает на то, что не запущен вспомогательный демон блокировок (rpc.statd или nfs-lockd), который используется для NFSv3-блокировок.
Для NFSv4 он не критичен, можно проигнорировать, но лучше включить сервис для совместимости:
systemctl enable --now nfs-blkmap.service rpc-statd.service - Настроить конфигурацию NFS-сервера /etc/exports
3.1 Открыть в редакторе
nano /etc/exports
3.1 добавить строку
/mnt/share 192.168.1.0/24(rw,sync,no_subtree_check,root_squash,fsid=1)
где
192.168.1.0/24 - сетевой доступ для всей подсети (если ваши сетевые настройки отличаются, то укажите актуальную для вас подсеть), при необходимости можно ограничить и указать IP конкретного клиента (доступ с других адресов будет запрещён)
rw - разрешение на запись и чтение (при наличии соответствующих разрешений у сетевой директории и прав у пользователя)
sync - сервер записывает изменения на диск немедленно (без кэша). Безопаснее, но чуть медленнее.
no_subtree_check - отключает проверку “подкаталогов”. Ускоряет работу и снижает ошибки при доступе к поддиректориям.
root_squash - преобразует root-клиента в nobody UID (65534). Защита от суперпользователя.
fsid=1 - File System ID, уникальный ID для каждого экспортирумой дирекории (обязательно при NFSv4 без общего корня). Для каждого нового экспорта fsid должен быть уникальным (fsid=2, fsid=n..).
3.2 Вариант настройки с общим доступом для всех пользователей
/mnt/share
192.168.1.0/24(rw,sync,no_subtree_check,root_squash,all_squash,anonuid=101000,anongid=101000,fsid=2)
где
all_squash — все пользователи на клиентах маппятся в одного анонимного пользователя
anonuid=101000, anongid=101000 — UID и GID, от имени которых будут работать все пользователи (
критично наличие на NFS-сервере пользователя с uid 101000 и основной группой gid 101000, которые должны совпадать с uid и gid директории 2775 101000:101000)
4. Применить настройки
exportfs -ra
5. Перезагрузить службу
systemctl restart nfs-server
6. Проверить текущий список экспортируемых каталогов
exportfs -v
Настройка подключения сетевой директории к клиентской машине на базе Proxmox c возможностью монтирования в unprivileged LXC контейнер
Справка:
- В качестве клиента будет выступать другой сервер Proxmox
- Конечный клиент - непривилегированный LXC
Настройка в Proxmox
- Создать директорию
mkdir -p /mnt/share - Установить NFS-клиент:
apt install nfs-common -y - Проверить наличе NFS-клиента
dpkg -l | grep nfs-common
ii nfs-common 1:2.8.3-1 amd64 NFS support files common to client and server
- Смонтировать сетевую NFS-директорию через /etc/fstab
4.1 Открыть в редакторе
nano /etc/fstab
4.2 Добавить строку
IP_NFS_SERVER:/mnt/share /mnt/share nfs4 rw,vers=4.2,hard,timeo=600,retrans=2,rsize=1048576,wsize=1048576,_netdev,x-systemd.automount 0 0
где
IP_NFS_SERVER - IP-адрес NFS-сервера
rw - разрешение на запись и чтение (при наличи прав соответствующих прав у пользователя)
vers=4.2 - используется NFS версии 4.2
hard - при потере соединения клиент ждёт восстановления сервера, не выдаёт ошибку (безопасно для данных, но процессы зависнут - не запустится lxc или повиснет терминал при попытке доступа к директории. При необходимости может быть заменено на soft, но есть риск потери данных, если в момент записи данных nfs-директория станет недоступной)
timeo=600 - (600×0.1=60 сек) время ожидания перед повтором запроса (чтение/запись)
retrans=2 - gосле 2 неудачных попыток выдаёт сообщение об ошибке, но при hard не размыкает монтирование
rsize=1048576 - размер блока чтения 1 МБ, увеличивает пропускную способность сети при чтении (оптимально для современных клиентов и сетей ≥ 1 Gbps)
wsize=1048576 - размер блока записи 1 МБ, аналогично для записи
_netdev - Systemd подождёт поднятия сети перед монтированием
x-systemd.automount - точка монтируется по первому обращению, не блокируя загрузку системы
0 0 - не проверять fsck, не включать в dump
6. Смонтировать
mount -a
7. Смонтировать директорию в непривилегированный LXC
pct set ID_LXC -mp0 /mnt/share,mp=/mnt/share
где
ID_LXC - ID вашего непривилегированного LXC контейнера
Настройка непривилегированного LXC
- Создать пользовтеля с одноимённой основной группой
useradd -M -u 1000 nfs
где
-M- не создавать домашний каталог
$ whoami
nfs
$ id nfs
uid=1000(nfs) gid=1000(nfs) groups=1000(nfs)
- Проверить возможность записи в директорию /mnt/share
4.1 Заменить текущего root-пользователя в LXC на созданного nfs
su - nfs
4.2 Создать тестовый файл и директорию в директории share
mkdir -p /mnt/share/nfs_test
touch /mnt/share/nfs_test.txt
4.3 Проверить
ls -n /mnt/share
total 4
drwxr-sr-x 2 1000 1000 4096 Nov 6 23:48 nfs_test
-rw-r--r-- 1 1000 1000 0 Nov 6 23:48 nfs_test.txt
Пользователь nfs имеет uid и gid равные аналогичным uid владельца и gid группы, соответственно имеет полные права (2775)
Для эксперимента попробуем создать файл из под пользователя root в LXC
root@nfs-test:~# touch /mnt/share/nfs_test.txt
touch: cannot touch '/mnt/share/nfs_test.txt': Permission denied
Пробуем прочитать директорию из под root-пользователя
root@nfs-test:/mnt# ls -n /mnt/share/
total 4
drwxr-sr-x 2 1000 1000 4096 Nov 6 23:48 nfs_test
-rw-r--r-- 1 1000 1000 0 Nov 6 23:48 nfs_test.txt
Как и ожидалось root пользователь может только читать, т.к. не является владельцем директории и не состоит в группе, т.е. является пользователем other и имеет права только на чтение (2775)
Несколько уточнений
- В случае внесения изменений в конфигурацию /etc/exports на NFS-сервере на клиентских машинах может возникнуть ошибка вида:
-bash: cd: share: Stale file handle
Для устранения необходимо перемонтировать директорию:
1.1 Отмонтировать
umount share
1.2 Смонтировать заново (монтирование через fstab)
mount -a - В выводе команды ls -n /mnt/share/ созданная директория nfs_test имеет разрешения
755, а файл nfs_test.txt644. Эти разрешения задаются в операционной системе клиента через umask (маска прав по умолчанию). При необходимости можно скорректировать.
Детальная информация под спойлером
Спойлер
Для всех пользователей
- Создать отдельный файл в /etc/profile.d/
nano /etc/profile.d/umask.sh - Вставить содержимое
# /etc/profile.d/umask.sh
# Устанавливает umask для всех интерактивных пользователей
if [ "$(id -u)" -eq 0 ]; then
umask 022 # root: файлы 644, каталоги 755
else
umask 002 # пользователи: файлы 664, каталоги 775
fi
- Установить строиге права на файл
chmod 644 /etc/profile.d/umask.sh - Перезагрузить систему
reboot
Этот скрипт автоматически подхватывается в конце /etc/profile (запускает все .sh из /etc/profile.d)
Для текущего пользователя
- Раскоментировать строку в файле nano ~/.bashrc
umask 022 - Скорретировать на нужное значение, например
umask 002 - Перезагрузить систему
reboot
При создании файла 666 вычитается umask: 666-002=664
При создании директории 777 вычитается umask: 777-002=775
Таким образом получаем сетевой доступ к директории через протокол nfs, которая ранее была расшарена по протоколу samba.

Для наглядности смонтировал nfs-директорию share в LXC контейнер с File Browser, где эта же директория (share_write) в рамках предыдущей статьи была смонитрована по протоколу samba.
Общие рекомендации
- Для обычной файловой шары с доступом для всех пользователей сети исользуйте настройки NFS-сервера
all_squash,anonuid,anongid(см. п.3.2 Настройка NFS-сервера в привилегированном LXC). Это поможет избежать проблем с разными uid и gid на клиентских машинах (дублирование, разный набор вторичных групп и т.д.) - Для дирекорий предназначенных только для чтения явно указывайте это в разрешениях на директорию и используйте параметр
ro(вместо rw) в настройках экспорта /etc/exports на NFS-сервере - Для директорий с которыми будет работать конкретный сервис из под фиксированного пользователя (uid) и группы (gid) необходимо создать аналогичного пользователя на NFS-сервере, создать директорию с такими же uid и gid, а так же в экспорте /etc/exports на NFS-сервере прописать IP адрес этого сервиса. Таким образом только этот сервис сможет читать и писать в данную директорию.
- Каждому новому экспорту присваивайте свой уникальный
fsidчерез /etc/exports. - Разрешения на директории, списки uid и gid настраивайте под ваши нужды, в данной статье приведён всего лишь пример одной из рабочих схем.




