Remix + Postgres + Fly.io security playbook
Updated
Remix's loader/action pattern + Fly's edge-distributed Postgres = a clean stack. Security boundaries: loaders need session checks; actions need CSRF; Fly secrets must never enter the repo.
What breaks on this stack
Loader without session check
loader() runs server-side but no auth by default. Add requireUser at top.
Read the guide →Postgres credential in fly.toml
fly.toml is committed; credentials must be in fly secrets, not in fly.toml.
Read the guide →Health check exposing internals
Default /health endpoint sometimes leaks build commit, env names. Restrict.
Read the guide →Pre-ship checklist
- DATABASE_URL in fly secrets
- loaders + actions require session
- CSRF guard on every action
- Health check minimal
- Fly volume snapshots configured
- Postgres pgbouncer sized for connections
Starter config
// app/sessions.server.ts
import { createCookieSessionStorage } from "@remix-run/node";
export const { getSession, commitSession, destroySession } =
createCookieSessionStorage({
cookie: { name: "_s", secrets: [process.env.SESSION_SECRET!], sameSite: "lax", path: "/", secure: true, httpOnly: true },
});