4

I have a scenario where a number of storage volumes are encrypted using keys contained on a removable encrypted USB "keyring" flash drive. I am running Arch Linux and this question is about systemd dependency configuration.

The system is configured so that, as long as the keyring is present, the system boots and the volumes are mounted. The keyring passphrase is manually entered during boot.

I want to be able to remove the USB keyring once the system is up, However, I am having problems with this because systemd unmounts everything.

Here is an example of what I have done. First, /etc/crypttab

# <name>  <device>           <password>             <options>
keyring   PARTLABEL=keyring  none                   noauto
abc       /dev/lvm/abc       /root/keyring/abc.key  header=/root/keyring/abc.hdr
xyz       /dev/lvm/xyz       /root/keyring/xyz.key  header=/root/keyring/xyz.hdr
  • I am using a recent Git checkout of systemd that supports the header option; it was added to the code-base on January 8th.

  • I am using the partition label of the keyring because there are multiple physical keyrings for backup/convenience reasons. They may have different UUIDs but are setup with the same PARTUUID.

  • I am using noauto so the keyring is only a dependency of any devices that need to be decrypted.

Next is /etc/fstab:

# <file system>     <dir>         <type>    <options>
/dev/mapper/keyring /root/keyring ext4      ro,noauto
/dev/mapper/abc     /srv/abc      ext4
/dev/mapper/xyz     /srv/xyz      ext4

Again, the keyring is noauto so mounting only occurs due to it being a dependency. Also, it's mounted read-only so that it's safe to just pull it out.

Now, to create the dependency between the volume and the keyring, I have used a drop-in override, for example:

# /etc/systemd/system/systemd-cryptsetup\@abc.service.d/override.conf
[Unit]
Requires=root-keyring.mount

That all works fine for start-up. The problem is that removing the keyring stops the units that are dependent on it. I don't want this to happen - the dependency is only required to make the keys and headers accesible while the encrypted volumes are unlocked. Once unlocked, the keys and headers are no longer required.

So, my question is to ask how can I arrange a dependency on the keyring that only exists for the duration of the "ExecStart" command in the systemd-cryptsetup@.service unit ?

Alternatively, if this is the wrong approach, any improved solutions would be welcome.

  • actually your override seems wrong. surely you should have After= as well. "If two units have no ordering dependencies between them, they are shut down or started up simultaneously". if it's happening to work at the moment, you could try replacing Requires with After and it might happen to work how you want it :P. not recommended tho. – sourcejedi Jan 30 '15 at 20:31
  • Tried that, kind-of makes sense but it doesn't work. Mounts still happen as expected but removal of the keyring unmounts them. – starfry Jan 31 '15 at 10:36
  • The dependency that causes the unmount is RequiresMountsFor in the systemd-cryptsetup that systemd creates from the entries in /etc/crypttab. To test this, I have manually created equivalent units without that dependency and this allows the keyring to be removed without unmounting the encrypted volumes. I'm going to look into this a little more and will write it up as an answer in due course. – starfry Jan 31 '15 at 11:24
1

Instead of an explicit dependency, perhaps you could use an automount.

I remember Systemd advertised this during Poettering's initial blog post, as a kind of implicit dependency. It's like how (with systemd) you can write requests to a socket and the appropriate service will be started for you, aka "socket activation". In this case, accessing the filesystem will cause it to be mounted.

With this approach you can expect to block until the service or filesystem is ready. Note: this implies your system will have a directory that blocks you if you try to look at it (once you've removed the "keyring" drive)... Maybe if you ever use /root for anything else, it'd be better to mount it elsewhere e.g. /automount/keyring, to avoid tripping over it. Personally I think this sort of issue makes automounts a bit confusing - but it does seem to make a very quick solution to your question.

If the filesystem is listed in /etc/fstab, just add x-systemd.automount to the list of options.

If it's described by a native .mount file instead, it looks like you need to create a .automount file of the same name. E.g. root-keyring.automount, containing:

[Automount]
Where=/root/keyring
  • Using an automount is a reasonable alternative to using a drop-in Requires dependency. Avoiding the need for a drop-in is good. However, there is still a dependency between the encrypted volumes and the keyring that causes them to unmount when the keyring is removed. So I am still trying to work out a solution to that. – starfry Jan 31 '15 at 10:27
  • I'm quite surprised. I admit I haven't tested this. However I wouldn't have expected that systemd would detect the service accessing the filesystem & generate a dependency like that. Does a dependency show up in systemctl list-dependencies? – sourcejedi Jan 31 '15 at 12:01
  • Scratch that, I just read your post comment about systemd-cryptsetup and RequiresMountsFor – sourcejedi Jan 31 '15 at 12:02
1

In the current systemd (218 at the time of writing), an entry in /etc/crypttab results in an instance of the systemd-cryptsetup@.service unit being generated by the systemd-cryptsetup-generator that systemd executes when the system is booting up.

The generated unit includes a dependency on the path to the key file:

RequiresMountsFor=/path/to/key_file

This kind of dependency is documented in man systemd.unit where it explains that it results in Requires= and After= dependencies for all mounts required to access the specified path.

The Requires= dependency causes systemd to stop the cryptsetup unit if the mount unit is deactivated.

This means that unmounting the device containing the key caues the cryptsetup unit to deactivate and it locks the volume when it does so.

The only work-around at the moment is to not use /etc/crypttab for any volumes where this may be an issue but instead provide a custom unit that doesn't include a RequiresMountsFor= dependency. . Here is an suitable custom unit that is based on the one produced by the generator:

# /etc/systemd/system/systemd-cryptsetup\@.service 
[Unit]
Description=Cryptography Setup for %I
Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)
DefaultDependencies=no
Conflicts=umount.target
BindsTo=dev-mapper-%i.device
IgnoreOnIsolate=true
After=cryptsetup-pre.target
Before=cryptsetup.target
BindsTo=dev-lvmvg-%i.device
After=dev-lvmvg-%i.device
Before=umount.target

[Service]
Type=oneshot
RemainAfterExit=yes
TimeoutSec=0
ExecStart=/usr/lib/systemd/systemd-cryptsetup attach '%i' '/dev/lvmvg/%i' '/root/keyring/%i.key' 'header=/root/keyring/%i.hdr'
ExecStop=/usr/lib/systemd/systemd-cryptsetup detach '%i'

[Install]
WantedBy=dev-mapper-%i.device

This example would be used instead of this /etc/crypttab entry:

 # <name>  <device>       <password>              <options>
mail      /dev/lvmvg/mail /root/keyring/mail.key  header=/root/keyring/mail.hdr   

This issue has been raised with the systemd developers and it has been added to the TODO list.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.