Всегда хотел развернуть шару SMB с хранилищем на ZFS, но есть нюансы…
Совершенно не приемлю, чтобы пользователи каким либо образом взаимодействовали с сервером, где расположен pool\ZFS. В моем понимании, СХД может включать в себя только служебные компоненты без прямого пользовательского доступа к его сети.

Был отдельно стоящий гипервизор KVM с ZFS и требовалось поднять обычную пользовательскую шару. Почему не сделать это красиво, подумал я. О, если я бы знал, что эта работа выльется в две недели наверно не стал бы этим заниматься.
Идея казалось мне очень простой - поднимаем виртуальный сервер, подключаем его к домену, цепляем туда существующий ZFS пул, добавляем плюшки в виде теневой копии. Все красиво по фэншую - пальму в угол, картину к двери. Осталось решить, как подключить сам ZFS пул к виртуальной машине, да, собственно, и все. Идея использовать NFS казалось самой очевидной. Однако пробежавшись по опциям гипервизора, я наткнулся на параметр, которого ранее не замечал - прямой проброс каталога в виртуальную машину. Из коробки система поддерживала два типа подключений: virtio-9p и VirtioFS.
virtio-9p - исключил сразу, так как он упоминался как нестабильный и с ограниченной поддержкой POSIX, так еще и низко производительный.
VirtioFS – выглядел крайне перспективным.
Ну, что ж, пусть будет VirtioFS, подумал я.
Первые же настройки VirtioFS дались тяжело. Да, проброс каталога работал из коробки вопросов нет, но, нам нужен демон, запущенный с определенными параметрами, а именно, ACL и xattr. Опций включить эти параметры в virt-manager не оказалось, оставалось только править XML машины.
Работающий XML для VirtioFS выкладывать не буду, и не потому, что мне жалко, просто не смог заставить запуститься ВМ с нужными мне параметрами, ни через libvirt, ни через Qemu. Единственный параметр, который я смог передать это xattr.
ACL (Access Control Lists) — списки контроля доступа, которые определяют права пользователей на файлы и папки.
xattr (Extended Attributes) — расширенные атрибуты файлов, позволяющие хранить дополнительную информацию.
К счастью, в какой-то момент, я наткнулся на крошечное обсуждение проблемы по этому вопросу на гитхаб , в качестве решения предлагалось добавить нужные параметры через обертку. Почему и нет? - вполне рабочее решение.
Убедимся, что мы можем передать необходимые нам параметры в virtiofsd, запустим:
/usr/libexec/virtiofsd --xattr --posix-acl --shared-dir /kvm/tmp --socket-path /tmp/vfs.sock
проверяем наличие необходимых ключей запуска, нам важно увидеть --xattr --posix-acl
ps aux | grep virtiofsd

все отлично!
(в моем случае версия - virtiofsd 1.11.1)
Делаем обертку
Создаем файл /usr/libexec/virtiofsdfix с содержимым:
#!/bin/bash exec /usr/libexec/virtiofsd "$@" --xattr --posix-acl --sandbox none
Делаем его исполнительным и сразу копируем контекст безопасности с оригинала.
sudo chmod +x /usr/libexec/virtiofsd sudo chcon --reference=/usr/libexec/virtiofsd /usr/libexec/virtiofsd
sandbox none - данный параметр появился в ходе экспериментов, я предпочел его оставить, он должен отключать изоляцию (об этом позже).
После того, как обертка готова, нужно указать ее в качестве основанного модуля VirtioFS
Правим XML в virt-manager или через virsh edit

