Initial commit — OpenClaw VM infrastructure

- ansible/: VM provisioning playbooks and roles
  - provision-vm.yml: create KVM VM from Ubuntu cloud image
  - install.yml: install OpenClaw on guest (upstream)
  - customize.yml: swappiness, virtiofs fstab, linger
  - roles/vm/: libvirt domain XML, cloud-init templates
  - inventory.yml + host_vars/zap.yml: zap instance config
- backup-openclaw-vm.sh: daily rsync + MinIO upload
- restore-openclaw-vm.sh: full redeploy from scratch
- README.md: full operational documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
William Valentin
2026-03-12 12:18:31 -07:00
commit aceeb7b542
71 changed files with 7840 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
---
# Post-provisioning customizations for OpenClaw VMs
# Run after playbooks/install.yml to apply host-specific tweaks
#
# Usage:
# ansible-playbook -i inventory.yml playbooks/customize.yml
# ansible-playbook -i inventory.yml playbooks/customize.yml --limit zap
- name: OpenClaw VM customizations
hosts: openclaw_servers
become: true
tasks:
- name: Set vm.swappiness=10 (live)
ansible.posix.sysctl:
name: vm.swappiness
value: "10"
state: present
reload: true
- name: Persist vm.swappiness in /etc/sysctl.conf
ansible.builtin.lineinfile:
path: /etc/sysctl.conf
regexp: '^vm\.swappiness'
line: 'vm.swappiness=10'
state: present
- name: Create virtiofs mount point
ansible.builtin.file:
path: /mnt/swarm
state: directory
mode: "0755"
- name: Mount virtiofs swarm share via fstab
ansible.posix.mount:
path: /mnt/swarm
src: swarm
fstype: virtiofs
opts: defaults
state: present
# Note: actual mount requires reboot after VM config update
- name: Ensure openclaw user lingering is enabled (for user systemd services)
ansible.builtin.command:
cmd: loginctl enable-linger openclaw
changed_when: false

View File

@@ -0,0 +1,39 @@
---
- name: Deploy OpenClaw to remote servers
hosts: openclaw_servers
become: true
vars:
ansible_python_interpreter: /usr/bin/python3
pre_tasks:
- name: Detect operating system
ansible.builtin.set_fact:
is_linux: "{{ ansible_system == 'Linux' }}"
is_debian_family: "{{ ansible_os_family == 'Debian' }}"
is_supported_distro: "{{ ansible_distribution in ['Debian', 'Ubuntu'] }}"
- name: Fail on unsupported non-Linux systems
ansible.builtin.fail:
msg: >-
Unsupported operating system: {{ ansible_system }}.
This installer supports Linux only.
when: not is_linux
- name: Fail on unsupported Linux distribution
ansible.builtin.fail:
msg: >-
Unsupported Linux distribution: {{ ansible_distribution }} {{ ansible_distribution_version }}.
This installer currently supports Debian and Ubuntu.
when:
- is_linux
- not is_supported_distro
- name: Install ACL for privilege escalation
ansible.builtin.package:
name: acl
state: present
when: is_supported_distro
roles:
- openclaw

View File

