chore(k8s): unify secrets template into one k8s/secrets.example.yaml
Replace the single-secret towerops-llm template with one multi-document YAML covering every Secret the Deployment references: towerops-secrets, towerops-db, towerops-aws, towerops-redis, towerops-billing, towerops-llm. Workflow: copy k8s/secrets.example.yaml to k8s/secrets.yaml (which is gitignored), fill in real values, kubectl apply. Real values never land in git.
This commit is contained in:
parent
b6513ec301
commit
32c9575952
4 changed files with 106 additions and 35 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -99,7 +99,7 @@ profiles.json
|
||||||
# Stride API credentials (contains secrets - never commit)
|
# Stride API credentials (contains secrets - never commit)
|
||||||
.stride_auth.md
|
.stride_auth.md
|
||||||
|
|
||||||
# Local k8s secret manifest — copy from any *.example.yaml in k8s/, fill in
|
# Local k8s secret manifest — copy from k8s/secrets.example.yaml, fill in
|
||||||
# real values, then `kubectl apply -f k8s/secrets.yaml`. Never commit.
|
# real values, then `kubectl apply -f k8s/secrets.yaml`. Never commit.
|
||||||
k8s/secrets.yaml
|
k8s/secrets.yaml
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,22 +13,27 @@ Required secrets in the `towerops` namespace:
|
||||||
Optional secrets:
|
Optional secrets:
|
||||||
- `towerops-llm` - DeepSeek API credentials for LLM-powered insight enrichment.
|
- `towerops-llm` - DeepSeek API credentials for LLM-powered insight enrichment.
|
||||||
Optional — when missing, insights still display without an AI summary.
|
Optional — when missing, insights still display without an AI summary.
|
||||||
|
- `towerops-billing` - Stripe credentials. Every key is optional in the deployment.
|
||||||
|
|
||||||
### Local secrets workflow
|
### Local secrets workflow
|
||||||
|
|
||||||
The file `k8s/secrets.yaml` is gitignored. Use it to keep one-or-more
|
`k8s/secrets.yaml` is gitignored. Use it to keep every `Secret` manifest
|
||||||
`Secret` manifests with real values for hand-application against the
|
the deployment needs in one place for hand-application against the
|
||||||
cluster. Bootstrap from any `*.example.yaml` template:
|
cluster. Bootstrap from the unified template:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp k8s/towerops-llm-secret.example.yaml k8s/secrets.yaml
|
cp k8s/secrets.example.yaml k8s/secrets.yaml
|
||||||
# edit k8s/secrets.yaml — fill in DEEPSEEK_API_KEY, etc.
|
# edit k8s/secrets.yaml — fill in DATABASE_URL, AWS keys, RELEASE_COOKIE,
|
||||||
|
# SECRET_KEY_BASE, CLOAK_KEY, and any optional ones (DEEPSEEK_API_KEY,
|
||||||
|
# Stripe keys, etc.)
|
||||||
kubectl apply -f k8s/secrets.yaml
|
kubectl apply -f k8s/secrets.yaml
|
||||||
kubectl rollout restart deployment/towerops -n towerops
|
kubectl rollout restart deployment/towerops -n towerops
|
||||||
```
|
```
|
||||||
|
|
||||||
`k8s/secrets.yaml` may contain multiple `---`-separated documents if you
|
`k8s/secrets.yaml` is one multi-document YAML covering every Secret the
|
||||||
need more than one secret. It is excluded from git via `.gitignore`.
|
deployment references (towerops-secrets, towerops-db, towerops-aws,
|
||||||
|
towerops-redis, towerops-billing, towerops-llm). It is excluded from git
|
||||||
|
via `.gitignore` so real values never accidentally land in source.
|
||||||
|
|
||||||
For local development, the project root `.envrc` is used by direnv.
|
For local development, the project root `.envrc` is used by direnv.
|
||||||
|
|
||||||
|
|
|
||||||
93
k8s/secrets.example.yaml
Normal file
93
k8s/secrets.example.yaml
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
# Unified template for every Kubernetes Secret the towerops Deployment
|
||||||
|
# references. Bootstrap your local copy:
|
||||||
|
#
|
||||||
|
# cp k8s/secrets.example.yaml k8s/secrets.yaml
|
||||||
|
# # edit k8s/secrets.yaml — fill in real values
|
||||||
|
# kubectl apply -f k8s/secrets.yaml
|
||||||
|
# kubectl rollout restart deployment/towerops -n towerops
|
||||||
|
#
|
||||||
|
# k8s/secrets.yaml is gitignored — never commit real secrets. Real
|
||||||
|
# values live in 1Password.
|
||||||
|
#
|
||||||
|
# Secret-by-secret:
|
||||||
|
# * towerops-secrets — application secrets (REQUIRED)
|
||||||
|
# * towerops-db — Postgres connection (REQUIRED, envFrom)
|
||||||
|
# * towerops-aws — AWS credentials (REQUIRED, envFrom)
|
||||||
|
# * towerops-redis — Redis connection (REQUIRED, envFrom)
|
||||||
|
# * towerops-billing — Stripe (optional)
|
||||||
|
# * towerops-llm — DeepSeek API key for insight enrichment (optional)
|
||||||
|
# * gitlab-registry — Docker registry creds (image pull, separate workflow)
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-secrets
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
RELEASE_COOKIE: ""
|
||||||
|
# Generate with: mix phx.gen.secret (or openssl rand -base64 64)
|
||||||
|
SECRET_KEY_BASE: ""
|
||||||
|
# Generate with: openssl rand -base64 32
|
||||||
|
# CRITICAL: losing this makes encrypted columns unrecoverable.
|
||||||
|
CLOAK_KEY: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-db
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Full ecto:// URL — used envFrom in the deployment.
|
||||||
|
DATABASE_URL: "ecto://USER:PASSWORD@HOST:5432/DATABASE"
|
||||||
|
# Optional pool tuning (defaults applied in runtime.exs if unset)
|
||||||
|
POOL_SIZE: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-aws
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
AWS_ACCESS_KEY_ID: ""
|
||||||
|
AWS_SECRET_ACCESS_KEY: ""
|
||||||
|
AWS_REGION: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-redis
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# envFrom block injects whatever keys exist here.
|
||||||
|
REDIS_URL: "redis://HOST:6379/0"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-billing
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# Stripe — every key is optional; the deployment marks them optional: true.
|
||||||
|
STRIPE_SECRET_KEY: ""
|
||||||
|
STRIPE_WEBHOOK_SECRET: ""
|
||||||
|
STRIPE_PRICE_ID: ""
|
||||||
|
STRIPE_METER_ID: ""
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: towerops-llm
|
||||||
|
namespace: towerops
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
# DeepSeek API key — get one at https://platform.deepseek.com/
|
||||||
|
# Without this, insight LLM enrichment stays no-op (insights still render).
|
||||||
|
DEEPSEEK_API_KEY: ""
|
||||||
|
# Optional: override the default model (default: deepseek-v4-pro).
|
||||||
|
DEEPSEEK_MODEL: ""
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
# Template for the towerops-llm secret. Apply with values filled in:
|
|
||||||
#
|
|
||||||
# kubectl create secret generic towerops-llm \
|
|
||||||
# --from-literal=DEEPSEEK_API_KEY="<your-deepseek-key>" \
|
|
||||||
# --from-literal=DEEPSEEK_MODEL="deepseek-v4-pro" \
|
|
||||||
# -n towerops
|
|
||||||
#
|
|
||||||
# Or apply this file directly after replacing the placeholder strings with
|
|
||||||
# your real values, then run: kubectl apply -f k8s/towerops-llm-secret.example.yaml
|
|
||||||
#
|
|
||||||
# This file is committed as a placeholder — DO NOT put real keys in here.
|
|
||||||
# Real values live in 1Password and are created in the cluster manually.
|
|
||||||
#
|
|
||||||
# The deployment references this secret with `optional: true`, so the app
|
|
||||||
# will start fine without it (LLM enrichment just stays no-op).
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: towerops-llm
|
|
||||||
namespace: towerops
|
|
||||||
type: Opaque
|
|
||||||
stringData:
|
|
||||||
# DeepSeek API key — get one at https://platform.deepseek.com/
|
|
||||||
DEEPSEEK_API_KEY: ""
|
|
||||||
# Optional: override the default model (default: deepseek-v4-pro)
|
|
||||||
DEEPSEEK_MODEL: ""
|
|
||||||
Loading…
Add table
Reference in a new issue