Skip to content

Transferring Encryption Keys Across Environments & Sites#

This guide covers how to transfer Easy Encryption keys when migrating sites, promoting databases between environments, or sharing encrypted configuration across independent Drupal installations.


1. Architectural Foundations: What Travels and What Stays#

When Drupal uses Easy Encryption to protect a secret (via the easy_encrypted key provider), two distinct parts exist:

┌────────────────────────────────────────┐       ┌────────────────────────────────────────┐
│            Drupal Configuration        │       │          Out-of-Band Secrets           │
│             (Safe for Git/Sync)        │       │             (Must Not Leak)            │
├────────────────────────────────────────┤       ├────────────────────────────────────────┤
│ 1. Application Key entity              │       │                                        │
│    - Contains Libsodium ciphertext     │       │                                        │
│    - References encryption_key_id      │       │                                        │
│                                        │       │                                        │
│ 2. Public Key entity                   │       │                                        │
│    - Contains public key (hex)         │       │                                        │
│                                        │       │                                        │
│ 3. Private Key entity (Metadata stub)  │       │ 4. Private Key cryptographic secret    │
│    - References storage provider       │  ───> │    - In .easy_encryption/<id>.php (FS) │
│      (e.g., file or state)             │       │    - OR Drupal State (fallback)        │
│                                        │       │    - OR Server Environment Variable    │
└────────────────────────────────────────┘       └────────────────────────────────────────┘

Why copying only the database or config is not enough

Transferring Drupal configuration (config/sync) carries the encrypted application keys and the public key, but not the private key secret. Conversely, copying only the .easy_encryption/ folder is not enough if the target site does not have the corresponding Drupal Key configuration entities. Both parts must be aligned for the target environment to successfully decrypt secrets.


2. Choosing the Right Transfer Strategy#

Depending on your hosting setup and workflow, choose one of the three strategies below:

Method Best For Requires Admin Module? Risk Profile
Method 1: Key Transfer Package (UI) Ad-hoc site copies, cross-site migration, non-DevOps administrators Yes (easy_encryption_admin) Lowest: Structured, validated import package with checksums.
Method 2: Filesystem Copy (.easy_encryption/) Infrastructure clones, DevOps CI/CD pipelines, container volumes No Low to Moderate: Requires secure out-of-band file transfer and strict permission preservation.
Method 3: State-to-Filesystem Migration Recovery after hosting platform changes or when file storage was previously blocked No (Drush) or Yes (Admin UI) Low: Migrates temporary database state keys to permanent filesystem storage.

3. Method 1: Portable Key Transfer (UI / Admin Module)#

The Easy Encryption Admin submodule (easy_encryption_admin) provides a secure, portable key transfer mechanism designed specifically for cross-site and cross-environment key movement.

How It Works#

The Key Transfer service packages the complete encryption key definition (public key, key metadata, and private key secret) into an armored, structured package format.

Step-by-Step Workflow#

Step 1: Export on the Source Site#

  1. Ensure the optional easy_encryption_admin module is enabled on both source and target sites:

    bash drush pm:enable easy_encryption_admin

  2. Navigate to Configuration > System > Easy Encryption keys (/admin/config/system/easy-encryption/keys).

  3. Locate the encryption key ID you wish to transfer and click Export.
  4. Copy the generated export package text or download the package.

Treat Export Packages as Highly Sensitive

The exported package contains the decryption private key. Never transmit it via unencrypted channels (such as Slack or plaintext email). Use secure password managers, encrypted pastebins, or temporary SSH tunnels.

Step 2: Import on the Target Site#

  1. On the destination Drupal site, navigate to Configuration > System > Easy Encryption keys > Import key (/admin/config/system/easy-encryption/keys/import).
  2. Paste the package text into the Key package field.
  3. (Optional) Check Activate this key after import if this key should immediately become the default key for new encryptions.
  4. Click Import key.
  5. The target site verifies the key pair cryptographically, provisions the corresponding Key configuration entities, and places the private key into secure storage.

Step 3: Deploy Configuration#

Now deploy your application configuration containing the encrypted Key entities (e.g., via drush config:import). The target site can now decrypt all values encrypted with that key ID.


4. Method 2: Filesystem-Based Transfer (.easy_encryption/)#

If your private keys are stored in the default filesystem directory (.easy_encryption/ located alongside or outside webroot), you can transfer keys via server-level file synchronization.

Step 1: Synchronize Configuration Entities#

Ensure the Key configuration entities exist on the destination environment:

drush config:export  # On source
# Commit & push to Git, or copy config/sync
drush config:import  # On destination

Step 2: Securely Copy .easy_encryption/ Files#

Using SSH/SCP or rsync over an encrypted channel:

# Example copying directly between servers
rsync -avz -e ssh /var/www/.easy_encryption/ user@target-server:/var/www/.easy_encryption/

Step 3: Enforce Correct Permissions#

The private key files must be readable and writable by the web server user (e.g. www-data or nginx), and restricted from all other users:

chown -R www-data:www-data /var/www/.easy_encryption
chmod 700 /var/www/.easy_encryption
chmod 600 /var/www/.easy_encryption/*.php

Never Commit to Git

Ensure .easy_encryption is listed in your project .gitignore. If accidentally committed, rotate the encryption key immediately using drush easy-encryption:rotate.


5. Method 3: State-Based Storage & Migration#

When write access to .easy_encryption/ fails during module installation (e.g. due to read-only container filesystems or restricted shared hosting), Easy Encryption automatically falls back to storing the private key in Drupal's database State system.

Inspecting State Storage#

Visit Reports > Status report (/admin/reports/status). If the private key is in State, a warning is displayed advising migration to filesystem storage for enhanced security.

Moving Between Environments with State Keys#

If your site relies on State fallback:

  1. Moving the entire database (e.g., database dump and restore) will automatically move the private key.
  2. Once the target environment has write access to the filesystem, you should migrate the private key out of the database into the filesystem.

Migrating State Keys to Filesystem#

You can perform the migration using Drush or the Admin UI:

Via Drush:#

# Check if migration is needed:
drush easy-encryption:migrate-private-key --check

# Execute the migration:
drush easy-encryption:migrate-private-key

Via Admin UI:#

  1. Navigate to Configuration > System > Easy Encryption keys.
  2. Click Migrate private key to filesystem (/admin/config/system/easy-encryption/migrate-private-key).
  3. Confirm the migration. The key material is written to .easy_encryption/ and purged from Drupal State.

6. Troubleshooting & Operational Footguns#

Issue Cause Fix
Status report: "Active Sodium key pair cannot decrypt" The target site imported configuration with a key ID, but the private key file or env var is missing on disk. Re-import the key using the Key Transfer UI or verify that .easy_encryption/<id>.php exists with correct permissions.
Import package rejected with validation error The package was corrupted during copy-paste (truncated whitespace or characters). Re-export the package from the source site and copy directly via clipboard or raw file download.
FilesystemPermissionException during migration Web server process does not have write permissions to .easy_encryption or the configured private_key_directory. Check directory ownership: chown www-data:www-data <dir> and chmod 700 <dir>.
Keys decrypt on Staging but fail on Production Production and Staging use different encryption key IDs, or configuration was imported without the matching key pair. Use drush easy-encryption:rotate --reencrypt before exporting configuration, or ensure both environments share the target encryption key pair.