By NHI Mgmt Group Editorial TeamDomain: Cyber SecuritySource: ngrokPublished October 27, 2025

TL;DR: A simple self-hosted web app can be moved onto a VPS, secured with SSH, reverse proxying, systemd, and HTTPS, then extended with endpoint pooling and IP-based request filtering, according to ngrok. The practical lesson is that exposed services fail when identity, binding, and traffic controls are treated as setup details rather than governance decisions.


At a glance

What this is: This is a self-hosting guide that shows how to put a simple web API online with a VPS, SSH, Caddy, systemd, and ngrok traffic controls.

Why it matters: It matters because the same patterns shape how teams govern access, privilege, and runtime exposure for human-operated services, NHI-backed workloads, and AI-enabled applications.

👉 Read ngrok's guide to self-hosting a web app on a VPS with Caddy and ngrok


Context

A self-hosted application becomes a security problem the moment it leaves localhost, because access, transport security, and process lifetime all have to be governed deliberately. In this post, the primary issue is not whether the app works, but whether the surrounding controls prevent unnecessary exposure, over-privilege, and unauthorised reach into the host.

That is where IAM and NHI governance intersect with general hosting practice. SSH keys, privileged service accounts, reverse proxy permissions, and request filtering all become part of the control surface, especially when the same deployment patterns are reused for API services, automation jobs, or agentic workloads.


Key questions

Q: How should security teams reduce privilege when self-hosting web applications?

A: Separate the application, proxy, and administration layers so no single process needs broad authority. Run the app as a non-root user, let a proxy handle public ports and TLS, and use narrow capabilities rather than sudo for the few tasks that need elevation. That keeps compromise impact smaller and makes runtime trust easier to review.

Q: Why do non-root service accounts matter for web app hosting?

A: Non-root service accounts limit what an exploited service can do after compromise. If the process is attacked, the attacker inherits only the permissions attached to that account, not full host control. That is especially important for web apps that need network reachability but do not need file-system administration or user management rights.

Q: What do teams get wrong about SSH access to production servers?

A: They often treat SSH as a convenience channel instead of privileged administration. Provider-default passwords, unverified host trust, and shared credentials make remote access far more exposed than teams assume. SSH should be governed like any other high-value access path, with key management, host verification, and clear ownership.

Q: How can organisations decide whether a reverse proxy is enough for public exposure?

A: A reverse proxy is useful when it is doing more than forwarding traffic. It should terminate TLS, enforce edge policy, and isolate the app from direct public ports. If the proxy is only a pass-through, the organisation has not really changed the exposure model, only the routing path.


Technical breakdown

Why reverse proxies reduce direct application exposure

A reverse proxy sits in front of the application and receives inbound traffic on standard ports such as 80 and 443, then forwards selected requests to an internal service. That separation lets the app run on a non-privileged port while the proxy handles TLS termination, routing, and edge controls. The security value is not magical, but architectural: the application no longer needs direct public exposure. Caddy is used here as the proxy layer, with systemd managing the long-running process and Linux capabilities allowing limited privileged binding without full root access.

Practical implication: keep the app off public ports and place edge controls in a separately governed process with narrower privileges.

SSH access, host trust, and remote administration

SSH provides encrypted remote shell access and verifies the host through a fingerprint the first time a connection is made. That fingerprint check matters because it gives the operator a basic trust anchor for detecting host changes or interception attempts. The guide also highlights a second control point: the default password should be changed immediately, because shared or provider-known credentials create avoidable exposure. In operational terms, SSH is both a convenience layer and a governance boundary, especially when used to transfer binaries and administer production systems.

Practical implication: treat SSH as privileged access, rotate away from provider defaults, and pin host trust through fingerprint verification.

Systemd, Linux capabilities, and least privilege at runtime

Systemd is the service manager that keeps processes running, restarts them after failure, and can define the privileges they receive. The article’s Caddy example uses AmbientCapabilities to grant only the ability to bind low-numbered ports instead of granting full root access. That distinction matters because Linux capabilities split root into smaller permission units. The result is a more precise runtime model: the web server can listen on the required ports while still being unable to perform unrelated administrative actions if compromised.

Practical implication: assign only the capability needed for the service task and avoid using root as a shortcut for port binding.


NHI Mgmt Group analysis

Least privilege is the real security control behind simple hosting choices. This guide shows that the main risk in self-hosting is not the app code alone, but how much authority the surrounding processes inherit. SSH defaults, low-port binding, and long-lived service accounts can turn a small deployment into an overly trusted host. For identity teams, the same logic applies to non-human credentials and automation accounts: limit what the runtime can do, not just who can log in.

Runtime separation is a governance pattern, not just an implementation detail. The article separates application execution, proxying, and management functions across different components. That separation reduces blast radius when one layer fails. In identity terms, it mirrors the case for distinct service identities, scoped permissions, and explicit trust boundaries rather than collapsing everything into a single administrative context.

