> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ardor.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Variables & Secrets

> Configure your services with environment variables and securely store sensitive data like API keys, passwords, and tokens.

<img src="https://mintcdn.com/ardor/sf-RwXk0pWSNetwj/docs/services/images/variables-and-secrets.webp?fit=max&auto=format&n=sf-RwXk0pWSNetwj&q=85&s=7b093b1f67baa100b52dc7a373a05344" alt="Variables and Secrets Management" width="1172" height="970" data-path="docs/services/images/variables-and-secrets.webp" />

## Overview

Every application needs configuration — API endpoints, feature flags, database passwords, third-party API keys. Variables & Secrets let you manage all of this without hardcoding values in your code.

<Tip>
  **Cerebrum manages variables.** Just say "add the OpenAI API key" or "set DEBUG to true" — Cerebrum will configure it. The details below explain how variables and secrets work.
</Tip>

<CardGroup cols="2">
  <Card title="Variables" icon="sliders">
    Plain text configuration visible in the UI. Use for non-sensitive settings like endpoints, flags, and paths.
  </Card>

  <Card title="Secrets" icon="lock">
    Encrypted values hidden from view. Use for passwords, API keys, tokens, and anything sensitive.
  </Card>
</CardGroup>

<Note>
  Variables and Secrets are configured per service and injected as environment variables at runtime — both in dev containers and production deployments.
</Note>

## Why Use Variables & Secrets

<CardGroup cols="2">
  <Card title="Keep secrets out of code" icon="shield-check">
    Never commit passwords or API keys to your repository. Store them securely in Ardor.
  </Card>

  <Card title="Environment-specific config" icon="layer-group">
    Same code, different configs. Switch between dev/staging/prod without changing code.
  </Card>

  <Card title="Easy updates" icon="rotate">
    Change a value once in the UI — no redeployment needed for dev containers.
  </Card>

  <Card title="Team-friendly" icon="users">
    Share configuration without sharing actual secret values. Team members see masked data.
  </Card>
</CardGroup>

## Variables vs Secrets

|                | Variables               | Secrets                           |
| -------------- | ----------------------- | --------------------------------- |
| **Visibility** | Visible in UI           | Masked (••••••••)                 |
| **Storage**    | Plain text              | Encrypted                         |
| **Use for**    | Endpoints, flags, paths | Passwords, API keys, tokens       |
| **Editable**   | View and edit freely    | Edit without seeing current value |

<Tip>
  **Rule of thumb:** Passwords, API keys, tokens? Always a Secret. They're stored encrypted in Ardor and never touch your code — only references to them do. Your GitHub repo stays clean.
</Tip>

## System Variables

At runtime, Ardor may add system variables based on your service settings. These variables are managed by Ardor and cannot be edited or overridden from Variables & Secrets.

Common system variables include:

| Variable               | Description                                                      |
| ---------------------- | ---------------------------------------------------------------- |
| `ARDOR_SERVICE_ID`     | ID of the current service                                        |
| `ARDOR_ENVIRONMENT_ID` | ID of the current environment                                    |
| `ARDOR_PRIVATE_HOST`   | Private hostname for reaching the service inside the environment |

<Note>
  System variables are injected automatically when they apply to the service. They may not all be present for every service configuration.
</Note>

## Adding Variables & Secrets

<Steps>
  <Step title="Open Service Settings">
    Navigate to your service and open the **Variables & Secrets** section
  </Step>

  <Step title="Add Variable or Secret">
    Click **Add Variable** or **Add Secret**, enter a name and value
  </Step>

  <Step title="Save">
    Changes apply to dev container immediately. For production, redeploy your service.
  </Step>
</Steps>

### Variable References

A variable or secret value can include references to variables from the current service or another service. Type `@` in the value field and select a variable from the list. Ardor inserts a reference token for you, including references to system variables such as `ARDOR_PRIVATE_HOST`.

<img src="https://mintcdn.com/ardor/sf-RwXk0pWSNetwj/docs/services/images/variable-references.webp?fit=max&auto=format&n=sf-RwXk0pWSNetwj&q=85&s=4d6ad9053a02c365be38ce63c437c57c" alt="Variable References" width="942" height="821" data-path="docs/services/images/variable-references.webp" />

