---
title: "Step 3: Create the secrets"
description: Create the Kubernetes Secrets that hold your OpenLM Platform connection details and the TLS certificate, before you install the chart.
product: OpenLM Platform
---

Create the Kubernetes Secrets that hold your connection details, with one script, before you install the chart. The chart contains **no passwords**: each service reads its connection details from Secrets that you create in the namespace.

The commands on this page load their variables from `openlm-install.env`, the file you created from the [installation worksheet](https://www.openlm.com/documentation/cloud/deployment-operations/on-premise/deployment-guide/kubernetes/before-you-start/worksheet).

:::note[Why the secrets aren't part of Helm]
You create the secrets with `kubectl`, not Helm, on purpose. That way, `helm uninstall` or a failed upgrade can never delete your credentials, and you can rotate a password without touching the Helm release.
:::

## 3.1 Save the script

Save the following block as `create-openlm-secrets.sh` next to your worksheet. You don't need to edit it: it reads everything from the worksheet.

```bash
#!/usr/bin/env bash
# create-openlm-secrets.sh: creates or updates every Secret the OpenLM Platform reads.
# Safe to run again: existing secrets are updated in place.
set -euo pipefail
: "${NS:?load openlm-install.env first}" "${SQL_HOST:?}" "${SQL_USER:?}" "${SQL_PASSWORD:?}" "${DB_PREFIX:?}"
: "${MONGO_URI:?}" "${KAFKA_BOOTSTRAP:?}" "${REDIS_HOST:?}" "${REDIS_PASSWORD:?}" "${HANGFIRE_PASSWORD:?}"

apply() { local name="$1"; shift
  kubectl -n "$NS" create secret generic "$name" "$@" --dry-run=client -o yaml | kubectl -n "$NS" apply -f - >/dev/null
  echo "  ok  $name"; }

# SQL Server. Connection strings carry the password BASE64-ENCODED (the services decode it).
# Split-field secrets carry it as plain text.
SQL_PASSWORD_B64="$(printf '%s' "$SQL_PASSWORD" | base64 | tr -d '\n')"
DS="$SQL_HOST"; [ "$SQL_PORT" != "1433" ] && DS="$SQL_HOST,$SQL_PORT"
TAIL="Min Pool Size=0;Max Pool Size=100;Encrypt=${SQL_ENCRYPT};TrustServerCertificate=True"
conn() { echo "Data Source=$DS;Initial Catalog=$1;User ID=$SQL_USER;Password=$SQL_PASSWORD_B64;$TAIL"; }

# Redis. With TLS the services need ssl=True in the connection string.
REDIS_CONN="$REDIS_HOST:$REDIS_PORT,password=$REDIS_PASSWORD,abortConnect=false"
[ "${REDIS_TLS:-false}" = "true" ] && REDIS_CONN="$REDIS_CONN,ssl=True"

echo "Creating secrets in namespace $NS ..."
apply openlm-generic-identity-db-credentials \
  --from-literal="IDENTITY_DATABASE_CONNECTIONSTRING=$(conn "${DB_PREFIX}_identity")" \
  --from-literal="ConnectionString=$(conn "${DB_PREFIX}_identity")"
apply openlm-generic-server-db-credentials \
  --from-literal="INFRASTRUCTURE__ServerConnectionStringTemplate=$(conn '{0}')"
apply openlm-generic-reporting-db-credentials \
  --from-literal="REPORTING_DATABASE_CONNECTIONSTRING=$(conn "${DB_PREFIX}_reporting")"
apply openlm-generic-reporting-mssql-credentials \
  --from-literal="HOST_NAME=$SQL_HOST" --from-literal="PORT=$SQL_PORT" \
  --from-literal="USERNAME=$SQL_USER" --from-literal="PASSWORD=$SQL_PASSWORD"
apply openlm-dss-db-credentials \
  --from-literal="DbType=2" --from-literal="DbServer=$SQL_HOST" --from-literal="DbPort=$SQL_PORT" \
  --from-literal="DbName=${DB_PREFIX}_dss" --from-literal="DbUser=$SQL_USER" --from-literal="DbPassword=$SQL_PASSWORD_B64"

apply openlm-generic-mongo-db-credentials \
  --from-literal="MONGODB__CONNECTIONSTRING=$MONGO_URI" \
  --from-literal="MONGODB_CONNECTION=$MONGO_URI" --from-literal="MONGOURI=$MONGO_URI" --from-literal="MONGO_URI=$MONGO_URI"
apply openlm-generic-kafka-bootstrap-credentials \
  --from-literal="INFRASTRUCTURE__KAFKABOOTSTRAPSERVERS=$KAFKA_BOOTSTRAP"
apply openlm-generic-redis-connection-credentials \
  --from-literal="REDIS__CONNECTIONSTRING=$REDIS_CONN" \
  --from-literal="INFRASTRUCTURE__REDIS__CONNECTIONSTRING=$REDIS_CONN" \
  --from-literal="INFRASTRUCTURE__REDISCONNECTION=$REDIS_CONN" --from-literal="REDIS_CONNECTION=$REDIS_CONN"

# Sign-in to the background-job dashboard of the identity discovery service.
apply openlm-identitydiscovery-hangfire-credentials \
  --from-literal="Hangfire__Dashboard__Authorization__Username=admin" \
  --from-literal="Hangfire__Dashboard__Authorization__Password=$HANGFIRE_PASSWORD"

# Optional integrations. They must exist; leave them empty unless you use the integration.
apply openlm-auditservice-aws-credentials --from-literal=ACCESSKEY= --from-literal=SECRETKEY=
apply openlm-licensefilecomparator-aws-credentials \
  --from-literal=AWS_SQS_ACCESS_KEY= --from-literal=AWS_SQS_SECRET_ACCESS_KEY=
apply openlm-licensefilecomparator-servicenow-credentials \
  --from-literal=SERVICENOW_CLIENTID= --from-literal=SERVICENOW_CLIENTSECRET= \
  --from-literal=SERVICENOW_USERNAME= --from-literal=SERVICENOW_PASSWORD= --from-literal=SERVICENOW_INSTANCE_URL= \
  --from-literal=AWS_SQS_QUEUE_URL= --from-literal=AWS_SQS_REGION= \
  --from-literal=BROKERHUBAPI_DELAY_IN_MILLISECONDS=10000 --from-literal=BROKERHUBAPI_MAX_RETRY_COUNT=5 \
  --from-literal=AWS_SQS_MAX_MESSAGES=5 --from-literal=AWS_SQS_QUEUE_WORKER_COUNT=3 --from-literal=AWS_SQS_WAIT_TIME_SECONDS=10
for p in alertservice:ALERT_SERVICE identityservice:IDENTITY identityalignment:IDENTITYALIGNMENT; do
  args=(); for f in TYPE PROJECT_ID PRIVATE_KEY_ID PRIVATE_KEY CLIENT_MAIL CLIENT_ID AUTH_URI TOKEN_URI AUTH_PROVIDER_X509 CLIENT_x509; do
    args+=("--from-literal=${p#*:}__$f="); done
  apply "openlm-pushnotification-${p%%:*}-credentials" "${args[@]}"
done
apply openlm-sam-apikeys --from-literal=EXCHANGERATES__CURRENCYFREAKS__APIKEY= \
  --from-literal=EXCHANGERATES__FREECURRENCYAPI__APIKEY= --from-literal=EXCHANGERATES__OPENEXCHANGERATES__APIKEY=
echo "Done."
```

## 3.2 Run the script

```bash
source ./openlm-install.env
bash ./create-openlm-secrets.sh
```

Every line must say `ok`. If the script stops with `load openlm-install.env first` or a variable name, that variable is empty in your worksheet.

## 3.3 Add the TLS certificate

Store your certificate in a secret called `openlm-lb-cert`. The ingress serves it from there:

```bash
kubectl -n "$NS" create secret tls openlm-lb-cert --cert="$TLS_CERT_FILE" --key="$TLS_KEY_FILE"
```

Two points apply to the certificate:

- **Certificate order**: The certificate file must hold the server certificate first, then the intermediates. If your certificate comes from a private CA, add the root certificate at the end as well. [TLS certificates](https://www.openlm.com/documentation/cloud/deployment-operations/on-premise/deployment-guide/kubernetes/concepts/tls-certificates) explains why this matters for sign-in.
- **OpenShift**: The Routes use the router's certificate by default. Read [OpenShift: certificates](https://www.openlm.com/documentation/cloud/deployment-operations/on-premise/deployment-guide/kubernetes/platforms/openshift#certificates) before this step.

## Things that commonly go wrong

If a later step fails, find the symptom in this table:

| Symptom later | Cause |
|---|---|
| Services log `FormatException` or `Login failed for user` | The SQL password in a connection string wasn't base64-encoded, or `SQL_PASSWORD` has a typo. The script handles the encoding. Don't edit connection strings by hand. |
| Pods stuck in `CreateContainerConfigError` | A secret a pod expects doesn't exist. Run the script again and check every line said `ok`. |
| Certain data jobs never write any data, with no error | `MONGO_URI` ends with `/`. Remove it and run the script again. |

:::tip[Check]
```bash
kubectl -n "$NS" get secrets | grep -c "^openlm-"
```

It must print **17** (16 from the script plus `openlm-lb-cert`).
:::

:::note[Changing a password later]
Change the value in your worksheet, run the script again, then restart the OpenLM Platform pods so they read the new value: `kubectl -n openlm rollout restart deployment`. A pod reads Secrets only when it starts.
:::
