Deploy in produzione¶
Jinbocho viene eseguito su Render (servizi applicativi + frontend) e Neon (database PostgreSQL). Questa combinazione offre uno stack completamente operativo a costo zero con i livelli gratuiti.
Architettura su Render¶
Internet
│
▼
┌─────────────────────────────────────────┐
│ jinbocho-fe (Render Static Site) │ https://jinbocho-fe.onrender.com
└──────────────────────┬──────────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────┐
│ jinbocho-api-gateway (Web Service) │ https://jinbocho-api-gateway.onrender.com
└────────────┬──────────────────────────────┘
│ Rete interna Render
┌────────┬────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ auth │ │catalog │ │ ai │ Servizi Privati (non raggiungibili da internet)
│:8001 │ │:8002 │ │:8003 │
└───┬───┘ └───┬───┘ └────────┘
│ │
▼ ▼
┌─────────┐ ┌──────────┐
│ auth_db │ │catalog_db│ Neon PostgreSQL (esterno — non su Render)
└─────────┘ └──────────┘
Solo due componenti sono pubblici: l’API gateway e il frontend. I tre servizi backend sono Servizi Privati — raggiungibili solo dalla rete interna di Render.
Step 0 — Genera i segreti¶
# JWT_SECRET_KEY — deve essere identica su auth, catalog e gateway
openssl rand -hex 32
Salva questo valore. Lo inserirai più volte. Chiamalo <JWT_SECRET> nei passi seguenti.
Step 1 — Crea i database Neon¶
Non usare il PostgreSQL integrato di Render
Il PostgreSQL gratuito di Render viene eliminato dopo circa 30 giorni. Usa Neon invece — il suo livello gratuito è persistente e non scade.
- Registrati su neon.tech → Crea progetto
- Nome:
jinbocho - Versione PostgreSQL:
16 - Regione: più vicina alla tua regione Render (es. EU-Central per Francoforte)
- Dalla console Neon → Database → Nuovo Database, crea:
auth_dbcatalog_dbai_db(opzionale — salta se non usi il servizio AI)- Per ogni database, vai su Dettagli di connessione → copia la stringa di connessione
Adattare la stringa di connessione¶
Neon fornisce una stringa di connessione come:
postgresql://user:password@ep-xxxx.eu-central-1.aws.neon.tech/auth_db?sslmode=require
Devi trasformarla prima di usarla su Render:
| Modifica | Motivo |
|---|---|
postgresql:// → postgresql+asyncpg:// |
driver asyncpg |
?sslmode=require → ?ssl=require |
asyncpg non capisce sslmode |
Risultato finale:
postgresql+asyncpg://user:password@ep-xxxx.eu-central-1.aws.neon.tech/auth_db?ssl=require
Fai questa trasformazione per ogni URL del database. Tieni privati i tre URL.
Step 2 — Distribuisci i servizi backend¶
Distribuisci in questo ordine: auth → catalog → (ai) → gateway. Il gateway ha bisogno degli URL interni degli altri servizi.
auth-service¶
- Dashboard Render → New + → Private Service
- Connetti il repository:
jinbocho-auth-v1 - Runtime: Docker
- Regione: stessa dei database Neon
- Tipo di istanza: Free (o Starter per evitare cold start)
- Docker Command: lascia vuoto (già nel Dockerfile)
- Aggiungi le variabili d’ambiente (vedi tabella sotto)
- Distribuisci
- Dopo che il deploy è completato: copia l’indirizzo interno mostrato nella pagina del servizio (formato:
http://jinbocho-auth:8001). Avrai bisogno di questo per catalog e gateway.
Variabili d’ambiente auth-service:
| Variabile | Valore |
|---|---|
DATABASE_URL |
Stringa di connessione Neon auth_db (trasformata) |
JWT_SECRET_KEY |
<JWT_SECRET> |
JWT_ALGORITHM |
HS256 |
ACCESS_TOKEN_EXPIRE_MINUTES |
30 |
REFRESH_TOKEN_EXPIRE_DAYS |
30 |
DEBUG |
false |
PORT |
8001 |
catalog-service¶
- New + → Private Service
- Repository:
jinbocho-catalog-v1, Docker, stessa regione - Aggiungi le variabili d’ambiente (vedi tabella sotto)
- Distribuisci
- Copia l’indirizzo interno dopo il deploy.
Variabili d’ambiente catalog-service:
| Variabile | Valore |
|---|---|
DATABASE_URL |
Stringa di connessione Neon catalog_db (trasformata) |
AUTH_SERVICE_URL |
Indirizzo interno di auth-service (es. http://jinbocho-auth:8001) |
JWT_SECRET_KEY |
<JWT_SECRET> — identica ad auth |
JWT_ALGORITHM |
HS256 |
GOOGLE_BOOKS_API_KEY |
La tua chiave Google Books API (ottienila gratuitamente) |
DEBUG |
false |
PORT |
8002 |
ai-service (opzionale)¶
Salta questo se non usi le funzioni AI.
- New + → Private Service
- Repository:
jinbocho-ai-v1, Docker, stessa regione
| Variabile | Valore |
|---|---|
DATABASE_URL |
Stringa di connessione Neon ai_db (trasformata) |
CATALOG_SERVICE_URL |
Indirizzo interno di catalog-service |
OPENAI_API_KEY |
La tua chiave API OpenAI |
DEBUG |
false |
PORT |
8003 |
api-gateway¶
Il gateway è l’unico componente backend pubblico.
- New + → Web Service (non Private!)
- Repository:
jinbocho-api-gateway-v1, Docker, stessa regione - Percorso health check:
/health - Aggiungi le variabili d’ambiente:
| Variabile | Valore |
|---|---|
JWT_SECRET_KEY |
<JWT_SECRET> — identica ad auth |
JWT_ALGORITHM |
HS256 |
AUTH_SERVICE_URL |
Indirizzo interno di auth-service |
CATALOG_SERVICE_URL |
Indirizzo interno di catalog-service |
AI_SERVICE_URL |
Indirizzo interno di ai-service (ometti se non distribuito) |
CORS_ORIGINS |
["https://jinbocho-fe.onrender.com"] — imposta dopo il deploy del FE |
DEBUG |
false |
- Distribuisci → Render assegna un URL pubblico come
https://jinbocho-api-gateway.onrender.com.
Salva questo URL — è ilVITE_API_BASE_URLper il frontend.
Step 3 — Distribuisci il frontend¶
- New + → Static Site
- Repository:
jinbocho-fe - Build Command:
npm ci && npm run build - Publish Directory:
dist - Aggiungi regola Redirect/Rewrite: Source
/*→ Destination/index.html→ Action Rewrite (routing SPA) - Variabile d’ambiente:
| Variabile | Valore |
|---|---|
VITE_API_BASE_URL |
URL pubblico dell’api-gateway (dallo Step 2) |
- Distribuisci → Render assegna un URL pubblico come
https://jinbocho-fe.onrender.com.
Step 4 — Chiudi il ciclo degli URL¶
Esiste una dipendenza circolare tra il gateway (che ha bisogno dell’URL del frontend per CORS) e il frontend (che ha bisogno dell’URL del gateway per le chiamate API). Risolvila ora:
- Vai su api-gateway su Render → Environment
- Imposta
CORS_ORIGINSall’URL del frontend:["https://jinbocho-fe.onrender.com"] - Clicca Save Changes → Render attiva automaticamente un rideploy
- Attendi il completamento del rideploy
Step 5 — Verifica il deployment¶
Esegui questi controlli dopo che tutti i servizi sono attivi:
GW=https://jinbocho-api-gateway.onrender.com
# 1. Health del gateway
curl $GW/health
# Atteso: {"status":"ok"}
# 2. Registra una famiglia di test
curl -X POST $GW/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"family_name":"Famiglia Test","full_name":"Alice","email":"alice@test.com","password":"Password123!"}'
# 3. Login e ottieni un token
curl -X POST $GW/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"alice@test.com","password":"Password123!"}'
# Copia l’access_token dalla risposta
# 4. Test ricerca ISBN
TOKEN="il-tuo-access-token"
curl "$GW/v1/records/isbn-lookup?isbn=9788845292613" \
-H "Authorization: Bearer $TOKEN"
Checklist di verifica completa:
- [ ]
GET /healthrestituisce{"status":"ok"} - [ ] Migrazioni Alembic applicate (controlla i log di auth e catalog: cerca il successo di
alembic upgrade head) - [ ] POST
/v1/auth/registerrestituisce{ family_id, user_id } - [ ] POST
/v1/auth/loginrestituisce{ access_token, refresh_token } - [ ] Il frontend si carica all’URL del sito statico Render
- [ ] Il login dal frontend funziona
- [ ] La ricerca ISBN restituisce metadati (la chiave Google Books è impostata)
- [ ] Nessun errore CORS nella console del browser
Alternativa: Deployment con Blueprint¶
Se preferisci Infrastructure-as-Code, il file render.yaml in jinbocho-infrastructure-v1 definisce l’intero stack:
- Aggiorna i campi
repo:inrender.yamlcon la tua org/username GitHub - Dashboard Render → New + → Blueprint → seleziona
jinbocho-infrastructure-v1 - Render crea tutti i servizi in una volta; inserisci i segreti quando richiesto
- Dopo il primo deploy, chiudi il ciclo degli URL (Step 4 sopra)
Costi e limiti del livello gratuito¶
| Componente | Provider | Costo | Limiti |
|---|---|---|---|
auth_db, catalog_db |
Neon free | €0 | 0,5 GB ciascuno, nessuna scadenza |
auth-service, catalog-service |
Render free | €0 | Cold start dopo 15 min di inattività (~30-60s) |
api-gateway |
Render free | €0 | Cold start dopo 15 min di inattività |
jinbocho-fe |
Render Static Site | €0 | Nessun cold start (CDN) |
| Totale | — | €0/mese | Cold start accettabili per uso domestico |
Per eliminare i cold start, passa a Render Starter ($7/mese per servizio). I database rimangono gratuiti su Neon indipendentemente.
Mantieni i servizi nella stessa regione
I Servizi Privati di Render possono comunicare solo all’interno della stessa regione. Distribuisci sempre auth, catalog, ai e gateway nella stessa regione. Scegli la regione Neon più vicina a quella Render per minimizzare la latenza del database.