## Summary
- Use async with poll: 0 for alloy and loki restart handlers
- Fire-and-forget approach prevents ansible from hanging on graceful shutdown
## Test plan
- [x] Manually verified `brew services restart grafana-alloy` works
- [x] Run full ansible playbook and verify it completes without timeout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/12
## Summary
- Add ansible role for devpi-server as a transparent PyPI caching proxy
- LaunchAgent with KeepAlive runs via `mise x -- devpi-server`
- Listens on port 3141, data stored in `~/devpi`
- Health checks added to `indri-services-check` script
## Manual Setup Required (on indri, before provisioning)
1. Add to `~/.config/mise/config.toml`:
```toml
[tools]
"pipx:devpi-server" = "latest"
"pipx:devpi-web" = "latest"
"pipx:devpi-client" = "latest"
```
2. Run `mise install`
3. Initialize: `mise x -- devpi-init --serverdir ~/devpi`
## Post-Provisioning
- Set up Tailscale service `pypi` on port 443 → 3141
- Configure client pip.conf with index-url
## Test plan
- [x] Ansible syntax check passes
- [x] Dry-run: `mise run provision-indri -- --check --diff`
- [x] Apply: `mise run provision-indri`
- [x] Health check: `mise run indri-services-check`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/9
## Summary
- Adds a new Grafana dashboard for Node Exporter metrics on macOS hosts
- Uses macOS-native memory metrics (node_memory_total_bytes, node_memory_active_bytes, etc.) instead of Linux-specific ones
- Includes dropdown selectors for instance, disk, and network device filtering
## Details
The standard Node Exporter dashboards show "No Data" for memory panels on macOS because they query Linux-specific metrics like `node_memory_MemTotal_bytes`. macOS node_exporter exports different metrics:
| Linux | macOS |
|-------|-------|
| node_memory_MemTotal_bytes | node_memory_total_bytes |
| node_memory_MemFree_bytes | node_memory_free_bytes |
| node_memory_Buffers_bytes | (not available) |
| node_memory_Cached_bytes | (not available) |
macOS has unique memory categories: Wired, Active, Compressed, Inactive, Free.
## Test plan
- [x] Dashboard deployed to indri via ansible
- [x] All panels showing data for indri
- [x] Instance selector works to switch between hosts
- [x] Disk and network device filters work
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/8
## Summary
- Adds Upload/Download Ratio stat panel with color thresholds (red < 0.5, yellow < 1, green >= 1)
- Adds Downloaded (Period) stat panel showing bytes downloaded in selected time range
- Adds Uploaded (Period) stat panel showing bytes uploaded in selected time range
Uses PromQL `increase()` on existing counter metrics - no new metrics collection needed.
## Test plan
- [x] Deployed to indri via `mise run provision-indri`
- [x] Grafana restarted successfully
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: https://forge.tail8d86e.ts.net/eblume/blumeops/pulls/6
- Query torrent-get RPC to sum totalSize of all torrents
- Add transmission_torrents_size_bytes gauge metric
- Add "Total Torrent Size" timeseries panel to dashboard
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add node_exporter ansible role to enable textfile collector
- Add transmission_metrics role with script and LaunchAgent
- Collects metrics every 60s via transmission RPC
- Writes to /opt/homebrew/var/node_exporter/textfile/transmission.prom
- Update grafana role to provision dashboards from files
- Add transmission.json dashboard with:
- Status indicator, torrent counts
- Transfer speeds, cumulative stats
- Time series graphs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Configure grafana to use provisioned datasources instead of UI config
- Add prometheus datasource template managed by ansible
- Create minimal grafana.ini with custom provisioning path
- Move ansible_managed to group_vars (fixes deprecation warning)
- Add Remote Hosts and Git Workflow sections to CLAUDE.md
- Document feature branch workflow with tea CLI for PRs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Inventory with tailnet hosts (indri, gilbert, sifaka)
- Prometheus role: installs via homebrew, templates config from current indri setup
- Grafana role: installs via homebrew, starts service
- ansible.cfg and requirements.yml for community.general collection
- Updated CLAUDE.md with ansible dry-run instructions
Tested: ansible-playbook playbooks/indri.yml --check --diff (all ok)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>