GIO can’t mount SMB

When trying to mount SMB share using gio you might encounter the following error:

$ gio mount smb://ptnas1.cellebrite.local
gio: smb://nas.corp.local/: Location is not mountable

This error might be due to a missing gvfs backend. The smb backend should be located in /usr/share/gvfs/mounts/smb.mount. If it is missing, you should install the gvfs-backends package and it should resolve the mounting issue.

If the mount was successful, but you can’t see it under $XDG_SESSION_DESKTOP/gvfss/, you are probably missing the FUSE server that makes the mounted filesystem available to all applications and not only to GIO aware applications. You can install the FUSE server by installing the gvfs-fuse package. The server will automatically run after reboot. If you want to start the server immediately, you can start it manually:

$ /usr/lib/gvfs/gvfsd-fuse /run/user/1000/gvfs

List obsolete packages using Apt

Apt 2.0 introduced a new feature allowing to use smarter patterns when listing packages. This allows to list all obsolete packages using the specifier ?obsolete or the shorthand ~o.

$ apt list ?obsolete

It will list all locally installed packages and packages.

You can also list all packages not provided by Debian (it will also catch packages once provided by Debian but since then remove from the repositories):

$ apt list --installed "?not(?origin(debian))"

Slack screen sharing under Wayland

To get screen sharing in Slack to properly work under Wayland, you need to explicitly tell Slack to use PipeWire for screen capturing. Copy Slack’s desktop file from /usr/share/applications/slack.desktop to ~/.local/share/applications/slack.desktop and modify the Exec line to look like:

Exec=/usr/bin/slack --enable-features=WebRTCPipeWireCapturer %U

Now restart Slack and screen sharing should work properly.

Unlock LUKS volume with a YubiKey

Update: The dracut configuration has been updated and now udev consistently recognizes the YubiKey in the initramfs.

Unlocking LUKS encrypted drives with a YubiKey has been supported since systemd 248. In Debian, systemd>=250 is required, as the feature has not been enabled in prior versions. This tutorial is geared towards Yubikeys, but it should work with slight modifications with any other FIDO2 token.

YubiKey series 5 and later should support the hmac-secret extension. You can make sure your Yubikey supports the needed hmac-secret extension by querying it with ykman:

$ ykman --diagnose 2>&1 | grep hmac-secret

Backup your LUKS header

In case you mess anything up, you would need a backup of your LUKS header. Remember to save your backup to some external storage, so you can actually access it if anything goes sideways.

# cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /media/guyru/E474-2D80/luks_backup.bin

Set FIDO2 PIN

We would like to set a FIDO2 PIN for the Yubikey, so unlocking the encrypted drive would require both the physical Yubikey and the PIN. You can set the PIN using:

$ ykman fido access change-pin

Enroll the Yubikey

Start by verifying that systemd-cryptenroll can see and can use your YubiKey:

$ systemd-cryptenroll --fido2-device=list
PATH         MANUFACTURER PRODUCT
/dev/hidraw0 Yubico       YubiKey FIDO+CCID

Now, enroll the Yubikey, replacing /dev/nvme0n1p3 with the block device of the LUKS encrypted drive.

$ sudo systemd-cryptenroll /dev/nvme0n1p3 --fido2-device=auto  --fido2-with-client-pin=yes
🔐 Please enter current passphrase for disk /dev/nvme0n1p3: (no echo)
Initializing FIDO2 credential on security token.
👆 (Hint: This might require confirmation of user presence on security token.)
🔐 Please enter security token PIN: (no echo)
Generating secret key on FIDO2 security token.
👆 In order to allow secret key generation, please confirm presence on security token.
New FIDO2 token enrolled as key slot 0.

Modify /etc/crypttab

We need to modify /etc/crypttab in order to tell cryptsetup to unlock the device using the YubiKey. Add fido2-device=auto in the options field of the crypttab entry for your device. For example:

nvme0n1p3_crypt UUID=307a6bef-5599-4963-8ce0-d9e999026c1a none luks,discard,fido2-device=auto

Switch to dracut

Debian’s default initramfs generator, update-initramfs of the initramfs-tools is using the old cryptsetup for mounting encrypted drives. However, cryptsetup doesn’t recognize the fido2-device option. Running update-initramfs will fail with the following error:

$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-5.15.0-3-amd64
cryptsetup: WARNING: nvme0n1p3_crypt: ignoring unknown option 'fido2-device'

This is unfortunate. The simplest solution is to switch to dracut, a more modern initramfs generator, which among other things relies on systemd to activate encrypted volumes. This solves the issue of the unknown fido2-device.

