Skip to content

Deployment

The generated project includes a Dockerfile and docker-compose.yml. This is the simplest way to deploy:

services:
postgres:
image: postgres:18-alpine
environment:
POSTGRES_USER: rebase
POSTGRES_PASSWORD: rebase
POSTGRES_DB: rebase
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
app:
build: ./backend
ports:
- "3001:3001"
environment:
DATABASE_URL: postgresql://rebase: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

Before deploying to production, ensure:

ItemDetails
JWT_SECRETUse a cryptographically strong random string (≥ 32 chars). Never reuse across environments.
DATABASE_URLUse a managed Postgres instance (Neon, Supabase, RDS) with TLS enabled
CORSConfigure allowed origins on your backend if frontend and backend are on different domains
Storage volumesMount persistent volumes for file uploads. Or switch to S3 for production.
HTTPSTerminate TLS at your reverse proxy (nginx, Cloudflare, load balancer)
RegistrationSet ALLOW_REGISTRATION=false after creating your admin account

In production, the backend can serve the frontend as a static SPA:

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

Build the frontend first:

cd frontend && pnpm build

This way you only need to deploy one server that handles both SPA and API.

Detailed step-by-step guides for each platform:

PlatformTypeGuide
AWSApp Runner / ECS + RDSDeploy on AWS →
Google CloudCloud Run + Cloud SQLDeploy on GCP →
AzureContainer Apps + PostgreSQLDeploy on Azure →
Hetzner CloudVPS + Docker ComposeDeploy on Hetzner →
ScalewayServerless ContainersDeploy on Scaleway →
RailwayPaaS (auto-detect Dockerfile)Deploy on Railway →
Fly.ioContainer runtimeDeploy on Fly.io →

If you want Rebase to run at a sub-path (e.g., /admin):

Frontend — Update the BrowserRouter basename:

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

Backend — Update the base path:

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