Pular para o conteúdo

Implantação

Um projeto Rebase é implantado como um servidor em uma URL (na Rebase Cloud: https://<project>.rebase.website). Esse servidor cuida de:

  • /api/* — a API de dados, autenticação, tempo real e armazenamento
  • todo o resto — o seu frontend/ compilado como uma SPA estática

Não há uma URL de administração separada: o painel de administração faz parte do seu frontend, então onde ele aparece depende do que o seu frontend é.

Tipo de projeto A URL raiz mostra O painel de administração está em
Scaffold padrão (rebase init) O painel de administração / — o frontend é o admin
Frontend de produto personalizado Sua app Onde você o montar, comumente /admin — veja Alterar a URL Base
Projeto somente backend Nada (apenas API) Não implantado

O projeto gerado inclui um Dockerfile e um docker-compose.yml. Use o docker-compose.yml gerado como fonte da verdade — o exemplo abaixo mostra apenas os campos essenciais. Esta é a forma mais simples de implantar:

services:
postgres:
image: pgvector/pgvector:pg18
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

Ao iniciar, o Rebase cria automaticamente apenas as tabelas de autenticação — as tabelas das suas próprias coleções não são criadas sozinhas. Execute pnpm run db:push uma vez contra o banco de dados de produção; caso contrário, a aplicação sobe e o login funciona normalmente, mas toda coleção retorna um erro de tabela ausente (“missing table”):

DATABASE_URL="<sua string de conexão de produção>" pnpm run db:push

Rode isso a partir de um checkout do projeto ou da sua CI, com a DATABASE_URL apontando para produção — não dentro do contêiner, pois a imagem de produção não inclui a CLI. Para migrações versionadas, use pnpm run db:generate e depois pnpm run db:migrate.

Antes de implantar em produção, garanta:

Item Detalhes
JWT_SECRET Use uma string aleatória criptograficamente forte (≥ 32 caracteres). Nunca reutilize entre ambientes.
DATABASE_URL Use uma instância Postgres gerenciada (Neon, Supabase, RDS) com TLS habilitado
Esquema do banco de dados Execute pnpm run db:push uma vez contra o banco de produção — o boot cria apenas as tabelas de autenticação, não as das suas coleções
CORS Configure as origens permitidas no seu backend se o frontend e o backend estiverem em domínios diferentes
Volumes de armazenamento Monte volumes persistentes para os uploads de arquivos. Ou mude para S3 na produção.
HTTPS Termine TLS no seu proxy reverso (nginx, Cloudflare, balanceador de carga)
Registro Defina ALLOW_REGISTRATION=false após criar sua conta de administrador

Em produção, o backend pode servir o frontend como uma SPA estática:

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

Compile o frontend primeiro:

cd frontend && pnpm build

Dessa forma, você só precisa implantar um servidor que cuide tanto da SPA quanto da API.

Guias detalhados passo a passo para cada plataforma:

Plataforma Tipo Guia
AWS App Runner / ECS + RDS Implantar na AWS →
Google Cloud Cloud Run + Cloud SQL Implantar no GCP →
Azure Container Apps + PostgreSQL Implantar no Azure →
Hetzner Cloud VPS + Docker Compose Implantar na Hetzner →
Scaleway Contêineres Serverless Implantar na Scaleway →
Railway PaaS (detecção automática do Dockerfile) Implantar na Railway →
Fly.io Runtime de contêineres Implantar no Fly.io →

Se você quiser que a Rebase rode em um subcaminho (por ex., /admin):

Frontend — Atualize o basename do BrowserRouter:

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

Backend — Atualize o caminho base:

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

App de Produto + Admin em uma Única Implantação

Seção intitulada “App de Produto + Admin em uma Única Implantação”

O motivo comum para mover o admin para /admin é entregar a sua própria app de produto na raiz da mesma implantação. Um único ponto de entrada Vite pode servir ambos, divididos por URL, de modo que cada app seja carregada de forma preguiçosa e os visitantes do produto nunca baixem o bundle do admin:

const isAdmin = window.location.pathname.startsWith("/admin");
const ProductApp = lazy(() => import("./App"));
const AdminApp = lazy(() => import("./AdminApp")); // renders <RebaseCMS 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>);
}

O backend não precisa de alterações para esse padrão — a API permanece em /api e o catch-all da SPA serve index.html tanto para / quanto para /admin/*.