Encrypting PostgreSQL with LUKS on Linux
Encrypting PostgreSQL with LUKS on Linux
Transparent Data Encryption in PostgreSQL becomes a top priority, securing sensitive information at rest is a non-negotiable requirement for any database system. PostgreSQL, being one of the most widely used open-source databases, can benefit greatly from Linux Unified Key Setup (LUKS) to encrypt its data directories. This approach ensures that even if someone gains unauthorized physical access to your disks, they won’t be able to read your database contents without the proper encryption key.

In this guide, we’ll walk through the entire process of encrypting a disk with LUKS, mounting it as the PostgreSQL data directory, and ensuring it works seamlessly with your PostgreSQL service. Additionally, we’ll explore how this setup impacts performance and provide tips for mitigating potential slowdowns.
Overview
This guide includes the following steps:
- Encrypting the disk using LUKS: Secure your disk with industry-standard encryption.
- Unlocking and formatting the disk: Prepare the encrypted volume for use.
- Mounting and assigning the PostgreSQL data directory: Direct PostgreSQL to use the new secure location.
- Configuring auto-unlock and mount at boot: Make sure your encrypted volume is available after reboots.
- Migrating existing PostgreSQL data: Move your database files safely.
- Evaluating performance: Understand how encryption affects system performance.
- Alternative encryption strategies: Explore other ways to secure your PostgreSQL data.
Preparing and Encrypting the Disk with LUKS
Let’s assume you’ve added a new disk to your Linux system:
lsblk
Example output:
sdd 8:16 0 500G 0 disk
Install cryptsetup if it’s not already installed:
dnf install cryptsetup
Warning: below will destroy all existing data on /dev/sdd. Make sure to back up any important data beforehand.
# Encrypt the disk using LUKS:
cryptsetup luksFormat /dev/sdd
This command initializes the disk with LUKS, turning it into a secure, encrypted volume. You’ll be prompted to enter a passphrase.
Unlock and Format the Encrypted Disk
Unlock the encrypted volume:
cryptsetup luksOpen /dev/sdd cryptdata
If successful, a decrypted mapping will appear at /dev/mapper/cryptdata. Also, using only open syntax supports other encryption backends besides LUKS, such as plain, loopaes or tcrypt. For example:
cryptsetup open /dev/sdd cryptdata
cryptdata: The logical name (mapping name) to be created after the device is opened.Now create a filesystem on it:
mkfs.xfs /dev/mapper/cryptdata
You can use other file systems (e.g., ext4) if desired.
Mounting the Disk and Setting Up PostgreSQL Directory
Create a mount point:
mkdir -p /security/pg_data
chown postgres:postgres /security/pg_data -R
chmod 650 -R /security/pg_data/
chmod 700 /security/pg_data
Mount the disk:
mount /dev/mapper/cryptdata /security/pg_data
To make it persistent across reboots, add the following lines to /etc/fstaband /etc/crypttab:
# For /etc/fstab
/dev/mapper/cryptdata /security/pg_data xfs defaults 0 2
# For /etc/crypttab
cryptdata /dev/sdd /root/cryptkeyfile luks
Auto-Unlocking on Boot (Optional)
To avoid manually entering the passphrase at boot, you can use a keyfile.
Generate the keyfile:
dd if=/dev/urandom of=/root/cryptkeyfile bs=1024 count=4
chmod 600 /root/cryptkeyfile
Add it to LUKS:
cryptsetup luksAddKey /dev/sdd /root/cryptkeyfile
Update /etc/crypttab:
cryptdata /dev/sdd /root/cryptkeyfile luks
Enable the cryptsetup service:
systemctl start cryptsetup.target
Test automatic mounting:
mount -a
Migrating PostgreSQL Data
Before making any changes, it’s essential to back up your existing PostgreSQL data. This step ensures that you have a safety net in case something goes wrong during the upgrade process.
Using pg_dumpall:
pg_dumpall > all_databases_backup.sql
If pgBackRest is available:
pgbackrest --stanza=main --type=full backup
These commands create a comprehensive backup of your current databases, which will be helpful if you need to restore your data later.
Stop PostgreSQL:
systemctl stop postgresql-13.service
Move the existing data to the new encrypted volume:
rsync -av --progress /var/lib/pgsql/13/data/ /security/pg_data/
Edit PostgreSQL’s systemd service unit file:
vi /usr/lib/systemd/system/postgresql-13.service
Change:
# Environment=PGDATA=/var/lib/pgsql/13/data/
Environment=PGDATA=/security/pg_data
Reload systemd and start PostgreSQL:
systemctl daemon-reload
systemctl start postgresql-13.service
Verify:
postgres=# show data_directory;
data_directory
-------------------
/security/pg_data
(1 row)
Performance Considerations
Does using LUKS affect PostgreSQL performance? Yes but usually only slightly, especially if you have modern hardware.
Things to Check:
- CPU AES Support:
lscpu | grep aes
- If your processor supports AES-NI, encryption operations are hardware-accelerated, minimizing overhead.
- Run Benchmarks:
- Use tools like
pgbenchto test performance with and without encryption. - Monitor I/O-Intensive Workloads:
- Monitor for slowdowns in disk-heavy operations. If disk I/O is your bottleneck, you may observe a measurable impact.
Alternatives to Full Disk Encryption
- Use Encrypted Partitions:
- Encrypt only the partitions storing sensitive data (e.g., via PostgreSQL tablespaces).
- Application-Level Encryption:
- Encrypt data at the column level in the application before storing it.
These approaches offer flexibility, especially if full-disk encryption introduces too much overhead or operational complexity.
Conclusion
Using LUKS to encrypt your PostgreSQL data directory is a robust way to protect your data from physical theft or unauthorized access. With proper hardware support and tuning, the performance trade-offs can be negligible. For high-security environments, it’s a small price to pay for peace of mind.
If your data matters, encrypt it.
← PostgreSQL Blog