VPS Deployment
Operate the Node application behind your own HTTPS reverse proxy, using Docker or a direct Node process.
See the hosted deployment status before using this deployment guide.
Use this path when you want to operate the application host yourself. Start with Vercel for managed hosting. A VPS requires you to manage the OS, firewall, HTTPS, process supervision, updates, monitoring, and recovery. Supabase still owns the configured Auth and database services.
Prepare the host
Use a maintained Linux host with Git and either Docker with Compose or the selected Node 24 deployment runtime and Bun 1.4+. The package's minimum is Node 22.23.4; this recipe uses the same Node 24 reference as the managed and container paths. Size it for your workload; a production bundle can be built on a separate machine. Give the public domain the correct DNS records, restrict SSH access, and expose only the ports your reverse proxy needs.
Install Docker using its official installation guide. For direct Node operation, follow the non-Docker path below. No app command provisions the host or applies firewall rules for you.
Run with Docker
Clone your repository, then follow
Docker Deployment to create the Dockerfile, Compose
configuration, public .env.build, and private .env.runtime. Use the same
hosted Supabase project and the selected provider's test account throughout
setup. Stripe is the default; see Polar Billing for
Polar sandbox configuration. Keep provider credentials server-side.
git clone <your-repo-url>
cd your-project
docker compose up -d --build
docker compose ps
curl --fail http://127.0.0.1:3000/api/healthThe documented Compose configuration binds the app to the host's loopback address. Keep that boundary when adding the reverse proxy.
Nginx configuration
Create an HTTP site for your domain before issuing its TLS certificate. For example, adapt this file to your host's Nginx layout:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Enable the site using your distribution's supported layout, validate it with
sudo nginx -t, and reload Nginx. Then follow
Certbot's Nginx instructions
for your OS to issue and renew the certificate and redirect HTTP to HTTPS.
Do not expose the application port directly to untrusted clients, which could
supply their own forwarded host and scheme headers.
Set NEXT_PUBLIC_APP_URL, Supabase Auth's Site URL and Redirect URLs, and the
selected provider's webhook destination to this same HTTPS origin
(/api/webhooks/stripe or /api/webhooks/polar). Keep prior provider
credentials and webhook delivery for retained billing and outstanding work.
Rebuild after changing a public setting. Check sign-in and session refresh through the public proxy;
a loopback health response cannot prove TLS, cookies, or provider callbacks.
Non-Docker deployment
Install Node 24 and Bun 1.4+ from their Node and Bun instructions. Bun owns dependency installation and build commands; Node runs the production output.
Use an isolated deployment checkout. Keep local-development .env.local
out of it so local values cannot override the hosted configuration. Save only
public NEXT_PUBLIC_* inputs in .env.production and unprefixed server
credentials in ignored .env.runtime, using the
hosted reference.
bun install --frozen-lockfile
bun run build
chmod 600 .env.runtime
NODE_ENV=production HOST=127.0.0.1 PORT=3000 node --env-file=.env.runtime .output/server/index.mjsThe built server does not load environment files automatically. Run this same Node command under your host's process supervisor, with the working directory set to the deployment root and the same runtime settings. Configure restart and boot behavior in that supervisor. Keep secrets in the protected runtime file or its environment configuration, rather than command arguments.
Update and recover
Deploy reviewed source, rebuild with its public settings, and restart the owned process or container. This recipe may interrupt requests. Keep the previous accepted output or image and its matching settings for rollback. Do not reset retained database data during an application update.
Inspect the application log and /api/health first after a restart. Then check
the affected Auth, content, and billing journeys. Monitor disk and memory using
your host's tools. Configure database backup and restore using your Supabase
plan's supported features; Git history protects source code, not runtime data.
Payment provider settings
Stripe is the default for new checkout. Set PAYMENT_PROVIDER=polar with
server-only Polar settings for a Polar app; see Polar Billing.
Hosted Polar on TanStack Start has not been verified. Complete the local
sandbox journey and stop before live Polar activation until the hosted path is
verified.
Keep the app origin and Supabase public settings in the build environment.
Configure public Stripe settings only for the offers you use. Missing mappings
leave those offers unavailable in either mode. Preserve Stripe credentials and
webhook delivery while retained billing or outstanding work still needs them.
The Node reference is 24.22.1 or later on 24.x; 22.23.4 or later on 22.x is also supported. Rebuild after public settings or the Node image change.
What's next
- Docker Deployment — use the complete container recipe.
- Environment Variables — check each setting's owner and mode.
- Authentication — verify sessions and callbacks.
Was this page helpful?