# How DeepSeek-Reasonix Manages API Keys and Secrets via api_key_env Without Storing in Config Files

> Securely manage API keys and secrets for DeepSeek-Reasonix using api_key_env. Learn how to avoid storing sensitive credentials in config files and keep them out of version control.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: how-to-guide
- Published: 2026-06-22

---

**DeepSeek-Reasonix stores only the environment variable name in JSON/TOML configuration files while persisting actual API secrets to a global `.env` file, using `upsertDotEnv` and `removeDotEnv` to ensure credentials never appear in project-level version control.**

DeepSeek-Reasonix implements a secure credential management pattern that keeps sensitive API keys out of configuration files. Instead of embedding secret values directly in JSON or TOML configs, the application uses the `apiKeyEnv` field to reference environment variables, delegating actual secret storage to a user-controlled global `.env` store managed by [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go). This architecture ensures that the system can manage API keys and secrets via `api_key_env` without exposing them in repository-tracked configuration files.

## The Architecture Behind apiKeyEnv Security

### Environment Variables vs. Config Files

Traditional approaches often embed secrets directly in configuration files, creating security risks when those files are committed to version control. DeepSeek-Reasonix solves this by storing **only the environment variable name** (e.g., `DEEPSEEK_API_KEY`) in the `APIKeyEnv` field defined in [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go), while the actual value lives in a global credential store outside the project directory.

### Separation of Concerns

The architecture enforces a strict separation between configuration and credentials:

- **Configuration files** contain the `apiKeyEnv` string identifying which environment variable to use for each provider.
- **Global .env store** contains the actual `KEY=value` pairs managed through `upsertDotEnv` and `removeDotEnv` functions in [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go).

## Writing and Removing Secrets via the Backend

When users save or clear provider keys through the Settings UI, the backend delegates to dedicated functions in [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go) that interface with the global `.env` store without modifying the project's configuration files.

### Setting a Provider Key

The `SetProviderKey` function validates the environment variable name and persists the secret via `upsertDotEnv` at line 815:

```go
func (a *App) SetProviderKey(apiKeyEnv, value string) (string, error) {
    apiKeyEnv = strings.TrimSpace(apiKeyEnv)
    if apiKeyEnv == "" {
        return "", fmt.Errorf("apiKeyEnv cannot be empty")
    }
    if err := upsertDotEnv(apiKeyEnv, value); err != nil {
        return "", err
    }
    return a.saveProviderCredential(apiKeyEnv, value)
}

```

### Clearing a Provider Key

The `ClearProviderKey` function removes the entry using `removeDotEnv` (implemented at line 1588 in [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go)):

```go
func (a *App) ClearProviderKey(apiKeyEnv string) error {
    apiKeyEnv = strings.TrimSpace(apiKeyEnv)
    if apiKeyEnv == "" {
        return fmt.Errorf("apiKeyEnv cannot be empty")
    }
    return removeDotEnv(apiKeyEnv)
}

```

### Dotenv Implementation

The [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go) file implements `upsertDotEnv` to write `KEY=value` pairs to the global store and `removeDotEnv` to delete entries, ensuring the secret never touches the project's configuration files or appears in [`settings.json`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/settings.json).

## Runtime Resolution and Shadow Detection

At runtime, DeepSeek-Reasonix resolves credentials using `os.LookupEnv` and `config.ResolveCredentialForRoot`. The system checks whether the environment variable referenced by `apiKeyEnv` contains a value without exposing the secret through the configuration layer.

### Shadow Warning

The implementation includes a safety mechanism around line 821 in [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go) called `providerCredentialShadowWarning`. This emits a warning if a system-level environment variable could shadow the value stored in the global `.env` file, preventing confusion about which credential is actually active when both sources define the same variable name.

## Frontend State Management

The frontend in [`desktop/frontend/src/lib/providerModels.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/providerModels.ts) mirrors this design pattern without accessing actual secret values. Each provider object exposes `apiKeyEnv` and a boolean `keySet` property that indicates whether the environment variable currently resolves to a non-empty value.

### Detecting Key Requirements

```typescript
export function providerRequiresKey(provider: {
    requiresKey?: boolean;
    apiKeyEnv?: string;
}): boolean {
    return Boolean((provider.apiKeyEnv ?? "").trim());
}

```

### UI Interaction

The Settings panel in [`desktop/frontend/src/components/SettingsPanel.tsx`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/components/SettingsPanel.tsx) calls `SetProviderKey` and `ClearProviderKey` through the Wails bridge defined in [`desktop/frontend/src/lib/bridge.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/bridge.ts). The UI never receives the raw secret value—only the environment variable name—maintaining security across the frontend-backend boundary while allowing users to see which keys are configured via the `keySet` boolean.

## Summary

- DeepSeek-Reasonix stores **only environment variable names** in configuration files via the `apiKeyEnv` field, ensuring actual secrets never appear in JSON or TOML configs.
- Secrets are persisted to a **global `.env` file** using `upsertDotEnv` in [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go) and removed via `removeDotEnv` when clearing keys.
- The `SetProviderKey` and `ClearProviderKey` functions in [`desktop/settings_app.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/settings_app.go) validate input by trimming whitespace and checking for empty strings before delegating to the dotenv store.
- Runtime resolution uses `os.LookupEnv` with shadow detection via `providerCredentialShadowWarning` to alert users of conflicting environment variables that might override stored values.
- The frontend tracks key status through `keySet` booleans in [`providerModels.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/providerModels.ts) without accessing secret values, ensuring credentials remain confined to the backend store.

## Frequently Asked Questions

### What happens if an environment variable is set both in the system and the global .env file?

DeepSeek-Reasonix emits a `providerCredentialShadowWarning` to alert users when a system-level environment variable might override the value stored in the global `.env` file. This prevents confusion about which credential is actually being used for API authentication, as `os.LookupEnv` typically prioritizes system-level variables over file-based entries.

### Is the apiKeyEnv pattern secure for production environments?

Yes, this pattern enhances security by ensuring API keys never appear in version-controlled configuration files. By storing only the variable name in project configs and the actual value in a user-specific global `.env` store managed by [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go), DeepSeek-Reasonix prevents accidental credential exposure through Git repositories while maintaining flexibility for different deployment environments.

### How does the frontend determine if a key is set without accessing the secret value?

The frontend checks the `keySet` boolean property on provider objects defined in [`desktop/frontend/src/lib/providerModels.ts`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/frontend/src/lib/providerModels.ts). This property reflects whether `apiKeyEnv` resolves to a non-empty value at runtime through the Wails bridge, allowing the UI to display key status indicators without ever receiving the actual secret from `SetProviderKey` calls.

### Where does DeepSeek-Reasonix store the global .env file?

The global `.env` file location is managed by [`desktop/dotenv.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/desktop/dotenv.go), which implements the `upsertDotEnv` and `removeDotEnv` functions. This file exists outside the project directory in a user-specific global location (typically in the user's home directory or application data folder), ensuring that secrets persist across application restarts while remaining separate from repository-tracked configuration files.