Salta ai contenuti

Distribuzione

Un progetto Rebase si distribuisce come un server a un URL (su Rebase Cloud: https://<project>.rebase.website). Quel server gestisce:

  • /api/* — l’API dei dati, l’autenticazione, il tempo reale e l’archiviazione
  • tutto il resto — il tuo frontend/ compilato come SPA statica

Non c’è un URL di amministrazione separato: il pannello di amministrazione fa parte del tuo frontend, quindi dove appare dipende da cosa è il tuo frontend.

Tipo di progetto L’URL radice mostra Il pannello di amministrazione si trova a
Scaffold predefinito (rebase init) Il pannello di amministrazione / — il frontend è l’amministrazione
Frontend di prodotto personalizzato La tua app Dove lo monti, comunemente /admin — vedi Cambiare l’URL di Base
Progetto solo backend Nulla (solo API) Non distribuito

Il progetto generato include un Dockerfile e un docker-compose.yml. Questo è il modo più semplice per distribuire. L’estratto qui sotto è illustrativo: il docker-compose.yml generato nel tuo progetto è la fonte di verità, quindi preferiscilo a questo esempio.

services:
postgres:
image: postgres:18-alpine
environment:
POSTGRES_USER: rebase_app
POSTGRES_PASSWORD: rebase
POSTGRES_DB: rebase
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
app:
build:
context: .
dockerfile: backend/Dockerfile
ports:
- "3001:3001"
environment:
DATABASE_URL: postgresql://rebase_app:rebase@postgres:5432/rebase
JWT_SECRET: ${JWT_SECRET}
NODE_ENV: production
depends_on:
- postgres
volumes:
- uploads:/app/uploads
volumes:
pgdata:
uploads:
docker compose up -d

All’avvio Rebase crea automaticamente solo le tabelle di autenticazione. Le tabelle per le tue collezioni non vengono create automaticamente: l’app si avvia comunque e il login funziona, quindi è facile non accorgersene, finché ogni collezione non restituisce un errore “missing table”.

Esegui la sincronizzazione dello schema una volta, con DATABASE_URL che punta al database di produzione:

pnpm run db:push

Eseguilo da un checkout del progetto o dalla CI, non dall’interno del container: l’immagine di produzione non include la CLI. Se preferisci migrazioni versionate a una sincronizzazione diretta, usa invece pnpm run db:generate seguito da pnpm run db:migrate.

Prima di distribuire in produzione, assicurati di:

Elemento Dettagli
Schema del database Esegui pnpm run db:push (oppure pnpm run db:generate + pnpm run db:migrate) con DATABASE_URL puntato alla produzione. All’avvio Rebase crea solo le tabelle di autenticazione, non quelle delle tue collezioni.
JWT_SECRET Usa una stringa casuale crittograficamente forte (≥ 32 caratteri). Non riutilizzarla mai tra ambienti.
DATABASE_URL Usa un’istanza Postgres gestita (Neon, Supabase, RDS) con TLS abilitato
CORS Configura le origini consentite sul tuo backend se frontend e backend sono su domini diversi
Volumi di archiviazione Monta volumi persistenti per i caricamenti di file. Oppure passa a S3 per la produzione.
HTTPS Termina TLS sul tuo reverse proxy (nginx, Cloudflare, bilanciatore di carico)
Registrazione Imposta ALLOW_REGISTRATION=false dopo aver creato il tuo account amministratore

In produzione, il backend può servire il frontend come SPA statica:

import { serveSPA } from "@rebasepro/server";
import path from "path";
// After initializeRebaseBackend()
serveSPA(app, { frontendPath: path.resolve(process.cwd(), "../frontend/dist") });

Compila prima il frontend:

cd frontend && pnpm build

In questo modo devi distribuire un solo server che gestisce sia la SPA sia l’API.

Guide dettagliate passo dopo passo per ogni piattaforma:

Piattaforma Tipo Guida
AWS App Runner / ECS + RDS Distribuire su AWS →
Google Cloud Cloud Run + Cloud SQL Distribuire su GCP →
Azure Container Apps + PostgreSQL Distribuire su Azure →
Hetzner Cloud VPS + Docker Compose Distribuire su Hetzner →
Scaleway Container serverless Distribuire su Scaleway →
Railway PaaS (rilevamento automatico del Dockerfile) Distribuire su Railway →
Fly.io Runtime di container Distribuire su Fly.io →

Se vuoi che Rebase venga eseguito su un sotto-percorso (ad es. /admin):

Frontend — Aggiorna il basename di BrowserRouter:

<BrowserRouter basename="/admin">
<App />
</BrowserRouter>

Backend — Aggiorna il percorso di base:

await initializeRebaseBackend({
// ...
basePath: "/admin/api"
});

App di Prodotto + Amministrazione in un’Unica Distribuzione

Sezione intitolata “App di Prodotto + Amministrazione in un’Unica Distribuzione”

Il motivo comune per spostare l’amministrazione su /admin è distribuire la tua app di prodotto alla radice della stessa distribuzione. Un singolo entry point Vite può servire entrambe, suddivise per URL, così ogni app viene caricata in lazy e i visitatori del prodotto non scaricano mai il bundle di amministrazione:

const isAdmin = window.location.pathname.startsWith("/admin");
const ProductApp = lazy(() => import("./App"));
const AdminApp = lazy(() => import("./AdminApp")); // renders <RebaseAdmin basePath="/admin" />
if (isAdmin) {
// The admin uses useBlocker → needs a data router
const router = createBrowserRouter([{ path: "/admin/*", element: <AdminApp /> }]);
root.render(<RouterProvider router={router} />);
} else {
root.render(<BrowserRouter><ProductApp /></BrowserRouter>);
}

Il backend non necessita di modifiche per questo pattern — l’API rimane a /api e il catch-all della SPA serve index.html sia per / sia per /admin/*.