homelab/.github/prompts/import-nas-role.prompt.md
nathan 016d38d5ab feat(prompts): add Docker service lifecycle and session management workflows
- 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.
2026-04-12 16:30:53 -04:00

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