Skip to main content

HP D2700: схема дисковых массивов и назначение хранилищ

HP D2700: схема дисковых массивов и назначение хранилищ

Версия 1.4
Дата 06.11.2026
Статус P411 с 512 MB FBWC и firmware 6.64 работает в PCIe Slot 1 как PCIe Gen2 x8. D2700 firmware 0150, все 25 дисков исправны, production RAID-массивы созданы. MAIN-DATA передан в VM 103, production Btrfs смонтирован в /srv/main-data. Созданы 8 функциональных Btrfs subvolume, Snapper, группы и POSIX ACL. Samba введена в эксплуатацию: опубликованы 8 SMB shares, проверена матрица доступа, Windows Previous Versions, Samba recycle и автоматическая очистка корзин. ACL корзин скорректированы для административного доступа через File Browser без раскрытия пользовательских корзин профильным группам. Установлен и проверен File Browser Next v3.0.0-next как отдельный systemd-сервис. Management-маршрутизация переведена на gateway 10.44.100.1 через ens19.

DNS-интеграция файлового сервера введена в эксплуатацию: настроен split DNS через systemd-resolved, для пяти OT-сегментов зарегистрированы отдельные FQDN и согласованные A/PTR, создан /usr/local/sbin/ot-ddns-register и включён ot-ddns-register.service.
Проект Расширение памяти сервера

1. Назначение документа

Документ фиксирует production-архитектуру хранения HP ProLiant DL380 G7 с внешней дисковой полкой HP StorageWorks D2700, контроллером Smart Array P411, аппаратными RAID, виртуальной машиной Ubuntu Server, Btrfs, Snapper, POSIX ACL и Samba.

Здесь рассматриваются основной файловый массив MAIN-DATA, локальный массив CRITICAL-BACKUP, служебный RECOVERY, общий горячий резерв, передача MAIN-DATA в VM 103 и публикация функциональных ресурсов по SMB. TFTP/PXE/Cisco recovery для массива RECOVERY должен оформляться отдельной статьёй.

Начиная с версии 1.3 документ также фиксирует DNS-интеграцию многосетевого файлового сервера: маршрутизацию DNS-запросов по OT-интерфейсам через systemd-resolved, сегментные FQDN, RFC 2136/DDNS через nsupdate и правила коротких имён для клиентов.

2. Состав оборудования

Сервер HP ProLiant DL380 G7
Гипервизор Proxmox VE 9.1.9
Внутренний RAID HP Smart Array P410i, firmware 6.64, 512 MB cache
Внешний RAID HP Smart Array P411, PCIe Slot 1, firmware 6.64, 512 MB FBWC
Полка HP StorageWorks D2700, 25 × 2.5" SFF SAS
Firmware D2700 0150
Подключение P411 port 1E → SFF-8088 → D2700 I/O Module A, P1
Режим Single Domain

3. Физическая раскладка дисков D2700

Отсеки Диски Роль Имя
1–12 12 × 600 GB SAS 10K Основной RAID50 MAIN-DATA
13–14 2 × 146 GB SAS 15K RAID1 RECOVERY
15 1 × 600 GB SAS 10K Shared online spare GLOBAL-SPARE
16–25 10 × 500 GB SAS 7.2K Резервный RAID50 CRITICAL-BACKUP
HP D2700 — bays 01–25

01–12  600 GB  MAIN-DATA
13–14  146 GB  RECOVERY
15     600 GB  GLOBAL-SPARE
16–25  500 GB  CRITICAL-BACKUP

4. Production RAID-массивы

4.1. MAIN-DATA

RAID RAID50
Состав 12 × 600 GB SAS 10K
Parity groups 2 группы: bays 1–6 и 7–12
Strip size 256 KiB
Полезная ёмкость 5.46 TiB / 6.00 TB
Назначение рабочие данные, SMB/NFS, Clonezilla

4.2. RECOVERY

RAID1 из bays 13–14, около 136 GiB. Зарезервирован под отдельный TFTP/PXE/Cisco recovery-проект.

4.3. GLOBAL-SPARE

Bay 15, 600 GB SAS 10K. P411 отображает диск как shared spare. При отказе активного диска контроллер автоматически использует spare для rebuild. После установки замены в штатный bay контроллер может выполнить copy-back, после чего bay 15 снова становится свободным spare.

4.4. CRITICAL-BACKUP

RAID50 из 10 × 500 GB SAS 7.2K, две parity group по пять дисков, полезная ёмкость около 3.64 TiB. Используется для локальных копий выбранных критичных данных и не публикуется как обычная пользовательская шара.

CRITICAL-BACKUP не является независимым backup: MAIN-DATA и CRITICAL-BACKUP находятся в одной D2700 и зависят от одного P411, сервера и общей инфраструктуры питания.

5. Логика использования хранилищ

MAIN-DATA
├── рабочие документы
├── SMB shares
├── NFS при необходимости
└── Clonezilla
        │
        └── выбранные критичные копии
                ↓
        CRITICAL-BACKUP

RECOVERY
└── отдельный TFTP/PXE/Cisco recovery проект

6. Имена объектов

Объект Имя Статус
Основной RAID50 MAIN-DATA Создан
Служебный RAID1 RECOVERY Создан
Общий spare GLOBAL-SPARE Назначен
Резервный RAID50 CRITICAL-BACKUP Создан

7. Ввод P411 и D2700 в эксплуатацию

Первоначальный 256 MB cache-модуль P411 оказался неисправным и приводил к ошибке self-test. После установки исправного 512 MB FBWC и обновления firmware до 6.64 P411 корректно заработал с SAS-expander D2700. D2700 и оба I/O-модуля работают на firmware 0150.

7.1. Диагностика PCIe/IOCK

При размещении P411 в прежнем PCIe Slot 5 воспроизводились IOCK, reset и controller lockup. Перевод драйвера hpsa в simple mode не устранил проблему. После переноса P411 в PCIe Slot 1 контроллер согласовал PCIe Gen2 5 GT/s ×8; повторных IOCK/lockup в контрольном периоде не зафиксировано.

7.2. Контроль через ssacli

ssacli ctrl all show status
ssacli ctrl slot=1 show detail
ssacli ctrl slot=1 show config
ssacli ctrl slot=1 ld all show detail
ssacli ctrl slot=1 pd all show status

Production checkpoint P411: Controller/Cache/Capacitor Status = OK; firmware 6.64; cache ratio 25% read / 75% write.

7.3. Parity initialization

MAIN-DATA и CRITICAL-BACKUP сохраняют Parity Initialization Status: Queued, при этом logical drive имеют Status: OK. Это не блокирует эксплуатацию, но статус продолжает контролироваться.

8. Виртуальная машина файлового сервера

VM ID 103
Имя SMR-SRV-OT-SHARE
Hostname smr-srv-ot-share
ОС Ubuntu Server 24.04.4 LTS
CPU 4 vCPU, type host
RAM 8 GiB
Системный диск 100 GiB, ext4/LVM
Production data MAIN-DATA через отдельный SCSI device
DNS-зона OT ot-samara.baltika.ru
DNS-модель Multi-homed: отдельный FQDN на каждый OT-сегмент; автоматическая регистрация A/PTR через RFC 2136

9. Системный диск VM

Системный диск 100 GiB размещён на внутреннем хранилище Proxmox/P410i. Корневая файловая система Ubuntu — ext4 поверх LVM; production-данные на системном диске не хранятся.

10. Сетевые интерфейсы VM

