{
  "schemaVersion": "1.0",
  "item": {
    "slug": "ansible-skill",
    "name": "Ansible",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/botond-rackhost/ansible-skill",
    "canonicalUrl": "https://clawhub.ai/botond-rackhost/ansible-skill",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/ansible-skill",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=ansible-skill",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "ansible.cfg",
      "inventory/group_vars/all.yml",
      "inventory/hosts.yml",
      "playbooks/openclaw-vps.yml",
      "playbooks/security.yml"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/ansible-skill"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/ansible-skill",
    "agentPageUrl": "https://openagent3.xyz/skills/ansible-skill/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ansible-skill/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ansible-skill/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Ansible Skill",
        "body": "Infrastructure as Code automation for server provisioning, configuration management, and orchestration."
      },
      {
        "title": "Prerequisites",
        "body": "# Install Ansible\npip install ansible\n\n# Or on macOS\nbrew install ansible\n\n# Verify\nansible --version"
      },
      {
        "title": "Run Your First Playbook",
        "body": "# Test connection\nansible all -i inventory/hosts.yml -m ping\n\n# Run playbook\nansible-playbook -i inventory/hosts.yml playbooks/site.yml\n\n# Dry run (check mode)\nansible-playbook -i inventory/hosts.yml playbooks/site.yml --check\n\n# With specific tags\nansible-playbook -i inventory/hosts.yml playbooks/site.yml --tags \"security,nodejs\""
      },
      {
        "title": "Directory Structure",
        "body": "skills/ansible/\n├── SKILL.md              # This file\n├── inventory/            # Host inventories\n│   ├── hosts.yml         # Main inventory\n│   └── group_vars/       # Group variables\n├── playbooks/            # Runnable playbooks\n│   ├── site.yml          # Master playbook\n│   ├── openclaw-vps.yml  # OpenClaw VPS setup\n│   └── security.yml      # Security hardening\n├── roles/                # Reusable roles\n│   ├── common/           # Base system setup\n│   ├── security/         # Hardening (SSH, fail2ban, UFW)\n│   ├── nodejs/           # Node.js installation\n│   └── openclaw/         # OpenClaw installation\n└── references/           # Documentation\n    ├── best-practices.md\n    ├── modules-cheatsheet.md\n    └── troubleshooting.md"
      },
      {
        "title": "Inventory",
        "body": "Define your hosts in inventory/hosts.yml:\n\nall:\n  children:\n    vps:\n      hosts:\n        eva:\n          ansible_host: 217.13.104.208\n          ansible_user: root\n          ansible_ssh_pass: \"{{ vault_eva_password }}\"\n        plane:\n          ansible_host: 217.13.104.99\n          ansible_user: asdbot\n          ansible_ssh_private_key_file: ~/.ssh/id_ed25519_plane\n    \n    openclaw:\n      hosts:\n        eva:"
      },
      {
        "title": "Playbooks",
        "body": "Entry points for automation:\n\n# playbooks/site.yml - Master playbook\n---\n- name: Configure all servers\n  hosts: all\n  become: yes\n  roles:\n    - common\n    - security\n\n- name: Setup OpenClaw servers\n  hosts: openclaw\n  become: yes\n  roles:\n    - nodejs\n    - openclaw"
      },
      {
        "title": "Roles",
        "body": "Reusable, modular configurations:\n\n# roles/common/tasks/main.yml\n---\n- name: Update apt cache\n  ansible.builtin.apt:\n    update_cache: yes\n    cache_valid_time: 3600\n  when: ansible_os_family == \"Debian\"\n\n- name: Install essential packages\n  ansible.builtin.apt:\n    name:\n      - curl\n      - wget\n      - git\n      - htop\n      - vim\n      - unzip\n    state: present"
      },
      {
        "title": "1. common",
        "body": "Base system configuration:\n\nSystem updates\nEssential packages\nTimezone configuration\nUser creation with SSH keys"
      },
      {
        "title": "2. security",
        "body": "Hardening following CIS benchmarks:\n\nSSH hardening (key-only, no root)\nfail2ban for brute-force protection\nUFW firewall configuration\nAutomatic security updates"
      },
      {
        "title": "3. nodejs",
        "body": "Node.js installation via NodeSource:\n\nConfigurable version (default: 22.x LTS)\nnpm global packages\npm2 process manager (optional)"
      },
      {
        "title": "4. openclaw",
        "body": "Complete OpenClaw setup:\n\nNode.js (via nodejs role)\nOpenClaw npm installation\nSystemd service\nConfiguration file setup"
      },
      {
        "title": "Pattern 1: New VPS Setup (OpenClaw)",
        "body": "# 1. Add host to inventory\ncat >> inventory/hosts.yml << 'EOF'\n        newserver:\n          ansible_host: 1.2.3.4\n          ansible_user: root\n          ansible_ssh_pass: \"initial_password\"\n          deploy_user: asdbot\n          deploy_ssh_pubkey: \"ssh-ed25519 AAAA... asdbot\"\nEOF\n\n# 2. Run OpenClaw playbook\nansible-playbook -i inventory/hosts.yml playbooks/openclaw-vps.yml \\\n  --limit newserver \\\n  --ask-vault-pass\n\n# 3. After initial setup, update inventory to use key auth\n# ansible_user: asdbot\n# ansible_ssh_private_key_file: ~/.ssh/id_ed25519"
      },
      {
        "title": "Pattern 2: Security Hardening Only",
        "body": "ansible-playbook -i inventory/hosts.yml playbooks/security.yml \\\n  --limit production \\\n  --tags \"ssh,firewall\""
      },
      {
        "title": "Pattern 3: Rolling Updates",
        "body": "# Update one server at a time\nansible-playbook -i inventory/hosts.yml playbooks/update.yml \\\n  --serial 1"
      },
      {
        "title": "Pattern 4: Ad-hoc Commands",
        "body": "# Check disk space on all servers\nansible all -i inventory/hosts.yml -m shell -a \"df -h\"\n\n# Restart service\nansible openclaw -i inventory/hosts.yml -m systemd -a \"name=openclaw state=restarted\"\n\n# Copy file\nansible all -i inventory/hosts.yml -m copy -a \"src=./file.txt dest=/tmp/\""
      },
      {
        "title": "Group Variables",
        "body": "# inventory/group_vars/all.yml\n---\ntimezone: Europe/Budapest\ndeploy_user: asdbot\nssh_port: 22\n\n# Security\nsecurity_ssh_password_auth: false\nsecurity_ssh_permit_root: false\nsecurity_fail2ban_enabled: true\nsecurity_ufw_enabled: true\nsecurity_ufw_allowed_ports:\n  - 22\n  - 80\n  - 443\n\n# Node.js\nnodejs_version: \"22.x\""
      },
      {
        "title": "Vault for Secrets",
        "body": "# Create encrypted vars file\nansible-vault create inventory/group_vars/all/vault.yml\n\n# Edit encrypted file\nansible-vault edit inventory/group_vars/all/vault.yml\n\n# Run with vault\nansible-playbook site.yml --ask-vault-pass\n\n# Or use vault password file\nansible-playbook site.yml --vault-password-file ~/.vault_pass\n\nVault file structure:\n\n# inventory/group_vars/all/vault.yml\n---\nvault_eva_password: \"y8UGHR1qH\"\nvault_deploy_ssh_key: |\n  -----BEGIN OPENSSH PRIVATE KEY-----\n  ...\n  -----END OPENSSH PRIVATE KEY-----"
      },
      {
        "title": "Common Modules",
        "body": "ModulePurposeExampleaptPackage management (Debian)apt: name=nginx state=presentyumPackage management (RHEL)yum: name=nginx state=presentcopyCopy filescopy: src=file dest=/path/templateTemplate files (Jinja2)template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conffileFile/directory managementfile: path=/dir state=directory mode=0755userUser managementuser: name=asdbot groups=sudo shell=/bin/bashauthorized_keySSH keysauthorized_key: user=asdbot key=\"{{ ssh_key }}\"systemdService managementsystemd: name=nginx state=started enabled=yesufwFirewall (Ubuntu)ufw: rule=allow port=22 proto=tcplineinfileEdit single linelineinfile: path=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin no'gitClone reposgit: repo=https://github.com/x/y.git dest=/opt/ynpmnpm packagesnpm: name=openclaw global=yescommandRun commandcommand: /opt/script.shshellRun shell commandshell: cat /etc/passwd | grep root"
      },
      {
        "title": "1. Always Name Tasks",
        "body": "# Good\n- name: Install nginx web server\n  apt:\n    name: nginx\n    state: present\n\n# Bad\n- apt: name=nginx"
      },
      {
        "title": "2. Use FQCN (Fully Qualified Collection Names)",
        "body": "# Good\n- ansible.builtin.apt:\n    name: nginx\n\n# Acceptable but less clear\n- apt:\n    name: nginx"
      },
      {
        "title": "3. Explicit State",
        "body": "# Good - explicit state\n- ansible.builtin.apt:\n    name: nginx\n    state: present\n\n# Bad - implicit state\n- ansible.builtin.apt:\n    name: nginx"
      },
      {
        "title": "4. Idempotency",
        "body": "Write tasks that can run multiple times safely:\n\n# Good - idempotent\n- name: Ensure config line exists\n  ansible.builtin.lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^PasswordAuthentication'\n    line: 'PasswordAuthentication no'\n\n# Bad - not idempotent\n- name: Add config line\n  ansible.builtin.shell: echo \"PasswordAuthentication no\" >> /etc/ssh/sshd_config"
      },
      {
        "title": "5. Use Handlers for Restarts",
        "body": "# tasks/main.yml\n- name: Update SSH config\n  ansible.builtin.template:\n    src: sshd_config.j2\n    dest: /etc/ssh/sshd_config\n  notify: Restart SSH\n\n# handlers/main.yml\n- name: Restart SSH\n  ansible.builtin.systemd:\n    name: sshd\n    state: restarted"
      },
      {
        "title": "6. Tags for Selective Runs",
        "body": "- name: Security tasks\n  ansible.builtin.include_tasks: security.yml\n  tags: [security, hardening]\n\n- name: App deployment\n  ansible.builtin.include_tasks: deploy.yml\n  tags: [deploy, app]"
      },
      {
        "title": "Connection Issues",
        "body": "# Test SSH connection manually\nssh -v user@host\n\n# Debug Ansible connection\nansible host -i inventory -m ping -vvv\n\n# Check inventory parsing\nansible-inventory -i inventory --list"
      },
      {
        "title": "Common Errors",
        "body": "\"Permission denied\"\n\nCheck SSH key permissions: chmod 600 ~/.ssh/id_*\nVerify user has sudo access\nAdd become: yes to playbook\n\n\"Host key verification failed\"\n\nAdd to ansible.cfg: host_key_checking = False\nOr add host key: ssh-keyscan -H host >> ~/.ssh/known_hosts\n\n\"Module not found\"\n\nUse FQCN: ansible.builtin.apt instead of apt\nInstall collection: ansible-galaxy collection install community.general"
      },
      {
        "title": "Debugging Playbooks",
        "body": "# Verbose output\nansible-playbook site.yml -v    # Basic\nansible-playbook site.yml -vv   # More\nansible-playbook site.yml -vvv  # Maximum\n\n# Step through tasks\nansible-playbook site.yml --step\n\n# Start at specific task\nansible-playbook site.yml --start-at-task=\"Install nginx\"\n\n# Check mode (dry run)\nansible-playbook site.yml --check --diff"
      },
      {
        "title": "From OpenClaw Agent",
        "body": "# Run playbook via exec tool\nexec command=\"ansible-playbook -i skills/ansible/inventory/hosts.yml skills/ansible/playbooks/openclaw-vps.yml --limit eva\"\n\n# Ad-hoc command\nexec command=\"ansible eva -i skills/ansible/inventory/hosts.yml -m shell -a 'systemctl status openclaw'\""
      },
      {
        "title": "Storing Credentials",
        "body": "Use OpenClaw's Vaultwarden integration:\n\n# Get password from vault cache\nPASSWORD=$(.secrets/get-secret.sh \"VPS - Eva\")\n\n# Use in ansible (not recommended - use ansible-vault instead)\nansible-playbook site.yml -e \"ansible_ssh_pass=$PASSWORD\"\n\nBetter: Store in Ansible Vault and use --ask-vault-pass."
      },
      {
        "title": "References",
        "body": "references/best-practices.md - Detailed best practices guide\nreferences/modules-cheatsheet.md - Common modules quick reference\nreferences/troubleshooting.md - Extended troubleshooting guide"
      },
      {
        "title": "External Resources",
        "body": "Ansible Documentation\nAnsible Galaxy - Community roles\ngeerlingguy roles - High quality roles\nAnsible for DevOps - Book by Jeff Geerling"
      }
    ],
    "body": "Ansible Skill\n\nInfrastructure as Code automation for server provisioning, configuration management, and orchestration.\n\nQuick Start\nPrerequisites\n# Install Ansible\npip install ansible\n\n# Or on macOS\nbrew install ansible\n\n# Verify\nansible --version\n\nRun Your First Playbook\n# Test connection\nansible all -i inventory/hosts.yml -m ping\n\n# Run playbook\nansible-playbook -i inventory/hosts.yml playbooks/site.yml\n\n# Dry run (check mode)\nansible-playbook -i inventory/hosts.yml playbooks/site.yml --check\n\n# With specific tags\nansible-playbook -i inventory/hosts.yml playbooks/site.yml --tags \"security,nodejs\"\n\nDirectory Structure\nskills/ansible/\n├── SKILL.md              # This file\n├── inventory/            # Host inventories\n│   ├── hosts.yml         # Main inventory\n│   └── group_vars/       # Group variables\n├── playbooks/            # Runnable playbooks\n│   ├── site.yml          # Master playbook\n│   ├── openclaw-vps.yml  # OpenClaw VPS setup\n│   └── security.yml      # Security hardening\n├── roles/                # Reusable roles\n│   ├── common/           # Base system setup\n│   ├── security/         # Hardening (SSH, fail2ban, UFW)\n│   ├── nodejs/           # Node.js installation\n│   └── openclaw/         # OpenClaw installation\n└── references/           # Documentation\n    ├── best-practices.md\n    ├── modules-cheatsheet.md\n    └── troubleshooting.md\n\nCore Concepts\nInventory\n\nDefine your hosts in inventory/hosts.yml:\n\nall:\n  children:\n    vps:\n      hosts:\n        eva:\n          ansible_host: 217.13.104.208\n          ansible_user: root\n          ansible_ssh_pass: \"{{ vault_eva_password }}\"\n        plane:\n          ansible_host: 217.13.104.99\n          ansible_user: asdbot\n          ansible_ssh_private_key_file: ~/.ssh/id_ed25519_plane\n    \n    openclaw:\n      hosts:\n        eva:\n\nPlaybooks\n\nEntry points for automation:\n\n# playbooks/site.yml - Master playbook\n---\n- name: Configure all servers\n  hosts: all\n  become: yes\n  roles:\n    - common\n    - security\n\n- name: Setup OpenClaw servers\n  hosts: openclaw\n  become: yes\n  roles:\n    - nodejs\n    - openclaw\n\nRoles\n\nReusable, modular configurations:\n\n# roles/common/tasks/main.yml\n---\n- name: Update apt cache\n  ansible.builtin.apt:\n    update_cache: yes\n    cache_valid_time: 3600\n  when: ansible_os_family == \"Debian\"\n\n- name: Install essential packages\n  ansible.builtin.apt:\n    name:\n      - curl\n      - wget\n      - git\n      - htop\n      - vim\n      - unzip\n    state: present\n\nIncluded Roles\n1. common\n\nBase system configuration:\n\nSystem updates\nEssential packages\nTimezone configuration\nUser creation with SSH keys\n2. security\n\nHardening following CIS benchmarks:\n\nSSH hardening (key-only, no root)\nfail2ban for brute-force protection\nUFW firewall configuration\nAutomatic security updates\n3. nodejs\n\nNode.js installation via NodeSource:\n\nConfigurable version (default: 22.x LTS)\nnpm global packages\npm2 process manager (optional)\n4. openclaw\n\nComplete OpenClaw setup:\n\nNode.js (via nodejs role)\nOpenClaw npm installation\nSystemd service\nConfiguration file setup\nUsage Patterns\nPattern 1: New VPS Setup (OpenClaw)\n# 1. Add host to inventory\ncat >> inventory/hosts.yml << 'EOF'\n        newserver:\n          ansible_host: 1.2.3.4\n          ansible_user: root\n          ansible_ssh_pass: \"initial_password\"\n          deploy_user: asdbot\n          deploy_ssh_pubkey: \"ssh-ed25519 AAAA... asdbot\"\nEOF\n\n# 2. Run OpenClaw playbook\nansible-playbook -i inventory/hosts.yml playbooks/openclaw-vps.yml \\\n  --limit newserver \\\n  --ask-vault-pass\n\n# 3. After initial setup, update inventory to use key auth\n# ansible_user: asdbot\n# ansible_ssh_private_key_file: ~/.ssh/id_ed25519\n\nPattern 2: Security Hardening Only\nansible-playbook -i inventory/hosts.yml playbooks/security.yml \\\n  --limit production \\\n  --tags \"ssh,firewall\"\n\nPattern 3: Rolling Updates\n# Update one server at a time\nansible-playbook -i inventory/hosts.yml playbooks/update.yml \\\n  --serial 1\n\nPattern 4: Ad-hoc Commands\n# Check disk space on all servers\nansible all -i inventory/hosts.yml -m shell -a \"df -h\"\n\n# Restart service\nansible openclaw -i inventory/hosts.yml -m systemd -a \"name=openclaw state=restarted\"\n\n# Copy file\nansible all -i inventory/hosts.yml -m copy -a \"src=./file.txt dest=/tmp/\"\n\nVariables & Secrets\nGroup Variables\n# inventory/group_vars/all.yml\n---\ntimezone: Europe/Budapest\ndeploy_user: asdbot\nssh_port: 22\n\n# Security\nsecurity_ssh_password_auth: false\nsecurity_ssh_permit_root: false\nsecurity_fail2ban_enabled: true\nsecurity_ufw_enabled: true\nsecurity_ufw_allowed_ports:\n  - 22\n  - 80\n  - 443\n\n# Node.js\nnodejs_version: \"22.x\"\n\nVault for Secrets\n# Create encrypted vars file\nansible-vault create inventory/group_vars/all/vault.yml\n\n# Edit encrypted file\nansible-vault edit inventory/group_vars/all/vault.yml\n\n# Run with vault\nansible-playbook site.yml --ask-vault-pass\n\n# Or use vault password file\nansible-playbook site.yml --vault-password-file ~/.vault_pass\n\n\nVault file structure:\n\n# inventory/group_vars/all/vault.yml\n---\nvault_eva_password: \"y8UGHR1qH\"\nvault_deploy_ssh_key: |\n  -----BEGIN OPENSSH PRIVATE KEY-----\n  ...\n  -----END OPENSSH PRIVATE KEY-----\n\nCommon Modules\nModule\tPurpose\tExample\napt\tPackage management (Debian)\tapt: name=nginx state=present\nyum\tPackage management (RHEL)\tyum: name=nginx state=present\ncopy\tCopy files\tcopy: src=file dest=/path/\ntemplate\tTemplate files (Jinja2)\ttemplate: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf\nfile\tFile/directory management\tfile: path=/dir state=directory mode=0755\nuser\tUser management\tuser: name=asdbot groups=sudo shell=/bin/bash\nauthorized_key\tSSH keys\tauthorized_key: user=asdbot key=\"{{ ssh_key }}\"\nsystemd\tService management\tsystemd: name=nginx state=started enabled=yes\nufw\tFirewall (Ubuntu)\tufw: rule=allow port=22 proto=tcp\nlineinfile\tEdit single line\tlineinfile: path=/etc/ssh/sshd_config regexp='^PermitRootLogin' line='PermitRootLogin no'\ngit\tClone repos\tgit: repo=https://github.com/x/y.git dest=/opt/y\nnpm\tnpm packages\tnpm: name=openclaw global=yes\ncommand\tRun command\tcommand: /opt/script.sh\nshell\tRun shell command\tshell: cat /etc/passwd | grep root\nBest Practices\n1. Always Name Tasks\n# Good\n- name: Install nginx web server\n  apt:\n    name: nginx\n    state: present\n\n# Bad\n- apt: name=nginx\n\n2. Use FQCN (Fully Qualified Collection Names)\n# Good\n- ansible.builtin.apt:\n    name: nginx\n\n# Acceptable but less clear\n- apt:\n    name: nginx\n\n3. Explicit State\n# Good - explicit state\n- ansible.builtin.apt:\n    name: nginx\n    state: present\n\n# Bad - implicit state\n- ansible.builtin.apt:\n    name: nginx\n\n4. Idempotency\n\nWrite tasks that can run multiple times safely:\n\n# Good - idempotent\n- name: Ensure config line exists\n  ansible.builtin.lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^PasswordAuthentication'\n    line: 'PasswordAuthentication no'\n\n# Bad - not idempotent\n- name: Add config line\n  ansible.builtin.shell: echo \"PasswordAuthentication no\" >> /etc/ssh/sshd_config\n\n5. Use Handlers for Restarts\n# tasks/main.yml\n- name: Update SSH config\n  ansible.builtin.template:\n    src: sshd_config.j2\n    dest: /etc/ssh/sshd_config\n  notify: Restart SSH\n\n# handlers/main.yml\n- name: Restart SSH\n  ansible.builtin.systemd:\n    name: sshd\n    state: restarted\n\n6. Tags for Selective Runs\n- name: Security tasks\n  ansible.builtin.include_tasks: security.yml\n  tags: [security, hardening]\n\n- name: App deployment\n  ansible.builtin.include_tasks: deploy.yml\n  tags: [deploy, app]\n\nTroubleshooting\nConnection Issues\n# Test SSH connection manually\nssh -v user@host\n\n# Debug Ansible connection\nansible host -i inventory -m ping -vvv\n\n# Check inventory parsing\nansible-inventory -i inventory --list\n\nCommon Errors\n\n\"Permission denied\"\n\nCheck SSH key permissions: chmod 600 ~/.ssh/id_*\nVerify user has sudo access\nAdd become: yes to playbook\n\n\"Host key verification failed\"\n\nAdd to ansible.cfg: host_key_checking = False\nOr add host key: ssh-keyscan -H host >> ~/.ssh/known_hosts\n\n\"Module not found\"\n\nUse FQCN: ansible.builtin.apt instead of apt\nInstall collection: ansible-galaxy collection install community.general\nDebugging Playbooks\n# Verbose output\nansible-playbook site.yml -v    # Basic\nansible-playbook site.yml -vv   # More\nansible-playbook site.yml -vvv  # Maximum\n\n# Step through tasks\nansible-playbook site.yml --step\n\n# Start at specific task\nansible-playbook site.yml --start-at-task=\"Install nginx\"\n\n# Check mode (dry run)\nansible-playbook site.yml --check --diff\n\nIntegration with OpenClaw\nFrom OpenClaw Agent\n# Run playbook via exec tool\nexec command=\"ansible-playbook -i skills/ansible/inventory/hosts.yml skills/ansible/playbooks/openclaw-vps.yml --limit eva\"\n\n# Ad-hoc command\nexec command=\"ansible eva -i skills/ansible/inventory/hosts.yml -m shell -a 'systemctl status openclaw'\"\n\nStoring Credentials\n\nUse OpenClaw's Vaultwarden integration:\n\n# Get password from vault cache\nPASSWORD=$(.secrets/get-secret.sh \"VPS - Eva\")\n\n# Use in ansible (not recommended - use ansible-vault instead)\nansible-playbook site.yml -e \"ansible_ssh_pass=$PASSWORD\"\n\n\nBetter: Store in Ansible Vault and use --ask-vault-pass.\n\nReferences\nreferences/best-practices.md - Detailed best practices guide\nreferences/modules-cheatsheet.md - Common modules quick reference\nreferences/troubleshooting.md - Extended troubleshooting guide\nExternal Resources\nAnsible Documentation\nAnsible Galaxy - Community roles\ngeerlingguy roles - High quality roles\nAnsible for DevOps - Book by Jeff Geerling"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/botond-rackhost/ansible-skill",
    "publisherUrl": "https://clawhub.ai/botond-rackhost/ansible-skill",
    "owner": "botond-rackhost",
    "version": "0.1.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/ansible-skill",
    "downloadUrl": "https://openagent3.xyz/downloads/ansible-skill",
    "agentUrl": "https://openagent3.xyz/skills/ansible-skill/agent",
    "manifestUrl": "https://openagent3.xyz/skills/ansible-skill/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/ansible-skill/agent.md"
  }
}