Welcome to the open source implementation of PostgreSQL Transparent Data Encryption!
This question was posed on the PostgreSQL forum, and the good news is that it’s actually pretty easy to do!
Q: Is it possible to automate the steps to enable pg_tde for all new databases?
A: Yes!
Here’s the routine:
- Part I: Download Percona Distribution for PostgreSQL and the pg_tde extension
- Part II: Configure pg_tde, permitting the encryption of tables
Part I
Getting pg_tde
The best way to get pg_tde is through Percona’s Distribution of PostgreSQL, which includes a curated collection of packages and extensions for enterprise production environments.
The long-term goal is to enable pg_tde across all Postgres implementations, irrespective of source repository. Community efforts are currently underway to tweak the Postgres base code, making this possible.
Here’s what you need to do on Ubuntu 24.04 (noble)…
Log in to your distro and perform the following as “root”:
1 2 |
#Make certain the packages are updated: apt update && apt upgrade -y |
You’ll need to install Percona Distribution for PostgreSQL:
1 |
apt install -y curl wget gnupg2 |
Installing Percona Distribution for PostgreSQL, among many other packages and extensions, includes the pg_tde extension.
1 2 |
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb dpkg -i percona-release_latest.generic_all.deb |
Note: Pay attention to the distribution version as the repository is constantly being updated.
1 2 |
#Enable the repository, you must use at least postgres version 17.5 percona-release enable ppg-17.5 release |
Install PostgreSQL, and the data cluster is created and started automatically:
1 |
apt install -y percona-postgresql-17 |
Enable pg_tde on the data cluster and restart the service:
1 2 |
pg_conftool 17 main postgresql.auto.conf set shared_preload_libraries 'pg_tde' systemctl restart postgresql@17-main |
Part II
Enabling and configuring table encryption across the data cluster
Enabling table encryption requires creating the extension in the database.
Here are the steps:
- Step 1: Create the template database and create the extension pg_tde
- Step 2:
- Create your database i.e., db01
- Add the “global” key provider via one of the two following methods:
- keyfile (localhost)
- key management server
In production, it is recommended to use a key management server, such as, for example, but not limited to, Hashicorp’s vault.
- Set the key
- Step 3: Create the user-defined database, log in, and create the table(s)/relation(s) as required
There are two methods for registering the provider.
- Per database
- Globally, across the data cluster
To keep things as simple as possible, we’ll use the global approach: register once, use everywhere.
Step 1: Create the template database
One can save effort by creating a “template” database; execute the following as postgres:
1 2 |
createdb tde_template psql tde_template -c 'create extension pg_tde' |
Step 2: Add the key provider and set the key
Log in to the template database and add the key provider.
Recall, we’re using a local keyfile, which can be located anywhere on the physical host that the PostgreSQL process owner can access.
1 2 |
createdb tde_template psql tde_template -c 'create extension pg_tde' |
Step 3: Create the user-defined database and encrypted tables
1 2 |
# Now let's create our encrypted database createdb --template=tde_template db01 |
1 2 3 4 5 |
-- database db01: -- add global provider and set the key select pg_tde_add_global_key_provider_file('provider_global','/var/lib/postgresql/key_global.file'); select pg_tde_create_key_using_global_key_provider('key_global','provider_global'); select pg_tde_set_key_using_global_key_provider('key_global','provider_global'); |
1 2 3 4 5 6 |
-- validate select * from pg_tde_list_all_global_key_providers(); id | name | type | options<br />----+-----------------+------+--------------------------------------------------<br /> -1 | provider_global | file | {"path" : "/var/lib/postgresql/key_global.file"} <b>-- -- -- --</b> select * from pg_tde_key_info(); key_name | provider_name | provider_id | key_creation_time <br />------------+-----------------+-------------+------------------------------- <br /> key_global | provider_global | -1 | 2025-07-02 21:06:00.875074+00 |
Creating the encrypted table is easy, as all that’s required is specifying the relation’s access method, i.e., “tde_heap”. Note that you can have both encrypted and unencrypted tables in the same database:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-- database db01 create table t1 ( id serial primary key, comments text default 'hello world, t1', t_stamp timestamptz default now() ) using tde_heap; -- check table is encrypted select * from pg_tde_is_encrypted('t1'); insert into t1 values(default,default,default) ,(default,default,default) ,(default,default,default); -- validate table t1; |
Since both the provider and key are global, it means creating new, encrypted databases requires minimal effort.
1 |
createdb db02 --template tde_template |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-- database db02 select pg_tde_set_key_using_global_key_provider('key_global','provider_global'); create table t2 ( id serial primary key, comments text default 'hello world, t2', t_stamp timestamptz default now() ) using tde_heap; -- check table is encrypted select * from pg_tde_is_encrypted('t2'); <strong><br /></strong>-- add records insert into t2 values(default,default,default) ,(default,default,default) ,(default,default,default); -- validate table t1; |
Conclusion
The next step in your journey into PostgreSQL transparent data encryption is to familiarize yourself with the full API and learn how to work with the key management server. References are included below.
References
- PostgreSQL:
- Reference documentation, version 17
- Percona:
- KMIP, specs