Ubuntu Сегмент Адрес Маршрутизация
ens18 временная сеть настройки 192.168.1.229/24 без default gateway
ens19 Prod management VLAN2100 10.44.100.229/24 default gateway 10.44.100.1
ens20 Rozliv VLAN2002 172.16.68.229/23 connected route
ens21 Pivoproduction VLAN2030 целевой 172.16.66.229/23 целевой интерфейс; route 172.16.66.0/23 пока остаётся на ens23
ens22 Utilities VLAN2040 172.16.70.229/23 connected route
ens23 Legacy VLAN1 10.255.0.229/16 + переходный 172.16.66.229/23 connected: 10.255.0.0/16 и переходный 172.16.66.0/23
enp2s1 АСТУЭ VLAN2006 172.17.14.229/24 connected route

Адрес 172.16.66.229 не должен одновременно находиться на legacy-интерфейсе и VLAN2030. После миграции он переносится на целевой интерфейс VLAN2030.

Основной маршрут по умолчанию для VM: default via 10.44.100.1 dev ens19. На ens18 адрес 192.168.1.229/24 сохранён для локального сервисного доступа, но default gateway через 192.168.1.1 удалён. Это исключает два конкурирующих default route и обеспечивает обратный трафик к корпоративной сети через management VLAN2100.

Проверенная таблица маршрутизации после netplan try:

default via 10.44.100.1 dev ens19 proto static
10.44.100.0/24 dev ens19 proto kernel scope link src 10.44.100.229
10.255.0.0/16 dev ens23 proto kernel scope link src 10.255.0.229
172.16.66.0/23 dev ens23 proto kernel scope link src 172.16.66.229
172.16.68.0/23 dev ens20 proto kernel scope link src 172.16.68.229
172.16.70.0/23 dev ens22 proto kernel scope link src 172.16.70.229
172.17.14.0/24 dev enp2s1 proto kernel scope link src 172.17.14.229
192.168.1.0/24 dev ens18 proto kernel scope link src 192.168.1.229

10.1. Split DNS через systemd-resolved

Файловый сервер подключён одновременно к нескольким изолированным OT-сегментам. Для корректного обращения к локальному BIND9 каждому OT-интерфейсу назначается DNS-адрес своего сегмента. Маршрутизация запросов выполняется systemd-resolved через route-only domains с префиксом ~.

Важно: ~ot-samara.baltika.ru — это не search suffix. Он определяет, на какой DNS отправлять запрос. Расширение короткого имени выполняется на клиенте через DNS suffix search list и описано в разделе 20.14.

Интерфейс Сегмент DNS Route-only domains
ens18 временная сеть настройки 192.168.1.1 общий/внешний resolver; без OT route-only domain
ens20 Rozliv 172.16.68.53 ~ot-samara.baltika.ru, ~68.16.172.in-addr.arpa, ~69.16.172.in-addr.arpa
ens22 Utilities 172.16.70.53 ~ot-samara.baltika.ru, ~70.16.172.in-addr.arpa, ~71.16.172.in-addr.arpa
ens23 Legacy + временно Pivo 10.255.0.53, 172.16.66.53 ~ot-samara.baltika.ru, ~255.10.in-addr.arpa, ~66.16.172.in-addr.arpa, ~67.16.172.in-addr.arpa
enp2s1 АСТУЭ 172.17.14.53 ~ot-samara.baltika.ru, ~14.17.172.in-addr.arpa
ens21 Pivoproduction VLAN2030, целевой пока не назначен после миграции сюда переносятся DNS 172.16.66.53 и route-only domains ~ot-samara.baltika.ru, ~66.16.172.in-addr.arpa, ~67.16.172.in-addr.arpa

Почему для /23 указаны две reverse-зоны. Сеть 172.16.66.0/23 включает две стандартные reverse-зоны: 66.16.172.in-addr.arpa для адресов 172.16.66.x и 67.16.172.in-addr.arpa для адресов 172.16.67.x. Обе route-only зоны нужны, чтобы файловый сервер мог разрешать PTR любого узла во всей /23.

Это не означает, что собственный IP SHARE должен иметь PTR в обеих зонах. Например, 172.16.66.229 имеет PTR только в 66.16.172.in-addr.arpa. Запись с owner 229 в зоне 67.16.172.in-addr.arpa означала бы другой адрес — 172.16.67.229.

Management-интерфейс ens19 не использует management-IP DNS-ВМ как DNS: BIND9 намеренно не слушает DNS на management-сети.

Фрагменты DNS-настроек в Netplan; существующие адреса и маршруты интерфейсов при этом сохраняются:

ens18:
  nameservers:
    addresses:
      - 192.168.1.1

ens20:
  nameservers:
    addresses:
      - 172.16.68.53
    search:
      - "~ot-samara.baltika.ru"
      - "~68.16.172.in-addr.arpa"
      - "~69.16.172.in-addr.arpa"

ens22:
  nameservers:
    addresses:
      - 172.16.70.53
    search:
      - "~ot-samara.baltika.ru"
      - "~70.16.172.in-addr.arpa"
      - "~71.16.172.in-addr.arpa"

ens23:
  nameservers:
    addresses:
      - 10.255.0.53
      - 172.16.66.53
    search:
      - "~ot-samara.baltika.ru"
      - "~255.10.in-addr.arpa"
      - "~66.16.172.in-addr.arpa"
      - "~67.16.172.in-addr.arpa"

enp2s1:
  nameservers:
    addresses:
      - 172.17.14.53
    search:
      - "~ot-samara.baltika.ru"
      - "~14.17.172.in-addr.arpa"

10.2. Применение и проверка DNS-маршрутизации

sudo netplan generate
sudo netplan try --timeout 120

resolvectl status

Подтверждённая маршрутизация:

  • 172.16.68.53 PTR — через ens20;
  • 172.16.70.53 PTR — через ens22;
  • 10.255.0.53 и 172.16.66.53 PTR — через ens23;
  • 172.17.14.53 PTR — через enp2s1;
  • прямая зона ot-samara.baltika.ru может обслуживаться любым равнозначным OT-link, поскольку все локальные BIND-адреса авторитетны для одной и той же зоны;
  • обычные внешние имена при текущей переходной конфигурации разрешаются через ens18 → 192.168.1.1, а не через OT BIND.

11. Ubuntu Server

Ubuntu Server 24.04.4 LTS установлен с OpenSSH. Hostname: smr-srv-ot-share. Временная сеть установки — 192.168.1.229/24.

12. Базовые пакеты

sudo apt install -y   ca-certificates curl nano openssl iputils-ping tcpdump arping   bash-completion lsof qemu-guest-agent systemd-timesyncd ufw   ethtool rsync acl attr btrfs-progs snapper

13. QEMU Guest Agent

sudo systemctl enable --now qemu-guest-agent
systemctl status qemu-guest-agent --no-pager

Сервис подтверждён как active (running).

14. Время

sudo timedatectl set-timezone Europe/Samara
sudo timedatectl set-local-rtc 0
sudo timedatectl set-ntp true

15. Запрет маршрутизации между OT-сегментами

net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

VM является многосетевым файловым сервером, но не маршрутизатором. Для reverse path filtering используется loose mode rp_filter=2.

16. Production MAIN-DATA в VM 103

Logical drive MAIN-DATA передан в VM по стабильному идентификатору /dev/disk/by-id/scsi-3600508b1001c2abf1f734aef851f07c9. Имена /dev/sdX не считаются постоянными.

qm set 103   -scsi2 /dev/disk/by-id/scsi-3600508b1001c2abf1f734aef851f07c9,cache=none,iothread=1,backup=0

16.1. Production Btrfs

