Next.js on CloudMagnus
Next.js with React installed and a placeholder app/page.tsx. Build locally, deploy via SFTP, run next start on the allocated port. The platform handles the nginx reverse-proxy, SSL, and the upstream port allocation.
What our scaffold installs
npm init -yinhtdocs/npm install next react react-dom- A minimal
next.config.jswithreactStrictMode: true - A placeholder
app/page.tsxrendering "Next.js site ready." - An allocated port from the 3000-3999 pool (visible on Site Detail)
- nginx vhost reverse-proxying to
127.0.0.1:<allocatedPort>with WebSocket upgrade headers passed through - Node 22 by default; pickable at provision time (18, 20, or 22)
What you do next
- SSH in (Site Detail → SFTP credentials work for SSH too).
- Run
npx next dev --port <allocatedPort>to confirm the placeholder responds. - Replace the placeholder app with your real code. Build locally with
next build; ship the source +.next/output via SFTP, or runnext buildover SSH. - Run
npx next start --port <allocatedPort>as your production process (under a process manager — see below).
The allocated port is shown on the site detail page; substitute it for <allocatedPort> in the commands above.
Where your files live
/home/<site-user>/
├── htdocs/ ← your Next.js project root
│ ├── app/ ← App Router pages (or pages/ for Pages Router)
│ ├── public/ ← static assets
│ ├── .next/ ← build output (gitignored, build-time)
│ ├── node_modules/ ← npm install output
│ ├── package.json
│ ├── next.config.js
│ └── server.js ← optional custom server
└── logs/ ← nginx logs (your Node process logs go where you point them)
Build pipeline
CloudMagnus does NOT run next build for you on deploy. Pick the workflow that fits your team:
- Build locally / in CI, ship artifacts. Run
next buildon your laptop or in GitHub Actions. SFTP up your project including.next/andnode_modules/(or runnpm ci --omit=devon the server after upload). Runnext starton the server. - Build on the server. SSH in,
npm install,next build. Slower and uses server CPU during the build, but the deploy is one git push + one ssh command.
Neither is automatic. We don't have CI integration today; whatever process you set up over SSH or via your CI is yours to maintain.
Process management
next start needs to keep running. Three reasonable options:
- pm2 (most common):
npm install pm2 && ./node_modules/.bin/pm2 start "npx next start --port <port>" --name nextjs && ./node_modules/.bin/pm2 save. To survive reboots, set uppm2 startupvia the user's crontab. - systemd user unit: if you have
loginctl enable-linger <site-user>available (ask support to enable), drop a unit at~/.config/systemd/user/nextjs.serviceandsystemctl --user enable --now nextjs. - nohup for low-stakes sites:
nohup npx next start --port <port> > ~/logs/next.log 2>&1 &. Restart manually after a deploy.
App Router vs Pages Router
The placeholder uses the App Router (app/page.tsx). If you're using the Pages Router, replace the app/ directory with pages/ and adjust accordingly. Either is fine; nothing in our hosting cares about which you use.
Image optimization
Next.js's built-in next/image works with the default loader. The optimization runs on your Node process, not on a CDN. For high-traffic image-heavy sites, consider one of:
- Routing through Cloudflare's image resizing (set the loader to a Cloudflare URL pattern)
- An external image CDN (imgix, ImageKit, etc.) — set the loader accordingly
- Pre-generating sizes at build time with a custom loader
Environment variables
Next.js reads .env.production at build time for any NEXT_PUBLIC_* variables (baked into the client bundle) and at runtime for everything else. Add the file to your project root, set mode 600, and reference variables via process.env.X as usual.
Don't put secrets in NEXT_PUBLIC_* — they end up in the client bundle, visible to anyone who views your page source.
Deploying changes
- Build locally / CI:
npm ci && npm run build - SFTP or rsync the project (or just the changed files) to
~/htdocs/ - SSH in and restart your process:
pm2 restart nextjs(or whatever the equivalent is for your manager)
Zero-downtime deploys are doable with two ports + nginx upstream switching, but require manual configuration in CloudPanel; v1's vhost points at one fixed port. Most customers find a 1-2 second restart blip acceptable.
Logs
~/logs/nginx/error.log ← nginx errors (proxy failures, etc.)
~/logs/nginx/access.log ← request log
<your-app-output> ← wherever you redirect Node stdout/stderr
(pm2 stores logs in ~/.pm2/logs/ by default)
The platform doesn't capture your Node app's console output unless you redirect it explicitly. Common pattern: pm2 logs nextjs --lines 200 for live-tailing.
Migrating from another host
Easier than most because Next.js apps are mostly self-contained:
- Add the site on CloudMagnus, let it provision, get your allocated port.
- Push your code to your git repo (or rsync directly).
- SSH in, clone/pull,
npm ci,next build. - Start the process on the allocated port.
- Switch DNS A records.
If you came from Vercel, anything that depended on Vercel's edge runtime (middleware, image optimization at the CDN, ISR with on-demand revalidation) will need adapting. Edge middleware works (it runs on your Node process); ISR works but invalidation is your responsibility.
Common Next.js issues
"Module not found" after deploy
npm install wasn't run on the server, or node_modules/ wasn't shipped. SSH in and run npm ci.
"Cannot find module 'next/dist/build'"
You uploaded source without node_modules/ AND haven't run install on the server. Either ship node_modules/ too, or run install over SSH.
SSR data fetching slow
Each request hits your server-side fetch calls. If those are slow, your pages are slow. CloudMagnus doesn't add caching in front of SSR; consider Next's revalidate options for ISR or fronting with Cloudflare for full-page cache.
Static pages serve stale content
Next.js's static cache lives in .next/. If you replaced the build output, restart next start so it picks up the new bundle. pm2 reload nextjs is safest.
WebSocket connections fail
Our reverse-proxy passes the standard upgrade headers, so app-side WebSockets (e.g. Socket.IO over HTTP) work. If you're seeing 502s on upgrade, double-check that your app actually listens on the allocated port and that your code accepts upgrade: websocket headers.
503 errors
Your Node process isn't running on the allocated port. Check pm2 list over SSH; restart if needed. nginx shows 503 when the upstream is gone.
Build runs out of memory
Default NODE_OPTIONS might be too tight. Try NODE_OPTIONS='--max-old-space-size=2048' next build. If you're consistently hitting this, your build is probably fine on a beefier tier.
What CloudMagnus doesn't do for Next.js
- Build your app on deploy.
- Manage your
next startprocess (you bring pm2 / systemd / nohup). - Provide an edge cache (use Cloudflare or Next ISR).
- Run image optimization off-node (runs on your Node process by default).
Going further
For nginx tuning beyond the v1 defaults (e.g. larger proxy buffers for big SSR payloads, custom error pages, or dropping the WebSocket upgrade if you don't use it), open CloudPanel from the site detail page and edit the vhost there. Our wizard ships sane defaults; CP exposes the rest.