@@ -0,0 +1,188 @@
---
- name: Install OpenClaw with Docker and UFW firewall
hosts: localhost
connection: local
become: true
vars:
ansible_python_interpreter: /usr/bin/python3
environment:
TERM: xterm-256color
COLORTERM: truecolor
pre_tasks:
- name: Enable color terminal for current session
ansible.builtin.set_fact:
ansible_env: "{{ ansible_env | combine({'TERM': 'xterm-256color', 'COLORTERM': 'truecolor'}) }}"
- name: Detect operating system
ansible.builtin.set_fact:
is_linux: "{{ ansible_system == 'Linux' }}"
is_debian_family: "{{ ansible_os_family == 'Debian' }}"
is_supported_distro: "{{ ansible_distribution in ['Debian', 'Ubuntu'] }}"
- name: Fail on unsupported non-Linux systems
ansible.builtin.fail:
msg: >-
Unsupported operating system: {{ ansible_system }}.
This installer supports Linux only.
when: not is_linux
- name: Fail on unsupported macOS
ansible.builtin.fail:
msg: >-
macOS bare-metal support has been deprecated and disabled.
Please use a Linux VM or container instead.
See README.md for details.
when: ansible_os_family == 'Darwin'
- name: Fail on unsupported Linux distribution
ansible.builtin.fail:
msg: >-
Unsupported Linux distribution: {{ ansible_distribution }} {{ ansible_distribution_version }}.
This installer currently supports Debian and Ubuntu.
when:
- is_linux
- not is_supported_distro
- name: Display detected OS
ansible.builtin.debug:
msg: |
Detected OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
OS Family: {{ ansible_os_family }}
Linux: {{ is_linux }}
Debian family: {{ is_debian_family }}
Supported distro: {{ is_supported_distro }}
- name: Update apt cache and upgrade all packages (Debian/Ubuntu)
ansible.builtin.apt:
update_cache: true
upgrade: dist
cache_valid_time: 3600
when: is_debian_family and not ci_test
register: apt_upgrade_result
- name: Display apt upgrade results
ansible.builtin.debug:
msg: "✅ System packages updated and upgraded"
when: is_debian_family and apt_upgrade_result.changed
- name: Install ACL for privilege escalation
ansible.builtin.package:
name: acl
state: present
when: is_supported_distro
- name: Check if running as root
ansible.builtin.command: id -u
register: user_id
changed_when: false
become: false
- name: Set fact for root user
ansible.builtin.set_fact:
is_root: "{{ user_id.stdout == '0' }}"
roles:
- openclaw
post_tasks:
- name: Copy ASCII art script
ansible.builtin.template:
src: "{{ playbook_dir }}/../roles/openclaw/templates/show-lobster.sh.j2"
dest: /tmp/show-lobster.sh
mode: '0755'
- name: Display ASCII art
ansible.builtin.command: /tmp/show-lobster.sh
changed_when: false
- name: Create one-time welcome message for openclaw user
ansible.builtin.copy:
dest: "{{ openclaw_home }}/.openclaw-welcome"
owner: "{{ openclaw_user }}"
group: "{{ openclaw_user }}"
mode: '0644'
content: |
echo ""
echo "╔════════════════════════════════════════════════════════╗"
echo "║ 📋 OpenClaw Setup - Next Steps ║"
echo "╚════════════════════════════════════════════════════════╝"
echo ""
echo "You are: $(whoami)@$(hostname)"
echo "Home: $HOME"
echo "OS: $(uname -s) $(uname -r)"
echo ""
echo "Environment is configured:"
echo " ✓ XDG_RUNTIME_DIR: ${XDG_RUNTIME_DIR:-not set}"
echo " ✓ DBUS_SESSION_BUS_ADDRESS: ${DBUS_SESSION_BUS_ADDRESS:-not set}"
echo " ✓ OpenClaw: $(openclaw --version 2>/dev/null || echo 'not found')"
echo ""
echo "────────────────────────────────────────────────────────"
echo "🚀 Quick Start - Run This Command:"
echo "────────────────────────────────────────────────────────"
echo ""
echo " openclaw onboard --install-daemon"
echo ""
echo "This will:"
echo " • Guide you through the setup wizard"
echo " • Configure your messaging provider"
echo " • Install and start the daemon service"
echo ""
echo "────────────────────────────────────────────────────────"
echo "📚 Alternative Manual Setup:"
echo "────────────────────────────────────────────────────────"
echo ""
echo "1⃣ Interactive onboarding (recommended):"
echo " openclaw onboard --install-daemon"
echo ""
echo "2⃣ Manual configuration:"
echo " openclaw configure"
echo " nano ~/.openclaw/openclaw.json"
echo ""
echo "3⃣ Login to messaging provider:"
echo " openclaw providers login"
echo ""
echo "4⃣ Test the gateway:"
echo " openclaw gateway"
echo ""
echo "5⃣ Install as daemon (if not using onboard):"
echo " openclaw daemon install"
echo " openclaw daemon start"
echo ""
echo "────────────────────────────────────────────────────────"
echo "🔧 Useful Commands:"
echo "────────────────────────────────────────────────────────"
echo ""
echo " • View logs: openclaw logs"
echo " • Check status: openclaw status"
echo " • Stop daemon: openclaw daemon stop"
echo " • Restart daemon: openclaw daemon restart"
echo " • Troubleshoot: openclaw doctor"
echo " • List agents: openclaw agents list"
echo ""
{% if tailscale_enabled | default(false) %}echo "────────────────────────────────────────────────────────"
echo "🌐 Connect Tailscale VPN (optional):"
echo "────────────────────────────────────────────────────────"
echo ""
echo " exit"
echo " sudo tailscale up"
echo ""
{% endif %}echo "────────────────────────────────────────────────────────"
echo ""
echo "Type 'exit' to return to your previous user"
echo ""
# Remove welcome message (suppress errors if already deleted)
rm -f "$HOME/.openclaw-welcome" 2>/dev/null || true
- name: Add welcome message to .bashrc
ansible.builtin.lineinfile:
path: "{{ openclaw_home }}/.bashrc"
line: '[ -f ~/.openclaw-welcome ] && source ~/.openclaw-welcome'
state: present
insertafter: EOF
- name: Notify that playbook is complete
ansible.builtin.debug:
msg: "✅ OpenClaw installation complete!"

View File

@@ -0,0 +1,30 @@
---
# Provision a new OpenClaw VM from scratch on the hypervisor host.
#
# This playbook runs on localhost (the hypervisor) and:
# 1. Downloads the Ubuntu cloud image (cached)
# 2. Creates the VM disk image
# 3. Builds a cloud-init seed ISO for first-boot configuration
# 4. Defines the VM XML (EFI, memfd, virtiofs, TPM, watchdog)
# 5. Configures a static DHCP reservation
# 6. Enables autostart and starts the VM
# 7. Waits for SSH
#
# After this playbook completes, run:
# ansible-playbook -i inventory.yml playbooks/install.yml --limit <instance>
# ansible-playbook -i inventory.yml playbooks/customize.yml --limit <instance>
# ~/lab/swarm/restore-openclaw-vm.sh <instance> # to restore config from backup
#
# Usage:
# ansible-playbook -i inventory.yml playbooks/provision-vm.yml --limit zap
- name: Provision OpenClaw VM
hosts: openclaw_servers
connection: local
become: true
vars:
ansible_python_interpreter: /usr/bin/python3
roles:
- vm