Label MAIN-DATA
UUID 98e5188a-407c-4d4a-adc1-24d8c90afb32
Размер 5.46 TiB
Data single
Metadata/System DUP
Mount /srv/main-data
UUID=98e5188a-407c-4d4a-adc1-24d8c90afb32 /srv/main-data btrfs defaults,nofail,x-systemd.device-timeout=10s 0 0

17. Логическая структура MAIN-DATA

/srv/main-data
└── baltikashare
    ├── clonezilla
    ├── exchange
    ├── pivoproduction
    ├── rozliv
    ├── utilities
    ├── software
    ├── documentation
    └── ot-admin
Ресурс Назначение
clonezilla образы рабочих станций и технологических ПК
exchange общий обмен инженеров
pivoproduction рабочие данные пивопроизводства
rozliv рабочие данные розлива
utilities инженерные и энергетические системы
software дистрибутивы, драйверы, firmware, утилиты
documentation инструкции, схемы, ТЗ и паспорта
ot-admin административные OT-материалы

18. Snapper

Для каждого из 8 функциональных Btrfs subvolume создана отдельная Snapper-конфигурация: clonezilla, exchange, pivoproduction, rozliv, utilities, software, documentation, ot-admin.

BACKGROUND_COMPARISON=no
TIMELINE_CREATE=yes
TIMELINE_CLEANUP=yes
TIMELINE_MIN_AGE=1800
Ресурс Hourly Daily Weekly Monthly Yearly
clonezilla 24 30 12 12 1
exchange 24 7 2 0 0
pivoproduction 72 30 12 12 0
rozliv 72 30 12 12 0
utilities 72 30 12 12 0
software 0 14 8 6 0
documentation 72 60 26 24 3
ot-admin 72 90 26 24 5
systemctl is-active snapper-timeline.timer snapper-cleanup.timer

Оба таймера подтверждены как active.

19. Модель доступа: группы и POSIX ACL

19.1. Группы

Группа Назначение
admins полный доступ ко всем ресурсам
engineers exchange RW; software/documentation RO
clonezilla-rw RW clonezilla
pivoproduction-rw RW pivoproduction
rozliv-rw RW rozliv
utilities-rw RW utilities
software-rw RW software
documentation-rw RW documentation

19.2. Матрица доступа

Ресурс admins engineers Профильная группа
clonezilla RW DENY clonezilla-rw → RW
exchange RW RW —
pivoproduction RW DENY pivoproduction-rw → RW
rozliv RW DENY rozliv-rw → RW
utilities RW DENY utilities-rw → RW
software RW RO software-rw → RW
documentation RW RO documentation-rw → RW
ot-admin RW DENY только admins

19.3. Универсальные учётные записи

Учётная запись Группа доступа
baltikashare admins
engineer engineers
clonezilla clonezilla-rw
pivo pivoproduction-rw
rozliv rozliv-rw
utilities utilities-rw
software software-rw
documents documentation-rw

19.4. POSIX ACL

Для профильного RW-ресурса используется следующая базовая модель:

user::rwx
group::rwx
group:admins:rwx
mask::rwx
other::---

default:user::rwx
default:group::rwx
default:group:admins:rwx
default:mask::rwx
default:other::---

Для software и documentation дополнительно задан RO для engineers:

group:engineers:r-x
default:group:engineers:r-x

20. Samba — production-конфигурация

20.1. Состояние

Версия Samba 4.19.5-Ubuntu
Роль standalone server
NetBIOS name SMR-OT-SHARE
Security user
Минимальный протокол SMB2_02; SMB1 отключён
Конфигурация /etc/samba/smb.conf
Сервис smbd.service — active

Проверка конфигурации:

sudo testparm
sudo systemctl restart smbd
sudo systemctl is-active smbd
sudo smbstatus

20.2. Опубликованные shares

\\SMR-OT-SHARE\exchange
\\SMR-OT-SHARE\clonezilla
\\SMR-OT-SHARE\pivoproduction
\\SMR-OT-SHARE\rozliv
\\SMR-OT-SHARE\utilities
\\SMR-OT-SHARE\software
\\SMR-OT-SHARE\documentation
\\SMR-OT-SHARE\ot-admin

20.3. Исправление ACL-маски при создании файлов через SMB

Первоначальная комбинация inherit acls = yes + inherit permissions = yes привела к тому, что новый файл через SMB получил эффективную маску mask::r--. Именованная ACL для admins присутствовала, но фактическая запись была запрещена.

-rwxr-----+
user::rwx
group::rwx                      #effective:r--
group:admins:rwx                #effective:r--
mask::r--
other::---

Production-схема изменена: default ACL наследуются Linux/Btrfs, а Samba создаёт файлы и каталоги с фиксированной базовой маской:

create mask = 0660
force create mode = 0660
directory mask = 0770
force directory mode = 0770

inherit acls = no
inherit permissions = no

После исправления новый файл через SMB:

-rw-rw----+
user::rw-
group::rwx                      #effective:rw-
group:admins:rwx                #effective:rw-
mask::rw-
other::---

Контрольная запись от пользователя baltikashare через ACL группы admins выполнена успешно.

20.4. DOS/Windows attributes

Чтобы DOS Archive/Hidden/System не превращались в UNIX execute-биты, Windows-атрибуты хранятся в xattr:

store dos attributes = yes
map archive = no
map hidden = no
map system = no

20.5. Актуальный smb.conf

# ============================================================
# Samba configuration
# Server: SMR-SRV-OT-SHARE
# Role: standalone OT file server
# Data root: /srv/main-data/baltikashare
# ============================================================

[global]

   # Рабочая группа Windows.
   # Используется для standalone Samba без Active Directory.
   workgroup = WORKGROUP

   # Сервер работает автономно и не является контроллером домена.
   server role = standalone server

   # Аутентификация пользователей по логину и паролю.
   security = user

   # Локальная база Samba-пользователей.
   # В неё пользователи добавляются командой smbpasswd -a.
   passdb backend = tdbsam

   # Короткое NetBIOS-имя Samba-сервера.
   # Ограничение NetBIOS — максимум 15 символов.
   # Linux hostname при этом остаётся smr-srv-ot-share.
   netbios name = SMR-OT-SHARE

   # Описание сервера, которое могут видеть SMB-клиенты.
   server string = SMR OT File Server

   # Никогда не преобразовывать неизвестного пользователя в guest.
   map to guest = never

   # Запрещаем usershare и guest usershare.
   usershare max shares = 0
   usershare allow guests = no

   # Samba не используется как print server.
   load printers = no
   disable spoolss = yes
   printcap name = /dev/null

   # Минимально разрешённая версия SMB — SMB2.
   # SMB1/CIFS не разрешаем.
   server min protocol = SMB2_02

   # Логирование.
   log file = /var/log/samba/log.%m
   logging = file
   max log size = 1000

   # PAM.
   obey pam restrictions = yes
   unix password sync = no
   pam password change = no

   # =========================================================
   # Права создаваемых файлов и каталогов
   # =========================================================

   # Обычные файлы:
   # владелец = RW, группа = RW, остальные = NO ACCESS.
   create mask = 0660
   force create mode = 0660

   # Каталоги:
   # владелец = RWX, группа = RWX, остальные = NO ACCESS.
   directory mask = 0770
   force directory mode = 0770

   # Специальное наследование Samba не используем.
   # Default POSIX ACL наследуются файловой системой Linux.
   #
   # inherit permissions = yes переопределяет create/directory mask
   # и в данной схеме использоваться не должен.
   inherit acls = no
   inherit permissions = no

   # =========================================================
   # DOS / Windows attributes
   # =========================================================

   # DOS/Windows-атрибуты храним в extended attributes,
   # а не кодируем UNIX execute-битами.
   store dos attributes = yes
   map archive = no
   map hidden = no
   map system = no