Отлично, мы готовы запустить виртуальную машину и примонтировать нашу директорию.
ZFS
Все вышеописанное достаточно, чтобы пробросить --xattr --posix-acl для локальной директории. например, ext4, но для ZFS этого недостаточно. Для того, чтобы пробросить ZFS, Dataset должен иметь точку монтирования и еще 3 параметра:
zfs set acltype=posixacl pool/smbfs
Включает поддержку стандартных Linux ACL это позволяет командам getfacl/setfacl работать корректно.
zfs set aclinherit=passthrough pool/smbfs
При создании нового файла передать ему права от родительского каталога.
zfs set aclmode=passthrough pool/smbfs
Режим невмешательства ZFS в ACL
Теперь мы готовы к настройке ВМ.
Из нашего первоначального плана ВМ уже должна находиться в домене и соответственно все необходимые пакеты Samba уже установлены.
Нам всего только нужно подмонтировать наше устройство VirtioFS, сделаем это сразу в /etc/fstab
добавив строчку в конец
fs /fs virtiofs rw,noatime,_netdev,nofail
после mount –a мы смонтировали наш ZFS каталог в ранее созданную директорию /fs
Samba
Для примера приведу настройку локальной директории на сервере Samba
[local] comment = local path = /local public = no writable = yes read only = no guest ok = no admin users = "domain\admin-domain" "superadmin" inherit acls = yes inherit owner = yes inherit permissions = yes map acl inherit = yes vfs objects = acl_xattr
Эта настройка прекрасно работает для локальной директории, но, как только мы активируем acl_xattr для директории VirtioFS.
Записать атрибуты безопасности мы не сможем. Если же активацию acl_xattr не производить, то можем задавать атрибуты безопасности только на уровне posix-acl со всеми вытекающими проблемами - лишние пользователи и группы из Linux, ну и, конечно, ограниченный функционал.
Логично разобраться: «а почему так происходит?».
Чтобы понять это, просто сделаем проверки setfacl, а лучше выполним проверки как на VirtioFS, так и на локальной директории /local.
# ПОДГОТОВКА #создаем файлы для теста от имени доменного пользователя sudo -u userDomain touch /fs/kvm.txt sudo -u userDomain touch /local/local.txt # Сброс владельцев для тестов chown userDomain:admindomain /fs /local chmod 775 /fs /local sudo -u userDomain touch /fs/kvm.txt sudo -u userDomain touch /local/local.txt echo echo TEST echo Проверка на локальном диске setfacl -m u:userDomain:rwx /local/local.txt && echo "Local POSIX: OK" # Проверка на VirtioFS setfacl -m u:userDomain:rwx /fs/kvm.txt && echo "VirtioFS POSIX: OK" echo echo Может ли владелец менять ACL? sudo -u userDomain setfacl -m u:root:r /local/local.txt && echo "Local User POSIX: OK" sudo -u userDomain setfacl -m u:root:r /fs/kvm.txt && echo "VirtioFS User POSIX: OK" echo echo Записываем тестовый бинарный блок -имитация прав Windows setfattr -n user.SAMBA_PAI -v 0s01020304 /local/local.txt && echo "Local XATTR: OK" setfattr -n user.SAMBA_PAI -v 0s01020304 /fs/kvm.txt && echo "VirtioFS XATTR: OK" echo echo Запись в локальный файл sudo -u userDomain setfattr -n user.SAMBA_PAI -v 0s05060708 /local/local.txt && echo "Local User XATTR: OK" # Запись в VirtioFS sudo -u userDomain setfattr -n user.SAMBA_PAI -v 0s05060708 /fs/kvm.txt && echo "VirtioFS User XATTR: OK" echo echo проверяем метки getfattr -d -m . /local/local.txt getfattr -d -m . /fs/kvm.txt
Все тесты пройдены, все отлично, только мы можем наблюдать пометку security.selinux на файле VirtioFS.

