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

# AWS Secrets Manager - Required Secrets

> Required secrets for EKS cluster infrastructure.

This document lists all AWS Secrets Manager secrets required for the EKS cluster infrastructure.

**Note:** All secrets are stored as JSON objects. ExternalSecrets extract individual properties from these JSON secrets.

## Shared Secrets

**AWS Secret Name:** `unkey/shared`

```json theme={"theme":"kanagawa-wave"}
{
  "UNKEY_DATABASE_PRIMARY": "mysql://...",
  "UNKEY_DATABASE_REPLICA": "mysql://...",
  "UNKEY_CLICKHOUSE_URL": "https://...",
  "UNKEY_VAULT_MASTER_KEYS": "...",
  "UNKEY_VAULT_S3_URL": "https://...",
  "UNKEY_VAULT_S3_BUCKET": "...",
  "UNKEY_VAULT_S3_ACCESS_KEY_ID": "...",
  "UNKEY_VAULT_S3_ACCESS_KEY_SECRET": "...",
  "UNKEY_REGISTRY_URL": "ghcr.io/...",
  "UNKEY_REGISTRY_USERNAME": "...",
  "UNKEY_REGISTRY_PASSWORD": "...",
  "GRAFANA_ADMIN_USER": "admin",
  "GRAFANA_ADMIN_PASSWORD": "..."
}
```

| Property                           | Used By                      | Description                        |
| ---------------------------------- | ---------------------------- | ---------------------------------- |
| `UNKEY_DATABASE_PRIMARY`           | control, frontline, sentinel | Primary database connection string |
| `UNKEY_DATABASE_REPLICA`           | frontline, sentinel          | Replica database connection string |
| `UNKEY_CLICKHOUSE_URL`             | control                      | ClickHouse analytics database URL  |
| `UNKEY_VAULT_MASTER_KEYS`          | control, krane, frontline    | Vault encryption master keys       |
| `UNKEY_VAULT_S3_URL`               | control, krane, frontline    | Vault S3 storage endpoint URL      |
| `UNKEY_VAULT_S3_BUCKET`            | control, krane, frontline    | Vault S3 bucket name               |
| `UNKEY_VAULT_S3_ACCESS_KEY_ID`     | control, krane, frontline    | Vault S3 access key ID             |
| `UNKEY_VAULT_S3_ACCESS_KEY_SECRET` | control, krane, frontline    | Vault S3 secret access key         |
| `UNKEY_REGISTRY_URL`               | control, krane               | Container registry URL             |
| `UNKEY_REGISTRY_USERNAME`          | control, krane               | Container registry username        |
| `UNKEY_REGISTRY_PASSWORD`          | control, krane               | Container registry password        |
| `GRAFANA_ADMIN_USER`               | observability                | Grafana admin username             |
| `GRAFANA_ADMIN_PASSWORD`           | observability                | Grafana admin password             |

## Service-Specific Secrets

### control (Control Plane)

**AWS Secret Name:** `unkey/control`

```json theme={"theme":"kanagawa-wave"}
{
  "UNKEY_AUTH_TOKEN": "...",
  "UNKEY_BUILD_S3_URL": "https://...",
  "UNKEY_BUILD_S3_BUCKET": "...",
  "UNKEY_BUILD_S3_ACCESS_KEY_ID": "...",
  "UNKEY_BUILD_S3_ACCESS_KEY_SECRET": "...",
  "UNKEY_RESTATE_API_KEY": "...",
  "UNKEY_ACME_ROUTE53_ENABLED": "true",
  "UNKEY_ACME_ROUTE53_ACCESS_KEY_ID": "...",
  "UNKEY_ACME_ROUTE53_SECRET_ACCESS_KEY": "...",
  "UNKEY_ACME_ROUTE53_REGION": "us-east-1"
}
```

| Property                               | Description                                         |
| -------------------------------------- | --------------------------------------------------- |
| `UNKEY_AUTH_TOKEN`                     | Authentication token for control API                |
| `UNKEY_BUILD_S3_URL`                   | Build artifacts S3 endpoint URL                     |
| `UNKEY_BUILD_S3_BUCKET`                | Build artifacts S3 bucket name                      |
| `UNKEY_BUILD_S3_ACCESS_KEY_ID`         | Build S3 access key ID                              |
| `UNKEY_BUILD_S3_ACCESS_KEY_SECRET`     | Build S3 secret access key                          |
| `UNKEY_RESTATE_API_KEY`                | Restate Cloud admin API token                       |
| `UNKEY_ACME_ROUTE53_ENABLED`           | Set to "true" to enable Route53 provider (optional) |
| `UNKEY_ACME_ROUTE53_ACCESS_KEY_ID`     | Route53 access key ID for ACME (optional)           |
| `UNKEY_ACME_ROUTE53_SECRET_ACCESS_KEY` | Route53 secret access key for ACME (optional)       |
| `UNKEY_ACME_ROUTE53_REGION`            | Route53 region (optional)                           |

### krane

**AWS Secret Name:** `unkey/krane`

```json theme={"theme":"kanagawa-wave"}
{
  "UNKEY_CONTROL_PLANE_BEARER": "..."
}
```

| Property                     | Description                                   |
| ---------------------------- | --------------------------------------------- |
| `UNKEY_CONTROL_PLANE_BEARER` | Bearer token for control plane authentication |

### argocd

