deploy · tutorial
From localhost to a $5 VPS in one command
Prefilled .env.local for dev, .env.prod for the server. No dashboard spelunking.

Boring Team
September 13, 2026 · 1 min read
Deployment usually means an afternoon of clicking through dashboards, pasting secrets into text boxes, and discovering that staging and prod disagree about everything.
Boring keeps two files:
.env.local # prefilled, gitignored, loads automatically
.env.prod # prod values, gitignored, scp'd to the server once
Local: just run it
.env.local ships prefilled — SQLite, test-mode billing, localhost URLs. The only empty lines are OAuth and provider keys, which you don't need until you do:
npm run dev
# → http://localhost:3000, database in ./db/app.db
Prod: source and start
Next.js doesn't auto-load .env.prod, so the scripts do it for you:
npm run build:prod # loads .env.prod, then next build
npm run start:prod # loads .env.prod, then next start
Shell variables beat .env.local every time, so prod values always win — even if both files exist on the box.
The checklist that remains
- Point DNS at the box, set
NEXTAUTH_URLto the real domain. - Generate a real
NEXTAUTH_SECRET(openssl rand -base64 32). - Create the billing product (Stripe price, Dodo product, or LS variant) and paste the ID.
- Paste the provider webhook secret, point the webhook URL at
/api/webhook/<rail>. - Run
schema.sqlonce if you chose Supabase.
That's the whole list. The boring kind of list — short, complete, and the same every time.
deploytutorial