Deploy a Node.js app as a dedicated systemd service, bind it to a private loopback port, and let Nginx handle public HTTP, HTTPS, routing, and WebSocket proxying. This arrangement starts the app at boot, restarts it after failures, centralizes logs in the journal, keeps the Node listener off the public network, and gives you one place to manage TLS.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
How the deployment fits together
A production installation has three cooperating parts:
As an Amazon Associate I earn from qualifying purchases.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Node.js: your application process listens on a local port such as
127.0.0.1:3000. - systemd: the operating system service manager starts Node at boot, tracks its process, applies restart behavior, and records stdout and stderr in the journal.
- Nginx: the public edge server accepts connections on ports 80 and 443, terminates TLS, adds forwarding headers, and proxies requests to Node.
Users therefore connect to your domain and Nginx, not directly to Node. Keeping Node on loopback prevents clients from bypassing Nginx’s TLS and routing rules. If Nginx is not the only entry point (for example, another proxy or a private network is involved), choose the bind address and firewall policy deliberately instead of exposing the application by default.
Prepare the host and application
Confirm the runtime and operating-system prerequisites
Use a supported Linux distribution with systemd and install the Node.js version required by the application. Verify the runtime as the same user that will run the service:
#1 Best Overall
- [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
- [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
- [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
- [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
- [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
node --version
npm --version
systemctl --version
Install Nginx from your distribution’s supported package source or from an approved package repository. The exact package command and configuration-directory layout vary by distribution, so use the paths supplied by that distribution.
Create a non-root service identity
Do not run the application as root. Create a dedicated account and group, with no interactive administration privileges, then give it ownership of only the application files and directories it must write.
sudo useradd --system --home /srv/myapp --shell /usr/sbin/nologin myapp
sudo install --directory --owner=myapp --group=myapp /srv/myapp
If your distribution uses a different system-account command or shell path, use its equivalent. Keep deployment files, uploads, logs, and secrets in separate directories when that makes permissions easier to audit.
Deploy a stable application directory
Place the release in a path that will not change between reboots, such as /srv/myapp/current, or use a versioned-release layout with a stable current link. Install production dependencies and verify the app’s start command before involving Nginx.
sudo -u myapp npm ci --omit=dev
sudo -u myapp node /srv/myapp/current/server.js
Adapt the entry point and dependency command to the project. The application should read its port from an environment variable where practical and listen on loopback:
HOST=127.0.0.1 PORT=3000 node /srv/myapp/current/server.js
Before creating the service, test the local endpoint from the server itself:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Rank #2
- 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
- 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
- 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
- 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
- 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.
curl --fail http://127.0.0.1:3000/
A successful local response proves that the runtime, files, dependencies, and bind address are working independently of Nginx.
Create a systemd unit for Node.js
Write the service file
Create /etc/systemd/system/myapp.service. Use an absolute path for both Node and the application entry point. A shell-specific command such as node may work in your terminal but fail under systemd because systemd does not load your interactive shell profile.
[Unit]
Description=My Node.js application
After=network.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/srv/myapp/current
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=HOST=127.0.0.1
# Use the path returned by: command -v node
ExecStart=/usr/bin/node /srv/myapp/current/server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Replace /usr/bin/node with the actual absolute executable path. If Node was installed with a version manager, point ExecStart at that installation’s binary and ensure the service account can traverse every parent directory. A system-wide Node installation is often simpler for a server service.
Put configuration in an environment file when needed
Environment variables can be declared in the unit, but credentials and a larger configuration set are easier to manage in a root-readable environment file:
[Service]
EnvironmentFile=/etc/myapp/myapp.env
sudo install --directory --mode=0750 --owner=root --group=myapp /etc/myapp
sudo sh -c 'umask 027; cat > /etc/myapp/myapp.env' <<'EOF'
NODE_ENV=production
PORT=3000
HOST=127.0.0.1
# DATABASE_URL=...
EOF
sudo chown root:myapp /etc/myapp/myapp.env
sudo chmod 0640 /etc/myapp/myapp.env
Do not place secrets in a world-readable file or in a unit that is copied into public documentation. Confirm that the application understands the variable names you provide; systemd does not transform them into application-specific settings.
Load, enable, and inspect the service
After every unit-file change, reload systemd’s configuration, then enable the service for boot and start it immediately:
Rank #3
- [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
- [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
- [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
- [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
- [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
sudo systemctl status myapp.service
sudo journalctl -u myapp.service
enable --now creates the boot-time link and starts the process in one operation. Use journalctl -u myapp.service -f to follow live output while testing. A failed start normally means an incorrect executable path, missing permissions, a wrong working directory, an unavailable environment variable, or an application that exits during startup.
Configure Nginx as the reverse proxy
Define the Node upstream and virtual host
Create a server configuration in the location used by your distribution. The upstream gives the backend a name; the server block maps your hostname to it.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →upstream node_backend {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://node_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Replace the hostnames and port with your values. The forwarding headers preserve the original host, client address, proxy chain, and protocol so the application can construct correct URLs and log the originating request. Make sure the Node framework is configured to trust the appropriate proxy headers; trusting every proxy indiscriminately can make client-IP and HTTPS detection unsafe.
Check DNS and network exposure
Your domain’s DNS records must point to the server that runs Nginx. Permit inbound TCP ports 80 and 443 in the host firewall and cloud firewall. The Node port should not be opened publicly when Nginx is the sole entry point. Test from the server first, then from an external network after DNS has propagated.
Validate and reload safely
Always test syntax before applying a changed configuration:
sudo nginx -t
sudo nginx -s reload
Only reload after nginx -t reports valid syntax. If your distribution provides a service wrapper, sudo service nginx reload is an equivalent reload method. A failed syntax test leaves the running configuration in place, allowing you to correct the new file without interrupting existing traffic.
Rank #4
- Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
- Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
- All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
- Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
- Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
Enable HTTPS and redirect HTTP
Configure the TLS server block
You need a certificate and matching private key issued or managed by a certificate authority or certificate service of your choice. Store the private key with restrictive permissions and reference the actual paths in Nginx:
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/myapp/fullchain.pem;
ssl_certificate_key /etc/ssl/myapp/privkey.pem;
location / {
proxy_pass http://node_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
The certificate file normally contains the server certificate and its intermediate chain, while the key file contains the corresponding private key. Do not guess filenames: confirm that both paths exist, that Nginx can read them, and that the certificate covers every hostname listed in server_name. Renewals require replacing or renewing those files and then testing and reloading Nginx.
The HTTP block performs a permanent redirect, so clients use HTTPS for subsequent requests. Keep port 80 reachable when you need HTTP-to-HTTPS redirects or certificate-validation workflows.
Proxy WebSockets correctly
WebSocket handshakes begin as HTTP but then switch protocols. The Upgrade and Connection headers are hop-by-hop headers, so Nginx must forward them explicitly in the location that handles the WebSocket endpoint.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorslocation /socket.io/ {
proxy_pass http://node_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Change /socket.io/ to the path used by your application. Keep ordinary HTTP requests in their normal location block. If a WebSocket client connects but immediately falls back or disconnects, inspect the Nginx error log, confirm that the backend path matches exactly, and verify that the Node process is listening on the expected port.
Run, update, and stop the service operationally
Useful systemd commands
| Task | Command | Purpose |
|---|---|---|
| Start | sudo systemctl start myapp.service |
Start without changing boot enablement. |
| Stop | sudo systemctl stop myapp.service |
Stop the managed process. |
| Restart | sudo systemctl restart myapp.service |
Stop and start after a release or environment change. |
| Boot enablement | sudo systemctl is-enabled myapp.service |
Check whether it will start during boot. |
| Recent logs | sudo journalctl -u myapp.service -n 100 --no-pager |
Read the latest service messages. |
| Live logs | sudo journalctl -u myapp.service -f |
Follow startup and request-related output. |
Deploy a new release
- Copy the new release into a separate directory rather than overwriting the running files.
- Install production dependencies as the service account and verify ownership and permissions.
- Run a local smoke test against the release’s configured port, or temporarily point a staging service at it.
- Update the stable
currentlink or the service’sWorkingDirectory. - Run
sudo systemctl restart myapp.service, then inspectsystemctl statusand the journal. - Run
curl --fail http://127.0.0.1:3000/and an HTTPS request through Nginx. - If the release fails, point
currentback to the previous directory and restart the service.
Keep the previous release until the new process has passed health checks. This makes rollback a filesystem change plus a service restart instead of an emergency reconstruction.
Best Value
Make Node shut down gracefully
systemd can stop a process, but the application should handle POSIX signals such as SIGTERM and SIGINT. A shutdown handler should stop accepting new work, close the HTTP server, finish or cancel background tasks, close database connections, and exit with an appropriate status.
const http = require('node:http');
const app = require('./app');
const server = http.createServer(app);
const port = Number(process.env.PORT || 3000);
const host = process.env.HOST || '127.0.0.1';
server.listen(port, host, () => {
console.log(`Listening on ${host}:${port}`);
});
let shuttingDown = false;
async function shutdown(signal) {
if (shuttingDown) return;
shuttingDown = true;
console.log(`${signal} received; closing server`);
server.close(async () => {
// Close databases, queues, and other resources here.
process.exit(0);
});
setTimeout(() => process.exit(1), 30000).unref();
}
process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
Do not try to recover from an uncaught exception by continuing in the same process. An uncaught exception can leave application state undefined. Let the process exit and allow systemd’s external restart policy to start a clean instance; investigate the original stack trace in the journal.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Troubleshoot in the right order
| Symptom | Checks and corrective action |
|---|---|
| Service fails immediately | Run systemctl status myapp.service and journalctl -u myapp.service. Verify the absolute Node path, entry-point path, WorkingDirectory, file ownership, and required environment variables. |
| Service is active but no response locally | Use ss -ltnp to confirm the expected listener, then curl http://127.0.0.1:3000/. Check that the app did not bind a different port or only an inaccessible address. |
| Nginx returns 502 Bad Gateway | Test the backend directly with curl, confirm the upstream address and port, and read the Nginx error log. Restarting Nginx cannot fix a stopped or misbound Node process. |
| Domain does not reach Nginx | Check DNS records, the server’s public address, and firewall rules for ports 80 and 443. Confirm that the requested hostname matches the intended server_name. |
| HTTPS fails to load | Run nginx -t, verify certificate and key paths and permissions, confirm the certificate covers the hostname, and inspect Nginx’s TLS error output. |
| HTTP works but HTTPS redirects incorrectly | Check the port-80 redirect, the TLS server’s server_name, and X-Forwarded-Proto. Ensure the application understands that the original request was HTTPS. |
| WebSocket handshake fails | Use a dedicated WebSocket location with HTTP/1.1 and explicit Upgrade and Connection headers. Confirm the endpoint path and backend support. |
| Works in a shell but not after reboot | Check systemctl is-enabled myapp.service, use absolute executable paths, avoid shell-profile-only variables, and review the boot-time journal. |
When debugging a request, move from inside out: first the Node process and local curl, then Nginx configuration and logs, then DNS, firewall, and certificate state. This isolates application failures from proxy and network failures.
Scale beyond one Node.js instance
For one instance, proxy directly to its local port. For multiple instances, list each listener in an Nginx upstream group and keep the same proxy headers:
upstream node_backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/myapp/fullchain.pem;
ssl_certificate_key /etc/ssl/myapp/privkey.pem;
location / {
proxy_pass http://node_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Nginx Open Source uses round-robin distribution by default. Before adding instances, decide how the application handles shared state, uploads, background jobs, and sessions. In-memory sessions can send a user to a different process on the next request; use a shared session store or another deliberate persistence strategy. WebSocket clients also need a consistent connection strategy because an established socket remains attached to one backend.
NGINX Plus provides additional capabilities such as advanced health checks, monitoring, session persistence, and dynamic upstream reconfiguration. Choose it only when those operational features and commercial support justify the added complexity; a small deployment can remain with one systemd service and a direct upstream.
Quick Recap
Security and maintenance checklist
- Run Node under a dedicated non-root account.
- Keep the application listener on
127.0.0.1unless a documented private-network design requires another bind address. - Allow inbound ports 80 and 443 only as required; do not expose the Node port publicly.
- Restrict environment files and TLS private keys to the users and groups that need them.
- Use absolute executable and configuration paths in systemd.
- Use
Restart=on-failureand inspect the journal after repeated restarts instead of hiding a crash loop. - Run
nginx -tbefore every reload. - Renew certificates before expiration and reload Nginx only after validating the renewed files.
- Test local HTTP, public HTTPS, and any WebSocket endpoint after each deployment.
- Keep a known-good previous release for rollback.
Final deployment checklist
- The application starts manually with the intended production environment.
- The service unit has the correct user, group, working directory, absolute
ExecStart, environment, and restart policy. systemctl daemon-reloadhas been run after unit changes.systemctl enable --now myapp.servicesucceeds and the journal shows a healthy process.- Local curl reaches the loopback listener.
- Nginx’s upstream and
server_namematch the application and DNS name. nginx -tpasses before reload.- Port 80 redirects to HTTPS and the certificate and key paths are readable by Nginx.
- WebSocket locations include HTTP/1.1 and explicit upgrade headers when the app needs them.
- A reboot test confirms that systemd starts the app and Nginx can proxy it afterward.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




