
I’m using a Mikrotik RDS2216 as a ethernet switch and NVMe-OF storage server for my home Proxmox cluster. The RDS2216 and Mikrotik RouterOS Storage Edition (ROSE) are relatively new products, so I’ve run into a few surprises and sharp edges but overall it’s working.
Instructions on how to set up RAID and NVMeOF exports on ROSE are rather spotty so I had to piece together how to get it to work from available docs, on-device tab-completion, and through trial & error. Unfortunately I realized that I forgot to write down how set it up after losing RAID arrays and NVMeOF exports because of the 2025-11 quirk listed below. So, now I’m documenting here 😊
I prefer to manage storage by position-independent attributes, so you’ll see [ find key=value ] matching in set statements.
/disk set [ find serial=S64GNG0X413417 ] comment=tk8s-node1-a self-encryption-password=SuperSecureSecretSentence
I set a comment on each drive of volumename-volumeindex where volumeindex a..z indicates the drive’s position in the RAID array. I don’t bother with the -volumeindex part if the drive isn’t going to be part of an array.
All the 7mm U.2 drives I’ve found support the TCG Opal self-encrypting drive standard, so I always use it so I don’t have to worry about physically destroying drives if they fail – data unreadable1 as soon as the drive is separated from the RDS2216 or the RDS2216’s config is wiped.
/disk add type=raid raid-type=1 raid-device-count=2 mount-filesystem=no comment=tk8s-node1
/disk set [ find comment=tk8s-node1-a ] raid-master=[ find comment=tk8s-node1 ]
/disk set [ find comment=tk8s-node1-b ] raid-master=[ find comment=tk8s-node1 ]
raid-type is set to the RAID level. E.g. 0=stripe, 1=mirror, 5=striping with parity for single-disk failure, 6=striping with parity for double-disk failure.
raid-device-count is the number of drives used in the array not including any spares.
We don’t specify the slot because RouterOS will automatically pick the next raid-arrayN.
We reduce the risk of changing the wrong RAID config or adding/removing disks from the wrong array by never directly specifying e.g. slot=raid-array1 and by setting raid-master using find instead of a hardcoded value.
We want raid-role to correspond to volumeindex as a=0, b=1, c=2, and so on. If you omit raid-role RouterOS will autoincrement, so be sure to add drives in order or specify the correct raid-role.
Easy enough, except no access control – I haven’t been able to get nvme-tcp-server-allow-host-name to work.
/disk set [ find comment=tk8s-node1 ] nvme-tcp-export=yes
And test by running nvme discover on your Linux host:
root@gpc1:/# nvme discover -t tcp -a 10.8.9.1 -s 4420
Discovery Log Number of Records 1, Generation counter 60
=====Discovery Log Entry 0======
trtype: tcp
adrfam: ipv4
subtype: nvme subsystem
treq: not specified, sq flow control disable supported
portid: 4420
trsvcid: 4420
subnqn: raid-array2
traddr: 10.8.9.1
eflags: none
sectype: none
Set fec-mode=fec74
Example full config line:
/interface/ethernet set [ find default-name=qsfp28-2-1 ] advertise=25G-baseCR comment="Server: gpc1 (frontend)" fec-mode=fec74 l2mtu=9100
I recently cabled up the 25G ports on the RDS2216 to this same NIC and needed to leave it at auto. Am not sure if this was resolved in a Mikrotik firmware update or if the problem I encountered was specific to using a QSFP28 breakout on the 100G port.
raid-arrayN and prior I used a value of my volume name (e.g. gpc1-util1) so I could see sensical names on my hosts instead of leaking storage details like raid-array4.Yes, I know that the data isn’t destroyed. It could be recovered if someone knew the secret or if there was a defect in the drive firmware. SED is good enough for my threat model. ↩︎