Fix secrets required injection for fastify
This commit is contained in:
@@ -12,15 +12,21 @@ declare module 'fastify' {
|
||||
}
|
||||
|
||||
// Docker secrets are mounted at /run/secrets/ by default in CapRover
|
||||
const readSecretFile = (secretName: string): string | undefined => {
|
||||
const readSecretFile = (secretName: string, logger?: any): string | undefined => {
|
||||
const secretPath = `/run/secrets/${secretName}`
|
||||
logger?.debug({ secretPath, exists: fs.existsSync(secretPath) }, `Checking secret file: ${secretName}`)
|
||||
|
||||
if (fs.existsSync(secretPath)) {
|
||||
try {
|
||||
return fs.readFileSync(secretPath, 'utf8').trim()
|
||||
const content = fs.readFileSync(secretPath, 'utf8').trim()
|
||||
logger?.info({ secretName, path: secretPath, length: content.length }, `Successfully read secret: ${secretName}`)
|
||||
return content
|
||||
} catch (error) {
|
||||
console.error(`Failed to read secret file ${secretPath}:`, error)
|
||||
logger?.error({ error, secretPath }, `Failed to read secret file ${secretPath}`)
|
||||
return undefined
|
||||
}
|
||||
} else {
|
||||
logger?.warn({ secretPath }, `Secret file does not exist: ${secretPath}`)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
@@ -28,15 +34,39 @@ const readSecretFile = (secretName: string): string | undefined => {
|
||||
export default fp(async function (fastify) {
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
|
||||
fastify.log.info({ isProd, nodeEnv: process.env.NODE_ENV }, 'Loading Privy secrets')
|
||||
|
||||
// Debug: List all files in /run/secrets/ directory
|
||||
const secretsDir = '/run/secrets'
|
||||
if (fs.existsSync(secretsDir)) {
|
||||
try {
|
||||
const files = fs.readdirSync(secretsDir)
|
||||
fastify.log.info({ files, dir: secretsDir }, 'Files found in /run/secrets/')
|
||||
} catch (error) {
|
||||
fastify.log.warn({ error }, 'Could not list /run/secrets/ directory')
|
||||
}
|
||||
} else {
|
||||
fastify.log.warn({ dir: secretsDir }, '/run/secrets/ directory does not exist')
|
||||
}
|
||||
|
||||
let appId: string
|
||||
let appSecret: string
|
||||
let authKey: string
|
||||
|
||||
if (isProd) {
|
||||
// In production, read from Docker secrets (mounted files)
|
||||
appId = readSecretFile('PRIVY_APP_ID') || process.env.PRIVY_APP_ID || ''
|
||||
appSecret = readSecretFile('PRIVY_APP_SECRET') || process.env.PRIVY_APP_SECRET || ''
|
||||
authKey = readSecretFile('PRIVY_AUTHORIZATION_KEY') || process.env.PRIVY_AUTHORIZATION_KEY || ''
|
||||
appId = readSecretFile('PRIVY_APP_ID', fastify.log) || process.env.PRIVY_APP_ID || ''
|
||||
appSecret = readSecretFile('PRIVY_APP_SECRET', fastify.log) || process.env.PRIVY_APP_SECRET || ''
|
||||
authKey = readSecretFile('PRIVY_AUTHORIZATION_KEY', fastify.log) || process.env.PRIVY_AUTHORIZATION_KEY || ''
|
||||
|
||||
fastify.log.info({
|
||||
appId: !!appId,
|
||||
appSecret: !!appSecret,
|
||||
authKey: !!authKey,
|
||||
appIdLength: appId.length,
|
||||
appSecretLength: appSecret.length,
|
||||
authKeyLength: authKey.length
|
||||
}, 'Privy secrets loaded from Docker secrets')
|
||||
} else {
|
||||
// In non-production, use env vars or file paths
|
||||
const readMaybeFile = (envKey: string, fileKey: string): string | undefined => {
|
||||
@@ -51,13 +81,14 @@ export default fp(async function (fastify) {
|
||||
}
|
||||
|
||||
if (!appId || !appSecret || !authKey) {
|
||||
fastify.log.warn('Privy secrets not fully resolved at plugin load.')
|
||||
fastify.log.warn({
|
||||
fastify.log.error({
|
||||
appId: !!appId,
|
||||
appSecret: !!appSecret,
|
||||
authKey: !!authKey,
|
||||
isProd
|
||||
}, 'Privy secrets status')
|
||||
isProd,
|
||||
nodeEnv: process.env.NODE_ENV
|
||||
}, 'Privy secrets not fully resolved at plugin load')
|
||||
throw new Error('Missing required Privy secrets. Check Docker secrets are mounted correctly.')
|
||||
}
|
||||
|
||||
fastify.decorate('privySecrets', {
|
||||
@@ -66,5 +97,9 @@ export default fp(async function (fastify) {
|
||||
authKey
|
||||
})
|
||||
|
||||
fastify.log.info('Privy secrets decorated on Fastify instance')
|
||||
fastify.log.info({
|
||||
appId: appId.substring(0, 10) + '...',
|
||||
appSecret: appSecret.substring(0, 10) + '...',
|
||||
authKey: authKey.substring(0, 20) + '...'
|
||||
}, 'Privy secrets decorated on Fastify instance')
|
||||
}, { name: 'privy-secrets' })
|
||||
|
||||
@@ -86,9 +86,16 @@ export const autoConfig = {
|
||||
* @see {@link https://github.com/fastify/fastify-env}
|
||||
*/
|
||||
export default fp(async (fastify) => {
|
||||
// In production, Privy secrets come from Docker secrets (mounted files), not env vars
|
||||
// Make them optional in the schema to avoid validation errors
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
const required = isProd
|
||||
? ['COOKIE_SECRET'] // In production, only require COOKIE_SECRET from env
|
||||
: ['PRIVY_APP_ID', 'PRIVY_APP_SECRET', 'PRIVY_AUTHORIZATION_KEY', 'COOKIE_SECRET']
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
required: ['PRIVY_APP_ID', 'PRIVY_APP_SECRET', 'PRIVY_AUTHORIZATION_KEY', 'COOKIE_SECRET'],
|
||||
required: required,
|
||||
properties: {
|
||||
PRIVY_APP_ID: {
|
||||
type: 'string'
|
||||
|
||||
Reference in New Issue
Block a user