--- 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 (`_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//tasks/main.yml - name: Start block: - name: Create Directories ansible.builtin.file: path: "{{ item }}" state: directory with_items: - "{{ _config_directory }}" - name: Create Docker Container community.docker.docker_container: name: "{{ _container_name }}" image: "{{ _image_name }}:{{ _image_version }}" # ... container config labels: traefik.enable: "{{ _available_externally | string }}" when: _enabled is true - name: Stop block: - name: Stop community.docker.docker_container: name: "{{ _container_name }}" state: absent when: _enabled is false ``` ### Default Variables Pattern ```yaml # roles//defaults/main.yml _enabled: false _container_name: "" _image_name: "vendor/" _image_version: "latest" # We will pin this _config_directory: "{{ docker_home }}//config" _data_directory: "{{ docker_home }}//data" _port: "8080" _hostname: "" _memory: "1g" _available_externally: false _user_id: "{{ ansible_nas_user_id }}" _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: ` 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//tasks/main.yml` - `https://raw.githubusercontent.com/davestephens/ansible-nas/main/roles//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: ` ### 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: -> ` ### 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//config` - Data: `/opt/docker//data` 3. **Add group conditional**: ```yaml when: - _enabled | default(false) - "'' 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//tasks/main.yml` - `roles//defaults/main.yml` - `roles//meta/main.yml` (dependencies) **Gate 3 — Approve Adapted Role** User must reply exactly: `APPROVE ROLE: ` ### Step 4 — Generate Group Variables Create or update `group_vars/.yml` with: ```yaml # Configuration _enabled: true _container_name: "" _image_version: "" _port: "" _hostname: "" _available_externally: false ``` **Gate 4 — Approve Variables** User must reply exactly: `APPROVE VARS: ` ### Step 5 — Create Deployment Playbook Generate `ansible/playbooks/deploy_.yml`: ```yaml --- - name: Deploy hosts: become: true roles: - role: tags: - ``` Or append to existing group playbook. ### Step 6 — Generate Documentation Create `documentation/roles/.md`: ```markdown # Role ## Overview - **Source:** Adapted from ansible-nas - **Target Group:** - **Image:** : - **Port:** ## Variables | Variable | Default | Description | | :--- | :--- | :--- | ## Usage \`\`\`bash ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_.yml \`\`\` ## Verification \`\`\`bash # Check container status ansible -m shell -a "docker ps --filter name=" # Check logs ansible -m shell -a "docker logs --tail=50 " \`\`\` ## Traefik Access - Internal: `http://:` - External: `https://.` (if enabled) ``` **Gate 5 — Approve Documentation** User must reply exactly: `APPROVE DOCS: ` ### Step 7 — Deploy and Test Provide copy/paste commands: ```bash # Syntax check ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_.yml --syntax-check # Dry run ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_.yml --check # Deploy ansible-playbook -i inventory/hosts.ini ansible/playbooks/deploy_.yml # Verify ansible -m shell -a "docker ps --filter name=" ansible -m shell -a "docker logs --tail=100 " # Health check (if applicable) curl -s http://:/health || curl -s http://:/ ``` **Gate 6 — Confirm Healthy** User must reply exactly: `HEALTHY: ` 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 role adapted from ansible-nas - Source: davestephens/ansible-nas - Target group: - Image pinned to - Traefik integration included ``` Remind user: - Do not commit `.env` files - Verify no secrets in group_vars **Required phrase to finish:** User must reply: `COMPLETE: ` --- ## 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//`) - [ ] 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