You can also click <svg aria-label="Add Reference" role="img" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" style={{ display: "inline-block", verticalAlign: "-0.15em" }}><path d="M9 17H7A5 5 0 0 1 7 7h2" /><path d="M15 7h2a5 5 0 1 1 0 10h-2" /><line x1="8" x2="16" y1="12" y2="12" /></svg> to create a reference directly.

A single value can combine static text and multiple references. For example, a `DATABASE_URL` can be assembled from database credentials and the database service private host:

```text theme={null}
postgresql://{{ postgres-db.POSTGRES_USER }}:{{ postgres-db.POSTGRES_PASSWORD }}@{{ postgres-db.ARDOR_PRIVATE_HOST }}:5432/{{ postgres-db.POSTGRES_DB }}
```

<Note>
  References are resolved when Ardor injects environment variables at runtime, so the consuming service receives one final value.
</Note>

### Naming Conventions

Environment variable names should be:

* **UPPERCASE** with underscores: `DATABASE_URL`, `API_KEY`, `DEBUG_MODE`
* Descriptive: `POSTGRES_PASSWORD` not `PW`
* Prefixed for clarity: `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`

<Warning>
  Some names are reserved by the system (like `PORT`). Ardor will warn you if you try to use a reserved name.
</Warning>

## Common Use Cases

<Tabs>
  <Tab title="Database Connection">
    Connect to PostgreSQL, MySQL, or other databases:

    | Variable            | Type     | Example                     |
    | ------------------- | -------- | --------------------------- |
    | `DATABASE_HOST`     | Variable | `postgres-service.internal` |
    | `DATABASE_PORT`     | Variable | `5432`                      |
    | `DATABASE_NAME`     | Variable | `myapp`                     |
    | `DATABASE_USER`     | Variable | `admin`                     |
    | `DATABASE_PASSWORD` | Secret   | `••••••••`                  |

    ```python theme={null}
    import os

    db_url = f"postgresql://{os.environ['DATABASE_USER']}:{os.environ['DATABASE_PASSWORD']}@{os.environ['DATABASE_HOST']}:{os.environ['DATABASE_PORT']}/{os.environ['DATABASE_NAME']}"
    ```
  </Tab>

  <Tab title="Third-Party APIs">
    Connect to OpenAI, Stripe, Twilio, etc:

    | Variable                | Type     | Example    |
    | ----------------------- | -------- | ---------- |
    | `OPENAI_API_KEY`        | Secret   | `••••••••` |
    | `OPENAI_MODEL`          | Variable | `gpt-4`    |
    | `STRIPE_SECRET_KEY`     | Secret   | `••••••••` |
    | `STRIPE_WEBHOOK_SECRET` | Secret   | `••••••••` |

    ```python theme={null}
    import os
    from openai import OpenAI

    client = OpenAI(api_key=os.environ['OPENAI_API_KEY'])
    ```
  </Tab>

  <Tab title="Feature Flags">
    Toggle features without code changes:

    | Variable           | Type     | Example    |
    | ------------------ | -------- | ---------- |
    | `DEBUG_MODE`       | Variable | `true`     |
    | `ENABLE_ANALYTICS` | Variable | `false`    |
    | `MAX_UPLOAD_SIZE`  | Variable | `10485760` |

    ```python theme={null}
    import os

    debug = os.environ.get('DEBUG_MODE', 'false').lower() == 'true'
    if debug:
        print("Debug mode enabled")
    ```
  </Tab>

  <Tab title="Service URLs">
    Connect services within your solution:

    | Variable       | Type     | Example                               |
    | -------------- | -------- | ------------------------------------- |
    | `API_BASE_URL` | Variable | `https://api.example.com`             |
    | `REDIS_URL`    | Variable | `redis://redis-service.internal:6379` |
    | `WEBHOOK_URL`  | Variable | `https://myapp.ardor.cloud/webhook`   |
  </Tab>
</Tabs>

## Reading Variables in Code

