Time Machine on Ubuntu 20.04

This is an updated version on my previous entry where I was installing it on Ubuntu 18.04. Now it reflects newer version of the Ubuntu and Samba itself which got a fix for CVE-2021-44142. I based this tutorial on Mac TimeMachine with Samba 4.8.* on Ubuntu 18.10

Due to the recent pandemic outbreak I had to switch to working from home. At the office I am using MacBook Pro which gets backed up to the dedicated Time Capsule device. It works as expected, nothing extra there. Unfortunately at home I didn’t have such contraption, but I had a custom built NAS based on Ubuntu 18.04 LTS. It turns out that you can emulate Time Machine by using Samba, just need to build it yourself as the one shipped lacks Spotlight support.

First step is to install tools and dependencies required:

apt update
apt install -y libreadline-dev git build-essential libattr1-dev libblkid-dev autoconf python-dev python-dnspython libacl1-dev gdb pkg-config libpopt-dev libldap2-dev dnsutils acl attr libbsd-dev docbook-xsl libcups2-dev libgnutls28-dev tracker libtracker-sparql-2.0-dev libpam0g-dev libavahi-client-dev libavahi-common-dev bison flex avahi-daemon liblmdb-dev libjansson-dev libgpgme-dev libarchive-dev libparse-yapp-perl libicu-dev python3-pyasn1 python3-markdown python3-dnspython libtasn1-bin

Create file /etc/avahi/services/timemachine.service with following contents:

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
   <port>445</port>
 </service>
<service>
<type>_device-info._tcp</type>
   <port>0</port>
   <txt-record>model=TimeCapsule8,119</txt-record>
</service>
<service>
<type>_adisk._tcp</type>
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
<txt-record>dk0=adVN=TimeMachine Home,adVF=0x82</txt-record>
</service>
</service-group>

Download Samba source code archive and verify it. You need to unzip the tar file first as tar file is signed and not gzipped file (which is a bit odd).

cd /usr/src
wget https://download.samba.org/pub/samba/samba-pubkey.asc
gpg --import samba-pubkey.asc
wget https://download.samba.org/pub/samba/stable/samba-4.15.5.tar.gz
gunzip samba-4.15.5.tar.gz
wget https://download.samba.org/pub/samba/stable/samba-4.15.5.tar.asc
gpg --verify samba-4.15.5.tar.asc

After confirming i’ts fine, unpack it and build it. On Atom N2800 with 4GB RAM and SATA SSD drive it takes around 90 minutes.

tar -xvf samba-4.15.5.tar
cd samba-4.15.5
./configure --sysconfdir=/etc/samba --systemd-install-services --with-systemddir=/lib/systemd/system --with-shared-modules=idmap_ad --enable-debug --enable-selftest --with-systemd --enable-spotlight
make
make install

Create Samba configuration file /etc/samba/smb.conf. Please adjust path under TimeMachine Home to point at the directory where you want to keep backups. In my case it was /zstorage/backups/timemachine which is stored on ZFS.

[global]
## Basic samba configuration

server role = standalone server
passdb backend = tdbsam
obey pam restrictions = yes
security = user
printcap name = /dev/null
load printers = no
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=524288 SO_SNDBUF=524288
server string = Samba Server %v
map to guest = bad user
dns proxy = no
wide links = yes
follow symlinks = yes
unix extensions = no
acl allow execute always = yes
log file = /var/log/samba/%m.log
max log size = 1000


# Special configuration for Apple's Time Machine
fruit:model = MacPro
fruit:advertise_fullsync = true
fruit:aapl = yes


# Define your shares here
[TimeMachine Home]
path = /zstorage/backups/timemachine/%U
valid users = %U
writable = yes
durable handles = yes
kernel oplocks = no
kernel share modes = no
posix locking = no
vfs objects = catia fruit streams_xattr
ea support = yes
browseable = yes
read only = No
inherit acls = yes
fruit:time machine = yes
fruit:aapl = yes
spotlight = yes
create mask = 0600
directory mask = 0700
comment = Time Machine

Create logs location and storage subdirectory (matching what you defined in previous step). Change USERNAME to your users name. Please note that this user needs to exist on the system running Samba daemon.

mkdir -p /var/log/samba
mkdir -p /zstorage/backups/timemachine/
mkdir -m 700 /zstorage/backups/timemachine/USERNAME
chown USERNAME /zstorage/backups/timemachine/USERNAME

Update password for the user

/usr/local/samba/bin/smbpasswd -a $USERNAME

Add Samba binaries path to /etc/profile and re-read the file

