Earlier I had shared an article to encrypt, decrypt and sign a file using GPG key in Linux. In this article I will show you the steps to create an encrypted block device using LUKS. By default if somebody connects your hard disk to their computer, it can be mounted automatically, even without entering any user credentials, and that is why we should always encrypt hard disk.
If your hard disk was encrypted then in order to mount an encrypted device, you need to enter a passphrase, without passphrase, nobody can mount it. So this will protect your hard disk, or your server, hard disk from being lost or stolen or whatever, after which data can be accessed easily.
To create encrypted devices in Linux we use LUKS which is the Linux encryption layer.
dm-crypt and cryptsetup vs LUKS
dm-crypt and cryptsetup
- Device-mapper is a part of the Linux kernel that provides a generic way to create virtual layers of block devices, most commonly LVM logical volumes. The device-mapper crypt target (dm-crypt) provides transparent encryption of block devices using the kernel crypto API.
- In Red Hat Enterprise Linux, userspace interaction with dm-crypt is managed by a tool called cryptsetup, which uses the device-mapper infrastructure to setup and operate on encrypted block devices.
LUKS
- With modern versions of cryptsetup (i.e., since ~2006), encrypted block devices can be created in two main formats, plain dm-crypt format or the extended LUKS (Linux Unified Key Setup-on-disk-format) format.
- LUKS provides a standard on-disk-format for hard disk encryption, which facilitates compatibility among Linux distributions and provides secure management of multiple user passwords.
- In contrast to previous Linux disk-encryption solutions, LUKS stores all necessary setup information in the partition header, enabling the user to more easily transport or migrate their data.
- The advantages of LUKS over plain dm-crypt are the obvious higher usability: automatic configuration of non-default crypto parameters, the ability to add, change, and remove multiple passphrases.
- Additionally, LUKS offers defenses against low-entropy passphrases like salting and iterated PBKDF2 passphrase hashing
Attach new hard disk (optional)
So to start with, you need an empty device. I have added a new virtual disk to my virtual machine as /dev/sdb
sda 8:0 0 25G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 2G 0 part /boot
└─sda3 8:3 0 23G 0 part
└─ubuntu--vg-ubuntu--lv 252:0 0 23G 0 lvm /
sdb 8:16 0 5G 0 disk
sr0 11:0 1 57.4M 0 rom

Install cryptsetup
It is possible your distro may not have cryptsetup installed by default. Since we are using Ubuntu 24.10 so we will use apt to install the package:
sudo apt update
sudo apt install cryptsetup -y
Create new partition
First let's wipe our device empty, just to be sure that there are no stale data.
sudo wipefs -a /dev/sdb
sudo dd if=/dev/zero of=/dev/sdb bs=1M count=100
We will create a new partition /dev/sdb1
on this disk
golinuxcloud@server1:~$ sudo fdisk /dev/sdb
Welcome to fdisk (util-linux 2.40.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS (MBR) disklabel with disk identifier 0xdaf1796a.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-10485759, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-10485759, default 10485759):
Created a new partition 1 of type 'Linux' and of size 5 GiB.
Command (m for help): p
Disk /dev/sdb: 5 GiB, 5368709120 bytes, 10485760 sectors
Disk model: VBOX HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xdaf1796a
Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 10485759 10483712 5G 83 Linux
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
So our partition is successfully created.
[root@node1 ~]# partprobe
So our partition is successfully created as we can check using lsblk
command.

We can also check /proc/partitions
:
golinuxcloud@server1:~$ cat /proc/partitions | grep sdb
8 16 5242880 sdb
8 17 5241856 sdb1
Encrypt the partition with LUKS
So you would do luksFormat
on the device, and the luksFormat
command is going to create the encryption layer. This is the passphrase that needs to be entered by anyone who wants to access the device. In real life of course, you wanna have something that really is secure because devices are not mounted that often. (computer keys tapping and clicking)
By default, cryptsetup luksFormat
uses pretty good defaults but you can pass additional arguments to further secure your disk with better encryption:
Parameter | Recommendation | Why |
---|---|---|
--type |
luks2 |
LUKS2 is superior (metadata redundancy, re-encryption support) |
--sector-size |
4096 |
Matches physical sector size of most modern disks |
--key-size |
256 |
Strong AES-256 key strength |
--cipher |
aes-xts-plain64 |
Default, still recommended |
--hash |
sha512 |
Stronger key derivation |
We can use the following command
sudo cryptsetup luksFormat --type luks2 --sector-size 4096 --key-size 256 --cipher aes-xts-plain64 --hash sha512 /dev/sdb1
Sample output:

