homelab/ansible/archive/documentation/playbooks/deploy-ansible-mcp-watchtower.md

138 lines
3.8 KiB
Markdown

# Deploy Ansible MCP server on Watchtower
## Purpose
Deploy a custom Ansible MCP server on Watchtower so AI tools can query inventory,
validate syntax, and run allowlisted playbooks through guarded tool calls.
## Scope
- Host: `watchtower` inventory group
- Playbook: `ansible/playbooks/ai/deploy_ansible_mcp_watchtower.yml`
- Runtime path: `/opt/ansible-mcp`
- Service name: `ansible-mcp`
- State and logs: `/var/lib/ansible-mcp`
## Features delivered
- MCP tools:
- `health`
- `list_inventory`
- `validate_syntax`
- `run_playbook`
- `get_job_status`
- `cancel_job`
- Path guardrails for playbook execution (allowlisted directories only)
- Optional explicit playbook allowlist for high-trust execution scopes
- Write-mode guardrails:
- global write toggle
- explicit confirm gate for write actions
- Auth guardrail:
- bearer token required when `ANSIBLE_MCP_API_TOKEN` is configured
- Input guardrails:
- max `extra_vars` payload size
- blocked `extra_vars` key list
- Background run tracking with per-run logs and status records
- JSONL audit records at `/var/lib/ansible-mcp/audit/events.jsonl`
## Prerequisites
1. Watchtower host is reachable from control node.
2. Python 3 is installed on Watchtower.
3. Inventory contains a valid `watchtower` group.
4. Ansible control node has access to this repository at `/home/chester/homelab`.
## Deploy
Run from `ansible/`:
```bash
cd /home/chester/homelab/ansible
export ANSIBLE_MCP_API_TOKEN='set-a-strong-token-before-deploy'
ansible-playbook -i inventory/hosts.ini playbooks/ai/deploy_ansible_mcp_watchtower.yml
```
Validate only:
```bash
cd /home/chester/homelab/ansible
ansible-playbook -i inventory/hosts.ini playbooks/ai/deploy_ansible_mcp_watchtower.yml --check
```
## Runtime configuration
The playbook sets these environment variables in the systemd unit:
- `ANSIBLE_MCP_REPO_ROOT=/home/chester/homelab/ansible`
- `ANSIBLE_MCP_INVENTORY=inventory/hosts.ini`
- `ANSIBLE_MCP_ALLOWED_PLAYBOOK_DIRS=playbooks`
- `ANSIBLE_MCP_ALLOWED_PLAYBOOKS=` (optional comma-separated explicit allowlist)
- `ANSIBLE_MCP_API_TOKEN=<token>` (required for HTTP transport in current playbook)
- `ANSIBLE_MCP_ALLOW_WRITE=true`
- `ANSIBLE_MCP_REQUIRE_CONFIRM=true`
- `ANSIBLE_MCP_DEFAULT_TIMEOUT=900`
- `ANSIBLE_MCP_MAX_TIMEOUT=3600`
- `ANSIBLE_MCP_MAX_EXTRA_VARS_BYTES=16384`
- `ANSIBLE_MCP_BLOCKED_EXTRA_VARS_KEYS=ansible_password,ansible_become_password,vault_password`
- `ANSIBLE_MCP_STATE_DIR=/var/lib/ansible-mcp`
- `ANSIBLE_MCP_TRANSPORT=streamable-http`
- `ANSIBLE_MCP_HOST=0.0.0.0`
- `ANSIBLE_MCP_PORT=8449`
## Verify
```bash
# Service state
sudo systemctl status ansible-mcp --no-pager
# Recent logs
sudo journalctl -u ansible-mcp -n 80 --no-pager
# Listening port
ss -ltnp | grep 8449
```
## Client connection example
For MCP clients that support HTTP transport:
```json
{
"mcpServers": {
"ansible-watchtower": {
"type": "http",
"url": "http://10.0.0.200:8449/mcp",
"headers": {
"Authorization": "Bearer ${env:ANSIBLE_MCP_API_TOKEN}"
}
}
}
}
```
If you terminate TLS upstream (recommended), expose this endpoint through your
existing ingress and use an HTTPS URL.
## Operational safety notes
- Keep `ANSIBLE_MCP_REQUIRE_CONFIRM=true` in write mode.
- Keep `ANSIBLE_MCP_API_TOKEN` set and rotate it regularly.
- Prefer explicit `ANSIBLE_MCP_ALLOWED_PLAYBOOKS` over broad directory allowlists.
- Restrict `ANSIBLE_MCP_ALLOWED_PLAYBOOK_DIRS` to known-safe playbook roots.
- Do not grant broad filesystem access to the service user.
- Treat background run logs in `/var/lib/ansible-mcp/logs` as audit artifacts.
## Rollback
```bash
sudo systemctl disable --now ansible-mcp
sudo rm -f /etc/systemd/system/ansible-mcp.service
sudo systemctl daemon-reload
```
Optional cleanup:
```bash
sudo rm -rf /opt/ansible-mcp /var/lib/ansible-mcp
```