OpenClaw Configuration
Archived. Manual hardening steps on this page are superseded by the
deploy.shAnsible automation. See Deployment for the current deployment workflow.
OpenClaw Configuration
Skillful-Alhazen is designed to run as a persistent agent via OpenClaw — an agent platform that provides always-on connectivity to messaging platforms (Telegram, Discord, etc.), scheduled tasks, and background processing.
This guide covers installing OpenClaw to work with skillful-alhazen, hardening the deployment for security, and accessing dashboards remotely via Tailscale.
Security context: OpenClaw grants an AI agent persistent access to your system — including shell execution, file I/O, and network access. The OpenClaw Security Hardening Guide documents the threat landscape in detail. This page applies those recommendations to a skillful-alhazen deployment. Read the full guide before proceeding.
Before You Begin: Account Hygiene
Never connect these accounts to an OpenClaw-managed system:
- Primary email, banking, or cryptocurrency accounts
- Work or corporate systems
- Password managers or credential vaults
- Social media with irreplaceable history
- Government or healthcare portals
Acceptable as dedicated/burner accounts only:
- A Telegram bot token (created for this purpose)
- A development-only GitHub account
- An Anthropic API key with usage limits set
- Low-stakes services you could recreate in under an hour
Skillful-alhazen’s skills (literature search, job hunting, knowledge graph) don’t require access to sensitive personal accounts. Keep it that way.
Prerequisites
- OpenClaw installed (
npm install -g openclaw) - Tailscale installed and configured (for remote dashboard access)
- Node.js 22.12.0+ — required to mitigate CVE-2026-21636 (permission model bypass). Check with
node --version. - Skillful-alhazen already set up per Getting Started
Installing OpenClaw
npm install -g openclaw
Verify installation:
openclaw --version
openclaw status
Gateway Configuration
The OpenClaw gateway is the always-on daemon that manages sessions, messaging, cron jobs, and heartbeats.
Start the Gateway
openclaw gateway start
Key Configuration
Use openclaw gateway config to set up:
- Channel: Connect to Telegram, Discord, Signal, etc.
- Workspace: Point to your skillful-alhazen workspace directory
- Model: Set your preferred Claude model
- Heartbeat: Configure periodic check-in interval
# View current config
openclaw gateway config get
# Example: set workspace
openclaw gateway config set workspace /path/to/skillful-alhazen
Refer to the OpenClaw docs for the full configuration reference.
Agent Setup
OpenClaw agents are configured under ~/.openclaw/agents/. The key files:
| File | Purpose |
|---|---|
AGENTS.md |
Agent behavior and conventions |
SOUL.md |
Personality and identity |
USER.md |
Information about the user |
MEMORY.md |
Long-term memory (curated) |
HEARTBEAT.md |
Periodic task checklist |
TOOLS.md |
Environment-specific notes (devices, SSH hosts, etc.) |
These files live in the OpenClaw workspace (~/.openclaw/workspace/) and are injected into every session.
Cron Jobs
OpenClaw supports scheduled tasks via cron jobs. Skillful-alhazen uses these for automated workflows like the job forager.
Example: Nightly Job Forager
The jobhunt skill’s forager pipeline runs nightly to discover new job postings:
Schedule: 0 0 * * * (midnight PST)
Type: agentTurn (isolated session)
Task: Run the full forager pipeline — search sources, triage candidates, report relevant finds
Cron jobs can be managed through the OpenClaw gateway or via the agent’s cron tool during a session.
Heartbeats vs Cron
| Use Case | Mechanism |
|---|---|
| Batch periodic checks (email, calendar) | Heartbeat |
| Exact timing (“9 AM every Monday”) | Cron |
| One-shot reminders | Cron (at schedule) |
| Tasks needing isolation from main session | Cron (isolated session) |
Security Hardening
The sections below follow the three-tier model from the OpenClaw Security Hardening Guide, adapted for a macOS deployment running skillful-alhazen.
Threat Model
Running OpenClaw under your login account means:
- The gateway process can read/write everything in your home directory
- Credentials (API keys, bot tokens, device keys) sit alongside personal files
- A compromised agent session could exfiltrate SSH keys, browser data, or documents
- No separation between “what the bot can do” and “what you can do”
Unfixable risks (acknowledged, not eliminated):
- Prompt injection from content the agent processes (papers, web pages, job postings)
- Zero-day exploits in OpenClaw, Node.js, or Claude’s tool use
- Compromised model provider APIs — a poisoned response could instruct the agent to act maliciously
- Supply chain attacks through MCP servers or npm packages
These are inherent to any system that gives an AI agent tool access. The mitigations below reduce the blast radius if any of them occur.
Deployment Choice: Local vs VPS
The hardening guide recommends running OpenClaw on an isolated VPS rather than a primary computer. Skillful-alhazen can run on either:
| Factor | Local (Mac Mini, etc.) | VPS (Hetzner, etc.) |
|---|---|---|
| Docker (TypeDB) | Native Docker Desktop | Docker CE |
| Latency to local LLMs (Ollama) | Low | High / N/A |
| Blast radius if compromised | Your local machine | Disposable server |
| Dashboard access | Tailscale Serve | Tailscale or direct |
| Cost | Hardware you already own | ~$4-10/month |
If you run locally, the dedicated user isolation described below is essential — it constrains the blast radius to the service user’s home directory rather than your entire account.
If you run on a VPS, user isolation is still recommended, but you gain the additional protection of being able to destroy and rebuild the entire machine if compromised.
Tier 1: Basic Protection
These are foundational steps. Skip none of them.
1.1 Gateway Binding: Loopback Only
The gateway must bind to 127.0.0.1, never 0.0.0.0. In openclaw.json:
{
"gateway": {
"bind": "loopback",
"port": 18789
}
}
Verify after startup:
sudo lsof -i :18789 -sTCP:LISTEN
# Should show localhost:18789, NOT *:18789
1.2 Firewall: Block the Gateway Port
Even with loopback binding, explicitly block the gateway port from external access:
macOS (pf):
# Add to /etc/pf.conf:
block in on ! lo0 proto tcp to any port 18789
Linux (ufw):
sudo ufw deny in 18789
1.3 File Permissions
Credential files must not be world-readable:
chmod 700 ~/.openclaw/credentials ~/.openclaw/identity
chmod 600 ~/.openclaw/openclaw.json
chmod 600 ~/.openclaw/identity/device.json
chmod 600 ~/.openclaw/credentials/*
1.4 Authentication Enforcement
Ensure device authentication is not disabled. In openclaw.json, verify that dangerouslyDisableDeviceAuth is not present or is set to false. Require pairing for Telegram DM access:
{
"channels": {
"telegram": {
"dmPolicy": "pairing"
}
}
}
1.5 Credential Encryption at Rest (Recommended)
File permissions prevent other users from reading credentials, but don’t protect against disk theft or backup exposure. For stronger protection, encrypt sensitive files with age before startup:
# Encrypt
age -r <your-public-key> -o openclaw.json.age openclaw.json
# Decrypt into memory at startup (in LaunchDaemon wrapper script)
age -d -i <key-file> openclaw.json.age > /tmp/openclaw-config && ...
This is especially important if your machine’s disk is not encrypted with FileVault (macOS) or LUKS (Linux).
1.6 Run the Built-in Security Audit
openclaw gateway audit
Fix all CRITICAL and WARNING findings before proceeding.
Tier 2: Standard Protection
2.1 Dedicated User Isolation (macOS)
This is the most impactful single hardening step for local deployments. Migrate the gateway from your login account to a dedicated service user.
What this achieves:
- Process isolation: Gateway runs as a separate OS user with no access to personal files
- Credential separation: Bot tokens, API keys, and device keys are owned by the service user; your login user cannot read them without sudo
- Least-privilege skill access: Read-only access to skill code via ACLs; the bot cannot modify code or push to git
- Auditability: All gateway processes visible under the service user in
ps
Architecture:
/Users/<your-user> (chmod 700)
├── <skill-repo>/ ◄── ACL: read-only for <service-user>
└── .docker/run/docker.sock ◄── ACL: read+write for <service-user>
│ (ACL traverse only)
▼
/Users/<service-user> (chmod 700)
└── .openclaw/
├── openclaw.json 600 — config + tokens
├── credentials/ 700 — telegram pairing
├── identity/ 700 — device keys
├── agents/ 700 — session data
├── workspace/ skills symlinks → shared repo
└── logs/ 755 — readable for debugging
│
▼
/Library/LaunchDaemons/
ai.openclaw.gateway.plist root:wheel 644
UserName: <service-user>
KeepAlive: true
Migration Steps
Step 0: Full Backup
mkdir -p ~/openclaw-migration-backup
rsync -a ~/.openclaw/ ~/openclaw-migration-backup/.openclaw/
cp ~/Library/LaunchAgents/ai.openclaw.gateway.plist ~/openclaw-migration-backup/
Step 1: Stop the gateway
launchctl bootout gui/$(id -u)/ai.openclaw.gateway
# Verify: lsof -i :<port> should return nothing
Step 2: Create a shared group
sudo dscl . -create /Groups/<shared-group>
sudo dscl . -create /Groups/<shared-group> PrimaryGroupID <available-gid>
sudo dscl . -create /Groups/<shared-group> RealName "OpenClaw Shared Access"
sudo dscl . -append /Groups/<shared-group> GroupMembership <your-user>
sudo dscl . -append /Groups/<shared-group> GroupMembership <service-user>
Step 3: ACL-based shared access
Grant the service user search-only (traverse) on your home directory and recursive read-only on the shared skill repository:
# Traverse only — cannot list directory contents
sudo chmod +a "<service-user> allow search" /Users/<your-user>
# Recursive read-only on the skill repository
sudo chmod -R +a "<service-user> allow read,readattr,readextattr,readsecurity,search,execute" \
/Users/<your-user>/<skill-repo>
If Docker Desktop is installed, the Docker socket on macOS is a symlink into your home directory. Add traverse ACLs on the intermediate directories:
sudo chmod +a "<service-user> allow search" /Users/<your-user>/.docker
sudo chmod +a "<service-user> allow search" /Users/<your-user>/.docker/run
sudo chmod +a "<service-user> allow read,write,readattr,readextattr" \
/Users/<your-user>/.docker/run/docker.sock
Step 4: Create directory structure
Mirror the .openclaw layout under the service user’s home:
/Users/<service-user>/.openclaw/
├── agents/main/{agent,sessions}
├── browser/
├── canvas/
├── credentials/
├── cron/runs/
├── devices/
├── identity/
├── logs/
├── media/
├── subagents/
├── telegram/
├── tools/
└── workspace/{memory,skills}
Step 5: Copy and adapt configuration
Copy all configuration files from the old location. Critical path rewrites:
openclaw.json: Changeworkspaceto the new location. Keep skill environment variables (likeALHAZEN_PROJECT_ROOT) pointing to the shared repo — accessed via ACL.sessions.json: Contains hardcoded paths to workspace, skills, and session files. Global find-and-replace the old.openclawprefix.exec-approvals.json: Contains a socket path that needs updating.- Session
.jsonlfiles: May contain embedded paths.
# Fix all .openclaw path references (but NOT shared repo paths)
sed -i '' 's|/Users/<your-user>/.openclaw/|/Users/<service-user>/.openclaw/|g' <files...>
Do not change paths that reference the shared skill repository — those are correct and accessed via ACL.
Set ownership and permissions:
- All files:
chown -R <service-user>:staff - Sensitive directories (
agents,credentials,identity,media,subagents,telegram):chmod 700 - Sensitive files (
openclaw.json, device keys, session state):chmod 600 - Logs directory:
chmod 755
Step 6: Service user shell profile
Create a minimal .zshrc for the service user:
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
export PYTHONDONTWRITEBYTECODE=1
export DOCKER_HOST="unix:///var/run/docker.sock"
export HOME="/Users/<service-user>"
export UV_NO_SYNC=1
export UV_CACHE_DIR="/Users/<service-user>/.cache/uv"
Key settings:
PYTHONDONTWRITEBYTECODE=1— prevents__pycache__write failures in the read-only shared repoUV_NO_SYNC=1— preventsuvfrom trying to write to the shared repo’s.venvUV_CACHE_DIR— writable cache location for the service user
Step 7: Docker configuration
mkdir -p /Users/<service-user>/.docker
echo '{"currentContext": "desktop-linux"}' > /Users/<service-user>/.docker/config.json
Step 8: Create LaunchDaemon
Replace the per-user LaunchAgent with a system LaunchDaemon at /Library/LaunchDaemons/ai.openclaw.gateway.plist:
UserNameandGroupNamespecify the service userHOMEpoints to the service user’s home- Environment includes
DOCKER_HOST,PYTHONDONTWRITEBYTECODE,UV_NO_SYNC,UV_CACHE_DIR - Owned by
root:wheel, mode644 RunAtLoad: trueandKeepAlive: true
Step 9: Disable old LaunchAgent
mv ~/Library/LaunchAgents/ai.openclaw.gateway.plist \
~/Library/LaunchAgents/ai.openclaw.gateway.plist.disabled
Step 10: Lock down home directories
sudo chmod 700 /Users/<your-user> # ACLs still allow service user traverse
sudo chmod 700 /Users/<service-user> # You can't read their credentials without sudo
Step 11: Start and verify
sudo launchctl bootstrap system /Library/LaunchDaemons/ai.openclaw.gateway.plist
Verify:
ps aux | grep openclaw-gateway— runs as service usercurl -4 http://127.0.0.1:18789/— HTTP 200sudo lsof -i :<port> -sTCP:LISTEN— bound to loopback- Send a Telegram message to the bot
2.2 Tool Allowlisting
Switch from denylists to explicit allowlists. Only permit commands the agent actually needs:
{
"permissions": {
"allow": [
"WebSearch",
"Bash(uv run:*)",
"Bash(docker ps:*)",
"Bash(docker compose:*)"
],
"deny": [
"Bash(sudo:*)",
"Bash(chmod:*)",
"Bash(chown:*)",
"Bash(rm -rf:*)",
"Bash(ssh:*)",
"Bash(scp:*)"
]
}
}
Allowlists are more secure than denylists — a denylist only blocks what you think of, while an allowlist blocks everything you didn’t think of.
2.3 MCP Server Security
If using MCP servers with OpenClaw:
- Pin versions — set
autoUpdate: falseto prevent untrusted updates - Disable unnecessary servers — especially
filesystem,shell,ssh, anddockerMCP servers - Never enable
enableAllProjectMcpServers: true - Review source code of any MCP server before installation — search for
eval(),exec(),spawn(), and unexpected network calls
Warning: A Cisco Talos study found that 26% of surveyed MCP skills contained vulnerabilities. Treat MCP servers as untrusted code.
2.4 Monitoring Script
Install a monitoring script that verifies security invariants. Run it periodically or after any configuration change:
| Check | What it verifies |
|---|---|
| Process isolation | Gateway runs as service user, not login user |
| LaunchDaemon status | Loaded with a running PID |
| Gateway connectivity | Responds on loopback |
| Network binding | Bound to localhost, not 0.0.0.0 |
| File permissions | Both homes are 700, config is 600, daemon is root:wheel |
| Cross-user isolation | Config files owned by service user |
| Old config | LaunchAgent is disabled |
| Logs | No EACCES or permission errors |
2.5 Maintenance Schedule
| Frequency | Task |
|---|---|
| Weekly | Review gateway logs for anomalies or permission errors |
| Monthly | Update OpenClaw (npm update -g openclaw), review tool allowlists |
| Monthly | Audit active OAuth sessions and API key usage |
| Quarterly | Rotate API keys and gateway tokens |
After any uv sync |
Re-apply ACL on the skill repo .venv (see Operations below) |
Tier 3: Advanced Protection (Optional)
These measures provide defense-in-depth but require more setup and maintenance.
3.1 Container Sandbox
The hardening guide recommends running OpenClaw inside a container with no direct internet access, proxying API calls through a credential broker (e.g., LiteLLM):
┌──────────────────────────────────────────────┐
│ openclaw-internal network (no internet) │
│ ┌──────────────┐ ┌───────────────────┐ │
│ │ OpenClaw │───▶│ LiteLLM │ │
│ │ (no egress) │ │ (credential │──▶ Internet (API only)
│ │ │ │ broker + rate │ │
│ └──────────────┘ │ limiting) │ │
│ └───────────────────┘ │
└──────────────────────────────────────────────┘
Verification if implemented:
docker exec openclaw-agent ping 8.8.8.8should faildocker exec openclaw-agent nc -zv litellm 4000should succeed- Containers run as UID 1000 (not root)
- Filesystem is read-only:
docker exec openclaw-agent touch /test-fileshould fail
Note: Use rootless Podman over Docker where possible. A Docker daemon escape grants full host access; a Podman escape lands as an unprivileged user.
Skillful-alhazen’s Docker Compose services (TypeDB, dashboards) already run on an isolated network. Containerizing the OpenClaw gateway itself would add an additional isolation layer.
3.2 Network Egress Filtering
A proxy container (e.g., Squid) between OpenClaw and the internet restricts which domains the agent can reach:
Example allowlist (deny-by-default):
# API providers
.anthropic.com
.openai.com
# Skills: literature search
.europepmc.org
.ebi.ac.uk
# Skills: job hunting
.linkedin.com
.greenhouse.io
.lever.co
# Infrastructure
.github.com
.npmjs.org
.telegram.org
.docker.io
Block all financial, email, cloud storage, social media, and unknown domains. Audit actually-accessed domains monthly and remove unused entries.
3.3 Source Code Review
Before installing any skill or MCP server:
- Download and review the source code
- Search for
eval(),exec(),spawn(),fetch(),XMLHttpRequest - Verify publisher identity and download history
- Run
npm auditon dependencies - Check for unexpected outbound network calls
This applies to third-party skills. Skillful-alhazen’s own skills are open source and auditable in the repository.
Remote Access with Tailscale
Skillful-alhazen runs Docker services (TypeDB, dashboards, hub) bound to 127.0.0.1 for security. To access these remotely (e.g., from your phone or laptop), use Tailscale Serve to proxy local ports over your Tailnet with authentication.
Why Tailscale Serve (Not Port Binding)
Binding ports to 0.0.0.0 exposes services to the entire network without authentication. Tailscale Serve keeps services on localhost and proxies them through your authenticated Tailnet — only your devices can reach them.
Setup
- Install Tailscale and join your Tailnet:
# macOS: Install from App Store or download from tailscale.com
# Verify connection
tailscale status
- Enable HTTPS (required for Tailscale Serve):
tailscale cert <your-machine-name>.<tailnet-name>.ts.net
- Serve the dashboard hub (port 8080):
tailscale serve --https=8080 http://127.0.0.1:8080
- Serve the job hunt dashboard (port 3001):
tailscale serve --https=3001 http://127.0.0.1:3001
- Verify from any device on your Tailnet:
https://<your-machine-name>.<tailnet-name>.ts.net:8080/
https://<your-machine-name>.<tailnet-name>.ts.net:3001/
Persistence Across Reboots
Tailscale Serve configs persist, but Tailscale itself must be running:
- macOS: Add Tailscale.app to System Settings > General > Login Items
- Linux:
sudo systemctl enable tailscaled
Docker Compose Port Bindings
The docker-compose.yml intentionally binds to 127.0.0.1:
services:
hub:
ports:
- "127.0.0.1:8080:80" # Only localhost — Tailscale proxies this
jobhunt-dashboard:
ports:
- "127.0.0.1:3001:3000" # Only localhost — Tailscale proxies this
typedb:
ports:
- "127.0.0.1:1729:1729" # Only localhost
Do not change these to 0.0.0.0 — that bypasses Tailscale’s authentication layer.
Ongoing Operations
| Task | Command | Restart needed? |
|---|---|---|
| Update skill code | git pull in the shared repo (as your user) |
No |
| Rebuild skill venv | uv sync then re-apply ACL on .venv (see below) |
No |
| Update OpenClaw | npm update -g openclaw then sudo launchctl kickstart -k system/ai.openclaw.gateway |
Yes |
| Edit config | sudo -u <service-user> vi /Users/<service-user>/.openclaw/openclaw.json then restart |
Yes |
| View logs | sudo tail -f /Users/<service-user>/.openclaw/logs/gateway.err.log |
No |
| Run monitor | openclaw-monitor |
No |
After recreating the skill repo .venv (e.g., after uv sync or dependency changes):
sudo chmod -R +a "<service-user> allow read,readattr,readextattr,readsecurity,search,execute" \
/Users/<your-user>/<skill-repo>/.venv
The service user runs with UV_NO_SYNC=1 — it uses the venv read-only and never tries to modify it.
Emergency Response
If you suspect a compromise:
- Stop immediately:
sudo launchctl bootout system/ai.openclaw.gateway(oropenclaw stop) - Cut network:
sudo pfctl -e && echo "block all" | sudo pfctl -f -(macOS) - Preserve evidence: Copy the
.openclawdirectory and logs before making changes - Assume all credentials compromised: Revoke API keys, bot tokens, OAuth sessions, and SSH keys immediately
- Review logs: Check session transcripts for unexpected tool invocations or data exfiltration attempts
Recovery: If running on a VPS, destroy and rebuild from scratch. If running locally, the dedicated user isolation means the blast radius is limited to the service user’s home directory — but still rotate all credentials the agent had access to.
Rollback (User Isolation)
If the user isolation setup causes issues, full rollback takes under 2 minutes:
sudo launchctl bootout system/ai.openclaw.gatewaysudo rm /Library/LaunchDaemons/ai.openclaw.gateway.plistsudo chmod 750 /Users/<your-user>+ remove ACLs withchmod -a- Rename
.disabledback to.plist, re-bootstrap the old LaunchAgent - Everything returns to pre-migration state
Risk Summary
| Risk | Status | Mitigation |
|---|---|---|
| Agent reads personal files | Mitigated | Dedicated user isolation; chmod 700 on both homes |
| Credentials exposed in plaintext | Partially mitigated | File permissions (600/700); full mitigation requires encryption at rest |
| Gateway exposed on network | Mitigated | Loopback binding; firewall rule |
| Agent runs destructive commands | Mitigated | Tool allowlisting; sudo denied |
| Python writes to read-only repo | Mitigated | PYTHONDONTWRITEBYTECODE=1 |
uv writes to read-only venv |
Mitigated | UV_NO_SYNC=1 |
| Docker socket access | Mitigated | Explicit ACLs on socket path |
| Prompt injection from content | Not mitigated | Inherent to AI agent architecture; reduce blast radius via isolation |
| Supply chain attacks (MCP/npm) | Partially mitigated | Source code review; version pinning |
| Compromised model provider | Not mitigated | Inherent risk; limit connected accounts |
| Container escape (Docker) | Not mitigated locally | Would require containerizing OpenClaw itself (Tier 3) |
| ACLs lost after venv recreation | Documented | Re-apply after each uv sync |
Architecture Overview
┌─────────────────────────────────────────────────────┐
│ Your Devices │
│ (phone, laptop, etc.) │
└──────────────────────┬──────────────────────────────┘
│ Tailscale (encrypted, authenticated)
▼
┌─────────────────────────────────────────────────────┐
│ Mac Mini / Server │
│ │
│ ┌──────────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ OpenClaw │ │ Tailscale │ │ Docker │ │
│ │ Gateway │ │ Serve │ │ │ │
│ │ (service │ │ │ │ ┌──────────┐ │ │
│ │ user) │ │ :8080 ──▶─│──│─│ Hub │ │ │
│ │ │ │ :3001 ──▶─│──│─│ Dashboard│ │ │
│ │ Telegram │ │ │ │ │ TypeDB │ │ │
│ │ Cron │ │ │ │ └──────────┘ │ │
│ │ Sessions │ └───────────┘ └──────────────┘ │
│ └──────────────┘ │
│ │ read-only ACL │
│ ▼ │
│ ┌──────────────┐ │
│ │ Skill Repo │ (owned by your login user) │
│ │ (read-only) │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────┘
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Dashboard returns 404 remotely | Tailscale stopped | tailscale up |
tailscale serve fails |
Tailscale not running | tailscale up first |
| Services unreachable after reboot | Tailscale not in Login Items | Add to Login Items |
| Gateway not responding | LaunchDaemon stopped | sudo launchctl kickstart -k system/ai.openclaw.gateway |
| Cron jobs not firing | Gateway down or job disabled | openclaw gateway status, check job config |
EACCES on agent sessions |
Hardcoded paths not updated | sed replace old .openclaw paths in sessions.json |
| Skill scripts fail with import errors | venv ACL missing after uv sync |
Re-apply ACL on .venv directory |
__pycache__ write errors |
Missing env var | Verify PYTHONDONTWRITEBYTECODE=1 in LaunchDaemon |
| Docker commands fail from agent | Socket ACL missing | Check ACLs on .docker/run/docker.sock |