656 lines
23 KiB
YAML
656 lines
23 KiB
YAML
---
|
|
- name: Inspect existing OpenClaw gateway JSON config
|
|
ansible.builtin.stat:
|
|
path: "{{ gateway_openclaw_config_path }}"
|
|
register: gateway_openclaw_existing_config_stat
|
|
no_log: true
|
|
|
|
- name: Read existing OpenClaw gateway JSON config
|
|
ansible.builtin.slurp:
|
|
path: "{{ gateway_openclaw_config_path }}"
|
|
register: gateway_openclaw_existing_config_raw
|
|
when: gateway_openclaw_existing_config_stat.stat.exists | default(false)
|
|
no_log: true
|
|
|
|
- name: Resolve OpenClaw gateway secrets
|
|
ansible.builtin.set_fact:
|
|
gateway_openclaw_effective_gateway_token: >-
|
|
{{
|
|
gateway_openclaw_gateway_token
|
|
if (gateway_openclaw_gateway_token | trim | length > 0)
|
|
else (
|
|
(
|
|
gateway_openclaw_existing_config_raw.content | default('') | b64decode | from_json
|
|
).gateway.auth.token | default('')
|
|
)
|
|
}}
|
|
no_log: true
|
|
|
|
- name: Assert OpenClaw gateway secrets are provided
|
|
ansible.builtin.assert:
|
|
that:
|
|
- gateway_openclaw_effective_gateway_token | trim | length > 0
|
|
fail_msg: >-
|
|
gateway_openclaw_gateway_token is required. Pass it with -e or keep an
|
|
existing {{ gateway_openclaw_config_path }} with gateway.auth.token; do
|
|
not commit it into inventory/defaults.
|
|
no_log: true
|
|
|
|
- name: Ensure OpenClaw gateway config directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_config_path | dirname }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0700"
|
|
|
|
- name: Ensure OpenClaw workspace directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_workspace_path }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "{{ gateway_openclaw_workspace_mode }}"
|
|
|
|
- name: Ensure OpenClaw compile cache directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0755"
|
|
|
|
- name: Ensure OpenClaw extension backup directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_extension_backup_dir }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0700"
|
|
|
|
- name: Install required OpenClaw gateway package version
|
|
ansible.builtin.command:
|
|
cmd: >-
|
|
npm install --global --omit=dev --no-audit --no-fund
|
|
--prefix "{{ gateway_openclaw_home }}/.local"
|
|
"{{ gateway_openclaw_npm_package_spec }}"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: "{{ ansible_os_family != 'Darwin' }}"
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_package_install
|
|
changed_when: >-
|
|
'added ' in (gateway_openclaw_package_install.stdout | default('')) or
|
|
'removed ' in (gateway_openclaw_package_install.stdout | default('')) or
|
|
'changed ' in (gateway_openclaw_package_install.stdout | default(''))
|
|
when:
|
|
- not ansible_check_mode
|
|
notify: Restart openclaw gateway
|
|
|
|
- name: Ensure OpenClaw global plugin npm directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_global_npm_dir }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0700"
|
|
|
|
- name: Install required OpenClaw global plugin versions
|
|
ansible.builtin.command:
|
|
cmd: >-
|
|
npm install --omit=dev --no-audit --no-fund --save-exact
|
|
--prefix "{{ gateway_openclaw_global_npm_dir }}"
|
|
{{ item.package_spec | default(item.name ~ '@' ~ item.version) | quote }}
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_required_global_plugin_installs
|
|
changed_when: >-
|
|
'added ' in (gateway_openclaw_required_global_plugin_installs.stdout | default('')) or
|
|
'removed ' in (gateway_openclaw_required_global_plugin_installs.stdout | default('')) or
|
|
'changed ' in (gateway_openclaw_required_global_plugin_installs.stdout | default(''))
|
|
loop: "{{ gateway_openclaw_required_global_plugins }}"
|
|
loop_control:
|
|
label: "{{ item.package_spec | default(item.name ~ '@' ~ item.version) }}"
|
|
when:
|
|
- not ansible_check_mode
|
|
notify: Restart openclaw gateway
|
|
|
|
- name: Remove unsupported OpenClaw global plugin packages
|
|
ansible.builtin.command:
|
|
cmd: >-
|
|
npm uninstall --no-audit --no-fund
|
|
--prefix "{{ gateway_openclaw_global_npm_dir }}"
|
|
{{ item }}
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_removed_global_plugin_packages
|
|
changed_when: "'removed ' in (gateway_openclaw_removed_global_plugin_packages.stdout | default(''))"
|
|
loop: "{{ gateway_openclaw_removed_global_plugins }}"
|
|
loop_control:
|
|
label: "{{ item }}"
|
|
when:
|
|
- gateway_openclaw_removed_global_plugins | length > 0
|
|
- not ansible_check_mode
|
|
notify: Restart openclaw gateway
|
|
|
|
- name: Reset OpenClaw compile cache after package or plugin changes
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
state: absent
|
|
when:
|
|
- not ansible_check_mode
|
|
- >-
|
|
(gateway_openclaw_package_install.changed | default(false))
|
|
or
|
|
(gateway_openclaw_required_global_plugin_installs.changed | default(false))
|
|
or
|
|
(gateway_openclaw_removed_global_plugin_packages.changed | default(false))
|
|
|
|
- name: Recreate OpenClaw compile cache after package or plugin changes
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0755"
|
|
when:
|
|
- not ansible_check_mode
|
|
- >-
|
|
(gateway_openclaw_package_install.changed | default(false))
|
|
or
|
|
(gateway_openclaw_required_global_plugin_installs.changed | default(false))
|
|
or
|
|
(gateway_openclaw_removed_global_plugin_packages.changed | default(false))
|
|
|
|
- name: Refresh OpenClaw plugin registry
|
|
ansible.builtin.command:
|
|
cmd: "{{ gateway_openclaw_binary_path }} plugins registry --refresh"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
changed_when: false
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Move stale OpenClaw plugin backups out of extension scan path
|
|
ansible.builtin.shell: |
|
|
set -euo pipefail
|
|
shopt -s nullglob
|
|
moved=0
|
|
for backup_path in "{{ gateway_openclaw_home }}/.openclaw/extensions"/openclaw-multi-session-plugins.backup.*; do
|
|
backup_name="$(basename "$backup_path")"
|
|
backup_target="{{ gateway_openclaw_extension_backup_dir }}/${backup_name}"
|
|
if [ -e "$backup_target" ]; then
|
|
rm -rf "$backup_path"
|
|
else
|
|
mv "$backup_path" "$backup_target"
|
|
fi
|
|
moved=1
|
|
done
|
|
chown -R "{{ gateway_openclaw_service_user }}:{{ gateway_openclaw_service_group }}" "{{ gateway_openclaw_extension_backup_dir }}"
|
|
echo "moved=${moved}"
|
|
args:
|
|
executable: /bin/bash
|
|
register: gateway_openclaw_stale_extension_backups
|
|
changed_when: "'moved=1' in (gateway_openclaw_stale_extension_backups.stdout | default(''))"
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Inspect OpenClaw gateway JSON config attributes
|
|
ansible.builtin.command:
|
|
cmd: lsattr "{{ gateway_openclaw_config_path }}"
|
|
register: gateway_openclaw_config_attrs
|
|
changed_when: false
|
|
failed_when: false
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Remove immutable flag from OpenClaw gateway JSON config when present
|
|
ansible.builtin.command:
|
|
cmd: chattr -i "{{ gateway_openclaw_config_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_config_attrs.stdout | default(''))"
|
|
changed_when: true
|
|
|
|
- name: Deploy OpenClaw gateway JSON config
|
|
ansible.builtin.template:
|
|
src: openclaw.json.j2
|
|
dest: "{{ gateway_openclaw_config_path }}"
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0600"
|
|
diff: false
|
|
notify: Restart openclaw gateway
|
|
|
|
- name: Inspect OpenClaw package manifest
|
|
ansible.builtin.stat:
|
|
path: "{{ gateway_openclaw_install_dir }}/package.json"
|
|
register: gateway_openclaw_package_manifest
|
|
|
|
- name: Ensure OpenClaw package install directory is owned by service user
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_install_dir }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
recurse: true
|
|
when:
|
|
- gateway_openclaw_package_manifest.stat.exists | default(false)
|
|
|
|
- name: Repair OpenClaw package runtime dependencies as service user
|
|
ansible.builtin.command:
|
|
cmd: npm install --omit=dev --no-audit --no-fund --prefix "{{ gateway_openclaw_install_dir }}"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_package_deps
|
|
changed_when: >-
|
|
'added ' in (gateway_openclaw_package_deps.stdout | default('')) or
|
|
'removed ' in (gateway_openclaw_package_deps.stdout | default('')) or
|
|
'changed ' in (gateway_openclaw_package_deps.stdout | default(''))
|
|
when:
|
|
- gateway_openclaw_package_manifest.stat.exists | default(false)
|
|
- not ansible_check_mode
|
|
|
|
- name: Inspect OpenClaw extension package manifests
|
|
ansible.builtin.stat:
|
|
path: "{{ item }}/package.json"
|
|
register: gateway_openclaw_extension_manifests
|
|
loop: "{{ gateway_openclaw_extension_dependency_dirs }}"
|
|
|
|
- name: Repair OpenClaw extension runtime dependencies as service user
|
|
ansible.builtin.command:
|
|
cmd: npm install --omit=dev --no-audit --no-fund --prefix "{{ item.item }}"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_extension_deps
|
|
changed_when: >-
|
|
'added ' in (gateway_openclaw_extension_deps.stdout | default('')) or
|
|
'removed ' in (gateway_openclaw_extension_deps.stdout | default('')) or
|
|
'changed ' in (gateway_openclaw_extension_deps.stdout | default(''))
|
|
loop: "{{ gateway_openclaw_extension_manifests.results }}"
|
|
when:
|
|
- item.stat.exists | default(false)
|
|
- not ansible_check_mode
|
|
|
|
- name: Restore immutable flag on OpenClaw gateway JSON config
|
|
ansible.builtin.command:
|
|
cmd: chattr +i "{{ gateway_openclaw_config_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_config_attrs.stdout | default(''))"
|
|
- not ansible_check_mode
|
|
changed_when: true
|
|
|
|
- name: Inspect OpenClaw gateway binary
|
|
ansible.builtin.stat:
|
|
path: "{{ gateway_openclaw_binary_path }}"
|
|
follow: true
|
|
register: gateway_openclaw_binary
|
|
|
|
- name: Fail when OpenClaw gateway binary is missing or not executable
|
|
ansible.builtin.assert:
|
|
that:
|
|
- gateway_openclaw_binary.stat.exists | default(false)
|
|
- gateway_openclaw_binary.stat.executable | default(false)
|
|
fail_msg: "OpenClaw gateway binary is missing or not executable: {{ gateway_openclaw_binary_path }}"
|
|
|
|
- name: Check OpenClaw gateway version
|
|
ansible.builtin.command:
|
|
cmd: "{{ gateway_openclaw_binary_path }} --version"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_version
|
|
changed_when: false
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Assert OpenClaw gateway version is pinned
|
|
ansible.builtin.assert:
|
|
that:
|
|
- gateway_openclaw_version.stdout is search('OpenClaw ' ~ gateway_openclaw_required_version)
|
|
fail_msg: >-
|
|
OpenClaw gateway must run {{ gateway_openclaw_required_version }} after the
|
|
package upgrade. Actual version output: {{ gateway_openclaw_version.stdout | default('') }}
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Check OpenClaw plugin registry
|
|
ansible.builtin.command:
|
|
cmd: "{{ gateway_openclaw_binary_path }} plugins list --json"
|
|
environment:
|
|
HOME: "{{ gateway_openclaw_home }}"
|
|
PATH: "{{ gateway_openclaw_service_path }}"
|
|
OPENCLAW_NO_RESPAWN: "1"
|
|
NODE_COMPILE_CACHE: "{{ gateway_openclaw_compile_cache_dir }}"
|
|
become: true
|
|
become_user: "{{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_plugin_registry
|
|
changed_when: false
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Assert OpenClaw Codex plugin matches gateway version
|
|
ansible.builtin.assert:
|
|
that:
|
|
- >-
|
|
(
|
|
(gateway_openclaw_plugin_registry.stdout | from_json).plugins
|
|
| selectattr('id', 'equalto', 'codex')
|
|
| selectattr('version', 'equalto', gateway_openclaw_required_version)
|
|
| list
|
|
| length
|
|
) == 1
|
|
- >-
|
|
(
|
|
(gateway_openclaw_plugin_registry.stdout | from_json).plugins
|
|
| selectattr('id', 'equalto', 'acpx')
|
|
| list
|
|
| length
|
|
) == 0
|
|
- >-
|
|
(
|
|
(gateway_openclaw_plugin_registry.stdout | from_json).plugins
|
|
| selectattr('id', 'equalto', 'openclaw-multi-session-plugins')
|
|
| selectattr('version', 'equalto', gateway_openclaw_required_version)
|
|
| list
|
|
| length
|
|
) == 1
|
|
fail_msg: >-
|
|
OpenClaw must run @openclaw/codex {{ gateway_openclaw_required_version }}
|
|
plus openclaw-multi-session-plugins {{ gateway_openclaw_required_version }},
|
|
and must not keep stale global @openclaw/acpx.
|
|
when:
|
|
- not ansible_check_mode
|
|
|
|
- name: Ensure OpenClaw user systemd unit directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_user_service_unit_path | dirname }}"
|
|
state: directory
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0755"
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Deploy OpenClaw user systemd unit
|
|
ansible.builtin.template:
|
|
src: openclaw-gateway.user.service.j2
|
|
dest: "{{ gateway_openclaw_user_service_unit_path }}"
|
|
owner: "{{ gateway_openclaw_service_user }}"
|
|
group: "{{ gateway_openclaw_service_group }}"
|
|
mode: "0644"
|
|
register: gateway_openclaw_user_service_unit
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Deploy OpenClaw user systemd shell environment
|
|
ansible.builtin.template:
|
|
src: openclaw-user-systemd.sh.j2
|
|
dest: "{{ gateway_openclaw_profile_script_path }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Enable OpenClaw service user linger
|
|
ansible.builtin.command:
|
|
cmd: "loginctl enable-linger {{ gateway_openclaw_service_user }}"
|
|
creates: "/var/lib/systemd/linger/{{ gateway_openclaw_service_user }}"
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Resolve OpenClaw service user uid
|
|
ansible.builtin.command:
|
|
cmd: "id -u {{ gateway_openclaw_service_user }}"
|
|
register: gateway_openclaw_resolved_service_uid
|
|
changed_when: false
|
|
check_mode: false
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Set OpenClaw effective service uid
|
|
ansible.builtin.set_fact:
|
|
gateway_openclaw_effective_service_uid: >-
|
|
{{
|
|
gateway_openclaw_service_uid
|
|
if (gateway_openclaw_service_uid | string | trim | length > 0)
|
|
else (gateway_openclaw_resolved_service_uid.stdout | default(''))
|
|
}}
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Ensure OpenClaw service user manager is running
|
|
ansible.builtin.systemd:
|
|
name: "user@{{ gateway_openclaw_effective_service_uid }}.service"
|
|
state: started
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Stop and disable stale root-managed OpenClaw gateway service
|
|
ansible.builtin.systemd:
|
|
name: "{{ gateway_openclaw_service_name }}"
|
|
enabled: false
|
|
state: stopped
|
|
failed_when: false
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Inspect stale OpenClaw gateway root systemd unit attributes
|
|
ansible.builtin.command:
|
|
cmd: lsattr "{{ gateway_openclaw_service_unit_path }}"
|
|
register: gateway_openclaw_unit_attrs
|
|
changed_when: false
|
|
failed_when: false
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Remove immutable flag from stale OpenClaw gateway root systemd unit when present
|
|
ansible.builtin.command:
|
|
cmd: chattr -i "{{ gateway_openclaw_service_unit_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_unit_attrs.stdout | default(''))"
|
|
changed_when: true
|
|
|
|
- name: Remove stale root-managed OpenClaw gateway systemd unit
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_service_unit_path }}"
|
|
state: absent
|
|
register: gateway_openclaw_removed_root_service_unit
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Reload root systemd after removing stale OpenClaw gateway unit
|
|
ansible.builtin.systemd:
|
|
daemon_reload: true
|
|
when:
|
|
- gateway_openclaw_removed_root_service_unit.changed | default(false)
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Reload OpenClaw user systemd manager
|
|
ansible.builtin.shell: |
|
|
set -eu
|
|
loginctl enable-linger {{ gateway_openclaw_service_user }} || true
|
|
systemctl start "user@{{ gateway_openclaw_effective_service_uid }}.service" || true
|
|
runuser -u {{ gateway_openclaw_service_user }} -- env \
|
|
HOME={{ gateway_openclaw_home | quote }} \
|
|
XDG_RUNTIME_DIR=/run/user/{{ gateway_openclaw_effective_service_uid }} \
|
|
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/{{ gateway_openclaw_effective_service_uid }}/bus \
|
|
systemctl --user daemon-reload
|
|
args:
|
|
executable: /bin/bash
|
|
become: true
|
|
changed_when: false
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Ensure OpenClaw user gateway service is enabled and running
|
|
ansible.builtin.shell: |
|
|
set -eu
|
|
loginctl enable-linger {{ gateway_openclaw_service_user }} || true
|
|
systemctl start "user@{{ gateway_openclaw_effective_service_uid }}.service" || true
|
|
runuser -u {{ gateway_openclaw_service_user }} -- env \
|
|
HOME={{ gateway_openclaw_home | quote }} \
|
|
XDG_RUNTIME_DIR=/run/user/{{ gateway_openclaw_effective_service_uid }} \
|
|
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/{{ gateway_openclaw_effective_service_uid }}/bus \
|
|
systemctl --user enable {{ '--now' if not (gateway_openclaw_user_service_unit.changed | default(false)) else '' }} {{ gateway_openclaw_service_name }}.service
|
|
args:
|
|
executable: /bin/bash
|
|
become: true
|
|
register: gateway_openclaw_user_service_enable
|
|
changed_when: >-
|
|
'Created symlink' in (gateway_openclaw_user_service_enable.stdout | default('')) or
|
|
'Created symlink' in (gateway_openclaw_user_service_enable.stderr | default(''))
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Restart OpenClaw user gateway service after unit changes
|
|
ansible.builtin.shell: |
|
|
set -eu
|
|
loginctl enable-linger {{ gateway_openclaw_service_user }} || true
|
|
systemctl start "user@{{ gateway_openclaw_effective_service_uid }}.service" || true
|
|
runuser -u {{ gateway_openclaw_service_user }} -- env \
|
|
HOME={{ gateway_openclaw_home | quote }} \
|
|
XDG_RUNTIME_DIR=/run/user/{{ gateway_openclaw_effective_service_uid }} \
|
|
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/{{ gateway_openclaw_effective_service_uid }}/bus \
|
|
systemctl --user restart {{ gateway_openclaw_service_name }}.service
|
|
args:
|
|
executable: /bin/bash
|
|
become: true
|
|
when:
|
|
- gateway_openclaw_user_service_unit.changed | default(false)
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|
|
|
|
- name: Import macOS specific service tasks
|
|
ansible.builtin.import_tasks: macos.yml
|
|
when: ansible_os_family == 'Darwin'
|
|
|
|
- name: Ensure Caddy fragment directory exists
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_caddy_conf_dir }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
|
|
- name: Inspect Caddy main file attributes
|
|
ansible.builtin.command:
|
|
cmd: lsattr "{{ gateway_openclaw_caddyfile_path }}"
|
|
register: gateway_openclaw_caddyfile_attrs
|
|
changed_when: false
|
|
failed_when: false
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Remove immutable flag from Caddy main file when present
|
|
ansible.builtin.command:
|
|
cmd: chattr -i "{{ gateway_openclaw_caddyfile_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_caddyfile_attrs.stdout | default(''))"
|
|
changed_when: true
|
|
|
|
- name: Ensure Caddy imports managed fragments
|
|
ansible.builtin.lineinfile:
|
|
path: "{{ gateway_openclaw_caddyfile_path }}"
|
|
line: "import {{ gateway_openclaw_caddy_conf_dir }}/*.caddy"
|
|
insertafter: EOF
|
|
create: true
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
state: present
|
|
notify: Reload caddy
|
|
|
|
- name: Restore immutable flag on Caddy main file
|
|
ansible.builtin.command:
|
|
cmd: chattr +i "{{ gateway_openclaw_caddyfile_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_caddyfile_attrs.stdout | default(''))"
|
|
- not ansible_check_mode
|
|
changed_when: true
|
|
|
|
- name: Inspect OpenClaw Caddy fragment attributes
|
|
ansible.builtin.command:
|
|
cmd: lsattr "{{ gateway_openclaw_caddy_fragment_path }}"
|
|
register: gateway_openclaw_caddy_fragment_attrs
|
|
changed_when: false
|
|
failed_when: false
|
|
when: ansible_os_family != 'Darwin'
|
|
|
|
- name: Remove immutable flag from OpenClaw Caddy fragment when present
|
|
ansible.builtin.command:
|
|
cmd: chattr -i "{{ gateway_openclaw_caddy_fragment_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_caddy_fragment_attrs.stdout | default(''))"
|
|
changed_when: true
|
|
|
|
- name: Deploy OpenClaw public Caddy site
|
|
ansible.builtin.template:
|
|
src: openclaw.svc.plus.caddy.j2
|
|
dest: "{{ gateway_openclaw_caddy_fragment_path }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
when: gateway_openclaw_public_access | bool
|
|
notify: Reload caddy
|
|
|
|
- name: Remove OpenClaw public Caddy site when public access is disabled
|
|
ansible.builtin.file:
|
|
path: "{{ gateway_openclaw_caddy_fragment_path }}"
|
|
state: absent
|
|
when: not (gateway_openclaw_public_access | bool)
|
|
notify: Reload caddy
|
|
|
|
- name: Restore immutable flag on OpenClaw Caddy fragment
|
|
ansible.builtin.command:
|
|
cmd: chattr +i "{{ gateway_openclaw_caddy_fragment_path }}"
|
|
when:
|
|
- ansible_os_family != 'Darwin'
|
|
- "'i' in (gateway_openclaw_caddy_fragment_attrs.stdout | default(''))"
|
|
- not ansible_check_mode
|
|
changed_when: true
|
|
|
|
- name: Ensure Caddy is enabled and running
|
|
ansible.builtin.systemd:
|
|
name: caddy
|
|
enabled: true
|
|
state: started
|
|
when:
|
|
- not ansible_check_mode
|
|
- ansible_os_family != 'Darwin'
|