Deploy NemoClaw to a Headless Server

View as Markdown

Run NemoClaw on a remote Linux server through SSH without exposing the OpenShell gateway or dashboard to the network. This guide covers unattended onboarding, verified readiness, routine updates, and manual recovery after a host reboot.

Headless Describes Operation, Not a Provider

A Linux VM that you provision through Brev is one example of a headless server. These instructions also apply to Linux hosts on other clouds, VPS services, or on-premises infrastructure. NemoClaw setup starts after server provisioning and does not depend on Brev or its web UI.

Host Reboot Recovery Is Manual

NemoClaw does not guarantee that Docker, the OpenShell gateway, sandboxes, tunnels, or host forwards start automatically after a host reboot. Use the manual recovery sequence after each reboot. Do not install an unofficial service unit as a substitute for this sequence.

Check the Server

Use a Linux host that meets the supported NemoClaw prerequisites. The primary tested server path is Linux with Docker.

ResourceMinimumRecommended
CPU4 vCPU4 or more vCPU
RAM8 GB16 GB
Free disk20 GB40 GB

The image build, Docker daemon, and OpenShell gateway can exhaust a smaller host during onboarding. If the host has less than 8 GB of RAM, configure at least 8 GB of swap before onboarding.

Run these checks from the remote host:

$uname -m
$. /etc/os-release
$printf '%s %s\n' "$ID" "$VERSION_ID"
$docker info
$docker_root=$(docker info --format '{{.DockerRootDir}}')
$df -h "$HOME" "$docker_root"
$free -h
$swapon --show

docker info must succeed for the same account that runs NemoClaw. Membership in the docker group grants root-level control of the Docker daemon, so grant it only to trusted accounts.

The host firewall must allow the outbound DNS, HTTPS, image-registry, package-registry, and inference-provider traffic selected during onboarding. The OpenShell policy controls traffic from the sandbox and does not replace the host firewall. Keep inbound dashboard and OpenShell gateway ports closed when you use SSH forwarding.

Keep Remote Access on Loopback

The OpenShell gateway binds to 127.0.0.1 by default. Dashboard and API forwards also stay on loopback outside WSL unless you explicitly change the bind setting.

Connect to the server from your workstation:

$ssh <user>@<server>

Deep Agents Code is a terminal runtime and has no dashboard port. Run nemo-deepagents launch headless-agent through the SSH session to start dcode in that session. Use nemo-deepagents headless-agent connect instead when you want a sandbox shell.

Do not open port 8080 for remote access. Do not bind the dashboard to every interface when an SSH tunnel meets the access requirement.

Protect a Long Onboarding Run

Run onboarding inside a tmux or screen session so an SSH disconnect does not terminate the host process. To start a tmux session, run:

$tmux new-session -s nemoclaw-onboard

Detach with Ctrl-b, then d while onboarding continues. After you reconnect through SSH, reattach to the session:

$tmux attach-session -t nemoclaw-onboard

To use screen instead, start a session:

$screen -S nemoclaw-onboard

Detach with Ctrl-a, then d while onboarding continues. After you reconnect through SSH, reattach to the session:

$screen -r nemoclaw-onboard

Do not enable shell tracing with set -x in a session that contains credentials. Do not save the session transcript when it can contain a dashboard URL or token.

If the onboarding process exited after it saved a resumable session, export the same required credential variables and resume it:

$NEMOCLAW_NON_INTERACTIVE=1 \
>NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \
>nemo-deepagents onboard --resume --yes-i-accept-third-party-software --yes

--resume uses the provider, model, sandbox name, agent, and completed non-secret choices from the saved session. Raw credentials are not stored in the onboarding session. If resume reports a missing credential variable, inject that variable again and repeat the command. Use --fresh only when you intend to discard the saved onboarding session and start again.

Run Unattended Onboarding

Select a reviewed NemoClaw commit and set its full 40-character SHA before unattended installation. The example uses that SHA in both the immutable bootstrap URL and NEMOCLAW_INSTALL_REF, so the bootstrap and cloned installer payload come from the same repository state. Do not use the mutable lkg or latest references as the primary install source for a persistent server. Inject provider credentials from your secret manager into the host environment before you run this example. The example fails before the network install if the commit SHA or NVIDIA_INFERENCE_API_KEY is missing or invalid.

