Files
swarm-master/ansible/playbooks/customize.yml
William Valentin c235b04fc3 feat: update ansible playbooks for openclaw VM configuration
- Add agentmon_ingest_url var to openclaw_servers inventory
- Reduce vm.swappiness from 10 to 5 for better memory management
- Refactor virtiofs mounts: remove bindfs layer, mount swarm-common
  directly at /mnt/swarm-common (simpler, no FUSE overhead)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:35:43 -07:00

229 lines
8.0 KiB
YAML

---
# 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/<name>.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