This will prompt you for a new passphrase. This will be used to unlock the encryption keys that encrypt the actual data. Now it does not directly encrypt the data itself — it just protects the master key which is stored in the LUKS header.
When we basically run luksFormat
, The LUKS generates:
- A random master key (full entropy, very strong).
- Our passphrase will be used to derive a key encryption key (KEK) using PBKDF2 or Argon2 key derivation.
- This KEK will encrypt the master key and then it will store it in the LUKS header.
When we later open (cryptsetup open
):
- We have to enter the same passphrase as we gave earlier.
- Next KEK is derived and Master key is decrypted.
- The master key will be loaded into kernel memory and will be used for actual disk I/O encryption/decryption.
Initialize LUKS device
Next, you need to do luksOpen
, and that brings you to a different level where you are going to work with the encrypted device. So this will create a new device, and this new device is managed by the device mapper, so let's call it /dev/mapper/secret
.
golinuxcloud@server1:~$ sudo cryptsetup luksOpen /dev/sdb1 secret
Enter passphrase for /dev/sdb1:
As we will see when you are using the cryptsetup
, luksOpen
command, a new device is created, and you will provide the name for the device. In this example, the name for the device is /dev/mapper/secret
golinuxcloud@server1:~$ ls -l /dev/mapper/
total 0
crw------- 1 root root 10, 236 May 30 18:41 control
lrwxrwxrwx 1 root root 7 May 30 19:06 secret -> ../dm-1
lrwxrwxrwx 1 root root 7 May 30 18:41 ubuntu--vg-ubuntu--lv -> ../dm-0
Create file system on LUKS device
Now the important step is that you need to create a file system on the encrypted device, and that means that the file system is going to be created here.
golinuxcloud@server1:~$ sudo pvcreate /dev/mapper/secret
Physical volume "/dev/mapper/secret" successfully created.
golinuxcloud@server1:~$
golinuxcloud@server1:~$ sudo vgcreate secure_vg /dev/mapper/secret
Volume group "secure_vg" successfully created
golinuxcloud@server1:~$
golinuxcloud@server1:~$ sudo lvcreate -l 100%FREE -n secure_lv secure_vg
Logical volume "secure_lv" created.
golinuxcloud@server1:~$
golinuxcloud@server1:~$ sudo mkfs.ext4 /dev/secure_vg/secure_lv
mke2fs 1.47.1 (20-May-2024)
Creating filesystem with 1305600 4k blocks and 326400 inodes
Filesystem UUID: 48ab4b7c-7a7c-41d6-b3a4-be45baa6a571
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done
Mount the LUKS partition
Once a file system has been created on the LUKS device, you can move on, you can create a mount point and mount it.
sudo mkdir /mnt/secure-lvm
sudo mount /dev/secure_vg/secure_lv /mnt/secure-lvm
Once we can verify using the mount command, you can see that from the mount command perspective, there's nothing visible about the device being encrypted, we just see a device that is encrypted.
golinuxcloud@server1:~$ mount | grep secure
/dev/mapper/secure_vg-secure_lv on /mnt/secure-lvm type ext4 (rw,relatime)
So we can create files on top of it. (computer keys tapping and clicking) And these files will be safely stored on the encrypted device.
Auto mount LUKS device using fstab with key (No prompt for LUKS passphrase)
Verify existing key slots
The current version of LUKS (LUKS2) supports up to 32 encryption keys per encrypted volume, whereas LUKS1 only supports up to 8 keys. Each slot can store a different key (password or keyfile) to unlock the same encrypted data. We can use one of these keys (for example, a keyfile stored securely) to configure auto-mounting of LUKS devices
But do you wonder, why we will need so many slots?
This can actually help for scenarios like following:
Reason | Why it helps |
---|---|
🔑 Multiple users | Admin and user can have separate passphrases |
🔄 Key rotation | You can add a new key, test it, then remove old key — without re-encrypting the entire disk |
🔐 Keyfiles for automation | Use passphrase for manual unlock + keyfile for auto-unlock at boot |
🎯 Backup key | Keep an emergency recovery passphrase |
🏢 Enterprise setups | One slot for admin, one for automation, one for recovery, etc. |
Let's dump the existing set of key slots using luksDump
:
golinuxcloud@server1:~$ sudo cryptsetup luksDump /dev/sdb1
LUKS header information
Version: 2
Epoch: 5
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 9cc957b0-fd12-4e73-affb-a96f2138d6e2
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 4096 [bytes]
Keyslots:
0: luks2
Key: 256 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 256 bits
PBKDF: argon2id
Time cost: 4
Memory: 761034
Threads: 2
Salt: db 23 b5 e3 ab 47 e3 5d 1d 70 8c 13 20 2c 16 38
46 65 3e 5c 05 92 5d 55 5e ba fa 4d bb e1 da f4
AF stripes: 4000
AF hash: sha512
Area offset:32768 [bytes]
Area length:131072 [bytes]
Digest ID: 0
Tokens:
Digests:
0: pbkdf2
Hash: sha512
Iterations: 193607
Salt: 80 b9 5e 4b f8 cc f0 fb 3a 14 7b a4 90 be 30 d5
cd 75 e6 50 49 41 71 b2 89 f9 fe 2c 95 89 2d 2c
Digest: 84 1e 62 02 c5 64 26 79 0f 0e 4e 4f f5 c5 b5 94
a2 69 d3 49 03 1c 1a 19 db 86 cd a2 f8 40 05 6d
9c 05 70 2e 72 44 87 9c 71 bb 43 f2 3c b8 fe a0
0f 1d d9 e3 e9 35 58 d8 b7 cd 73 f8 5a a5 5e 7d
As you can see, currently only one active keyslot: Keyslot 0. This slot holds the encrypted copy of the master key — protected by the passphrase we entered during luksFormat.
When we run sudo cryptsetup open /dev/sdb1
secret then we are using the passphrase stored in Keyslot 0 to decrypt the master key and unlock the disk.
Next we need to create a keyfile which will be used to auto mount the partition during reboot. As if you don't follow this then the boot up stage will halt at password prompt while trying to mount the encrypted disk.
Create keyfile to avoid interactive passphrase prompt
sudo dd if=/dev/urandom of=/root/keyfile.bin bs=512 count=4
sudo chmod 600 /root/keyfile.bin
Now add this key to LUKS:
sudo cryptsetup luksAddKey /dev/sdb1 /root/keyfile.bin
This will just add the keyfile into a new slot.
Let's re-verify the key dump:
golinuxcloud@server1:~$ sudo cryptsetup luksDump /dev/sdb1
LUKS header information
Version: 2
Epoch: 6
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: 9cc957b0-fd12-4e73-affb-a96f2138d6e2
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flags)
Data segments:
0: crypt
offset: 16777216 [bytes]
length: (whole device)
cipher: aes-xts-plain64
sector: 4096 [bytes]
Keyslots:
0: luks2
Key: 256 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 256 bits
PBKDF: argon2id
Time cost: 4
Memory: 761034
Threads: 2
Salt: db 23 b5 e3 ab 47 e3 5d 1d 70 8c 13 20 2c 16 38
46 65 3e 5c 05 92 5d 55 5e ba fa 4d bb e1 da f4
AF stripes: 4000
AF hash: sha512
Area offset:32768 [bytes]
Area length:131072 [bytes]
Digest ID: 0
1: luks2
Key: 256 bits
Priority: normal
Cipher: aes-xts-plain64
Cipher key: 256 bits
PBKDF: argon2id
Time cost: 4
Memory: 1048576
Threads: 2
Salt: 45 06 0a 8b fd ec 3a 03 60 71 9d 62 c2 ef 8b 8f
b3 75 76 dd 4a 38 28 40 5d 93 06 b4 d8 68 d4 b6
AF stripes: 4000
AF hash: sha256
Area offset:163840 [bytes]
Area length:131072 [bytes]
Digest ID: 0
sudo cryptsetup luksRemoveKey /dev/sdb1
which will remove that keyslot. If you know the exact keyslot to be removed then you can also use sudo cryptsetup luksKillSlot /dev/sdb1 1
where 1
is the slot to be deleted.
Configure /etc/crypttab for automatic LUKS unlock
First, get UUID of your encrypted partition:
golinuxcloud@server1:~$ sudo blkid /dev/sdb1
/dev/sdb1: UUID="9cc957b0-fd12-4e73-affb-a96f2138d6e2" TYPE="crypto_LUKS" PARTUUID="daf1796a-01"
Now edit /etc/crypttab
using sudo privilege and add following entry based on your UUID value:
secret UUID=9cc957b0-fd12-4e73-affb-a96f2138d6e2 /root/keyfile.bin luks
secret
→ this is the LUKS mapper name (/dev/mapper/secret
)- Keyfile path is used to unlock automatically.
Configure /etc/fstab for LVM mount
Earlier we had created a directory /mnt/secure-lvm
to mount our secure LVM /dev/secure_vg/secure_lv
. So, now we will update our /etc/fstab
to automatically mount this partition:
Update initramfs
Since we're modifying boot-time decryption:
golinuxcloud@server1:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.11.0-19-generic
Don't skip this — or else boot may fail because your crypttab changes won’t be loaded into initrd.
Test the full boot automation
Reboot your VM. System should automatically:
- Unlock
/dev/sdb1
via keyfile. - Map it as
/dev/mapper/secret
. - Activate
secure_vg
automatically. - Mount
secure_lv
on your target mount point.
As in my case, the partition is added automatically:
golinuxcloud@server1:~$ mount | grep secure
/dev/mapper/secure_vg-secure_lv on /mnt/secure-lvm type ext4 (rw,relatime)
Lastly I hope the steps from the article to encrypt hard disk (partition) using LUKS on Linux was helpful. So, let me know your suggestions and feedback using the comment section.
In the next article I will share the steps to automatically decrypt and mount the encrypted partition at booting stage using key file on Linux
Great & helpful tutorials, these helped me to setup & automount encrypted partition, thank you!
As suggestion, running the cryptsetup with arguments “cryptsetup –sector-size=4096 –key-size=256” provides better performance than the default settings.
hello, thank you for this tutorial..
I want to ask about change mount point..
I want to move all my /home to separated encrypted disk..
so, according this tutorial, I just need change /secret to /home, isn’t it?? or there is additional workaround??
thank you..
You will have to create an additional encrypted partition and then move your data from /home to this new partition which in this article is /secret.
ok, thank you very much..
Hi there!
I tried to do this procedure on a second backup device. The first device still works like a charm (also automounting) but the new device is not mounting.
My fstab looks like this:
and my crypttab like this:
When plugin the new HDD sdb changed to sdc. So the old HDD is
/dev/sdc1
and still working. The new is/dev/sdb1
.I can only mount the new HDD after:
Before this I am not able to mount the new HDD. How can I perform encryption with two HDDs?
You will have to create a key slot for the second device as well to make it auto mount after reboot.
Thanks a lot! Works like a charm now. I think the mistake was with this:
It should be:
Thanks for highlighting, I overlooked the LVM name 🙂
I am glad you sorted it out and thanks for sharing the solution.
Very nice – much appreciated.
Hello, thank you very much for the tuto!
A question: what is the difference between encrypting a partition and simply assigning password protected privileges to a file system, like a user password or a root password? For instance, allowing only root access to a file, or simply use a user’s password to open a session? If the drive is stolen, people won’t have access to the content either, no?
both have their pros and cons, it would depend on the end user’s requirement.
i tried it didn’t help
PLS Help Me!
you have to be more descriptive!
Really great Tutorial! I run through it in Kubuntu 18.04 and everything from the start worked out very nicely!!! Great job! Cheers