app.py: - Move warnings import to top-level imports - Remove MICRONAS_SECRET env var (undocumented, unnecessary) - Inline secret key derivation cleanly CLAUDE.md: - Remove stale quotas mention - Add WebDAV, setup.html, favicon to file layout - Document /etc/micronas/ permissions requirements - Document <Location> vs <Directory> for WebDAV DAV On PLANNING.md: - Mark Phase 5 complete with all shipped items - Add v1 complete marker and future ideas section README.md: - Simplify dev/test section (remove complex hash snippet) - Fix double blank line Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
151 lines
7.1 KiB
Markdown
151 lines
7.1 KiB
Markdown
# 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.
|
|
|
|
---
|
|
|
|
## Project structure
|
|
|
|
```
|
|
MicroNAS/
|
|
├── app.py Flask backend (all API routes + business logic)
|
|
├── templates/
|
|
│ ├── index.html Main SPA shell (Jinja2, no inline JS/CSS)
|
|
│ └── login.html Login form
|
|
├── static/
|
|
│ ├── css/app.css Custom dark theme (GitHub-palette CSS vars)
|
|
│ └── js/
|
|
│ ├── utils.js esc(), showToast(), apiFetch()
|
|
│ ├── dashboard.js loadDashboard()
|
|
│ ├── shares.js SMB/NFS CRUD + edit/delete/toggle
|
|
│ ├── users.js User CRUD + password modal
|
|
│ └── main.js Init + auto-refresh countdown
|
|
├── micronas.service systemd unit
|
|
├── README.md
|
|
└── PLANNING.md
|
|
```
|
|
|
|
---
|
|
|
|
## Roadmap
|
|
|
|
### Phase 1 — Correctness & safety ✅
|
|
- [x] Implement `parse_smb()` so `/api/shares` works.
|
|
- [x] Remove all `shell=True`; use argument-list `subprocess` calls.
|
|
- [x] Validate input: names `^[A-Za-z0-9_-]+$`; paths must resolve under `/srv`.
|
|
- [x] Session-based login (custom `/login` page, Flask sessions, secret key
|
|
derived from `MICRONAS_PASS`).
|
|
- [x] `systemd` unit + `gunicorn` + README install guide.
|
|
|
|
### Phase 2 — Dashboard & health ✅
|
|
- [x] **Daemon status** — smbd / nfsd running? (green/red dot).
|
|
- [x] **Disk usage** — free / used / total for `/srv` with progress bar.
|
|
- [x] **All shares in one view** — SMB + NFS, paths, access, size on disk.
|
|
- [x] **Per-share data used** — `du -sb` per share path.
|
|
- [x] Auto-refresh every 30 s + manual refresh button.
|
|
|
|
### Phase 2.5 — UX improvements ✅
|
|
- [x] UI redesign — GitHub-dark palette, custom CSS vars, better contrast
|
|
and typography.
|
|
- [x] Toast notifications — replaced all `alert()`.
|
|
- [x] Frontend split into `templates/` + `static/css/` + `static/js/`.
|
|
- [x] User management tab — list users (uid ≥ 1000), create, delete,
|
|
change SMB password.
|
|
- [x] Login page — replaces browser Basic Auth dialog.
|
|
|
|
### Phase 3 — Full share management ✅
|
|
- [x] Working **delete** for SMB & NFS (parse config into sections, rewrite
|
|
whole file — not append-only).
|
|
- [x] **Edit** existing shares — name, path, valid users (SMB); clients,
|
|
ro/rw (NFS). Edit modal pre-filled with current values.
|
|
- [x] **Enable/disable** a share without deleting it — SMB uses
|
|
`available = no`; NFS comments out the export line.
|
|
- [x] Status indicator per share row (green/red dot, reduced opacity when
|
|
disabled).
|
|
|
|
### Phase 3.5 — Share & dashboard polish ✅
|
|
- [x] **Permission editor in edit modal** — owner, group, chmod mode per share
|
|
folder. Owner/Group are dropdowns from live system users/groups.
|
|
- [x] **Group management** — create/delete groups, add/remove members. Users tab.
|
|
- [x] **SMB extra settings** — force user, force group, guest ok, read only,
|
|
recycle bin (vfs objects = recycle, files go to .recycle inside share).
|
|
- [x] **NFS extra settings** — no_root_squash, all_squash toggles.
|
|
- [x] **Server IPs on dashboard** — shows all non-loopback IPv4 addresses.
|
|
- [x] **Service restart buttons** — restart smbd / nfsd from the dashboard.
|
|
- [x] **Active SMB connections** — live table on dashboard via smbstatus.
|
|
- [x] **Delete confirmation modal** — replaces browser confirm().
|
|
- [x] **Auto-refresh countdown** — 30 s timer with live seconds display.
|
|
|
|
### Phase 4 — WebDAV ✅
|
|
- [x] Apache `mod_dav` + `mod_dav_fs` managed by MicroNAS.
|
|
Config written to `/etc/apache2/conf-available/micronas-webdav.conf`
|
|
with BEGIN/END markers per share; `a2enconf` + `systemctl reload apache2`.
|
|
- [x] Shares served at `http://<server>/dav/<name>` (Apache on port 80).
|
|
- [x] Auth via htpasswd (`/etc/micronas-webdav.passwd`) — passwords synced
|
|
automatically when creating/changing user passwords in the Users tab.
|
|
- [x] Full CRUD: create, edit (name/path/users/permissions), delete.
|
|
- [x] Dashboard: apache2 status dot + restart button.
|
|
- [x] WebDAV badge in dashboard shares overview.
|
|
- [x] @groupname fix in SMB valid users (was incorrectly rejected by VALID_NAME).
|
|
|
|
### Phase 5 — Security & UX ✅
|
|
- [x] **PBKDF2 password hashing** — admin credentials stored hashed (SHA-256, 260k iterations, salt$hex) in `/etc/micronas/micronas.env`. Legacy plaintext still accepted for migration.
|
|
- [x] **First-login setup page** — `/setup` route shown on fresh install, no manual env editing needed.
|
|
- [x] **Admin credential change** — ⚙ Settings modal in topbar; requires current password, logs out after change.
|
|
- [x] **Config directory** — `/etc/micronas/` with correct ownership (`root:www-data`, mode 750) auto-created by code.
|
|
- [x] **WebDAV browser access** — `Options Indexes` + `<Location>` blocks for DAV On; directories browsable in browser.
|
|
- [x] **Favicon & logo** — SVG drive-bay icon, shown in browser tab and topbar.
|
|
- [x] **www-data in owner dropdown** — selectable as folder owner for WebDAV shares.
|
|
|
|
---
|
|
|
|
## v1 complete 🎉
|
|
|
|
All planned phases shipped. The app manages SMB, NFS, and WebDAV shares with
|
|
a dark-themed web UI, secure hashed credentials, auto-synced WebDAV passwords,
|
|
group management, dashboard with live status, and a favicon.
|
|
|
|
### Possible future additions
|
|
- Simple in-browser file browser for `/srv`.
|
|
- Auto-create share directory on add (with correct owner/permissions).
|
|
- HTTPS via Let's Encrypt / self-signed cert.
|
|
|
|
---
|
|
|
|
## 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.
|
|
- **Disk quotas** — removed. Linux `setquota`/`repquota` require quota
|
|
support on the filesystem. The target deployment uses a ZFS-backed
|
|
Proxmox LXC where this is unavailable inside the container. Per-dataset
|
|
limits can be set from the Proxmox host with `zfs set quota=`.
|