# Fileshare Web — 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` (and per-disk if simple). - [ ] **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 (e.g. "12 GB / 50 GB"). - [ ] Auto-refresh or a manual refresh button. ### 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. - [ ] 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`. - [ ] Toast notifications instead of `alert()`. --- ## 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.