Read secret from docker secrets
This commit is contained in:
@@ -1,4 +1,45 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./src/Managing.Web3Proxy/Dockerfile-web3proxy"
|
||||
}
|
||||
"dockerfilePath": "./src/Managing.Web3Proxy/Dockerfile-web3proxy",
|
||||
"preDeployFunction": function(captainAppObj, dockerUpdateObject) {
|
||||
// Define the array of all three secrets to be mounted in the container
|
||||
// File.Name must match the filename that code reads from /run/secrets/
|
||||
dockerUpdateObject.TaskTemplate.ContainerSpec.Secrets = [
|
||||
{
|
||||
// Secret 1: PRIVY_APP_ID
|
||||
File: {
|
||||
Name: "PRIVY_APP_ID", // Filename in the container at /run/secrets/PRIVY_APP_ID
|
||||
UID: '0',
|
||||
GID: '0',
|
||||
Mode: 292
|
||||
},
|
||||
SecretID: "4kk2gw2945x8hdatyhuhomtk2", // <<-- REPLACE THIS with the actual Secret ID from 'docker secret ls'
|
||||
SecretName: "privy_app_id"
|
||||
},
|
||||
{
|
||||
// Secret 2: PRIVY_APP_SECRET
|
||||
File: {
|
||||
Name: "PRIVY_APP_SECRET", // Filename in the container at /run/secrets/PRIVY_APP_SECRET
|
||||
UID: '0',
|
||||
GID: '0',
|
||||
Mode: 292
|
||||
},
|
||||
SecretID: "y81woaa2388zidk35gul7y9n6", // <<-- REPLACE THIS with the actual Secret ID from 'docker secret ls'
|
||||
SecretName: "privy_app_secret"
|
||||
},
|
||||
{
|
||||
// Secret 3: PRIVY_AUTHORIZATION_KEY
|
||||
File: {
|
||||
Name: "PRIVY_AUTHORIZATION_KEY", // Filename in the container at /run/secrets/PRIVY_AUTHORIZATION_KEY
|
||||
UID: '0',
|
||||
GID: '0',
|
||||
Mode: 292
|
||||
},
|
||||
SecretID: "spnc1vle5q560jsoy72ng0vtc", // <<-- REPLACE THIS with the actual Secret ID from 'docker secret ls'
|
||||
SecretName: "privy_auth_key"
|
||||
}
|
||||
];
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,22 @@
|
||||
# --- Stage 1: Build & Install Dependencies ---
|
||||
FROM node:18-alpine AS builder
|
||||
# Use an official Node.js image as the base
|
||||
FROM node:22.14.0-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package.json and lock file (if used) from source subdir
|
||||
COPY /src/Managing.Web3Proxy/package*.json ./
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
# Install dependencies (development dependencies are fine here)
|
||||
RUN npm ci --no-audit --fund=false
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY src/Managing.Web3Proxy/ .
|
||||
|
||||
# Run the build script
|
||||
RUN npm run build
|
||||
|
||||
# --- Stage 2: Production Runtime ---
|
||||
FROM node:22.14.0-alpine AS production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy essential files from the builder stage
|
||||
COPY --from=builder /app/package*.json ./
|
||||
COPY --from=builder /app/node_modules/ ./node_modules/
|
||||
# Copy the compiled application code (assuming 'dist' is the output folder)
|
||||
COPY --from=builder /app/dist/ ./dist/
|
||||
|
||||
# Set production environment again for the runtime stage
|
||||
ENV NODE_ENV production
|
||||
|
||||
EXPOSE 4111
|
||||
|
||||
# Start the application from the compiled output
|
||||
CMD ["fastify", "start", "-l", "info", "dist/app.js"]
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# COPY package*.json ./
|
||||
COPY /src/Managing.Web3Proxy/package.json ./
|
||||
|
||||
# Declaring env
|
||||
ENV NODE_ENV production
|
||||
|
||||
# Install dependencies with the --legacy-peer-deps flag to bypass peer dependency conflicts
|
||||
RUN npm install
|
||||
|
||||
COPY src/Managing.Web3Proxy/ .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 4111
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
80
src/Managing.Web3Proxy/package-lock.json
generated
80
src/Managing.Web3Proxy/package-lock.json
generated
@@ -9,7 +9,6 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bitwarden/sdk-napi": "1.0.0",
|
||||
"@fastify/autoload": "^6.0.0",
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@fastify/cors": "^11.0.0",
|
||||
@@ -82,85 +81,6 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-napi": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-napi/-/sdk-napi-1.0.0.tgz",
|
||||
"integrity": "sha512-KrOXiuuQdVBvIM4l7XGrKl8otA9tSEKHjRQr0nF71eyCmIDzOV2kt/gchgLK42exGGuD/JcmmgnXx/j+U6W/+g==",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@bitwarden/sdk-napi-darwin-arm64": "1.0.0",
|
||||
"@bitwarden/sdk-napi-darwin-x64": "1.0.0",
|
||||
"@bitwarden/sdk-napi-linux-x64-gnu": "1.0.0",
|
||||
"@bitwarden/sdk-napi-win32-x64-msvc": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-napi-darwin-arm64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-napi-darwin-arm64/-/sdk-napi-darwin-arm64-1.0.0.tgz",
|
||||
"integrity": "sha512-0W6P2VByGFqYIf6bkI7qKWlXPGhG9KFibrN14pvllFIkbNRaz3hktMOLJ/JdWZVmdHrz0R5xmAVldbIWNMjFOA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-napi-darwin-x64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-napi-darwin-x64/-/sdk-napi-darwin-x64-1.0.0.tgz",
|
||||
"integrity": "sha512-Esyg8sktE50U+g12lL/xe68hgc5y78jPPV9maNcKTO9EWdde4RIx9u3xEpbYk5fyHaeMFXdo3TK8A8qLD34X5w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-napi-linux-x64-gnu": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-napi-linux-x64-gnu/-/sdk-napi-linux-x64-gnu-1.0.0.tgz",
|
||||
"integrity": "sha512-PBGEOq9saYuBBthCq5jAr7eQSyEmQylB+kwsuT0j666VXT124a3YjDGgobPYaR9KN/IRDQ5h2Tysuy1pojx10A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@bitwarden/sdk-napi-win32-x64-msvc": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@bitwarden/sdk-napi-win32-x64-msvc/-/sdk-napi-win32-x64-msvc-1.0.0.tgz",
|
||||
"integrity": "sha512-cu92XYjsOWEVECyohGtLxiXcMJMVui+nDJtyNg52iGDeAzWQ7QZh0/bcjkymTCuGoqRD3sT0cCs+5PbW66K2XQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz",
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
"author": "Oda",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bitwarden/sdk-napi": "1.0.0",
|
||||
"@fastify/autoload": "^6.0.0",
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@fastify/cors": "^11.0.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fp from 'fastify-plugin'
|
||||
import {getSecret} from '../../utils/bitwarden.js'
|
||||
import fs from 'fs'
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
@@ -11,24 +11,53 @@ declare module 'fastify' {
|
||||
}
|
||||
}
|
||||
|
||||
// Docker secrets are mounted at /run/secrets/ by default in CapRover
|
||||
const readSecretFile = (secretName: string): string | undefined => {
|
||||
const secretPath = `/run/secrets/${secretName}`
|
||||
if (fs.existsSync(secretPath)) {
|
||||
try {
|
||||
return fs.readFileSync(secretPath, 'utf8').trim()
|
||||
} catch (error) {
|
||||
console.error(`Failed to read secret file ${secretPath}:`, error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export default fp(async function (fastify) {
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
|
||||
// Resolve secrets
|
||||
const [authKeyBw, appIdBw, appSecretBw] = isProd
|
||||
? await Promise.all([
|
||||
getSecret('PRIVY_AUTHORIZATION_KEY'),
|
||||
getSecret('PRIVY_APP_ID'),
|
||||
getSecret('PRIVY_APP_SECRET')
|
||||
])
|
||||
: [undefined, undefined, undefined]
|
||||
let appId: string
|
||||
let appSecret: string
|
||||
let authKey: string
|
||||
|
||||
const appId = appIdBw || process.env.PRIVY_APP_ID || ''
|
||||
const appSecret = appSecretBw || process.env.PRIVY_APP_SECRET || ''
|
||||
const authKey = authKeyBw || process.env.PRIVY_AUTHORIZATION_KEY || ''
|
||||
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 || ''
|
||||
} else {
|
||||
// In non-production, use env vars or file paths
|
||||
const readMaybeFile = (envKey: string, fileKey: string): string | undefined => {
|
||||
const filePath = process.env[fileKey]
|
||||
if (filePath && fs.existsSync(filePath)) return fs.readFileSync(filePath, 'utf8').trim()
|
||||
return process.env[envKey]
|
||||
}
|
||||
|
||||
appId = readMaybeFile('PRIVY_APP_ID', 'PRIVY_APP_ID_FILE') || ''
|
||||
appSecret = readMaybeFile('PRIVY_APP_SECRET', 'PRIVY_APP_SECRET_FILE') || ''
|
||||
authKey = readMaybeFile('PRIVY_AUTHORIZATION_KEY', 'PRIVY_AUTHORIZATION_KEY_FILE') || ''
|
||||
}
|
||||
|
||||
if (!appId || !appSecret || !authKey) {
|
||||
fastify.log.warn('Privy secrets not fully resolved at plugin load.')
|
||||
fastify.log.warn({
|
||||
appId: !!appId,
|
||||
appSecret: !!appSecret,
|
||||
authKey: !!authKey,
|
||||
isProd
|
||||
}, 'Privy secrets status')
|
||||
}
|
||||
|
||||
fastify.decorate('privySecrets', {
|
||||
@@ -39,5 +68,3 @@ export default fp(async function (fastify) {
|
||||
|
||||
fastify.log.info('Privy secrets decorated on Fastify instance')
|
||||
}, { name: 'privy-secrets' })
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import {PrivyClient} from '@privy-io/server-auth'
|
||||
import {ethers} from 'ethers'
|
||||
import dotenv from 'dotenv'
|
||||
import fs from 'fs'
|
||||
import {PRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_AUTHORIZATION_KEY} from '../../utils/privy-secrets.js'
|
||||
import Token from '../../generated/gmxsdk/abis/Token.json' with {type: 'json'}
|
||||
import {ARBITRUM} from '../../generated/gmxsdk/configs/chains.js'
|
||||
import {TOKENS} from '../../generated/gmxsdk/configs/tokens.js'
|
||||
@@ -96,7 +95,7 @@ export async function getAuthorizationSignature({url, body}: {url: string; body:
|
||||
url,
|
||||
body,
|
||||
headers: {
|
||||
'privy-app-id': process.env.NODE_ENV === 'production' ? (PRIVY_APP_ID ?? process.env.PRIVY_APP_ID) : process.env.PRIVY_APP_ID
|
||||
'privy-app-id': process.env.PRIVY_APP_ID || ''
|
||||
}
|
||||
};
|
||||
|
||||
@@ -105,11 +104,18 @@ export async function getAuthorizationSignature({url, body}: {url: string; body:
|
||||
const serializedPayload = canonicalize(payload) as string;
|
||||
const serializedPayloadBuffer = Buffer.from(serializedPayload);
|
||||
|
||||
// Resolve authorization key: use constant in production, file/env in non-production
|
||||
// Resolve authorization key: Docker secrets in production, file/env in non-production
|
||||
let resolvedKey: string | undefined
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
resolvedKey = PRIVY_AUTHORIZATION_KEY
|
||||
// In production, read from Docker secrets mounted at /run/secrets/
|
||||
const secretPath = '/run/secrets/PRIVY_AUTHORIZATION_KEY'
|
||||
if (fs.existsSync(secretPath)) {
|
||||
resolvedKey = fs.readFileSync(secretPath, 'utf8').trim()
|
||||
} else {
|
||||
resolvedKey = process.env.PRIVY_AUTHORIZATION_KEY
|
||||
}
|
||||
} else {
|
||||
// Non-production: allow file fallback
|
||||
const filePath = process.env.PRIVY_AUTHORIZATION_KEY_FILE
|
||||
const fromFile = filePath && fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8').trim() : undefined
|
||||
resolvedKey = fromFile || process.env.PRIVY_AUTHORIZATION_KEY || undefined
|
||||
@@ -146,13 +152,21 @@ export const makePrivyRequest = async <T>(
|
||||
method: 'GET' | 'POST' = 'POST'
|
||||
): Promise<T> => {
|
||||
try {
|
||||
// Use constants in production, env in non-production
|
||||
const appId = process.env.NODE_ENV === 'production'
|
||||
? (PRIVY_APP_ID ?? process.env.PRIVY_APP_ID ?? "")
|
||||
: (process.env.PRIVY_APP_ID ?? "")
|
||||
const appSecret = process.env.NODE_ENV === 'production'
|
||||
? (PRIVY_APP_SECRET ?? process.env.PRIVY_APP_SECRET ?? "")
|
||||
: (process.env.PRIVY_APP_SECRET ?? "")
|
||||
// Resolve secrets: Docker secrets in production, env in non-production
|
||||
let appId: string
|
||||
let appSecret: string
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
// In production, read from Docker secrets mounted at /run/secrets/
|
||||
const appIdPath = '/run/secrets/PRIVY_APP_ID'
|
||||
const appSecretPath = '/run/secrets/PRIVY_APP_SECRET'
|
||||
appId = (fs.existsSync(appIdPath) ? fs.readFileSync(appIdPath, 'utf8').trim() : undefined) || process.env.PRIVY_APP_ID || ''
|
||||
appSecret = (fs.existsSync(appSecretPath) ? fs.readFileSync(appSecretPath, 'utf8').trim() : undefined) || process.env.PRIVY_APP_SECRET || ''
|
||||
} else {
|
||||
// Non-production: use env vars
|
||||
appId = process.env.PRIVY_APP_ID || ''
|
||||
appSecret = process.env.PRIVY_APP_SECRET || ''
|
||||
}
|
||||
|
||||
let headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
import Fastify from 'fastify'
|
||||
import './bootstrap/privy-secrets.js'
|
||||
import fp from 'fastify-plugin'
|
||||
import {createClient, RedisClientType} from 'redis'
|
||||
|
||||
@@ -15,8 +14,6 @@ import closeWithGrace from 'close-with-grace'
|
||||
|
||||
// Import your application as a normal plugin.
|
||||
import serviceApp from './app.js'
|
||||
// Import Privy secrets initialization
|
||||
import {initializePrivySecrets} from './utils/privy-secrets.js'
|
||||
|
||||
// Idempotency storage using Redis
|
||||
interface IdempotencyEntry {
|
||||
@@ -169,9 +166,6 @@ const app = Fastify({
|
||||
})
|
||||
|
||||
async function init () {
|
||||
// Initialize Privy secrets from Bitwarden (production) or env (non-production)
|
||||
await initializePrivySecrets()
|
||||
|
||||
// Initialize Redis connection
|
||||
await initializeRedis()
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
import {BitwardenClient, ClientSettings, DeviceType} from '@bitwarden/sdk-napi'
|
||||
|
||||
type SecretFetcher = (nameOrId: string) => Promise<string | undefined>
|
||||
|
||||
let clientPromise: Promise<BitwardenClient> | null = null
|
||||
const secretCache = new Map<string, string>()
|
||||
|
||||
function getClient(): Promise<BitwardenClient> {
|
||||
if (clientPromise) return clientPromise
|
||||
|
||||
clientPromise = (async () => {
|
||||
const accessToken = process.env.BITWARDEN_ACCESS_TOKEN
|
||||
if (!accessToken) throw new Error('BITWARDEN_ACCESS_TOKEN is not set')
|
||||
|
||||
const settings: ClientSettings = {
|
||||
apiUrl: process.env.BITWARDEN_API_URL || 'https://vault.bitwarden.com/api',
|
||||
identityUrl: process.env.BITWARDEN_IDENTITY_URL || 'https://vault.bitwarden.com/identity',
|
||||
userAgent: 'Managing-Web3Proxy',
|
||||
deviceType: DeviceType.SDK,
|
||||
}
|
||||
|
||||
const client = new BitwardenClient(settings)
|
||||
const stateFile = process.env.BITWARDEN_STATE_FILE || '/tmp/bw-sdk-state.json'
|
||||
await client.auth().loginAccessToken(accessToken, stateFile)
|
||||
return client
|
||||
})()
|
||||
|
||||
return clientPromise
|
||||
}
|
||||
|
||||
export const getSecret: SecretFetcher = async (nameOrId: string) => {
|
||||
if (secretCache.has(nameOrId)) return secretCache.get(nameOrId)
|
||||
|
||||
const client = await getClient()
|
||||
const organizationId = process.env.BITWARDEN_ORGANIZATION_ID
|
||||
|
||||
// Try fetch by ID first
|
||||
try {
|
||||
const byId = await client.secrets().get(nameOrId)
|
||||
if (byId?.value) {
|
||||
secretCache.set(nameOrId, byId.value)
|
||||
return byId.value
|
||||
}
|
||||
} catch {}
|
||||
|
||||
// Optional: fetch by configured secret id env
|
||||
const envKey = process.env[`BITWARDEN_SECRET_ID_${nameOrId}`]
|
||||
if (envKey) {
|
||||
try {
|
||||
const res = await client.secrets().get(envKey)
|
||||
if (res?.value) {
|
||||
secretCache.set(nameOrId, res.value)
|
||||
return res.value
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// If we have organization_id, try listing secrets and finding by name/key
|
||||
if (organizationId) {
|
||||
try {
|
||||
const secretsList = await client.secrets().list(organizationId)
|
||||
if (secretsList?.data) {
|
||||
// Find secret by key (name) matching nameOrId
|
||||
const found = secretsList.data.find((s: any) => s.key === nameOrId || s.id === nameOrId)
|
||||
if (found) {
|
||||
// Fetch the full secret by ID to get the value
|
||||
try {
|
||||
const secret = await client.secrets().get(found.id)
|
||||
if (secret?.value) {
|
||||
secretCache.set(nameOrId, secret.value)
|
||||
return secret.value
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to list secrets for organization ${organizationId}:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function clearSecretCache() {
|
||||
secretCache.clear()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import {getSecret} from './bitwarden.js'
|
||||
|
||||
let PRIVY_APP_ID: string | undefined
|
||||
let PRIVY_APP_SECRET: string | undefined
|
||||
let PRIVY_AUTHORIZATION_KEY: string | undefined
|
||||
let initialized = false
|
||||
|
||||
// Initialize secrets from Bitwarden in production
|
||||
export async function initializePrivySecrets(): Promise<void> {
|
||||
if (initialized) return
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
try {
|
||||
const [authKey, appId, appSecret] = await Promise.all([
|
||||
getSecret('PRIVY_AUTHORIZATION_KEY'),
|
||||
getSecret('PRIVY_APP_ID'),
|
||||
getSecret('PRIVY_APP_SECRET')
|
||||
])
|
||||
|
||||
console.log('appId', appId);
|
||||
|
||||
PRIVY_AUTHORIZATION_KEY = authKey || process.env.PRIVY_AUTHORIZATION_KEY
|
||||
PRIVY_APP_ID = appId || process.env.PRIVY_APP_ID
|
||||
PRIVY_APP_SECRET = appSecret || process.env.PRIVY_APP_SECRET
|
||||
} catch (error) {
|
||||
console.error('Failed to load Privy secrets from Bitwarden:', error)
|
||||
// Fallback to env vars
|
||||
PRIVY_AUTHORIZATION_KEY = process.env.PRIVY_AUTHORIZATION_KEY
|
||||
PRIVY_APP_ID = process.env.PRIVY_APP_ID
|
||||
PRIVY_APP_SECRET = process.env.PRIVY_APP_SECRET
|
||||
}
|
||||
} else {
|
||||
// In non-production, use env vars directly
|
||||
PRIVY_AUTHORIZATION_KEY = process.env.PRIVY_AUTHORIZATION_KEY
|
||||
PRIVY_APP_ID = process.env.PRIVY_APP_ID
|
||||
PRIVY_APP_SECRET = process.env.PRIVY_APP_SECRET
|
||||
}
|
||||
|
||||
initialized = true
|
||||
}
|
||||
|
||||
export { PRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_AUTHORIZATION_KEY }
|
||||
|
||||
Reference in New Issue
Block a user