procedures/ansible-playbook: Add NFS client role documentation
- 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
This commit is contained in:
174
procedures/ansible-playbook/README.md
Normal file
174
procedures/ansible-playbook/README.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Ansible Playbook — NFS Client Role (Iron Legion)
|
||||
|
||||
**Status:** Canonical | **Last updated:** 2026-06-04
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Standardized NFS client mounting for fleet Debian nodes. Mounts the TrueNAS `Repo` dataset (`/mnt/Ice/Repo`) to `/home/jarvis/repo` on all non-PVE, non-igor nodes.
|
||||
|
||||
---
|
||||
|
||||
## 2. Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `roles/nfs_client/tasks/main.yml` | Role tasks: install package, create dirs, create repogroup, mount NFS, fix permissions |
|
||||
| `inventory.yml` | Host definitions + `nfs_shares` variable |
|
||||
| `main.yml` | Playbook entry point: target selection |
|
||||
|
||||
---
|
||||
|
||||
## 3. Role Task Breakdown
|
||||
|
||||
### 3.1 Install nfs-common
|
||||
|
||||
```yaml
|
||||
- name: Install nfs-common
|
||||
ansible.builtin.apt:
|
||||
name: nfs-common
|
||||
state: present
|
||||
become: true
|
||||
when: ansible_os_family == "Debian"
|
||||
```
|
||||
|
||||
- Guard: only runs on Debian family (excludes ZimaOS/igor).
|
||||
|
||||
### 3.2 Create mount directory
|
||||
|
||||
```yaml
|
||||
- name: Ensure NFS mount directories exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
owner: jarvis
|
||||
group: jarvis
|
||||
become: true
|
||||
loop: "{{ nfs_shares }}"
|
||||
```
|
||||
|
||||
- Owner set to `jarvis` (NOT root) because user jarvis needs to access files after mount.
|
||||
|
||||
### 3.3 Create local `repogroup` (GID 568)
|
||||
|
||||
```yaml
|
||||
- name: Create local repogroup matching TrueNAS GID 568
|
||||
ansible.builtin.group:
|
||||
name: repogroup
|
||||
gid: 568
|
||||
state: present
|
||||
become: true
|
||||
```
|
||||
|
||||
- TrueNAS `apps` group uses GID 568. Creating a local group with the same GID maps jarvis's supplementary group across the NFSv4 identity boundary.
|
||||
|
||||
### 3.4 Add jarvis to repogroup
|
||||
|
||||
```yaml
|
||||
- name: Add jarvis to repogroup
|
||||
ansible.builtin.user:
|
||||
name: jarvis
|
||||
groups:
|
||||
- repogroup
|
||||
append: true
|
||||
become: true
|
||||
```
|
||||
|
||||
- After relogin (or `sg repogroup`), jarvis inherits group 568 write access.
|
||||
|
||||
### 3.5 Mount NFS (root required)
|
||||
|
||||
```yaml
|
||||
- name: Mount an NFS volume (root, because kernel mount)
|
||||
ansible.posix.mount:
|
||||
src: "{{ item.src }}"
|
||||
path: "{{ item.path }}"
|
||||
opts: "vers=4.2,proto=tcp,_netdev"
|
||||
state: mounted
|
||||
fstype: nfs
|
||||
become: true
|
||||
loop: "{{ nfs_shares }}"
|
||||
```
|
||||
|
||||
- Kernel mount requires root. `vers=4.2` required because TrueNAS SCALE 25.10.2 exports NFSv4.2 only; `defaults` fails silently.
|
||||
|
||||
### 3.6 Fix mount permissions
|
||||
|
||||
```yaml
|
||||
- name: Set mount permissions so jarvis (repogroup member) can write
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
mode: '0770'
|
||||
owner: root
|
||||
group: repogroup
|
||||
become: true
|
||||
loop: "{{ nfs_shares }}"
|
||||
```
|
||||
|
||||
- Mountpoint inherits remote permissions from TrueNAS, but the underlying local permission layer is `770` with group `repogroup`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Inventory Host Targeting
|
||||
|
||||
```yaml
|
||||
- name: Install NFS client
|
||||
hosts: fleet_nodes:!pve_hosts:!igor
|
||||
become: false
|
||||
roles:
|
||||
- nfs_client
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- PVE nodes (`mk33`, `mk34`, `mk39`) already have TrueNAS mounts via Proxmox integration. Don't double-mount.
|
||||
- `igor` is ZimaOS (non-Debian) and can't run `apt`.
|
||||
- Group exclusion syntax: `fleet_nodes:!pve_hosts:!igor`
|
||||
|
||||
---
|
||||
|
||||
## 5. TrueNAS Server-Side Companion
|
||||
|
||||
### Dataset: `/mnt/Ice/Repo`
|
||||
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| NFS version | 4.2 |
|
||||
| Maproot user | `pveuser` (UID 3003) |
|
||||
| Dataset owner | `root` (UID 0) |
|
||||
| Dataset group | `apps` (GID 568) |
|
||||
| Dataset permissions | `775` |
|
||||
|
||||
**Why 775 on TrueNAS:**
|
||||
- Without 775, jarvis (who is `other` in the NFS identity mapping) sees `drwxrwx---` and gets permission denied on listing.
|
||||
- With 775 (`drwxrwxr-x`), jarvis gains `read + execute` through the "other" bit.
|
||||
- Through the supplementary group path, jarvis gets `read + write` via group 568 after repogroup is applied.
|
||||
|
||||
---
|
||||
|
||||
## 6. Tested Behavior
|
||||
|
||||
| Action | Result |
|
||||
|--------|--------|
|
||||
| `sudo mount` | OK — root mounts, `mountpoint` returns true |
|
||||
| `ls -la /home/jarvis/repo` | OK — all TrueNAS files visible |
|
||||
| `touch` without relogin | FAIL — Permission denied (jarvis hasn't picked up new group in current shell) |
|
||||
| `sg repogroup -c "touch ..."` | OK — works immediately |
|
||||
| `touch` after relogin | OK — jarvis has repogroup in new shell |
|
||||
|
||||
---
|
||||
|
||||
## 7. Caveats
|
||||
|
||||
1. **NFSv4 identity mapping** requires supplemental groups. They are NOT transmitted across NFSv4 by default in Linux. The local `repogroup` creation is the workaround.
|
||||
2. **TrueNAS 775** is the non-Negotiable server-side change. Without it, jarvis gets no access.
|
||||
3. **Reboot or relogin** required on client after first `repogroup` addition. The group change doesn't apply retroactively to existing sessions.
|
||||
4. **Kernel mount must be root** — don't try user-space NFS (FUSE). It fails for non-root users without `fusermount3` and proper `/etc/fuse.conf`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Changelog
|
||||
|
||||
| Date | Change | Author |
|
||||
|------|--------|--------|
|
||||
| 2026-06-03 | Initial playbook + inventory validation | Artemis |
|
||||
| 2026-06-04 | Added repogroup + permission fix after TrueNAS 775 | Artemis |
|
||||
Reference in New Issue
Block a user