Skip to content

Instantly share code, notes, and snippets.

@othyn
Last active September 21, 2025 20:13
Show Gist options
  • Save othyn/4554c1f409f34d1674ba2095acf441ee to your computer and use it in GitHub Desktop.
Save othyn/4554c1f409f34d1674ba2095acf441ee to your computer and use it in GitHub Desktop.
Fix horrendously bad macOS (12.3.1 tested) SMB (Samba) performance on Unraid

Intro

Out of the box, my SMB performance on macOS 12.3.1 would top out at around 20MB/s in short ~5 second bursts, which was absolutely horrendous, slow to navigate in Finder and slugish to interact with.

Since making these changes, I now get sustained ~80-100MB/s+ and instant Finder navigation which is superb and how things should be out-of-the-box (OOTB)!

May 2023 update: As of Ventura, the SMB issues were just horribly inconsistent and hard to maintain. Something in the combination of Unraid, macOS and SMB just doesn't play nice. I ended up binning NFS/SMB all together and heading to a locally hosted Nextcloud instance for file syncing, then using SFTP/Ansible Git flow for editing files within appdata.

Sources

  1. Apple - Disable local SMB directory enumeration caching
  2. Apple - Adjust SMB browsing behavior in macOS
  3. 45Drives - KB450114 – MacOS Samba Optimization
  4. Unraid Forum - Maxrad Post (the absolute legend)

Guide

