Last Updated 7 days by cneuhaus
📢 Automating LUKS – Seamless Encryption & The Battle Against sudo
Fun fact – I used one Chat-Window with ChatGPT to find this solution, at the end I asked him to understand the objective of my questions, and used below prompt to build this post – wouhhh ( I love it how he ignores my spelling mistakes ;.))
The Problem
I’ve always been a fan of automation—no unnecessary manual steps, no friction, no surprises.
When dealing with LUKS-encrypted storage and Samba shares, I had one clear goal:
✅ Fully automate mounting and unmounting without needing to enter manual passwords
Actually, I have another script that gets the password via https request, so its a remote lock/unlock. The script is a simple web-server, you will know how to do it 🙂
That sounds simple? It wasn’t.
The First Idea: Just Use udisksctl
At first, udisksctl
seemed perfect. A simple:
udisksctl unlock -b /dev/sdf2
would unlock my LUKS volume, and:
udisksctl lock -b /dev/disk/by-uuid/XXXX
should lock it. No root, no sudo.
But then came the first brick wall: It asked for a password—even when running from a script.
💬 “Wait, why does udisksctl
need root to lock a device, but not to unlock it?”
Welcome to Polkit & UDisks2—a world of undocumented edge cases.
Polkit: The Rabbit Hole
My next move? Polkit rules.
It should allow passwordless execution, right?
polkit.addRule(function(action, subject) {
if ((action.id == "org.freedesktop.udisks2.encrypted-unlock" ||
action.id == "org.freedesktop.udisks2.lock-device") &&
subject.isInGroup("disk")) {
return polkit.Result.YES;
}
});
Result? Still asking for a password.
Debugging with journalctl -f | grep polkit
told me that some actions were still being denied.
One step forward, two steps back.
The Real Issue: fuser
, Samba & Busy Devices
Unmounting a LUKS volume is not just about stopping I/O operations—it’s about breaking any remaining connections.
- Samba still held open files on my mounted LUKS drive.
udisksctl lock
failed with “Device or resource busy”.umount -l
wasn’t enough—becausesmbd
was still running in the background.
I needed to force kill processes before unmounting.
sudo smbcontrol smbd close-share LUKSShare
sudo fuser -km /data/check
sudo udisksctl unmount -b /dev/mapper/my_luks_drive
💡 Lesson learned: Locking a LUKS device isn’t just about the disk—it’s about all the services using it.
The Compromise: Selective sudo
At this point, I had a choice:
- Go even deeper into Polkit and hack my way through more rules.
- Accept reality and selectively allow
sudo
—but in a controlled way.
I chose option 2.
Using visudo
, I allowed only the required commands to run without a password:
youruser ALL=(ALL) NOPASSWD: /usr/bin/udisksctl lock -b /dev/disk/by-uuid/*, /usr/bin/smbcontrol smbd close-share *, /usr/bin/fuser -km /data/check
This kept security tight while making automation work smoothly.
The Final Setup
At the end of this journey, I had a fully working system that:
- ✅ Mounts LUKS automatically.
- ✅ Unmounts and locks it without requiring sudo manually.
- ✅ Closes Samba shares properly to avoid
device busy
errors. - ✅ Uses
sudo
only for the absolute essentials (but without password prompts).
Final Changes
Below are the final changed files:
- 📂 Mount and Unmount Scripts
(automating the full LUKS lifecycle) - 📂
sudoers
File
(allowing selective passwordlesssudo
execution) - 📂 Polkit Rules
(the necessary adjustments to make it work)
🚀 Conclusion
This wasn’t just about avoiding sudo
. It was about understanding Linux security, process management, and automation.
Would I do it the same way again? Probably.
Would I recommend it to someone else?
💡 “Only if you’re really into debugging Linux internals.”
🚀 Final setup below. Let me know if you see ways to make it even cleaner.
💡 This post is for those who want real, practical automation without compromising security.
If you’ve fought the same battle, drop a comment. 🔥
Mount
1 #!/bin/bash
2
3 # Check if password is provided
4 if [ -z "$1" ]; then
5 echo "Usage: $0 <password>"
6 exit 1
7 fi
8
9 password="$1"
10 device="/dev/sdx1" # Your LUKS partition
12 luks_name="luks-xxx" # Custom device name
13
14 # Unlock LUKS partition with a fixed name
15 udisksctl unlock --block-device "$device" --key-file <(echo -n "$password")
16
17 sleep 1
18 # Mount the unlocked LUKS volume
19 udisksctl mount -b "/dev/mapper/$luks_name"
Unmount
#!/bin/bash
2
3 # Configuration: Set your LUKS device details
4 LUKS_UUID="luks-xxxx"
5 LUKS_MAPPER="/dev/mapper/luks-xxxx"
6 MOUNT_PATH="//mount_point" # Mount point
7 SAMBA_SHARE_NAME="smb_share" # Samba share name
8 DEVICE="/dev/sdx1"
9
10 # Close active Samba connections
11 echo "Closing Samba share: $SAMBA_SHARE_NAME..."
12 sudo smbcontrol smbd close-share "$SAMBA_SHARE_NAME"
13
14 sleep 1
15
16
17 # Unmount the LUKS volume
18 echo "Unmounting LUKS volume..."
19 sudo udisksctl unmount -b "$LUKS_MAPPER" || umount -l "$LUKS_MAPPER"
20
21
22 # Kill all processes using the mount point
23 #echo "Killing active processes on $MOUNT_PATH..."
24 #sudo fuser -km "$MOUNT_PATH"
25
26 # Wait for system to release resources
27 sleep 1
28
29 # Lock the LUKS device
30 echo "Locking LUKS device..."
31 sudo udisksctl lock -b "$DEVICE"
32
33 if [ $? -eq 0 ]; then
34 echo "LUKS device successfully locked!"
35 exit 0
36 else
37 echo "Failed to lock LUKS device."
38 exit 1
39 fi
40
41 sleep 1
42
43 echo "Set HD to sleep mode"
44 # sudo hdparm -y "$DEVICE
Sudo File:
docbox ALL=(ALL) NOPASSWD: /usr/bin/udisksctl lock -b /dev/sdf2 , \
/usr/bin/udisksctl unmount -b /dev/mapper/*, \
/usr/bin/smbcontrol smbd close-share *, \
/usr/bin/fuser -km *, \
/usr/sbin/hdparm -y /dev/sdx1
Polkit Files:
polkit.addRule(function(action, subject) {
if ((action.id == "org.freedesktop.udisks2.encrypted-unlock" ||
action.id == "org.freedesktop.udisks2.filesystem-mount" ||
action.id == "org.freedesktop.udisks2.filesystem-unmount-others" ||
action.id == "org.freedesktop.udisks2.unmount" ||
action.id == "org.freedesktop.udisks2.lock-device" ||
action.id == "org.freedesktop.udisks2.encrypted-unlock-other-seat") &&
subject.isInGroup("disk")) {
return polkit.Result.YES;
}
});