Create an empty /etc/micronas-webdav.passwd on first webdav config write
so Apache returns 401 instead of 500 before any user password is set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dashboard:
- Server IPs card showing all non-loopback IPv4 interfaces
- Restart buttons next to smbd/nfsd status dots (POST /api/service/<name>/restart)
- Active SMB connections table (smbstatus -b parsed in backend)
SMB edit modal:
- Read only toggle (writable vs read only in smb.conf)
- Recycle Bin toggle (vfs objects = recycle, files go to .recycle folder)
Docs: PLANNING.md phase 3.5, README recycle bin + read-only, CLAUDE.md JS overview
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Explains valid users, folder permissions, force user/group, guest ok,
no_root_squash, all_squash with use cases and recipes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SMB: force user, force group, guest ok fields + dropdowns for owner/group
NFS: no_root_squash and all_squash toggles exposed in edit modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- _list_groups(): reads /etc/group, returns groups with gid >= 1000
plus a small whitelist (root, staff, sambashare, www-data)
- GET/POST /api/groups: list and create groups (groupadd)
- DELETE /api/groups/<name>: delete group (groupdel)
- POST /api/groups/<name>/members: add user to group (gpasswd -a)
- DELETE /api/groups/<name>/members/<user>: remove user (gpasswd -d)
Frontend:
- Users tab now has a Groups section: table with GID, member badges
with × remove buttons, per-row "add member" select populated with
users not already in the group, delete group button
- loadUsers() caches result in _cachedUsers for groups table to use
- openEditModal is now async; fetches /api/users + /api/groups before
rendering so Owner and Group inputs have datalist autocomplete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- Import pwd/grp for uid/gid → name resolution
- _path_stat(path): returns current owner, group, octal mode via os.stat
- get_all_shares: attaches stat info to each share so the modal can
pre-fill current values
- POST /api/permissions: validates and applies chown/chmod to a share
path; returns updated stat on success
Frontend:
- Edit modal now has a Permissions section (Owner / Group / Mode)
pre-filled with current values, with a hint line showing common modes
- Valid Users label notes @groupname syntax for Samba group access
- submitEdit applies permissions after saving the share config if any
permission field is non-empty; shows specific error on failure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers one-time and permanent (fstab) mounts for both protocols,
credentials file for SMB, _netdev flag, multi-network NFS clients,
and useful commands (showmount, umount, mount -a).
Also remove stale "quotas" from the project description line.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The default nfs-kernel-server package ships /etc/exports with commented
example lines like '# /srv/homes hostname1(rw,...)'. The old parser
treated any comment containing a path as a disabled export, so these
examples showed up in the UI.
Fix: use a distinct '## ' prefix (double-hash + space) for exports that
MicroNAS disables. The parser now only recognises '## /path ...' as a
disabled export — any other '#' line is left as a plain comment.
_write_exports updated to use the same prefix when toggling off.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
app.py:
- Remove 'raw' field from export dict entries (only comment/blank
kinds need raw; export entries are always reconstructed from
path/rest/enabled when writing back)
- Remove extra blank line
shares.js:
- Remove unused pathJson variable in SMB row (was only needed for
the quota button, which was removed)
docker-compose.yml:
- Deleted entirely: was missing templates/ and static/ mounts so the
Flask app couldn't serve pages; SYS_ADMIN cap_add was only needed
for quotas; deployment is systemd, not Docker
README.md:
- Remove quota package from apt install command
- Remove quota setup section (feature removed)
- Remove docker-compose from Dev section
CLAUDE.md / PLANNING.md:
- Remove docker-compose.yml references and quotas.js from file tree
.gitignore:
- Remove redundant micronas.env entry (already covered by *.env)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Linux setquota/repquota require quota support on the underlying
filesystem. The target deployment is a Proxmox LXC on ZFS storage where
this is not available inside the container.
Removed: /api/quota endpoint, _quota_supported, _quota_usage,
_find_quota_fs, quotas.js, quota modal, dashboard quota table,
Quota button from share rows.
PLANNING.md updated: notes quota as out of scope with reason.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _quota_supported() checks df -T /srv; returns false + reason for ZFS,
tmpfs, overlay — surfaces as quota_supported/quota_reason in dashboard API
- Dashboard quota section shows the reason string instead of an empty table
- Quota button hidden from share rows when quota_supported is false
- Prevents setquota errors for ZFS-backed Proxmox LXC containers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- main.js: show live countdown "Updated HH:MM:SS — next in Xs" so the
30s auto-refresh is visually obvious instead of just a static timestamp
- app.py: rename _find_mountpoint → _find_quota_fs and fix the stale
call site that caused a NameError; function now returns mountpoint from
df, falling back to the path itself if df returns /
- README: add full quota setup section (fstab usrquota, quotacheck,
quotaon, verify with repquota); fix stale "127.0.0.1" bind note
(service already uses 0.0.0.0); update Auth section (sessions, not
Basic Auth)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: detect the actual filesystem mountpoint via 'df' instead of
hardcoding /srv/samba — setquota needs the mountpoint, not a subpath
- Backend: catch CalledProcessError and FileNotFoundError from setquota
and return the actual error message (e.g. quota not enabled, package
not installed) instead of crashing with 500
- Frontend: always send the share path in the quota API call so the
backend can find the right filesystem, even for SMB per-user quotas
- Frontend: read the actual error message from the response and show it
in the toast instead of just "N quota(s) failed"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- shares.js, users.js: JSON.stringify() inside onclick="..." attributes
produced unescaped " chars that broke HTML attribute parsing — all
dynamic onclick JSON now passed through esc() so the browser decodes
" back to " before executing the handler
- Replace browser confirm() dialogs with a styled Bootstrap modal
(#deleteModal) for share and user deletion — reusable across all tabs
- users.js: rename shadow variable 'confirm' → 'pwConfirm' to avoid
shadowing the now-removed confirm() call
- main.js: auto-refresh now reloads shares and users every 30 s,
not just the dashboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- SMB config parser/writer (_parse_smb_conf, _write_smb_conf) for
safe whole-file rewrites instead of append-only
- NFS exports parser/writer (_parse_exports, _write_exports) with
support for disabled (commented-out) exports
- DELETE/PATCH/toggle endpoints for SMB and NFS shares
- parse_smb() now returns enabled field (reads available = no)
- get_nfs_shares() uses the new parser and returns enabled field
- Replace HTTP Basic Auth with Flask session auth (secret key derived
from MICRONAS_PASS so sessions survive restarts)
- /login GET/POST, /logout routes
Frontend:
- Login page (templates/login.html) with same dark theme
- Sign out button in header
- Edit modal pre-filled with current share values
- Delete buttons wired up (with confirm dialog)
- Enable/Disable toggle per share (green/grey dot status indicator)
- Disabled shares shown at reduced opacity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Full UI redesign: GitHub-dark palette, custom CSS vars, better
contrast, card layout, cleaner tables and typography
- Dashboard auto-refresh every 30s (was 60s)
- Remove Quotas tab; each share row now has a Quota button that opens
a modal pre-filled with the share's valid users (SMB) or path (NFS)
- Replace all alert() with Bootstrap toast notifications
- Add Users tab: list system users (uid >= 1000) with SMB status,
create user (useradd + smbpasswd), delete user, change SMB password
- Backend: /api/users GET/POST, /api/users/<name> DELETE,
/api/users/<name>/password POST
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>