Skip to content
← All projects

Systems & security

Linux in Production

How I deploy, supervise and diagnose MartialXPro on its Ubuntu host using Nginx, PM2, system services, permissions and logs.

Host
Ubuntu Server
Serving
Node.js API behind Nginx
Focus
Administration & hardening
Status
Ongoing

Why this is its own project

An API can work locally and still fail on its host because of process state, permissions, proxy routing or service startup. This case study isolates that operational layer from the application itself.

The examples come from the Ubuntu host serving MartialXPro.

The host

Web layer
Nginx: reverse proxy, TLS termination, static content
Process layer
PM2: supervision, restart on failure and on boot
Runtime
Node.js, configured entirely through environment variables
Access
SSH with key-based authentication
Diagnostics
PM2 process logs and Nginx access/error logs
Linux request and operations pathsA client request reaches Nginx and is proxied to the Node.js API supervised by PM2. Nginx access and error logs, PM2 process state and application logs feed operational diagnosis on the Ubuntu host.UBUNTU HOSTREQUEST PATHClientHTTPSNginxreverse proxyproxy_passNode.js APIsupervised by PM2PM2restart + stateDIAGNOSTIC EVIDENCENginx logsaccess · errorPM2 + app evidencestate · process logsDiagnosison the hostService status · file ownership · environment configuration · startup order
Request and diagnostic paths on the Ubuntu host serving MartialXPro.

Nginx as the front door

Nginx sits in front of the Node process rather than exposing the application port directly. That gives one place to terminate TLS, one place to decide what is proxied and what is served as a static file, and one place to control the headers the application sees.

Most of the configuration work was in the details: correct proxy_pass upstreams, forwarding the headers the application depends on, and keeping the split between API traffic and static content unambiguous. A reverse proxy that quietly rewrites part of a request produces bugs that look like application bugs.

Keeping the process alive

PM2 supervises the Node.js application. It restarts the process if it exits, brings it back after a reboot and gives a consistent place to read runtime logs from. Combined with environment-variable configuration, that means a server restart requires no manual steps to get back to a serving state.

Hardening the box

The security work is not a separate phase bolted on at the end. It is part of the host's default configuration. Coming from CEHP and WAPT coursework, the baseline I apply is the one I would otherwise be probing for gaps in:

  • Key-based SSH only
    Administrative SSH access uses key-based authentication; password authentication is disabled.
  • Least-privilege file permissions
    Application files, log directories and environment files are owned and readable only by the accounts that genuinely need them, rather than using blanket 777 permissions to make an error go away.
  • Minimal exposed surface
    Only the ports that need to be reachable are reachable. Everything else stays closed at the firewall and security-group level.
  • No secrets in the repository
    Credentials and environment-specific configuration live in environment variables on the host, never in version control.
  • Separation of deploy and runtime accounts
    The account that ships code and the account that runs it are distinct, so a compromise of one is not automatically a compromise of the other.

Operating it

Operational diagnosis starts with PM2 process state and application logs, then Nginx access and error logs, service status, file ownership and environment configuration. Recurring issues have included deploy and runtime ownership mismatches, proxy assumptions and startup ordering after reboots.

Current learning priorities are Docker for repeatable runtime packaging and Terraform for describing infrastructure. Orchestration is a later decision, contingent on the platform needing multiple services or hosts.

Use the up and down arrow keys to choose a result, Enter to open it, and Escape to close search.