$export NEMOCLAW_AGENT=langchain-deepagents-code
$export NEMOCLAW_INSTALL_REF="<reviewed-40-character-commit-sha>"
$: "${NVIDIA_INFERENCE_API_KEY:?Inject NVIDIA_INFERENCE_API_KEY from a secret store}"
$[[ "$NEMOCLAW_INSTALL_REF" =~ ^[0-9a-f]{40}$ ]] || {
> echo "NEMOCLAW_INSTALL_REF must be a reviewed full commit SHA" >&2
> exit 1
>}
$export NEMOCLAW_PROVIDER=build
$export NEMOCLAW_SANDBOX_NAME=headless-agent
$export NEMOCLAW_POLICY_TIER=balanced
$
$curl -fsSL "https://raw.githubusercontent.com/NVIDIA/NemoClaw/${NEMOCLAW_INSTALL_REF}/install.sh" | \
> NEMOCLAW_INSTALL_REF="$NEMOCLAW_INSTALL_REF" \
> NEMOCLAW_NON_INTERACTIVE=1 \
> NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 \
> NEMOCLAW_AGENT="$NEMOCLAW_AGENT" \
> NEMOCLAW_PROVIDER="$NEMOCLAW_PROVIDER" \
> NVIDIA_INFERENCE_API_KEY="$NVIDIA_INFERENCE_API_KEY" \
> NEMOCLAW_SANDBOX_NAME="$NEMOCLAW_SANDBOX_NAME" \
> NEMOCLAW_POLICY_TIER="$NEMOCLAW_POLICY_TIER" \
> NEMOCLAW_WEB_SEARCH_PROVIDER=none \
> bash

Pass every onboarding NEMOCLAW_* value on the bash side of the pipeline so the downloaded installer can read it. The commit pin also appears in the bootstrap URL so no mutable tag selects the code that enters the pipeline. Do not put a credential before curl, in a command-line argument, or in a committed script. Unset the credential from the interactive shell after onboarding completes:

$unset NVIDIA_INFERENCE_API_KEY

Use the matching credential variable when you select another provider. Refer to the CLI commands reference for provider-specific variables and accepted values.

VariableRequirementSecretPurpose
NEMOCLAW_NON_INTERACTIVE=1Required for unattended useNoDisables interactive onboarding prompts.
NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1Required for unattended useNoRecords explicit acceptance for the current run.
NEMOCLAW_AGENTRequired when the agent must not use the defaultNoSelects openclaw, hermes, or langchain-deepagents-code.
NEMOCLAW_PROVIDERRequired for a deterministic provider selectionNoSelects the inference provider.
Provider credentialRequired for providers that authenticateYesRegisters the credential with the OpenShell gateway.
NEMOCLAW_SANDBOX_NAMERequired for a deterministic sandbox nameNoNames the sandbox and its host registry entry.
NEMOCLAW_POLICY_TIEROptional, default balancedNoSelects the initial policy tier.
NEMOCLAW_WEB_SEARCH_PROVIDEROptionalNoSelects a supported search provider or none.
NEMOCLAW_INSTALL_REFRequired for this unattended server flowNoSelects the reviewed full commit SHA used by both the bootstrap URL and installer.
NEMOCLAW_INSTALL_TAGOptional convenience path, default lkgNoSelects a tag only when NEMOCLAW_INSTALL_REF is unset. Mutable tags are not the primary persistent-server path.

Verify Readiness

Do not use process presence as the sandbox-ready signal. The authoritative OpenShell signal is the row for headless-agent in phase Ready or Running. The substring NotReady is not a ready state.

Run each verification on the remote host:

$openshell sandbox list
$nemo-deepagents headless-agent status
$nemo-deepagents headless-agent connect --probe-only

nemo-deepagents headless-agent status exits nonzero when the sandbox, gateway, local container, or authoritative inference route is not verified. Its main Inference line probes https://inference.local/v1/models from inside the sandbox, then sends an inference request over the same route when that probe reports the route reachable. It repeats both probes up to three total attempts when that request returns a transient gateway status; refer to the CLI commands reference for the retried statuses and their token cost. The line reports healthy when the route served the request, unauthorized when the route rejected it with HTTP 401 or 403, and unhealthy after a final failure or after all transient attempts fail.

connect --probe-only waits up to 300 seconds by default for a cold sandbox to become ready. It then verifies or repairs the in-sandbox agent process and host forwards without opening a shell. It does not restart or replace the shared host OpenShell gateway.

The command prints one Probe timing: line with elapsed milliseconds for readiness, authority, lifecycle, gateway, processes, forward, inference, pairing, and publication stages. Use the stage values to identify where a slow or failed deployment spent its time. The line also reports lifecycle and forward actions and names the failed stage when available. Timing collection is diagnostic and fail-open. The command exit status remains the readiness decision: status 0 means the complete probe passed, and any nonzero status means the host is not ready for launch.

Readiness requires all of these results:

  • The OpenShell sandbox row is Ready or Running.
  • nemo-deepagents headless-agent status exits with status 0 and reports the inference route as healthy.
  • nemo-deepagents headless-agent connect --probe-only exits with status 0.

Access the Dashboard and API

Retrieve dashboard URLs and API tokens only when you need them. Do not write either value to logs, shell history, support bundles, or version control.

Deep Agents Code does not expose a dashboard URL or gateway token. Model traffic uses the OpenShell-managed inference.local route.

Understand Credential and State Boundaries

NemoClaw separates provider credentials, host metadata, and sandbox state.

BoundaryStored dataRebuild behavior
OpenShell gatewayProvider credentials and provider registrationsReused when the gateway and provider binding remain available. Raw values cannot be read back.
~/.nemoclaw/ on the hostSandbox registry, provider names, and onboarding session statePreserved by normal updates. The directory contains no sandbox policy or provider credential values.
Agent configuration in the sandboxGenerated inference routes, OpenShell resolver placeholders, and agent-specific settingsRegenerated from host registry and OpenShell state. Generated files are not a credential store.
Manifest-defined sandbox stateAgent workspace, memory, skills, and agent-specific durable filesSnapshotted and restored according to the selected agent manifest.
Arbitrary environment and profile editsDirect shell exports and edits outside the manifest contractNot guaranteed. Export host variables again and use documented host commands for durable configuration.

NemoClaw holds an environment-supplied provider credential in memory while it registers the value with OpenShell. The sandbox receives a resolver placeholder, and OpenShell substitutes the raw value at egress. For details, refer to Credential Storage.

Install a declarative agent skill through the supported host command:

$nemo-deepagents headless-agent skill install ./my-skill/

The skill directory must contain SKILL.md with a name field in its YAML frontmatter. Do not assume that packages, shell exports, or profile edits made by a skill survive a rebuild.

Add a Least-Privilege Policy

Use an additive custom preset when the sandbox needs a destination that the current policy does not allow. Scope the host, port, method, path, and executable to the smallest required set.

Save a reviewed preset as ./presets/internal-status.yaml, preview it, then apply it without a prompt:

$nemo-deepagents headless-agent policy add --from-file ./presets/internal-status.yaml --dry-run
$nemo-deepagents headless-agent policy add --from-file ./presets/internal-status.yaml --yes
$nemo-deepagents headless-agent policy list

--yes skips the confirmation prompt but does not skip schema, destination, or SSRF validation. NemoClaw merges the validated content into the current OpenShell policy and stores no second copy in the sandbox registry. Snapshot clone and rebuild carry the complete current OpenShell policy forward. Keep the source YAML in your configuration repository so operators can review and intentionally reapply changes. For the preset schema and removal workflow, refer to Network Policies.

An SSH command without -t, a service unit, and a CI job have no terminal on stdin, so the preset picker cannot run there. Pass the preset name, --from-file, or --from-dir in such a session. policy add and policy remove skip their confirmation prompts without a terminal on stdin, so neither needs --yes or NEMOCLAW_NON_INTERACTIVE=1.

Plan for Updates and Rebuilds

Create a named snapshot before host maintenance or a manual update:

