My OpenClaw Setup: One Box That Can Make Websites

Posted
July 11, 2026
Updated
July 11, 2026
By
Jacob Lloyd β€” written with AI assistance, post-project
Read time
12 min read

In plain terms: This article explains my OpenClaw setup: one small Linux computer in my house whose AI helpers can make and maintain entire websites. They write draft articles, rebuild the site, and publish changes β€” but only through a safety script that previews everything first, backs up the server, and never deletes files. This very article is re-checked and refreshed once a week by the same setup it describes.

The website you’re reading right now is maintained by AI agents running on a small Linux box in my house β€” and the whole arrangement is built so they can do real work without ever being able to wreck anything.

Before anything else, the self-demonstrating part: this article is refreshed once a week by the very setup it describes. A scheduled job wakes an OpenClaw agent, it re-reads this page, fixes anything stale, runs the guard checks, and stamps the result. The “Updated” date at the top of this page is written by that weekly job β€” nobody types it. If that date is recent, the pipeline in these diagrams ran, end to end, within the last seven days.

tl;dr

  • What it is: a dedicated Linux mini-PC running OpenClaw (an open, self-hosted AI agent gateway) with local LLMs, wired to a static site generator and a gated deploy script.
  • What it costs: the hardware, electricity, and a cheap cloud API β€” DeepSeek runs most of my agent turns for a few dollars a month; free local models are the fallback tier.
  • What you need: any Linux box that can run a local model server, a static site, SSH access to your web host, and one afternoon.
  • What you end up with: agents that draft posts, rebuild the site, dry-run every deploy, back up the server before publishing, and refresh content weekly behind secret-scan and content-quality guards.

The whole box at a glance

Everything lives on one machine. Models serve tokens β€” mostly DeepSeek’s cheap cloud API these days, with local models as the fallback β€” the OpenClaw gateway turns them into agents with tools, the agents edit plain-text content, a deterministic generator builds the site, and a single gated script is the only road to the server.

What you end up with

The end state, before any setup talk:

  • “Draft me a post about X” in chat β†’ an agent writes a Markdown article into the site’s content/ folder, following the site’s frontmatter schema and house style, and rebuilds the local preview.
  • “Deploy it” β†’ the agent runs the deploy script, which by default is a dry run: it shows exactly which files would change on the server and touches nothing. Publishing for real requires an explicit --go from me, and even then the script takes a server-side backup first and never deletes anything.
  • Once a week, a scheduled job wakes an agent to refresh the site β€” fix stale dates, improve weak posts, check links β€” with guard checks before anything can publish (Step 3 has the details).
  • laserlloyd.com itself is managed this way.

The division of labor is the point: the agents do the typing, the scripts enforce the rules, and I make the one decision that matters β€” whether a change goes live.

The hardware and OS: any Linux box works

I use a mini-PC with a lot of unified memory because I like running large models locally (the full stack is in my companion post, Eight AI Agents, One AMD Box). But for website management specifically, the requirements are modest:

  • Any 64-bit Linux machine β€” a mini-PC, an old desktop, even a capable laptop. 16GB RAM runs small local models fine; 32GB+ opens up mid-size models that write noticeably better prose.
  • A distro with systemd (almost all of them) β€” the scheduling and service supervision below assume it.
  • Python 3 for the static site generator, rsync + SSH for deploys.

You don’t even strictly need a GPU. Small instruction-tuned models run acceptably on CPU for drafting and editing text. But I’ll be honest about where I landed after months of running both: DeepSeek’s cloud API is now the primary driver of my whole OpenClaw setup. The open local models were the original plan, and they still run, but the tradeoffs add up β€” minutes of model load time, VRAM juggling between services, and noticeably less intelligence than a frontier-cheap cloud model that costs fractions of a cent per message. Local is my fallback and my privacy tier, not my daily driver. (The real monthly bill: about $24.)

Step 1: install an agent gateway and a local model

Two pieces: something that serves a model over an OpenAI-compatible API, and something that turns that model into an agent β€” with tools, file access, and scheduled jobs.

Model server. LM Studio, Ollama, or llama.cpp’s server all work. Whichever you pick, run it as a systemd user service so it survives reboots:

# ~/.config/systemd/user/model-server.service
[Unit]
Description=Local LLM server
[Service]
ExecStart=/path/to/your/model-server --port 1234
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now model-server
curl -s http://localhost:1234/v1/models   # sanity check