Traffic policy is becoming part of access governance for modern apps. The ngrok example moves beyond network reachability and into policy-based request decisions, including IP category filtering and endpoint pooling. That is relevant for identity-adjacent security because access is no longer only about authentication. It is also about context, routing, and which sources should be allowed to interact with a service at all.

Named concept: deployment privilege drift. When teams bootstrap a service, they often begin with broad permissions, direct shell access, and ad hoc port handling. Those choices harden into the production baseline unless someone deliberately reverses them. The practical lesson is to review hosting stacks as governance artefacts, because small convenience decisions become persistent privilege patterns.

For NHI governance, the same pattern appears in service accounts and automation workflows. Any non-human workload that keeps a shell, token, or binding privilege longer than necessary is carrying implicit trust. That trust should be time-bounded, narrowly scoped, and reviewed as part of the operational model, not just during initial deployment.

What this signals

A deployment that starts as a developer convenience can quickly become a privilege problem if host access, runtime binding, and edge policy are not separated early. That is the same governance failure pattern NHIs create in CI/CD and infrastructure automation, where service identities inherit permissions that outlive their original task.

Deployment privilege drift: the longer a service keeps temporary setup permissions, the more those permissions become part of its permanent security posture. Teams should review provisioning, daemon users, and runtime exceptions as one lifecycle, not three separate operational concerns.


For practitioners

  • Harden SSH as privileged access Require key-based login, change provider defaults immediately, and verify the host fingerprint on first connection to prevent silent host substitution.
  • Separate proxy and application privileges Run the application as a non-root process and place port binding, TLS termination, and routing in a distinct proxy process with narrower permissions.
  • Use Linux capabilities instead of full root Grant only CAP_NET_BIND_SERVICE or equivalent runtime capability when a service needs low ports, and avoid broad sudo-based startup patterns.
  • Treat request filtering as access policy Apply IP category and source-based policy at the edge so that unwanted automation, hosting ranges, or other disallowed sources are blocked before they reach the app.
  • Review non-human runtime trust periodically Inventory service accounts, daemon users, and automation credentials to confirm they still match the minimum permissions required for their active function.

Key takeaways

  • Self-hosting becomes a governance issue the moment application, proxy, and administrative privileges collapse into one runtime path.
  • SSH defaults, root binding, and unmanaged service accounts all expand blast radius even when the application itself is simple.
  • Least privilege, host trust verification, and edge policy are the controls that make small deployments safer as they scale.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

NIST CSF 2.0, NIST SP 800-53 Rev 5 and CIS Controls v8 set the technical controls, while ISO/IEC 27001:2022 define the regulatory obligations.

FrameworkControl / ReferenceRelevance
NIST CSF 2.0PR.AC-4The post centres on access scope and privilege separation for services and operators.
NIST SP 800-53 Rev 5AC-6Least privilege is explicit in the proxy and runtime separation described here.
CIS Controls v8CIS-5 , Account ManagementThe guide touches on host accounts, daemon users, and administrative access.
ISO/IEC 27001:2022A.8.2The article’s runtime separation and privilege model aligns with access control governance.

Document access boundaries for service processes under A.8.2 and review them whenever the deployment changes.


Key terms

  • Reverse Proxy: A reverse proxy is a server-side intermediary that receives inbound traffic on behalf of backend services. In identity-aware deployments, it also validates the caller and enforces authorization before the application handles the request, making it a control point for access and audit evidence.
  • Linux Capabilities: Linux capabilities split root privileges into smaller permissions, such as the ability to bind low-numbered ports without granting full administrative control. They are useful when a service needs one elevated function but should not inherit the broad authority associated with running as root.
  • Systemd Service: A systemd service is a managed background process on Linux that can be started, stopped, restarted, and configured with specific permissions. It is commonly used for long-running applications because it provides lifecycle control, automatic recovery, and a place to define operational constraints.
  • Deployment Privilege Drift: Deployment privilege drift is the tendency for temporary setup permissions to become permanent production permissions. It often happens when engineers keep broad access, shared credentials, or elevated runtime roles after the initial rollout, creating a larger attack surface than the application still requires.

What's in the full article

ngrok's full blog post covers the operational detail this post intentionally leaves for the source:

  • Step-by-step VPS setup, including provider selection, SSH login, and moving a compiled binary onto the host.
  • Detailed Caddy and systemd configuration, including the exact service layout and low-port binding approach.
  • ngrok endpoint pooling setup for multi-host load balancing and failover handling.
  • Traffic Policy examples for blocking unwanted requests based on IP intelligence and category data.

👉 The full ngrok post covers the VPS setup, reverse proxy configuration, and traffic policy examples in detail.

Deepen your knowledge

NHI Foundation Level course, the industry's only accredited NHI security programme, covers NHI governance, machine identity security, secrets management, and identity lifecycle. It helps practitioners build the governance skills needed to control service accounts and automation across modern environments.
NHIMG Editorial Note
Published by the NHIMG editorial team on August 19, 2026.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org