Every workflow writes values as <placeholder>. Copy this table, fill in the right-hand
column, and paste it to your AI with the workflow, or keep it as profile.local.md (the
repo ignores *.local.md, so it never gets committed).
Never put secrets here. Passwords, API keys and tokens go in the server's .env files,
never in a document you paste into a chat.
| Placeholder | Meaning | Example |
|---|---|---|
<domain> |
your apex domain | example.com |
<app> |
short name of one app; used for the service, the folder and the DB | notes |
<app-host> |
the hostname that app is served on | notes.example.com |
<app-port> |
the localhost port the app's API listens on (one per app) | 3001 |
<server> |
your SSH alias for the server (~/.ssh/config Host) |
web1 |
<deploy-user> |
the non-root user that owns the apps | deploy |
<web-root> |
where a site's static files live | /var/www/notes.example.com |
<db-name> / <db-user> |
the app's Postgres database and role | notes / notes |
<repo> |
the app's git repository | github.com/you/notes |
<email-from> |
the sender your apps mail from | Notes <[email protected]> |
| Choice | Default | Change it if… |
|---|---|---|
| Server | 1 vCPU / 1 GB RAM / 25 GB disk VPS, Ubuntu 24.04 | you have measured a reason; see workflows/lean-production.md |
| DNS + TLS + CDN | Cloudflare free plan, proxied, origin certificate | you want Let's Encrypt directly instead |
| Web server | Nginx, one server block per host | — |
| Database | PostgreSQL 16 on the same box, bound to localhost | — |
| App runtime | Node 22, built output run by systemd, memory-capped | — |
| an HTTP email API (e.g. Brevo), since most VPS providers block SMTP | your provider opens port 25 | |
| Stack | see reference/stack.md |
— |
Give every app its own port and write it down. Nothing on the server should listen publicly except 22, 80 and 443.
3001 <app-1> API
3002 <app-2> API
5432 Postgres (localhost only)