macOS Changes

  1. Prevent macOS writing ._DS_Store files to SMB shares (Source #2), just enter the following into your mac's terminal:
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE
  1. Configure macOS to disable directory caching (Source #1) and request signing/verification (Source #3), the following should be the contents of the existing /etc/nsmb.conf file if you have it, or create it if you don't (may require sudo):
[default]
dir_cache_max_cnt=0
signing_required=no
  1. After a reboot, run $ smbutil statshares -a in a terminal window in macOS whilst connected to your SMB shares. The commands output should NOT contain SIGNING_ON TRUE (Source #3).

Unraid / SMB (Samba) Changes

  1. On your Unraid box, login to the web GUI and stop your array.

  2. Head to: Settings > SMB > SMB Extras > Samba Extra Configuration.

  3. Paste the following into the text field (Source #4), making sure to edit "MY_SHARE" to be the name of your share and cloning that block for any more shares that you may have, in this case also renaming or removing "MY_OTHER_SHARE" to meet your needs.

#unassigned_devices_start
#Unassigned devices share includes
   include = /tmp/unassigned.devices/smb-settings.conf
#unassigned_devices_end

[global]
   vfs objects = catia fruit streams_xattr
   fruit:nfs_aces = no
   fruit:zero_file_id = yes
   fruit:metadata = stream
   fruit:encoding = native
   spotlight backend = tracker

[MY_SHARE]
   path = /mnt/user/MY_SHARE
   veto files = /._*/.DS_Store/
   delete veto files = yes
   spotlight = yes

[MY_OTHER_SHARE]
   path = /mnt/user/MY_OTHER_SHARE
   veto files = /._*/.DS_Store/
   delete veto files = yes
   spotlight = yes
  1. Hit Apply once done in which Unraid will then apply the SMB configuration.

  2. Before starting the array again, run $ testparm -s in the Unraid web GUI terminal or via SSH'ing onto your Unraid box, this is to ensure that all is working and Samba has accepted the configuration. It should look something like the following, just with your share names instead of the example ones and should have no errors:

Load smb config files from /etc/samba/smb.conf
lpcfg_do_global_parameter: WARNING: The "null passwords" option is deprecated
Loaded services file OK.
Weak crypto is allowed

Server role: ROLE_STANDALONE

# Global parameters
[global]
	disable netbios = Yes
	disable spoolss = Yes
	load printers = No
	logging = syslog@0
	map to guest = Bad User
	multicast dns register = No
	ntlm auth = ntlmv1-permitted
	null passwords = Yes
	passdb backend = smbpasswd
	printcap name = /dev/null
	security = USER
	server min protocol = SMB2
	server string = Network Attached Storage
	show add printer wizard = No
	unix extensions = No
	fruit:zero_file_id = yes
	fruit:nfs_aces = no
	fruit:encoding = native
	fruit:locking = none
	fruit:metadata = stream
	fruit:resource = file
	fruit:aapl = yes
	idmap config * : range = 3000-7999
	idmap config * : backend = tdb
	acl allow execute always = Yes
	aio read size = 0
	aio write size = 0
	create mask = 0777
	directory mask = 0777
	hide dot files = No
	include = /tmp/unassigned.devices/smb-settings.conf
	invalid users = root
	map archive = No
	map readonly = yes
	spotlight backend = tracker
	use sendfile = Yes
	vfs objects = catia fruit streams_xattr
	wide links = Yes


[MY_SHARE]
	delete veto files = Yes
	path = /mnt/user/MY_SHARE
	spotlight = Yes
	veto files = /._*/.DS_Store/

[MY_OTHER_SHARE]
	delete veto files = Yes
	path = /mnt/user/MY_OTHER_SHARE
	spotlight = Yes
	veto files = /._*/.DS_Store/
  1. Start the array and connect the macOS client to the SMB share and test that its working nicely, maybe do some test copies and check that the performance is what you expect.

  2. Done!

@SoCuul
Copy link

SoCuul commented Sep 21, 2025

@superKoder what is your speed after you did that? I added those settings to nsmb.conf but I still see the same speed.

Here's my entire nsmb.conf file which should hopefully maximize the performance on the latest macOS versions:

[default]

# Disable SMB signing (decreases security, for speed)
signing_required=no

# Disable SMB session signing (decreases security, for speed)
validate_neg_off=yes

# How to use SMB TCP/UDP ports.
# normal: Attempt to connect via port 445. If that is unsuccessful, try to connect via NetBIOS.
# netbios_only: Do not attempt to connect via port 445.
# no_netbios: Attempt to connect via port 445. If that is unsuccessful, do not try NetBIOS.
port445=no_netbios

# Force SMB protocol versions
# Protocol version is specified using binary bitmap # 1 => 0001 => SMB 1 only
# 2 => 0010 => SMB 2 only
# 3 => 0011 => SMB 1 or 2
# 4 => 0100 => SMB 3 only
# 6 => 0110 => SMB 2 or 3
protocol_vers_map=6

# SMB Negotiation (normal, smb1_only, smb2_only, smb3_only)
smb_neg=smb3_only

# Enable soft/hard mounts of shares
# Hard mount: a request is issued repeatedly until the request is satisfied.
# Soft mount: tried until completed, the retry limit is met or the timeout limit is met.
soft=yes

# Force enabling alternate data streams (named streams)
streams=yes

# Enable multi-channel support and prefer wired connections
mc_on=yes
mc_prefer_wired=yes

# Disable directory enumeration caching
# Ensures Finder folder contents display is up to date
dir_cache_off=yes
dir_cache_max_cnt=0
dir_cache_max=0

# Disable change notifications (neutral security impact, but might affect operational efficiency)
notify_off=yes

# Change max response timeout to allow for slower connections
max_resp_timeout=600

# Enable Apple SMB extensions
# 
# ReadDirAttr: This feature changes how macOS handles reads of file metadata stored in
#   alternate data stream when listing the contents of large directories. Finder info, 
#   access rights, and resource fork size are returned more efficiently for the files
#   in the directory.
# 
# OsxCopyFile: With the SMB2 protocol, Microsoft implemented server-side optimizations 
#   when copying files between directories on the file share. The extension introduced by 
#   Apple ensures that all Apple-specific file metadata is properly copied along with the file 
#   itself. The copy process is also simplified as it is executed in just one request as 
#   opposed to splitting the requests into logical chunks which was the case in 
#   the original feature.
aapl_off=false

After replacing your nsmb.conf file, then run the following commands to ensure proper functionality:

# Set proper permissions on nsmb.conf
sudo chown root:wheel /etc/nsmb.conf
sudo chmod 644 /etc/nsmb.conf

# Prevent creation of .DS_Store files on network shares
sudo defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE

# Improve speed of loading large shares
sudo defaults write com.apple.desktopservices UseBareEnumeration -bool FALSE

# Flush DNS caches
sudo killall -HUP mDNSResponder > /dev/null 2>&1
sudo killall mDNSResponderHelper >> /dev/null 2>&1
sudo dscacheutil -flushcache

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment