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 errorsiTechGuides 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
Deploy the application as two processes: Nginx listens on the public HTTP and HTTPS ports, serves files that never need application logic, and forwards dynamic requests to a private application server. This guide uses Ubuntu 24.04, Nginx installed on the host, and an example Node.js 20 LTS application listening on 127.0.0.1:3000. The same boundary works with another runtime as long as it exposes an HTTP listener.
What the deployment looks like
Nginx is the public web-server and reverse-proxy layer, not the job-application runtime. A browser connects to Nginx; Nginx decides whether it can return a file directly or must pass the request to the application process. The application validates submissions, runs business rules, and talks to whatever data services your project requires.
Browser
|
| HTTPS :443 (HTTP :80 redirects)
v
Nginx on the server
|-- /assets/*, existing public files -> filesystem
|-- /api/*, /apply, /dashboard -> 127.0.0.1:3000
v
Node.js application server
NGINX documents this split and the use of an upstream referenced by proxy_pass in its Node.js deployment guide; Node.js is an example here, not a requirement for a job-application product. See NGINX’s web-server administration guide and its Node.js deployment guide.
| Request | Handler in this example | Reason |
|---|---|---|
/assets/app.css, images, browser bundles |
Nginx filesystem | Lower overhead and no application worker is needed. |
/apply and /api/applications |
Node.js on 127.0.0.1:3000 |
These routes need validation, sessions, persistence, or other application logic. |
/healthz |
Application (or a deliberately static Nginx check) | Provides a useful release and monitoring signal. |
Choose the operating model before installing anything
The commands below assume a single Linux server, host-managed Nginx, and a host-managed Node.js service. That is the clearest starting point when the title does not specify a platform. Docker Compose is covered later as an optional route; do not combine both process managers accidentally.
#1 Best Overall
- A DNS record such as
jobs.example.compoints to the server’s public address. - Ports 80 and 443 are allowed through the server firewall and any cloud firewall.
- The application has a production start command and listens on the address and port supplied by environment variables.
- The deploy user can place releases under
/var/www/job-app; Nginx can read the published files. - Application secrets are supplied through a protected environment file or service manager, not committed to the repository.
Do not assume that this web-server setup answers the domain-specific questions of candidate-data retention, upload storage and limits, email delivery, database backups, migrations, or jurisdiction-specific privacy obligations. Design and document those separately for the application you are deploying.
Make the application reachable only from the server
Use a production build and a private listener
Build the frontend and backend using the versions your project supports. Configure the process to bind to 127.0.0.1 (or a private container network address) rather than a public interface. A typical environment file might contain:
NODE_ENV=production
HOST=127.0.0.1
PORT=3000
Your framework may use different variable names; the important result is an HTTP listener on the address Nginx will proxy to. Verify locally before adding Nginx:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallcurl -i http://127.0.0.1:3000/healthz
Expect an HTTP response from the application. If this fails, fix the application process first; a reverse proxy cannot repair a process that is stopped, listening on another port, or crashing during startup.
Run the process under a service manager
For a host-managed deployment, create a dedicated unprivileged account and a systemd unit. Adjust ExecStart to your framework’s real production command:
Rank #2
sudo useradd --system --home /var/www/job-app --shell /usr/sbin/nologin jobapp
sudo mkdir -p /var/www/job-app/current
sudo chown -R jobapp:jobapp /var/www/job-app
sudo nano /etc/systemd/system/jobapp.service
[Unit]
Description=Job application web service
After=network.target
[Service]
Type=simple
User=jobapp
Group=jobapp
WorkingDirectory=/var/www/job-app/current
EnvironmentFile=/etc/jobapp/jobapp.env
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo mkdir -p /etc/jobapp
sudo chmod 750 /etc/jobapp
sudo chmod 640 /etc/jobapp/jobapp.env
sudo systemctl daemon-reload
sudo systemctl enable --now jobapp
sudo systemctl status jobapp
Check service output with sudo journalctl -u jobapp -n 100 --no-pager. Keep the application port private; Nginx is the component that should be exposed publicly.
Install Nginx and define the routing boundary
Install and test the package
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
nginx -v
On many distributions the main configuration is /etc/nginx/nginx.conf, with virtual hosts in /etc/nginx/sites-available and enabled links in /etc/nginx/sites-enabled. Distribution layouts vary, so inspect the active file with sudo nginx -T before editing.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Create a server block
Place this example in /etc/nginx/sites-available/jobs.example.com. It serves existing files below /var/www/job-app/current/public and sends everything else to the application:
upstream job_app {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name jobs.example.com;
root /var/www/job-app/current/public;
index index.html;
location /assets/ {
try_files $uri =404;
access_log off;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
try_files $uri $uri/ @job_app;
}
location @job_app {
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;
proxy_set_header Connection "";
proxy_pass http://job_app;
}
}
The try_files directive lets Nginx return a real asset or page. A missing path falls through to the named location, where proxy_pass forwards the original URI to the Node.js service. If your frontend is a single-page application, replace the fallback behavior with the framework’s documented production entry file, while keeping API paths explicitly proxied when necessary.
sudo ln -s /etc/nginx/sites-available/jobs.example.com /etc/nginx/sites-enabled/jobs.example.com
sudo nginx -t
sudo systemctl reload nginx
Never skip nginx -t. NGINX’s Beginner’s Guide explains that a reload makes the master process check the new configuration and attempt to apply it; if applying the new configuration fails, Nginx keeps serving with the old configuration. This makes validation and reload a safe deployment operation when used deliberately: NGINX Beginner’s Guide.
Add HTTPS without exposing the private key
Use a certificate and key readable by the Nginx master
Obtain a certificate for the exact hostname and install the public certificate and private key in protected locations. A common arrangement is:
Free tools Windows power users keep installed
One-click scans. No signup required.
sudo install -d -m 750 /etc/nginx/tls
sudo install -m 644 fullchain.pem /etc/nginx/tls/jobs.example.com.crt
sudo install -m 600 privkey.pem /etc/nginx/tls/jobs.example.com.key
The certificate is public; the private key is not. Restrict key-file access and confirm that the Nginx master process can read it. Do not make the key world-readable merely to resolve a permission error. The official NGINX HTTPS configuration guide documents this distinction and shows the ssl_certificate and ssl_certificate_key directives.
Redirect HTTP and listen on 443
Replace the HTTP server block with a redirect and add a TLS server block (retain your existing locations):
server {
listen 80;
listen [::]:80;
server_name jobs.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name jobs.example.com;
ssl_certificate /etc/nginx/tls/jobs.example.com.crt;
ssl_certificate_key /etc/nginx/tls/jobs.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/job-app/current/public;
index index.html;
location /assets/ {
try_files $uri =404;
access_log off;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
try_files $uri $uri/ @job_app;
}
location @job_app {
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;
proxy_set_header Connection "";
proxy_pass http://job_app;
}
}
The guide lists TLSv1.2 TLSv1.3 and a high-strength cipher policy among its defaults, while noting that defaults have changed over time. Treat the installed Nginx version as authoritative, review its effective configuration, and do not describe those defaults as permanent.
sudo nginx -t
sudo systemctl reload nginx
curl -I https://jobs.example.com/
Release code with a rollback-friendly sequence
Use a versioned release directory and switch current only after the new code has been installed. A practical sequence is:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
- Copy the new application build to a new directory such as
/var/www/job-app/releases/2026-10-18-01and set ownership tojobapp:jobapp. - Install production dependencies and build assets in that release, without placing secrets in the release directory.
- Run the new process or restart the service, then verify
curl http://127.0.0.1:3000/healthz. - Update the
currentsymlink to the tested release and restart or reload the application service as required by the runtime. - If Nginx configuration changed, run
sudo nginx -t; only then runsudo systemctl reload nginx. - Check the public HTTPS endpoint, application logs, and Nginx logs before declaring the release complete.
To roll back application code, point current to the previous known-good release and restart the service. To roll back a bad Nginx edit, restore the previous configuration and reload after another syntax test; a failed reload leaves the old configuration active.
Optional route: Docker Compose
Compose is convenient when you want the application, Nginx, and supporting services described as reproducible containers on one server. Docker calls single-server Compose deployment the easiest application deployment path and describes production overrides for settings such as code mounts, host ports, environment variables, restart policies, and logging. See Docker’s Compose production guide.
Keep the app port private
If Nginx runs on the host and the app runs in a container, bind the published port to loopback:
services:
web:
build: .
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3000
ports:
- "127.0.0.1:3000:3000"
restart: unless-stopped
If Nginx is another Compose service, put both services on a private Compose network and proxy to the service name instead of publishing the application port at all. Docker’s documentation states, “Publishing container ports is insecure by default.” A published port is available outside the host unless you bind it to a specific interface; binding to 127.0.0.1 or ::1 restricts access to the Docker host. Docker also notes a localhost-publishing caveat for releases older than 28.0.0, where same-layer-2 hosts may reach such ports, so account for the engine version and network controls: Docker port publishing and mapping.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Redeploy only the changed service
docker compose -f compose.yml -f compose.production.yml up -d --build web
docker compose ps
docker compose logs --tail=100 web
The production file can remove development bind mounts, set production environment variables, and add restart behavior. Rebuild and recreate the service when releasing code; do not assume that changing a source file on the host changes an already-built image. Keep database persistence, secret injection, migrations, backups, and health checks explicit rather than copying development defaults.
Best Value
Host Nginx or containerized Nginx?
| Choice | Operational advantages | Trade-offs |
|---|---|---|
| Host Nginx + host-managed app | Simple systemd logs, direct certificate files, fewer moving parts. | Package, runtime, and release updates are managed separately. |
| Host Nginx + Compose app | Application dependencies are packaged; Nginx remains easy to inspect from the host. | Port binding and container/host permissions must be designed correctly. |
| Compose Nginx + Compose app | One deployment definition and private service-to-service networking. | Certificate volumes, proxy logs, upgrades, and container health need a deliberate production design. |
Neither arrangement is universally best. Choose the one your team can patch, observe, back up, and roll back reliably.
One application instance or several?
The configuration above has one upstream server. When the application is stateless and the server has capacity, you can list several private instances:
upstream job_app {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
Nginx will distribute requests among the upstream members. Before doing this, ensure sessions, uploaded files, caches, and other state are available consistently to every instance; otherwise users can see different behavior between requests. Multiple workers also require a release strategy that avoids taking every instance offline at once.
Verify the finished deployment
- Configuration:
sudo nginx -texits successfully before every reload. - Process:
systemctl is-active jobapp(ordocker compose ps) reports the expected service as running. - Private path: the application answers on
127.0.0.1:3000, while an unintended public connection to port 3000 is blocked. - Static path: an asset returns from Nginx without an application error in the app log.
- Dynamic path: the application form and API return the expected status through HTTPS.
- Forwarded context: generated links and secure-cookie logic see the original host and HTTPS scheme through the forwarded headers.
- Logs: inspect both Nginx error/access logs and the application journal or container logs for the same request.
- Certificate: the hostname, chain, expiry, and private-key permissions are correct.
Common failures and their fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| 502 Bad Gateway | The app is stopped, listening on another address/port, or refusing connections. | Check the service status and local curl; make the upstream match the actual listener. |
| 404 for CSS or JavaScript | Nginx root does not contain the production build, or the asset URL is wrong. |
Inspect the resolved current/public path and test the exact asset URL. |
| 502 after a release | The new process failed to start because of a missing environment variable or dependency. | Read the service journal, restore the previous release, and fix startup before retrying. |
| Nginx will not reload | A syntax, include, certificate-path, or permission error exists. | Run sudo nginx -t; the old configuration remains active until a valid reload succeeds. |
| HTTPS redirects in a loop | The app does not trust the proxy’s HTTPS indication and redirects an already secure request. | Configure the framework’s trusted-proxy setting according to its documentation and retain X-Forwarded-Proto. |
| Application port is reachable from the internet | A container port was published on all host interfaces or a firewall rule allows it. | Bind it to loopback or a private network, remove unnecessary publishing, and audit firewall rules. |
What this architecture does not decide
Nginx can terminate TLS, serve static content, and route requests, but it does not define how a job application stores candidate records, accepts and scans resumes, sends confirmation mail, performs database migrations, retains backups, or meets privacy law. Set those policies and controls at the application and data-service layers. Keep upload limits, timeout choices, authentication, rate limiting, and audit logging explicit; add them only after the application’s requirements and threat model are known.
Quick Recap
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.

