PG-1354: Update documentation with latest changes (#46)

pull/209/head
Zsolt Parragi 7 months ago committed by GitHub
parent b31a383381
commit 828a42a81b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 48
      contrib/pg_tde/documentation/_resource/overrides/main.html
  2. 9
      contrib/pg_tde/documentation/_resource/overrides/partials/banner.html
  3. 81
      contrib/pg_tde/documentation/docs/css/design.css
  4. 16
      contrib/pg_tde/documentation/docs/css/extra.css
  5. 15
      contrib/pg_tde/documentation/docs/decrypt.md
  6. 144
      contrib/pg_tde/documentation/docs/faq.md
  7. 24
      contrib/pg_tde/documentation/docs/get-help.md
  8. 10
      contrib/pg_tde/documentation/docs/index.md
  9. 38
      contrib/pg_tde/documentation/docs/install.md
  10. 6
      contrib/pg_tde/documentation/docs/setup.md
  11. 20
      contrib/pg_tde/documentation/docs/test.md
  12. 2
      contrib/pg_tde/documentation/mkdocs-pdf.yml
  13. 6
      contrib/pg_tde/documentation/mkdocs.yml
  14. 13
      contrib/pg_tde/documentation/snippets/services-banner.md

@ -24,14 +24,46 @@
{% endif %}
<meta property="og:type" content="website" />
<meta property="og:title" content="{{ title }}" />
<meta property="og:image" content="https://percona-lab.github.io/pg_tde/main/documentation/_images/pg_tde.png">
<meta property="og:url" content="https://percona-lab.github.io/pg_tde/main/">
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_7unoI9J6Fm0SMrfDp35xNOpCRTkOAibbffQwdGWbHnL',{api_host:'https://eu.posthog.com'})
</script>
{% endblock %}
<meta property="og:image" content="https://percona.github.io/pg_tde/main/documentation/_images/pg_tde.png">
<meta property="og:url" content="https://percona.github.io/pg_tde/main/">
{% endblock %}
{% block site_nav %}
{% if nav %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "navigation" in page.meta.hide %}
{% endif %}
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" {{ hidden }}>
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
{% include "partials/nav.html" %}
<br>
<label class="md-nav__title" for="__drawer">
</label>
</div>
</div>
</div>
{% endif %}
{% if "toc.integrate" not in features %}
{% if page.meta and page.meta.hide %}
{% set hidden = "hidden" if "toc" in page.meta.hide %}
{% endif %}
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" {{ hidden }}>
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
{% include "partials/toc.html" %}
</div>
<div class="md-sidebar__inner">
{% include "partials/banner.html" %}
</div>
</div>
</div>
{% endif %}
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_7unoI9J6Fm0SMrfDp35xNOpCRTkOAibbffQwdGWbHnL',{api_host:'https://eu.posthog.com'})
</script>
{% endblock %}

@ -0,0 +1,9 @@
<div data-banner="data-banner">
<p><svg style="display:block;margin:-1em 0 0.75em" width="78" height="69" viewBox="0 0 78 69" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M56.7281 30.7666C62.6528 26.8938 64.5914 18.9942 61.0059 12.7854C59.2094 9.67113 56.3053 7.44082 52.8311 6.50951C49.6122 5.64535 46.2502 5.99872 43.2912 7.49366L39.251 0.5L30.8648 15.0245L11.4811 48.5937H67.021L56.7281 30.7666ZM51.881 10.0674C54.4064 10.7401 56.5079 12.3616 57.8168 14.6194C60.3895 19.0701 59.053 24.7153 54.8808 27.5665L45.1362 10.6905C47.2355 9.68104 49.6034 9.46087 51.881 10.0674ZM39.251 7.87125L60.6339 44.907H48.1228L32.9927 18.7102L39.2499 7.87235L39.251 7.87125ZM17.8682 44.907L30.8637 22.4035L43.8592 44.907H17.8682Z" fill="url(#paint0_linear_2899_1968)"></path><path style="fill:var(--md-typeset-color)" d="M4.981 64.943H3.157V68.207H.756V57.323H5.217C7.822 57.323 9.397 58.861 9.397 61.086V61.116C9.397 63.635 7.433 64.94 4.984 64.94L4.981 64.943V64.943ZM6.961 61.134C6.961 60.061 6.213 59.485 5.011 59.485H3.154V62.812H5.056C6.258 62.812 6.958 62.096 6.958 61.163V61.134H6.961ZM10.738 68.208V57.323H18.973V59.455H13.124V61.664H18.27V63.796H13.124V66.082H19.051V68.214H10.738V68.208 68.208ZM27.557 68.208 25.218 64.726H23.332V68.208H20.931V57.323H25.921C28.496 57.323 30.039 58.677 30.039 60.915V60.945C30.039 62.702 29.088 63.807 27.7 64.32L30.367 68.207H27.556L27.557 68.208ZM27.605 61.041C27.605 60.016 26.887 59.485 25.719 59.485H23.333V62.61H25.767C26.936 62.61 27.605 61.987 27.605 61.071V61.042 61.041ZM36.922 68.499C33.668 68.499 31.249 65.994 31.249 62.825V62.795C31.249 59.659 33.619 57.091 37.019 57.091 39.105 57.091 40.356 57.783 41.383 58.792L39.834 60.571C38.98 59.798 38.113 59.327 37.004 59.327 35.141 59.327 33.795 60.871 33.795 62.762V62.793C33.795 64.684 35.107 66.257 37.004 66.257 38.268 66.257 39.043 65.753 39.913 64.964L41.462 66.524C40.322 67.738 39.059 68.493 36.925 68.493L36.922 68.499ZM47.885 68.499C44.47 68.499 42.021 65.962 42.021 62.825V62.795C42.021 59.659 44.503 57.091 47.915 57.091 51.327 57.091 53.779 59.628 53.779 62.765V62.795C53.779 65.931 51.297 68.499 47.885 68.499ZM51.237 62.795C51.237 60.904 49.846 59.331 47.885 59.331 45.925 59.331 44.567 60.874 44.567 62.766V62.796C44.567 64.688 45.959 66.261 47.919 66.261 49.879 66.261 51.237 64.717 51.237 62.826V62.795 62.795ZM67.001 68.217 72.374 57.091 77.746 68.218H75.052L72.374 62.681 69.705 68.218H67.001V68.217ZM66.007 57.327V68.5L57.813 61.884V68.199H55.264V57.091L63.458 63.681V57.327H66.007Z"></path><defs><linearGradient id="paint0_linear_2899_1968" x1="18.1513" y1="44.7152" x2="61.4356" y2="20.9786" gradientUnits="userSpaceOnUse"><stop stop-color="#FC3519"></stop><stop offset="1" stop-color="#F0D136"></stop></linearGradient></defs></svg></p>
<p>For help, click the link below to get free database assistance or contact our experts for personalized support.</p>
<div class="actions">
<a href="https://docs.percona.com/pg-stat-monitor/get-help.html" style="color: var(--md-typeset-a-color);">Get help from Percona</a>
</div>
</div>

@ -77,6 +77,7 @@
[data-md-color-scheme="percona-light"] {
/* Primitives */
--md-hue: 220;
--md-primary-fg-color: var(--sky700);
/* Type */
@ -85,6 +86,7 @@
/* Defaults */
--md-default-bg-color: var(--white);
--md-default-fg-color: var(--stone900);
--md-default-fg-color--light: rgba(44,50,62,0.72);
--md-default-fg-color--lighter: rgba(44,50,62,0.40);
--md-default-fg-color--lightest: rgba(44,50,62,0.25);
@ -102,11 +104,14 @@
/* Code */
--md-code-bg-color: var(--stone800);
--md-code-bg-color: var(--stone50);
/* Tables */
--md-typeset-table-color: hsla(var(--md-hue),17%,21%,0.25)
}
[data-md-color-scheme="percona-dark"] {
/* Primitives */
--md-hue: 230;
--md-hue: 0;
--md-primary-fg-color: var(--sky200);
/* Type */
@ -115,6 +120,7 @@
/* Defaults */
--md-default-bg-color: var(--stone900);
--md-default-fg-color: var(--white);
--md-default-fg-color--light: rgba(251,251,251,0.72);
--md-default-fg-color--lighter: rgba(251,251,251,0.4);
--md-default-fg-color--lightest: rgba(209,213,222,0.25);
@ -133,6 +139,9 @@
/* Code */
--md-code-bg-color: var(--stone50);
--md-code-bg-color: var(--stone800);
/* Tables */
--md-typeset-table-color: hsla(var(--md-hue),0%,100%,0.25)
}
/* Typography */
@ -155,7 +164,7 @@
.md-typeset h1 {
margin: 0 0 0.75em;
}
.md-header {
.md-header :not(.md-search__suggest) {
font-family: var(--fHeading);
font-weight: bold;
}
@ -208,12 +217,20 @@
.md-tabs__link {
margin-top: 0.55rem;
}
.md-header__topic {
transition: opacity .25s;
}
.md-header__topic:hover {
opacity: 0.7;
/* .md-header__topic .md-ellipsis {
position: relative;
}
.md-header__topic:hover .md-ellipsis::after {
content: "";
position: absolute;
display: block;
right: 0;
bottom: 11px;
left: 0;
width: 100%;
height: 2.5px;
background-color: currentColor;
} */
/* Footer */
@ -254,6 +271,13 @@
vertical-align: baseline;
padding: 0 0.2em 0.1em;
border-radius: 0.15em;
white-space: pre-wrap; /* Ensure long lines wrap */
}
.md-typeset .highlight code span,
.md-typeset code,
.md-typeset kbd,
.md-typeset pre {
color: var(--md-typeset-color);
}
.md-button code,
[data-md-color-scheme="percona-dark"] .md-button:not(.md-button--primary) code {
@ -636,6 +660,7 @@ i[warning] [class*="moji"] {
-moz-appearance: none;
appearance: none;
align-self: center;
font-family: var(--fHeading);
font-size: 0.9rem;
line-height: 1;
font-weight: 700;
@ -650,6 +675,46 @@ i[warning] [class*="moji"] {
display: none;
}
/* Mike Version Select */
.md-version__current,
.md-version__link {
font-size: 0.9rem;
font-weight: 700;
line-height: 1;
padding: 0.5em;
}
.md-version__current {
top: unset;
margin-left: 0.25em !important;
margin-right: 0.25em !important;
border-radius: 0.1rem;
background-color: rgba(0,0,0,0.2);
}
.md-version__current::after {
width: 0.5em;
height: 0.75em;
}
.md-version__list {
top: 0.1em;
margin: 0.25em;
border-radius: 0.1rem;
}
[dir="ltr"] .md-version__current::after {
margin-left: 0.4em;
}
[dir="rtl"] .md-version__current::after {
margin-right: 0.4em;
}
[dir="ltr"] .md-version__link {
padding-left: 0.5em;
padding-right: 1.4375em;
}
[dir="rtl"] .md-version__link {
padding-left: 1.4375em;
padding-right: 0.5em;
}
/* Media queries */
@media screen and (max-width: 76.1875em) {
@ -667,4 +732,4 @@ i[warning] [class*="moji"] {
padding: 1em;
}
}
/**/
/**/

@ -1,7 +1,13 @@
@media print {
/* Adjusts positioning of admonition icon */
.md-typeset :is(.admonition-title,summary):before {
top: 0.6rem;
left: 0.6rem;
}
}
.md-typeset :is(.admonition-title,summary):before {
top: 0.6rem;
left: 0.6rem;
}
}
.md-sidebar__inner {
font-size: 0.65rem; /* Font size */
line-height: 1.6;
}

@ -8,6 +8,12 @@ If you encrypted a table with the `tde_heap` or `tde_heap_basic` access method a
ALTER TABLE mytable SET access method heap;
```
Note that the `ALTER TABLE SET` command drops hint bits and this may affect the performance. Running a plain `SELECT, count(*)`, or `VACUUM` commands on the entire table will check every tuple for visibility and set its hint bits. Therefore, after executing the ALTER command, run a simple "count(*)" on your tables:
```
SELECT COUNT(*) FROM mytable;
```
Check that the table is not encrypted:
```
@ -25,6 +31,13 @@ The output returns `f` meaning that the table is no longer encrypted.
```
Note that the indexes and WAL files will no longer be encrypted.
Run a simple "count(*)" on your table to check every tuple for visibility and set the hint bits:
```
SELECT COUNT(*) FROM mytable;
```
## Method 2. Create a new unencrypted table on the base of the encrypted one
@ -41,4 +54,4 @@ The new table `Customers` inherits the structure and the data from `EncryptedCus
```
DROP TABLE EncryptedCustomers;
```
```

@ -2,18 +2,53 @@
## Why do I need TDE?
- Compliance to security and legal regulations like GDPR, PCI DSS and others
- Encryption of backups
- Granular encryption of specific data sets and reducing the performance overhead that encryption brings
- Compliance to security and legal regulations like General Data Protection Regulation (GDPR), Payment Card Industry Data Security Standard (PCI DSS), California Consumer Privacy Act (CCPA), Data Protection Act 2018 (DPA 2018) and others
- Encryption of backups. Even when an authorized person gets physical access to a backup, encryption ensures that the data remains unreadable and secure.
- Granular encryption of specific data sets and reducing the performance overhead that encryption brings.
- Additional layer of security to existing security measures
## When and how should I use TDE?
If you are dealing with Personally Identifiable Information (PII), data encryption is crucial. Especially if you are involved in areas with strict regulations like:
* financial services where TDE helps to comply with PCI DSS
* healthcare and insurance - compliance with HIPAA, HITECH, CCPA
* telecommunications, government and education to ensure data confidentiality.
Using TDE helps you avoid the following risks:
* Data breaches
* Identity theft that may lead to financial fraud and other crimes
* Reputation damage leading to loss of customer trust and business
* Legal consequences and financial losses for non-compliance with data protection regulations
* Internal threats by misusing unencrypted sensitive data
If to translate sensitive data to files stored in your database, these are user data in tables, temporary files, WAL files. TDE has you covered encrypting all these files.
`pg_tde` does not encrypt system catalogs yet. This means that statistics data and database metadata are not encrypted. The encryption of system catalogs is planned for future releases.
## I use disk-level encryption. Why should I care about TDE?
Encrypting a hard drive encrypts all data including system and application files that are there. However, disk encryption doesn’t protect your data after the boot-up of your system. During runtime, the files are decrypted with disk-encryption.
Encrypting a hard drive encrypts all data, including system, application, and temporary files.
Full disk encryption protects your data from people who have physical access to your device and even if it is lost or stolen. However, it doesn't protect the data after system boot-up: the data is automatically decrypted when the system runs or when an authorized user requests it.
Another point to consider is PCI DSS compliance for Personal Account Numbers (PAN) encryption.
* **PCI DSS 3.4.1** standards might consider disk encryption sufficient for compliance if you meet these requirements:
* Separate the logical data access from the operating system authentication.
* Ensure the decryption key is not linked to user accounts.
Note that PCI DSS 3.4.1 is retiring on March 31, 2025. Therefore, consider switching to PCI DSS 4.0.
* **PCI DSS 4.0** standards consider using only disk and partition-level encryption not enough to ensure PAN protection. It requires an additional layer of security that `pg_tde` can provide.
TDE focuses specifically on data files and offers a more granular control over encrypted data. It also ensures that files are encrypted on disk during runtime and when moved to another system or storage.
`pg_tde` focuses specifically on data files and offers more granular control over encrypted data. The data remains encrypted on disk during runtime and when you move it to another directory, another system or storage. An example of such data is backups. They remain encrypted when moved to the backup storage.
Consider using TDE and storage-level encryption together to add another layer of data security
Thus, to protect your sensitive data, consider using TDE to encrypt it at the table level. Then use disk-level encryption to encrypt a specific volume where this data is stored, or the entire disk.
## Is TDE enough to ensure data security?
@ -25,6 +60,101 @@ No. TDE is an additional layer to ensure data security. It protects data at rest
* Regular monitoring and auditing
* Additional data protection for sensitive fields (e.g., application-layer encryption)
## How does `pg_tde` make my data safe?
`pg_tde` uses two keys to encrypt data:
* Internal encryption keys to encrypt the data. These keys are stored internally in an encrypted format, in a single `$PGDATA/pg_tde` directory.
* Principal keys to encrypt internal encryption keys. These keys are stored externally, in the Key Management System (KMS).
You can use the following KMSs:
* [HashiCorp Vault](https://developer.hashicorp.com/vault/docs/what-is-vault). `pg_tde` supports the KV secrets engine v2 of Vault.
* [OpenBao](https://openbao.org/) implementation of Vault
* KMIP-compatible server. KMIP is a standardized protocol for handling cryptographic workloads and secrets management
HashiCorp Vault can also act as the KMIP server, managing cryptographic keys for clients that use the KMIP protocol.
Here’s how encryption of data files works:
First, data files are encrypted with internal keys. Each file that has a different OID, has an internal key. For example, a table with 4 indexes will have 5 internal keys - one for the table and one for each index.
The initial decision on what file to encrypt is based on the table access method in PostgreSQL. When you run a `CREATE` or `ALTER TABLE` statement with the `USING tde_heap` clause, the newly created data files are marked as encrypted, and then file operations encrypt/decrypt the data. Later, if an initial file is re-created as a result of a `TRUNCATE` or `VACUUM FULL` command, the newly created file inherits the encryption information and is either encrypted or not.
The principal key is used to encrypt the internal keys. The principal key is stored in the key management store. When you query the table, the principal key is retrieved from the key store to decrypt the table. Then the internal key for that table is used to decrypt the data.
WAL encryption is done globally for the entire database cluster. All modifications to any database within a PostgreSQL cluster are written to the same WAL to maintain data consistency and integrity and ensure that PostgreSQL cluster can be restored to a consistent state. Therefore, WAL is encrypted globally.
When you turn on WAL encryption, `pg_tde` encrypts entire WAL pages except for the header. The header contains a marker if a page is encrypted or not.
The same 2-tier approach is used with WAL as with the table data: WAL pages are first encrypted with the internal key. Then the internal key is encrypted with the global principal key.
You can turn WAL encryption on and off so WAL can contain both encrypted and unencrypted pages. The WAL encryption GUC variable influences only writes.
Whenever the WAL is being read (by the recovery process or tools), the decision on what pages should be decrypted is based solely on the encryption flag of each page.
## Should I encrypt all my data?
It depends on your business requirements and the sensitivity of your data. Encrypting all data is a good practice but it can have a performance impact.
Consider encrypting only tables that store sensitive data. You can decide what tables to encrypt and with what key. The [Setup](setup.md) section in documentation focuses on this approach.
We advise encrypting the whole database only if all your data is sensitive, like PII, or if there is no other way to comply with data safety requirements. See [How to configure global encryption](global-encryption.md).
## What cipher mechanisms are used by `pg_tde`?
`pg_tde` currently uses a AES-CBC-128 algorithm. First the internal keys in the datafile are encrypted using the principal key with AES-CBC-128, then the file data itself is again encrypted using AES-CBC-128 with the internal key.
For WAL encryption, AES-CTR-128 is used.
The support of other encryption mechanisms such as AES256 is planned for future releases. Reach out to us with your requirements and usage scenarios of other encryption methods are needed.
## Is post-quantum encryption supported?
No, it's not yet supported. In our implementation we reply on OpenSSL libraries that don't yet support post-quantum encryption.
## Can I encrypt an existing table?
Yes, you can encrypt an existing table. Run the ALTER TABLE command as follows:
```
ALTER TABLE table_name SET ACCESS METHOD tde_heap;
```
Since the `ALTER TABLE SET` command drops hint bits and this may affect the performance, we recommend to run the `SELECT COUNT(*)` command. It checks every tuple for visibility and sets its hint bits. Read more in the [Changing existing table](test.md) section.
## Do I have to restart the database to encrypt the data?
You must restart the database in the following cases to apply the changes:
* after you enabled the `pg_tde` extension
* to turn on / off the WAL encryption
After that, no database restart is required. When you create or alter the table using the `tde_heap` access method, the files are marked as those that require encryption. The encryption happens at the storage manager level, before a transaction is written to disk. Read more about [how tde_heap works](table-access-method.md#how-tde_heap-works).
## What happens to my data if I lose a principal key?
If you lose encryption keys, especially, the principal key, the data is lost. That's why it's critical to back up your encryption keys securely.
If you lose encryption keys, especially, the principal key, the data is lost. That's why it's critical to back up your encryption keys securely and use the Key Management service for key management.
## Can I use `pg_tde` in a multi-tenant setup?
Multi-tenancy is the type of architecture where multiple users, or tenants, share the same resource. It can be a database, a schema or an entire cluster.
In `pg_tde`, multi-tenancy is supported via a separate principal key per database. This means that a database owner can decide what tables to encrypt within a database. The same database can have both encrypted and non-encrypted tables.
To control user access to the databases, you can use role-based access control (RBAC).
WAL files are encrypted globally across the entire PostgreSQL cluster using the same encryption key. Users don't interact with WAL files as these are used by the database management system to ensure data integrity and durability.
## Are my backups safe? Can I restore from them?
`pg_tde` encrypts data at rest. This means that data is stored on disk in an encrypted form. During a backup, already encrypted data files are copied from disk onto the storage. This ensures the data safety in backups.
Since the encryption happens on the database level, it makes no difference for your tools and applications. They work with the data in the same way.
To restore from an encrypted backup, you must have the same principal encryption key, which was used to encrypt files in your backup.
## I'm using OpenSSL in FIPS mode and need to use `pg_tde`. Does `pg_tde` comply with FIPS requirements? Can I use my own FIPS-mode OpenSSL library with `pg_tde`?
Yes. `pg_tde` works with the FIPS-compliant version of OpenSSL, whether it is provided by your operating system or if you use your own OpenSSL libraries. If you use your own libraries, make sure they are FIPS certified.

@ -0,0 +1,24 @@
# Get help from Percona
Our documentation guides are packed with information, but they can't cover everything you need to know about `pg_tde`. They also won't cover every scenario you might come across. Don't be afraid to try things out and ask questions when you get stuck.
## Percona's Community Forum
Be a part of a space where you can tap into a wealth of knowledge from other database enthusiasts and experts who work with Percona's software every day. While our service is entirely free, keep in mind that response times can vary depending on the complexity of the question. You are engaging with people who genuinely love solving database challenges.
We recommend visiting our [Community Forum](https://forums.percona.com/t/welcome-to-perconas-community-forum/7){:target="_blank"}. It's an excellent place for discussions, technical insights, and support around Percona database software. If you’re new and feeling a bit unsure, our [FAQ](https://forums.percona.com/faq){:target="_blank"} and [Guide for New Users](https://forums.percona.com/t/faq-guide-for-new-users/8562){:target="_blank"} ease you in.
If you have thoughts, feedback, or ideas, the community team would like to hear from you at [Any ideas on how to make the forum better?](https://forums.percona.com/t/any-ideas-on-how-to-make-the-forum-better/11522){:target="blank"}. We’re always excited to connect and improve everyone's experience.
## Percona experts
[Percona experts](https://www.percona.com/services/consulting){:target="_blank"} bring years of experience in tackling tough database performance issues and design challenges. We understand your challenges when managing complex database environments. That's why we offer various services to help you simplify your operations and achieve your goals.
| Service | Description |
|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 24/7 Expert Support | Our dedicated team of database experts is available 24/7 to assist you with any database issues. We provide flexible support plans tailored to your specific needs. |
| Hands-On Database Management | Our managed services team can take over the day-to-day management of your database infrastructure, freeing up your time to focus on other priorities. |
| Expert Consulting | Our experienced consultants provide guidance on database topics like architecture design, migration planning, performance optimization, and security best practices. |
| Comprehensive Training | Our training programs help your team develop skills to manage databases effectively, offering virtual and in-person courses. |
We're here to help you every step of the way. Whether you need a quick fix or a long-term partnership, we're ready to provide your expertise and support.

@ -2,9 +2,7 @@
`pg_tde` is the open source PostgreSQL extension that provides Transparent Data Encryption (TDE) to protect data at rest. This ensures that the data stored on disk is encrypted, and no one can read it without the proper encryption keys, even if they gain access to the physical storage media.
You can configure encryption differently for each database, encrypting specific tables in some databases with different encryption keys while keeping others unencrypted.
Lear more [what is Transparent Data Encryption](tde.md#how-does-it-work) and [why you need it](tde.md#why-do-you-need-tde).
Learn more [what is Transparent Data Encryption](tde.md#how-does-it-work) and [why you need it](tde.md#why-do-you-need-tde).
!!! important
@ -27,9 +25,9 @@ Lear more [what is Transparent Data Encryption](tde.md#how-does-it-work) and [wh
* Keys in the local keyfile are stored unencrypted. For better security we recommend using the Key management storage.
* System tables are currently not encrypted.
* Currently you cannot update the configuration of an existing Key Management Store (KMS). If its configuration changes (e.g. your Vault server has a new URL), you must set up a new key provider in `pg_tde` and create new keys there. Both the KMS and PostgreSQL servers must be up and running during these changes. [Reach out to our experts](https://www.percona.com/about/contact) for assistance and to outline the best update path for you.
* Currently you cannot update the configuration of an existing Key Management Store (KMS). If its configuration changes (e.g. your Vault server has a new URL), you must set up a new key provider in `pg_tde` and create new keys there. Both the KMS and PostgreSQL servers must be up and running during these changes. [Reach out to our experts](https://www.percona.com/about/contact) for help and to outline the best update path for you.
We plan to introduce the way to update the configuration of an existing KMS in future releases.
We plan to introduce the way to update the configuration of an existing KMS in future releases.
* `pg_rewind` doesn't work with encrypted WAL for now. We plan to fix it in future releases.
@ -50,7 +48,7 @@ The `pg_tde` extension comes in two distinct versions with specific access metho
### Which version to chose?
The answer is pretty straightforward: for data sets where indexing is not mandatory or index encryption is not required, use the community version and the `tde_heap_basic` access method. Check the [upstream documentation :octicons-link-external-16:](https://github.com/percona/pg_tde/blob/main/README.md) how to get started.
Use the community version and the `tde_heap_basic` access method for data sets where indexing is not mandatory or index encryption is not required. Check the [upstream documentation :octicons-link-external-16:](https://github.com/percona/pg_tde/blob/main/README.md) how to get started.
Otherwise, enjoy full encryption with the Percona Server for PostgreSQL version and the `tde_heap` access method.

@ -4,13 +4,27 @@
You can use the following options to manage encryption keys:
* Use the HashiCorp Vault server. This is the recommended approach. The Vault server configuration is out of scope of this document. We assume that you have the Vault server up and running. For the `pg_tde` configuration, you need the following information:
* Use the Key Management Store (KMS). This is the recommended approach. `pg_tde` supports the following KMS:
* The secret access token to the Vault server
* The URL to access the Vault server
* (Optional) The CA file used for SSL verification
* HashiCorp Vault as the key/value secrets engine version 2 with secret versioning
* HashiCorp Vault as the KMIP server. The KMIP server is part of Vault Enterprise and requires a license
* OpenBao as the open-source alternative to HashiCorp Vault KMIP
* A KMIP-compatible server. For testing and development purposes you can use PyKMIP.
* Use the local keyfile. This approach is rather used for development and testing purposes since the keys are stored unencrypted in the specified keyfile.
The KMS configuration is out of scope of this document. We assume that you have the KMS up and running. For the `pg_tde` configuration, you need the following information:
=== "Vault secrets engine"
* The secret access token to the Vault server
* The URL to access the Vault server
* (Optional) The CA file used for SSL verification
=== "KMIP server"
* The hostname or IP address of the KMIP server.
* The valid certificates issued by the key management appliance.
* Use the local keyfile. Use the keyfile only development and testing purposes since the keys are stored unencrypted.
## Procedure
@ -34,7 +48,7 @@ Install `pg_tde` using one of available installation methods:
=== "Build from source"
To build `pg_tde` from source code, do the following
To build `pg_tde` from source code, do the following:
1. On Ubuntu/Debian: Install the following dependencies required for the build:
@ -64,11 +78,11 @@ Install `pg_tde` using one of available installation methods:
!!! note
The steps below are for the `pg_tde` community version.
The steps below are for the PostgreSQL Community version of `pg_tde`. It provides the `tde_heap_basic` access method for data encryption.
To run `pg_tde` version for Percona Server for PostgreSQL, [use the Percona Distribution for PostgreSQL Docker image :octicons-link-external-16:](https://docs.percona.com/postgresql/17/docker.html).
To run the `pg_tde` version for Percona Server for PostgreSQL, [use the Percona Distribution for PostgreSQL Docker image :octicons-link-external-16:](https://docs.percona.com/postgresql/17/docker.html).
You can find Docker images built from the current main branch on [Docker Hub](https://hub.docker.com/r/perconalab/pg_tde). Images are built on top of [postgres:16](https://hub.docker.com/_/postgres) official image.
You can find Docker images on [Docker Hub](https://hub.docker.com/r/perconalab/pg_tde). Images are built on top of [postgres:16](https://hub.docker.com/_/postgres) official image.
To run `pg_tde` in Docker, use the following command:
@ -76,9 +90,11 @@ Install `pg_tde` using one of available installation methods:
docker run --name pg-tde -e POSTGRES_PASSWORD=mysecretpassword -d perconalab/pg_tde
```
It builds and adds `pg_tde` extension to PostgreSQL 16. The `postgresql.conf` contains the required modifications. The `pg_tde` extension is added to `template1` so that all new databases automatically have the `pg_tde` extension loaded.
It builds and adds the `pg_tde` extension to PostgreSQL 16. The `postgresql.conf` contains the required modifications. The `pg_tde` extension is added to `template1` so that all new databases automatically have the `pg_tde` extension loaded.
Keys are not created automatically. You must configure a key provider and a principal key for each database where you wish to use encrypted tables.
Keys are not created automatically. You must configure a key provider and a principal key for each database where you wish to use encrypted tables. See the instructions in the [Setup](setup.md) section, starting with the 4th point, as the first 3 steps are already completed in the Docker image.
Connect to the container and establish the `psql` session there. Then, see the instructions in the [Setup](setup.md) section, starting with the 4th point, as the first 3 steps are already completed in the Docker image.
See [Docker Docs](https://hub.docker.com/_/postgres) on usage.

@ -64,8 +64,6 @@ Load the `pg_tde` at the start time. The extension requires additional shared me
<i warning>:material-information: Warning:</i> This example is for testing purposes only:
The Vault server setup is out of scope of this document.
```
SELECT pg_tde_add_key_provider_kmip('kmip','127.0.0.1', 5696, '/tmp/server_certificate.pem', '/tmp/client_key_jane_doe.pem');
```
@ -88,7 +86,7 @@ Load the `pg_tde` at the start time. The extension requires additional shared me
<i warning>:material-information: Warning:</i> This example is for testing purposes only:
```
SELECT pg_tde_add_key_provider_file_vault_v2('my-vault','https://vault.example.com','secret/data','hvs.zPuyktykA...example...ewUEnIRVaKoBzs2', NULL);
SELECT pg_tde_add_key_provider_file_vault_v2('my-vault','http://vault.vault.svc.cluster.local:8200,'secret/data','hvs.zPuyktykA...example...ewUEnIRVaKoBzs2', NULL);
```
=== "With a keyring file"
@ -124,7 +122,7 @@ Load the `pg_tde` at the start time. The extension requires additional shared me
<i info>:material-information: Info:</i> The key provider configuration is stored in the database catalog in an unencrypted table. See [how to use external reference to parameters](external-parameters.md) to add an extra security layer to your setup.
## WAL encryption configuration
## WAL encryption configuration (tech preview)
After you [enabled `pg_tde`](#enable-extension) and started the Percona Server for PostgreSQL, a principal key and a keyring for WAL are created. Now you need to instruct `pg_tde ` to encrypt WAL files by configuring WAL encryption.

@ -4,6 +4,8 @@ Enabling `pg_tde` extension for a database creates the table access method `tde_
Here's how to do it:
## Encrypt data in a new table
1. Create a table in the database for which you have [enabled `pg_tde`](setup.md) using the `tde_heap` access method as follows:
```
@ -41,11 +43,21 @@ Here's how to do it:
SELECT pg_tde_rotate_principal_key('new-principal-key', 'new-provider'); -- changeprovider
```
4. You can encrypt an existing table. It requires rewriting the table, so for large tables, it might take a considerable amount of time.
## Encrypt existing table
```
ALTER TABLE table_name SET access method tde_heap;
```
You can encrypt an existing table. It requires rewriting the table, so for large tables, it might take a considerable amount of time.
Run the following command:
```
ALTER TABLE table_name SET access method tde_heap;
```
Note that the `ALTER TABLE SET` command drops hint bits and this may affect the performance. Running a plain `SELECT, count(*)`, or `VACUUM` commands on the entire table will check every tuple for visibility and set its hint bits. Therefore, after executing the ALTER command, run a simple "count(*)" on your tables:
```
SELECT COUNT(*) FROM table_name;
```
!!! hint

@ -3,7 +3,7 @@
INHERIT: mkdocs.yml
copyright: Percona LLC, &#169; 2024
copyright: Percona LLC, &#169; 2025
extra_css:
- https://unicons.iconscout.com/release/v3.0.3/css/line.css

@ -4,7 +4,7 @@ site_name: pg_tde documentation
site_description: Documentation
site_author: Percona LLC
copyright: >
<a href="https://www.percona.com/about">Percona LLC</a> and/or its affiliates © 2023 — <a href="#__consent">Cookie Consent</a>
<a href="https://www.percona.com/about">Percona LLC</a> and/or its affiliates © 2025 — <a href="#__consent">Cookie Consent</a>
repo_name: percona/pg_tde
@ -92,8 +92,8 @@ markdown_extensions:
linenums: false
- pymdownx.snippets:
base_path: ["snippets"]
auto_append:
- services-banner.md
# auto_append:
# - services-banner.md
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg

@ -1,13 +0,0 @@
<div data-banner markdown><svg style="display:block;margin:-1em 0 0.75em" width="78" height="69" viewBox="0 0 78 69" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M56.7281 30.7666C62.6528 26.8938 64.5914 18.9942 61.0059 12.7854C59.2094 9.67113 56.3053 7.44082 52.8311 6.50951C49.6122 5.64535 46.2502 5.99872 43.2912 7.49366L39.251 0.5L30.8648 15.0245L11.4811 48.5937H67.021L56.7281 30.7666ZM51.881 10.0674C54.4064 10.7401 56.5079 12.3616 57.8168 14.6194C60.3895 19.0701 59.053 24.7153 54.8808 27.5665L45.1362 10.6905C47.2355 9.68104 49.6034 9.46087 51.881 10.0674ZM39.251 7.87125L60.6339 44.907H48.1228L32.9927 18.7102L39.2499 7.87235L39.251 7.87125ZM17.8682 44.907L30.8637 22.4035L43.8592 44.907H17.8682Z" fill="url(#paint0_linear_2899_1968)"/><path style="fill:var(--md-typeset-color)" d="M4.981 64.943H3.157V68.207H.756V57.323H5.217C7.822 57.323 9.397 58.861 9.397 61.086V61.116C9.397 63.635 7.433 64.94 4.984 64.94L4.981 64.943V64.943ZM6.961 61.134C6.961 60.061 6.213 59.485 5.011 59.485H3.154V62.812H5.056C6.258 62.812 6.958 62.096 6.958 61.163V61.134H6.961ZM10.738 68.208V57.323H18.973V59.455H13.124V61.664H18.27V63.796H13.124V66.082H19.051V68.214H10.738V68.208 68.208ZM27.557 68.208 25.218 64.726H23.332V68.208H20.931V57.323H25.921C28.496 57.323 30.039 58.677 30.039 60.915V60.945C30.039 62.702 29.088 63.807 27.7 64.32L30.367 68.207H27.556L27.557 68.208ZM27.605 61.041C27.605 60.016 26.887 59.485 25.719 59.485H23.333V62.61H25.767C26.936 62.61 27.605 61.987 27.605 61.071V61.042 61.041ZM36.922 68.499C33.668 68.499 31.249 65.994 31.249 62.825V62.795C31.249 59.659 33.619 57.091 37.019 57.091 39.105 57.091 40.356 57.783 41.383 58.792L39.834 60.571C38.98 59.798 38.113 59.327 37.004 59.327 35.141 59.327 33.795 60.871 33.795 62.762V62.793C33.795 64.684 35.107 66.257 37.004 66.257 38.268 66.257 39.043 65.753 39.913 64.964L41.462 66.524C40.322 67.738 39.059 68.493 36.925 68.493L36.922 68.499ZM47.885 68.499C44.47 68.499 42.021 65.962 42.021 62.825V62.795C42.021 59.659 44.503 57.091 47.915 57.091 51.327 57.091 53.779 59.628 53.779 62.765V62.795C53.779 65.931 51.297 68.499 47.885 68.499ZM51.237 62.795C51.237 60.904 49.846 59.331 47.885 59.331 45.925 59.331 44.567 60.874 44.567 62.766V62.796C44.567 64.688 45.959 66.261 47.919 66.261 49.879 66.261 51.237 64.717 51.237 62.826V62.795 62.795ZM67.001 68.217 72.374 57.091 77.746 68.218H75.052L72.374 62.681 69.705 68.218H67.001V68.217ZM66.007 57.327V68.5L57.813 61.884V68.199H55.264V57.091L63.458 63.681V57.327H66.007Z"/><defs><linearGradient id="paint0_linear_2899_1968" x1="18.1513" y1="44.7152" x2="61.4356" y2="20.9786" gradientUnits="userSpaceOnUse"><stop stop-color="#FC3519"/><stop offset="1" stop-color="#F0D136"/></linearGradient></defs></svg>
## Get expert help { .title }
If you need assistance, visit the community forum for comprehensive and free database knowledge, or contact our Percona Database Experts for professional support and services.
<div class="actions" markdown>
[:material-forum-outline: Community Forum](https://forums.percona.com/c/postgresql/pg-tde-transparent-data-encryption-tde/82) [:percona-logo: Get a Percona Expert](https://www.percona.com/about/contact)
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=b95a2b04-c5c7-47f9-bb4e-b7fc13c3ab0d" />
</div></div>
Loading…
Cancel
Save