Setup reverse proxy NodeJS
Setup reverse proxy NodeJS
This example creates a small Node.js 20+ application inside the Devilbox PHP container, runs it with pm2, and proxies the virtual host to the Node process through the Devilbox vhost-gen reverse proxy templates.
Overview
| Project name | Container path | Database | TLD_SUFFIX | Project URL |
|---|---|---|---|---|
my-node | /shared/httpd/my-node | none | lvh.me | http://my-node.lvh.me / https://my-node.lvh.me |
The Node.js application listens on port 4000 inside the PHP container. Devilbox HTTPD proxies requests from my-node.lvh.me to php:4000.
Prerequisites
- Devilbox installed with PHP, HTTPD, and Bind services.
- Node.js 20 LTS or newer and
pm2available in the selected PHP image. - Docker Compose v2 through Docker.
Start the stack:
./dvl.sh up php httpd bindWalk through
It will be ready in nine steps:
- Enter the PHP container.
- Create a new virtual host directory.
- Create a Node.js application.
- Create a placeholder
htdocsdirectory. - Add reverse-proxy vhost-gen config files.
- Create an autostart script.
- Verify DNS.
- Restart Devilbox.
- Open the project in a browser.
1. Enter the PHP container
./dvl.sh shell php83Confirm the runtime:
node --versionpm2 --versionUse Node.js 20 LTS or newer.
2. Create the vhost directory
mkdir -p /shared/httpd/my-nodecd /shared/httpd/my-node3. Create the Node.js application
mkdir srcvi src/index.jsimport http from 'node:http';
const server = http.createServer((request, response) => { response.writeHead(200, { 'Content-Type': 'text/plain' }); response.end('Hello from Node.js 20 on Devilbox\n');});
server.listen(4000, '0.0.0.0');Add a minimal package file:
cat > package.json <<'JSON'{ "type": "module", "scripts": { "start": "node src/index.js" }, "engines": { "node": ">=20" }}JSON4. Create a placeholder docroot
Reverse-proxy projects still need an htdocs directory so the Devilbox intranet recognizes the virtual host.
mkdir htdocs5. Add reverse-proxy vhost-gen config files
Leave the container and copy the reverse-proxy templates from the Devilbox directory on the host:
exitcd /path/to/devilboxmkdir -p data/www/my-node/.devilboxcp cfg/vhost-gen/apache22.yml-example-rproxy data/www/my-node/.devilbox/apache22.ymlcp cfg/vhost-gen/apache24.yml-example-rproxy data/www/my-node/.devilbox/apache24.ymlcp cfg/vhost-gen/nginx.yml-example-rproxy data/www/my-node/.devilbox/nginx.ymlEdit each copied template and change the upstream port from 8000 to 4000.
Apache templates should contain:
ProxyPass / http://php:4000/ProxyPassReverse / http://php:4000/The Nginx template should contain:
location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://php:4000;}6. Create an autostart script
Copy the Node.js autostart template and register your app path:
cd /path/to/devilboxcp autostart/run-node-js-projects.sh-example autostart/run-node-js-projects.shvi autostart/run-node-js-projects.shSet the project list to the internal container path:
NODE_PROJECTS=( "/shared/httpd/my-node/src/index.js")If your template starts files directly with pm2, keep that behavior. If you prefer npm scripts, use a small custom startup command that runs pm2 start npm --name my-node -- start from /shared/httpd/my-node.
7. Verify DNS
my-node.lvh.me resolves to localhost by default. For another suffix, add a hosts-file record.
8. Restart Devilbox
./dvl.sh restartOr recycle only the required services:
./dvl.sh down./dvl.sh up php httpd bind9. Open your browser
Visit http://my-node.lvh.me or https://my-node.lvh.me. The web server proxies the request to the Node.js process on port 4000.
Managing Node.js
Enter the container and inspect pm2:
./dvl.sh shell php83pm2 listpm2 logs my-nodeFor a one-off status check from the host, run:
./dvl.sh exec "pm2 list"Next steps
- Move larger Node services to a dedicated container when they need separate dependencies.
- Configure trusted HTTPS before testing browser APIs.
- Keep ports unique when multiple reverse-proxy apps run in the PHP container.