D9 key secret env
Agent Skills for d9 (Directus 9 fork) — install with: npx skills add LaWebcapsule/d9-skills
npx -y skills add LaWebcapsule/d9-skills --skill d9-key-secret-envAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Prevent d9 auth failures by ensuring both KEY and SECRET environment variables are set with distinct values.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.4 KB, as published. Nobody here has run it
d9-key-secret-env
Purpose
Prevent authentication failures in d9 (Directus 9 fork by La Webcapsule) caused by missing or identical KEY and SECRET environment variables. d9 requires BOTH variables to be set with distinct values. The server starts successfully without them, but auth operations fail silently or with misleading errors, making the root cause hard to diagnose.
Triggers
- Configuring a new d9 instance (Docker, bare metal, or cloud deployment).
- Debugging auth/login failures where the d9 server starts and responds to requests but tokens are invalid or login returns cryptic errors.
- Reviewing a
docker-compose.yml,.envfile, or deployment manifest for a d9 service. - Migrating from upstream Directus 9 to d9, where prior config may only define
SECRET.
Behavior
- Check that both
KEYandSECRETare defined. Look indocker-compose.yml,.env, Kubernetes manifests, or the hosting platform's environment variable settings. - Verify the values are different.
KEYandSECRETmust not be the same string. They serve different cryptographic purposes. - Generate secure random values if missing. Use
openssl rand -hex 32(or equivalent) to produce each value. - Restart the d9 instance after setting or changing the variables.
Minimal Fix (.env)
KEY=a1b2c3d4e5f6... # openssl rand -hex 32
SECRET=f6e5d4c3b2a1... # openssl rand -hex 32 (different value)
Docker Compose Example
services:
d9:
image: d9:latest
environment:
KEY: "${D9_KEY}"
SECRET: "${D9_SECRET}"
DB_CLIENT: pg
DB_HOST: db
DB_DATABASE: d9
Generation Commands
# Linux / macOS / Git Bash on Windows
echo "KEY=$(openssl rand -hex 32)"
echo "SECRET=$(openssl rand -hex 32)"
# Node.js alternative
node -e "const c=require('crypto'); console.log('KEY='+c.randomBytes(32).toString('hex')); console.log('SECRET='+c.randomBytes(32).toString('hex'))"
Errors Prevented
- Login returns HTTP 401 or 403 with no actionable error message despite correct credentials.
- Tokens issued by d9 are rejected on subsequent requests (
INVALID_TOKEN,TOKEN_EXPIREDimmediately after issuance). - Refresh token rotation fails silently, logging users out unexpectedly.
- Server starts without errors in logs, giving the false impression that configuration is complete.
Restrictions
Hard Boundaries
- Do NOT use the same value for
KEYandSECRET. They are used for different cryptographic operations and reusing values weakens security. - Do NOT commit
KEYorSECRETvalues to version control. Use.envfiles (excluded via.gitignore), secrets managers, or platform-level environment variable injection. - Do NOT use short or predictable values (e.g.,
KEY=123,SECRET=secret). Always use cryptographically random strings of at least 32 characters.
Soft Boundaries
- Prefer
openssl rand -hex 32for generation; it produces 64-character hex strings with 256 bits of entropy. - In Docker Compose, reference variables from
.env(e.g.,${D9_KEY}) rather than hardcoding values in the YAML file. - When rotating secrets, update both
KEYandSECRETsimultaneously to avoid partial invalidation of existing sessions.
Self-Check
- Both
KEYandSECRETare defined in the environment configuration. - The two values are distinct strings.
- Values are at least 32 characters long and cryptographically random.
- Values are not committed to version control.
- The d9 instance has been restarted after setting or changing the variables.
- Login and token refresh work correctly after the fix.
Examples
Example 1: New Docker Compose Deployment
A developer sets up d9 with Docker Compose and only defines SECRET (following upstream Directus documentation).
Before (auth fails):
services:
d9:
image: d9:latest
environment:
SECRET: "my-super-secret-value"
DB_CLIENT: pg
DB_HOST: db
DB_PORT: 5432
DB_DATABASE: d9
DB_USER: d9
DB_PASSWORD: d9pass
Symptom: Server starts. Admin user can be created via bootstrap. Login POST to /auth/login returns a token, but subsequent authenticated requests fail with INVALID_TOKEN.
After (works):
services:
d9:
image: d9:latest
environment:
KEY: "4f8a1c3e7b9d2f0a5c6e8d1b3a7f9e2c4d6a8b0e1f3c5a7d9b2e4f6a8c0d2e"
SECRET: "9b2e4f6a8c0d2e4f8a1c3e7b9d2f0a5c6e8d1b3a7f9e2c4d6a8b0e1f3c5a7d"
DB_CLIENT: pg
DB_HOST: db
DB_PORT: 5432
DB_DATABASE: d9
DB_USER: d9
DB_PASSWORD: d9pass
Example 2: Bare Metal Deployment with .env (Edge Case)
A developer migrates from upstream Directus 9 to d9. Their existing .env has SECRET but not KEY. The migration completes, d9 starts, but existing user sessions break.
Before (.env):
# Carried over from Directus 9
SECRET=original-directus-secret
DB_CLIENT=sqlite3
DB_FILENAME=./data/database.sqlite
Symptom: d9 starts without errors. Existing sessions from Directus 9 are all invalid (expected after migration). New login attempts succeed intermittently or fail with "errors":[{"message":"Invalid user credentials."}] even though credentials are correct.
Diagnosis: Run node -e "console.log(process.env.KEY)" inside the d9 process context (or check the startup logs in debug mode). KEY is undefined.
After (.env):
KEY=b7c4e9a1f2d8365e0c7a4b1d9f6e3c8a5d2b7f0e4a1c6d9b3f8e5a2c7d0b4f
SECRET=original-directus-secret
DB_CLIENT=sqlite3
DB_FILENAME=./data/database.sqlite
Example 3: Kubernetes Deployment with Secrets (Edge Case)
In a Kubernetes deployment, environment variables come from a Secret resource. A team member creates the secret with only one key, or both keys reference the same secret data field.
Before (both reference the same value):
apiVersion: v1
kind: Secret
metadata:
name: d9-secrets
type: Opaque
data:
token-secret: NGY4YTFjM2U3YjlkMmYwYTVjNmU4ZDFiM2E3ZjllMmM=
---
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: d9
env:
- name: KEY
valueFrom:
secretKeyRef:
name: d9-secrets
key: token-secret # Same source as SECRET
- name: SECRET
valueFrom:
secretKeyRef:
name: d9-secrets
key: token-secret # Same source as KEY
After (distinct values):
apiVersion: v1
kind: Secret
metadata:
name: d9-secrets
type: Opaque
data:
app-key: NGY4YTFjM2U3YjlkMmYwYTVjNmU4ZDFiM2E3ZjllMmM=
app-secret: OWIyZTRmNmE4YzBkMmU0Zjh...
---
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: d9
env:
- name: KEY
valueFrom:
secretKeyRef:
name: d9-secrets
key: app-key
- name: SECRET
valueFrom:
secretKeyRef:
name: d9-secrets
key: app-secret