Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The dependable production pattern is to let systemd own the Node.js process and let Nginx be the public reverse proxy. Node runs as a non-root service on a private loopback port; Nginx accepts traffic on ports 80 and 443, terminates TLS, adds forwarding headers, and proxies requests to Node. This gives you boot-time startup, controlled restarts, centralized logs, HTTPS, and a clean path to multiple Node instances without exposing the application port directly.

The deployment architecture

A production deployment has three separate responsibilities:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Component Responsibility Publicly reachable?
Node.js application Executes your routes, API, server-rendered pages, or WebSocket logic. No. Bind it to 127.0.0.1 when Nginx is the only entry point.
systemd Starts the application at boot, supervises its process, restarts failures according to policy, and sends output to the journal. No.
Nginx Listens on HTTP/HTTPS, handles TLS and routing, and forwards requests to Node with proxy_pass. Yes, on ports 80 and 443.

Keeping these roles separate means a crashed Node process does not require Nginx to be restarted, and changing a proxy or certificate does not change how the application is supervised. It also prevents a local application port from becoming an unintended Internet-facing service.

Prepare the server and application

Use a supported Linux host

Use a Linux distribution that provides systemd and a supported Node.js release for your application. Package names, the default Nginx configuration directory, and the location of the Node executable vary by distribution. The commands below use the common Debian/Ubuntu layout; adapt package installation and paths to your operating system.

#1 Best Overall
Sale
Compressed Air Duster,130000RPM Super Power Cordless Air Duster,Rechargeable Brushless Blower,3 Gear Adjustable Blower with LED Light,Dust Remover for Computer/House/Outdoor/Car
  • Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
  • With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
  • Wide Application: attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
  • Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
  • Economical &Reusable: Built durable materials with a long-lasting battery,our CAGIWIRU air duster it's a sustainable alternative to disposable air cans.

Create a dedicated service account

Do not run the application as root. Create a user and group used only by this service, then make the deployed application readable by that account and writable only where the application genuinely needs to write.

sudo useradd --system --home /srv/my-node-app --shell /usr/sbin/nologin mynode
sudo install -d -o mynode -g mynode /srv/my-node-app

If your distribution already has a suitable application account, use it instead of creating a second one. Keep deployment files, runtime files, and secrets separate where practical.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Deploy production files

Place the application in a stable directory such as /srv/my-node-app. Install only production dependencies on the server and ensure the project has a production start command. For a project whose entry point is server.js, a typical deployment command is:

cd /srv/my-node-app
sudo -u mynode npm ci --omit=dev

The exact command depends on your lockfile and package manager. The important property is that the files and dependencies used by the service are present before systemd starts it.

Choose a private listening address and port

Have the application listen on a local port, for example 127.0.0.1:3000. Express-style applications commonly use an environment variable:

app.listen(process.env.PORT || 3000, '127.0.0.1');

Do not assume that binding to localhost is equivalent on every stack; explicitly selecting 127.0.0.1 makes the intended IPv4 loopback behavior clear. If your application needs IPv6 loopback, configure both the application and proxy deliberately.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
EVEO® Screen Cleaner Spray Kit (Streak-Free) TV Screen Cleaner for Smart TV, Lcd, LEd, Oled | Computer Screen Cleaner Spray and Wipe Microfiber Cloth - TV, Monitor, Laptop, iPad, Car - 6.7oz 1 Pack
  • Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
  • Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
  • Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
  • Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
  • Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth

Create the systemd service

Find the absolute Node executable

systemd does not load your interactive shell profile. If Node was installed with a version manager, the path available in your shell may not exist when systemd starts the service. Determine the path as the service account or deployment user and use that absolute path in ExecStart:

command -v node

Common system-wide installations return a path such as /usr/bin/node; a version-manager installation may return a path under the user’s home directory. The service account must be able to traverse every parent directory and execute the binary.

Write the unit file

Create /etc/systemd/system/my-node-app.service:

[Unit]
Description=My Node.js application
After=network.target

[Service]
Type=simple
User=mynode
Group=mynode
WorkingDirectory=/srv/my-node-app
Environment=NODE_ENV=production
Environment=PORT=3000
# Alternatively, use: EnvironmentFile=/etc/my-node-app/my-node-app.env
ExecStart=/usr/bin/node /srv/my-node-app/server.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Replace the description, account, working directory, Node path, and entry point with your project’s values. After=network.target orders startup after the basic network target; it does not prove that DNS or a remote database is ready. If the application depends on another service, model that dependency explicitly rather than assuming network startup means every dependency is available.

Restart=on-failure asks systemd to restart an abnormal exit while leaving an intentional clean stop alone. The five-second delay prevents an immediate crash loop from consuming the machine. This is an operational policy, not a guarantee that the application is healthy: systemd can restart a process that starts successfully and then serves bad responses.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Supply configuration and secrets safely

Small, non-sensitive values can be declared with Environment=. For a larger set of variables, use an environment file:

