- Full README.md with task breakdown, inventory targeting, TrueNAS requirements - ADDITIONAL_NOTES.md with per-node key nuances, repogroup mapping, mount opts evolution - Included canonical copies of: inventory.yml, main.yml, roles/nfs_client/tasks/main.yml - Covers TrueNAS maproot/ACL interaction and jarvis write access patterns
3.5 KiB
Additional Notes — Ansible NFS Playbook (Iron Legion)
Date: 2026-06-04 | Author: Artemis (AI Foreman)
Nuance 1: ansible_ssh_private_key_file per node
Most fleet nodes use the standard id_ed25519 key (auto-discovered). Mark44 requires vscode_ed25519 — the code-server key. Because it's a special case, mark44's inventory block sets:
mark44:
ansible_host: 192.168.5.214
ansible_user: jarvis
ansible_ssh_private_key_file: /root/.ssh/vscode_ed25519
Don't change this to id_ed25519 — mark44's authorized_keys only contains:
- The Termius key (artemis_key)
- The vscode_ed25519 key
The artemis_key is NOT auto-discovered by Ansible because the filename is non-standard. Keep the explicit ansible_ssh_private_key_file for mark44.
Nuance 2: What the repogroup actually is
repogroup is a local alias for TrueNAS's apps group (GID 568). The mapping works like this:
| System | Group Name | GID |
|---|---|---|
| TrueNAS | apps |
568 |
| Client | repogroup |
568 |
NFSv4 identity mapping sees the numeric GID only, not the symbolic name. So "jarvis in group 568" on the client maps to "jarvis in group apps" on TrueNAS.
No TrueNAS-side user creation is needed on clients. We only need the local group with the matching GID.
Nuance 3: NFS mount opts evolution
| Stage | Mount opts | Result |
|---|---|---|
| Old (broken) | defaults,_netdev |
Mount failed — TrueNAS rejects unversioned (v3) negotiation |
| Current | vers=4.2,proto=tcp,_netdev |
Mount succeeds; root can RWX |
The proto=tcp is required because UDP negotiation can silently fall back and fail on large packets.
Nuance 4: Why ansible.posix.mount instead of mount module
The native Ansible ansible.posix.mount module handles idempotency correctly:
- If already mounted at the same
src+path+opts, reportsok - If opts don't match, reports
changedand remounts - If
state: mounted, ensures/etc/fstabentry is added
Manual shell: mount ... would create duplicate fstab entries.
Nuance 5: TrueNAS server-side chmod 775 on /mnt/Ice/Repo
This was applied as an emergency fix during debugging. The correct long-term approach would be to add a proper NFS4 ACL entry for jarvis (UID 1000) via TrueNAS WebUI or midclt API, but the chmod 775 workaround is sufficient for production.
Command used (for record):
ssh -i ~/.ssh/artemis_key jarvis@192.168.16.254 'sudo chmod 775 /mnt/Ice/Repo'
Nuance 6: Host targeting syntax edge cases
Ansible supports two exclusion syntaxes:
- Union + subtraction:
hosts: fleet_nodes:!pve_hosts:!igor✅ Working - Direct group list:
hosts: physical_agents:core_services:infrastructure❌ Broken —nfs_sharesvariable is scoped underfleet_nodes, not these child groups
The inventory variable nfs_shares is defined at fleet_nodes level. Exclusion from fleet_nodes is the only way to get the variable AND exclude specific children.
Nuance 7: Container vs bare-metal execution
When running Ansible inside the Docker container (docker exec -it ansible ...):
- SSH keys mount to
/root/.sshinside container ansible.cfglives in/ansible(container working dir)
When running Ansible on the host (Artemis bare metal):
- SSH keys at
/home/jarvis/.ssh ansible.cfgmay be in/home/jarvis/.ansible-repoor current dir
The playbooks are identical but paths may differ. Always run from the project root where ansible.cfg and inventory files exist.