- Add service management prompts (review, standardize, troubleshoot, integration) - Add Docker Swarm migration and tutoring workflows (swarm-migration, swarm-tutor) - Add SSO onboarding guide for Authentik integration (sso-onboarding) - Add session lifecycle prompts (start, end, status) for context continuity - Add node bootstrap scripts for Debian Trixie (day0bootstrap.sh) and Ubuntu/Debian (pi_init.sh) These prompts implement gated, step-by-step workflows with explicit confirmation requirements to prevent accidental changes during service operations. Bootstrap scripts standardize IP configuration (10.0.0.200) and install Docker + Ansible on new nodes.
521 lines
15 KiB
Markdown
521 lines
15 KiB
Markdown
---
|
|
description: "Import and adapt roles from davestephens/ansible-nas into distributed homelab architecture with proper group placement, documentation, and testing."
|
|
---
|
|
|
|
# ansible-nas Role Importer
|
|
|
|
## Context (Pre-Loaded Analysis)
|
|
|
|
This prompt contains embedded knowledge from a prior deep analysis of the `davestephens/ansible-nas` repository. No re-scanning is required for basic operations.
|
|
|
|
### Repository Overview
|
|
|
|
- **Source:** https://github.com/davestephens/ansible-nas
|
|
- **Branch:** main
|
|
- **Role Count:** 90+ Docker application roles
|
|
- **Pattern:** Toggle-based (`<app>_enabled: true/false`)
|
|
- **Limitation:** Single-host design (`hosts: all`) — requires adaptation for distributed architecture
|
|
|
|
### Target Environment (Chester's Homelab)
|
|
|
|
| Group | Purpose | Example Hosts |
|
|
| :--- | :--- | :--- |
|
|
| `docker_hosts` | General compute, web apps | docker-01 (10.0.0.251) |
|
|
| `ai_grid` | GPU workloads, LLM inference | ai-lenovo (10.0.0.220) |
|
|
| `storage` | NAS, backup agents | synology, terramaster |
|
|
| `swarm_managers` | Docker Swarm cluster | pve-01 through pve-04 |
|
|
|
|
### Role Structure Pattern (ansible-nas)
|
|
|
|
All roles follow this pattern:
|
|
|
|
```yaml
|
|
# roles/<app>/tasks/main.yml
|
|
- name: Start <App>
|
|
block:
|
|
- name: Create <App> Directories
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
with_items:
|
|
- "{{ <app>_config_directory }}"
|
|
|
|
- name: Create <App> Docker Container
|
|
community.docker.docker_container:
|
|
name: "{{ <app>_container_name }}"
|
|
image: "{{ <app>_image_name }}:{{ <app>_image_version }}"
|
|
# ... container config
|
|
labels:
|
|
traefik.enable: "{{ <app>_available_externally | string }}"
|
|
when: <app>_enabled is true
|
|
|
|
- name: Stop <App>
|
|
block:
|
|
- name: Stop <App>
|
|
community.docker.docker_container:
|
|
name: "{{ <app>_container_name }}"
|
|
state: absent
|
|
when: <app>_enabled is false
|
|
```
|
|
|
|
### Default Variables Pattern
|
|
|
|
```yaml
|
|
# roles/<app>/defaults/main.yml
|
|
<app>_enabled: false
|
|
<app>_container_name: "<app>"
|
|
<app>_image_name: "vendor/<app>"
|
|
<app>_image_version: "latest" # We will pin this
|
|
<app>_config_directory: "{{ docker_home }}/<app>/config"
|
|
<app>_data_directory: "{{ docker_home }}/<app>/data"
|
|
<app>_port: "8080"
|
|
<app>_hostname: "<app>"
|
|
<app>_memory: "1g"
|
|
<app>_available_externally: false
|
|
<app>_user_id: "{{ ansible_nas_user_id }}"
|
|
<app>_group_id: "{{ ansible_nas_group_id }}"
|
|
```
|
|
|
|
---
|
|
|
|
## Available Applications (Categorized)
|
|
|
|
### Media & Streaming
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `plex` | Media server (proprietary) | Medium |
|
|
| `jellyfin` | Media server (FOSS) | Medium |
|
|
| `emby` | Media server | Medium |
|
|
| `airsonic` | Music streaming | Low |
|
|
| `navidrome` | Music streaming (modern) | Low |
|
|
| `booksonic` | Audiobook server | Low |
|
|
| `komga` | Comic/manga server | Low |
|
|
| `ubooquity` | Book/comic server | Low |
|
|
| `minidlna` | DLNA server | Low |
|
|
|
|
### Media Management (Arr Stack)
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `sonarr` | TV show management | Medium |
|
|
| `radarr` | Movie management | Medium |
|
|
| `lidarr` | Music management | Medium |
|
|
| `bazarr` | Subtitle management | Low |
|
|
| `prowlarr` | Indexer aggregator | Medium |
|
|
| `jackett` | Torrent indexer API | Medium |
|
|
| `overseerr` | Request management | Medium |
|
|
| `ombi` | Request management | Medium |
|
|
|
|
### Download Clients
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `transmission` | BitTorrent client | Low |
|
|
| `transmission-with-openvpn` | BitTorrent + VPN | High |
|
|
| `deluge` | BitTorrent client | Low |
|
|
| `sabnzbd` | Usenet downloader | Medium |
|
|
| `nzbget` | Usenet downloader | Medium |
|
|
| `pyload` | Download manager | Low |
|
|
| `youtubedlmaterial` | YouTube downloader | Low |
|
|
|
|
### Reverse Proxy & Networking
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `traefik` | Reverse proxy + SSL | High |
|
|
| `cloudflare_ddns` | Dynamic DNS (Cloudflare) | Low |
|
|
| `ddns_updater` | Multi-provider DDNS | Low |
|
|
| `route53_ddns` | Dynamic DNS (AWS) | Low |
|
|
| `guacamole` | Remote desktop gateway | High |
|
|
|
|
### Home Automation
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `homeassistant` | Home automation hub | High |
|
|
| `homebridge` | HomeKit bridge | Medium |
|
|
| `openhab` | Home automation | High |
|
|
| `esphome` | ESP device management | Medium |
|
|
| `mosquitto` | MQTT broker | Low |
|
|
|
|
### Monitoring & Observability
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `stats` | Grafana + Prometheus stack | High |
|
|
| `grafana` | Dashboards (via stats) | - |
|
|
| `prometheus` | Metrics (via stats) | - |
|
|
| `netdata` | System monitoring | Low |
|
|
| `glances` | System monitoring | Low |
|
|
| `speedtest-tracker` | Internet speed logging | Low |
|
|
| `healthchecks.io` | Uptime monitoring | Low |
|
|
|
|
### Logging
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `logging` | Loki + Promtail stack | High |
|
|
| `loki` | Log aggregation | Medium |
|
|
| `promtail` | Log shipping agent | Medium |
|
|
|
|
### Dashboards
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `homepage` | Modern dashboard | Low |
|
|
| `heimdall` | Application dashboard | Low |
|
|
| `dashy` | Customizable dashboard | Low |
|
|
| `organizr` | Tab-based dashboard | Medium |
|
|
|
|
### Development & CI/CD
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `gitea` | Lightweight Git server | Medium |
|
|
| `gitlab` | Full Git platform | High |
|
|
| `code-server` | VS Code in browser | Medium |
|
|
| `drone-ci` | CI/CD platform | High |
|
|
| `woodpecker-ci` | CI/CD (Drone fork) | High |
|
|
|
|
### Documents & Notes
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `nextcloud` | Cloud storage/office | High |
|
|
| `paperless_ng` | Document management | High |
|
|
| `dokuwiki` | Wiki | Low |
|
|
| `tiddlywiki` | Personal wiki | Low |
|
|
| `silverbullet` | Markdown notes | Low |
|
|
| `wallabag` | Read-it-later | Medium |
|
|
| `freshrss` | RSS reader | Low |
|
|
| `miniflux` | RSS reader (minimal) | Low |
|
|
|
|
### Backup & Sync
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `duplicati` | Backup to cloud | Medium |
|
|
| `duplicacy` | Deduplication backup | Medium |
|
|
| `syncthing` | File sync | Low |
|
|
| `timemachine` | Mac backup server | Medium |
|
|
|
|
### Security & Identity
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `bitwarden` | Password manager (Vaultwarden) | Medium |
|
|
|
|
### Utilities
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `portainer` | Docker management UI | Low |
|
|
| `watchtower` | Container auto-update | Low |
|
|
| `cloudcmd` | File manager (web) | Low |
|
|
| `krusader` | File manager (desktop) | Low |
|
|
| `wireshark` | Network analysis | Medium |
|
|
| `netbootxyz` | PXE boot server | High |
|
|
| `n8n` | Workflow automation | Medium |
|
|
| `minio` | S3-compatible storage | Medium |
|
|
|
|
### Communication
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `gotify` | Push notifications | Low |
|
|
| `thelounge` | IRC client | Low |
|
|
| `znc` | IRC bouncer | Medium |
|
|
| `mumble` | Voice chat | Medium |
|
|
|
|
### Gaming
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `minecraft-server` | Java edition server | Medium |
|
|
| `minecraft-bedrock-server` | Bedrock server | Medium |
|
|
| `valheim` | Valheim server | Medium |
|
|
| `romm` | ROM manager | Low |
|
|
|
|
### Other
|
|
| App | Description | Complexity |
|
|
| :--- | :--- | :---: |
|
|
| `piwigo` | Photo gallery | Medium |
|
|
| `calibre` | E-book management | Medium |
|
|
| `calibreweb` | E-book web UI | Low |
|
|
| `octoprint` | 3D printer control | Medium |
|
|
| `virtual_desktop` | Remote desktop | High |
|
|
| `mealie` | Recipe manager | Low |
|
|
| `firefly` | Personal finance | High |
|
|
| `apcupsd` | UPS monitoring | Low |
|
|
| `threadfin` | IPTV proxy | Medium |
|
|
| `tautulli` | Plex monitoring | Low |
|
|
|
|
### NOT in ansible-nas (Build Yourself)
|
|
| App | Description | Notes |
|
|
| :--- | :--- | :--- |
|
|
| `ollama` | LLM inference | Requires custom role |
|
|
| `localai` | OpenAI-compatible API | Requires custom role |
|
|
| `stable-diffusion` | Image generation | Requires GPU role |
|
|
| `whisper` | Speech-to-text | Requires custom role |
|
|
|
|
---
|
|
|
|
## Workflow
|
|
|
|
### Gate 0 — Select Application
|
|
|
|
Present the categorized list above. Ask user to select ONE application.
|
|
|
|
**Required confirmation phrase:**
|
|
User must reply exactly: `IMPORT: <app-name>`
|
|
|
|
Do not proceed until this is received.
|
|
|
|
### Step 1 — Fetch Current Role Definition
|
|
|
|
Fetch the role from ansible-nas:
|
|
- `https://raw.githubusercontent.com/davestephens/ansible-nas/main/roles/<app>/tasks/main.yml`
|
|
- `https://raw.githubusercontent.com/davestephens/ansible-nas/main/roles/<app>/defaults/main.yml`
|
|
|
|
Summarize:
|
|
- Required variables
|
|
- Docker image and version
|
|
- Ports exposed
|
|
- Volumes/bind mounts
|
|
- Dependencies (databases, other services)
|
|
- Traefik labels present
|
|
|
|
**Gate 1 — Confirm Role Analysis**
|
|
|
|
User must reply exactly: `CONFIRM ANALYSIS: <app-name>`
|
|
|
|
### Step 2 — Determine Target Group
|
|
|
|
Based on app category and user input, recommend placement:
|
|
|
|
| Category | Recommended Group |
|
|
| :--- | :--- |
|
|
| Media, Arr Stack, Dashboards | `docker_hosts` |
|
|
| Monitoring agents, Logging agents | All hosts |
|
|
| Backup | `storage` or `docker_hosts` |
|
|
| GPU workloads | `ai_grid` |
|
|
| Development tools | `docker_hosts` |
|
|
|
|
Ask user to confirm or override placement.
|
|
|
|
**Gate 2 — Confirm Placement**
|
|
|
|
User must reply exactly: `PLACE: <app-name> -> <group-name>`
|
|
|
|
### Step 3 — Adapt Role for Distributed Architecture
|
|
|
|
Transform the role:
|
|
|
|
1. **Pin image version** (replace `:latest`)
|
|
2. **Adapt paths** for Chester's environment:
|
|
- Config: `/opt/docker/<app>/config`
|
|
- Data: `/opt/docker/<app>/data`
|
|
3. **Add group conditional**:
|
|
```yaml
|
|
when:
|
|
- <app>_enabled | default(false)
|
|
- "'<target-group>' in group_names"
|
|
```
|
|
4. **Update Traefik labels** for Chester's domain
|
|
5. **Add resource limits** if missing
|
|
6. **Remove NAS-specific paths** (e.g., `/mnt/Volume3`)
|
|
|
|
Output the adapted role files:
|
|
- `roles/<app>/tasks/main.yml`
|
|
- `roles/<app>/defaults/main.yml`
|
|
- `roles/<app>/meta/main.yml` (dependencies)
|
|
|
|
**Gate 3 — Approve Adapted Role**
|
|
|
|
User must reply exactly: `APPROVE ROLE: <app-name>`
|
|
|
|
### Step 4 — Generate Group Variables
|
|
|
|
Create or update `group_vars/<target-group>.yml` with:
|
|
|
|
```yaml
|
|
# <app> Configuration
|
|
<app>_enabled: true
|
|
<app>_container_name: "<app>"
|
|
<app>_image_version: "<pinned-version>"
|
|
<app>_port: "<port>"
|
|
<app>_hostname: "<app>"
|
|
<app>_available_externally: false
|
|
```
|
|
|
|
**Gate 4 — Approve Variables**
|
|
|
|
User must reply exactly: `APPROVE VARS: <app-name>`
|
|
|
|
### Step 5 — Create Deployment Playbook
|
|
|
|
Generate `ansible/playbooks/deploy_<app>.yml`:
|
|
|
|
```yaml
|
|
---
|
|
- name: Deploy <App>
|
|
hosts: <target-group>
|
|
become: true
|
|
roles:
|
|
- role: <app>
|
|
tags:
|
|
- <app>
|
|
```
|
|
|
|
Or append to existing group playbook.
|
|
|
|
### Step 6 — Generate Documentation
|
|
|
|
Create `documentation/roles/<app>.md`:
|
|
|
|
```markdown
|
|
# <App> Role
|
|
|
|
## Overview
|
|
- **Source:** Adapted from ansible-nas
|
|
- **Target Group:** <target-group>
|
|
- **Image:** <image>:<version>
|
|
- **Port:** <port>
|
|
|
|
## Variables
|
|
| Variable | Default | Description |
|
|
| :--- | :--- | :--- |
|
|
|
|
## Usage
|
|
\`\`\`bash
|
|
ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_<app>.yml
|
|
\`\`\`
|
|
|
|
## Verification
|
|
\`\`\`bash
|
|
# Check container status
|
|
ansible <target-group> -m shell -a "docker ps --filter name=<app>"
|
|
|
|
# Check logs
|
|
ansible <target-group> -m shell -a "docker logs --tail=50 <app>"
|
|
\`\`\`
|
|
|
|
## Traefik Access
|
|
- Internal: `http://<host-ip>:<port>`
|
|
- External: `https://<app>.<domain>` (if enabled)
|
|
```
|
|
|
|
**Gate 5 — Approve Documentation**
|
|
|
|
User must reply exactly: `APPROVE DOCS: <app-name>`
|
|
|
|
### Step 7 — Deploy and Test
|
|
|
|
Provide copy/paste commands:
|
|
|
|
```bash
|
|
# Syntax check
|
|
ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_<app>.yml --syntax-check
|
|
|
|
# Dry run
|
|
ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_<app>.yml --check
|
|
|
|
# Deploy
|
|
ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_<app>.yml
|
|
|
|
# Verify
|
|
ansible <target-group> -m shell -a "docker ps --filter name=<app>"
|
|
ansible <target-group> -m shell -a "docker logs --tail=100 <app>"
|
|
|
|
# Health check (if applicable)
|
|
curl -s http://<host-ip>:<port>/health || curl -s http://<host-ip>:<port>/
|
|
```
|
|
|
|
**Gate 6 — Confirm Healthy**
|
|
|
|
User must reply exactly: `HEALTHY: <app-name>`
|
|
|
|
If NOT healthy, troubleshoot using:
|
|
1. Container logs
|
|
2. Port conflicts
|
|
3. Volume permissions
|
|
4. Network connectivity
|
|
|
|
### Step 8 — Commit
|
|
|
|
Generate conventional commit message:
|
|
|
|
```
|
|
feat(roles): add <app> role adapted from ansible-nas
|
|
|
|
- Source: davestephens/ansible-nas
|
|
- Target group: <target-group>
|
|
- Image pinned to <version>
|
|
- Traefik integration included
|
|
```
|
|
|
|
Remind user:
|
|
- Do not commit `.env` files
|
|
- Verify no secrets in group_vars
|
|
|
|
**Required phrase to finish:**
|
|
User must reply: `COMPLETE: <app-name>`
|
|
|
|
---
|
|
|
|
## Quick Reference Commands
|
|
|
|
### List All ansible-nas Roles
|
|
```bash
|
|
curl -sL "https://api.github.com/repos/davestephens/ansible-nas/contents/roles" | grep '"name"' | cut -d'"' -f4 | sort
|
|
```
|
|
|
|
### Fetch Role Files
|
|
```bash
|
|
APP="plex"
|
|
curl -sL "https://raw.githubusercontent.com/davestephens/ansible-nas/main/roles/${APP}/tasks/main.yml"
|
|
curl -sL "https://raw.githubusercontent.com/davestephens/ansible-nas/main/roles/${APP}/defaults/main.yml"
|
|
```
|
|
|
|
### Check for Updates
|
|
```bash
|
|
curl -sL "https://api.github.com/repos/davestephens/ansible-nas/commits?per_page=5" | grep '"message"' | head -5
|
|
```
|
|
|
|
---
|
|
|
|
## Non-Negotiables
|
|
|
|
1. **One app at a time.** Do not batch imports.
|
|
2. **Pin image versions.** Never deploy `:latest` in production.
|
|
3. **Test before production.** Always run `--check` first.
|
|
4. **Document everything.** Every imported role gets a doc file.
|
|
5. **Respect group boundaries.** Don't deploy media apps to AI nodes.
|
|
6. **Never expose secrets.** Redact any credentials found in roles.
|
|
|
|
---
|
|
|
|
## Adaptation Checklist
|
|
|
|
For each imported role, verify:
|
|
|
|
- [ ] Image version pinned
|
|
- [ ] Paths updated for Chester's structure (`/opt/docker/<app>/`)
|
|
- [ ] Group conditional added
|
|
- [ ] Traefik labels updated for Chester's domain
|
|
- [ ] Resource limits added (memory, CPU)
|
|
- [ ] PUID/PGID aligned with Chester's user
|
|
- [ ] Dependencies documented (databases, other services)
|
|
- [ ] Health check included
|
|
- [ ] Documentation generated
|
|
- [ ] Deployment tested
|
|
|
|
---
|
|
|
|
## Session Memory
|
|
|
|
When resuming this workflow, the AI should:
|
|
1. Check `roles/` directory for already-imported roles
|
|
2. Check `group_vars/` for enabled applications
|
|
3. Avoid re-importing existing roles unless upgrading
|
|
|
|
---
|
|
|
|
## Related Prompts
|
|
|
|
- `service-new.prompt.md` — For services NOT in ansible-nas
|
|
- `service-review.prompt.md` — For auditing imported roles
|
|
- `service-standardize.prompt.md` — For pinning image versions
|
|
|
|
## Related Documentation
|
|
|
|
- [Inventory](../../ansible/inventory/hosts.ini) — Host groups
|
|
- [Docker Management](../../ansible/playbooks/docker/manage_containers.yml) — Base Docker playbook
|
|
- [Onboarding](../../ansible/playbooks/onboarding/generic_host.yml) — New host setup
|