# ============================================================
# EXCHANGE
# admins = RW
# engineers = RW
# ============================================================

[exchange]

   path = /srv/main-data/baltikashare/exchange
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @engineers

   # =========================================================
   # Служебные каталоги
   # =========================================================

   # Каталог Snapper полностью скрываем от обычного SMB-доступа.
   # Пользователь работает со snapshots через Windows
   # «Свойства» -> «Предыдущие версии».
   veto files = /.snapshots/

   # Сетевую корзину скрываем из обычного списка файлов,
   # но оставляем доступной по прямому SMB-пути.
   hide files = /.recycle/

   # Snapper = Windows Previous Versions.
   # Recycle = сетевая корзина Samba.
   vfs objects = snapper recycle

   # Для каждого SMB-пользователя создаётся отдельная корзина.
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# CLONEZILLA
# admins = RW
# clonezilla-rw = RW
# ============================================================

[clonezilla]

   path = /srv/main-data/baltikashare/clonezilla
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @clonezilla-rw

   # =========================================================
   # Служебные каталоги
   # =========================================================

   # Каталог Snapper полностью скрываем от обычного SMB-доступа.
   # Previous Versions продолжает работать через vfs_snapper.
   veto files = /.snapshots/

   # Только Snapper.
   # vfs_recycle намеренно не включён: большие образы могут
   # одновременно удерживаться корзиной и Btrfs snapshots.
   vfs objects = snapper


# ============================================================
# PIVOPRODUCTION
# admins = RW
# pivoproduction-rw = RW
# ============================================================

[pivoproduction]

   path = /srv/main-data/baltikashare/pivoproduction
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @pivoproduction-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# ROZLIV
# admins = RW
# rozliv-rw = RW
# ============================================================

[rozliv]

   path = /srv/main-data/baltikashare/rozliv
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @rozliv-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# UTILITIES
# admins = RW
# utilities-rw = RW
# ============================================================

[utilities]

   path = /srv/main-data/baltikashare/utilities
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins @utilities-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# SOFTWARE
# admins = RW
# software-rw = RW
# engineers = RO
# ============================================================

[software]

   path = /srv/main-data/baltikashare/software
   browseable = yes
   guest ok = no

   # По умолчанию только чтение.
   read only = yes
   valid users = @admins @engineers @software-rw

   # Запись только для admins и software-rw.
   write list = @admins @software-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# DOCUMENTATION
# admins = RW
# documentation-rw = RW
# engineers = RO
# ============================================================

[documentation]

   path = /srv/main-data/baltikashare/documentation
   browseable = yes
   guest ok = no

   # По умолчанию только чтение.
   read only = yes
   valid users = @admins @engineers @documentation-rw

   # Запись только для admins и documentation-rw.
   write list = @admins @documentation-rw

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle


# ============================================================
# OT-ADMIN
# admins = RW
# Все остальные = NO ACCESS
# ============================================================

[ot-admin]

   path = /srv/main-data/baltikashare/ot-admin
   browseable = yes
   guest ok = no
   read only = no
   valid users = @admins

   # Служебные каталоги.
   veto files = /.snapshots/
   hide files = /.recycle/

   vfs objects = snapper recycle
   recycle:repository = .recycle/%U
   recycle:keeptree = yes
   recycle:versions = yes
   recycle:touch_mtime = yes
   recycle:directory_mode = 0770
   recycle:subdir_mode = 0770
   recycle:exclude_dir = .recycle

20.6. Проверка матрицы доступа через smbclient

Пользователь engineer проверен фактическими SMB-операциями:

Share Ожидаемо Факт
exchange RW OK: put/del
software RO OK: ls; put → ACCESS_DENIED
documentation RO OK: ls; put → ACCESS_DENIED
clonezilla DENY ACCESS_DENIED
pivoproduction DENY ACCESS_DENIED
rozliv DENY ACCESS_DENIED
utilities DENY ACCESS_DENIED
ot-admin DENY ACCESS_DENIED

Профильные учётные записи подтвердили RW только на своих shares:

Учётка Share Результат
clonezilla clonezilla RW OK
pivo pivoproduction RW OK
rozliv rozliv RW OK
utilities utilities RW OK
software software RW OK
documents documentation RW OK

Контрольные попытки профильных пользователей подключиться к чужим ресурсам вернули tree connect failed: NT_STATUS_ACCESS_DENIED.

Администратор baltikashare успешно выполнил создание и удаление файла во всех восьми shares, включая software и documentation, где запись разрешена через write list.

20.7. Samba recycle

vfs_recycle включён на: exchange, pivoproduction, rozliv, utilities, software, documentation, ot-admin.

Для clonezilla recycle намеренно отключён: крупные образы могут одновременно удерживаться корзиной и Btrfs snapshots, что создаёт риск чрезмерного расхода MAIN-DATA. Clonezilla защищается Snapper; критичные образы дополнительно должны копироваться на CRITICAL-BACKUP.

20.7.1. Структура корзины

.recycle/%U

Пример для Pivoproduction:

/srv/main-data/baltikashare/pivoproduction/.recycle/pivo/recycle-test-dir/recycle-test.txt

Проверенный файл в корзине сохранил корректные ACL:

-rw-rw----+  pivo pivoproduction-rw

user::rw-
group::rwx                      #effective:rw-
group:admins:rwx                #effective:rw-
mask::rw-
other::---

20.7.1.1. Production ACL для корзин

Изначально recycle:directory_mode = 0700 и recycle:subdir_mode = 0700 приводили к созданию каталогов с ACL group:admins:rwx, но с mask::---. В результате группа admins фактически не имела доступа, и сервисный пользователь filebrowser не мог открыть большинство каталогов .recycle.

Для всех shares с vfs_recycle используется:

recycle:directory_mode = 0770
recycle:subdir_mode = 0770

Корень .recycle имеет следующую модель:

user::rwx
group::rwx
group:admins:rwx
mask::rwx
other::---

default:user::rwx
default:group::---
default:group:admins:rwx
default:mask::rwx
default:other::---

На корне .recycle установлен sticky bit. Типовой режим отображается как drwxrws--T+. Основная группа ресурса может войти в корень и создать свой .recycle/%U, но sticky bit не позволяет пользователю удалить чужой каталог верхнего уровня.

Персональный каталог .recycle/<user> имеет более строгую модель:

user::rwx
group::---
group:admins:rwx
mask::rwx
other::---

default:user::rwx
default:group::---
default:group:admins:rwx
default:mask::rwx
default:other::---

Таким образом, владелец видит собственную корзину, группа admins получает полный административный доступ, а остальные участники профильной группы ресурса не получают доступ к содержимому чужой корзины. Для software и documentation ACL engineers внутри .recycle удалены, чтобы RO-доступ к рабочим данным не распространялся на удалённые файлы.

Для ot-admin отдельная именованная запись group:admins не требуется, поскольку admins является основной группой каталога.

Схема проверена не только на существующих каталогах: .recycle/pivo был полностью удалён, после чего Samba повторно создала его при удалении файла. Новый каталог автоматически получил правильные default ACL, а filebrowser сохранил доступ к содержимому.

20.7.2. Сохранение структуры

recycle:keeptree = yes проверен удалением файла из вложенного каталога: исходная структура каталога появилась внутри персональной корзины.

20.7.3. Несколько версий

recycle:versions = yes проверен двойным удалением файла с одинаковым именем. В корзине появились:

