--- # 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 # # Per-host variables (set in host_vars/.yml): # brew_packages: [] # list of Homebrew packages to install - name: OpenClaw VM customizations hosts: openclaw_servers become: true tasks: - name: Set vm.swappiness=5 (live) ansible.posix.sysctl: name: vm.swappiness value: "5" 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=5' state: present # ── virtiofs shares ───────────────────────────────────────────────────── # Host: ~/lab/swarm → Guest: /mnt/swarm # Host: ~/lab/swarm/swarm-common → Guest: /mnt/swarm-common # Mounted directly via virtiofs (no bindfs layer). # Host dirs have o+w so openclaw (UID 999) can write. - name: Create swarm virtiofs mount point ansible.builtin.file: path: /mnt/swarm state: directory mode: "0755" - name: Create swarm-common virtiofs mount point ansible.builtin.file: path: /mnt/swarm-common state: directory mode: "0755" - name: Add swarm virtiofs entry to fstab ansible.posix.mount: path: /mnt/swarm src: swarm fstype: virtiofs opts: defaults state: present - name: Add swarm-common virtiofs entry to fstab ansible.posix.mount: path: /mnt/swarm-common src: swarm-common fstype: virtiofs opts: defaults state: present - name: Ensure swarm share root is world-writable (for openclaw UID 999) ansible.builtin.file: path: /mnt/swarm mode: "0777" state: directory - name: Ensure swarm-common share root is world-writable (for openclaw UID 999) ansible.builtin.file: path: /mnt/swarm-common mode: "0777" state: directory - name: Ensure openclaw user lingering is enabled (for user systemd services) ansible.builtin.command: cmd: loginctl enable-linger openclaw changed_when: false # ── Homebrew ─────────────────────────────────────────────────────────── - name: Install Homebrew dependencies ansible.builtin.apt: name: - build-essential - procps - curl - file - git state: present - name: Pre-create /home/linuxbrew owned by openclaw ansible.builtin.file: path: /home/linuxbrew state: directory owner: openclaw group: openclaw mode: "0755" - name: Install Homebrew (as openclaw user) ansible.builtin.shell: | NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" become_user: openclaw args: creates: /home/linuxbrew/.linuxbrew/bin/brew - name: Add Homebrew to openclaw user PATH ansible.builtin.blockinfile: path: /home/openclaw/.bashrc marker: "# {mark} HOMEBREW" block: | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" owner: openclaw group: openclaw create: true - name: Install Homebrew packages ansible.builtin.shell: | brew list {{ item }} 2>/dev/null || brew install {{ item }} become_user: openclaw environment: HOME: /home/openclaw PATH: /home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin loop: "{{ brew_packages | default([]) }}" register: brew_install changed_when: "'Installing' in brew_install.stdout" # ── Automatic security updates ───────────────────────────────────────── # The upstream role installs unattended-upgrades with security-only updates. # We extend it here to enable automatic reboots for kernel/libc updates, # scheduled at 04:00 — after the 03:00 backup and the Sunday 03:10 e2scrub. - name: Ensure unattended-upgrades is installed ansible.builtin.apt: name: - unattended-upgrades - apt-listchanges state: present - name: Configure unattended-upgrades ansible.builtin.copy: dest: /etc/apt/apt.conf.d/50unattended-upgrades mode: "0644" content: | // OpenClaw VM — automatic security updates Unattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}-security"; "${distro_id}ESMApps:${distro_codename}-apps-security"; "${distro_id}ESM:${distro_codename}-infra-security"; }; Unattended-Upgrade::Package-Blacklist {}; Unattended-Upgrade::AutoFixInterruptedDpkg "true"; Unattended-Upgrade::MinimalSteps "true"; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Remove-New-Unused-Dependencies "true"; Unattended-Upgrade::Remove-Unused-Kernel-Packages "true"; // Reboot at 04:00 if required (after 03:00 backup + Sunday 03:10 e2scrub) Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "04:00"; notify: Restart unattended-upgrades - name: Enable daily apt update and upgrade triggers ansible.builtin.copy: dest: /etc/apt/apt.conf.d/20auto-upgrades mode: "0644" content: | APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::AutocleanInterval "7"; - name: Ensure unattended-upgrades service is running and enabled ansible.builtin.systemd: name: unattended-upgrades state: started enabled: true # ── Agentmon telemetry hook ────────────────────────────────────────────── # Deploys the agentmon hook to OpenClaw's hooks directory so agent # activity (sessions, runs, tool calls, errors) is streamed to the # agentmon ingest gateway for monitoring. - name: Create agentmon hook directory ansible.builtin.file: path: "{{ openclaw_home }}/.openclaw/hooks/agentmon" state: directory owner: "{{ openclaw_user }}" group: "{{ openclaw_user }}" mode: "0755" - name: Deploy agentmon hook files ansible.builtin.copy: src: "files/agentmon-hook/{{ item }}" dest: "{{ openclaw_home }}/.openclaw/hooks/agentmon/{{ item }}" owner: "{{ openclaw_user }}" group: "{{ openclaw_user }}" mode: "0644" loop: - HOOK.md - handler.ts - name: Set AGENTMON_INGEST_URL in OpenClaw env ansible.builtin.lineinfile: path: "{{ openclaw_home }}/.openclaw/.env" regexp: '^AGENTMON_INGEST_URL=' line: "AGENTMON_INGEST_URL={{ agentmon_ingest_url }}" create: true owner: "{{ openclaw_user }}" group: "{{ openclaw_user }}" mode: "0600" - name: Set AGENTMON_VM_NAME in OpenClaw env ansible.builtin.lineinfile: path: "{{ openclaw_home }}/.openclaw/.env" regexp: '^AGENTMON_VM_NAME=' line: "AGENTMON_VM_NAME={{ inventory_hostname }}" create: true owner: "{{ openclaw_user }}" group: "{{ openclaw_user }}" mode: "0600" handlers: - name: Restart unattended-upgrades ansible.builtin.systemd: name: unattended-upgrades state: restarted