Files
nasmon/internal/web/templates/shares.html
T
a.gritsenkoandClaude Opus 5.5 b965d2c9db
build / build (push) Successful in 1m1s
SMB: optional legacy mode (SMB1 + NTLMv1) for old clients
Supermicro BMC virtual media ("CD-ROM image" over a Windows share) only
offers the SMB1 dialect "NT LM 0.12", which Samba rejects with
server min protocol = SMB2. Add an opt-in "Allow legacy clients" SMB
setting that renders server min protocol = NT1 and
ntlm auth = ntlmv1-permitted. Off by default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:59:53 +03:00

145 lines
10 KiB
HTML

{{define "content"}}
{{template "flash" .}}
{{with .Data}}
{{if .ApplyErr}}<div class="flash crit">Configuration saved but not applied: {{.ApplyErr}}
<form method="post" action="/shares/apply" class="inline"><button type="submit" class="secondary">Apply again</button></form></div>{{end}}
<datalist id="mountpoints">{{range .Mountpoints}}<option value="{{.}}">{{end}}</datalist>
<section class="card" id="smb">
<h2>SMB (Windows / macOS network shares)
{{if not .Svc.SMBInstalled}}<span class="badge warn">not installed</span>
{{else if .Svc.SMBActive}}<span class="badge ok">running</span> <span class="muted small">{{.Svc.SMBSessions}} session(s)</span>
{{else}}<span class="badge">stopped</span>{{end}}
</h2>
{{if not .Svc.SMBInstalled}}<p class="warn-text">Samba is not installed — run <span class="mono">sudo apt install samba wsdd</span> on the NAS (install.sh does it). Shares can be defined now and are applied once Samba is there.</p>{{end}}
<form method="post" action="/shares/smb/settings" class="form-grid">
<label class="check"><input type="checkbox" name="enabled" value="1" {{if .C.SMB.Enabled}}checked{{end}}> SMB server enabled</label>
<label>Workgroup <input name="workgroup" value="{{.C.SMB.Workgroup}}"></label>
<label>Description <input name="server_string" value="{{.C.SMB.ServerString}}"></label>
<label class="check"><input type="checkbox" name="legacy" value="1" {{if .C.SMB.Legacy}}checked{{end}}> Allow legacy clients (SMB1 + NTLMv1) — IPMI/BMC virtual media, old devices; less secure</label>
<div class="field"><span class="field-name">&nbsp;</span><span><button type="submit" class="secondary">Save SMB settings</button></span></div>
</form>
<h3>Shares</h3>
<div class="tablewrap"><table>
<thead><tr><th>Name</th><th>Path</th><th>Access</th><th>Who</th><th>Connect as</th><th></th></tr></thead>
<tbody>
{{range .C.SMB.Shares}}
<tr>
<td><b>{{.Name}}</b>{{if .Comment}} <span class="muted small">{{.Comment}}</span>{{end}}{{if not .Browseable}} <span class="badge">hidden</span>{{end}}</td>
<td class="mono small">{{.Path}}</td>
<td>{{if .ReadOnly}}read-only{{else}}read/write{{end}}</td>
<td>{{if .Guest}}<span class="ok">guest</span> (no password){{else}}{{join .Users ", "}}{{end}}</td>
<td class="mono small">\\{{$.Data.Host}}\{{.Name}}</td>
<td class="small nowrap">
<a href="/shares?edit={{.Name}}#smbform">edit</a> ·
<form method="post" action="/shares/smb/delete" class="inline" onsubmit="return confirm('Delete share {{.Name}}? Files are not touched.')"><input type="hidden" name="name" value="{{.Name}}"><button type="submit" class="link">delete</button></form>
</td>
</tr>
{{else}}<tr><td colspan="6" class="muted">No SMB shares yet.</td></tr>{{end}}
</tbody>
</table></div>
<details class="newds" id="smbform" {{if or (not .Form.New) .Form.Path $.Error}}open{{end}}>
<summary>{{if .Form.New}}New share{{else}}Edit share {{.Form.Orig}}{{end}}</summary>
<form method="post" action="/shares/smb/save" class="ds-form">
<input type="hidden" name="orig" value="{{.Form.Orig}}">
<div class="form-grid">
<label>Share name <input name="name" required value="{{.Form.Name}}" placeholder="documents"></label>
<label>Path <input name="path" required list="mountpoints" value="{{.Form.Path}}" placeholder="/nas_pool_1_8_gb/documents or /mnt/usb"></label>
<label>Comment <input name="comment" value="{{.Form.Comment}}"></label>
<label class="check"><input type="checkbox" name="read_only" value="1" {{if .Form.ReadOnly}}checked{{end}}> Read-only</label>
<label class="check"><input type="checkbox" name="guest" value="1" {{if .Form.Guest}}checked{{end}}> Guest access (anyone on the LAN, no password)</label>
<label class="check"><input type="checkbox" name="browseable" value="1" {{if .Form.Browseable}}checked{{end}}> Visible in the share list</label>
<label class="check"><input type="checkbox" name="hide_sys" value="1" {{if .Form.HideSys}}checked{{end}}> Hide ._*, .DS_Store, Thumbs.db, desktop.ini</label>
<div class="wide field">
<span class="field-name">Allowed users (when guest access is off)</span>
<span class="checks">{{range .Users}}<label class="check-item"><input type="checkbox" name="users" value="{{.}}" {{if contains $.Data.Form.Users .}}checked{{end}}> {{.}}</label>{{else}}<span class="muted">no SMB users yet — add one below</span>{{end}}</span>
</div>
</div>
<p class="small muted">Path: any folder on the NAS — a ZFS dataset, a USB disk under /mnt or /media, /srv… System directories (/etc, /usr, /var…) are refused.</p>
<p class="small muted">Files are read and written as <b>{{.Owner}}</b> regardless of the SMB user, so containers and shares see the same ownership.</p>
<button type="submit">{{if .Form.New}}Create share{{else}}Save share{{end}}</button>
{{if not .Form.New}}<a href="/shares" class="small">cancel</a>{{end}}
</form>
</details>
<h3 id="users">SMB users</h3>
<div class="tablewrap"><table class="compact">
<tbody>
{{range .Users}}<tr><td class="mono">{{.}}</td><td class="small">
<form method="post" action="/shares/users/delete" class="inline" onsubmit="return confirm('Delete SMB user {{.}}?')"><input type="hidden" name="name" value="{{.}}"><button type="submit" class="link">delete</button></form>
</td></tr>{{else}}<tr><td class="muted">No SMB users. Guest shares work without users.</td></tr>{{end}}
</tbody>
</table></div>
<form method="post" action="/shares/users/save" class="form-grid">
<label>User <input name="name" required placeholder="alice" list="smbusers" autocomplete="off"></label>
<datalist id="smbusers">{{range .Users}}<option value="{{.}}">{{end}}</datalist>
<label>Password <input name="password" type="password" required minlength="4" autocomplete="new-password"></label>
<div class="field"><span class="field-name">&nbsp;</span><span><button type="submit" class="secondary">Add user / set password</button></span></div>
</form>
<p class="muted small">Windows: <span class="mono">\\{{.Host}}\share</span> in Explorer, or map a network drive. macOS: Finder → Go → Connect to Server → <span class="mono">smb://{{.Host}}/share</span>.
Note: Windows 10/11 Pro/Enterprise refuse <i>guest</i> shares by default (error 0x80070035 «network path not found») — use an SMB user with a password, or allow guest access on the PC (gpedit: Lanman Workstation → Enable insecure guest logons).
If a password share still gives 0x80070035, connect explicitly: <span class="mono">net use \\{{.Host}}\share /user:&lt;name&gt; *</span> (Windows keeps one login per server — run <span class="mono">net use * /delete</span> first).</p>
</section>
<section class="card" id="nfs">
<h2>NFS (Linux / other NAS)
{{if not .Svc.NFSInstalled}}<span class="badge warn">not installed</span>
{{else if .Svc.NFSActive}}<span class="badge ok">running</span>
{{else}}<span class="badge">stopped</span>{{end}}
</h2>
{{if not .Svc.NFSInstalled}}<p class="warn-text">NFS server is not installed — run <span class="mono">sudo apt install nfs-kernel-server</span> on the NAS (install.sh does it).</p>{{end}}
<form method="post" action="/shares/nfs/settings" class="form-grid">
<label class="check"><input type="checkbox" name="enabled" value="1" {{if .C.NFS.Enabled}}checked{{end}}> NFS server enabled</label>
<div class="field"><span class="field-name">&nbsp;</span><span><button type="submit" class="secondary">Save NFS settings</button></span></div>
</form>
<div class="tablewrap"><table>
<thead><tr><th>Path</th><th>Clients</th><th>Access</th><th>Squash</th><th>Mount</th><th></th></tr></thead>
<tbody>
{{range .C.NFS.Exports}}
<tr>
<td class="mono small">{{.Path}}</td>
<td class="mono small">{{join .Clients ", "}}</td>
<td>{{if .ReadOnly}}read-only{{else}}read/write{{end}}{{if .Async}} <span class="muted small">async</span>{{end}}</td>
<td>{{.Squash}}</td>
<td class="mono small">{{$.Data.Host}}:{{.Path}}</td>
<td class="small nowrap">
<a href="/shares?nedit={{.Path}}#nfsform">edit</a> ·
<form method="post" action="/shares/nfs/delete" class="inline" onsubmit="return confirm('Remove NFS export {{.Path}}?')"><input type="hidden" name="path" value="{{.Path}}"><button type="submit" class="link">delete</button></form>
</td>
</tr>
{{else}}<tr><td colspan="6" class="muted">No NFS exports yet.</td></tr>{{end}}
</tbody>
</table></div>
<details class="newds" id="nfsform" {{if or (not .NForm.New) .NForm.Path}}open{{end}}>
<summary>{{if .NForm.New}}New export{{else}}Edit export {{.NForm.Orig}}{{end}}</summary>
<form method="post" action="/shares/nfs/save" class="ds-form">
<input type="hidden" name="orig" value="{{.NForm.Orig}}">
<div class="form-grid">
<label>Path <input name="path" required list="mountpoints" value="{{.NForm.Path}}" placeholder="/nas_pool_1_8_gb/documents or /mnt/usb"></label>
<label>Clients <input name="clients" required value="{{.NForm.Clients}}" placeholder="192.168.101.0/24, pc.lan, *"></label>
<label>Squash
<select name="squash">
<option value="root" {{if eq .NForm.Squash "root"}}selected{{end}}>root → {{.Owner}} (root_squash)</option>
<option value="all" {{if eq .NForm.Squash "all"}}selected{{end}}>everyone → {{.Owner}} (all_squash)</option>
<option value="none" {{if eq .NForm.Squash "none"}}selected{{end}}>none (no_root_squash, trusted clients only)</option>
</select>
</label>
<label class="check"><input type="checkbox" name="read_only" value="1" {{if .NForm.ReadOnly}}checked{{end}}> Read-only</label>
<label class="check"><input type="checkbox" name="async" value="1" {{if .NForm.Async}}checked{{end}}> async writes (faster, less safe on power loss)</label>
</div>
<p class="small muted">Filesystems mounted below the path (nested datasets, disks) are exported too (crossmnt). Clients: host names, IPs, networks like 192.168.101.0/24, or * for everyone.</p>
<button type="submit">{{if .NForm.New}}Create export{{else}}Save export{{end}}</button>
{{if not .NForm.New}}<a href="/shares" class="small">cancel</a>{{end}}
</form>
</details>
<p class="muted small">Linux: <span class="mono">sudo mount -t nfs {{.Host}}:/nas_pool_1_8_gb/documents /mnt/nas</span>; list exports with <span class="mono">showmount -e {{.Host}}</span>.</p>
</section>
{{end}}
{{end}}