Migrate Your Next.js App from Vercel to Your Own Infrastructure
Introduction
Vercel is a fantastic platform for getting a Next.js app running in minutes. But as your application grows, the trade-off for that initial simplicity becomes clear: rising costs, platform lock-in, and a lack of control over your infrastructure.
This guide shows you how to self-host your Next.js application on your own VPS using Disco. The result? The same magical git-push-to-deploy
workflow you love, with predictable costs (from $5/month) and the freedom to run on any cloud provider you choose.
This is an advanced tutorial. It assumes you're comfortable provisioning a server and setting a DNS record. In exchange for that one-time setup, you get a powerful, open-source platform that you own and control.
Step 1 - Create a Server
You need a VPS to host your application. You can use any cloud provider:
Recommended providers:
- Digital Ocean - Easy to use, global locations
- AWS Lightsail or EC2 - If you're already on AWS
- Hetzner Cloud - Great EU performance
Minimum requirements:
- 2 GB RAM minimum (more is better for Next.js builds)
- Ubuntu 24.04 LTS
Create your server using your provider's dashboard and note down the IP address.
Step 2 - Configure DNS Settings
You need to set up two domains: one for your Disco server and one for your application.
Go to your domain registrar's DNS settings and create two A records:
A Server domain (e.g., disco.example.com
):
- Name:
disco
- Type:
A
- Value: Your server IP (e.g.,
203.0.113.1
) - TTL:
3600
(or leave default)
And an Application domain (e.g., app.example.com
):
- Name:
app
- Type:
A
- Value: Your server IP (e.g.,
203.0.113.1
) - TTL:
3600
(or leave default)
Example DNS configuration:
Type Name Value TTL
A disco 203.0.113.1 3600
A app 203.0.113.1 3600
DNS propagation can take a few minutes to several hours. Verify that your DNS records are properly set up:
ping disco.example.com
If you're seeing that ping
is hitting your server's IP, you are good to continue.
Step 3 - Install the Disco CLI
Important: Run this on your local machine, NOT on your server.
curl https://cli-assets.letsdisco.dev/install.sh | sh
Verify installation:
disco --version
Step 4 - Initialize Server with Disco
Initialize your server with Disco (this installs Docker, Caddy, and the Disco daemon) by running the following command on your own, local machine:
disco init root@disco.example.com
Replace disco.example.com
with your server domain from Step 2.
What this does:
- Installs Docker and Docker Swarm
- Installs the Caddy web server (handles HTTPS automatically)
- Installs the Disco daemon for deployment management
This process should take a few minutes.
Step 5 - Prepare Your Next.js Application
To deploy Next.js with Disco, you need to add a few files to your project:
- Configure Next.js for standalone mode in
next.config.js
ornext.config.ts
- Add a Dockerfile for building your app (see below for an example repo)
- Add a disco.json configuration file (see below as well)
See the complete example: Next.js Disco Example Repository
The key changes are:
- Setting
output: 'standalone'
in the Next.js config file - Using a multi-stage Docker build
- Exposing port 3000 in disco.json
Step 6 - Connect to GitHub
6.1 - Create a GitHub Repository
If you haven't already:
- Go to github.com and create a new repository
- Initialize git and push your code:
# Initialize git if needed
git init
# Add all files
git add .
# Commit
git commit -m "Initial commit with Disco configuration"
# Add remote and push
git remote add origin git@github.com:YOUR_USERNAME/my-nextjs-app.git
git push -u origin main
6.2 - Connect Disco to GitHub
Install the Disco GitHub App to enable automatic deployments:
disco github:apps:add
This will open a browser window. Authorize the Disco GitHub App and select your repository.
Step 7 - Deploy the Application
Create a new project on your Disco server. This will automatically trigger the first deployment:
disco projects:add \
--name my-nextjs-app \
--github YOUR_GITHUB_USERNAME/my-nextjs-app \
--domain app.example.com \
HOSTNAME=0.0.0.0
Replace app.example.com
with your application domain from Step 2, and YOUR_GITHUB_USERNAME/my-nextjs-app
with the path to your GitHub repo.
The first build will take 2-5 minutes as Docker downloads base images and builds your application. Further deployments will be faster thanks to layer caching.
Step 8 - Test the Deployed Application
Once deployment completes, visit your domain:
open https://app.example.com
What to verify:
- Homepage loads correctly
- HTTPS certificate is valid (automatic via Let's Encrypt)
- Images are loading
- API routes work (test with
/api/...
endpoints) - Dynamic routes render correctly
Step 9 - Automatic Deployments
Now that everything is set up, any git push
to your main
branch will automatically trigger a deployment. Disco detects the push and immediately deploys your changes. You can follow the deployment output by running:
disco deploy:output --project my-nextjs-app
FAQ
What Next.js features work with self-hosting?
Standard Next.js features work perfectly: SSR, SSG, API Routes, App Router, Pages Router, middleware (runs on Node.js), and image optimization (using the sharp
library).
What doesn't work?
Vercel-specific features like Edge Functions, Edge Middleware, and Vercel Analytics won't work. Use standard alternatives instead.
How do I set environment variables?
Use the Disco CLI:
disco env:set --project my-nextjs-app DATABASE_URL "postgresql://..."
The command above will automatically trigger a redeploy.
Do I need to modify my existing Next.js app?
Yes. The minimal changes are:
- Add
output: 'standalone'
to next.config.js - Add a
Dockerfile
(see example repo) - Add
disco.json
configuration file (see repo as well)
What if my images aren't loading?
Verify sharp
is installed (automatic in Next.js 15+). For Next.js 14 and below, add to package.json:
"sharp": "^0.33.0"
How can I improve global performance?
Consider adding a CDN like Cloudflare in front of your deployment for better global distribution and caching.
Need help?
If you have questions or run into issues:
- Email us: info@letsdisco.dev
- Join our Discord: discord.gg/7J4vb5uUwU