Но Samba упрямо отказывается писать атрибуты XATTR.
В конечном итоге, я выключил SELinux на хосте, и кто бы мог подумать? -ничего не изменилось.
За кадром также провел тесты записи параметров безопасности от имени другого приложения (Payton), также успех!
Какой вывод? - а никакого. Все должно, но не работает. Далее пошел метод «тыка» - Сколько было вариантов параметров в Samba, сбился со счету. Что-то давало результаты, но промежуточные.
В конечном итоге включил параметр vfs objects = acl_tdb вместо acl_xattr, да, это не решение, а затычка, samba пишет параметры безопасности в локальную базу, VirtioFS используется исключительно как хранилище файлов, нам не нужен не –xattr не --posix-acl, все бы ничего, но и доступа к снимкам ZFS у пользователей не будет, а если и будет, то дырявый. Ну и статью эту писать не о чем, не нужна она! но, она есть, а значит решение было найдено.
Читав документацию docs.altlinux.org (хотя, признаюсь, что тут используется другой Российский дистрибутив).
При использовании параметров значения расширенных атрибутов файлов (xattr security.NTACL) на всех контроллерах будут одинаковы, независимо от uid/gid. Именно это и является проблемой при использовании rsync….
security.NTACL - это расширенный атрибут (xattr), который используется Samba для хранения Windows-разрешений (NTFS ACL) на Linux-сервере (именно из-за этого параметра на хосте в VirtioFS был добавлен --sandbox none).
Linux-права (rwx) и POSIX ACL не могут полностью описать правила доступа Windows (например, «запрет на удаление» при наличии «прав на запись»). Поэтому, модуль Samba vfs_acl_xattr упаковывает весь Windows Security Descriptor (включая SID пользователей и групп) в этот атрибут.
Замечательно, давайте проверим и его
echo -имитация Samba запись по умолчанию
echo -имитация Samba запись по умолчанию sudo -u userDomain setfattr -n security.NTACL -v 0s01020304 /local/local.txt && echo "Local Security: OK" sudo -u userDomain setfattr -n security.NTACL -v 0s01020304 /fs/kvm.txt && echo "VirtioFS Security: OK"

опять мимо, на обоих отказ!
Но, я так долго в промежуточных тестах просил Samba писать атрибуты именно из-под root, а как обстоят дела с root?
Выполним то же самое, но от суперпользователя.

Вот он корень зла!
security.NTACL для Samba - родное место, где Samba ищет и пишет Windows-дескрипторы. Только процессы с CAP_SYS_ADMIN (root) могут записывать в пространство security. Обычные пользователи (даже владелец файла) не могут изменять или удалять этот атрибут напрямую.
user.NTACL (пользовательское пространство) - альтернативное расположение в пространстве имен user. Любой пользователь, имеющий права на запись в файл, может изменять атрибуты в user.
Да, последняя строчка неприятна, но, в принципе, не так и критична, так как самих пользователей на сервер мы не пускаем.
Что происходит? Samba пытается записать атрибут security.NTACL для VirtioFS и, у нее это не получается, параметр, который должен разрешать запись данных атрибутов --sandbox none все равно не решает проблемы. Скорее всего, что-то на уровне ядра или VirtioFS на хосте запрещает эти правки. Возможно, в вашем дистрибутиве --sandbox none сработает.
echo -имитация Samba запись в user.NTACL sudo -u userDomain setfattr -n user.NTACL -v 0s01020304 /local/local.txt && echo "Local Security: OK" sudo -u userDomain setfattr -n user.NTACL -v 0s01020304 /fs/kvm.txt && echo "VirtioFS Security: OK"

У меня в тестах использовались:
хост PRETTY_NAME="RED OS 8.0.2"
гость PRETTY_NAME="Ubuntu 24.04.3 LTS"
для того, чтобы все заработало, нужно добавить в конфигурационный файл samba
# user.NTACL acl_xattr:security_acl_name = user.NTACL acl_xattr:ignore system acls = yes
пример, вместе со снимками
[VirtioFS] path = /fs writable = yes admin users = "domain\admin-domain" "superadmin" vfs objects = acl_xattr shadow_copy2 # user.NTACL acl_xattr:security_acl_name = user.NTACL acl_xattr:ignore system acls = yes shadow:basedir = /fs shadow:snapdir = .zfs/snapshot shadow:format = GMT-%Y.%m.%d_%H.%M.%S shadow:sort = desc shadow:localtime = yes
Снимки ZFS
Я давно заметил, еще при использовании NFS, чтобы получить снимки ZFS на госте, нужно выполнить на хосте сразу после создания снимка ls – l
Возможно, при включении просмотров снимков в общем пуле zpool set listsnapshots=on data выполнять ls – l не нужно, но мне не нравится внешний вид zfs list с перечислением всех снимков.
пример скрипта создания снимка ZFS
#!/bin/bash PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin zpool="pool/fs" dt="GMT-"$(date +%Y.%m.%d_%H.%M.%S) zfs snapshot $zpool@$dt ls -l /kvm/fs/.zfs/snapshot/$dt
что мы получили? все что хотели!
ZFS не отдает доступ к данным напрямую с хоста, для этого используется ВМ, именно ВМ авторизовывает доменных пользователей и предоставляет им шару.
