# The secrets an operator writes. Minted ONCE, mounted by every pod. # # ─── READ THIS BEFORE YOU GENERATE ANYTHING ─────────────────────────────────────────────────── # # There are two Secrets, and the split is not filing: `jarvis-generated` holds the values that are # random bytes and `jarvis-secrets` — this file — holds the ones that are facts about your estate. # One of those can be regenerated safely and the other cannot, so they do not share an object. # # The three keys below are here as the MANUAL path. If you would rather have them minted for you, # apply `01-secret-job.yaml` instead and leave the `VAULT_*`/`JWT_*` lines out of this file # entirely. Do not do both: `04-api.yaml` reads this Secret last on purpose, so a value typed here # wins over a generated one, and the two quietly disagreeing is the shape of the accident. # # `apps/api/init-secrets.cjs` is the Compose generator, and it must NEVER become an initContainer # here. Its guarantee that a key is minted exactly once is every writer sharing one filesystem. # Per-pod, on an `emptyDir`, each replica generates its own — and the consequence is not a crash. # Pod A seals a vault credential under a key pod B does not have; pod B reports that credential as # corrupt; both pods log nothing at boot, because from each one's point of view everything is fine. # By the time anybody notices, there are several keys in circulation and no way to tell which # entries belong to which. `apps/api/mint-k8s-secret.cjs` is the same one-shot done correctly, with # the API server's 409 standing in for the filesystem's exclusion. # # Either way, keep the output. The vault key in particular is the thing every stored credential is # encrypted under — a database backup that travelled with its own key would be a backup that # decrypts itself, which is why this lives apart from the database. # # VAULT_MASTER_KEY openssl rand -base64 32 # JWT_ACCESS_SECRET openssl rand -base64 48 # JWT_REFRESH_SECRET openssl rand -base64 48 # # In anything beyond a trial, do not commit this file with values in it. Use SealedSecrets, # ExternalSecrets, or `kubectl create secret generic` from a password manager. # ────────────────────────────────────────────────────────────────────────────────────────────── apiVersion: v1 kind: Secret metadata: name: jarvis-secrets namespace: jarvis type: Opaque stringData: # Everything in the vault is sealed under this. Lose it and the credentials are unreadable; # leak it and a database dump is enough to read them all. VAULT_MASTER_KEY: "REPLACE_ME" JWT_ACCESS_SECRET: "REPLACE_ME" JWT_REFRESH_SECRET: "REPLACE_ME" # WHEN THE VAULT KEY WAS CREATED, as an ISO 8601 timestamp or epoch seconds. # # Set it when you mint the key, and never move it afterwards. On Compose this is inferred from the # key file's modification time, which is a good answer on a volume nobody rewrites. Here it is a # wrong one: the kubelet writes a projected Secret into every pod at start, so the mtime is the # POD's age and every pod reports a key created seconds ago however old it is. # # What that number decides is narrow and serious. An instance with no accounts can have its first # super-admin claimed by whoever reaches the install screen — unless the vault key is old, which # means the database has gone missing from an instance that already existed (a bad restore, a PVC # pointed at the wrong volume) and the claim needs proof of possession instead. Without this line, # that check reads "brand new instance" on exactly the estate it exists to protect. VAULT_KEY_CREATED_AT: "REPLACE_ME" # `connection_limit` is not optional here, and it is the reason this URL is in the Secret rather # than assembled from parts. Prisma's default pool is per-process: N pods times that default will # exhaust `max_connections` long before the application is under any real load. Size it as # (max_connections − reserve) ÷ (replicas + maxSurge + jobs). DATABASE_URL: "postgresql://jarvis:REPLACE_ME@postgres.jarvis.svc.cluster.local:5432/jarvis?schema=public&connection_limit=10&pool_timeout=20" # Required to create new organizations, users or agents. Without it an instance keeps running # everything it already has and creates nothing new. See the project README. JARVIS_LICENSE_KEY: "" OPENAI_API_KEY: "REPLACE_ME"