> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/alchemy-run/alchemy/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

> Securely manage sensitive values in your Alchemy infrastructure

# Secrets

Alchemy provides built-in secret management to securely handle sensitive values like API keys, passwords, and credentials. Secrets are automatically encrypted when stored in state files, protecting your sensitive data.

## What are Secrets?

Secrets in Alchemy are wrapper objects that:

* **Encrypt values** when persisted to state files
* **Prevent accidental logging** by overriding `toString()`
* **Maintain type safety** through TypeScript
* **Integrate seamlessly** with resource props

<Warning>
  Without using secrets, sensitive values are stored in plain text in state files. Always wrap sensitive data with `alchemy.secret()`.
</Warning>

## Creating Secrets

### From Environment Variables

The recommended approach uses `alchemy.secret.env`:

```typescript theme={null}
import { alchemy } from "alchemy";

const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});

// Best practice: Using alchemy.secret.env
const apiKey = alchemy.secret.env.API_KEY;

// Also works: Direct wrapping
const dbPassword = alchemy.secret(process.env.DB_PASSWORD);
```

<Info>
  `alchemy.secret.env.VAR_NAME` automatically throws an error if the environment variable is not set, providing better error messages than manual checking.
</Info>

### From Literal Values

You can also create secrets from literal values:

```typescript theme={null}
const token = alchemy.secret("my-secret-token");
const password = alchemy.secret("super-secure-password");
```

<Warning>
  Avoid hardcoding secrets in source code. Always use environment variables for production deployments.
</Warning>

## Encryption Password

Secrets require a password for encryption. Set it globally:

```typescript theme={null}
const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});
```

Or via environment variables:

```bash theme={null}
export ALCHEMY_PASSWORD="your-encryption-password"
bun ./alchemy.run.ts
```

<Note>
  The password is used to encrypt/decrypt secrets in state files. Without it, operations involving secrets will fail.
</Note>

## Using Secrets in Resources

Secrets integrate seamlessly with resource properties:

```typescript theme={null}
import { Worker } from "alchemy/cloudflare";
import { alchemy } from "alchemy";

const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});

const worker = await Worker("api", {
  entrypoint: "./src/worker.ts",
  bindings: {
    API_KEY: alchemy.secret.env.API_KEY,
    DATABASE_URL: alchemy.secret.env.DATABASE_URL
  }
});

await app.finalize();
```

## How Secrets Work

### Encryption in State Files

When resources are saved to state:

```json theme={null}
// .alchemy/my-app/dev/worker.json
{
  "props": {
    "bindings": {
      "API_KEY": {
        "@secret": "encrypted-base64-string-here..."
      }
    }
  }
}
```

The actual value is encrypted using AES-256-GCM with your password.

### Runtime Access

Secrets expose their values through the `unencrypted` property:

```typescript theme={null}
const apiKey = alchemy.secret.env.API_KEY;

// Access the actual value
console.log(apiKey.unencrypted); // "actual-api-key-value"

// The secret itself is safe to log
console.log(apiKey); // "Secret(API_KEY)"
console.log(apiKey.toString()); // "Secret(API_KEY)"
```

<Tip>
  Secrets automatically prevent accidental exposure by overriding `toString()` and `util.inspect.custom`.
</Tip>

## Secret Utilities

### Wrapping Values

Ensure a value is a secret:

```typescript theme={null}
import { Secret } from "alchemy";

function processApiKey(key: string | Secret<string>) {
  // Wrap if needed
  const secret = Secret.wrap(key);
  // Now guaranteed to be a Secret
}
```

### Unwrapping Values

Extract the raw value:

```typescript theme={null}
import { Secret } from "alchemy";

function callApi(key: string | Secret<string>) {
  // Unwrap to get the actual value
  const actualKey = Secret.unwrap(key);
  
  // Use in API call
  return fetch("https://api.example.com", {
    headers: { "Authorization": `Bearer ${actualKey}` }
  });
}
```

### Type Guards

Check if a value is a secret:

```typescript theme={null}
import { isSecret } from "alchemy";

function handleValue(value: unknown) {
  if (isSecret(value)) {
    console.log("This is a secret:", value.name);
    console.log("Encrypted value:", value.unencrypted);
  }
}
```

## Implementing Resources with Secrets

When creating custom resources that accept secrets:

```typescript theme={null}
import { Resource, Secret, type Context } from "alchemy";

export interface MyResourceProps {
  /**
   * API key for authentication
   * Use alchemy.secret() to securely store this value
   */
  apiKey: string | Secret<string>;
}

export interface MyResource {
  id: string;
  /**
   * API key (always wrapped as Secret in output)
   */
  apiKey: Secret<string>;
}

export const MyResource = Resource(
  "provider::MyResource",
  async function (
    this: Context<MyResource>,
    id: string,
    props: MyResourceProps
  ): Promise<MyResource> {
    // Unwrap for API calls
    const actualKey = Secret.unwrap(props.apiKey);
    
    await fetch("https://api.provider.com/resources", {
      headers: {
        "Authorization": `Bearer ${actualKey}`
      },
      method: "POST",
      body: JSON.stringify({ name: id })
    });
    
    // Wrap for output (ensures it's always a Secret)
    return {
      id,
      apiKey: Secret.wrap(props.apiKey)
    };
  }
);
```

