Deploying Next.js Beyond Vercel
Next.js is often associated with Vercel, but it's just a Node.js application — it runs anywhere Node runs. Here's how to deploy it on your Hetzner VPS.
Method 1: Coolify (Recommended)
If you've set up Coolify on your VPS, deploying Next.js is straightforward:
1. Connect your repo in Coolify's dashboard
2. Select "Nixpacks" or "Dockerfile" as the build method
3. Set environment variables in the Coolify UI
4. Add your domain — Coolify handles SSL automatically
5. Deploy
Coolify auto-detects Next.js and configures the build correctly.
Method 2: Docker
Create a Dockerfile in your project root:
FROM node:20-alpine AS base
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
Requires output: 'standalone' in your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
}
module.exports = nextConfig
Build and run:
docker build -t my-nextjs-app .
docker run -d -p 3000:3000 --name my-app my-nextjs-app
Method 3: Docker Compose
For apps with a database:
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/myapp
- NEXTAUTH_SECRET=your-secret
- NEXTAUTH_URL=https://yourdomain.com
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=myapp
restart: unless-stopped
volumes:
pgdata:
Production Considerations
Environment Variables: Never bake secrets into your Docker image. Use environment variables at runtime.
Health Checks: Add a health check endpoint:
// app/api/health/route.ts
export function GET() {
return Response.json({ status: 'ok' })
}
Reverse Proxy: Use Coolify's Traefik or set up Nginx/Caddy for:
- SSL termination
- HTTP → HTTPS redirect
- Gzip compression
- Static asset caching
Memory: A Next.js standalone server typically uses 100-200MB RAM. On a CPX42 with 16GB, you can run many instances.
Performance Tips
1. Enable standalone output — reduces deployed size by 80%+
2. Use sharp for image optimization — npm install sharp
3. Set proper cache headers for static assets
4. Use ISR/SSG where possible to reduce server load
5. Monitor with Netdata or similar
Our complete guide covers deploying Next.js as part of a full production stack, including database setup, SSL, monitoring, and CI/CD workflows.
Want the Complete Setup Guide?
This blog post covers the basics. Our premium guide includes step-by-step commands, exact configurations, and the solutions to every gotcha we encountered.