Skip to content

Instantly share code, notes, and snippets.

@erkserkserks
Last active November 26, 2023 10:11
Show Gist options
  • Save erkserkserks/0d48f75e1a36bc9e1ccdc3e1428efba0 to your computer and use it in GitHub Desktop.
Save erkserkserks/0d48f75e1a36bc9e1ccdc3e1428efba0 to your computer and use it in GitHub Desktop.
Fast UTM shared directories using Samba

Fast UTM shared directories using Samba

Problem

UTM's shared directory implementation relies on SPICE WebDAV, which is slow.

Solution

Use Samba for faster shared directories. Samba is ~5x faster, see benchmarks at the end.

Mac Setup

Note: Tested on macOS 11.4 on M1 Macbook Air, UTM 2.1.1, Ubuntu 20.04 arm64.

  1. Install samba using MacPorts. The built in macOS samba may work, but I have not tested this. The macOS version of samba is non-standard and is more difficult to find documentation for.

    sudo port install samba4
    
  2. Create the samba configuration file

    sudo vi /opt/local/etc/samba/smb.conf
    

    Here is an example configuration that shares the ~/Downloads directory on the lo0 (loopback) interface for the sambauser user. Note that the samba server only listens on the loopback interface; it is inaccessible outside of the local machine.

    [global]
       workgroup = WORKGROUP 
       server string = samba server
       server role = standalone server
       bind interfaces only = yes
       interfaces = lo0
       max log size = 50
       passdb backend = tdbsam
    
    [Downloads]
       comment = Downloads 
       path = /Users/<username>/Downloads
       valid users = sambauser
       create mask = 664
       public = no
       writable = yes
    

    You may also need to create the samba log directory: sudo mkdir -p /opt/local/var/log/samba

  3. In macOS preferences, create a new (sharing only) user called sambauser.

  4. Once the local account sambauser has been created, then add the corresponding samba user account:

    sudo smbpasswd -a sambauser
    
  5. Modify permissions of the shared directory so that sambauser can access it. For example:

    chmod 770 ~/Downloads
    
  6. Test authentication (run both commands on macOS):

    Run the server:

    sudo /opt/local/sbin/smbd  --debuglevel=10 --log-stdout --foreground
    

    Connect to the server:

    smbclient -L localhost -U sambauser
    

    You should be able to authenticate successfully.

  7. Configure macOS to launch samba server at boot.

    Create the launchd plist:

    sudo vi /Library/LaunchDaemons/org.samba.smbd.plist
    

    Add the following:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    	<dict>
    		<key>Label</key>
    		<string>org.samba.smbd</string>
    		<key>ProgramArguments</key>
    		<array>
    			<string>/opt/local/sbin/smbd</string>
    			<string>--foreground</string>
    			<string>--no-process-group</string>
    		</array>
    		<key>RunAtLoad</key>
    		<true/>
    		<key>KeepAlive</key>
    		<true/>
    		<key>ServiceDescription</key>
    		<string>samba</string>
    	</dict>
    </plist>
    
  8. Load and start the job

    Run:

    sudo launchctl load /Library/LaunchDaemons/org.samba.smbd.plist
    

    You should see success in the logs:

    tail -f /opt/local/var/log/samba/log.smbd
    
    
    [2021/06/18 18:20:19.580395,  0] ../../source3/smbd/server.c:1784(main)
      smbd version 4.13.1 started.
      Copyright Andrew Tridgell and the Samba Team 1992-2020
    [2021/06/18 18:20:19.593845,  0] ../../lib/util/become_daemon.c:136(daemon_ready)
      daemon_ready: daemon 'smbd' finished starting up and ready to serve connections
    

    You should see smbd processes when running ps:

    ps aux | grep smbd
    
    root              4619   0.0  0.1  4790608   9632   ??  S     6:20PM   0:00.01 /opt/local/sbin/smbd --foreground --no-process-group
    root              4616   0.0  0.0  4792928   4880   ??  S     6:20PM   0:00.00 /opt/local/sbin/smbd --foreground --no-process-group
    root              4615   0.0  0.0  4758640   3216   ??  S     6:20PM   0:00.00 /opt/local/sbin/smbd --foreground --no-process-group
    root              4614   0.0  0.0  4766832   3664   ??  S     6:20PM   0:00.00 /opt/local/sbin/smbd --foreground --no-process-group
    root              4613   0.0  0.1 408484096  18016   ??  Ss    6:20PM   0:00.07 /opt/local/sbin/smbd --foreground --no-process-group
    

    Reboot your mac and check that smbd is runnning.

Ubuntu Setup

  1. Install cifs-utils so the samba share can be mounted:

    sudo apt install cifs-utils
    
  2. Create the mountpoint:

    sudo mkdir /mnt/smb
    
  3. Mount the samba share. Note: With the default UTM/QEMU configuration, the guest can access the host at 10.0.2.2.

    sudo mount -t cifs -o user=sambauser /10.0.2.2/Downloads /mnt/smb
    
  4. Mount smb share automatically at boot.

    Create credential file:

    vi /home/<username>/.smbcredentials
    

    Add the following:

    username=sambauser
    password=<your password here>
    

    Open fstab file:

    sudo vi /etc/fstab
    

    Add the following:

    //10.0.2.2/Downloads /mnt/smb cifs uid=1000,credentials=/home/<username>/.smbcredentials 0 0
    

    You can find your uid by running id -u.

    Test by running:

    sudo mount -a
    

    No errors should appear.

  5. Reboot the Ubuntu VM and check that /mnt/smb has the expected contents.

Benchmarks

Benchmarks show that Samba is significantly (~5x) faster than WebDAV.

The below command creates a 4GB file and performs 4KB reads and writes using a 75%/25% split within the file, with 64 operations running at a time (source):

fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=4G --filename=/mnt/smb/testfile

WebDAV Results

test: (groupid=0, jobs=1): err= 0: pid=4104: Sat Jun 19 04:45:23 2021
  read: IOPS=4174, BW=16.3MiB/s (17.1MB/s)(3070MiB/188281msec)
   bw (  KiB/s): min=  386, max=24769, per=100.00%, avg=18492.86, stdev=4240.84, samples=328
   iops        : min=   96, max= 6192, avg=4622.96, stdev=1060.22, samples=328
  write: IOPS=1395, BW=5580KiB/s (5714kB/s)(1026MiB/188281msec); 0 zone resets
   bw (  KiB/s): min=  111, max= 8784, per=100.00%, avg=6183.13, stdev=1437.66, samples=328
   iops        : min=   27, max= 2196, avg=1545.49, stdev=359.40, samples=328
  cpu          : usr=2.07%, sys=12.78%, ctx=1048728, majf=1, minf=126
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued rwts: total=785920,262656,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: bw=16.3MiB/s (17.1MB/s), 16.3MiB/s-16.3MiB/s (17.1MB/s-17.1MB/s), io=3070MiB (3219MB), run=188281-188281msec
  WRITE: bw=5580KiB/s (5714kB/s), 5580KiB/s-5580KiB/s (5714kB/s-5714kB/s), io=1026MiB (1076MB), run=188281-188281msec

Samba Results

test: (groupid=0, jobs=1): err= 0: pid=4135: Sat Jun 19 04:51:19 2021
  read: IOPS=20.4k, BW=79.6MiB/s (83.5MB/s)(3070MiB/38572msec)
   bw (  KiB/s): min=63480, max=119361, per=99.77%, avg=81313.23, stdev=10849.17, samples=77
   iops        : min=15870, max=29840, avg=20328.09, stdev=2712.31, samples=77
  write: IOPS=6809, BW=26.6MiB/s (27.9MB/s)(1026MiB/38572msec); 0 zone resets
   bw (  KiB/s): min=21880, max=40088, per=99.77%, avg=27175.34, stdev=3643.98, samples=77
   iops        : min= 5470, max=10022, avg=6793.61, stdev=911.01, samples=77
  cpu          : usr=5.23%, sys=57.15%, ctx=204667, majf=0, minf=16
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued rwts: total=785920,262656,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: bw=79.6MiB/s (83.5MB/s), 79.6MiB/s-79.6MiB/s (83.5MB/s-83.5MB/s), io=3070MiB (3219MB), run=38572-38572msec
  WRITE: bw=26.6MiB/s (27.9MB/s), 26.6MiB/s-26.6MiB/s (27.9MB/s-27.9MB/s), io=1026MiB (1076MB), run=38572-38572msec
@munapower
Copy link

Hello, I have followed your tutorial and have not been able to connect from Ubuntu to my MacOs share. I did try on my MacOs side to run smbclient and I get listed the shares, when I try to mount from the Ubuntu side I get a protocol negotiation failed: NT_STATUS_CONNECTION_DISCONNECTED
What I wonder is what type of Network definition do you have in UTM for the Ubuntu VM?

@munapower
Copy link

Hello, I have followed your tutorial and have not been able to connect from Ubuntu to my MacOs share. I did try on my MacOs side to run smbclient and I get listed the shares, when I try to mount from the Ubuntu side I get a protocol negotiation failed: NT_STATUS_CONNECTION_DISCONNECTED What I wonder is what type of Network definition do you have in UTM for the Ubuntu VM?

I found out. Emulated VLAN.

@unphased
Copy link

unphased commented Jun 29, 2022

I was able to get samba set up with my UTM running aarch64 Ubuntu 22.04, hoping for good performance (not interested in installing Spice...) and the performance is underwhelming:

Run status group 0 (all jobs):
   READ: bw=28.3MiB/s (29.7MB/s), 28.3MiB/s-28.3MiB/s (29.7MB/s-29.7MB/s), io=3070MiB (3219MB), run=108553-108553msec
  WRITE: bw=9678KiB/s (9911kB/s), 9678KiB/s-9678KiB/s (9911kB/s-9911kB/s), io=1026MiB (1076MB), run=108553-108553msec

I will try and see if switching from bridged networking back to the default or some kind of NATted setup could bring the speed back. I noticed while this was running that iStat Menus showed no network activity, but Little Snitch's network monitor did show the activity.

@unphased
Copy link

unphased commented Jun 29, 2022

Hi there, I switched over to "Shared Network" in UTM and thankfully got some reasonable looking throughput:

Run status group 0 (all jobs):
   READ: bw=104MiB/s (109MB/s), 104MiB/s-104MiB/s (109MB/s-109MB/s), io=3070MiB (3219MB), run=29516-29516msec
  WRITE: bw=34.8MiB/s (36.4MB/s), 34.8MiB/s-34.8MiB/s (36.4MB/s-36.4MB/s), io=1026MiB (1076MB), run=29516-29516msec

CPU utilization on the M1 Max was through the roof though, and the raw performance seen here is nothing to write home about especially considering this is local machine to local machine, and that 2.5Gbit ethernet is already way faster (even my Wifi is faster than this write speed), but... I'll take what I can get if this is the best we can do for now.

Also, Emulated VLAN was not good. I could curl google.com, but any time I pinged anything it reported lots of errors. Seemed to be pretty buggy. And yeah, could confirm, in that mode I couldn't even connect to smb.

@mrcalvin
Copy link

Hi! I followed through the guideline successfully till the moment of actually working with the shares (accessing them is possible), but they appear all empty except for the directories: See https://apple.stackexchange.com/questions/466771/smbd-on-macos-shares-appear-empty-only-directories-no-files. Anyone experienced the same? Any hints?

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