Skip to content

Credential Management

How Dango stores and manages API keys and credentials.


Overview

Dango needs credentials to connect to data sources:

  • API keys (Stripe, etc.)
  • OAuth tokens (Google, Facebook)
  • Database passwords
  • Custom source credentials

Storage Mechanisms

secrets.toml (Primary Storage)

Dango stores all credentials in .dlt/secrets.toml:

# .dlt/secrets.toml
[sources.stripe]
api_key = "sk_live_xxx"

[sources.my_database]
password = "database_password"

Never Commit secrets.toml

This file contains plaintext credentials. Always add to .gitignore.


Credential Types

API Keys

For services like Stripe:

# Add via wizard (stored in secrets.toml)
dango source add  # select Stripe from wizard
# Enter API key when prompted

# Or configure manually in secrets.toml
# .dlt/secrets.toml
[sources.stripe]
stripe_secret_key = "sk_live_xxx"

OAuth Tokens

For Google, Facebook, etc.:

# Authenticate via browser
dango oauth google_sheets

OAuth tokens are stored in .dlt/secrets.toml under the source's credentials section:

# .dlt/secrets.toml (auto-generated by dango oauth setup)
[sources.google_sheets.credentials]
client_id = "xxx.apps.googleusercontent.com"
client_secret = "xxx"
refresh_token = "1//xxx"

Database Credentials

For database connections:

# .dlt/secrets.toml
[sources.my_postgres]
host = "localhost"
port = 5432
database = "mydb"
username = "user"
password = "password"

Environment Variables

Using Environment Variables

Reference environment variables in secrets.toml:

# .dlt/secrets.toml
[sources.stripe]
stripe_secret_key = "${STRIPE_API_KEY}"

Set the variable:

export STRIPE_API_KEY="sk_live_xxx"
$env:STRIPE_API_KEY = "sk_live_xxx"

.env Files

For development, use a .env file:

# .env (DO NOT COMMIT)
STRIPE_API_KEY=sk_live_xxx
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com

Load with:

source .env  # Linux/macOS
dango sync

Or use a tool like direnv for automatic loading.


Credential Lifecycle

Adding Credentials

# Via wizard (recommended)
dango source add  # select source type from menu

# Manually edit secrets.toml
nano .dlt/secrets.toml

Viewing Credentials

Credentials are masked in Dango output:

dango config show
# API Key: sk_live_***************

To verify OAuth credentials exist:

dango oauth status

Updating Credentials

# Re-run auth for OAuth
dango oauth google_sheets

# Edit secrets.toml for API keys
nano .dlt/secrets.toml

Removing Credentials

# Remove OAuth token
dango oauth remove google_sheets

# Remove from secrets.toml manually
nano .dlt/secrets.toml

Cloud Credentials

For cloud deployments, manage environment variables and secrets on the remote server:

# Set a credential on the remote server
dango remote env set STRIPE_API_KEY=sk_live_xxx

# List all remote environment variables
dango remote env list

# Remove a remote credential
dango remote env delete STRIPE_API_KEY

Remote credentials are stored in the server's .env file and are not synced during dango remote push — they must be managed separately.


Credential Rotation

When to Rotate

Rotate credentials when: - Credential may have been exposed - Employee leaves the team - Regular security policy (e.g., quarterly) - Service provider recommends

Rotation Process

  1. Generate new credential in the service provider's dashboard
  2. Update Dango with new credential
  3. Test with dango sync affected_source
  4. Revoke old credential in the service provider
# Update credential
nano .dlt/secrets.toml

# Test
dango sync stripe_payments

# If successful, revoke old key in Stripe dashboard

Secrets.toml Structure

Full Example

# .dlt/secrets.toml

# Stripe API
[sources.stripe]
stripe_secret_key = "sk_live_xxx"

# Google OAuth (manual setup)
[sources.google_sheets]
client_id = "xxx.apps.googleusercontent.com"
client_secret = "xxx"

# Database connection
[sources.postgres_db]
host = "localhost"
port = 5432
database = "analytics"
username = "dango_user"
password = "secure_password"

# Custom API
[sources.my_api]
api_key = "xxx"
base_url = "https://api.example.com"

# Using environment variables
[sources.production]
api_key = "${PROD_API_KEY}"

Organizing Secrets

Group by source name (must match sources.yml):

# .dango/sources.yml
sources:
  - name: stripe_payments  # <- This name
    type: stripe
# .dlt/secrets.toml
[sources.stripe_payments]  # <- Must match
stripe_secret_key = "sk_live_xxx"

System Keyring (Optional Encryption)

Dango can optionally use the system keyring to store an encryption key that protects sensitive tokens in secrets.toml:

Platform Backend
macOS Keychain
Linux Secret Service (GNOME Keyring)
Windows Windows Credential Manager

What's in the Keyring

The keyring stores only the encryption key, not your actual credentials. Your OAuth tokens and API keys are stored in secrets.toml, optionally encrypted with the keyring-stored key.

Keyring Troubleshooting

Issue Solution
"No keyring backend" Install keyrings.alt package
Permission denied Check OS keyring permissions
Credential not found Re-authenticate with dango oauth setup <provider>

Security Considerations

Plaintext Risks

secrets.toml stores credentials in plaintext: - Readable by anyone with file access - Visible in backups - Could be accidentally committed

Mitigations: - Proper file permissions: chmod 600 .dlt/secrets.toml - Always use .gitignore - Encrypt backups

Credential Exposure Signs

Watch for: - Unexpected API usage spikes - Unknown IP addresses in service logs - Credentials in git history - Credentials in error logs

If Credentials Are Exposed

  1. Immediately revoke the compromised credential
  2. Generate new credential
  3. Update Dango configuration
  4. Audit for unauthorized access
  5. Review how exposure occurred

Next Steps