This is a guide intended for anyone who wants to encrypt their Steam Deck.
Unlike all mobile devices of today (phones, laptops, tablets), the Steam Deck has no encryption.
In particular a malicious actor can get access to -
Note: You can (and should) activate the security lock inbuilt to Steam Deck's UI. But that does not encrypt the storage - and it is extremely easy for anyone to take the SSD or MMC out and access your data directly.
If you follow this guide through, your Steam deck will be more secure, and it will make it very difficult (if not impossible) for bad actors to get access to accounts you have logged in to.
After encryption through this guide -
This project is very similar to the one here - https://github.com/Ethorbit/SteamDeck-SteamOS-Guides/tree/main/Encrypting-With-LUKS
I am indebted to the owner trying a similar approach before. I think there are certain aspects that inspired me, and showed that I am going in the right direction.
I recommend going there to watch the video, because the video is very much representative of how this will end up. There are differences in the setup process however. This workflow should be (a) possible to do without having to repartition and (b) more compatible with all future Steam updates.
/home/deck
and swapfile will be encrypted.~/home/on_decrypt_user.sh
and ~/home/on_decrypt_root.sh
(e.g. plugin_loader). A possible future
solution could be to retry all the failed services after the container is
decrypted.As with every DIY project, things can go wrong. If you choose to follow this guide, please do so on your own responsibility.
That said, I think the steps outlined here are pretty safe.
Up until the point where you choose to erase data from unencrypted partition, the process is very easily reversible.
The set up process is generally safe. However, please understand the process first before going through it.
blackist=tpm
from /etc/default/grub. This is needed to be able to use encryption with LUKS.sudo update-grub
and reboot.NOTE: After you have done this once, every time Steam OS updates you will need to run only step 2 above.
This is required only one time, to create the filesystem container for your encrypted home.
Run the lines below as root.
Either enter super user sudo su -
, or prefix sudo
to each of the lines as you execute them.
cd /home
# Choose a size depending on your SSD.
# This will replace your home, which will contain entire steam installation,
# and games that you install in the SSD.
# Try to choose a size that will serve you for a long time.
# I chose 750G for a 1TB SSD.
# Note: This can be increased (or even decreased) wthout loss; but that requires some expertise.
fallocate -l 750G ./container
cryptsetup luksFormat ./container
cryptsetup open ./container deck_alt
# Note: If you want btrfs, use `mkfs.btrfs ...` instead; and ignore the `tune2fs` line.
mkfs.ext4 /dev/mapper/deck_alt
tune2fs -m 1 /dev/mapper/deck_alt
# Allow discards for fstrim.
cryptsetup --allow-discards --persistent refresh /dev/mapper/deck_alt
mkdir /run/mount/deck_alt # Temporary one-time mount.
chown deck:deck /run/mount/deck_alt
mount /dev/mapper/deck_alt /run/mount/deck_alt
rsync -aAXHSv /home/deck/ /run/mount/deck_alt/
Add these scripts to your current (non-encrypted) home -
The idea is to run sudo ~/unlocker/runasroot.sh
on every boot to unlock the container and replace your home/deck
with an the encrypted filesystem.
#!/bin/bash
set -uexo pipefail
# After this is done, you can `sudo systemctl disable NetworkManager` to prevent Steam from
# updating the Steam binary in container (only required for keyboard) during boot.
# Line below starts it if it is disabled.
systemctl start NetworkManager
# Steam OS has tpm in kernel module_blacklist, but that prevents encryption.
# Here we check it, and if present, automatically removes it and updates grub.
readonly GRUBFILE=/etc/default/grub
# Note: If you change this REGEX, change the tests/tpm_removal and run it to check that it works.
readonly TPM_BLACKLIST_REGEX='^\s*GRUB_CMDLINE_LINUX_DEFAULT\b.*\bmodule_blacklist=[^\s]*,?tpm,?\s*\b'
if grep -E -q "${TPM_BLACKLIST_REGEX}" $GRUBFILE; then
echo "tpm is blacklisted in ${GRUBFILE}, editing to remove."
cp ${GRUBFILE} ~deck/grub_original_backup
sed -E -i "/${TPM_BLACKLIST_REGEX}/"\
'{h;s/^/# Modified from: /p;x;'\
's/(module_blacklist=)([^\s]*)?\b(tpm,?)\b/\1\2/;s/,([ \s$])/\1/;}' $GRUBFILE
fi
# Steam update images appear to always have tpm blacklisted. If so, we need to update-grub.
if ! lsmod | grep -q '^tpm\b'; then
update-grub
echo "PRESS ENTER TO REBOOT. This should happen only once after OS update."
read && reboot && exit 1
fi
# Encrypt swap.
# Note: After this is run once, swap will not mount for the unencrypted partition.
# To revert, simply execute `mkswap /home/swapfile`.
if [[ ! -e /dev/mapper/swap ]]; then
swapoff -a
cryptsetup open /home/swapfile swap --type=plain --cipher=aes-xts-plain64 --key-file=/dev/urandom
mkswap /dev/mapper/swap
swapon /dev/mapper/swap
fi
# Unlock home. This will ask for the decryption password.
cryptsetup open /home/container deck_alt - --allow-discards
# Point /home/deck to the unlocked container.
mount /dev/mapper/deck_alt /home/deck
# Run optional root autostart script if present.
# This can be used for example to automatically unlock and mount sdcard with a keyfile.
readonly OPTIONAL_STARTUP_ROOT=/home/deck/on_decrypt_root.sh
if [[ -f $OPTIONAL_STARTUP_ROOT ]]; then
# For safety, ensure that user programs cannot write to this script.
if [[ "$(stat -L -c "%a %G %U" $OPTIONAL_STARTUP_ROOT)" != "744 root root" ]]; then
echo "$OPTIONAL_STARTUP_ROOT exists but is not owned by root:root with mode 744."
echo "Skipping execution, continuing in a few seconds..."
sleep 5
else
$OPTIONAL_STARTUP_ROOT || true
fi
fi
# Run optional user ~/decrypt_startup.sh if present in the unlocked home.
# This can be used to start your own services or carry out any maintainence on unlock.
readonly OPTIONAL_STARTUP_SCRIPT=/home/deck/on_decrypt_user.sh
if [[ -f $OPTIONAL_STARTUP_SCRIPT ]]; then
# Need to set a few variabls, otherwise systemctl --user does not work.
# See https://askubuntu.com/questions/1007055/systemctl-edit-problem-failed-to-connect-to-bus
USER_XDG_DIR=/run/user/1000
sudo su - deck <<EOF || true
set -x
export XDG_RUNTIME_DIR=${USER_XDG_DIR}
export DBUS_SESSION_BUS_ADDRESS="unix:path=${USER_XDG_DIR}/bus"
$OPTIONAL_STARTUP_SCRIPT
EOF
# Note: Do not indent the EOF line above!
fi
# For convenience, keep the unencrypted home mounted in some location to maintain access to it.
readonly ORIGINAL_HOME=/run/mount/_home_dirs_orig
# See https://unix.stackexchange.com/questions/4426/access-to-original-contents-of-mount-point
# Note: This must be done _after_ we mount the replacement and not before.
mkdir -p $ORIGINAL_HOME
mount --bind /home $ORIGINAL_HOME
ln -s $ORIGINAL_HOME/deck $(dirname $ORIGINAL_HOME)/_deck_orig
# Restart gamescope compositor and steam.
systemctl restart sddm
This is to add a wrapper to show terminal on Steam deck, which you'll need to type the password in.
#!/bin/bash
# Add to steam as a shortcut.
set -uexo pipefail
readonly SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
xterm -e "sudo $SCRIPT_DIR/runasroot.sh"
Add this to Steam as a shortcut.
If everything works, when you start it, you will be asked for two passwords. First one is for your user, second for the encrypted drive. Once you pass both of them, Steam will restart using the newly encrypted home.
If you complete Step 2 successfully, you're pretty much done. You will now want to clean up original data left in unencrypted partition, and encrypt the swap.
NOTE: Some of these are irreversible, so please be extra careful that you are doing it on the right partition.
Do the following before you decrypt -
~/.var/app/*
which contains settings and authentication for apps you installed through Discover.HISTFILE=
to the end of ~/.bash_profile
~/.bash_history
Reboot and verify decryption still works.
Swap will be encrypted when you unlock the deck.
sudo swapoff -a
sudo rm /home/swapfile
# Note: 1G is the default swap size that Steam OS comes with.
# If you want to use a different size, you can change it below.
sudo fallocate -l 1G /home/swapfile
sudo chmod 600 /home/swapfile
# Then reboot.
# You can verify that swap is active after reboot, by running `swapon -s`.
sudo mkswap /home/swapfile
to let the unencrypted swapfile to be used again.You can add the following two files in the encrypted container, which will be executed on startup -
Startup File | Purpose |
---|---|
/home/deck/on_decrypt_root.sh |
Will run as root after a successful unlock. Must be owned by root, and have attribute 744 to deter malicious or unintended edits. |
/home/deck/on_decrypt_user.sh |
Will run as user after a successful unlock. Good place for starting user services. |
For example, if you use Decky Loader, you can place this
in /home/deck/on_decrypt_root.sh
after you have unlocked your decrypted
container -
#!/bin/bash
# This is run when the home directory is decrypted.
set -uexo pipefail
# Decky loader service.
if [[ -f /etc/systemd/system/plugin_loader.service ]]; then
systemctl start plugin_loader
fi
Change ownership and permissions to prevent malicious or unintended edits -
sudo chown root:root /home/deck/on_decrypt_root.sh
sudo chmod 744 /home/deck/on_decrypt_root.sh
Every time you get a SteamOS update, you need to do the following -
sudo upgrade-grub
from a console in Desktop mode before you unlock, and reboot.This setup is very non-intrusive and compatible with the partition structure.
As a result, this way of encrypting may be a viable option for Steam to roll out for existing users seamlessly.
/home/deck
directory./home/container
file to free up the space. Then if you want, you can continue to use it unencrypted, or go through the process again to re-encrypt.device-mapper: reload ioctl on swap (254:0) failed: Invalid argument
sudo update-grub
, and reboot to resolve. More info: The error is
likely caused because the image after an update does not have tpm. See
"Unblacklist tpm" for more details.