← Files LaunchDarklyARCHIVED FILE

skills/projects/references/env-config.md

9.66 KB · Oct 3, 2026 · 06:25 UTC

↓ Download file

# Environment Configuration

Patterns for saving SDK keys to your codebase's configuration system.

## Overview

After creating a project, you need to save the SDK keys so your application can use them. The approach depends on your existing configuration pattern.

## Common Patterns

### 1. .env Files

Most common pattern for local development and simple deployments.

#### Python
```python
def save_sdk_key_to_env(
    project_key: str,
    environment: str = "production",
    env_file: str = ".env",
    var_name: str = "LAUNCHDARKLY_SDK_KEY"
):
    """Save SDK key to .env file."""
    # Get the SDK key
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    if not sdk_key:
        raise ValueError(f"Could not get SDK key for {project_key}/{environment}")
    
    # Read existing .env content
    env_content = {}
    if os.path.exists(env_file):
        with open(env_file, "r") as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith("#") and "=" in line:
                    key, value = line.split("=", 1)
                    env_content[key] = value
    
    # Update or add the SDK key
    env_content[var_name] = sdk_key
    
    # Write back to .env
    with open(env_file, "w") as f:
        for key, value in env_content.items():
            f.write(f"{key}={value}\n")
    
    print(f"✓ Saved {var_name} to {env_file}")
```

#### Node.js/TypeScript
```typescript
import * as fs from 'fs';
import * as path from 'path';

async function saveSdkKeyToEnv(
  projectKey: string,
  environment: string = 'production',
  envFile: string = '.env',
  varName: string = 'LAUNCHDARKLY_SDK_KEY'
): Promise<void> {
  const pm = new ProjectManager();
  const sdkKey = await pm.getSdkKey(projectKey, environment);
  
  if (!sdkKey) {
    throw new Error(`Could not get SDK key for ${projectKey}/${environment}`);
  }
  
  // Read existing .env content
  const envContent: Record<string, string> = {};
  if (fs.existsSync(envFile)) {
    const content = fs.readFileSync(envFile, 'utf-8');
    content.split('\n').forEach((line) => {
      const trimmed = line.trim();
      if (trimmed && !trimmed.startsWith('#') && trimmed.includes('=')) {
        const [key, ...valueParts] = trimmed.split('=');
        envContent[key] = valueParts.join('=');
      }
    });
  }
  
  // Update or add the SDK key
  envContent[varName] = sdkKey;
  
  // Write back to .env
  const lines = Object.entries(envContent).map(([key, value]) => `${key}=${value}`);
  fs.writeFileSync(envFile, lines.join('\n') + '\n');
  
  console.log(`✓ Saved ${varName} to ${envFile}`);
}
```

#### Usage
```bash
# Python
python -c "from launchdarkly.projects import save_sdk_key_to_env; save_sdk_key_to_env('my-project')"

# Node.js
node -e "require('./src/launchdarkly/env-config').saveSdkKeyToEnv('my-project')"
```

### 2. Multiple Environments

Save keys for multiple environments:

```python
# Save both production and test keys
save_sdk_key_to_env("my-project", "production", var_name="LD_SDK_KEY_PROD")
save_sdk_key_to_env("my-project", "test", var_name="LD_SDK_KEY_TEST")
```

**.env result:**
```bash
LD_SDK_KEY_PROD=sdk-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
LD_SDK_KEY_TEST=sdk-yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
```

### 3. Secrets Manager Integration

For cloud deployments, integrate with secrets managers.

#### AWS Secrets Manager
```python
import boto3
import json

def save_to_aws_secrets(project_key: str, environment: str, secret_name: str):
    """Save SDK key to AWS Secrets Manager."""
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    client = boto3.client('secretsmanager')
    
    try:
        # Get existing secret
        response = client.get_secret_value(SecretId=secret_name)
        secrets = json.loads(response['SecretString'])
    except client.exceptions.ResourceNotFoundException:
        secrets = {}
    
    # Update with new key
    secrets['LAUNCHDARKLY_SDK_KEY'] = sdk_key
    
    # Save back
    client.put_secret_value(
        SecretId=secret_name,
        SecretString=json.dumps(secrets)
    )
    
    print(f"✓ Saved SDK key to AWS Secrets Manager: {secret_name}")

# Usage
save_to_aws_secrets("my-project", "production", "myapp/production")
```

#### GCP Secret Manager
```python
from google.cloud import secretmanager

def save_to_gcp_secrets(project_key: str, environment: str, secret_id: str, gcp_project: str):
    """Save SDK key to GCP Secret Manager."""
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    client = secretmanager.SecretManagerServiceClient()
    parent = f"projects/{gcp_project}/secrets/{secret_id}"
    
    # Add new version
    response = client.add_secret_version(
        request={
            "parent": parent,
            "payload": {"data": sdk_key.encode("UTF-8")},
        }
    )
    
    print(f"✓ Saved SDK key to GCP Secret Manager: {response.name}")
```