sudo install -d -m 0750 -o root -g mynode /etc/my-node-app
sudoedit /etc/my-node-app/my-node-app.env
sudo chmod 0640 /etc/my-node-app/my-node-app.env

Use one KEY=value assignment per line and avoid putting secrets in the unit file if you need to grant broader read access to service definitions. Ensure the service account can read the file, but do not make it world-readable. Never print credentials in startup logs.

Rank #3
Sale
BladeHawks RGB Gaming Mouse Pad Extra Large Extended 31.5x12 Inch-Black | LED mouse pad with 14 lighting modes, covers keyboard & mouse, anti-slip rubber base, waterproof surface, USB powered
  • 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
  • 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
  • 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
  • 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
  • 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.

Load, start, and inspect the service

  1. Ask systemd to reread unit files after creating or changing the service:
    sudo systemctl daemon-reload
  2. Enable the service for boot and start it immediately:
    sudo systemctl enable --now my-node-app.service
  3. Inspect its current state and the most recent messages:
    sudo systemctl status my-node-app.service
    sudo journalctl -u my-node-app.service
  4. Follow new log entries while testing:
    sudo journalctl -u my-node-app.service -f

A successful active (running) status confirms that the process is running, not that the application is responding correctly. Test the listener directly before adding Nginx:

curl -i http://127.0.0.1:3000/

If this request fails, fix the Node service first. Nginx cannot repair an application that is not listening, is listening on another port, or is returning an application error.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure Nginx as the reverse proxy

Define the upstream and server block

Create a site configuration in the location used by your distribution, commonly /etc/nginx/sites-available/my-node-app:

upstream node_backend {
    server 127.0.0.1:3000;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://node_backend;
        proxy_http_version 1.1;
        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 names in server_name with domains whose DNS records point to this server. The upstream name is an internal Nginx label; the application still listens on the local port. Host preserves the requested host, while the X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto headers tell the application how the original request arrived. Configure your framework to trust proxy headers only when requests can reach it through the proxy you control; otherwise a client could forge those values.

Enable the site and test syntax

On systems using the sites-enabled convention:

sudo ln -s /etc/nginx/sites-available/my-node-app /etc/nginx/sites-enabled/my-node-app
sudo nginx -t

Only reload after nginx -t reports valid syntax:

sudo nginx -s reload

service nginx reload is an equivalent service-management form on many distributions. A failed syntax test leaves the current configuration running; correct the reported file and line before trying again.

Add HTTPS and redirect HTTP

Provide a certificate and private key

HTTPS requires a certificate chain and private key issued or managed by the certificate authority or certificate service you choose. Put the paths for those files in an Nginx TLS server block and ensure the Nginx master process can read them. A common layout is:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Vaydeer Wrist Rest for Keyboard and Mouse, Computer Ergonomic Wrist Support Pad, Soft Memory Foam Arm Cushion for Desk, Palm Hand Office Laptop Typing
  • 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
  • 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
  • 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
  • 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
  • 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://node_backend;
        proxy_http_version 1.1;
        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;
    }
}

The example paths are illustrative; use the paths produced by your certificate deployment. Protect the private key from ordinary users and arrange renewal according to the certificate service’s process.

Redirect port 80 to HTTPS

After the TLS block works, make the port-80 block redirect permanently:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Keep port 80 reachable for the redirect and for any certificate-validation method that requires it. Test both the certificate hostname and the redirect after reloading Nginx.

Proxy WebSockets correctly

WebSocket upgrade headers are hop-by-hop headers. Nginx does not forward them automatically, so a WebSocket route needs explicit settings:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location /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;
}

Use the actual path handled by your WebSocket library. Keep the ordinary HTTP location separate if only one route upgrades connections. If the handshake returns a normal HTTP response instead of a successful upgrade, inspect the browser or client request path, the two upgrade headers, and the Node application logs before changing timeouts or application code.

Verify the complete request path

  1. Check that DNS resolves the domain to the server’s address.
  2. Confirm the host firewall and any cloud firewall allow inbound TCP 80 and 443. The Node port normally does not need to be opened publicly because Nginx connects over loopback.
  3. Check the service: systemctl is-active my-node-app.service.
  4. Check the backend directly: curl -i http://127.0.0.1:3000/.
  5. Check Nginx syntax: sudo nginx -t.
  6. Reload Nginx and request the public URL over HTTPS.
  7. Review Nginx access and error logs together with journalctl -u my-node-app.service.

This order isolates the layers. A failed loopback request is an application or systemd problem; a successful loopback request with a failed public request points toward Nginx, DNS, firewall, TLS, or the request headers.

Best Value
Sale
Under Desk Cable Management Tray No Drill, Metal Mesh Cable Management Under Desk with Clamp Mount, 2 Hole Cable Tray with Wire Management and Cord Organizer for Home Office Standing Desk
  • 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
  • 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
  • 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
  • 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
  • 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Graceful shutdown and crash recovery

