Skip to main content
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
{
  "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": "..."
}
PropertyUsed ByDescription
UNKEY_DATABASE_PRIMARYcontrol, frontline, sentinelPrimary database connection string
UNKEY_DATABASE_REPLICAfrontline, sentinelReplica database connection string
UNKEY_CLICKHOUSE_URLcontrolClickHouse analytics database URL
UNKEY_VAULT_MASTER_KEYScontrol, krane, frontlineVault encryption master keys
UNKEY_VAULT_S3_URLcontrol, krane, frontlineVault S3 storage endpoint URL
UNKEY_VAULT_S3_BUCKETcontrol, krane, frontlineVault S3 bucket name
UNKEY_VAULT_S3_ACCESS_KEY_IDcontrol, krane, frontlineVault S3 access key ID
UNKEY_VAULT_S3_ACCESS_KEY_SECRETcontrol, krane, frontlineVault S3 secret access key
UNKEY_REGISTRY_URLcontrol, kraneContainer registry URL
UNKEY_REGISTRY_USERNAMEcontrol, kraneContainer registry username
UNKEY_REGISTRY_PASSWORDcontrol, kraneContainer registry password
GRAFANA_ADMIN_USERobservabilityGrafana admin username
GRAFANA_ADMIN_PASSWORDobservabilityGrafana admin password

Service-Specific Secrets

control (Control Plane)

AWS Secret Name: unkey/control
{
  "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"
}
PropertyDescription
UNKEY_AUTH_TOKENAuthentication token for control API
UNKEY_BUILD_S3_URLBuild artifacts S3 endpoint URL
UNKEY_BUILD_S3_BUCKETBuild artifacts S3 bucket name
UNKEY_BUILD_S3_ACCESS_KEY_IDBuild S3 access key ID
UNKEY_BUILD_S3_ACCESS_KEY_SECRETBuild S3 secret access key
UNKEY_RESTATE_API_KEYRestate Cloud admin API token
UNKEY_ACME_ROUTE53_ENABLEDSet to “true” to enable Route53 provider (optional)
UNKEY_ACME_ROUTE53_ACCESS_KEY_IDRoute53 access key ID for ACME (optional)
UNKEY_ACME_ROUTE53_SECRET_ACCESS_KEYRoute53 secret access key for ACME (optional)
UNKEY_ACME_ROUTE53_REGIONRoute53 region (optional)

krane

AWS Secret Name: unkey/krane
{
  "UNKEY_CONTROL_PLANE_BEARER": "..."
}
PropertyDescription
UNKEY_CONTROL_PLANE_BEARERBearer token for control plane authentication

argocd

AWS Secret Name: unkey/argocd
{
  "github-webhook-secret": "...",
  "slack-token": "...",
  "admin.password": "$2a$10$..."
}
PropertyUsed ByDescription
github-webhook-secretargocdGitHub webhook secret for ArgoCD notifications
slack-tokenargocdSlack token for ArgoCD notifications
admin.passwordargocdbcrypt-hashed admin password (merged into argocd-secret)
Note: admin.password must be a bcrypt hash. See Rotating the ArgoCD Admin Password below.

Secret Usage by Service

ServiceJSON SecretProperties Used
controlunkey/sharedDATABASE_PRIMARY, CLICKHOUSE_URL, VAULT_, REGISTRY_
controlunkey/controlAUTH_TOKEN, BUILD_S3_, RESTATE_API_KEY, ACME_ROUTE53_
kraneunkey/sharedVAULT_, REGISTRY_
kraneunkey/kraneCONTROL_PLANE_BEARER
frontlineunkey/sharedDATABASE_PRIMARY, DATABASE_REPLICA, VAULT_*
sentinelunkey/sharedDATABASE_PRIMARY, DATABASE_REPLICA
observabilityunkey/sharedGRAFANA_ADMIN_USER, GRAFANA_ADMIN_PASSWORD
restateunkey/controlRESTATE_API_KEY
argocdunkey/argocdgithub-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

# 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
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:
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:
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:
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:
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:
# 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"