OpenClaw on Linux (Ubuntu/Debian): Setup Guide
A guide to installing and configuring OpenClaw on Linux: VPS and dedicated hardware, prerequisites, installation, systemd setup, and firewall configuration.
#Linux as an OpenClaw Host
Linux is an excellent choice for running OpenClaw, especially on cloud VPS instances or dedicated servers. With systemd service management, low resource overhead, and rock-solid uptime, a Linux server can keep your agent running indefinitely without intervention.
This guide focuses on Ubuntu 22.04 LTS and Ubuntu 24.04 LTS, which are the most popular choices in the OpenClaw community. The instructions also apply to Debian 12 (Bookworm) with minor adjustments. For other distributions, adapt the package manager commands accordingly.
#VPS vs Dedicated Hardware
| Factor | VPS (Cloud) | Dedicated Hardware |
|---|---|---|
| Cost | $5-20/month | One-time hardware cost |
| Uptime | 99.9%+ SLA | Depends on your power/internet |
| Setup time | 5 minutes | 30+ minutes |
| Maintenance | Provider handles hardware | You handle everything |
| Privacy | Data on provider's servers | Data stays local |
| Performance | Shared resources | Dedicated resources |
| Best for | Quick start, remote access | Privacy-focused, power users |
Recommended VPS providers: Hetzner (best value), DigitalOcean, Linode, Vultr. A $5-10/month instance with 1 vCPU and 1 GB RAM is sufficient for a single OpenClaw agent.
Recommended hardware: Any x86_64 or ARM64 machine running Ubuntu or Debian. A Raspberry Pi 5 works but is not recommended for production use due to SD card reliability.
#Step 1: System Prerequisites
#Update Your System
Start with a fresh, updated system:
#Install Required Packages
Install the essential build tools and dependencies:
#What Node.js Version Does OpenClaw Need?
The install docs list the supported runtimes as "Node 24.16+ or 26.1+", and recommend Node 26. Use the NodeSource repository to get one:
Verify the installation:
Ubuntu's own nodejs package is usually older than the supported range for the latest release listed as of September 19, 2026, which is why the NodeSource step comes first.
#Install pnpm (Optional)
#Step 2: Create a Dedicated User
Running OpenClaw as root is a security risk. Create a dedicated user account:
This creates a system user with:
- Home directory at
/home/openclaw - A dedicated group named
openclaw - Bash as the default shell
- No password login (use
sudo su - openclawto switch)
Grant the user necessary permissions:
Adding the openclaw user to the sudo group is optional and only needed if your skills require elevated permissions. For maximum security, do not add sudo access and instead grant specific permissions as needed.
Switch to the new user for the rest of the installation:
#Step 3: Install OpenClaw
Run the documented installer script as the openclaw user:
If you prefer a global package install, the docs give an npm and a pnpm path. npm 12 blocks unapproved package lifecycle scripts by default, hence the flag:
Then run onboarding, which is also where the managed service gets installed:
#What Does Onboarding Actually Ask?
openclaw onboard is "Guided setup that establishes inference first: it detects existing AI access, waits for your provider choice, verifies that connection, persists only the working route, and then starts OpenClaw to configure the rest." The documented phases are:
- Security notice and agent naming
The wizard opens with a security notice, then names your first agent. Use --agent-name <name> to set it non-interactively when no roster exists.
- Discovery access-level choice
Choose how much discovery access the agent gets.
- AI provider detection and selection
OpenClaw detects existing AI access and waits for your provider choice. See the API Key Setup guide for details on obtaining keys. The docs do not name a default or recommended model, so choose on your own cost and capability trade-off.
- Live connection verification
The wizard verifies the connection and persists only the working route.
- Memory import offer
If there is anything to import, the wizard offers to bring it across.
- Standard setup application
Config, workspace and bootstrap files are written. Pass --skip-health if you only want those writes in automation.
- Plugin and skill recommendations
The wizard suggests plugins and skills for your setup.
- Control UI dashboard handoff
The wizard hands off to the Control UI dashboard, or falls back to the terminal.
--install-daemon "starts the managed gateway install path first". Without a daemon flag, a local gateway must already be running (for example openclaw gateway run). openclaw onboard --classic opens the full step-by-step wizard, and --flow manual gives full prompts for port, bind and secret storage.
Messaging channels are configured after onboarding; see the Messaging Channels Guide.
#Verify Installation
After onboarding completes, check that OpenClaw is working:
openclaw health fetches "a health snapshot from the running Gateway over WebSocket RPC (no direct channel sockets from the CLI)". It takes --json, --timeout <ms> (default 10000) and --verbose, which "forces a live probe and expands output across all configured accounts and agents". There is no --quiet flag, so parse --json rather than grepping prose:
#Step 4: Set Up systemd Service
The systemd service ensures OpenClaw starts on boot and restarts automatically if it crashes. This is the Linux equivalent of the macOS LaunchAgent.
#Automatic Installation
The easiest approach is to use the built-in service installer. There is no bare openclaw --install-daemon flag. openclaw gateway install "installs and starts the service"; the --install-daemon flag belongs to onboarding, where it "starts the managed gateway install path first".
#What Is the Service Actually Called?
openclaw-gateway.service, not openclaw.service. The docs name the unit openclaw-gateway.service, or openclaw-gateway-<profile>.service for a named profile. Get it running and enabled:
Inspect the unit OpenClaw wrote:
#Manual Installation
If you prefer to write the unit yourself, the Gateway runbook's example uses these directives:
# ~/.config/systemd/user/openclaw-gateway.service[Unit]Description=OpenClaw GatewayAfter=network-online.targetWants=network-online.target[Service]Type=simpleExecStart=/usr/local/bin/openclaw gateway --port 18789Restart=alwaysRestartSec=10TimeoutStopSec=330RestartPreventExitStatus=78[Install]WantedBy=default.targetTwo of those directives are load-bearing and easy to get wrong:
TimeoutStopSec=330covers the Gateway's maximum 315-second stop drain. systemd's own limit is 330 seconds; launchd's is 20.RestartPreventExitStatus=78stops a restart loop on config errors. Exit code 78 signals invalid configuration.
Note that there is no --foreground flag. openclaw gateway (explicitly, openclaw gateway run) runs in the foreground already, which is what a Type=simple unit wants. Adjust the ExecStart= path if your openclaw binary lives elsewhere. For a system-wide unit, install it under /etc/systemd/system/openclaw-gateway.service and add a User= line to [Service].
Save the file and enable it:
For a system unit instead:
#Enable Lingering
By default, systemd user services stop when the user logs out. Enable lingering so the service runs even when no session is active:
This is critical for headless servers and VPS instances.
#Verify the Service
You should see active (running) in the output. openclaw gateway status --deep adds system-level service scanning, and openclaw doctor --fix audits and repairs service config drift.
View logs:
The journal only carries what the unit writes to stdout and stderr. OpenClaw's own log file defaults to /tmp/openclaw/openclaw-YYYY-MM-DD.log (/tmp/openclaw/openclaw-<profile>-YYYY-MM-DD.log for named profiles), and you can redirect it in ~/.openclaw/openclaw.json:
{ "logging": { "file": "/path/to/openclaw.log" }}Separately, Gateway lifecycle mutations "append best-effort key-value audit records to <state-dir>/logs/gateway-restart.log".
#Step 5: Configure the Firewall
If your server is accessible from the internet (especially on a VPS), you must configure the firewall to protect your OpenClaw instance.
#Install and Enable UFW
Set default policies:
#Allow SSH
Before enabling the firewall, make sure SSH is allowed or you will lock yourself out:
#Allow the Gateway Port (Optional)
The Gateway multiplexes "WebSocket + HTTP (Control UI, hooks, etc.)" onto a single port. The documented default is 18789, with precedence --port > OPENCLAW_GATEWAY_PORT > gateway.port > 18789. If you genuinely need it reachable off-host:
The Gateway does have built-in auth, and it is required: "Gateway auth is required by default - with no valid auth path configured, the Gateway refuses WebSocket connections (fail-closed)." The gateway.auth.mode values are token ("shared bearer token (recommended for most setups)"), password and trusted-proxy. That is a reason to configure auth properly, not a reason to open the port: the docs say the lan, tailnet and custom bind modes "expand the attack surface. Only use with gateway auth ... and a real firewall", advise preferring Tailscale Serve over LAN binds, and say to "never expose the Gateway unauthenticated on 0.0.0.0". Non-loopback Control UI deployments also require gateway.controlUi.allowedOrigins; allowing all origins is "an explicit allow-all policy, not a hardened default".
In most cases, leave gateway.bind on its loopback default and reach the box over Tailscale or an SSH tunnel instead of punching a hole in the firewall.
#Enable the Firewall
Check the status:
#Step 6: Remote Access
#Option A: SSH (Simplest)
If your server has a public IP or you are on the same network:
ssh openclaw@your-server-ipFor VPS instances, use the IP address provided by your hosting provider.
#Option B: Tailscale (Recommended for Home Servers)
Tailscale creates a secure mesh VPN, allowing you to access your server from anywhere without exposing ports to the internet.
Install Tailscale:
Follow the authentication link printed in the terminal. Once connected, your server gets a stable Tailscale IP (e.g., 100.x.y.z) that you can use from any device on your Tailscale network.
#Option C: Cloudflare Tunnel (Advanced)
For exposing the dashboard securely without opening ports:
Configure a tunnel pointing to localhost:18789, the default Gateway port. This gives you a custom domain with Cloudflare's authentication layer in front of the Gateway's own. If the Control UI will be reached on a non-loopback origin, set gateway.controlUi.allowedOrigins and consider gateway.publicOrigin, documented as an "optional externally reachable HTTPS origin".
#Step 7: Verify Everything Works
Run the comprehensive diagnostic:
Send a test message through your configured messaging channel and confirm the agent responds.
#Monitoring the Agent
Set up basic monitoring to ensure your agent stays healthy:
Check logs for errors:
Monitor resource usage:
Set up a simple health check cron:
openclaw health has no --quiet flag, so branch on --json output instead of prose:
# Add to crontab: checks health every 5 minutes, restarts if the snapshot fails*/5 * * * * openclaw health --json --timeout 5000 >/dev/null 2>&1 || systemctl --user restart openclaw-gateway.serviceOpenClaw also has its own scheduler, so a host cron entry is only for the case where the Gateway itself is down. Anything the agent should do on a schedule belongs in an automation: openclaw automations list --all shows every job including disabled ones, and the command "registers as openclaw cron with openclaw automations as an alias".
#Where Does OpenClaw Put Its Files?
"Everything lives under $OPENCLAW_STATE_DIR (default: ~/.openclaw)", which for the dedicated user on this guide's setup is /home/openclaw/.openclaw. The docs describe it as holding "config, channel/provider state, auth profiles, sessions, logs". These are the paths they actually name:
/home/openclaw/.openclaw/ openclaw.json # Main configuration file .env # Global environment fallback secrets.json # Secret values referenced from config credentials/oauth.json # OAuth credentials state/openclaw.sqlite # Shared state database skills/ # Shared managed skills agents/<agentId>/agent/auth.json # Per-agent auth profile agents/<agentId>/agent/openclaw-agent.sqlite agents/<agentId>/sessions/ # Per-agent session records workspace/ # Agent workspace (agents.defaults.workspace)The agent workspace defaults to OPENCLAW_WORKSPACE_DIR when set, otherwise <state-dir>/workspace. Bootstrap writes these files into it:
/home/openclaw/.openclaw/workspace/ AGENTS.md # Operating rules, including a `## Tools` section SOUL.md # Agent personality (optional bootstrap file) IDENTITY.md # Name, role and avatar (optional bootstrap file) USER.md # Context about you (optional bootstrap file) BOOTSTRAP.md # First-run only MEMORY.md # Curated long-term memory (optional) BOOT.md # Optional memory/YYYY-MM-DD.md # Daily memory files skills/ # Optional workspace-local skillsWorth knowing:
- There is no
data/orbackups/directory in the documented layout, andskills/is not split into built-in, community and custom folders. TOOLS.mdandHEARTBEAT.mdare retired. Tool and environment notes "now live in the## Toolssection ofAGENTS.md", andHEARTBEAT.md"is accepted but a no-op since heartbeat context moved to cron monitor scratch"..envhere is a global fallback. OpenClaw reads env vars from the parent process (shell, launchd/systemd, CI) and additionally loads a.envfrom the current working directory plus the global one at~/.openclaw/.env. Neither normally overrides an existing variable. On fresh Ubuntu installs using the default state dir, OpenClaw also reads~/.config/openclaw/gateway.envas a compatibility fallback after the global.env; if the two disagree it keeps~/.openclaw/.envand prints a warning.- Logs are not under the state directory by default. See the logging note in the service section above.
There is also no openclaw config edit. To find the file your editor should open, use config file, which "Prints the active config file path, resolved from OPENCLAW_CONFIG_PATH or the default location", and edit that file directly:
Or directly:
#Managing the Service
Common systemd commands for managing your OpenClaw instance:
| Command | Description |
|---|---|
systemctl --user start openclaw-gateway | Start the service |
systemctl --user stop openclaw-gateway | Stop the service |
systemctl --user restart openclaw-gateway | Restart the service |
systemctl --user status openclaw-gateway | Check service status |
journalctl --user -u openclaw-gateway -f | Stream the unit's stdout/stderr |
journalctl --user -u openclaw-gateway --since today | View today's journal entries |
systemctl --user enable openclaw-gateway | Enable start on boot |
systemctl --user disable openclaw-gateway | Disable start on boot |
You can also use the OpenClaw CLI commands, which wrap these systemd operations:
#Updating OpenClaw on Linux
To update to the latest version:
openclaw update is documented as "Update OpenClaw and switch between stable/extended-stable/beta/dev channels." What the docs actually promise:
- It restarts the Gateway service after a successful update unless you pass
--no-restart. - Package-manager updates that do restart "verify the restarted service reports the expected version before the command succeeds."
--channelsets and persists the update channel after core update success.--dry-runpreviews the planned actions "without writing config, installing, syncing plugins, or restarting."
The docs make no claim that update backs up your config, so take your own backup of openclaw.json before a risky upgrade.
If you installed globally with npm and prefer to drive the package manager yourself:
#Troubleshooting Linux-Specific Issues
#Service fails to start
Check the journal for error details:
Common causes:
- Node.js not found in PATH, or below the supported "Node 24.16+ or 26.1+" (fix: add the full path to
ExecStartin the service file, or upgrade Node) - Port 18789 already in use (fix: set
gateway.portinopenclaw.json, pass--port, or stop the conflicting service) - Invalid configuration, which exits with code 78 (fix: run
openclaw config validate, which "validates the current config against the active schema without starting the gateway") - Missing API keys (fix: run
openclaw config fileto locateopenclaw.json, then add your keys)
#Permission denied errors
If OpenClaw cannot write to its data directory:
#DNS resolution failures
Some minimal VPS images do not have proper DNS configuration:
#High memory usage
OpenClaw publishes no memory or CPU budget for the Gateway, so there is no documented "normal" to compare against. Measure first with systemctl --user status openclaw-gateway, then run openclaw doctor before reaching for a cap. systemd's MemoryMax and CPUQuota will happily throttle or OOM-kill a healthy Gateway mid-turn, so set them only once you know what your own workload needs, and keep TimeoutStopSec=330 so a restart still gets its full stop drain.
#Next Steps
- Security Hardening: essential for internet-facing servers
- API Key Setup: configure multiple LLM providers
- Cost Optimization: control API spending
- Heartbeat & Cron Configuration: schedule recurring tasks
- Troubleshooting: solutions for common issues
Sources
- OpenClaw: Where things live on disk
- OpenClaw: Agent workspace
- OpenClaw: Configuration: agent workspace and bootstrap
- OpenClaw: Config
- OpenClaw: Gateway
- OpenClaw: Manage the Gateway service
- OpenClaw: Onboard
- OpenClaw: Logs
- OpenClaw: Install
- OpenClaw: Env vars and .env loading
- OpenClaw: Configuration: gateway
- OpenClaw: Gateway ports, already running, and remote mode
- OpenClaw: Network exposure
- OpenClaw: Gateway runbook
- OpenClaw: Run the Gateway
- OpenClaw: Logging
- OpenClaw: Health
- OpenClaw: Dashboard
- OpenClaw: Update