Private Services
Run an internal service that is reachable by services in the same workspace network.
Private Services#
A Private Service is a persistent application that does not receive a public URL. Use it for internal APIs, internal webhooks, service-to-service RPC endpoints, and application components that should only be called by services in the same workspace network. It is the counterpart to a Web Service when the intended callers are inside the workspace rather than on the internet.
Choosing "private" is a network decision, not an authentication decision: an internal service protected only by a shared bearer token but still reachable from the public internet does not offer the same tenancy isolation as a service that has no public ingress at all.
When to use — and when not to#
Use Private Service when:
- The consumer is another NexHost service in the same workspace — for example an API called only by your Frontend App, a webhook processor other workers invoke, or a BFF (backend-for-frontend) that your worker pool internalizes.
- The API manages workspace-internal concerns (job orchestration, service-mesh control, internal event ingestion) that external users must not invoke directly.
- You want the workspace boundary to be the network boundary — code in a different workspace must not reach the internals.
Do not use Private Service when:
- The caller is a browser, mobile app, or third-party webhook on the public internet — ship a Web Service and enforce application-level authentication there.
- The work is a long-lived queue consumer (use Background Worker) or a scheduler-controlled on-demand run (use Cron Job / Workflow).
If the service serves both callers (an API that external apps call, plus one endpoint that only workspace services call), decompose: keep the external surface on a public service and the internal surface on a private one, each with the minimal needed environment variables.
Configure it like a runtime service#
From a configuration standpoint, a Private Service is a sibling of a Web Service: it needs a source, build and start commands when they apply, and any required environment variables. NexHost discovers a reachable TCP listener during startup even though the result is not a public hostname.
- Choose a source. Select a supported repository, archive, folder, or an existing image when the dashboard offers it. Confirm the branch and root directory for that source.
- Set build and start commands. The build produces the artifact the platform will attempt to start; the start command keeps the process alive. A continuous
npm start,gunicorn …, or binary invocation are common. - Configure environment variables. Wire database URLs, inter-service credentials, and queue endpoints as scoped secrets. Keep them out of source — the same scoping rules that apply to public runtimes apply here.
- Bind the process to `0.0.0.0`. NexHost discovers the private listener automatically; no health path or port setting is required.
Keep credentials and service connection details in the workspace configuration rather than committing them to source. A service definition committed to a repository that contains connection parameters is still history that must be rotated.
Validate readiness locally before you deploy. Run the same start command with the same environment values and confirm that it opens a TCP listener on 0.0.0.0.
Connect from other services#
The dashboard provides the private service’s connection details in its service configuration — the internal host, port, connection string, or workspace-scoped URL as appropriate for the runtime type. Use those displayed details from the other services in the same workspace.
Reading the correct value matters:
- A workspace-private address is not a hostname you memorize; it is the address the deployment currently advertises. A redeployment or infrastructure operation can change it, so prefer reading it at configuration time rather than caching it in application documentation.
- Cross-workspace access is not expected to succeed even when the workspace names feel similar. Treat the workspace as the addressing boundary.
Do not expect a private service to be reachable directly from the public internet. Probing it from an external browser, curl outside the workspace, or a third-party webhook will fail by design — use an external-service measurement (the calling workspace service’s logs, not a public-network curl from your laptop) to verify connectivity.
Troubleshooting#
| Symptom | Likely cause | Fix |
|---|---|---|
Calling service reports ECONNREFUSED to the private address | The private service never entered ready — check its deployment detail (build or startup/launch failure) before blaming the network | Open the private service’s last deployment; read the stage output from the first error upward |
401/403 on a private API call | The application route is protected; the caller did not send the application credential | Pass the application authentication header between services; this is separate from NexHost TCP readiness. |
| Intermittent failure only on first call after deploy | Transition/cold-start window on first readiness | Keep startup cheap; avoid synchronous external calls in the startup path |
Related documentation#
- Web Services — the public counterpart when external callers must reach the API.
- Background Workers — long-lived consumers with a similar "stay alive" contract but no HTTP ingress.
- Environment Variables — scope credentials so build and runtime see the right values.
- Domains and Networking — the public vs private split and how listener discovery fits.
- Deployments / Logs — diagnose why a private service never reported ready.