#### Azure Key Vault
```python
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential

def save_to_azure_keyvault(project_key: str, environment: str, vault_url: str, secret_name: str):
    """Save SDK key to Azure Key Vault."""
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    credential = DefaultAzureCredential()
    client = SecretClient(vault_url=vault_url, credential=credential)
    
    client.set_secret(secret_name, sdk_key)
    
    print(f"✓ Saved SDK key to Azure Key Vault: {secret_name}")
```

### 4. Kubernetes Secrets

For Kubernetes deployments:

```python
import base64
import yaml

def create_k8s_secret(project_key: str, environment: str, namespace: str = "default"):
    """Generate Kubernetes secret manifest."""
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    # Encode SDK key
    encoded_key = base64.b64encode(sdk_key.encode()).decode()
    
    secret = {
        "apiVersion": "v1",
        "kind": "Secret",
        "metadata": {
            "name": "launchdarkly-sdk-key",
            "namespace": namespace
        },
        "type": "Opaque",
        "data": {
            "sdk-key": encoded_key
        }
    }
    
    # Write to file
    with open("k8s-secret.yaml", "w") as f:
        yaml.dump(secret, f)
    
    print("✓ Created k8s-secret.yaml")
    print("Apply with: kubectl apply -f k8s-secret.yaml")
```

### 5. Configuration Files

For applications using config files (YAML, JSON, TOML):

#### YAML Config
```python
import yaml

def save_to_yaml_config(project_key: str, environment: str, config_file: str = "config.yaml"):
    """Save SDK key to YAML config file."""
    pm = ProjectManager()
    sdk_key = pm.get_sdk_key(project_key, environment)
    
    # Read existing config
    config = {}
    if os.path.exists(config_file):
        with open(config_file, "r") as f:
            config = yaml.safe_load(f) or {}
    
    # Update LaunchDarkly section
    if "launchdarkly" not in config:
        config["launchdarkly"] = {}
    
    config["launchdarkly"]["sdk_key"] = sdk_key
    config["launchdarkly"]["project_key"] = project_key
    config["launchdarkly"]["environment"] = environment
    
    # Write back
    with open(config_file, "w") as f:
        yaml.dump(config, f, default_flow_style=False)
    
    print(f"✓ Saved SDK key to {config_file}")
```

#### JSON Config
```typescript
import * as fs from 'fs';

async function saveToJsonConfig(
  projectKey: string,
  environment: string,
  configFile: string = 'config.json'
): Promise<void> {
  const pm = new ProjectManager();
  const sdkKey = await pm.getSdkKey(projectKey, environment);
  
  // Read existing config
  let config: any = {};
  if (fs.existsSync(configFile)) {
    config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
  }
  
  // Update LaunchDarkly section
  config.launchdarkly = {
    sdkKey,
    projectKey,
    environment,
  };
  
  // Write back
  fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
  
  console.log(`✓ Saved SDK key to ${configFile}`);
}
```

## Security Best Practices

### 1. Never Commit SDK Keys
Add to `.gitignore`:
```gitignore
# Environment files
.env
.env.local
.env.production
.env.test

# Config files with secrets
config/secrets.yaml
config/production.json
```

### 2. Use Different Keys Per Environment
```python
# Development
save_sdk_key_to_env("my-project", "test", ".env.development")

# Production (deploy separately)
save_sdk_key_to_env("my-project", "production", ".env.production")
```

### 3. Rotate Keys Regularly
```python
def rotate_sdk_key(project_key: str, environment: str):
    """
    Note: This requires creating a new SDK key via API.
    The LaunchDarkly API doesn't support key rotation directly.
    You would need to create a new environment or reset the key in the UI.
    """
    print("⚠️  SDK key rotation must be done via LaunchDarkly UI")
    print(f"   Go to: Project Settings → Environments → {environment} → Reset SDK Key")
```

### 4. Least Privilege Access
- API tokens for project creation: `projects:write`
- Application SDK keys: read-only by default
- Separate keys for test vs production

## Verification

After saving SDK keys, verify they work:

```python
def verify_sdk_key(sdk_key: str):
    """Verify SDK key works by testing connection."""
    import ldclient
    from ldclient.config import Config
    
    config = Config(sdk_key)
    client = ldclient.get()
    
    if client.is_initialized():
        print("✓ SDK key is valid and working")
        return True
    else:
        print("✗ SDK key failed to initialize")
        return False
```

## Next Steps

- [Integrate SDK in your application](../sdk/SKILL.md)
- [Set up project cloning](project-cloning.md)
- [Build automation scripts](iac-automation.md)

SHA-256: 9b93ae42f23183ccc2915ff099c5f224dc70c57fee8b626d837e63ec571c98c4