Introduction

Time Machine on macOS does not like windows hosts as targets, likely due to noncompliance to Time Machine over SMB Specification.

In this article, we’ll document the steps to create a compatible Time Machine target via AFP using netatalk running under Ubuntu in WSL 2 or WSL 1

Selecting WSL version

While WSL 2 offers better compatibility by means of full Linux kernel running in VM (see https://docs.microsoft.com/en-us/windows/wsl/compare-versions), there are some issue which may make WSL 1 a better choice for our purposes, at least for now:

Install WSL and pick default version:

In the new cmd session:

wsl --install

Reboot when prompted, relaunch the cmd and set the chosen WSL version as default:

wsl --set-default-version 2

or

wsl --set-default-version 1

For details and best practices please refere to the documentation https://docs.microsoft.com/en-us/windows/wsl/install

Install Ubuntu and configure netatalk

  1. Install the desired distribution (from https://aka.ms/wslstore or directly in the CMD):
     wsl --list --online
     wsl --install -d ubuntu-20.04
    
  2. Unless the shell into the newly installed distribution has launched in a separate window – launch it by name. In this case, ubuntu2004 (note, remove punctuation). You can also run the default simply by running wsl:
     wsl
    
  3. After a while, a prompt to set up the username and password will appear. These credentials will be used to connect to AFP share from the Mac later. Proceed with configuring them and wait for the shell prompt to appear.

  4. Optional. At this point I would get rid of all non-essential packages as described here https://askubuntu.com/questions/79665/keep-only-essential-packages. There is no reason to keep all the bloatware, including snapd and graphics drivers for our purposes.

  5. Start logging service (will be helpful for troubleshooting if anything goes wrong):
     sudo service rsyslog start
    

    Logs can be viewed by tailing /var/log/syslog

  6. Update repositories and install netatalk:
     sudo apt update
     sudo apt -y upgrade
     sudo apt -y install netatalk 
    
  7. Edit /etc/netatalk/afp.conf to configure paths to the folders to be shared. Windows disks are mounted under /mnt/. For example, to share general purpose folder name Storage and another one dedicated to Time Machine named Time Machine located in the root of windows drive R: add the following:
     [Storage]
     path = /mnt/r/Storage
        
     [Time Machine]
     path = '/mnt/r/Time Machine'
     time machine = yes
    

    Note, if you later want to make changes to the file, restart netatalk with sudo service netatalk restart.

  8. Allow starting the netatalk (and optionally logging) service without prompts. Edit sudoers file via sudo visudo and add the following lines:
     %sudo   ALL=(ALL) NOPASSWD: /usr/sbin/service netatalk start
     %sudo   ALL=(ALL) NOPASSWD: /usr/sbin/service rsyslog start
    
  9. Start the service
     sudo service netatalk start
    
  10. If Windows firewall prompted for access – click Allow access. Otherwise, add the rule manually:
     netsh advfirewall firewall add rule name="Allow AFP connections" dir=in action=allow protocol=TCP localport=548
    

Service startup script

WSL 2

WSL 2 runs in a separate internal network connected to an internal Hyper-V virtual switch named WSL. Unfortunately, it is not feasible to make it external without breaking everything around it, so we’ll instead create a port mapping. Consequently, mDNS/Bonjour won’t work to advertise AFP shares and Time Machine services, but that’s not a big deal: windows host supports mDNS, so we can connect to it directly in the finder via Command+K, afp://windows-host-name.local.

To configure firewall to access the WSL instance, we will build on the excellent script shared here: https://github.com/microsoft/WSL/issues/4150#issuecomment-504209723

Additionally, it may be helpful to start the logging service as well, just to be able to troubleshoot any possible runtime issues with the netatalk in the future.

Create the script somewhere accessible, like c:\Scripts\wsl_startup.ps1, with the following content:

$remoteport = bash.exe -c "hostname -I"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

iex "netsh interface portproxy add v4tov4 listenport=548 listenaddress=0.0.0.0 connectport=548 connectaddress=$remoteport";

wsl sudo service rsyslog start
wsl sudo service netatalk start

WSL 1

There is no need to configure port forwarding. Remove any existing forwards you might have created when playing with WSL 2 above:

netsh interface portproxy show v4tov4
netsh interface portproxy delete v4tov4 listenport=548 listenaddress=0.0.0.0

Create the script somewhere accessible, like c:\Scripts\wsl_startup.ps1, with the following content:

wsl sudo service rsyslog start
wsl sudo service netatalk start

If logging is not needed and therefore the contents of the script condense to a single line it can be directly scheduled in the Task Scheduler (program name wsl, arguments sudo service netatalk start).

Scheduling service startup

Using Task Scheduler, create a new task to launch the script on each Windows start:

  1. search for Task Scheduler and launch it
  2. ActionCreate Task
  3. General:
    1. Name: Pick something, e.g. AFP Startup
    2. Security Options: Select Run whether user is logged on or not
    3. Security Options: Check Run with highest privileges
    4. Configure for: Windows 10
  4. TriggersNew...
    1. Begin the task: At startup
    2. Delay the task: 15 seconds (just in case)
    3. Press OK
  5. ActionsNew...
    1. Action: Start a program
    2. Program/script: powershell.exe
    3. Add arguments: -ExecutionPolicy Unrestricted -File c:\Scripts\wsl_startup.ps1
  6. Press OK. Enter the administrator account credentials as requested.

To test the whole thing, including the scheduler item, restart windows host. Then on macOS, try to connect to it:

Connecting from macOS and configuring Time Machine

  1. Press Command+K in Finder, type afp://windows-host-name.local, press Enter.
  2. Pick the Time Machine share and press OK.
  3. Now that is it mounted, go to Time Machine settings in System Preferences, and click Select Disk. Pick the available share from the list (named as configured in afpd.conf above).

That’s pretty much it. The Time Machine from there on will be auto-mounting the share to perform the backup.

History

Dec 12, 2021 initial publication
Dec 14, 20201 added WSL 1 specifics and simplified scripts