DEV Community

Cover image for OpenClaw on Mac Mini: Secure 24/7 Setup Guide for Production Use
Muhammad Zafar
Muhammad Zafar

Posted on • Edited on

OpenClaw on Mac Mini: Secure 24/7 Setup Guide for Production Use

This is a step-by-step guide to run OpenClaw on a Mac mini, intended for 24/7 uptime with a security-first baseline.

Side note: If you want this set up for you, message me. I’ll install it and tailor the agent to your goals.

Phase 1: macOS prep (uptime + baseline hardening)
1) Stop the machine from sleeping

sudo pmset -a sleep 0 disksleep 0 displaysleep 0
sudo pmset -a hibernatemode 0 powernap 0
sudo pmset -a standby 0 autopoweroff 0
sudo pmset -a autorestart 1

Verify:

pmset -g | grep sleep

Expected: sleep-related values are 0.

2) Keep the system awake across reboots (LaunchAgent + caffeinate)


cat > ~/Library/LaunchAgents/com.openclaw.caffeinate.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.openclaw.caffeinate</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/caffeinate</string>
        <string>-s</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
EOF

launchctl load ~/Library/LaunchAgents/com.openclaw.caffeinate.plist
Enter fullscreen mode Exit fullscreen mode

Verify:

pgrep caffeinate

Expected: returns a PID.

3) Enable auto-login for the agent user

System Settings → Users & Groups → Login Options → Automatic login: [agent user]

4) Turn on firewall + stealth mode
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on

5) Disable services you don’t need

sudo mdutil -a -i off
defaults write com.apple.NetworkBrowser DisableAirDrop -bool YES

6) Lock down home directory permissions

chmod 700 ~/

7) Enable FileVault (full disk encryption)

System Settings → Privacy & Security → FileVault → Turn On

8) Optional: enable Remote Login (SSH)

System Settings → General → Sharing → Remote Login → ON Restriction: agent user only.
Phase 2: Install Tailscale

brew install tailscale
tailscale up

Follow the auth URL to join your tailnet.

Verify:

tailscale status

Note: If you already have the Mac App Store version installed, the Homebrew CLI can conflict. The App Store build also doesn’t support Tailscale SSH. Use the Mac app for GUI management and the brew CLI for tailscale serve only.

Phase 3: Install prerequisites
Homebrew (if needed)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Node 22+

brew install node@22

Git

brew install git

Verify Node:

node -v

Expected: 22+
Create a Telegram bot (required for onboarding)

Message @botfather on Telegram
Send /newbot, choose name + username
Copy the bot token (used during onboarding)

Phase 4: Install OpenClaw and run onboarding

Install:

npm install -g openclaw@latest

Onboard:

openclaw onboard --install-daemon

During the wizard you’ll handle gateway setup, model/auth, channels (Telegram + bot token), skills, and daemon install.

Known bug (v2026.2.12+ / Issue #16134): the wizard can skip the Model/Auth step and jump ahead without collecting an API key. If that happens, the agent will be unresponsive. The fix is in Phase 5.

Verify:

openclaw --version
openclaw health

Pair Telegram:

Message your bot on Telegram, get the pairing code
Approve:
Enter fullscreen mode Exit fullscreen mode

openclaw pairing list --channel Telegram
openclaw pairing approve Telegram <CODE>

Verify again:

openclaw health

Expected: Telegram: ok (@yourbotname)

Phase 5: Configure API key + model setup
5.1 Remove stale env var overrides

A shell-level ANTHROPIC_API_KEY can override OpenClaw config and cause silent auth failures if it’s wrong.

Check:

echo $ANTHROPIC_API_KEY

If it returns something, find where it’s set:

grep -rn ANTHROPIC_API_KEY ~/.zshrc ~/.zprofile ~/.bash_profile ~/.zshenv 2>/dev/null

Remove the export line, then:

source ~/.zshrc
unset ANTHROPIC_API_KEY

5.2 Confirm your key works with a direct API call

Replace YOUR_KEY with your key from console.anthropic.com:

curl https://api.anthropic.com/v1/messages \
-H "x-api-key: YOUR_KEY" \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"claude-sonnet-4-20250514","max_tokens":50,"messages":[{"role":"user","content":"hi"}]}'

Expected: a JSON reply with Claude output. Errors usually mean the key is invalid.

5.3 Add env + models to openclaw.json

Edit:
nano ~/.openclaw/openclaw.json

Add at top-level:

"env": {
"ANTHROPIC_API_KEY": "YOUR_ACTUAL_KEY_HERE"
},

Inside agents.defaults, set model strategy:

"model": {
"primary": "anthropic/claude-sonnet-4-6",
"fallbacks": ["anthropic/claude-opus-4-6"]
},
"heartbeat": {
"every": "30m",
"model": "anthropic/claude-haiku-4-5",
"activeHours": { "start": "08:00", "end": "23:00" }
},

Meaning:

Sonnet for normal work
Haiku for heartbeat pings
Opus as fallback

