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

15 KiB

description
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:

# 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

# 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:
    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:

# <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:

---
- 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:

# <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:

# 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

curl -sL "https://api.github.com/repos/davestephens/ansible-nas/contents/roles" | grep '"name"' | cut -d'"' -f4 | sort

Fetch Role Files

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

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

  • 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