Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions k8s/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Paste the output into the corresponding field in `secret.yaml`.

### 2. Update the ConfigMap

Edit `k8s/manifests/configmap.yaml` and set `NEXTAUTH_URL` to your actual domain.
Edit `k8s/manifests/configmap.yaml` and set `AUTH_URL` to your actual domain.

### 3. Set your container image

Expand Down Expand Up @@ -142,15 +142,20 @@ Create a file **outside** your git repository (e.g., `~/hrmanager-secrets.yaml`)
secrets:
data:
DATABASE_URL: "postgresql://user:pass@host:5432/hrmanager"
NEXTAUTH_SECRET: "your-nextauth-secret-min-32-chars"
GOOGLE_CLIENT_ID: "your-google-client-id"
GOOGLE_CLIENT_SECRET: "your-google-client-secret"
GITHUB_CLIENT_ID: "your-github-client-id"
GITHUB_CLIENT_SECRET: "your-github-client-secret"
MONGODB_URI: "mongodb://user:pass@host:27017/hrmanager_audit"
# Auth.js v5 reads AUTH_SECRET — the legacy NEXTAUTH_SECRET is not read.
AUTH_SECRET: "your-auth-secret-min-32-chars"
# Both fail closed in production; generate with: openssl rand -base64 32
AUDIT_HMAC_SECRET: "your-audit-hmac-secret"
TOTP_ENCRYPTION_KEY: "your-totp-encryption-key"
AUTH_GOOGLE_ID: "your-google-client-id"
AUTH_GOOGLE_SECRET: "your-google-client-secret"
AUTH_GITHUB_ID: "your-github-client-id"
AUTH_GITHUB_SECRET: "your-github-client-secret"
# The app reads MONGODB_URL — with any other name the audit trail no-ops.
MONGODB_URL: "mongodb://user:pass@host:27017/hrmanager_audit"

config:
NEXTAUTH_URL: "https://your-domain.com"
AUTH_URL: "https://your-domain.com"

ingress:
host: your-domain.com
Expand Down
29 changes: 20 additions & 9 deletions k8s/helm/hrmanager/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ affinity: {}
# -- Application environment variables (non-sensitive)
config:
NODE_ENV: "production"
NEXTAUTH_URL: "https://hrmanager.example.com"
MONGO_DB_NAME: "hrmanager_audit"
# Auth.js v5 canonical name (legacy NEXTAUTH_URL also works).
AUTH_URL: "https://hrmanager.example.com"
# Required behind the ingress — Auth.js v5 rejects proxied Host headers
# with UntrustedHost otherwise.
AUTH_TRUST_HOST: "true"
NEXT_TELEMETRY_DISABLED: "1"

# -- Sensitive environment variables.
Expand All @@ -120,14 +123,22 @@ secrets:
# If set, the 'data' block below is ignored.
existingSecret: ""
data:
# Replace all placeholder values with actual base64-encoded secrets before deploying.
# Key names match exactly what the app reads (injected verbatim via envFrom)
# — see .env.example at the repo root for the authoritative list.
DATABASE_URL: ""
NEXTAUTH_SECRET: ""
GOOGLE_CLIENT_ID: ""
GOOGLE_CLIENT_SECRET: ""
GITHUB_CLIENT_ID: ""
GITHUB_CLIENT_SECRET: ""
MONGODB_URI: ""
# Auth.js v5 session secret (v5 does not read the legacy NEXTAUTH_SECRET).
AUTH_SECRET: ""
# Fail-closed in production: audit hash chain + 2FA secret encryption.
AUDIT_HMAC_SECRET: ""
TOTP_ENCRYPTION_KEY: ""
AUTH_GOOGLE_ID: ""
AUTH_GOOGLE_SECRET: ""
AUTH_GITHUB_ID: ""
AUTH_GITHUB_SECRET: ""
# The app reads MONGODB_URL — with any other name the audit trail no-ops.
MONGODB_URL: ""
# Optional: gates /api/cron/* if scheduled via CronJob/external scheduler.
# CRON_SECRET: ""