Agent gateway. I use OpenClaw, an open self-hosted gateway that hosts named agents, gives them tools (shell, file read/write, web search), routes each agent to a model (local or cloud, with fallbacks), and exposes a chat interface. Install it, point a “webmaster” agent at your local model, and grant it tool access scoped to the website’s directory. Two configuration rules that matter regardless of which gateway you choose:

  • Bind the gateway to loopback and put any chat UI behind authentication. An agent with shell access is not a thing to leave open on your network.
  • Scope the agent’s working directory to the site repo. It needs to edit content/, not your home directory.

Two tiers: local agents for the routine, a strong cloud model for repairs

One box, two tiers of brainpower. The OpenClaw agents β€” riding DeepSeek’s cheap API, with local models behind them β€” handle the everyday, high-volume work: drafting, editing, link-checking, the weekly refresh. But when the system itself breaks (a config regression, a crashed gateway, a build that won’t run), I escalate to a strong cloud coding model that treats the whole box as its patient. I wrote that story up separately in When OpenClaw Breaks, I Fix It with Claude Code: the OpenClaw agents are the workforce, the strong coding model is the mechanic.

The crew: every bot on the box

The gateway hosts a roster of named agents, each routed to the model that fits its job. They all show up in DisPatch, the chat app the family uses β€” but not all of them in both modes: DisPatch’s PIN lock splits the roster into a safe, always-available set and a full-power set that only appears after unlock.

BotJobRuns onDisPatch (locked)DisPatch (unlocked)
BitsFront desk β€” the agent you talk to; understands the ask, dispatches the right specialistDeepSeek flash (cloud)β€”βœ”
BrainsThe hard thinker β€” specs, audits, anything worth waiting forDeepSeek reasoner (cloud)β€”βœ”
FlashQuick jobs and scheduled follow-ups β€” the watchdog that chases late workDeepSeek flash (cloud)β€”βœ”
HermesThe coding-agent bridge β€” dispatched programming workDeepSeek (cloud)β€”βœ”
DoxyLocal workhorse β€” bulk and private jobs that shouldn't leave the house122B local model (vLLM)β€”βœ”
CharleyVision β€” "what's in this photo?", image-aware tasksGemma 31B (local, LM Studio)βœ”βœ”
Alpha & BetaFamily-safe general helpers β€” homework questions, everyday chatDeepSeek flash (cloud)βœ”βœ”
TerminexNot an agent β€” DisPatch's Reasonix coding terminal, a real PTY in the browserDeepSeek (cloud)β€”βœ”

How they perform, honestly:

  • The DeepSeek-backed bots are the daily drivers. Flash-tier agents (Bits, Flash, Alpha, Beta) answer in seconds, cost fractions of a cent per message, and never need warming up. Brains, on the reasoner tier, takes noticeably longer per answer β€” that’s the point, it’s the one you hand problems worth thinking about β€” and still costs pennies per session. The whole stack’s measured bill is in the cost article.
  • The local bots are slower and dumber, but private and free. Doxy’s 122B model takes minutes to load into memory and its long turns can run several minutes more; the gateway’s timeouts had to be raised specifically to accommodate it. Charley’s vision model is the exception that stays busy β€” image description is something no cheap cloud tier here does, so a local model earns its VRAM.
  • The safe set is deliberately boring. Alpha, Beta, and Charley are the locked-mode roster: general info and vision, no tools that touch files or systems. That’s what makes handing a phone to a kid a non-event.

Step 2: a static site plus a gated deploy script

Agents and WordPress mix badly β€” a database, a login, plugins, and PHP are all attack surface and all failure modes. A static site generator is the natural partner for an agent: the entire site is plain text files in a folder, the build is one command, and “publish” is a file copy. My generator is a few hundred lines of Python (Jinja2 + Markdown + YAML); Hugo, Eleventy, or Zola work the same way. What matters is the contract:

  • Content is Markdown files with frontmatter. An LLM edits these natively and a git diff shows exactly what it did.
  • The build is deterministic. Same content in, byte-identical site out β€” so any output change is traceable to a content change.
  • There is exactly one deploy path, and it is a script with the safety built in, not a set of instructions the agent is trusted to follow.

That last one is the heart of this whole setup. Here’s the shape of mine:

./deploy.sh preflight   # checks SSH, target webroot, size budget
./deploy.sh             # build + DRY-RUN rsync β€” prints what would change
./deploy.sh --go        # build + server-side backup + publish + verify

