Restore Mr. Bernard from a fresh Ubuntu VPS to production parity in 45-90 minutes.
This repo is the operational ground truth for mrb.sh. It captures every
repo, every systemd unit, every nginx config, every vault entry, and every
manual step needed to take a clean VPS to the running stack. If the
production VPS dies, this repo plus the KeePassXC vault is enough to
rebuild — no other state required.
A phased VPS installer + ecosystem manifest + configuration snapshots + operator runbook that together reproduce a working OpenClaw agent stack:
- 27 repos declared in
ecosystem.yaml— cloned bysetup-ecosystem.shin tier order (core → service → optional) - 30+ systemd
--userservices + 12 timers materialized fromsnapshots/systemd/and wired up byprovision/phases/06-services.sh - 26 nginx site configs in
snapshots/nginx/with hostname-template substitution, installed by phase 8 - KeePassXC vault as single source of truth for ~25 credential entries,
schema in
provision/secrets-template.md - 10-phase installer (
provision/install.sh) with--only,--from,--skipflags for resumable, idempotent runs - Operator runbook in
provision/INSTALL.mdfor the human in the loop
- Not a copy of the agent — IDENTITY/SOUL/USER/RULES live in
openclaw-workspace(private). This repo bootstraps the scaffolding around the agent. - Not magic — you still need to populate the vault, run certbot, point DNS, and confirm Telegram/Telnyx webhooks manually. The runbook tells you when.
- Not a replacement for OpenClaw itself —
npm install -g openclawhappens in phase 4. This repo wraps OpenClaw, it doesn't replace it.
Full step-by-step is in provision/INSTALL.md.
Two-line summary on a fresh Ubuntu 22.04/24.04 VPS:
git clone https://github.com/mister-bernard/bernard-bootstrap.git /tmp/bernard-bootstrap
cd /tmp/bernard-bootstrap && bash provision/install.shThe installer walks you through identity prompts, vault creation, the long ecosystem clone, service+nginx wiring, and final verification. Re-runs are safe — it skips phases that already succeeded.
To bring up a passive standby instance instead of a primary:
BERNARD_MODE=failover bash provision/install.shServices install but don't start; nginx serves a standby page; promotion is
one command (bash provision/failover/promote-to-primary.sh). See
provision/FAILOVER.md for the full
failover model.
ecosystem.yaml is the source of truth. Each repo has a tier:
- core (4 repos) — agent cannot boot without these bernard-bootstrap, openclaw-workspace, openclaw-1, cc-bridge
- service (~15 repos) — production services mrb-sh, telegraph, harness, auto-responder, glucose-tracker, giant-cedar (pipeline + site), petrock-club, mrno-app, fund-tracker, call-queue, retell-backend, telnyx-sms/voice, n-number-tracking, webapi, book-factory
- optional (~8 repos) — nice-to-have, skipped by default bolzano-real-estate, wp-factory, defi-sec-lab, papertrade-audit, market-dashboard-v2 (deprecated), zero-g, aurora, harness-pulse (deprecated)
Default install brings up core,service. To include optional:
BERNARD_TIERS=core,service,optional bash provision/install.sh --only 5bash setup-ecosystem.sh # core+service
bash setup-ecosystem.sh --all # core+service+optional
bash setup-ecosystem.sh --status # show what's present/missing
bash setup-ecosystem.sh --update # git pull existing reposbernard-bootstrap/
├── README.md ← You are here
├── ECOSYSTEM.md ← Constellation diagram
├── AGENTS.md ← Operational rules (delegation, memory, safety)
├── ecosystem.yaml ← 27-repo manifest with tiers + post_clone + vault deps
├── setup-ecosystem.sh ← Clone/update repos honoring BERNARD_TIERS
├── setup.sh ← (legacy) thin workspace setup — superseded by provision/
│
├── provision/ ← VPS-to-production installer
│ ├── INSTALL.md ← Operator runbook (read this first)
│ ├── FAILOVER.md ← Failover/promotion model
│ ├── install.sh ← Phased dispatcher (--only N, --from N, --skip N)
│ ├── phases/ ← One script per phase
│ │ ├── 00-preflight.sh ← apt, Node 20, gh, KeePassXC, openclaw user
│ │ ├── 01-identity.sh ← interactive → ~/.openclaw/identity.env
│ │ ├── 02-vault.sh ← keepassxc-cli db-create, verify minimum entries
│ │ ├── 03-workspace.sh ← clone openclaw-workspace, hydrate templates
│ │ ├── 04-openclaw.sh ← npm install -g openclaw, materialize openclaw.json
│ │ ├── 05-ecosystem.sh ← invoke setup-ecosystem.sh per BERNARD_TIERS
│ │ ├── 06-services.sh ← copy units, materialize .env from vault, enable
│ │ ├── 07-timers.sh ← same pattern for timers
│ │ ├── 08-nginx.sh ← snapshot configs + hostname sub + certbot prompt
│ │ └── 09-verify.sh ← health curls, openclaw doctor, watchdog --once
│ ├── failover/ ← Failover scripts (sync/promote/demote)
│ ├── refresh-snapshots.sh ← Re-snapshot from running VPS (with secret scanner)
│ ├── secrets-template.md ← Vault schema — every credential the stack needs
│ ├── services-manifest.yaml ← 30+ service entries: unit_source, env_file, vault_entries, port
│ ├── provision-vps.sh ← (legacy) one-shot script — superseded by install.sh
│ ├── README.md ← Provisioning notes
│ └── setup-telegram-bot.md ← @BotFather walkthrough
│
├── snapshots/ ← Verbatim configs from production (sanitized)
│ ├── README.md ← Sanitization invariant + refresh workflow
│ ├── systemd/ ← ~70 user .service + .timer files
│ └── nginx/ ← ~26 nginx site configs (hostname placeholders)
│
├── templates/ ← Persona templates (customize for your agent)
│ ├── AGENTS.md SOUL.md IDENTITY.md USER.md HEARTBEAT.md TOOLS.md MEMORY.md
│
├── qwen-scaffolding/ ← Optional: Qwen-as-orchestrator starter kit
├── playbook/ ← Production-tested playbook docs
├── scripts/ ← Generic safety tools (restart-gateway, watchdog, etc.)
├── skills/ ← Skill manifest (see bernard-skills repo for impls)
└── tasks/ ← Lightweight task queue
provision/install.sh is the entry point. Phases:
| # | Phase | Interactive? | Owner |
|---|---|---|---|
| 0 | pre-flight | no | root |
| 1 | identity | yes | openclaw user |
| 2 | vault | yes | openclaw user |
| 3 | workspace | no | openclaw user |
| 4 | openclaw | no | openclaw user |
| 5 | ecosystem | no (long) | openclaw user |
| 6 | services | no | openclaw user |
| 7 | timers | no | openclaw user |
| 8 | nginx | yes (certbot) | root |
| 9 | verify | no | openclaw user |
Each phase is a standalone script under provision/phases/. Failures stop
the run and tell you exactly where to resume from. All output is logged to
/tmp/bernard-bootstrap-install.log.
snapshots/systemd/ and snapshots/nginx/ are verbatim copies of the
running production configuration. They are committed to git — but only after
provision/refresh-snapshots.sh confirms zero inline secrets. The refresh
script greps for sk-ant-, gho_, github_pat_, Retell key_, Telegram
bot tokens, and a generic 32-hex pattern; any hit aborts the snapshot.
To capture a config change after editing on production:
cd ~/projects/bernard-bootstrap
bash provision/refresh-snapshots.sh
git diff snapshots/
git add snapshots/ && git commit -m "snapshots: refresh — <reason>"
git push origin mainEvery credential lives in ~/.openclaw/vault.kdbx (KeePassXC). Per-service
.env files are deployment caches, materialized at install time by
secrets-deploy.sh (in openclaw-workspace) per services-manifest.yaml.
Schema for every entry is in provision/secrets-template.md.
Workflow:
vault entry edited
→ bash ~/.openclaw/workspace/scripts/secrets-deploy.sh --service <name>
→ systemctl --user restart <name>.service
Never hand-edit .env files for vault-backed secrets. secrets-audit.sh
detects drift between vault and .env.
This repo is designed so that {this repo} + {vault.kdbx} is sufficient
to rebuild Mr. Bernard from any Ubuntu 22.04/24.04 VPS. No data lives only
in the production filesystem. Anything that does live only in production
(memory store, ledger SQLite DBs, cached generated content) is backed up by
scripts/backup-system.py to a Hetzner StorageBox per the schedule in
workspace/playbook/backup.md.
If the production VPS is unrecoverable:
- Spin a new Ubuntu VPS
- Restore vault from any device (KeePassXC + Syncthing keep three copies)
- Restore latest StorageBox backup of
~/.openclaw/memory/and project DBs git clone bernard-bootstrap && bash provision/install.sh- Walk the runbook
A passive failover instance removes step 1 — it's already provisioned
and waiting. See provision/FAILOVER.md.
- v12.0 (2026-04-24) — Failover mode (
BERNARD_MODE=failover): installs only the standby nginx site, defers services until promoted, drives sync via thefailover/cron + rsync setup. Seeprovision/FAILOVER.md. - v11.0 (2026-04-24) — Full production parity overhaul. Phased
installer, 27-repo ecosystem with tiers, 96 verbatim snapshots, vault
schema, operator runbook. Two end-to-end audits on fresh Hetzner
CPX21 instances caught and fixed 12 fresh-box bugs (per-UID install
log, Node 22, gh apt repo, openclaw user creation,
BERNARD_VAULT_PWfor unattended vaults, D-Bus env vars for non-login shells, certbot bundled-options stub, cert-aware snapshot skipping, …) — log inprovision/FAILOVER.md. Re-runs are idempotent. - v9.0 → v10.x — see
git logfor incremental changes. - v1 → v8 — playbook + templates only, no installer.
Personal use. The templates and playbook are MIT-style; the scripts/ and
provision/ are tailored to this stack but should be readable as a
reference.