Hosting Next.JS on Plesk + Passenger (in 2021)
Install the Node.JS version (X) you like/need
- Connect to the server via SSH (either directly as root user, change to root using
su
or try to usesudo
in front of all commands to gain write permissions on the needed folders) - Install NVM:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
- Restart the SSH connection. or source your terminal profile file:
source ~/.bashrc
orsource ~/.bash_profile
or whatever shell you’re using - Install Node.js version X:
nvm install X
(FYI: you can always switch node versions by runningnvm use X
- no need to be root user for that) - Copy the installed files to Plesk working directory:
List available versions:ls ~/.nvm/versions/node/
- Choose the one you’ve just installed and make it available to plesk (please note node 16 might actually be saved in v16.2.0):
cp -R ~/.nvm/versions/node/X/ /opt/plesk/node/
- Register the installed version in Plesk:
plesk sbin nodemng register /opt/plesk/node/X/bin/node
- Log in to Plesk and go to Extensions > Node.js.
- Click Refresh: to make sure that the newly installed. Once listed you will be able to select them while installing a plesk app on step 2.
To ensure that the “NPM Install” and “Execute Script” buttons on the plesk node app settings page do work with the correct version. You can also choose to register the just installed version globally accessible by creating symlinks to the currently choosen version:
ln -s /opt/plesk/node/v16.2.0/bin/node /usr/bin/node
ln -s /opt/plesk/node/v16.2.0/bin/npm /usr/bin/npm
More info:
https://support.plesk.com/hc/en-us/articles/115001630174-Node-js-versions-available-in-Plesk
https://talk.plesk.com/threads/usr-bin-env-node-no-such-file-or-directory.350987/
2. Create a Node.JS app in Plesk
Primarily follow (its a : https://raoulkramer.de/deploy-a-nuxt-js-application-on-a-plesk-onyx-v-server-as-node-js-application/
Please note that if you’ve symlinked the node versions above you can omit the full path to npm in the post deploy actions. Touching tmp/restart.txt will instruct the server to restart the next time a user hits the app
npm ci --scripts-prepend-node-path
npm run build --scripts-prepend-node-path
touch tmp/restart.txt
Use the --scripts-prepend-node-path
option to include the path. e.g. npm ci –scripts-prepend-node-path
to avoid executed scripts to run accidentally the wrong npm/node version
3. Next.JS + Plesk Passenger
It does work. With SSR and ISR but you need to tweak some things and be aware of the following.
Environment Variables
While you can configure environment variables in the Plesk settings next.js does not pick these up. You will need to provide a .env.local
file in the apps root. Do not commit the file into your repository. Further pulls/deploys keep it, you can place it right in the app root folder on the server (use SSH, SFTP or the file manager to adjust it to your needs).
Start Script.
You don’t need a custom server. But you can use the the next script node_modules/bin/next
as the start script.
Even if Plesk complains
it does work.
HOWEVER! Executing node_modules/bin/next
without any parameter (dev, build, start) does start the script in dev
mode.
As it is not currently (June 2021) possible to configure an „Application Startup File“ with a parameter: e.g. node_modules/bin/next start
(this breaks the passenger configuration). And the defaultCommand
of the start script can’t be changed. I had to create a clone of the script in the app root (called it next-start.js), change the defaulCommand from „dev“ to „start“, and adjust all requires to match the new location of the script.
What I did was
cp node_modules/bin/next next-start.js
- Then I edited the file to change
const defaultCommand = “dev”;
toconst defaultCommand = “start”;
- And replaced all
require(“../
andrequire(“next/dist/…
torequire(“./node_modules/next/dist/…
- I then pointed the application startup file to the new startup file and all works as it should
Here is a quick excerpt of the file.
#!/usr/bin/env node"use strict";var log = _interopRequireWildcard(require("./node_modules/next/dist/build/output/log"));
var _index = _interopRequireDefault(require("./node_modules/next/dist/compiled/arg/index.js"));
var _constants = require("./node_modules/next/dist/lib/constants");...const defaultCommand = "start";const commands = {build: () =>Promise.resolve().then(() => _interopRequireWildcard(require("./node_modules/next/dist/cli/next-build"))).then((i) => i.nextBuild),start: () =>Promise.resolve().then(() => _interopRequireWildcard(require("./node_modules/next/dist/cli/next-start"))).then((i) => i.nextStart),export: () =>Promise.resolve().then(() => _interopRequireWildcard(require("./node_modules/next/dist/cli/next-export"))).then((i) => i.nextExport),dev: () =>Promise.resolve().then(() => _interopRequireWildcard(require("./node_modules/next/dist/cli/next-dev"))).then((i) => i.nextDev),telemetry: () =>Promise.resolve().then(() => _interopRequireWildcard(require("./node_modules/next/dist/cli/next-telemetry"))).then((i) => i.nextTelemetry),};...if (command === "dev") {const { CONFIG_FILE } = require("./node_modules/next/dist/next-server/lib/constants");});}//# sourceMappingURL=next.map