Self-Hosting Next.js with Contabo VPS and Dokploy: A Step-by-Step Guide
Learn how to self-host your Next.js applications on Contabo VPS using Dokploy. A cost-effective, high-performance alternative to Vercel with push-to-deploy, automatic SSL, and multi-app support.
Self-Hosting Next.js Apps with Contabo VPS and Dokploy
Self-hosting your Next.js applications doesn't have to be complicated or expensive. In this guide, we'll walk through setting up a professional-grade deployment pipeline using Contabo VPS and Dokploy.
[!NOTE] This setup provides a Vercel-like experience (push-to-deploy, automatic SSL, dashboard) at a fraction of the cost, giving you full control over your infrastructure.
📋 Table of Contents
- Why This Setup?
- Contabo VPS vs. Alternatives
- Contabo VPS Plans
- Prerequisites
- Step 1: Setting Up Your Contabo VPS
- Step 2: Installing Dokploy
- Step 3: Connecting GitHub to Dokploy
- Step 4: Deploying Your Next.js App
- Step 5: Custom Domains and SSL
- Step 6: Add Analytics with Umami
- Step 7: Hosting a Database
- Troubleshooting
- Scaling Your Setup
What You'll Get
By the end of this guide, you'll have:
- ✅ A Contabo VPS server running Ubuntu
- ✅ Dokploy managing your deployments with a clean dashboard
- ✅ Automatic deployments triggered by GitHub pushes
- ✅ SSL certificates via Traefik + Let's Encrypt
- ✅ Multiple apps running on a single VPS
- ✅ Cost: ~$5–$8/month vs $20–$100+ on managed platforms
🚀 Why This Setup?
| Benefit | Description |
|---|---|
| 💰 Cost Effective | Contabo offers high specs (up to 6 vCPU & 12 GB RAM) starting at ~$8/month. |
| 🎓 Educational | Gain deep understanding of server management and DevOps. |
| 📦 Scalable | Easily host multiple apps, databases, and services on a single node. |
| 🔓 No Lock-in | Full root access gives you total control over your deployment environment. |
📊 Contabo VPS vs. Alternatives
| Feature | Contabo + Dokploy | Vercel | Railway |
|---|---|---|---|
| Monthly Cost | ~$8 | $20+ (Pro) | $5–$20+ |
| Multiple Apps | ✅ Unlimited | ⚠️ Limited | ⚠️ Limited |
| Automatic SSL | ✅ Included | ✅ Included | ✅ Included |
| Push-to-Deploy | ✅ GitHub | ✅ GitHub | ✅ GitHub |
| Database Hosting | ✅ Same server | ❌ Separate | ✅ Add-on |
| Full Root Access | ✅ Yes | ❌ No | ❌ No |
| Traffic | Unlimited | Limited | Limited |
📑 Contabo VPS Plans
| Plan | vCPU | RAM | Storage | Price/mo |
|---|---|---|---|---|
| Cloud VPS 10 | 3 vCPU | 8 GB | 75 GB NVMe | ~$5 |
| Cloud VPS 20 ★ | 6 vCPU | 12 GB | 200 GB NVMe | ~$8 |
| Cloud VPS 30 | 8 vCPU | 24 GB | 300 GB NVMe | ~$15 |
[!TIP] > Cloud VPS 20 is the sweet spot. It provides enough power to run 5+ Next.js apps, a PostgreSQL instance, and analytics without breaking a sweat.
Prerequisites
- Basic terminal / command line knowledge
- A GitHub account with your Next.js project
- A domain name (optional but required for SSL)
- A credit card for Contabo (~$5–$8/month)
Step 1: Setting Up Your Contabo VPS
1.1 Create a Contabo Account
- Visit contabo.com/en/vps
- Click "Get Started" under your chosen plan
- Create an account and verify your email
- Add a payment method (credit card or PayPal)
- Complete the order — Contabo will email you your server credentials within minutes
Note: Contabo sends your root password via email after provisioning. Keep it safe.
1.2 Generate an SSH Key
Before connecting to your server, generate a secure SSH key on your local machine.
On Mac / Linux:
ssh-keygen -b 4096 -t rsa -C "your-email@example.com"Get your public key:
cat ~/.ssh/id_rsa.pubCopy the entire output — you'll need it shortly.
On Windows (PowerShell):
ssh-keygen -b 4096 -t rsa
type $env:USERPROFILE\.ssh\id_rsa.pub1.3 Access Your Server for the First Time
Contabo will email you:
- IP address of your server
- Root password
SSH into the server using the password:
ssh root@YOUR_SERVER_IPAccept the fingerprint prompt by typing yes. You'll be asked to change your root password on first login — do it immediately.
1.4 Add Your SSH Key (Recommended)
Once logged in, add your SSH public key so you can log in without a password:
mkdir -p ~/.ssh
echo "YOUR_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keysNow you can log in with just:
ssh root@YOUR_SERVER_IP1.5 Update Your Server
Always update your packages after first login:
apt update && apt upgrade -yStep 2: Installing Dokploy
2.1 Run the Dokploy Installer
While still SSH'd into your server, run the official Dokploy install script:
curl -fsSL https://dokploy.com/install.sh | shThis installer will:
- Install Docker and Docker Compose
- Set up Traefik as a reverse proxy (handles SSL automatically)
- Configure the Dokploy dashboard
- Take approximately 1–3 minutes
2.2 Access the Dokploy Dashboard
Once the install completes, you'll see a URL in the terminal output.
- Open your browser and visit:
http://YOUR_SERVER_IP:3000
- You'll be prompted to create your admin account:
- Choose a strong username
- Set a secure password
- This is your main Dokploy admin account
2.3 Enable Two-Factor Authentication
- Go to Settings in the Dokploy dashboard.
- Navigate to Security.
- Enable 2FA using an authenticator app (Google Authenticator, Authy, etc.).
[!IMPORTANT] Always enable 2FA on any dashboard exposed to the public internet to prevent unauthorized access.
Step 3: Connect GitHub to Dokploy
3.1 Create a GitHub App
- In the Dokploy dashboard, navigate to Settings → Git
- Click "Connect GitHub"
- Click "Create GitHub App"
- Choose a unique app name, e.g.:
dokploy-yourusername-2024
GitHub app names must be globally unique — add random digits if needed.
3.2 Install the GitHub App
- After creating the app, click "Install"
- Select the GitHub account / organization
- Choose:
- All repositories — for full access, or
- Select repositories — for specific repos only
- Complete the authorization
3.3 Verify the Connection
Go back to Dokploy. Your GitHub repositories should now be visible in dropdowns throughout the dashboard. If they don't appear immediately, wait 30 seconds and refresh.
Step 4: Deploy Your Next.js Application
4.1 Prepare Your Next.js Project
If you don't have a project yet, create one:
pnpm create next-app@latest my-dokploy-app
cd my-dokploy-app
Push it to GitHub:
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/my-dokploy-app.git
git push -u origin main4.2 Create a Project in Dokploy
- In the Dokploy dashboard, click "Create Project"
- Enter a name:
my-nextjs-app - Click "Create"
4.3 Add an Application Service
- Inside your project, click "Add a Service"
- Select "Application" (not Template or Database)
- Name it:
next-frontend - Click "Create"
4.4 Configure the Application
Repository Settings:
| Field | Value |
|---|---|
| Repository | Select your GitHub repo |
| Branch | main |
| Build Path | / (root) |
| Build Pack | Next |
| Port | 3000 |
Domain:
- Click "Generate" for a random test subdomain, or
- Enter your own:
https://myapp.yourdomain.com
⚠️ HTTPS / SSL only works with a proper domain name, not with an IP address.
Environment Variables (if needed):
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
NODE_ENV=production4.5 Deploy the Application
- Click "Save" to store your configuration
- Click "Deploy"
- Watch the build logs in real time
- Wait for the "Deployment successful" message (typically 1–3 minutes)
4.6 Test Auto-Deployment (Push-to-Deploy)
Make a small change and push to GitHub:
# App Router
cat > app/page.tsx << 'EOF'
export default function Home() {
return <h1>Hello from Contabo + Dokploy! 🚀</h1>;
}
EOF
git add .
git commit -m "Test auto-deploy"
git push origin mainDokploy will automatically detect the GitHub push via webhook and trigger a new deployment. Check the "Deployments" tab — it should show as "webhook" initiated.
Step 5: Configure a Custom Domain and SSL
5.1 Point Your Domain to the Server
In your DNS provider (Cloudflare, Namecheap, etc.), add the following A records:
| Record | Host | Value |
|---|---|---|
| A | @ | YOUR_SERVER_IP |
| A | * | YOUR_SERVER_IP |
| A | www | YOUR_SERVER_IP |
DNS propagation can take 5–60 minutes.
5.2 Using Cloudflare (Recommended)
- Add your domain to Cloudflare
- Update your domain's nameservers to Cloudflare's
- Add your server IP as an A record
- Enable "Proxied" (orange cloud) for DDoS protection
5.3 Set Custom Domain in Dokploy
- Go to your application in Dokploy
- Under "Domains", replace the generated subdomain with your real domain:
https://myapp.yourdomain.com
- Save the settings
- Dokploy + Traefik will automatically generate an SSL certificate via Let's Encrypt
✅ Your app is now live at
https://myapp.yourdomain.comwith a valid SSL certificate.
Step 6: Add Analytics with Umami (Optional)
6.1 Deploy Umami from a Dokploy Template
- Inside your project, click "Add a Service"
- Select "Template"
- Find and select "Umami"
- Name it:
analytics - Set a domain:
analytics.yourdomain.com - Click "Deploy"
6.2 Configure Umami
- Visit your Umami URL after deployment
- Log in with default credentials:
- Username:
admin - Password:
umami
- Username:
- ⚠️ Change the password immediately under Settings → Profile
6.3 Add Your Website to Umami
- In Umami → Settings → Websites
- Click "Add Website"
- Enter:
- Name: Your app name
- Domain:
https://myapp.yourdomain.com
- Go to the Tracking Code tab and copy the script
6.4 Integrate Umami into Your Next.js App
App Router (app/layout.tsx):
import Script from "next/script";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<Script
async
src="https://analytics.yourdomain.com/script.js"
data-website-id="YOUR_WEBSITE_ID"
strategy="afterInteractive"
/>
</head>
<body>{children}</body>
</html>
);
}Pages Router (pages/_app.tsx):
import Script from "next/script";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Script
async
src="https://analytics.yourdomain.com/script.js"
data-website-id="YOUR_WEBSITE_ID"
strategy="afterInteractive"
/>
<Component {...pageProps} />
</>
);
}Commit and push — Dokploy will auto-deploy with analytics enabled.
Step 7: Hosting a Database (PostgreSQL / MySQL)
7.1 Add a Database Service in Dokploy
- Inside your project, click "Add a Service"
- Select "Database"
- Choose PostgreSQL (or MySQL / MongoDB)
- Set a name:
postgres-db - Configure:
- Database name
- Username
- Password (use a strong password)
- Click "Create"
7.2 Connect Your Next.js App to the Database
Dokploy will show you the internal connection string. Add it to your app's environment variables:
DATABASE_URL=postgresql://username:password@postgres-db:5432/mydbInternal service names (e.g.,
postgres-db) are used instead oflocalhostwhen connecting between Dokploy services on the same server.
Step 8: Monitor Your Server
8.1 Dokploy Built-in Monitoring
Dokploy provides a built-in monitoring panel showing:
- CPU usage per container
- Memory consumption
- Disk I/O
- Network traffic
Access it via the "Monitoring" tab in your dashboard.
8.2 SSH-Based Monitoring
SSH into your server for real-time resource inspection:
ssh root@YOUR_SERVER_IP
# Real-time CPU and memory
htop
# Disk space
df -h
# Docker containers
docker ps
# Container logs
docker logs <container_id>
# Resource usage per container
docker statsTroubleshooting
SSL Certificate Not Generating
Symptom: HTTPS shows an error or certificate is not valid
- Make sure your DNS A record is pointing to the correct server IP
- Wait for DNS propagation (can take up to 1 hour)
- Ensure port 80 and 443 are open on your server
- Check Traefik logs:
docker logs traefik
Deployment Failing
Symptom: Build errors in the Dokploy logs
- Check the exact error in Deployment Logs
- Verify your
package.jsonhas a validbuildscript:
{
"scripts": {
"build": "next build",
"start": "next start"
}
}- Ensure all required environment variables are set in Dokploy
GitHub Webhook Not Triggering
Symptom: Pushing to GitHub doesn't trigger a new deployment
- Verify the GitHub App has access to the repository
- In Dokploy, go to Settings → Webhooks and check the webhook URL
- Try a manual deploy first to confirm the configuration works
- Re-install the GitHub App if the webhook URL has changed
High Memory / CPU Usage
Symptom: Server is slow or containers are crashing
# Check resource usage
htop
# Check which containers are using the most resources
docker stats --no-stream
# Restart a specific service
docker restart <container_name>Consider upgrading to Cloud VPS 30 if you're running many services.
Port Already in Use
Symptom: Container fails to start, port conflict error
# Find what's using the port
lsof -i :3000
# Kill the process if needed
kill -9 <PID>Cost Breakdown
Monthly Costs with Contabo
| Item | Cost |
|---|---|
| Contabo Cloud VPS 20 | ~$7.99/month |
| Domain name (optional) | |
| Total | ~$9/month |
Compared to Managed Platforms
| Platform | Monthly Cost |
|---|---|
| Contabo + Dokploy | ~$8–9/month |
| Vercel Pro | $20/month + usage |
| Railway | $5–20+/month |
| Render | $7–25+/month |
| DigitalOcean App Platform | $12–25+/month |
💡 Savings: 60–80% cost reduction while maintaining identical functionality — push-to-deploy, SSL, custom domains, and analytics.
Scaling Your Setup
Multiple Applications on One VPS
Each app gets its own subdomain automatically. On a Cloud VPS 20 (6 vCPU, 12 GB RAM), you can comfortably run:
- 3–5 production Next.js apps
- 1–2 databases (PostgreSQL, MySQL)
- Analytics (Umami)
- Background services (Redis, queues)
When to Upgrade
| Signal | Action |
|---|---|
| CPU consistently > 70% | Upgrade to Cloud VPS 30 |
| RAM > 80% usage | Upgrade or optimize containers |
| Disk > 80% | Expand storage or add a volume |
| > 5 apps running | Upgrade to Cloud VPS 30 or add a second server |
Advanced Dokploy Features
- Docker Swarm — container orchestration for high availability
- Multi-server management — manage multiple VPS instances from one dashboard
- Load balancer — distribute traffic across servers
- Database clustering — redundant database setups
Quick Reference
Useful Commands
# SSH into server
ssh root@YOUR_SERVER_IP
# View all running containers
docker ps
# View Dokploy logs
docker logs dokploy
# Restart Dokploy
docker restart dokploy
# View Traefik (reverse proxy) logs
docker logs traefik
# Check disk usage
df -h
# Check memory
free -h
# Update server packages
apt update && apt upgrade -yDokploy Dashboard URLs
| Page | Path |
|---|---|
| Dashboard | http://YOUR_SERVER_IP:3000 |
| Projects | /dashboard/projects |
| Settings | /dashboard/settings |
| Monitoring | /dashboard/monitoring |
Next Steps
After completing this guide, consider:
- Set up a staging environment — deploy a
stagingbranch to a separate subdomain - Configure backups — use Contabo's snapshot feature or a backup script for your database
- Set up alerts — configure uptime monitoring via UptimeRobot or Betterstack (both have free tiers)
- Harden your server — configure UFW firewall, disable root password login, use fail2ban
- Add Redis — deploy a Redis instance in Dokploy for caching and session storage
- Explore Dokploy templates — one-click deploys for Ghost, WordPress, Plausible, n8n, and more
Conclusion
You now have a production-ready Next.js deployment pipeline that rivals managed platforms at a fraction of the cost. The combination of Contabo's affordable, high-spec VPS and Dokploy's developer-friendly interface gives you everything you need:
- 🚀 Push-to-deploy from GitHub
- 🔒 Automatic SSL certificates
- 📊 Self-hosted analytics
- 🗄️ Integrated database hosting
- 💰 80% cost savings vs. managed platforms
Self-hosting gives you full control over your infrastructure, eliminates vendor lock-in, and — most importantly — teaches you skills that make you a significantly better developer.
Built with ❤️ — Adapted from the original Hetzner + Dokploy guide. Updated for Contabo VPS.