Files
MicroNAS/PLANNING.md
T
marcandClaude Sonnet 4.6 822e6b3b87 Phase 2.5: UI redesign, inline quotas, toasts, Users tab
- 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>
2026-06-19 22:14:10 +02:00

4.9 KiB

MicroNAS — Planning

A lightweight web GUI to manage file shares on a single home server — like a minimal NAS control panel for a Proxmox LXC/VM. Manages SMB shares, NFS exports, and quotas by editing the host config files and reloading the daemons.

Design principle: keep it small. Single box, home/LAN use only, no database, no auth framework, dependency-light. If a feature needs heavy machinery, it's out of scope.


Deployment decision

Run directly on the LXC/VM as a systemd service (Flask behind gunicorn). Not Docker.

Reason: this app's whole job is to manipulate host services (smbd, nfsd, /etc/exports, exportfs, setquota). Containerizing it means bind-mounting host config, running privileged, and fighting the kernel NFS server — all the downsides of running on the host with none of the isolation benefit. Docker is kept only as an optional dev/test sandbox.

Network: LAN-only. Never expose to the internet. Reach it via local network or Tailscale. Auth is a safety net, not an internet-facing defense.

Backups: Out of scope. Handled at the Proxmox layer (Proxmox Backup Server on a second client). This app does not implement backup.


Current state (baseline)

  • app.py — Flask API: list/create SMB & NFS shares, set quotas.
  • index.html — Bootstrap UI with SMB / NFS / Quotas tabs.
  • docker-compose.yml — test sandbox.

Known issues to fix

  • parse_smb() is called (app.py:13) but never defined → /api/shares 500s.
  • subprocess.run(cmd, shell=True) with f-string input (app.py:82) → command injection as root.
  • add_smb_share writes raw user input into smb.conf → config injection via newlines.
  • No authentication on any route.
  • Config is append-only (open(..., 'a')) → no working delete/edit; UI Delete buttons are wired to nothing.
  • No input validation on names or paths (path traversal, share of /).

Roadmap

Phase 1 — Correctness & safety (must-have)

  • Implement parse_smb() so /api/shares works.
  • Remove all shell=True; use argument-list subprocess calls.
  • Validate input:
    • share/user names: ^[A-Za-z0-9_-]+$
    • paths must resolve under /srv
    • reject anything else with a clear error.
  • Simple login: HTTP Basic Auth, single user + password from env var, protecting all routes.
  • systemd unit + gunicorn, plus README run instructions.

Phase 2 — Dashboard & health (the main goal)

A landing page that shows the state of the server at a glance:

  • Daemon status — is smbd running? is nfsd running? (green/red).
  • Disk usage — free / used / total for /srv.
  • All shares in one view — every SMB share and NFS export, their paths, and who can access them.
  • Per-share data used — size on disk of each share's path (du).
  • Quota usage — for each user with a quota: used vs limit, with a progress bar.
  • Auto-refresh every 30 seconds + manual refresh button.

Phase 2.5 — UX improvements (next up)

Improvements identified after first real test:

  • UI redesign — GitHub-dark palette, better contrast, card layout, breathing room. Custom CSS variables, no extra dependencies.
  • Inline quota management — removed dedicated Quotas tab. Each SMB share and NFS export row has a "Quota" button that opens a modal. For SMB: lists valid_users with individual GB inputs. For NFS: manual user + GB. Submits one API call per user in parallel.
  • Toast notifications — replaced all alert() with Bootstrap toasts.
  • Auto-refresh every 30 s (was 60 s).
  • User management tab — create, delete, and change the SMB password of NAS users without touching the command line: - List all system users (uid ≥ 1000), show whether they have a Samba account. - Create user: useradd -M -s /usr/sbin/nologin + smbpasswd -a. - Delete user: smbpasswd -x + userdel. - Change SMB password: smbpasswd -s via modal. - Backend: /api/users GET/POST, /api/users/<name> DELETE, /api/users/<name>/password POST.

Phase 3 — Full management (complete the CRUD)

  • Working delete for SMB & NFS (parse config into blocks, rewrite the whole file — not append-only).
  • Edit existing shares (path, valid users).
  • Enable/disable a share without deleting it.

Phase 4 — Nice-to-have

  • WebDAV support. Preferred approach: don't build it in Flask — have the app drop an Apache/nginx WebDAV config snippet, same pattern as SMB/NFS, so it reuses the existing architecture.
  • Simple in-browser file browser for /srv.

Out of scope (intentionally)

  • Backups (Proxmox Backup Server handles this).
  • Multi-user accounts / roles (single admin login is enough).
  • Database (config files are the source of truth).
  • Internet exposure / TLS termination (LAN + Tailscale only).
  • Clustering / multi-host management.