Database Schema for Sensitive Data in TeslaMate: Private Schemas and Cloak Encryption
TeslaMate stores Tesla API tokens in a private PostgreSQL schema with AES-GCM encryption using the Cloak library, ensuring sensitive credentials are never persisted in plain text or exposed in application logs.
TeslaMate, the open-source Tesla data logger, handles sensitive authentication credentials through a carefully architected database design. Understanding the database schema for sensitive data in TeslaMate reveals how the application protects your Tesla API tokens using PostgreSQL private schemas and transparent encryption. This analysis examines the actual source code in the teslamate-org/teslamate repository to explain the security implementation.
Private Schema Architecture for Credential Isolation
TeslaMate isolates sensitive authentication data in a dedicated PostgreSQL schema rather than the default public schema. This architectural decision creates a security boundary that separates credential storage from operational vehicle data.
In lib/teslamate/auth/tokens.ex, the Ecto schema explicitly declares the private prefix:
@schema_prefix :private
schema "tokens" do
field :refresh, Encrypted.Binary, redact: true
field :access, Encrypted.Binary, redact: true
timestamps()
end
The @schema_prefix :private directive instructs Ecto to create and query the tokens table within the PostgreSQL private schema. This isolation prevents accidental exposure through broad queries against the public schema and supports granular access control at the database level.
The Tokens Table Schema Definition
Encrypted Field Types
The tokens table stores exactly two sensitive values: the Tesla API refresh token and access token. Both fields use Encrypted.Binary, a custom Ecto type provided by the Cloak library that handles transparent encryption and decryption.
Key characteristics of this schema:
- Transparent encryption: Data is automatically encrypted before insertion and decrypted when fetched
- AES-GCM algorithm: The Cloak vault configured in
lib/teslamate/vault.exuses AES-256-GCM authenticated encryption - Binary storage: Underlying PostgreSQL columns use the
byteatype to store ciphertext
Redaction Protection
The redact: true option on both fields ensures that token values are omitted from all Ecto logging and inspection output. Even if debug logging is enabled, the actual token strings appear as **redacted** in application logs, preventing credential leakage through log files.
Cloak Vault Configuration
The encryption layer is centralized in lib/teslamate/vault.ex, which configures the Cloak vault for the application. The vault generates a cryptographically secure random key when the ENCRYPTION_KEY environment variable is not provided during initial setup.
For Docker deployments, the vault persists the generated key to a temporary file (and optionally an import folder) to survive container restarts. This design ensures that:
- Fresh installations without explicit configuration still receive encryption
- The encryption key remains consistent across application restarts
- Users can optionally specify their own
ENCRYPTION_KEYfor key rotation scenarios
Database Migration Strategy
The migration file priv/repo/migrations/20220123131732_encrypt_api_tokens.exs handles the transition from plain-text to encrypted storage. This migration implements a zero-downtime strategy for existing deployments:
- Creates new
encrypted_refreshandencrypted_accesscolumns as:binary(PostgreSQLbytea) - Migrates existing plain-text token values to the encrypted representation using the Cloak vault
- Drops the original plain-text columns
- Renames the encrypted columns to
refreshandaccessto maintain the public API
The migration also includes helper modules for key generation and vault configuration, ensuring that the encryption setup completes successfully even on fresh installations.
Working with Encrypted Tokens
Creating Token Records
When the Tesla authentication flow completes successfully, the application creates a token record like this:
%TeslaMate.Auth.Tokens{}
|> TeslaMate.Auth.Tokens.changeset(%{
access: access_token, # plain-text, encrypted by Ecto/Cloak
refresh: refresh_token # plain-text, encrypted by Ecto/Cloak
})
|> Repo.insert!()
The plain-text values are automatically encrypted by the Encrypted.Binary type before the SQL INSERT executes, ensuring the database never stores unencrypted credentials.
Reading Token Data
When fetching tokens for API requests, the decryption happens transparently:
tokens = Repo.get_by(TeslaMate.Auth.Tokens, id: 1)
# tokens.access and tokens.refresh are plain strings,
# automatically decrypted by Cloak on load
The application code works with plain strings while the database layer handles cryptographic operations, maintaining clean separation between business logic and security implementation.
Summary
- Private schema isolation: The
tokenstable resides in the PostgreSQLprivateschema, separate from vehicle telemetry data - AES-GCM encryption: TeslaMate uses the Cloak library with AES-256-GCM authenticated encryption for all token storage
- Automatic redaction: The
redact: trueschema option prevents token values from appearing in application logs or debug output - Migration safety: The
20220123131732_encrypt_api_tokens.exsmigration safely converts existing plain-text tokens to encrypted storage without data loss - Vault key management: The
lib/teslamate/vault.exconfiguration handles key generation, storage, and rotation support through environment variables
Frequently Asked Questions
Where are Tesla API tokens stored in TeslaMate?
Tesla API tokens are stored in the tokens table within the private PostgreSQL schema, defined in lib/teslamate/auth/tokens.ex. This table uses the @schema_prefix :private directive to ensure physical and logical separation from other application data, and all token values are encrypted using the Cloak library before persistence.
What encryption algorithm does TeslaMate use for sensitive data?
TeslaMate uses AES-256-GCM (Galois/Counter Mode) authenticated encryption provided by the Cloak library. The encryption keys are managed through the vault configuration in lib/teslamate/vault.ex, which supports both environment variable-based keys and automatically generated keys for Docker deployments.
How does TeslaMate prevent API tokens from appearing in logs?
The Ecto schema in lib/teslamate/auth/tokens.ex marks both token fields with redact: true. This Ecto feature ensures that whenever the struct is inspected or logged, the sensitive values display as **redacted** rather than the actual token strings, preventing accidental credential exposure through log files or error reports.
Can I rotate the encryption key for existing TeslaMate tokens?
Yes, you can rotate encryption keys by setting a new ENCRYPTION_KEY environment variable and running a re-encryption migration. The process involves configuring the new key in lib/teslamate/vault.ex, fetching all existing token records (which decrypts them with the old key), and re-inserting them to encrypt with the new key. Always back up your database before performing key rotation operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →