Sailfish OS ‑ Auto‑mount encrypted memory card at boot
Table of Contents
Intro
Disclaimer I: This worked for me. Chances are it will work for you, too, but this is not a copy-paste tutorial. Stay vigilant, messing up will be on you. Make a backup before you begin. Maybe you should also know how to perform recovery. Nota bene: "Turn the phone OFF" = press the power button really, really long. Maybe two minutes.
Disclaimer II: If you want to open encryption automatically, you have to store the key somewhere, which makes the whole thing potentially less secure.
Without Udev
There are other approaches to this involving udev
rules to unlock & mount every time you insert/remove the card. This is different - the idea is that the memory card mostly stays where it is and that apps can rely on it being mounted. Manual un/mounting, removal and insertion, is still possible though.
Prerequisites
Consider reading the "Connect to PC" chapter from this article.
Encrypt the memory card with a key file instead of a password
Format the card through the UI (Settings-> Storage), with encryption, using a Linux filesystem (ext4).
It will ask for a password - enter a good one, we are not going to discard this option.
Unlock & mount it.
Open a terminal.
To get an overview of where we are:
$> lsblk
It should show luks-$UUID1
1, mounted on /run/media/*/$UUID2
.
Start a root session.
$> devel-su
First we add a key file to the LUKS container. You can use any file of any size, or generate one:
#> dd if=/dev/urandom of=/path/to/some.key bs=1M count=1
#> cryptsetup luksAddKey UUID="$UUID1" /path/to/some.key
It will ask for your passphrase, then add the key; so now there's two ways to open the encryption.
Test if it works:
#> cryptsetup luksOpen UUID="$UUID1" --key-file=/path/to/some.key luks-"$UUID1"
Enable user mounting
Execute this command and add the complete line to /etc/fstab
:
#> grep luks-$UUID1 /etc/mtab
Add noauto,user
to the options. So the string that now probably looks like
rw,nosuid,nodev,relatime,errors=remount-ro,data=ordered
should become
noauto,user,rw,nosuid,nodev,relatime,errors=remount-ro,data=ordered
in /etc/fstab
. IMPORTANT!
#> reboot
...and hope you did it right. Nothing happens yet - the system won't (yet) automount this partition.
Two systemd services to prepare and mount the card
The card can be automatically mounted as a normal user, but not without some preparations during the boot process.
First, create a file that contains both UUIDs as environment variables, for convenience (see .service files):
$> echo -e 'UUID1="XXXXXXXXXXXXXXXXXXXXXXXXXXXX"\nUUID2="XXXXXXXXXXXXXXXXXXXXXXXXXXXX"' > /path/to/automount-memcard.env
As root
Create /etc/systemd/system/automount-memcard-prepare.service
:
ini[Unit] Description=Prepare Automount memory card After=local-fs.target cryptsetup.target graphical.target multi-user.target Requires=local-fs.target cryptsetup.target graphical.target multi-user.target [Service] EnvironmentFile=/path/to/automount-memcard.env ExecStart=/bin/sh -c '{ [ -z "$UUID1" ] || [ -z "$UUID2" ]; } && exit 1;\ cryptsetup luksOpen UUID="$UUID1" \ --key-file=/path/to/some.key luks-"$UUID1"; \ mkdir -p /run/media/nemo/"$UUID2"; \ chown 100000:100000 /run/media/nemo/"$UUID2";' [Install] WantedBy=multi-user.target
It opens the encryption and creates the directory to mount on, with the right ownership.
Take care you get all the backslashes \
right, otherwise systemd might balk and leave your phone with a WSOD2.
As usual, start, check status, enable if OK:
#> systemctl start automount-memcard-prepare.service
#> systemctl status automount-memcard-prepare.service
#> systemctl enable automount-memcard-prepare.service
exit
the superuser session.
As normal user
Create ~/.config/systemd/user/automount-memcard.service
:
ini[Unit] Description=Automount memory card After=user-session.target Requires=user-session.target [Service] EnvironmentFile=/path/to/automount-memcard.env ExecStart=/bin/bash -c '[ -z "$UUID1" ] && [ -z "$UUID2" ] && exit 1;\ ok=0; for ((i=0;i<100;i++)); do \ sleep 1;\ [ -b /dev/mapper/luks-"$UUID1" ] \ && [ -d /run/media/nemo/"$UUID2" ] \ && [ "$(stat -c %%u /run/media/nemo/"$UUID2"/)" = 100000 ] \ && ok=1 && break;\ done;\ [ "$ok" = 1 ] && ! grep -q /run/media/nemo/"$UUID2" /etc/mtab && mount -v /run/media/nemo/"$UUID2"' [Install] WantedBy=user-session.target
It waits until the preparations from the first service have completed, then mounts the luksOpened partition.
Again, start, check status, enable if OK:
$> systemctl --user start automount-memcard.service
$> systemctl --user status automount-memcard.service
$> systemctl --user enable automount-memcard.service
This should have worked if you followed exactly until now. Test with a reboot, go to Settings=>Storage, the memory card should be there, mounted and ready to use.
Tracker does not track files on SD Card
I took some pictures; the camera app decided to store them on the memory card, but the gallery app did not see them.
It might be necessary to manually add the memory card directory to the tracker configuration.
See where we are:
$> gsettings list-recursively | grep -i org.freedesktop.Tracker
Script to add the directory:
#!/bin/bash
user=nemo # or defaultuser
source "/path/to/automount-memcard.env"
[ -n "$UUID2" ] || exit
schema="org.freedesktop.Tracker3.Miner.Files"
key="index-recursive-directories"
dirs="$(gsettings get "$schema" "$key")"
add="'/run/media/$user/$UUID2'"
[[ "$dirs" == *$add* ]] && exit
dirs="${dirs%]}, $add]"
gsettings set "$schema" "$key" "$dirs"
This should be necessary only once. If it doesn't persist after a reboot add the script to the automount-memcard.service
.
-
A UUID is a long string of hexadecimal numbers separated by hyphens, in this exact (afaik) format: nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn (i.e. 8-4-4-4-12). It is unique for each device. Please substitute accordingly whenever the text reads
$UUID1
or$UUID2
. ↩ -
White Screen Of Death. Fixable with booting into recovery & editing or removing the file. There's no such thing as a bricked SFOS phone. ↩