version-test.txt
Copy #1 of version-test.txt

20.7.4. Удаление из самой корзины

recycle:exclude_dir = .recycle проверен удалением файла непосредственно из .recycle через SMB. Файл исчез окончательно и не был повторно перемещён во вложенную корзину.

20.7.5. Скрытие служебных каталогов

Для рабочих shares каталог Snapper полностью исключён из обычного SMB-просмотра, а Samba-корзина помечена как скрытая:

veto files = /.snapshots/
hide files = /.recycle/

veto files делает .snapshots недоступным по обычному SMB-пути, но не мешает vfs_snapper публиковать snapshots через Windows «Предыдущие версии». hide files присваивает .recycle атрибут Hidden; при необходимости корзину можно открыть напрямую, например \\SMR-OT-SHARE\exchange\.recycle.

На clonezilla используется только veto files = /.snapshots/, так как vfs_recycle для этого ресурса отключён.

20.8. Snapper и Windows «Предыдущие версии»

Цепочка Btrfs snapshot → Snapper → vfs_snapper → Samba → Windows Previous Versions проверена на реальном Windows-клиенте.

20.8.1. Контрольный тест

Для exchange были созданы две ручные точки Snapper с разными версиями одного файла, после чего текущая версия файла была изменена ещё раз. Windows отобразил обе сохранённые версии в свойствах файла и позволил восстановить более раннюю версию. После восстановления содержимое файла фактически вернулось к исходному варианту.

Отдельный тест выполнен на documentation: snapshot появился в «Свойства → Предыдущие версии», его содержимое успешно открывалось из Windows. Это подтвердило работу настройки не только на exchange, но и после её распространения на остальные shares.

20.8.2. Проверка автоматических timeline snapshots

Snapper создаёт timeline snapshots ежечасно. Контрольный вывод для exchange 28.10.2026 показывал последовательные snapshots с 05:00 до 14:00. Если Windows Explorer не сразу показывает последние точки, достаточно повторно открыть каталог или окно свойств: серверные snapshots при этом продолжают создаваться корректно.

20.9. Автоматическая очистка Samba recycle

Так как одновременно используется Snapper, корзина Samba предназначена для быстрого возврата случайно удалённых файлов и не должна хранить данные месяцами без ограничения. Для каждого ресурса задан отдельный срок хранения.

Ресурс Срок хранения .recycle
exchange 7 дней
pivoproduction 14 дней
rozliv 14 дней
utilities 14 дней
software 14 дней
documentation 30 дней
ot-admin 30 дней
clonezilla recycle отключён

В smb.conf используется recycle:touch_mtime = yes, поэтому при перемещении файла в корзину обновляется его mtime, и очистка может ориентироваться на время удаления через Samba.

20.9.1. Скрипт /usr/local/sbin/samba-recycle-cleanup

#!/usr/bin/env bash

# ============================================================
# Samba recycle cleanup
# Server: SMR-SRV-OT-SHARE
#
# Автоматическая очистка файлов из Samba .recycle
# по времени их нахождения в корзине.
#
# Режимы:
#   --dry-run  только показать, что было бы удалено
#   --delete   реально удалить просроченные файлы
# ============================================================

set -u
set -o pipefail

BASE="/srv/main-data/baltikashare"
MODE="${1:---dry-run}"

case "$MODE" in
    --dry-run)
        DELETE=false
        ;;
    --delete)
        DELETE=true
        ;;
    *)
        echo "Usage: $0 [--dry-run|--delete]"
        exit 2
        ;;
esac

# Не допускаем работу по каталогу на root FS,
# если production MAIN-DATA не смонтирован.
if ! mountpoint -q /srv/main-data; then
    echo "ERROR: /srv/main-data is not mounted."
    echo "Cleanup aborted."
    exit 1
fi

FS_TYPE="$(findmnt -n -o FSTYPE /srv/main-data 2>/dev/null || true)"
if [[ "$FS_TYPE" != "btrfs" ]]; then
    echo "ERROR: /srv/main-data filesystem is '$FS_TYPE', expected 'btrfs'."
    echo "Cleanup aborted."
    exit 1
fi

POLICY=(
    "exchange:7"
    "pivoproduction:14"
    "rozliv:14"
    "utilities:14"
    "software:14"
    "documentation:30"
    "ot-admin:30"
)

echo "============================================================"
echo "Samba recycle cleanup"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S %z')"
echo "Mode: $MODE"
echo "============================================================"

TOTAL_FILES=0
TOTAL_BYTES=0

for ITEM in "${POLICY[@]}"; do
    SHARE="${ITEM%%:*}"
    DAYS="${ITEM##*:}"
    RECYCLE="${BASE}/${SHARE}/.recycle"

    echo
    echo "------------------------------------------------------------"
    echo "Share:     $SHARE"
    echo "Recycle:   $RECYCLE"
    echo "Retention: $DAYS days"
    echo "------------------------------------------------------------"

    if [[ ! -d "$RECYCLE" ]]; then
        echo "INFO: recycle directory does not exist, skipping."
        continue
    fi

    AGE_MINUTES=$((DAYS * 24 * 60))

    while IFS= read -r -d '' FILE; do
        SIZE="$(stat -c '%s' "$FILE" 2>/dev/null || echo 0)"
        TOTAL_FILES=$((TOTAL_FILES + 1))
        TOTAL_BYTES=$((TOTAL_BYTES + SIZE))

        if [[ "$DELETE" == true ]]; then
            echo "DELETE: $FILE"
            rm -f -- "$FILE"
        else
            echo "WOULD DELETE: $FILE"
        fi
    done < <(
        find "$RECYCLE" \
            -xdev \
            -type f \
            -mmin "+${AGE_MINUTES}" \
            -print0
    )

    if [[ "$DELETE" == true ]]; then
        find "$RECYCLE" \
            -xdev \
            -depth \
            -mindepth 1 \
            -type d \
            -empty \
            -delete
    fi
done

echo
echo "============================================================"
echo "Summary"
echo "============================================================"
echo "Matched files: $TOTAL_FILES"
echo "Matched bytes: $TOTAL_BYTES"

if command -v numfmt >/dev/null 2>&1; then
    echo "Matched size:  $(numfmt --to=iec-i --suffix=B "$TOTAL_BYTES")"
fi

if [[ "$DELETE" == true ]]; then
    echo "Result: expired files deleted."
else
    echo "Result: DRY-RUN only. Nothing was deleted."
fi

echo "Finished: $(date '+%Y-%m-%d %H:%M:%S %z')"

Права и контроль синтаксиса:

sudo chmod 0755 /usr/local/sbin/samba-recycle-cleanup
sudo bash -n /usr/local/sbin/samba-recycle-cleanup

20.9.2. Проверка dry-run и удаления

Сначала скрипт был запущен с --dry-run: при отсутствии просроченных файлов он вернул Matched files: 0. Затем в корзине exchange был создан искусственно состаренный на 8 дней файл. Dry-run обнаружил его как WOULD DELETE, но не удалил. Запуск с --delete удалил только этот файл и вернул успешный результат.

20.9.3. systemd service

/etc/systemd/system/samba-recycle-cleanup.service:

[Unit]
Description=Cleanup expired Samba recycle files
Documentation=man:find(1)
RequiresMountsFor=/srv/main-data

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/samba-recycle-cleanup --delete
PrivateTmp=yes
NoNewPrivileges=yes
StandardOutput=journal
StandardError=journal

20.9.4. systemd timer

/etc/systemd/system/samba-recycle-cleanup.timer:

[Unit]
Description=Daily Samba recycle cleanup