**AWS Secret Name:** `unkey/argocd`

```json theme={"theme":"kanagawa-wave"}
{
  "github-webhook-secret": "...",
  "slack-token": "...",
  "admin.password": "$2a$10$..."
}
```

| Property                | Used By | Description                                                |
| ----------------------- | ------- | ---------------------------------------------------------- |
| `github-webhook-secret` | argocd  | GitHub webhook secret for ArgoCD notifications             |
| `slack-token`           | argocd  | Slack token for ArgoCD notifications                       |
| `admin.password`        | argocd  | bcrypt-hashed admin password (merged into `argocd-secret`) |

**Note:** `admin.password` must be a bcrypt hash. See [Rotating the ArgoCD Admin Password](#rotating-the-argocd-admin-password) below.

## Secret Usage by Service

| Service           | JSON Secret     | Properties Used                                                |
| ----------------- | --------------- | -------------------------------------------------------------- |
| **control**       | `unkey/shared`  | DATABASE\_PRIMARY, CLICKHOUSE\_URL, VAULT\_*, REGISTRY\_*      |
| **control**       | `unkey/control` | AUTH\_TOKEN, BUILD\_S3\_*, RESTATE\_API\_KEY, ACME\_ROUTE53\_* |
| **krane**         | `unkey/shared`  | VAULT\_*, REGISTRY\_*                                          |
| **krane**         | `unkey/krane`   | CONTROL\_PLANE\_BEARER                                         |
| **frontline**     | `unkey/shared`  | DATABASE\_PRIMARY, DATABASE\_REPLICA, VAULT\_\*                |
| **sentinel**      | `unkey/shared`  | DATABASE\_PRIMARY, DATABASE\_REPLICA                           |
| **observability** | `unkey/shared`  | GRAFANA\_ADMIN\_USER, GRAFANA\_ADMIN\_PASSWORD                 |
| **restate**       | `unkey/control` | RESTATE\_API\_KEY                                              |
| **argocd**        | `unkey/argocd`  | github-webhook-secret, slack-token, admin.password             |

## Rotating the ArgoCD Admin Password

The ArgoCD admin password is stored as a bcrypt hash in AWS Secrets Manager and synced into each cluster by External Secrets Operator. To rotate it:

### 1. Generate a bcrypt hash of the new password

```bash theme={"theme":"kanagawa-wave"}
# Using htpasswd (if installed)
HASH=$(htpasswd -nbBC 10 "" "NEW_PASSWORD_HERE" | tr -d ':\n' | sed 's/$2y/$2a/')

# Or using docker
HASH=$(docker run --rm httpd:2-alpine htpasswd -nbBC 10 "" "NEW_PASSWORD_HERE" | tr -d ':\n' | sed 's/$2y/$2a/')
```

### 2. Update the AWS secret

Replace `PROFILE` and `REGION` for your target environment:

* **Staging:** `--profile unkey-sandbox-admin --region eu-central-1`
* **Production:** `--profile unkey-production001-admin --region us-east-1`

```bash theme={"theme":"kanagawa-wave"}
CURRENT=$(aws secretsmanager get-secret-value \
  --profile PROFILE --region REGION \
  --secret-id "unkey/argocd" --query SecretString --output text)

UPDATED=$(echo "$CURRENT" | jq --arg h "$HASH" '.["admin.password"] = $h')

aws secretsmanager put-secret-value \
  --profile PROFILE --region REGION \
  --secret-id "unkey/argocd" --secret-string "$UPDATED"
```

The secret automatically replicates to other regions via AWS-native replication.

### 3. Wait for ESO to sync (or force it)

The ArgoCD ExternalSecrets poll every 1 minute (most services use `1m`, some like incident.io and restate use `1h`). Verify the sync:

```bash theme={"theme":"kanagawa-wave"}
kubectl --context CONTEXT -n argocd get externalsecret argocd-admin-password
```

### 4. Restart argocd-server

ArgoCD caches the password in memory, so a restart is required:

```bash theme={"theme":"kanagawa-wave"}
kubectl --context CONTEXT -n argocd rollout restart deployment argocd-server
```

### 5. Verify

Log in to the ArgoCD UI with username `admin` and the new password.

## Creating/Updating Secrets

Create a JSON secret:

```bash theme={"theme":"kanagawa-wave"}
aws secretsmanager create-secret \
  --name "unkey/shared" \
  --secret-string '{"UNKEY_DATABASE_PRIMARY":"mysql://...","UNKEY_DATABASE_REPLICA":"mysql://..."}' \
  --region us-east-1
```

Update an existing JSON secret:

```bash theme={"theme":"kanagawa-wave"}
aws secretsmanager put-secret-value \
  --secret-id "unkey/shared" \
  --secret-string '{"UNKEY_DATABASE_PRIMARY":"mysql://...","UNKEY_DATABASE_REPLICA":"mysql://..."}' \
  --region us-east-1
```

To update a single property without replacing the entire secret:

```bash theme={"theme":"kanagawa-wave"}
# Get current secret
CURRENT=$(aws secretsmanager get-secret-value --secret-id "unkey/shared" --query SecretString --output text)

# Update single property with jq
UPDATED=$(echo "$CURRENT" | jq '.UNKEY_DATABASE_PRIMARY = "new-value"')

# Put updated secret
aws secretsmanager put-secret-value --secret-id "unkey/shared" --secret-string "$UPDATED"
```
