Updated 2026-10-19 against the Levelrail 0.6.0 docs. Since the first version of this post, Levelrail started shipping stable releases.
Leave Vercel for Your Own Server: A Self-Hosted Vercel Alternative Runbook
Moving off Vercel is hard because of configuration, not code. Vercel holds configuration in its dashboard that never lived in your repo: env vars per environment, domain redirects, cron schedules, integrations. This runbook inventories that first, then maps each piece to Levelrail, a self-hosted platform I am building.
Vercel has no automatic importer. Everything here is manual. Run the new setup beside Vercel, and keep Vercel as your rollback until the checks at the end pass.
TL;DR
| Phase | Goal |
|---|---|
| 1. Inventory | Write down everything Vercel holds |
| 2. Map | Match each concept to a self-hosted counterpart |
| 3. Build | Deploy to a test URL, no real domain yet |
| 4. Cutover | Lower DNS TTLs, switch, watch |
| 5. Shadow run | Run both until boring problems show up |
Phase 1: inventory
Collect this before you touch anything new.
| Item | Where in Vercel | Why it matters |
|---|---|---|
| Env vars per environment | Project Settings, Environment Variables | You decide how Production, Preview and Development map over |
NEXT_PUBLIC_* vars |
Same list | Compiled in at build time, never read at runtime |
| Domains and redirects | Project Settings, Domains | You recreate each one |
| DNS provider and TTLs | Your registrar | You lower TTLs before cutover |
| Cron jobs |
vercel.json and the Cron tab |
Vercel cron hits an HTTP path |
| Functions config |
vercel.json, runtime = "edge" in code |
Nothing replaces the edge runtime |
| Storage and add-ons | Integrations | Managed storage does not move with the app |
Phase 2: the concept map
| Vercel | Levelrail |
|---|---|
| Project | An app with one or more services |
| Git deploy on push | A git source with push trigger mode |
| Framework preset build |
railpack build type, or dockerfile
|
| Static export |
static build type, served by Caddy with no container |
| Environments | Optional environments in a project, with promote |
| Sensitive env vars | Encrypted, write-only secrets |
| Preview deployments | Per pull request previews, opt in per app |
| Instant Rollback | Rollback by deploy id, pinned by digest |
| Cron Jobs | Scheduled tasks that run a command in the container |
| Vercel Postgres | A managed Postgres you restore a dump into |
Two rows hide a difference worth knowing. Vercel cron calls an HTTP route, while a scheduled task runs a command inside your running container, so the command must use a tool your image actually contains. And previews here are per pull request, never per branch.
The build-time trap
next build bakes NEXT_PUBLIC_* values in. The platform injects env only when a container starts, so it never reaches the build. Commit a .env.production with the public values and every build type picks it up. The deploy guide in this series explains the failure mode in detail.
Phase 3: build it on a test URL
Leave domains out of the first deploy so nothing competes with Vercel for your real hostname. Create the app from git, load plain env with a dry run first, then secrets:
levelrail-cli apps env import your-app --file prod.env --dry-run
levelrail-cli apps secrets set your-app --env-file secrets.env
levelrail-cli apps apply your-app
Copy values from the Production column in Vercel, not Preview. Add a cheap readiness route that does not depend on outside services, then check pages, API routes, auth callbacks, image requests and streaming responses on the test URL.
If the app uses Vercel Postgres, create a managed database, restore a dump into it and rehearse that restore before cutover.
What has no counterpart
Plan for these before you commit.
| Vercel feature | Status |
|---|---|
| Edge Functions and Middleware | None. Node-compatible middleware works, edge-only code must move to the Node runtime |
| Image Optimization CDN |
next/image runs in your container on your CPU |
| Global CDN and edge caching | None built in. Caddy serves from your nodes |
| Web Analytics and Speed Insights | No browser-side analytics. Server request metrics exist |
| Blob, KV, Edge Config | No drop-in match. Managed Redis exists but you rewrite the client |
| Autoscaling and scale to zero | Fixed replicas only |
| Plain HTTP to HTTPS redirect | Not done by the ingress today. Add it at DNS or a CDN in front |
If any row is a deal breaker, you just saved yourself a migration.
Phase 4: DNS cutover with a way back
- Lower TTLs to 60 to 300 seconds, at least one full old TTL before cutover.
- Add the real domains, plus the
wwwredirect. - Have a certificate ready first. Public issuance needs the domain pointing at the server, so expect a short gap, or upload your own certificate beforehand.
- Test with a host override before you change DNS:
curl --resolve YOUR_DOMAIN:443:SERVER_IP YOUR_DOMAIN_URL
- Switch the A and AAAA records. Write down the old values first.
- Watch logs and metrics from outside your network.
- To roll back, restore the old records. With a low TTL most clients return in minutes.
Do not remove the domain from Vercel until the shadow run is clean.
Phase 5: the shadow run
Run both platforms for a full business cycle, including any weekly or monthly cron. Check at least these:
- [ ] A deliberately broken deploy fails while the old container keeps serving
- [ ] A rollback works from the CLI and the dashboard
- [ ] Every Production env key from Vercel exists
- [ ]
NEXT_PUBLIC_*values are correct in the deployed bundle - [ ] OAuth callback URLs updated at each provider
- [ ] Payment and other webhooks point at the new URL
- [ ] Each scheduled task ran on time
- [ ] The certificate arrived and has expiry alerting
- [ ] A database backup ran and you rehearsed a restore
- [ ] Error rate and latency compare acceptably with Vercel
What to check before trusting it
Levelrail ships stable releases now (v0.6.0 as of 2026-10-19), and single-server deployments are labeled production ready. Public certificate issuance has had one live verification against Let's Encrypt, with renewal and DNS-01 wildcards not yet exercised live. Treat this as a parallel run, not a leap.
Which Vercel feature is the one you would find hardest to replace?
Frequently asked questions
Is there a self-hosted Vercel alternative?
Levelrail can run a Next.js app on your own server with git deploys, automatic HTTPS and rollback. It does not replicate Vercel's edge network or every managed feature, and the runbook above lists what has no counterpart. See the Vercel alternative page.
Is Levelrail production ready?
Single-server deployments are labeled production ready, and multi-node plus a handful of newer features are still beta. The latest release is v0.6.0 (2026-10-17), and the feature status page links the evidence behind each label.
Is Levelrail free?
Yes. Levelrail is Apache 2.0 with one edition, no license key and no paid tier. Sign-in with Google, GitHub, Microsoft or generic OIDC, TOTP and passkeys, IAM policies, an audit log with CSV export, verified backups and deploy approvals all ship in the same binary.
Go deeper
- Migrating a Next.js app from Vercel
- Domains, TLS and ingress
- Feature status, with the evidence behind each claim
- New to Levelrail? Start with the five minute install
Try it, and tell me what breaks
Levelrail is open source under Apache 2.0. It is young, so every bug report changes what gets built next.
glincker
/
levelrail
Free, self-hosted alternative to Vercel, Heroku, Railway, Coolify and Dokku. Push to git, get HTTPS, logs, metrics and one-click rollback on your own servers. One Go binary, no Kubernetes.
Levelrail
The lightweight, self-hosted alternative to Vercel, Heroku, Railway, Coolify and Dokku.
Push to git. Get HTTPS, logs, metrics and one-click rollback on your own servers.
One Go binary · Docker runtime · agents instead of SSH · observability built in · no Kubernetes
Website · Docs · Install · Production ready · Compare · Guides · Roadmap · Changelog · Discussions · Discord
Levelrail is an open source (Apache 2.0) self-hosted PaaS: a Vercel and Heroku alternative that runs on any Linux server you own, from a $5 VPS to a rack. It turns plain servers into a private cloud with Git deploys, automatic HTTPS, databases with verified backups, metrics, logs and alerts, without Kubernetes and without the monitoring stack you would otherwise bolt on.
Install in one command
Needs a Linux server (amd64 or arm64) with systemd and root. Docker is installed for you if…
If this post saved you time, a star on the repo helps other self-hosters find it. Bugs and feature requests go in the issue tracker.
GDS K S · thegdsks.com · building Glincker · follow on X @thegdsks
Leaving a platform gets easy once you write down everything it quietly did for you.

Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.