[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
RandomizedDelaySec=10m
Unit=samba-recycle-cleanup.service

[Install]
WantedBy=timers.target

Активация:

sudo systemctl daemon-reload
sudo systemctl enable --now samba-recycle-cleanup.timer

systemctl status samba-recycle-cleanup.timer --no-pager
systemctl list-timers samba-recycle-cleanup.timer --all

sudo journalctl \
  -u samba-recycle-cleanup.service \
  -n 100 \
  --no-pager

Контрольный статус: timer active (waiting). После включения 28.10.2026 следующий запуск был назначен на 29.10.2026 03:36:04 +04, что соответствует 03:30 плюс RandomizedDelaySec=10m.

20.10. Защита smbd от запуска без MAIN-DATA

Если D2700 или MAIN-DATA недоступны, каталог /srv/main-data всё равно может существовать на системном root filesystem. Без дополнительной защиты Samba могла бы запуститься и начать принимать данные в этот обычный каталог, заполняя системный диск.

Для smbd.service создан systemd drop-in: /etc/systemd/system/smbd.service.d/main-data.conf.

# ============================================================
# SMR-SRV-OT-SHARE
# Защита Samba от запуска без MAIN-DATA
#
# Не позволять smbd стартовать, если production-хранилище
# /srv/main-data не смонтировано.
# ============================================================

[Unit]

# systemd должен поднять все mount units, необходимые
# для доступа к /srv/main-data, до запуска smbd.
RequiresMountsFor=/srv/main-data


[Service]

# /srv/main-data должен быть именно mountpoint.
# Если MAIN-DATA не смонтирован, ExecStartPre завершится
# неуспешно и smbd не запустится.
ExecStartPre=/usr/bin/mountpoint -q /srv/main-data

Применение и проверка:

sudo systemctl daemon-reload
sudo systemctl cat smbd

mountpoint /srv/main-data
findmnt /srv/main-data

sudo systemctl restart smbd
sudo systemctl status smbd --no-pager

Фактически подтверждено:

/srv/main-data is a mountpoint

TARGET         SOURCE    FSTYPE OPTIONS
/srv/main-data /dev/sdb1 btrfs  rw,relatime,space_cache=v2,subvolid=5,subvol=/

ExecStartPre=/usr/bin/mountpoint -q /srv/main-data
(code=exited, status=0/SUCCESS)

Status: "smbd: ready to serve connections..."

Проверка UUID в ExecStartPre намеренно не добавлялась: для текущей схемы принято оставить защиту простой — systemd dependency плюс проверка факта монтирования.

20.11. NFS

NFS на текущем этапе не установлен и не публикуется. Решение отложено до появления реальной необходимости со стороны Clonezilla или другого клиента. При последующем внедрении необходимо отдельно определить разрешённые сети/клиенты, UID/GID-модель и root squashing.

20.12. Access Based Enumeration

Access Based Enumeration намеренно не включается. Недоступные SMB shares могут отображаться в списке ресурсов сервера, но попытка подключения к ним блокируется через valid users и файловые ACL. Для текущей эксплуатации такое поведение принято как штатное.

20.13. File Browser Next — административный web-доступ

Для административного web-доступа к MAIN-DATA установлен File Browser Next v3.0.0-next. Сервис предназначен для работы из management-сети и не заменяет SMB. Через web-интерфейс администратор видит все восемь функциональных каталогов, включая служебные .snapshots и .recycle.

Для web-интерфейса намеренно не включается скрытие dot-files: административная задача File Browser включает просмотр и обслуживание .snapshots и .recycle.

20.13.1. Версия и бинарный файл

File Browser Next v3.0.0-next
/usr/local/bin/filebrowser

Проверенная SHA-256 загруженного архива filebrowser-linux-amd64.tar.gz:

17a51c2b8fe2eaf88ca4f7a80bd2f2b2e7fe968961bbeb8569a86942696e08b0

20.13.2. Системная учётная запись

user: filebrowser
shell: /usr/sbin/nologin
supplementary group: admins

Сервис не запускается от root. Доступ к файловым ресурсам он получает через существующую POSIX ACL-модель и членство в admins.

id filebrowser
# uid=999(filebrowser) gid=987(filebrowser) groups=987(filebrowser),1001(admins)

20.13.3. Каталоги и база

/etc/filebrowser                  root:root             0755
/var/lib/filebrowser              filebrowser:filebrowser 0750
/var/lib/filebrowser/filebrowser.db

Основные параметры хранятся в BoltDB. Отдельный конфигурационный файл на текущем этапе не используется.

20.13.4. Основные параметры File Browser

Параметр Значение
Root /srv/main-data/baltikashare
Management address 10.44.100.229
TCP port 28443
Authentication json
Locale ru
File mode 0660
Directory mode 0770
Minimum password length 12
Execute disabled
Share disabled
External symlinks disabled
Hide dotfiles false

Первичная проверка выполнялась на 127.0.0.1:28443. После локальной проверки сервис предназначен для bind только на management-адрес 10.44.100.229:28443, а не на 0.0.0.0.

20.13.5. Web-учётная запись

login: baltikafile
scope: /
admin: true
execute: false
share: false

Пароль в документации не хранится.

20.13.6. systemd unit

Файл: /etc/systemd/system/filebrowser.service

# ============================================================
# SMR-SRV-OT-SHARE
# File Browser Next
#
# Web-доступ к данным MAIN-DATA.
# Сервис работает от отдельной системной учётной записи
# filebrowser и получает права через группу admins / POSIX ACL.
# ============================================================

[Unit]
Description=File Browser Next
After=network.target
RequiresMountsFor=/srv/main-data

[Service]
Type=simple
User=filebrowser
Group=filebrowser
SupplementaryGroups=admins
WorkingDirectory=/var/lib/filebrowser

# Не допускаем запуск на пустом каталоге /srv/main-data,
# если production Btrfs по какой-либо причине не смонтирован.
ExecStartPre=/usr/bin/mountpoint -q /srv/main-data

ExecStart=/usr/local/bin/filebrowser \
    -d /var/lib/filebrowser/filebrowser.db

Restart=on-failure
RestartSec=5s
NoNewPrivileges=yes
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

Проверка:

sudo systemctl daemon-reload
sudo systemctl start filebrowser
sudo systemctl status filebrowser --no-pager
sudo ss -ltnp | grep ':28443'
curl -s -o /dev/null -w '%{http_code}\n' http://10.44.100.229:28443/

Ожидаемый HTTP-код: 200.

После окончательной проверки для включения автозапуска:

sudo systemctl enable filebrowser
systemctl is-enabled filebrowser
systemctl is-active filebrowser

20.13.7. Проверенные права

От имени Linux-пользователя filebrowser проверены чтение и запись в рабочий ресурс, доступ ко всем восьми верхнеуровневым каталогам и административный проход в .recycle. Для корзин итоговая проверка дала ACCESS OK на всех семи ресурсах, где используется vfs_recycle.

Удаление файлов через File Browser выполняется непосредственно на файловой системе и не проходит через Samba vfs_recycle. Основной механизм защиты от ошибочных административных изменений в этом случае — Btrfs/Snapper snapshots.

20.13.8. Ограничение management-сети

Management-интерфейс VM: ens19 = 10.44.100.229/24, gateway 10.44.100.1. Целевая модель — публиковать на этом интерфейсе только необходимые административные web-сервисы, в первую очередь File Browser на 28443/tcp. Ограничение firewall выполняется отдельным этапом после инвентаризации текущих слушающих портов, чтобы не потерять административный доступ.

20.14. DNS-имена и DDNS многосетевого файлового сервера

Центральная конфигурация BIND9 описана в отдельной статье «Установка DNS сервера BIND9 на Ubuntu Server 24.04 с Webmin в Proxmox». Здесь фиксируется только конфигурация самого SMR-SRV-OT-SHARE и правила его использования клиентами.

20.14.1. Модель имён

Один multi-homed сервер не публикуется одной A-записью со всеми интерфейсами. Каждый OT-интерфейс получает собственный сегментный FQDN:

Сегмент IP FQDN
Legacy 10.255.0.229 smr-srv-ot-share.legacy.ot-samara.baltika.ru
Пивопроизводство 172.16.66.229 smr-srv-ot-share.pivo.ot-samara.baltika.ru
Розлив 172.16.68.229 smr-srv-ot-share.rozliv.ot-samara.baltika.ru
Утилиты 172.16.70.229 smr-srv-ot-share.utilities.ot-samara.baltika.ru
АСТУЭ 172.17.14.229 smr-srv-ot-share.astue.ot-samara.baltika.ru

PTR каждого адреса указывает на соответствующий сегментный FQDN.

20.14.2. Как клиенты используют короткое имя

На самом SHARE добавление suffix не заставляет удалённые компьютеры использовать его. DNS suffix search list задаётся на клиенте, который выполняет запрос.

Для обычного одноинтерфейсного Windows-клиента основной connection-specific suffix остаётся ot-samara.baltika.ru, а глобальный список поиска содержит два элемента:

Сегмент клиента 1-й suffix 2-й suffix
Legacy legacy.ot-samara.baltika.ru ot-samara.baltika.ru
Pivo pivo.ot-samara.baltika.ru ot-samara.baltika.ru
Rozliv rozliv.ot-samara.baltika.ru ot-samara.baltika.ru
Utilities utilities.ot-samara.baltika.ru ot-samara.baltika.ru
АСТУЭ astue.ot-samara.baltika.ru ot-samara.baltika.ru

Например, клиент Розлива при обращении к \\SMR-SRV-OT-SHARE\exchange сначала проверит SMR-SRV-OT-SHARE.rozliv.ot-samara.baltika.ru и получит 172.16.68.229.

Не добавлять на обычный клиент suffix всех сегментов. Первым должен быть только suffix его локального сегмента, вторым — общая зона.

20.14.3. Установка DNS-утилит

sudo apt update
sudo apt install -y dnsutils

command -v nsupdate
command -v dig

20.14.4. Скрипт /usr/local/sbin/ot-ddns-register

sudo tee /usr/local/sbin/ot-ddns-register >/dev/null <<'SCRIPT_EOF'
#!/usr/bin/env bash

# ============================================================
# SMR-SRV-OT-SHARE
# Регистрация интерфейсных DNS-имён многосетевого сервера
# в авторитетном BIND9 через RFC 2136 / nsupdate.
# ============================================================

set -euo pipefail

TTL=3600
ZONE="ot-samara.baltika.ru."

register_dns()
{
    local iface="$1"
    local ip="$2"
    local dns="$3"
    local fqdn="$4"
    local ptr="$5"

    echo
    echo "============================================================"
    echo "Interface : $iface"
    echo "IP        : $ip"
    echo "DNS       : $dns"
    echo "FQDN      : $fqdn"
    echo "============================================================"

    if ! ip -4 addr show dev "$iface" | grep -qw "$ip"; then
        echo "ERROR: IP $ip отсутствует на интерфейсе $iface"
        return 1
    fi

    route_info="$(ip route get "$dns" | head -n1)"
    echo "Route     : $route_info"

    if ! grep -qw "src $ip" <<< "$route_info"; then
        echo "ERROR: запрос к $dns пойдёт не с source IP $ip"
        return 1
    fi

    nsupdate <<EOF
server $dns
zone $ZONE
update delete $fqdn A
update add $fqdn $TTL A $ip
send
EOF

    nsupdate <<EOF
server $dns
update delete $ptr PTR
update add $ptr $TTL PTR $fqdn
send
EOF

    result_a="$(dig +short +norecurse @"$dns" "$fqdn" A | head -n1)"

    if [[ "$result_a" != "$ip" ]]; then
        echo "ERROR: A verification failed: '$result_a'"
        return 1
    fi

    result_ptr="$(dig +short +norecurse @"$dns" -x "$ip" | head -n1)"

    if [[ "$result_ptr" != "$fqdn" ]]; then
        echo "ERROR: PTR verification failed: '$result_ptr'"
        return 1
    fi

    echo "OK: A   $fqdn -> $ip"
    echo "OK: PTR $ip -> $fqdn"
}

# Legacy OT / VLAN 1.
register_dns \
    "ens23" \
    "10.255.0.229" \
    "10.255.0.53" \
    "smr-srv-ot-share.legacy.ot-samara.baltika.ru." \
    "229.0.255.10.in-addr.arpa."

# Пивопроизводство. Пока 172.16.66.229 находится на ens23.
# После миграции VLAN2030 заменить ens23 на ens21.
register_dns \
    "ens23" \
    "172.16.66.229" \
    "172.16.66.53" \
    "smr-srv-ot-share.pivo.ot-samara.baltika.ru." \
    "229.66.16.172.in-addr.arpa."

# Розлив / VLAN2002.
register_dns \
    "ens20" \
    "172.16.68.229" \
    "172.16.68.53" \
    "smr-srv-ot-share.rozliv.ot-samara.baltika.ru." \
    "229.68.16.172.in-addr.arpa."

# Утилиты / VLAN2040.
register_dns \
    "ens22" \
    "172.16.70.229" \
    "172.16.70.53" \
    "smr-srv-ot-share.utilities.ot-samara.baltika.ru." \
    "229.70.16.172.in-addr.arpa."

# АСТУЭ / VLAN2006.
register_dns \
    "enp2s1" \
    "172.17.14.229" \
    "172.17.14.53" \
    "smr-srv-ot-share.astue.ot-samara.baltika.ru." \
    "229.14.17.172.in-addr.arpa."

echo
echo "============================================================"
echo "OT DDNS registration completed successfully."
echo "============================================================"
SCRIPT_EOF

sudo chown root:root /usr/local/sbin/ot-ddns-register
sudo chmod 0755 /usr/local/sbin/ot-ddns-register

Перед включением автозапуска скрипт проверяется вручную:

sudo /usr/local/sbin/ot-ddns-register

Успешный результат содержит по всем пяти интерфейсам строки OK: A и OK: PTR.

20.14.5. systemd unit

sudo tee /etc/systemd/system/ot-ddns-register.service >/dev/null <<'UNIT_EOF'
[Unit]
Description=Register SMR-SRV-OT-SHARE DNS records in OT BIND9
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/ot-ddns-register

[Install]
WantedBy=multi-user.target
UNIT_EOF

sudo chown root:root /etc/systemd/system/ot-ddns-register.service
sudo chmod 0644 /etc/systemd/system/ot-ddns-register.service

sudo systemctl daemon-reload
sudo systemctl enable ot-ddns-register.service
sudo systemctl start ot-ddns-register.service
sudo systemctl status ot-ddns-register.service --no-pager
sudo journalctl -u ot-ddns-register.service -n 100 --no-pager

Для Type=oneshot состояние inactive (dead) после выполнения является нормальным. Критерий успеха: code=exited, status=0/SUCCESS и успешные проверки A/PTR.

20.14.6. Фактически зарегистрированные A/PTR

FQDN A PTR
smr-srv-ot-share.legacy.ot-samara.baltika.ru 10.255.0.229 на это же FQDN
smr-srv-ot-share.pivo.ot-samara.baltika.ru 172.16.66.229 на это же FQDN
smr-srv-ot-share.rozliv.ot-samara.baltika.ru 172.16.68.229 на это же FQDN
smr-srv-ot-share.utilities.ot-samara.baltika.ru 172.16.70.229 на это же FQDN
smr-srv-ot-share.astue.ot-samara.baltika.ru 172.17.14.229 на это же FQDN

PTR для сетей /23. У SHARE адреса Пивопроизводства, Розлива и Утилит находятся в первых половинах соответствующих /23: 172.16.66.229, 172.16.68.229 и 172.16.70.229. Поэтому их PTR находятся соответственно только в reverse-зонах 66.16.172.in-addr.arpa, 68.16.172.in-addr.arpa и 70.16.172.in-addr.arpa.

Парные зоны 67.16.172.in-addr.arpa, 69.16.172.in-addr.arpa и 71.16.172.in-addr.arpa существуют и обслуживаются тем же BIND9, но используются для узлов с адресами 172.16.67.x, 172.16.69.x и 172.16.71.x. Дублировать в них PTR адресов SHARE нельзя.

05.11.2026 ручной запуск и запуск через systemd завершились успешно для всех пяти пар A/PTR.

20.14.7. Миграция Пивопроизводства на VLAN2030

При переносе 172.16.66.229/23 с ens23 на ens21 одновременно:

  • перенести IP в Netplan; один IP не должен одновременно присутствовать на двух интерфейсах;
  • перенести DNS 172.16.66.53 и route-only domains ~ot-samara.baltika.ru, ~66.16.172.in-addr.arpa и ~67.16.172.in-addr.arpa на ens21; на ens23 оставить только Legacy DNS/домены;
  • в /usr/local/sbin/ot-ddns-register для Pivo заменить ens23 на ens21;
  • запустить sudo systemctl start ot-ddns-register.service и проверить журнал.

21. Текущая контрольная точка

Этап Состояние
P411 Slot 1, firmware 6.64, 512 MB FBWC, PCIe Gen2 x8, Status OK
D2700 firmware 0150, 25/25 дисков OK
MAIN-DATA RAID50, 5.46 TiB, production Btrfs, VM 103
RECOVERY RAID1, около 136 GiB
CRITICAL-BACKUP RAID50, около 3.64 TiB
GLOBAL-SPARE bay 15, shared spare, OK
Parity RAID50 Queued; эксплуатацию не блокирует, контролируется
Production Btrfs LABEL MAIN-DATA, mount /srv/main-data
Subvolume 8 functional Btrfs subvolume
Snapper 8 configs; timeline/cleanup timers active
POSIX ACL SGID/default ACL настроены; корзины переведены на приватную модель .recycle/<user> + административный доступ admins
Samba введена в эксплуатацию; 8 shares; матрица доступа проверена
vfs_recycle 7 shares; directory_mode/subdir_mode = 0770; sticky bit и ACL проверены; clonezilla исключён намеренно
Очистка .recycle production-скрипт + systemd timer; dry-run/delete проверены
vfs_snapper Windows Previous Versions: просмотр и восстановление проверены
Служебные каталоги .snapshots veto; .recycle hidden
Защита smbd RequiresMountsFor + mountpoint ExecStartPre работают
File Browser Next v3.0.0-next; отдельный user filebrowser; web-admin baltikafile; root MAIN-DATA; port 28443
Management route default via 10.44.100.1 dev ens19; 192.168.1.229/24 без default gateway
File Browser / recycle доступ к .recycle на всех 7 recycle-shares проверен; повторное создание .recycle/pivo проверено
ABE не используется по принятому решению
NFS не установлен; внедрение отложено до реальной необходимости
Split DNS systemd-resolved: per-link OT DNS и route-only domains для прямой и reverse-зон; проверено
DNS-имена SHARE 5 сегментных FQDN; A/PTR зарегистрированы и проверены. Для сетей /23 PTR находится только в reverse-зоне /24, соответствующей фактическому IP; дублирования в парную зону нет.
Linux DDNS ot-ddns-register + ot-ddns-register.service; systemd запуск завершён status=0/SUCCESS

21.1. Следующие этапы

После следующей плановой перезагрузки один раз проверить boot-журнал ot-ddns-register.service.

При переводе Пивопроизводства на VLAN2030 выполнить DNS-миграцию ens23 → ens21 по разделу 20.14.7.

При вводе клиентов новых сегментов стандартизировать двухэлементный DNS suffix search list: локальный сегментный suffix + ot-samara.baltika.ru.

  1. Провести инвентаризацию слушающих портов и настроить firewall для management-интерфейса 10.44.100.229; оставить только сознательно необходимые административные сервисы.
  2. Настроить копирование выбранных критичных данных на CRITICAL-BACKUP.
  3. Добавить мониторинг P410i/P411, D2700, physical disks, Btrfs usage, Snapper, mount, Samba и File Browser.
  4. NFS внедрять только при появлении реальной необходимости; первым потенциальным потребителем остаётся Clonezilla.
  5. Отдельно решить вопрос постоянного использования hpsa_simple_mode=1.
  6. Отдельно оценить необходимость Dual Domain через второй порт P411 и I/O Module B.

22. Порядок включения и выключения D2700

22.1. Включение

  1. Подать питание на оба БП D2700.
  2. Включить полку и дождаться инициализации.
  3. Включить DL380 G7.
  4. Проверить POST P411 и доступность logical drive.

22.2. Выключение

  1. Корректно остановить VM.
  2. Корректно остановить Proxmox/DL380.
  3. Дождаться полного выключения сервера.
  4. Перевести D2700 в Standby.
  5. При необходимости снять AC с БП полки.

22.3. Восстановление питания

Желаемая последовательность: сначала D2700 и её инициализация, затем запуск DL380 G7 с задержкой. Поведение после полного снятия и возврата AC требуется отдельно проверить в production-конфигурации.

23. Справочные материалы

  • Btrfs documentation
  • Snapper documentation
  • Samba vfs_snapper / vfs_recycle
  • HPE Smart Array / D2700 documentation
  • File Browser Next documentation / release v3.0.0-next

BookStack page: HP D2700: схема дисковых массивов и назначение хранилищ

Обновление 1.0: фактическая конфигурация Samba и результаты тестов добавлены 28.10.2026.
Обновление 1.1: проверены Windows Previous Versions, скрытие служебных каталогов, автоматическая очистка Samba recycle и защита smbd от запуска без MAIN-DATA; ABE оставлен отключённым.
Обновление 1.2: добавлены File Browser Next, management gateway 10.44.100.1, production ACL для Samba recycle, проверка повторного создания персональной корзины и актуальная контрольная точка на 30.10.2026.

BookStack: Установка DNS сервера BIND9 на Ubuntu Server 24.04 с Webmin в Proxmox

Обновление 1.3: добавлены split DNS через systemd-resolved, сегментные FQDN файлового сервера, RFC 2136/DDNS через nsupdate, ot-ddns-register.service, клиентская модель DNS suffix search list и процедура миграции Pivo на ens21. 05.11.2026.

Обновление 1.4: уточнена логика reverse DNS для сетей /23. Обе половины /23 обслуживаются отдельными reverse-зонами /24, но PTR конкретного адреса SHARE создаётся только в той зоне, которой принадлежит его фактический IP. Для 172.16.66.229, 172.16.68.229 и 172.16.70.229 это зоны 66, 68 и 70.16.172.in-addr.arpa; зоны 67, 69 и 71 предназначены для других адресов второй половины соответствующих /23. 06.11.2026.