$nemo-deepagents headless-agent snapshot create --name before-maintenance
$export NEMOCLAW_INSTALL_REF="<next-reviewed-40-character-commit-sha>"
$[[ "$NEMOCLAW_INSTALL_REF" =~ ^[0-9a-f]{40}$ ]] || {
> echo "NEMOCLAW_INSTALL_REF must be a reviewed full commit SHA" >&2
> exit 1
>}
$curl -fsSL "https://raw.githubusercontent.com/NVIDIA/NemoClaw/${NEMOCLAW_INSTALL_REF}/install.sh" | \
> NEMOCLAW_INSTALL_REF="$NEMOCLAW_INSTALL_REF" \
> bash
$nemo-deepagents upgrade-sandboxes --check

Use a newly reviewed commit SHA for each planned update instead of relying on the mutable installer default. The installer requires current backups before it changes an existing managed installation. Use nemo-deepagents headless-agent rebuild when you need the current agent image while preserving supported state.

ItemSame-container restartSnapshot and restoreRebuild or sandbox upgrade
Provider configurationPreservedProvider names are recorded, but raw credentials are not in the snapshotRegenerated from registry and OpenShell provider state
Current OpenShell policy, including custom presets and host editsRemains in OpenShellRead live for a clone handoff, not stored in snapshot metadataRead live and handed to replacement creation
Manifest-defined user and agent statePreservedPreservedPreserved when backup and restore succeed
Arbitrary files outside manifest stateUsually remain in the same writable layerNot preservedNot preserved
Manually installed system or global packagesUsually remain in the same writable layerNot preservedNot preserved
Direct edits to generated profile, config, or environment filesMay remain until regenerationAgent-specific and usually excluded or filteredRegenerated or filtered by the current manifest

| Host tunnel process | Not applicable to a container restart | Not preserved | Not preserved | | Dashboard, API, messaging, and agent forwards | Preserved only while their host processes remain active | Re-established during supported recovery | Re-established and verified after rebuild |

Snapshot only the state that the current agent manifest declares. Download any required file outside that contract before a destructive operation. Refer to Understand Sandbox State and Create and Restore Snapshots for agent-specific exclusions.

Recover After a Host Reboot

Use this sequence after every reboot until NemoClaw documents an automatic boot-persistence contract.

Start Docker first:

$sudo systemctl start docker
$docker info

Ask NemoClaw to select the sandbox’s recorded OpenShell gateway and report the current failure layer:

$nemo-deepagents headless-agent status

If status reports that the sandbox container exists but is stopped, start it:

$nemo-deepagents headless-agent start

Wait for authoritative readiness and repair sandbox-scoped processes and forwards:

$openshell sandbox list
$nemo-deepagents headless-agent connect --probe-only
$nemo-deepagents headless-agent status

Deep Agents Code has no in-sandbox gateway to recover. If status reports a degraded terminal runtime after the sandbox becomes ready, rebuild the sandbox.

If the registry entry remains but the sandbox container is missing, rebuild cannot recover the sandbox because its authoritative OpenShell policy and live workspace are gone. Remove the stale local entry and create a clean replacement:

$nemo-deepagents headless-agent destroy --yes
$nemo-deepagents onboard

The missing sandbox’s state cannot be recovered unless you have a separate snapshot. After onboarding, restore that snapshot explicitly. For failure-specific recovery boundaries, refer to Recover and Rebuild Sandboxes.

Troubleshoot a Headless Deployment

Use the failure layer from nemo-deepagents headless-agent status before you choose a recovery action.

Onboarding Was Interrupted

Reattach to the tmux or screen session first. If the process exited with a resumable session, inject the required credentials and use onboard --resume. Do not use --fresh unless discarding the saved choices and progress is intentional.

The Sandbox Is Missing or Not Ready

Run openshell sandbox list and inspect the row for headless-agent. NotReady does not satisfy readiness. Run nemo-deepagents headless-agent status, then use its start, connect --probe-only, or rebuild --yes guidance.

Inference Returns HTTP 5xx

A final HTTP status from 500 through 599 makes the authoritative inference.local route unhealthy. HTTP 502, 503, and 504 report unhealthy only after all transient attempts fail. Check the configured provider and host egress, then run:

$nemo-deepagents headless-agent doctor
$nemo-deepagents headless-agent logs --tail 200
$nemo-deepagents headless-agent status

Do not treat a running agent process as proof that inference works.

For Docker, DNS, port, memory, provider, and recovery errors, refer to Troubleshooting.