Before installing dracut, I would highly recommend creating a copy of the existing initramfs in the boot partition in case something goes wrong.

$ sudo apt install dracut

Dracut includes systemd-cryptsetup by default. systemd-cryptsetup depends on libfido for unlocking devices using FIDO2 tokens. At least in Debian, systemd-cryptsetup dynamically loads libfido2.so (as opposed to being dynamically linked), which causes dracut not to have libfido2.so in the initramfs. This causes systemd-cryptsetup to issue the following error upon boot:

FIDO2 tokens not supported on this build. 

We fix it by manually adding libfido2.so to the initramfs. Of course, we also need to include libfido2’s dependencies as well. Dracut has a mechanism for automatically adding dependencies for executables, but it doesn’t work on libraries. As a workaround, instead of adding libfido2 directly, we will add an executable that depends on libfido2, which will add libfido2 and its dependencies to the initramfs. We will usefido2-token from the fido2-tools package for this trick.

$ sudo apt install fido2-tools
$ cat << EOF | sudo tee /etc/dracut.conf.d/11-fido2.conf
## Spaces in the quotes are critical.
# install_optional_items+=" /usr/lib/x86_64-linux-gnu/libfido2.so.* "

## Ugly workround because the line above doesn't fetch
## dependencies of libfido2.so
install_items+=" /usr/bin/fido2-token "

# Required detecting the fido2 key
install_items+=" /usr/lib/udev/rules.d/60-fido-id.rules /usr/lib/udev/fido_id "
EOF

Now, recreate the initramfs images:

$ sudo dracut -f

Last remarks

At this point, we are done. Reboot you’re machine and it will prompt you for your YubiKey and allow you to unlock your LUKS encrypted root patition with it. If you don’t have your YubiKey, it will give the following prompt:

Security token not present for unlocking volume root (nvme0n1p3_crypt), please plug it in.

After around 30 seconds, it would time out and display the following message:

Timed out waiting for security device, aborting security device based authentication attempt.

Afterwards, it would allow you to unlock the partition using a password (or a recovery key).

In case you run into any trouble, append rd.break=initqueue to the kernel command line, and dracut will enter a shell before attempting to mount the partitions. You can manually mount the drive using the following command:

# /usr/lib/systemd/systemd-cryptsetup attach root /dev/nvme0n1p3

Exit the emergency shell, and the system will continue its normal boot.

Extend laptop’s battery life using TLP

TLP helps optimize battery usage for laptops. TLP supports setting battery charging threshold, to allow keeping the battery partially charged, which prolongs its life. This can be done creating a new file under /etc/tlp.d/01-battery.conf:

START_CHARGE_THRESH_BAT0=80
STOP_CHARGE_THRESH_BAT0=85

Reload the TLP configuration for the new settings to take effect:

$ systemctl reload tlp.service

You can disable the battery threshold temporarily using:

$ sudo tlp fullcharge

Restoring the thresholds is done using

$ sudo tlp setcharge

Enable TRIM on external LUKS encrypted drive

If you use an encrypted external SSD, you should periodically trim it. The first step would be to make sure the external drive itself supports trimming. The next step would be to make sure the LUKS partition on the device supports trimming as well. By default, encrypted filesystems do not support passing discard requests due to some security concerns. For example, crypttab man page states:

WARNING: Assess the specific security risks carefully before enabling this option. For example, allowing discards on encrypted devices may lead to the leak of information about the ciphertext device (filesystem type, used space etc.) if the discarded blocks can be located easily on the device later.

For most users, the benefit of TRIM outweigh those security concerns. The easiest way to enable TRIM is to pass the dicard option in /etc/crypttab. For example:

cdisk0 UUID=12345678-9abc-def012345-6789abcdef01 none luks,discard

The problem with the /etc/crypttab approach is that it requires you to pre-configure your external drives. A better approach would be to enable discards at the LUKS configuration, which would apply automatically whenever the drive is used. This can be done in LUKS version 2 headers.

# cryptsetup --allow-discards --persistent refresh luks-643dc0f7-c876-4e37-9207-5c053a75fc70

Where luks-643dc0f7-c876-4e37-9207-5c053a75fc70 is the name of the mapping for the encrypted drive. You can verify that allow_discards is now part of the flag by dumping the LUKS header.

# cryptsetup luksDump /dev/sda4 | grep Flags
Flags:       	allow-discard

Now, you should be able to use fstrim to trim your external SSD with LUKS encryption drive.

Enable TRIM/discard on external SSD

