> ## 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.

# Managing Secrets

> Securely store and manage sensitive values like API keys and credentials with Alchemy

# Managing Secrets

Alchemy provides a built-in **Secret** system for handling sensitive values like API keys, passwords, and credentials. Secrets are automatically encrypted when stored in state files using a password.

## Creating Secrets

Use `alchemy.secret()` to wrap sensitive values:

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

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

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

await app.finalize();
```

<Note>
  Secrets require a password to be set. Without a password, secret operations will fail.
</Note>

## Setting the Password

The password is used to encrypt and decrypt secrets. You can provide it in two ways:

### Global Password

Set the password when creating your application:

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

### Environment Variable

Alchemy automatically reads from the `ALCHEMY_PASSWORD` environment variable:

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

<CodeGroup>
  ```bash .env theme={null}
  ALCHEMY_PASSWORD=my-secure-password
  API_KEY=sk-1234567890abcdef
  DB_PASSWORD=super-secret-password
  ```

  ```typescript alchemy.run.ts theme={null}
  import "dotenv/config";
  import alchemy from "alchemy";

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

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

  await app.finalize();
  ```
</CodeGroup>

<Warning>
  Never commit your `.env` file or password to version control. Add `.env` to `.gitignore`.
</Warning>

## Secret from Environment Variables

Alchemy provides a convenient helper for creating secrets from environment variables:

### Using `secret.env`

```typescript theme={null}
const worker = await Worker("api", {
  entrypoint: "./src/index.ts",
  bindings: {
    // Preferred: Better error messages
    API_KEY: alchemy.secret.env.API_KEY,
    DB_PASSWORD: alchemy.secret.env.DB_PASSWORD
  }
});
```

### Using `secret()`

```typescript theme={null}
const worker = await Worker("api", {
  entrypoint: "./src/index.ts",
  bindings: {
    // Also valid
    API_KEY: alchemy.secret(process.env.API_KEY),
    DB_PASSWORD: alchemy.secret(process.env.DB_PASSWORD)
  }
});
```

<Tip>
  Use `alchemy.secret.env.VAR_NAME` for better error messages when environment variables are missing.
</Tip>

## How Secrets Work

### Encryption in State Files

When resources are saved to state files (`.alchemy/`), secrets are automatically encrypted:

```json theme={null}
{
  "props": {
    "apiKey": {
      "@secret": "encrypted-value-using-password-here..."
    }
  }
}
```

The encrypted value can only be decrypted with the correct password.

### Secret Lifecycle

<Steps>
  ### Creation

  When you create a secret, the value is wrapped in a `Secret` object:

  ```typescript theme={null}
  const apiKey = alchemy.secret(process.env.API_KEY);
  // Secret { unencrypted: "sk-1234...", name: "alchemy:anonymous-secret-0" }
  ```

  ### Storage

  When the resource is saved to state, the secret is encrypted:

  ```typescript theme={null}
  // In memory: unencrypted
  const secret = alchemy.secret("my-secret-value");

  // In state file: encrypted
  { "@secret": "U2FsdGVkX1..." }
  ```

  ### Retrieval

  When state is loaded, secrets are automatically decrypted using the password:

  ```typescript theme={null}
  const worker = await Worker("api", { /* ... */ });
  // Secrets are decrypted and available in worker.bindings
  ```
</Steps>

## Named Secrets

You can assign names to secrets for better debugging:

```typescript theme={null}
const worker = await Worker("api", {
  entrypoint: "./src/index.ts",
  bindings: {
    API_KEY: alchemy.secret(process.env.API_KEY, "openai-api-key"),
    DB_PASSWORD: alchemy.secret(process.env.DB_PASSWORD, "postgres-password")
  }
});
```

Named secrets appear in logs and error messages:

```
Secret(openai-api-key)
Secret(postgres-password)
```

## Secret Wrapping and Unwrapping

The `Secret` class provides utilities for working with secret values:

### Wrap

Ensure a value is wrapped in a Secret:

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

const secret = Secret.wrap(process.env.API_KEY);
// If already a Secret, returns as-is
// Otherwise, wraps in a new Secret
```

### Unwrap

Extract the unencrypted value from a Secret:

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

const apiKey = alchemy.secret(process.env.API_KEY);
const plainValue = Secret.unwrap(apiKey);
// Returns the original unencrypted value
```

<Warning>
  Be careful when unwrapping secrets. Avoid logging or exposing unencrypted values.
</Warning>

## Type Guard

Check if a value is a Secret:

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

const value = alchemy.secret("my-secret");

if (isSecret(value)) {
  console.log("This is a secret!");
  // TypeScript knows value is Secret<string>
}
```

## Secret Safety Features

### toString Protection

Secrets override `toString()` to prevent accidental exposure:

