cPanel shared hosting can run a Next.js app in two ways: as a fully static export, or as a Node.js application on a host that explicitly supports a Node runtime. A standard PHP-only shared plan cannot run Server Actions, dynamic routes or a Next.js server.
Key takeaways
- Ask the host three questions before you build: which Node versions, which application runtime (Passenger/Web Apps), and whether a custom start command is allowed.
- Static export is the safest option on constrained shared hosting; it removes the Node server but also removes Server Actions, dynamic rendering and built-in image optimisation.
- A Node deployment needs the standalone build, a startup file, environment variables and a process that the host keeps alive.
- Test HTTPS, redirects, forms, images and the 404 page on the real domain before calling it done.
First, find out what the host actually supports
cPanel is a control panel, not a runtime. Two hosts can show the same cPanel theme and have very different Node support. Before you upload anything, ask support for the following in writing.
| Question | Why it matters |
|---|---|
| Which Node.js versions are available? | Next.js requires a modern Node version; a mismatch breaks the build or runtime. |
| Is Passenger, Setup Node.js App or Web Apps enabled? | This determines how the application is started and kept alive. |
| Can I set a custom startup file and environment variables? | Next.js standalone needs server.js and production env values. |
| Is SSH or a terminal available? | You may need it to install dependencies or inspect logs. |
| What are the memory, process and entry-process limits? | Next.js builds and server rendering can exceed shared limits. |
| Which database and outbound ports are allowed? | Remote Postgres/MySQL and SMTP are often restricted. |
| Is cron available? | Scheduled jobs need a cron entry, not a long-running worker. |
Two deployment models
| Model | What works | What you lose |
|---|---|---|
Static export (output: 'export') | Pages, client components, static assets, contact forms via an external API | Server Actions, dynamic routes at request time, ISR, next/image optimisation, middleware |
| Node.js application | SSR, Server Actions, Route Handlers, dynamic routes, ISR with a writable cache | Requires a supported Node runtime, more memory and a process the host keeps alive |
Option A: deploy a static export
- Set the export config. In
next.config.ts, setoutput: 'export'andimages.unoptimized: trueunless you use a separate image CDN. - Build locally or in CI. Run
npm ciandnpm run buildwith the same Node major version the host will serve. - Find the output. Next.js writes the static site to
out/. - Upload the contents of
out/. Use cPanel File Manager or SFTP. Put the files inpublic_htmlor the domain's document root. - Add redirects and headers. Use
.htaccessfor redirects, HTTPS and cache headers. Test that the rules do not break Next.js routes. - Handle 404s. Create a
404.htmlin the export and point Apache at it, or use the host's error-page setting. - Test on the domain. Check every route, form, image, canonical URL and the trailing-slash behaviour.
Static export is a good fit for a marketing site, documentation, a portfolio or a client-rendered app that talks to an external API. It is a poor fit for authenticated dashboards that need server-side session checks, Server Actions or request-time personalisation.
Option B: deploy a Node.js application
- Build the standalone output. Set
output: 'standalone'and run the production build. The standalone folder containsserver.jsand the traced dependencies. - Assemble the upload. Copy
public/into.next/standalone/publicand.next/staticinto.next/standalone/.next/static. - Create the application in cPanel. Open the Node.js selector, choose the supported Node version, set the application root and the startup file to
server.js. - Install production dependencies. If the host does not include them in the upload, run
npm ci --omit=devin the application root using the host's Node environment. - Set environment variables. Add production values in the cPanel UI. Do not upload a
.envfile intopublic_html. - Start and map the domain. Start the app, confirm the temporary URL works, then map the domain and force HTTPS.
- Check logs and memory. Open the application logs, watch for restarts and confirm the process stays alive under a real request.
- Test the full journey. Auth callback, form submission, image loading, redirects, 404s and a hard refresh on a deep route.
Environment variables and secrets
- Keep
.envfiles outside the public web root and set permissions so they are not world-readable. - Use the cPanel environment-variable UI where possible; it survives redeploys better than a file.
- Never expose server keys through
NEXT_PUBLIC_*; those values are embedded in the browser bundle. - Use a separate database and auth callback for staging. A preview that writes to production is not a preview.
Images, caching and Server Actions
- With static export,
next/imagecannot optimise on the server; setunoptimized: trueor use a CDN with resizing. - With a Node app, keep the image optimiser enabled only if the host has enough memory and a writable cache.
- ISR needs a persistent, writable cache. If the host wipes the filesystem on restart, use static generation or on-demand revalidation with a durable cache.
- Server Actions require the Node runtime and a correct
NEXTAUTH_URL/site URL. Test them on the real domain, not just localhost.
Database, email and cron
Shared hosting often provides MySQL but not Postgres. If your app needs Postgres, confirm that a remote database is allowed and that outbound TLS works. Use a connection pool or a serverless driver, because shared process limits are low. For email, use an SMTP provider rather than the host's local mail service; transactional email needs authentication and delivery monitoring.
Use cPanel cron for scheduled tasks such as sitemap refresh, cleanup or reminders. Do not use it for long-running workers or queues. If the app needs background processing, run a separate worker on a VPS or a managed queue.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| 500 on every route | Node version mismatch or missing dependencies | Match the build/runtime version and reinstall production dependencies |
| Static assets 404 | Files uploaded to the wrong root | Put _next/static at the correct path inside the app root |
| Deep link 404 | Apache is not rewriting to the app | Configure the Node app or add the correct rewrite rules |
| Images broken | Image optimiser unavailable or static export | Use unoptimized or a CDN loader |
| Forms fail | Server Action/API route not running | Confirm the Node runtime and the site URL |
| App restarts randomly | Memory or process limit | Reduce concurrency, move to a larger plan or a VPS |
| HTTPS mixed content | Hard-coded http:// URLs | Use relative URLs or the production HTTPS origin |
When to move off shared hosting
- You need Server Actions, request-time personalisation or ISR with reliable caching.
- The app needs a Postgres database, Redis, WebSockets or background workers.
- The host cannot guarantee memory, process count or a supported Node version.
- You need preview deployments, rollbacks or observability that cPanel does not provide.
A small VPS with a deployment panel or a managed platform is often cheaper than the engineering time spent fighting shared-host limits. Move when the constraint is structural, not when a single support ticket can fix it.
Frequently asked questions
No. You need either static export support (any host can serve the files) or a Node.js application runtime. A PHP-only plan cannot run the Next.js server.
No. Server Actions require a running server. Static export produces HTML, CSS and JavaScript only.
Sometimes. Confirm the database type, remote access, connection limits and TLS. A remote Postgres database may be blocked or too slow from a shared host.
Build in CI or locally, upload the new output, and keep the previous release for rollback. For a Node app, restart the application after replacing the files.
The usual causes are a different Node version, missing environment variables, a case-sensitive Linux filesystem, a blocked outbound port or a process/memory limit.
Sources and further reading
- Next.js deployment guide (nextjs.org)
- Next.js self-hosting guide (nextjs.org)
- cPanel Node.js application documentation (docs.cpanel.net)
Related services
Stuck on a cPanel deployment?
Send the error, the Node version and the hosting plan. I will tell you whether it is fixable or whether a small VPS is the cheaper path.
How to cite this guide: Nur Hossain Repon, “How to Deploy a Next.js App to cPanel Shared Hosting”, Nhrepon Portfolio, reviewed October 2026, https://nhrepon.com/posts/deploy-nextjs-to-cpanel.





Comments
Frank
Shared this with my team.
Oct 17, 2026
Erin
Any chance of a follow-up on caching?
Oct 17, 2026