Variables and Secrets are injected as environment variables. Here's how to read them:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import os

    # Required variable (raises error if missing)
    api_key = os.environ['API_KEY']

    # Optional with default
    debug = os.environ.get('DEBUG', 'false')
    port = int(os.environ.get('PORT', 8080))
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    // Required variable
    const apiKey = process.env.API_KEY;
    if (!apiKey) throw new Error('API_KEY is required');

    // Optional with default
    const debug = process.env.DEBUG || 'false';
    const port = parseInt(process.env.PORT || '8080');
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    import "os"

    // Required variable
    apiKey := os.Getenv("API_KEY")
    if apiKey == "" {
        panic("API_KEY is required")
    }

    // Optional with default
    debug := os.Getenv("DEBUG")
    if debug == "" {
        debug = "false"
    }
    ```
  </Tab>
</Tabs>

## Frontend Services

<Note>
  For frontend services (React, Vue, Next.js, etc.), variables and secrets are composed into a `.env` file at build time. Use them in your Dockerfile:

  ```dockerfile theme={null}
  COPY .env .

  RUN npm run build
  ```
</Note>

Frontend variables typically need a prefix depending on your framework:

* **Vite:** `VITE_`
* **Create React App:** `REACT_APP_`
* **Next.js:** `NEXT_PUBLIC_`

<Warning>
  Frontend variables are embedded in the built code and visible to users. Never put secrets in frontend variables!
</Warning>

## When Changes Apply

| In                | Variables         | Secrets           |
| ----------------- | ----------------- | ----------------- |
| **Dev Container** | Restart container | Restart container |
| **Deployment**    | Redeploy service  | Redeploy service  |

<Note>
  Dev containers restart automatically when you save variable changes. For deployed service, you need to trigger a new deployment.
</Note>

## Security

### How Secrets Are Protected

* **Encrypted at rest** — Secrets are stored encrypted
* **Masked by default** — Shown as `••••••••`, but you can reveal them by clicking the eye icon

### Best Practices

<AccordionGroup>
  <Accordion title="Use secrets for anything sensitive">
    API keys, passwords, tokens, private keys — if it grants access to something, it's a secret.
  </Accordion>

  <Accordion title="Don't log secrets">
    Be careful with debug logging. Never print environment variables that might contain secrets.
  </Accordion>

  <Accordion title="Rotate regularly">
    Change passwords and API keys periodically. Update the secret in Ardor, redeploy, done.
  </Accordion>

  <Accordion title="Use descriptive names">
    `STRIPE_SECRET_KEY` is better than `KEY1`. Future you will thank present you.
  </Accordion>

  <Accordion title="Minimum access principle">
    Only add secrets that a service actually needs. Don't share database passwords with services that don't use the database.
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Variable not available in my code">
    **Cause:** Container hasn't restarted after adding the variable.

    **Solution:** Restart the dev container or redeploy the service.
  </Accordion>

  <Accordion title="Variable has wrong value">
    **Cause:** Typo in variable name or old cached value.

    **Solution:**

    * Check the exact variable name (case-sensitive!)
    * Restart container to pick up latest values
  </Accordion>

  <Accordion title="Secret visible in logs">
    **Cause:** Your code is logging environment variables.

    **Solution:** Review your logging code. Never log `os.environ` or similar dumps.
  </Accordion>

  <Accordion title="Frontend can't access variable">
    **Cause:** Missing framework prefix or variable added after build.

    **Solution:**

    * Add required prefix (`VITE_`, `REACT_APP_`, etc.)
    * Rebuild and redeploy the frontend
  </Accordion>
</AccordionGroup>

## What's Next

<CardGroup cols="2">
  <Card title="Service Configuration" icon="cube" href="/docs/services/service">
    Learn about all service settings including resources and networking
  </Card>

  <Card title="Development Container" icon="terminal" href="/docs/services/service#development-container">
    Use the dev container to test your variables in real-time
  </Card>

  <Card title="Connecting Services" icon="network-wired" href="/docs/services/networking">
    Connect multiple services and share configuration
  </Card>

  <Card title="Build with Cerebrum" icon="robot" href="/docs/cerebrum/agent">
    Let Cerebrum set up variables and secrets for you automatically
  </Card>
</CardGroup>
