Files
davide e82e20b0f1 docs: add localhost vs production comparison and fix Caddyfile example
- Add new section summarising the 4 differences between local dev and
  production: domain/HTTPS, env vars, server requirements, backups
- Update production Caddyfile example to include /uploads/* static
  file handler (required for image serving)
2026-05-18 17:55:12 +02:00

379 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# E-commerce Platform
Piattaforma e-commerce containerizzata, avviabile con un singolo comando.
**Stack:** Next.js 14 · PostgreSQL 16 · Prisma · Stripe · Caddy · Docker Compose
---
## Avvio in locale (test su localhost)
### Prerequisiti
- [Docker Desktop](https://docs.docker.com/get-docker/) installato e avviato
- Porta **80** libera (nessun altro web server in esecuzione)
### 1. Clona il repository
```bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea il file `.env`
```bash
cp .env.example .env
```
Il file `.env` di default è già configurato per localhost. **Non serve modificare nulla** per i primi test.
### 3. Avvia la piattaforma
```bash
docker compose up -d
```
Il primo avvio richiede **510 minuti**: Docker scarica le immagini, installa le dipendenze npm, compila Next.js, esegue le migrazioni e crea l'utente admin.
Segui il progresso con:
```bash
docker compose logs -f app
```
La piattaforma è pronta quando vedi:
```
✓ Ready in 91ms
```
### 4. Apri nel browser
| URL | Cosa trovi |
|-----|------------|
| http://localhost | Sito pubblico (vetrina) |
| http://localhost/admin | Dashboard amministratore |
| http://localhost:8025 | Mailpit — cattura le email di test |
### 5. Primo accesso admin
Vai su **http://localhost/admin** e accedi con:
```
Email: admin@example.com
Password: Admin1234!test
```
Al primo accesso il sistema ti obbliga a cambiare la password.
**Requisiti password:** minimo 12 caratteri, almeno una maiuscola, una minuscola, un numero e un simbolo.
### 6. Configura il negozio (ordine consigliato)
1. **Product Types** → crea un tipo di prodotto (es. "Prodotto") con gli attributi che vuoi
2. **Categories** → crea le categorie
3. **Products** → crea un prodotto, assegna tipo e categoria, impostalo su **Published**
4. Apri http://localhost → il prodotto appare in homepage
### 7. Cosa funziona in locale senza configurazione extra
| Funzionalità | Stato |
|---|---|
| Admin dashboard completa | ✅ |
| Gestione prodotti, categorie, ordini | ✅ |
| Registrazione e login clienti | ✅ |
| Email (reset password, ecc.) | ✅ visibili su http://localhost:8025 |
| Pagamenti Stripe | ⚠️ richiede chiavi reali (vedi sotto) |
**Per testare i pagamenti Stripe** in locale, inserisci una chiave `sk_test_...` reale nel `.env` (gratuita, modalità test su [dashboard.stripe.com](https://dashboard.stripe.com/test/apikeys)):
```env
STRIPE_SECRET_KEY=sk_test_la_tua_chiave
```
Poi riavvia l'app:
```bash
docker compose restart app
```
### 8. Ferma la piattaforma
```bash
docker compose down # ferma i container, i dati restano
docker compose down -v # ferma e cancella anche il database
```
---
## Differenze tra localhost e produzione
Quattro cose cambiano quando si passa da localhost a un dominio reale.
### 1 — Dominio e HTTPS
Modificare **una sola riga** nel `Caddyfile`:
```
# localhost
localhost { ... }
# produzione
tuodominio.com { ... }
```
Caddy ottiene e rinnova automaticamente il certificato HTTPS tramite Let's Encrypt. Non serve nessuna configurazione SSL manuale.
### 2 — Variabili d'ambiente
Cinque variabili da aggiornare nel `.env`:
| Variabile | Localhost | Produzione |
|-----------|-----------|------------|
| `APP_URL` | `http://localhost` | `https://tuodominio.com` |
| `AUTH_SECRET` | qualsiasi stringa | `openssl rand -hex 32` |
| `STRIPE_SECRET_KEY` | `sk_test_...` (gratuita) | `sk_live_...` |
| `STRIPE_WEBHOOK_SECRET` | opzionale | obbligatorio |
| `SMTP_*` | Mailpit locale (porta 8025) | provider reale (Resend, Mailgun, SendGrid…) |
### 3 — Server
Serve un VPS Linux con Docker installato (DigitalOcean, Hetzner, OVH, ecc.) e il record DNS del dominio puntato all'IP del server. Il comando di avvio è identico: `docker compose up -d`.
### 4 — Backup
In locale i dati si perdono con `docker compose down -v`. In produzione è necessario un backup automatico del database (vedi sezione [Backup database](#backup-database)) e conservare il volume `uploads` che contiene le immagini dei prodotti.
---
## Deploy in produzione
### Prerequisiti
- Server Linux con Docker e Docker Compose v2 (qualsiasi VPS o cloud VM)
- Dominio con record **A** puntato all'IP del server
- Porte **80** e **443** aperte nel firewall del server
- Account [Stripe](https://stripe.com) (per i pagamenti reali)
- Account SMTP (per le email: Mailgun, Resend, SendGrid, ecc.)
### 1. Clona il repository sul server
```bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea e configura `.env`
```bash
cp .env.example .env
nano .env
```
Modifica questi valori:
```env
# URL pubblico del sito — con https://
APP_URL=https://tuodominio.com
# Genera un segreto casuale: openssl rand -hex 32
AUTH_SECRET=incolla_qui_il_risultato_di_openssl
# Credenziali del primo admin — cambia subito dopo il primo accesso
INITIAL_ADMIN_EMAIL=admin@tuodominio.com
INITIAL_ADMIN_PASSWORD=UnaPasswordSicura1!
# Stripe — usa le chiavi live (non sk_test_)
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxx
# SMTP reale per le email
SMTP_HOST=smtp.tuoprovider.com
SMTP_PORT=587
SMTP_USER=user@tuodominio.com
SMTP_PASSWORD=la_tua_password_smtp
SMTP_FROM=noreply@tuodominio.com
```
> `DATABASE_URL` non va modificato: usa già il nome del container Docker corretto.
### 3. Genera `AUTH_SECRET`
```bash
openssl rand -hex 32
```
Copia l'output nel campo `AUTH_SECRET` nel file `.env`.
### 4. Configura il dominio nel Caddyfile
Apri `Caddyfile` e sostituisci `localhost` con il tuo dominio:
```
tuodominio.com {
handle /uploads/* {
root * /srv
file_server
}
encode gzip zstd
reverse_proxy app:3000
}
```
Caddy ottiene e rinnova automaticamente il certificato HTTPS tramite Let's Encrypt. Non serve nessuna configurazione SSL manuale.
### 5. Avvia
```bash
docker compose up -d
```
Attendi che l'app sia pronta:
```bash
docker compose logs -f app
# attendi: ✓ Ready in ...ms
```
Il sito è live su `https://tuodominio.com`.
### 6. Configura il webhook Stripe
Nel [dashboard Stripe → Webhooks](https://dashboard.stripe.com/webhooks), aggiungi un endpoint:
```
URL endpoint: https://tuodominio.com/api/webhooks/stripe
Eventi da ascoltare:
- checkout.session.completed
- payment_intent.succeeded
- payment_intent.payment_failed
```
Copia il **Signing secret** (`whsec_...`) nel `.env` come `STRIPE_WEBHOOK_SECRET`, poi:
```bash
docker compose restart app
```
### 7. Primo accesso e configurazione negozio
1. Vai su `https://tuodominio.com/admin`
2. Accedi con le credenziali del `.env`
3. Cambia la password quando richiesto
4. Configura il negozio in questo ordine:
- **Settings** → nome negozio, logo, colori
- **Product Types** → tipi di prodotto con attributi personalizzati
- **Categories** → categorie prodotto
- **Products** → aggiungi i tuoi prodotti
- **Admin Users** → aggiungi altri amministratori se necessario
---
## Aggiornamenti
```bash
git pull
docker compose build app
docker compose up -d
```
Le migrazioni del database vengono applicate automaticamente all'avvio.
---
## Backup database
**Dump manuale:**
```bash
docker compose exec db pg_dump -U ecommerce ecommerce > backup_$(date +%Y%m%d_%H%M%S).sql
```
**Ripristino:**
```bash
cat backup_XXXXXXXX_XXXXXX.sql | docker compose exec -T db psql -U ecommerce ecommerce
```
**Backup automatico giornaliero** (aggiungi al crontab del server con `crontab -e`):
```bash
0 3 * * * cd /percorso/ecommerce-platform && docker compose exec -T db pg_dump -U ecommerce ecommerce | gzip > /backups/ecommerce_$(date +\%Y\%m\%d).sql.gz
```
---
## Problemi comuni
**Il build impiega molto tempo al primo avvio**
È normale. npm install + compilazione Next.js richiedono 510 minuti la prima volta. I build successivi sono molto più veloci grazie alla cache Docker.
**http://localhost non risponde (502 Bad Gateway)**
L'app è ancora in fase di avvio. Aspetta qualche secondo e ricarica. Controlla lo stato con:
```bash
docker compose logs -f app
```
**Errore "port 80 already in use"**
Un altro servizio usa la porta 80 (Apache, Nginx, ecc.). Fermalo o cambia la porta nel `docker-compose.yml`.
**Dimentico la password admin**
Resetta direttamente nel database:
```bash
# genera hash bcrypt per la nuova password
docker compose exec app node -e "
const bcrypt = require('bcryptjs');
bcrypt.hash('NuovaPassword1!', 12).then(h => console.log(h));
"
# aggiorna nel db
docker compose exec db psql -U ecommerce ecommerce -c \
"UPDATE \"User\" SET \"passwordHash\"='HASH_QUI', \"mustChangePassword\"=true WHERE email='admin@example.com';"
```
---
## Struttura del progetto
```
ecommerce-platform/
├── docker-compose.yml Orchestrazione: db, app, caddy, mailpit
├── Caddyfile Reverse proxy — modifica qui il dominio
├── .env Variabili d'ambiente (non committare)
├── .env.example Template da copiare
└── app/
├── Dockerfile Build multi-stage Next.js
├── entrypoint.sh Sequenza avvio: migrazioni → admin → server
├── prisma/
│ └── schema.prisma Schema database completo
├── scripts/
│ └── bootstrap-admin.ts Crea il primo OWNER se non esiste
└── src/
├── app/ Pagine Next.js (App Router)
│ ├── admin/ Dashboard admin (protetta per ruolo)
│ ├── api/ API routes (auth, prodotti, ordini, webhook)
│ └── (storefront) Homepage, catalogo, carrello, checkout
├── components/ Componenti React riutilizzabili
└── lib/ Auth, Prisma client, Stripe, email
```
---
## Variabili d'ambiente
| Variabile | Descrizione | Locale | Produzione |
|-----------|-------------|:------:|:----------:|
| `APP_URL` | URL pubblico del sito | `http://localhost` | `https://tuodominio.com` |
| `DATABASE_URL` | Connessione PostgreSQL | invariato | invariato |
| `AUTH_SECRET` | Segreto sessioni (min 32 char) | qualsiasi | `openssl rand -hex 32` |
| `INITIAL_ADMIN_EMAIL` | Email primo admin | qualsiasi | la tua email |
| `INITIAL_ADMIN_PASSWORD` | Password primo admin | qualsiasi | sicura |
| `STRIPE_SECRET_KEY` | Chiave Stripe | `sk_test_...` | `sk_live_...` |
| `STRIPE_WEBHOOK_SECRET` | Segreto webhook Stripe | opzionale | obbligatorio |
| `SMTP_HOST` | Server SMTP | `mailpit` | provider reale |
| `SMTP_PORT` | Porta SMTP | `1025` | `587` |
| `SMTP_USER` | Utente SMTP | vuoto | obbligatorio |
| `SMTP_PASSWORD` | Password SMTP | vuoto | obbligatorio |
| `SMTP_FROM` | Mittente email | qualsiasi | `noreply@tuodominio.com` |