echo 'export PATH=/usr/local/samba/bin/:/usr/local/samba/sbin/:$PATH' >> /etc/profile source /etc/profile

Apply a fix to systemd service definition (without it smbd won’t start correctly) and then start the daemon

sed -i 's/Type=notify/Type=simple/g' /lib/systemd/system/smb.service systemctl enable --now smb.service

If you have a firewall running you need to allow port 445 access, for ufw it would be (assuming 192.168.0.0/24 is your LAN)

ufw allow from 192.168.0.0/24 to any port 445

Now you can setup your MacBook to use it the same way as it uses Time Capsule.

Smokeping with NGINX

My humble little webserver (which hosts used to host this site) is using NGINX. It works exceptionally well for my needs. I also have a Smokeping running on it all the time to monitor my ISP connectivity.

As link quality has deteriorated recently I wanted to review relevant graphs. It turns out that Smokeping is still using CGI in 2020 (d’oh). NGINX does not support it so the idea was to spin up CGI to FastCGI bridge and serve the content via fastcgi_pass. To have it working on Ubuntu 18.04 LTS you need to add following lines to your virtual host definition in /etc/nginx/sites-enabled:

location /smokeping {
        alias /usr/share/smokeping/www;
        try_files $uri $uri/ =404;

        location /smokeping/smokeping.cgi {
                fastcgi_pass  localhost:9999;

                fastcgi_param QUERY_STRING    $query_string;
                fastcgi_param REQUEST_METHOD  $request_method;
                fastcgi_param CONTENT_TYPE    $content_type;
                fastcgi_param CONTENT_LENGTH  $content_length;
        }

        allow 192.168.0.0/24;
        deny all;
}

Please note it also limits access to your LAN only (assuming it is 192.168.0.0/24). Then install libfcgi-bin

apt update && apt install libfcgi-bin

And spin up the bridge from the unprivileged user that has write access to /var/lib/smokeping/:

sudo -u smokeping -- /usr/bin/cgi-fcgi -start -connect 127.0.0.1:9999 /usr/share/smokeping/smokeping.cgi

And that’s all. I use the web frontend rarely so I spin it manually. You can make it persistent using /etc/rc.local or systemd if you need it more often.

Using SoloKey on vanilla Ubuntu

It has been almost a year since last time I posted here so today we will have a quick one. I recently bought a SoloKey U2F key. It is a much cheaper and opensorce replacement for YubiKey (which is also a great product – I had a chance to use it for almost 2 years and it was flawless). In vanilla Ubuntu 18.04 when you plugin the key it gets detected correctly:

[Tue Feb 19 21:13:28 2019] usb 1-1: new full-speed USB device number 8 using xhci_hcd
[Tue Feb 19 21:13:28 2019] usb 1-1: New USB device found, idVendor=0483, idProduct=a2ca
[Tue Feb 19 21:13:28 2019] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[Tue Feb 19 21:13:28 2019] usb 1-1: Product: Solo
[Tue Feb 19 21:13:28 2019] usb 1-1: Manufacturer: Solo Keys
[Tue Feb 19 21:13:28 2019] usb 1-1: SerialNumber: 0123456789ABCDEF
[Tue Feb 19 21:13:28 2019] hid-generic 0003:0483:A2CA.0008: hiddev1,hidraw3: USB HID v1.11 Device [Solo Keys Solo] on usb-0000:00:14.0-1/input0

Unfortunately permissions for device are incorrect and the key won’t be accessible from the browser:

$ ls -la /dev/hidraw*
crw------- 1 root root 243, 0 lut 19 21:03 hidraw0
crw------- 1 root root 243, 1 lut 19 21:03 hidraw1
crw------- 1 root root 243, 2 lut 19 21:03 hidraw2
crw------- 1 root root 243, 3 lut 19 21:13 hidraw3

To fix it we need a simple udev rule in /etc/udev/rules.d/90-solokey.rules:

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca"

And then reload the udev rules:

sudo udevadm control --reload-rules

Thanks to that rule it will have group set to plugdev and read/write permissions for that device. By default user created in Ubuntu is a member of such group so it will work out of the box:

$ id
uid=1000(alchemyx) gid=1000(alchemyx) grupy=1000(alchemyx),4(adm),20(dialout),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare),128(kismet)

Now you can test it by going to demo.yubico.com using Google Chrome. Click Next on first page and allow access to the key. The LED on SoloKey should turn amber and after clicking its hardware button it will get registered correctly.

If you want to do the same from the Firefox you need to reconfigure it first. Open about:config URL and confirm that you accept the risk. Find security.webauth.u2f there and flip it to True.