- 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>
216 lines
6.7 KiB
YAML
216 lines
6.7 KiB
YAML
---
|
|
# Development mode installation - Clone repo, build from source, link globally
|
|
|
|
- name: Create code directory
|
|
ansible.builtin.file:
|
|
path: "{{ openclaw_code_dir }}"
|
|
state: directory
|
|
owner: "{{ openclaw_user }}"
|
|
group: "{{ openclaw_user }}"
|
|
mode: '0755'
|
|
|
|
- name: Check if openclaw repository already exists
|
|
ansible.builtin.stat:
|
|
path: "{{ openclaw_repo_dir }}/.git"
|
|
register: openclaw_repo_exists
|
|
|
|
- name: Clone openclaw repository
|
|
ansible.builtin.git:
|
|
repo: "{{ openclaw_repo_url }}"
|
|
dest: "{{ openclaw_repo_dir }}"
|
|
version: "{{ openclaw_repo_branch }}"
|
|
update: true
|
|
become: true
|
|
become_user: "{{ openclaw_user }}"
|
|
when: not openclaw_repo_exists.stat.exists
|
|
|
|
- name: Pull latest changes if repo exists
|
|
ansible.builtin.git:
|
|
repo: "{{ openclaw_repo_url }}"
|
|
dest: "{{ openclaw_repo_dir }}"
|
|
version: "{{ openclaw_repo_branch }}"
|
|
update: true
|
|
become: true
|
|
become_user: "{{ openclaw_user }}"
|
|
when: openclaw_repo_exists.stat.exists
|
|
register: git_pull_result
|
|
|
|
- name: Display git pull status
|
|
ansible.builtin.debug:
|
|
msg: "Git repository updated: {{ git_pull_result.changed | default(false) }}"
|
|
when: openclaw_repo_exists.stat.exists
|
|
|
|
- name: Install dependencies with pnpm
|
|
ansible.builtin.shell:
|
|
cmd: pnpm install
|
|
chdir: "{{ openclaw_repo_dir }}"
|
|
executable: /bin/bash
|
|
become: true
|
|
become_user: "{{ openclaw_user }}"
|
|
environment:
|
|
PNPM_HOME: "{{ openclaw_home }}/.local/share/pnpm"
|
|
PATH: "{{ openclaw_home }}/.local/bin:{{ openclaw_home }}/.local/share/pnpm:/usr/local/bin:/usr/bin:/bin"
|
|
HOME: "{{ openclaw_home }}"
|
|
register: pnpm_install_result
|
|
changed_when: "'Already up to date' not in pnpm_install_result.stdout"
|
|
|
|
- name: Build openclaw from source
|
|
ansible.builtin.shell:
|
|
cmd: pnpm build
|
|
chdir: "{{ openclaw_repo_dir }}"
|
|
executable: /bin/bash
|
|
become: true
|
|
become_user: "{{ openclaw_user }}"
|
|
environment:
|
|
PNPM_HOME: "{{ openclaw_home }}/.local/share/pnpm"
|
|
PATH: "{{ openclaw_home }}/.local/bin:{{ openclaw_home }}/.local/share/pnpm:/usr/local/bin:/usr/bin:/bin"
|
|
HOME: "{{ openclaw_home }}"
|
|
register: pnpm_build_result
|
|
changed_when: true # Build always changes dist/ directory
|
|
|
|
- name: Display build output
|
|
ansible.builtin.debug:
|
|
msg: "Build completed successfully"
|
|
when: pnpm_build_result.rc == 0
|
|
|
|
- name: Check if dist directory exists
|
|
ansible.builtin.stat:
|
|
path: "{{ openclaw_repo_dir }}/dist"
|
|
register: dist_dir
|
|
|
|
- name: Fail if build didn't create dist directory
|
|
ansible.builtin.fail:
|
|
msg: "Build failed - dist directory not found"
|
|
when: not dist_dir.stat.exists
|
|
|
|
- name: Check for package metadata
|
|
ansible.builtin.stat:
|
|
path: "{{ openclaw_repo_dir }}/package.json"
|
|
register: openclaw_package_json_stat
|
|
|
|
- name: Read package metadata
|
|
ansible.builtin.slurp:
|
|
src: "{{ openclaw_repo_dir }}/package.json"
|
|
register: openclaw_package_json_raw
|
|
when: openclaw_package_json_stat.stat.exists
|
|
|
|
- name: Parse package metadata
|
|
ansible.builtin.set_fact:
|
|
openclaw_package_json: "{{ openclaw_package_json_raw.content | b64decode | from_json }}"
|
|
when: openclaw_package_json_stat.stat.exists
|
|
|
|
- name: Resolve metadata-defined CLI entrypoint
|
|
ansible.builtin.set_fact:
|
|
openclaw_package_bin_entry: >-
|
|
{{
|
|
openclaw_package_json.bin
|
|
if openclaw_package_json.bin is string else
|
|
(
|
|
openclaw_package_json.bin.openclaw
|
|
if openclaw_package_json.bin is mapping and 'openclaw' in openclaw_package_json.bin else
|
|
(
|
|
(openclaw_package_json.bin | dict2items | map(attribute='value') | list | first)
|
|
if openclaw_package_json.bin is mapping else
|
|
''
|
|
)
|
|
)
|
|
}}
|
|
when: openclaw_package_json_stat.stat.exists
|
|
|
|
- name: Build CLI entrypoint candidate list
|
|
ansible.builtin.set_fact:
|
|
openclaw_cli_candidate_paths: >-
|
|
{{
|
|
[
|
|
openclaw_package_bin_entry | default(''),
|
|
'openclaw.mjs',
|
|
'bin/openclaw.js',
|
|
'dist/index.js'
|
|
] | reject('equalto', '') | unique | list
|
|
}}
|
|
|
|
- name: Check possible OpenClaw CLI entrypoints
|
|
ansible.builtin.stat:
|
|
path: "{{ openclaw_repo_dir }}/{{ item }}"
|
|
loop: "{{ openclaw_cli_candidate_paths }}"
|
|
register: openclaw_cli_candidates
|
|
|
|
- name: Resolve OpenClaw CLI entrypoint path
|
|
ansible.builtin.set_fact:
|
|
openclaw_cli_entry: >-
|
|
{{
|
|
(
|
|
openclaw_cli_candidates.results
|
|
| selectattr('stat.exists')
|
|
| map(attribute='stat.path')
|
|
| list
|
|
| first
|
|
) | default('')
|
|
}}
|
|
changed_when: false
|
|
|
|
- name: Fail if openclaw CLI entrypoint is missing
|
|
ansible.builtin.fail:
|
|
msg: >-
|
|
Unable to locate OpenClaw CLI entrypoint in {{ openclaw_repo_dir }}.
|
|
Expected one of: {{ openclaw_cli_candidate_paths | join(', ') }}
|
|
when: openclaw_cli_entry == ""
|
|
|
|
- name: Remove existing global openclaw symlink (if any)
|
|
ansible.builtin.file:
|
|
path: "{{ openclaw_home }}/.local/bin/openclaw"
|
|
state: absent
|
|
|
|
- name: Create symlink to openclaw binary
|
|
ansible.builtin.file:
|
|
src: "{{ openclaw_cli_entry }}"
|
|
dest: "{{ openclaw_home }}/.local/bin/openclaw"
|
|
state: link
|
|
owner: "{{ openclaw_user }}"
|
|
group: "{{ openclaw_user }}"
|
|
force: true
|
|
|
|
- name: Make openclaw binary executable
|
|
ansible.builtin.file:
|
|
path: "{{ openclaw_cli_entry }}"
|
|
mode: '0755'
|
|
owner: "{{ openclaw_user }}"
|
|
group: "{{ openclaw_user }}"
|
|
|
|
- name: Verify openclaw installation from development build
|
|
ansible.builtin.shell:
|
|
cmd: openclaw --version
|
|
executable: /bin/bash
|
|
become: true
|
|
become_user: "{{ openclaw_user }}"
|
|
environment:
|
|
PNPM_HOME: "{{ openclaw_home }}/.local/share/pnpm"
|
|
PATH: "{{ openclaw_home }}/.local/bin:{{ openclaw_home }}/.local/share/pnpm:/usr/local/bin:/usr/bin:/bin"
|
|
HOME: "{{ openclaw_home }}"
|
|
register: openclaw_dev_version
|
|
changed_when: false
|
|
|
|
- name: Display installed OpenClaw version (development build)
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
OpenClaw installed from source: {{ openclaw_dev_version.stdout }}
|
|
Repository: {{ openclaw_repo_dir }}
|
|
Binary: {{ openclaw_home }}/.local/bin/openclaw -> {{ openclaw_cli_entry }}
|
|
|
|
- name: Add development mode info to .bashrc
|
|
ansible.builtin.blockinfile:
|
|
path: "{{ openclaw_home }}/.bashrc"
|
|
marker: "# {mark} ANSIBLE MANAGED BLOCK - OpenClaw development"
|
|
block: |
|
|
# OpenClaw development mode
|
|
export OPENCLAW_DEV_DIR="{{ openclaw_repo_dir }}"
|
|
|
|
# Aliases for development
|
|
alias openclaw-rebuild='cd {{ openclaw_repo_dir }} && pnpm build'
|
|
alias openclaw-dev='cd {{ openclaw_repo_dir }}'
|
|
alias openclaw-pull='cd {{ openclaw_repo_dir }} && git pull && pnpm install && pnpm build'
|
|
create: true
|
|
owner: "{{ openclaw_user }}"
|
|
group: "{{ openclaw_user }}"
|
|
mode: '0644'
|