First, find out whether your device already supports TRIM commands.

$ lsblk --discard

Non-zero values in the DISC-GRAN and DISC-MAX indicate support. If it looks like your external SSD doesn’t support trimming, then maybe it supports UNMAP which is equivalent (UNMAP is just in the SCSI command set vs TRIM which is in the ATA command set). Assuming your external drive is /dev/sda

# apt install sg3-utils
# sg_vpd -a /dev/sda | grep -i unmap

If the last command has Unmap command supported (LBPU): 1 it means the drive supports the UNMAP command. If it’s supported, and discard wasn’t supported, it’s likely the kernel didn’t detect the UNMAP support. You can verify it by reading /sys/block/sda/device/scsi_disk/0\:0\:0\:0/provisioning_mode

$ cat /sys/block/sda/device/scsi_disk/0\:0\:0\:0/provisioning_mode 
full

full means no support. As we know our device supports unmap we can manually instruct the kernel about it.

# echo "unmap" >/sys/block/sda/device/scsi_disk/0\:0\:0\:0/provisioning_mode 

Now, lsblk --discard should report that the drive supports trimming, and you can use fstrim to trim it.

Making the change permanent

The changes above are ephemeral and will be reverted once you disconnect the drive. If you want to automatically apply those changes whenever your external drive is connected, we need to use udev rules.

Add the following rule to udev under /etc/udev/rules.d/90-usb-discard.rules

ACTION=="add|change", ATTRS{idVendor}=="0b05", ATTRS{idProduct}=="1932", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"

Replace idVendor and idProduct above with the corresponding values for your device, as can be found in the output of lsusb.

Reload the udev rules using

# udevadm control --reload

Use Alt-Shift for keyboard layout switching in GNOME 40

Since GNOME 40 the keyboard layout indicator doesn’t work if the keyboard is switched using a key combination defined in GNOME Tweaks. The indicator does work for key combinations defined through GNOME Setting’s Keyboard Shortcut settings. However, GNOME Settings doesn’t allow one to set Alt+Shift as the key combination layout switching, as it seems to require at least one non-modifier key in every shortcut. This limitation only exists in GNOME Settings GUI and you can work around it by defining the shortcut using gsettings:

$ gsettings set org.gnome.desktop.wm.keybindings switch-input-source "['<Shift>Alt_L']"
$ gsettings set org.gnome.desktop.wm.keybindings switch-input-source-backward "['<Alt>Shift_L']"

Downgrade PipeWire 0.3.39 to 0.3.38

PipeWire 0.3.39 on Debian deprecates pipewire-media-session in favor of WirePlumber. The main issue I found with the new version is that it doesn’t support Bluetooth profile autoswitching, as it is unimplemented in WirePlumber. The best solution until this is resolved is simply holding back upgrading to 0.3.39. If you already upgraded, downgrading is a bit of hassle.

The first step is to retrieve all the necessary packages in the last working version, which is 0.3.38-2.

$ cd `mktemp -d`
$ debsnap -a amd64 --binary -d . gstreamer1.0-pipewire 0.3.38-2
$ debsnap -a amd64 --binary -d . libpipewire-0.3-0 0.3.38-2
$ debsnap -a all --binary -d . libpipewire-0.3-common 0.3.38-2
$ debsnap -a amd64 --binary -d . libpipewire-0.3-modules 0.3.38-2
$ debsnap -a amd64 --binary -d . pipewire-audio-client-libraries 0.3.38-2
$ debsnap -a amd64 --binary -d . pipewire-bin 0.3.38-2
$ debsnap -a amd64 --binary -d . pipewire-pulse 0.3.38-2
$ debsnap -a amd64 --binary -d . pipewire 0.3.38-2
$ debsnap -a amd64 --binary -d . pipewire-media-session 0.3.38-2
$ debsnap -a amd64 --binary -d . libspa-0.2-modules 0.3.38-2
$ debsnap -a amd64 --binary -d . libspa-0.2-bluetooth 0.3.38-2

Install all the retrieved packages and mark some of the packages back as automatically installed.

$ sudo apt install ./*.deb
$ sudo apt-mark auto gstreamer1.0-pipewire libpipewire-0.3-0 libpipewire-0.3-common libpipewire-0.3-modules pipewire-bin pipewire libspa-0.2-modules

Mark pipewire-media-session as held so it won’t get accidentally removed again.

$ sudo apt-mark hold pipewire-media-session

Finally, restart PipeWire.

$ systemctl --user daemon-reload
$ systemctl --user restart pipewire pipewire-pulse