<Info>
  Always unwrap secrets when making API calls, and wrap them in the resource output.
</Info>

## Scoped Passwords

Different scopes can use different encryption passwords:

```typescript theme={null}
import { alchemy } from "alchemy";

const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});

// Standard secrets use app password
const apiKey = alchemy.secret.env.API_KEY;

await alchemy.run("secure-service", {
  password: process.env.SECURE_SERVICE_PASSWORD
}, async (scope) => {
  // Secrets in this scope use different password
  const serviceKey = alchemy.secret.env.SERVICE_KEY;
  
  const resource = await MyResource("secure", {
    apiKey: serviceKey
  });
});

await app.finalize();
```

<Tip>
  Scoped passwords enable different teams or services to manage their own encryption keys.
</Tip>

## Secret Recovery

If you lose your encryption password:

### Option 1: Erase Secrets

```bash theme={null}
bun ./alchemy.run.ts --erase-secrets --force
```

This treats all secrets as `undefined` and allows you to redeploy with a new password.

<Warning>
  `--erase-secrets` removes encrypted values permanently. You'll need to provide new secret values after erasing.
</Warning>

### Option 2: Manually Update State

Edit state files in `.alchemy/` to remove or update encrypted values.

### Option 3: Destroy and Recreate

```bash theme={null}
bun ./alchemy.run.ts --destroy
# Update password
export ALCHEMY_PASSWORD="new-password"
bun ./alchemy.run.ts
```

## Environment Variable Patterns

### Named Secrets

Create secrets with custom names for better debugging:

```typescript theme={null}
const apiKey = alchemy.secret(process.env.API_KEY, "stripe-api-key");
console.log(apiKey.toString()); // "Secret(stripe-api-key)"
```

### Validation

Validate secrets before use:

```typescript theme={null}
const apiKey = alchemy.secret.env.API_KEY;

if (!apiKey.unencrypted.startsWith("sk_")) {
  throw new Error("Invalid API key format");
}
```

### Conditional Secrets

Use different secrets based on stage:

```typescript theme={null}
const app = await alchemy("my-app");

const apiKey = app.stage === "prod"
  ? alchemy.secret.env.PROD_API_KEY
  : alchemy.secret.env.DEV_API_KEY;
```

## Type Safety

Secrets maintain full TypeScript type safety:

```typescript theme={null}
import { Secret } from "alchemy";

// Typed secret
const config: Secret<{ apiKey: string; endpoint: string }> = alchemy.secret({
  apiKey: process.env.API_KEY!,
  endpoint: "https://api.example.com"
});

// TypeScript knows the shape
const endpoint = config.unencrypted.endpoint;
```

## Security Best Practices

<Steps>
  <Step title="Never hardcode secrets">
    Always use environment variables or external secret managers
  </Step>

  <Step title="Rotate passwords regularly">
    Change encryption passwords periodically
  </Step>

  <Step title="Use strong passwords">
    Encryption password should be long and random (32+ characters)
  </Step>

  <Step title="Separate dev and prod passwords">
    Use different passwords for different stages
  </Step>

  <Step title="Don't commit .env files">
    Add `.env` to `.gitignore`
  </Step>

  <Step title="Use secret managers in CI/CD">
    Store passwords in GitHub Secrets, AWS Secrets Manager, etc.
  </Step>
</Steps>

## Common Patterns

### Database Credentials

```typescript theme={null}
const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});

const database = await PostgresDatabase("db", {
  connectionString: alchemy.secret.env.DATABASE_URL
});
```

### OAuth Tokens

```typescript theme={null}
const githubToken = alchemy.secret.env.GITHUB_TOKEN;

const integration = await GitHubApp("bot", {
  token: githubToken,
  repository: "my-org/my-repo"
});
```

### Multi-Provider Credentials

```typescript theme={null}
const app = await alchemy("my-app", {
  password: process.env.ALCHEMY_PASSWORD
});

const awsKey = alchemy.secret.env.AWS_ACCESS_KEY;
const cloudflareToken = alchemy.secret.env.CLOUDFLARE_API_TOKEN;
```

## Debugging Secrets

Enable secret logging for debugging (use carefully):

```typescript theme={null}
const apiKey = alchemy.secret.env.API_KEY;

if (process.env.DEBUG_SECRETS === "true") {
  console.log("API Key (debug):", apiKey.unencrypted);
} else {
  console.log("API Key:", apiKey); // "Secret(API_KEY)"
}
```

<Warning>
  Never enable secret debugging in production or commit debug logs.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Resources" icon="cube" href="/concepts/resources">
    Learn how to use secrets in resource properties
  </Card>

  <Card title="State Management" icon="database" href="/concepts/state-management">
    Understand how secrets are stored in state
  </Card>

  <Card title="Scopes" icon="folder-tree" href="/concepts/scopes">
    Manage scope-level password configuration
  </Card>

  <Card title="Environment Variables" icon="code" href="/essentials/configuration">
    Best practices for environment variable management
  </Card>
</CardGroup>
