Files
Lorenzo SanesiandClaude Opus 5.5 b83ce039fb
Deploy stack su Proxmox / deploy (push) Failing after 3s
Piattaforma ITI TECHNOLOGY: monorepo, Medusa, API, sito, area riservata e deploy
Monorepo npm con apps/public (Angular SSR), apps/private (Angular SPA),
apps/api (Fastify), packages/shared e packages/styles; Medusa 2.21 in medusa/;
infrastruttura Docker (Postgres PostGIS+pgvector, Redis, Caddy, backup) e
workflow Gitea Actions per il deploy via SSH a ogni push su master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jQyT6dR9czzGwqb7FkG6u
2026-10-20 09:30:48 +02:00

118 lines
3.8 KiB
TypeScript

import { loadEnv, defineConfig } from '@medusajs/framework/utils'
loadEnv(process.env.NODE_ENV || 'development', process.cwd())
const redisUrl = process.env.REDIS_URL
// Stripe: il provider lancia un errore all'avvio se manca apiKey, quindi si registra solo se configurato.
// Provider ID risultante: pp_stripe_stripe. Webhook: {MEDUSA_BACKEND_URL}/hooks/payment/stripe_stripe
const stripeApiKey = process.env.STRIPE_API_KEY
if (!stripeApiKey) {
console.warn('[medusa-config] STRIPE_API_KEY non impostata: provider di pagamento Stripe disabilitato')
}
// Produzione: senza JWT_SECRET/COOKIE_SECRET Medusa userebbe il default "supersecret" (token del dashboard
// falsificabili). Si rifiuta di partire con segreti mancanti o corti.
if (process.env.NODE_ENV === 'production') {
const weak = ['JWT_SECRET', 'COOKIE_SECRET', 'INTERNAL_API_SECRET', 'WEBHOOK_SECRET'].filter(
(name) => (process.env[name]?.length ?? 0) < 32
)
if (weak.length) {
throw new Error(`[medusa-config] segreti mancanti o più corti di 32 caratteri: ${weak.join(', ')}`)
}
if (stripeApiKey && !process.env.STRIPE_WEBHOOK_SECRET) {
console.warn('[medusa-config] STRIPE_WEBHOOK_SECRET non impostata: i webhook Stripe verranno rifiutati (firma non verificabile)')
}
}
module.exports = defineConfig({
projectConfig: {
// Postgres dedicato a Medusa (database iti_medusa, vedi docker-compose.dev.yml)
databaseUrl: process.env.DATABASE_URL,
redisUrl,
http: {
storeCors: process.env.STORE_CORS!,
adminCors: process.env.ADMIN_CORS!,
authCors: process.env.AUTH_CORS!,
jwtSecret: process.env.JWT_SECRET,
cookieSecret: process.env.COOKIE_SECRET,
},
},
modules: [
// File: storage locale su disco. Medusa serve sempre <backend>/static su /static:
// se FILE_UPLOAD_DIR punta altrove (es. volume Docker in produzione) va servita da Caddy
// e FILE_BACKEND_URL deve puntare a quell'URL pubblico.
{
resolve: '@medusajs/medusa/file',
options: {
providers: [
{
resolve: '@medusajs/medusa/file-local',
id: 'local',
options: {
upload_dir: process.env.FILE_UPLOAD_DIR || 'static',
backend_url: process.env.FILE_BACKEND_URL || 'http://localhost:9000/static',
},
},
],
},
},
...(stripeApiKey
? [
{
resolve: '@medusajs/medusa/payment',
options: {
providers: [
{
resolve: '@medusajs/medusa/payment-stripe',
id: 'stripe',
options: {
apiKey: stripeApiKey,
webhookSecret: process.env.STRIPE_WEBHOOK_SECRET,
// Cattura automatica all'autorizzazione: niente capture manuale dal dashboard
capture: true,
},
},
],
},
},
]
: []),
// Moduli Redis (configurazione consigliata dalla guida di deployment Medusa)
{
resolve: '@medusajs/medusa/caching',
options: {
providers: [
{
resolve: '@medusajs/caching-redis',
id: 'caching-redis',
is_default: true,
options: { redisUrl },
},
],
},
},
{
resolve: '@medusajs/medusa/event-bus-redis',
options: { redisUrl },
},
{
resolve: '@medusajs/medusa/workflow-engine-redis',
options: { redis: { redisUrl } },
},
{
resolve: '@medusajs/medusa/locking',
options: {
providers: [
{
resolve: '@medusajs/medusa/locking-redis',
id: 'locking-redis',
is_default: true,
options: { redisUrl },
},
],
},
},
],
})