```typescript theme={null}
const apiKey = alchemy.secret(process.env.API_KEY);
console.log(apiKey);
// Output: Secret(alchemy:anonymous-secret-0)
// NOT: sk-1234567890abcdef
```

### console.log Protection

Secrets implement custom inspect for Node.js:

```typescript theme={null}
const apiKey = alchemy.secret(process.env.API_KEY);
console.log(apiKey);
// Output: Secret(alchemy:anonymous-secret-0)
```

<Tip>
  This prevents secrets from accidentally appearing in logs or debug output.
</Tip>

## Scoped Secrets

You can use different passwords for different scopes:

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

const app = await alchemy("my-app");

await alchemy.run("production-resources", {
  password: process.env.PROD_PASSWORD
}, async () => {
  const prodWorker = await Worker("prod-api", {
    entrypoint: "./src/index.ts",
    bindings: {
      // This secret is encrypted with PROD_PASSWORD
      API_KEY: alchemy.secret(process.env.PROD_API_KEY)
    }
  });
});

await alchemy.run("staging-resources", {
  password: process.env.STAGING_PASSWORD
}, async () => {
  const stagingWorker = await Worker("staging-api", {
    entrypoint: "./src/index.ts",
    bindings: {
      // This secret is encrypted with STAGING_PASSWORD
      API_KEY: alchemy.secret(process.env.STAGING_API_KEY)
    }
  });
});

await app.finalize();
```

## Recovering from Lost Passwords

If you lose your encryption password, you can erase secrets and start fresh:

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

<Warning>
  This will treat all secrets as `undefined`. You'll need to re-deploy with new secret values.
</Warning>

## Best Practices

<Steps>
  ### Use Environment Variables

  Store sensitive values in environment variables, not in code:

  ```typescript theme={null}
  // ✅ Good
  API_KEY: alchemy.secret.env.API_KEY

  // ❌ Bad - Hardcoded secret
  API_KEY: alchemy.secret("sk-1234567890abcdef")
  ```

  ### Set a Strong Password

  Use a strong, random password for encryption:

  ```bash theme={null}
  # Generate a secure password
  openssl rand -base64 32 > .alchemy-password

  # Use it in your environment
  export ALCHEMY_PASSWORD=$(cat .alchemy-password)
  ```

  ### Never Commit Secrets

  Add sensitive files to `.gitignore`:

  ```gitignore theme={null}
  .env
  .env.local
  .alchemy-password
  *.key
  *.pem
  ```

  ### Use Named Secrets for Debugging

  ```typescript theme={null}
  API_KEY: alchemy.secret(process.env.API_KEY, "stripe-api-key"),
  DB_PASS: alchemy.secret(process.env.DB_PASS, "postgres-password")
  ```

  ### Validate Secrets Exist

  Check for required environment variables early:

  ```typescript theme={null}
  const requiredEnvVars = ["API_KEY", "DB_PASSWORD", "ALCHEMY_PASSWORD"];

  for (const varName of requiredEnvVars) {
    if (!process.env[varName]) {
      throw new Error(`Missing required environment variable: ${varName}`);
    }
  }

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

## Example: Complete Secret Setup

<CodeGroup>
  ```bash .env.example theme={null}
  # Copy this file to .env and fill in the values
  ALCHEMY_PASSWORD=your-encryption-password
  API_KEY=your-api-key
  DB_PASSWORD=your-database-password
  CLOUDFLARE_API_KEY=your-cloudflare-api-key
  CLOUDFLARE_ACCOUNT_ID=your-account-id
  ```

  ```typescript alchemy.run.ts theme={null}
  import "dotenv/config";
  import alchemy from "alchemy";
  import { Worker, D1Database } from "alchemy/cloudflare";
  import path from "node:path";

  // Validate required environment variables
  const requiredVars = [
    "ALCHEMY_PASSWORD",
    "API_KEY",
    "DB_PASSWORD"
  ];

  for (const varName of requiredVars) {
    if (!process.env[varName]) {
      throw new Error(`Missing ${varName} in .env file`);
    }
  }

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

  // Create database
  const db = await D1Database("database", {
    name: "my-database"
  });

  // Create worker with secrets
  const worker = await Worker("api", {
    entrypoint: path.join(import.meta.dirname, "src", "index.ts"),
    bindings: {
      DB: db,
      API_KEY: alchemy.secret.env.API_KEY,
      DB_PASSWORD: alchemy.secret.env.DB_PASSWORD
    }
  });

  console.log({ url: worker.url });

  await app.finalize();
  ```
</CodeGroup>

## Next Steps

* [Creating Resources](/guides/creating-resources) - Learn how to create infrastructure resources
* [Local Development](/guides/local-development) - Test with secrets locally
* [Deployment](/guides/deployment) - Deploy with secrets to production