And what the script guarantees, in order of importance:

  1. Dry-run by default. Running it with no arguments can never modify the server. An agent can run it freely to show me a pending deploy.
  2. Never deletes. rsync runs without --delete. A confused agent can overwrite a page with a newer version; it cannot erase the site.
  3. Backs up first. With --go, the script takes a server-side tarball of the webroot before any file is overwritten (keeping the last few). If the backup fails, the deploy aborts.
  4. Fail-closed. A missing manifest, an unreachable host, or a placeholder config value aborts before rsync runs. Source files (templates, scripts, configs) are hard-excluded so they can never ship to the public webroot.
  5. Verifies after. It fetches the live homepage and greps for a generator marker the build embeds β€” a bare HTTP 200 can be a false positive if old hosting still answers for the domain.

The agent is allowed to run the dry run and preflight whenever it likes. The --go flag is reserved for me. That single asymmetry converts “an AI has SSH-adjacent access to my production site” from terrifying to boring.

Step 3: weekly scheduled updates, with guardrails

The last piece makes it self-maintaining. A systemd timer fires once a week and hands the agent a standing brief: review the site, refresh anything stale, tighten weak posts, verify internal links, and stage β€” not publish β€” the result. That job is also what maintains this article: part of its brief is “re-read the OpenClaw setup post, fix anything that has drifted from reality, and stamp the updated: date.” The date at the top of this page is that stamp.

# ~/.config/systemd/user/site-refresh.timer
[Unit]
Description=Weekly website content refresh
[Timer]
OnCalendar=Sun 06:00
Persistent=true
[Install]
WantedBy=timers.target

The service it triggers calls the gateway’s API (or CLI) with the brief, then runs the guard checks on whatever the agent staged:

  • Secret scan. A pattern scan over the diff for anything shaped like an API key, token, password, or private hostname. Tools like gitleaks do this off the shelf. Any hit aborts the run β€” fail closed, no exceptions.
  • Professional-content check. A second LLM pass, with a different prompt than the writer, reviews the staged changes against one question: “would a business be comfortable publishing this?” Tone, claims, unfinished TODOs, placeholder text. A fail leaves the changes staged for human review instead of deploying.
  • Build must pass, including the link/asset checker β€” a broken image or dead internal link fails the run before it ever reaches the deploy script.

Only when all three pass does the job even dry-run a deploy β€” and on this site, actual publishing still waits for my --go. If you eventually trust the pipeline enough to let the weekly job publish autonomously, the guards plus the never-delete, backup-first deploy script cap the blast radius at “a bad article went live and I restored from backup.”

Replicating this

Everything above is buildable from this description β€” there’s nothing proprietary in it. The recipe, condensed:

  1. Pick a Linux box and install a local model server (LM Studio, Ollama, llama.cpp) as a systemd service.
  2. Install an agent gateway (OpenClaw or similar) bound to loopback; create one webmaster agent with file/shell tools scoped to the site directory.
  3. Move the site to a static generator if it isn’t already β€” Markdown content in, one build command out.
  4. Write the gated deploy script with the five guarantees above: dry-run default, no deletions, backup-first, fail-closed, post-deploy verification. This is the piece worth the most care; it’s maybe 150 lines of bash.
  5. Add the weekly timer and the two guard checks (secret scan + LLM content review), fail-closed.
  6. Keep --go human until the pipeline has earned otherwise.

Per this site’s convention, the “implement this yourself” box at the top of the article means exactly what it says: this write-up is deliberately detailed enough that you can hand the whole article to your own LLM and ask it to build each piece for your site. The deploy script’s guarantees list is effectively its spec.

Gotchas

  • The deploy script must be the only path. The first time you (or an agent) hand-rolls an rsync “just this once,” you’ve created the incident the script existed to prevent. Mine hard-excludes source files and refuses placeholder configs precisely because a one-off command wouldn’t.
  • A bare HTTP 200 is not a successful deploy. During my WordPress migration, the old hosting kept answering for the domain β€” every “verification” passed while the new files sat unused. Embed a generator marker in your build and grep the live page for it.
  • Agents follow the schema you show them, including the TODOs. If your post scaffold has placeholder text, a lazy model will publish TODO: excerpt here verbatim. That’s half of why the professional-content check exists.
  • Don’t let the writer review itself. Same model, same prompt, same blind spots. The reviewer needs a different prompt at minimum, ideally a different model.
  • Scheduled LLM jobs need timeouts and a “staged, not published” default. A weekly job that can publish unsupervised will eventually publish something weird at 6am on a Sunday. Staging costs you nothing but a review.
  • Secret scans belong in the pipeline, not in the agent’s instructions. “Never include secrets” in a prompt is a wish; a fail-closed scan on the diff is a control.

← More AI & Local LLM