BENZUKO is a Next.js 15 app with server-side API routes and dynamic response
headers, so it must run as a live Node.js process on cPanel — via Phusion
Passenger. It is not a static-export site, so you cannot just drop HTML into
public_html.
This guide covers three paths: Git deployment, ZIP upload, and rollback — plus the caveats that actually bite people on shared hosting.
| Requirement | Why | If missing |
|---|---|---|
| Node.js Selector (Setup Node.js App) | Registers the app with Passenger | Ask host to enable, or use a VPS + PM2 (ecosystem.config.js) |
| Node 18.18+ (20 recommended) | Next.js 15 / React 19 requirement | Pick 20 in the app UI |
| SSH access | Run npm ci / npm run build reliably |
Use the UI “Run NPM Install” + build in CI instead |
| ~1 GB build memory & outbound network at build time | next build + Google Fonts fetch (next/font/google) |
Build in GitHub Actions or locally, upload the .next output |
The single most common failure is
next buildbeing killed on shared hosting (out of memory) or failing to fetch Google Fonts (no outbound network). If either happens, use the build-elsewhere strategy below.
A. Build on the server (VPS or generous shared plan): run npm ci then
npm run build in the app root over SSH.
B. Build elsewhere, upload artifacts (recommended for shared hosting):
build in CI or locally, then upload the repo including .next/ and install
production deps on the server. The included
.github/workflows/release-artifact.yml produces a ready-to-upload
benzuko-cpanel.zip on every tagged release.
Either way the app runs the custom server.js (Passenger entry point)
against the normal .next build. Standalone output is Docker-only and stays off
here (see next.config.js).
/home/CPANELUSER/benzuko — remember this exact path.benzuko (the SAME folder as the repo path above)server.jsnpm run build (or rely on .cpanel.yml, which does both)..cpanel.yml: replace CPANELUSER and confirm APP_ROOT. Commit..cpanel.yml installs deps, builds, and touches tmp/restart.txt to reload
Passenger.benzuko-cpanel.zip from the release-artifact workflow, ornpm ci && npm run build, then zip the project including
.next/, server.js, public/, package.json, package-lock.json
(exclude node_modules)./home/CPANELUSER/benzuko
and Extract.benzuko, startup server.js, Node 20)..next, you’re done. If not, run
npm run build in the venv terminal.If you ever deploy without the Node.js App UI, use
deploy/htaccess.passenger.templateto write the.htaccessby hand. When the UI manages the app, leave its generated.htaccessalone.
tmp/restart.txt trickPassenger reloads the app whenever tmp/restart.txt changes:
mkdir -p ~/benzuko/tmp && touch ~/benzuko/tmp/restart.txt
The Node.js App UI’s Restart button does the same thing.
Set these in Setup Node.js App → Environment variables (not a committed
.env):
| Variable | Value |
|---|---|
NODE_ENV |
production |
NEXT_PUBLIC_APP_URL |
https://yourdomain.com (fixes SEO/sitemap/robots) |
NEXT_PUBLIC_APP_NAME |
BENZUKO |
AUTH_SECRET |
long random string |
RATE_LIMIT_WINDOW_MS / RATE_LIMIT_MAX |
tune as needed |
Do not set PORT — Passenger assigns its own socket. See .env.example
for the full list.
/ in the Node.js App UI. Passenger serves it directly.next.config.js, so serve HTTPS before enabling it
publicly.644, directories 755, server.js 644.
Never 777.curl -I https://yourdomain.com # 200 + security headers
curl https://yourdomain.com/api/health # {"status":"ok",...}
Check ~/benzuko/tmp/passenger.log and the Node.js App UI logs if it 502s.
git reset --hard <sha> in the repo path over SSH), then touch
tmp/restart.txt..next + release ZIP. To roll back, re-extract
the prior ZIP over the app root and restart.benzuko-cpanel.zip from CI as your rollback artifact.| Symptom | Likely cause | Fix |
|---|---|---|
| 502 / “Incident” page | App crashed on boot | Read tmp/passenger.log; usually missing build or env var |
| Build killed / OOM | Shared-hosting memory cap | Build in CI/locally, upload .next |
| Build fails fetching fonts | No outbound network at build | Same — build where network exists |
| CSS/JS 404s | .next/static not uploaded |
Include the whole .next/ folder |
| Changes don’t show | Passenger cached old process | touch tmp/restart.txt |
| Node version errors | Selector on Node < 18.18 | Switch app to Node 20 |