# How to store application secrets and inject them at runtime

Source: https://docs.quake.ai/docs/security/how-to/inject-app-secrets
Markdown: https://docs.quake.ai/docs/security/how-to/inject-app-secrets.md

---

# How to store application secrets and inject them at runtime

Keep database passwords, API tokens, and signing keys out of git by injecting them at deploy time. Quake AI does not run a managed secrets manager like AWS Secrets Manager. Use CI secrets plus environment files on VMs, Kubernetes Secret objects on clusters, or self-hosted Vault for team-scale rotation.

## Choose a pattern

| Workload | Pattern | Rotation |
|---|---|---|
| VM + systemd service | CI secret → SSH → `/etc/myapp/env` | Redeploy from CI with new values |
| VM + Docker | CI secret → `docker run -e` or env file | Redeploy container |
| Kubernetes | `Secret` + `envFrom` or mounted volume | `kubectl apply` or Helm values from CI |
| Many services / teams | HashiCorp Vault on a Quake AI VM | Vault policies and dynamic secrets |

## VM: inject with CI and systemd

1. Store secrets in GitHub Actions or GitLab CI variables (masked).
2. During deploy ([application CI/CD](/docs/automation/how-to/app-cicd-vm)), write a root-owned env file:

```bash
ssh "$DEPLOY_USER@$DEPLOY_HOST" 'sudo install -D -m 600 /dev/stdin /etc/myapp/env' <<EOF
DATABASE_URL=${{ secrets.DATABASE_URL }}
API_KEY=${{ secrets.API_KEY }}
EOF
```

The `-D` flag creates `/etc/myapp` if it does not exist, so this step succeeds on a fresh VM without a separate `mkdir`.

3. Reference the file in the unit file:

```ini
[Service]
EnvironmentFile=/etc/myapp/env
```

4. Reload systemd and restart the service.

Never commit `/etc/myapp/env` to git or bake it into a custom image.

## Kubernetes: Secret and deployment

```bash
kubectl create secret generic myapp-secrets \
  --from-literal=DATABASE_URL="$DATABASE_URL" \
  --from-literal=API_KEY="$API_KEY" \
  -n my-namespace
```

```yaml
envFrom:
  - secretRef:
      name: myapp-secrets
```

For private registry credentials, use [image pull secrets](/docs/kubernetes/how-to/use-container-registry).

## Self-hosted Vault (advanced)

Run [Vault](https://developer.hashicorp.com/vault/docs) on a dedicated instance with persistent block storage. Applications authenticate with AppRole or Kubernetes auth. This pattern suits teams that already operate Vault; it is more moving parts than CI-injected env files.

## Rotate secrets

1. Generate a new credential at the provider (database, API vendor).
2. Update CI variables.
3. Redeploy VMs or roll Kubernetes Deployments.
4. Revoke the old credential after traffic stabilizes.

## See also

- [Secrets management](/docs/security/secrets-management)
- [How to deploy an application to a Quake AI VM from CI](/docs/automation/how-to/app-cicd-vm)
- [How to send transactional email from a Quake AI workload](/docs/operate/how-to/send-transactional-email)
- [Generate app credentials](/docs/tools/generate-app-credentials)