Important: avoid the setup-token auth flow (openclaw models auth setup-token). It uses OAuth bearer tokens that can get stuck in persistent 401 loops. Prefer direct API key via the env block.

If onboarding created an auth.profiles block with "mode": "token", it can override your env key. If you see 401 errors, remove auth.profiles and delete:

rm ~/.openclaw/agents/main/agent/auth-profiles.json

5.4 Restart and test end-to-end

openclaw gateway restart
openclaw tui

Type hello. If you get (no output) or 401s, revisit 5.1 to 5.3.
Phase 6: Expose the dashboard safely with Tailscale Serve

tailscale serve --bg http://127.0.0.1:18789

Use http:// (plain loopback). Using https+insecure:// often yields 502 errors.

Access from tailnet: https://[mac-mini-hostname].tail[xxxxx].ts.net

Verify from another device:

curl -k https://[mac-mini-hostname].tail[xxxxx].ts.net

Security note: Use Serve, not Funnel. Serve stays private to your tailnet.

Phase 7: Security hardening

Run audits:

openclaw security audit
openclaw security audit --deep
openclaw security audit --fix

Lock down permissions:

chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/openclaw.json
find ~/.openclaw/credentials -type f -exec chmod 600 {} \;
find ~/.openclaw/agents -name "auth-profiles.json" -exec chmod 600 {} \;
find ~/.openclaw/agents -name "sessions.json" -exec chmod 600 {} \; 
Enter fullscreen mode Exit fullscreen mode

Verify gateway binds to loopback:

grep '"bind"' ~/.openclaw/openclaw.json
Expected: loopback

Verify token auth mode:

grep -A 3 '"auth"' ~/.openclaw/openclaw.json

Expected: "mode": "token"

Verify DM pairing policy:

grep '"dmPolicy"' ~/.openclaw/openclaw.json

Expected: pairing

Verify no insecure flags:

grep "allowInsecureAuth" ~/.openclaw/openclaw.json
grep "dangerouslyDisableDeviceAuth" ~/.openclaw/openclaw.json

Expected: no output

Run doctor:

openclaw doctor --fix

Note: gateway.discovery.mode is not a valid config key in v2026.2.13. Don’t add it.
Phase 8: Define the agent’s identity (this is what makes it useful)

List workspace files:
ls ~/.openclaw/workspace/

Use your LLM to generate these files:

IDENTITY.md
SOUL.md
USER.md
AGENTS.md
HEARTBEAT.md

Then paste them into:
nano ~/.openclaw/workspace/IDENTITY.md
nano ~/.openclaw/workspace/SOUL.md
nano ~/.openclaw/workspace/USER.md
nano ~/.openclaw/workspace/AGENTS.md
nano ~/.openclaw/workspace/HEARTBEAT.md

Warning: an empty HEARTBEAT.md can cause heartbeat to silently skip. It needs real content.

Test understanding (via Telegram): Ask it to explain autonomy zones, what it can do without permission, and what it must never do.

Phase 9: Cron jobs (optional)

Only add scheduled tasks if needed. Use --session isolated to avoid heartbeat prompt hijacking (bug #3589).


openclaw cron add \
  --name "job-name" \
  --cron "0 7 * * 1-5" \
  --tz "Europe/Vienna" \
  --session isolated \
  --message "Clear, specific instruction here." \
  --model "anthropic/claude-sonnet-4-5" \
  --deliver \
  --channel telegram \
  --best-effort 
Enter fullscreen mode Exit fullscreen mode

Verify:
openclaw cron list

Phase 10: Final verification checklist

macOS:
pmset -g | grep sleep
pgrep caffeinate
tailscale status

OpenClaw:

openclaw --version
openclaw health
openclaw security audit
openclaw system heartbeat last
openclaw cron list

Security:
grep '"bind"' ~/.openclaw/openclaw.json
grep '"dmPolicy"' ~/.openclaw/openclaw.json

Tailscale:

tailscale serve status

Behavior test: Send a task on Telegram. You should see it start without extra permission prompts, report results, and log work to memory/YYYY-MM-DD.md.
Key commands

Gateway

openclaw gateway restart
openclaw gateway status
openclaw dashboard

Status

openclaw health
openclaw doctor --fix
openclaw system heartbeat last

Security

openclaw security audit --deep --fix

Cron

openclaw cron list
openclaw cron add --name "..." --cron "..." --tz "..." --session isolated --message "..."

Telegram pairing

openclaw pairing list --channel Telegram
openclaw pairing approve Telegram <CODE>

Models

openclaw models status
openclaw models list

Config

cat ~/.openclaw/openclaw.json

Tailscale

tailscale status
tailscale serve status
tailscale serve --bg http://127.0.0.1:18789

Now if you don’t want to deal with any of this, contact me. I’ll set it up and tailor the agent to your business goals so you don’t have to figure it out. Email at: zafarrbizz@gmail.com

Top comments (0)