When systemd stops or restarts a service, Node.js receives a POSIX signal such as SIGTERM. Register a handler that stops accepting new work, closes the HTTP server, finishes or cancels outstanding resources, and exits within a bounded time:

const server = app.listen(process.env.PORT || 3000, '127.0.0.1');

process.on('SIGTERM', () => {
  server.close(() => process.exit(0));
});

process.on('SIGINT', () => {
  server.close(() => process.exit(0));
});

Adapt the handler for database pools, queues, and WebSocket connections used by your application. A graceful handler prevents a deployment or reboot from abruptly cutting active work, but it must not wait forever; set an operational timeout appropriate to your workload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

An uncaught exception leaves a Node process in an undefined state. Do not try to continue serving from the same process after such a failure. Let the process exit and allow systemd, as the external monitor, to restart it according to the unit policy. Inspect the journal to find the underlying exception rather than treating repeated restarts as a fix.

Troubleshoot by symptom

systemd reports “failed”

  • Read the complete unit log with journalctl -u my-node-app.service -b.
  • Run the same entry command manually as the service account, from the configured working directory.
  • Verify the absolute Node path, entry-point path, file permissions, and environment-file permissions.
  • Check that the configured port is not already occupied.
  • If Node came from a version manager, replace the shell-dependent path with the executable’s absolute path.

The service is running but Nginx returns 502 Bad Gateway

  • Run curl -i http://127.0.0.1:3000/ on the server.
  • Compare the application’s actual bind address and port with the Nginx upstream.
  • Read the Nginx error log for connection-refused, timeout, or permission messages.
  • Confirm a local security policy is not blocking Nginx from connecting to the loopback listener.

The site shows the wrong Nginx server block

  • Verify the requested hostname exactly matches server_name.
  • Confirm the intended file is enabled and that an older default site is not taking precedence.
  • Run nginx -T to inspect the loaded configuration, then run nginx -t before reloading any correction.

HTTPS fails while HTTP works

  • Check that the certificate includes the hostname being requested.
  • Verify the certificate and key paths and their permissions.
  • Check that port 443 is allowed through every firewall layer.
  • Review Nginx’s error log for certificate parsing or key-mismatch errors.

WebSockets do not connect

  • Confirm the client is using the proxied WebSocket path.
  • Ensure the location contains proxy_http_version 1.1, Upgrade, and Connection headers.
  • Check that the Node application is actually accepting upgrades and that its logs show the handshake attempt.

Run more than one Node instance

One instance can be proxied directly to its local port. For multiple instances, define an Nginx upstream group:

upstream node_backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
}

Keep the same proxy_pass http://node_backend; directive in the server locations. Nginx Open Source uses round-robin distribution by default. This is a distribution policy, not application-level session management: if users must return to the same instance, design session storage and persistence deliberately. WebSocket connections remain attached to the selected backend for their lifetime.

Need Single local instance Upstream group
Configuration effort One service and one backend address. Multiple processes, ports, and upstream entries.
Failure isolation A process failure makes the application unavailable until systemd restarts it. Other instances can continue receiving traffic while one fails, subject to how failure is detected and removed.
Sessions No cross-instance consistency issue. Use shared session state or an intentional persistence strategy when required.
WebSockets Simple routing to one listener. Each connection stays with its selected instance; coordinate shared state if clients interact across instances.
Advanced operations Usually unnecessary. NGINX Plus adds enterprise features such as advanced health checks, monitoring, session persistence, and dynamic upstream reconfiguration.

Scaling the proxy does not replace process supervision. Each Node instance still needs a reliable lifecycle owner, separate port, configuration, and log strategy. Decide how deployments start, stop, and roll back every instance before adding capacity.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Operational checklist

  • Application files are in a stable directory and production dependencies are installed.
  • A dedicated non-root account owns or can read the required files.
  • The systemd unit has an absolute Node executable, correct working directory, entry point, environment, restart policy, and WantedBy=multi-user.target.
  • The service starts with systemctl enable --now and its journal is readable.
  • Node listens on a private local address and the expected port.
  • Nginx has the correct server_name, upstream, forwarding headers, and enabled configuration.
  • nginx -t succeeds before every reload.
  • The TLS certificate and private key paths are valid and protected.
  • Port 80 redirects to HTTPS, while ports 80 and 443 are allowed through the firewall.
  • WebSocket locations explicitly forward upgrade headers when the application needs them.
  • Shutdown handlers close servers and dependent resources on SIGTERM and SIGINT.
  • Monitoring starts with the systemd journal, Nginx logs, and direct loopback tests.

What this setup gives you

With systemd supervising a non-root Node process and Nginx serving as the TLS-enabled edge, reboot startup, crash recovery, private application binding, certificate termination, HTTP routing, and WebSocket proxying each have a defined place. The same arrangement works for a single application and can be extended with an Nginx upstream group when you operate multiple instances. Keep the configuration explicit, test syntax before reloads, and troubleshoot from the Node listener outward to the public endpoint.

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.