# -- Liveness probe configuration
livenessProbe:
Expand Down
9 changes: 6 additions & 3 deletions k8s/manifests/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ metadata:
app.kubernetes.io/managed-by: kubectl
data:
NODE_ENV: "production"
NEXTAUTH_URL: "https://hrmanager.example.com"
# MongoDB connection (non-sensitive host/db part — put full URI in secret)
MONGO_DB_NAME: "hrmanager_audit"
# Auth.js v5 canonical name (the legacy NEXTAUTH_URL still works, but use the
# name the rest of the config uses).
AUTH_URL: "https://hrmanager.example.com"
# Behind the ingress the Host header is proxied — without this Auth.js v5
# rejects requests with UntrustedHost.
AUTH_TRUST_HOST: "true"
# Next.js performance tuning
NEXT_TELEMETRY_DISABLED: "1"
40 changes: 29 additions & 11 deletions k8s/manifests/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,45 @@ metadata:
type: Opaque
# All values must be base64-encoded. Example: echo -n 'myvalue' | base64
# Replace every placeholder below with your actual base64-encoded value before applying.
#
# Key names match exactly what the app reads (they are injected verbatim via
# envFrom) — see .env.example at the repo root for the authoritative list.
data:
# PostgreSQL connection string
# Replace with: echo -n 'postgresql://user:password@host:5432/hrmanager' | base64
DATABASE_URL: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# NextAuth secret (min 32 chars, generate with: openssl rand -base64 32)
# Replace with: echo -n '<your-secret>' | base64
NEXTAUTH_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
# Auth.js (NextAuth v5) session secret — the v5 name is AUTH_SECRET, not
# NEXTAUTH_SECRET (v5 does not read the legacy name; sign-in fails without this).
# Generate with: openssl rand -base64 32, then: echo -n '<your-secret>' | base64
AUTH_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# Google OAuth credentials
# Audit-log hash chain key — REQUIRED in production (the app fails closed
# without it once MongoDB is configured). Generate fresh, never reuse, never
# rotate casually (old entries verify against the key that wrote them).
AUDIT_HMAC_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# 2FA secret-encryption key (AES-256-GCM) — REQUIRED in production (2FA
# setup/verify fails closed without it). Never rotate casually — stored
# secrets decrypt only with the key that encrypted them.
TOTP_ENCRYPTION_KEY: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# Google OAuth credentials (Auth.js v5 names: AUTH_GOOGLE_*)
# Replace with: echo -n '<your-google-client-id>' | base64
GOOGLE_CLIENT_ID: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
AUTH_GOOGLE_ID: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
# Replace with: echo -n '<your-google-client-secret>' | base64
GOOGLE_CLIENT_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
AUTH_GOOGLE_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# GitHub OAuth credentials
# GitHub OAuth credentials (Auth.js v5 names: AUTH_GITHUB_*)
# Replace with: echo -n '<your-github-client-id>' | base64
GITHUB_CLIENT_ID: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
AUTH_GITHUB_ID: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
# Replace with: echo -n '<your-github-client-secret>' | base64
GITHUB_CLIENT_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
AUTH_GITHUB_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"

# MongoDB connection string (for audit logs)
# MongoDB connection string for audit logs — the app reads MONGODB_URL
# (with any other name the audit trail silently no-ops).
# Replace with: echo -n 'mongodb://user:password@host:27017/hrmanager_audit' | base64
MONGODB_URI: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
MONGODB_URL: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
# Optional: gates the /api/cron/* endpoints (audit drain, job drain, cleanup)
# if you schedule them with a CronJob or an external scheduler.
# CRON_SECRET: "cmVwbGFjZV93aXRoX2Jhc2U2NF9lbmNvZGVkX3ZhbHVl"
Loading