Files
zmb-webui/backend/README.md
T
Claude Code 92bed208e0 ZMB Webui: Complete Project – Rebrand & Initial Clean Commit
ARCHITECTURE
============
Backend: FastAPI + uvicorn (port 8000)
  - JWT authentication with PAM system users
  - ZFS CLI wrapper with caching (30-60s TTL)
  - WebSocket pool status broadcaster (30s interval)
  - Services: auth, zfs_runner, file_manager, shares, identities, system_info
  - Routers: pools, datasets, snapshots, shares, identities, navigator, system

Frontend: Next.js 15 + TypeScript (static export)
  - Incremental Static Regeneration (ISR) for weak hardware
  - Type-safe API client (lib/api.ts)
  - Dark mode + custom Tailwind theme
  - Pages: Dashboard, Login, Snapshots, Datasets, Shares, etc.

DEPLOYMENT
==========
Test Target: 192.168.1.179:8090 (Debian LXC)
Production: 10.66.120.3:9090 (Raspberry Pi 4GB ARM64)
Updater: Automated Gitea-based deployment (update-test.sh, update-pi.sh)

FEATURES COMPLETED
==================
Phase 3a: Dashboard Quick Stats (System, CPU, Memory, Storage)
  - Real-time stats with color-coded progress bars
  - Responsive grid layout (mobile: 1, tablet: 2, desktop: 4 columns)
  - ISR-optimized for fast loads on weak hardware

REBRANDING
==========
Renamed throughout:
  - Project: 'ZFS Manager' → 'ZMB Webui'
  - Services: 'zfs-manager' → 'zmb-webui'
  - Systemd units: zfs-manager-backend → zmb-webui-backend
  - Configuration files and documentation

Co-Authored-By: Patrick <patrick@perlbach24.de>
2026-04-22 00:43:05 +02:00

228 lines
6.1 KiB
Markdown

# ZMB Webui Backend API
FastAPI backend for ZFS pool, dataset, and snapshot management.
## Quick Start (Local Development)
### Prerequisites
- Python 3.11+
- ZFS tools installed (`zpool`, `zfs`)
### Setup
```bash
cd backend
# Create virtual environment
python3 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create default admin user (password: admin)
python3 -c "from services.auth import auth_service; auth_service.add_user('admin', 'admin')"
# Run development server
python3 main.py
```
Server runs on `http://localhost:8000`
## API Endpoints
### Authentication
```bash
# Login
curl -X POST http://localhost:8000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# Returns: {"access_token":"...", "token_type":"bearer"}
```
### Pools
```bash
# List pools (requires auth)
curl http://localhost:8000/api/pools \
-H "Authorization: Bearer YOUR_TOKEN"
# Get pool status
curl http://localhost:8000/api/pools/tank \
-H "Authorization: Bearer YOUR_TOKEN"
# Start scrub
curl -X POST http://localhost:8000/api/pools/tank/scrub \
-H "Authorization: Bearer YOUR_TOKEN"
```
### Datasets
```bash
# List datasets
curl http://localhost:8000/api/datasets \
-H "Authorization: Bearer YOUR_TOKEN"
# Create dataset
curl -X POST http://localhost:8000/api/datasets \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"tank/backup","properties":{"compression":"lz4"}}'
# Delete dataset
curl -X DELETE http://localhost:8000/api/datasets/tank/test \
-H "Authorization: Bearer YOUR_TOKEN"
```
### Snapshots
```bash
# List snapshots
curl http://localhost:8000/api/snapshots \
-H "Authorization: Bearer YOUR_TOKEN"
# Create snapshot
curl -X POST http://localhost:8000/api/snapshots \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"dataset":"tank/share"}'
# Delete snapshot
curl -X DELETE http://localhost:8000/api/snapshots/tank/share@2026-04-14-120000 \
-H "Authorization: Bearer YOUR_TOKEN"
# Rollback snapshot
curl -X POST http://localhost:8000/api/snapshots/rollback \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"snapshot":"tank/share@2026-04-14-120000"}'
```
### File Manager (Browse /tank/share)
```bash
# Browse directory
curl "http://localhost:8000/api/files/browse?path=/" \
-H "Authorization: Bearer YOUR_TOKEN"
# Get file info
curl "http://localhost:8000/api/files/info?path=/document.pdf" \
-H "Authorization: Bearer YOUR_TOKEN"
# Read text file (< 10MB)
curl "http://localhost:8000/api/files/read?path=/config.json&limit=1000" \
-H "Authorization: Bearer YOUR_TOKEN"
# Download file
curl "http://localhost:8000/api/files/download?path=/archive.tar.gz" \
-H "Authorization: Bearer YOUR_TOKEN" \
-O
# Upload file
curl -X POST "http://localhost:8000/api/files/upload?path=/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "file=@/local/path/file.txt"
# Create directory
curl -X POST http://localhost:8000/api/files/mkdir \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/new_folder"}'
# Create file
curl -X POST http://localhost:8000/api/files/create \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"path":"/notes.txt","content":"Hello World"}'
# Rename file
curl -X POST http://localhost:8000/api/files/rename \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"old_path":"/oldname.txt","new_name":"newname.txt"}'
# Delete file
curl -X DELETE "http://localhost:8000/api/files/delete?path=/file.txt" \
-H "Authorization: Bearer YOUR_TOKEN"
# Delete directory (recursive)
curl -X DELETE "http://localhost:8000/api/files/delete?path=/folder&recursive=true" \
-H "Authorization: Bearer YOUR_TOKEN"
# Get space usage
curl http://localhost:8000/api/files/space \
-H "Authorization: Bearer YOUR_TOKEN"
```
## Architecture
### Services
- **zfs_runner.py**: Subprocess wrapper for ZFS commands with caching
- **auth.py**: JWT token generation and verification
### Routers
- **auth.py**: Login endpoint
- **pools.py**: Pool list, status, scrub operations
- **datasets.py**: Dataset CRUD operations
- **snapshots.py**: Snapshot CRUD, rollback
### Models
- **pool.py**: Pool, PoolStatus, PoolHealth
- **dataset.py**: Dataset, DatasetType
- **snapshot.py**: Snapshot
- **auth.py**: User, Token, TokenData
## Caching Strategy
- Pool status: 30s TTL
- Snapshots: 60s TTL
- Datasets: 60s TTL
Cache is cleared on mutations (create/delete operations).
## Performance Notes
### For 4GB RAM Raspberry Pi:
- gunicorn: 2 workers
- Memory limit: 512M soft / 768M hard
- Connection timeout: 30s
- Max requests per worker: 500 (recycle to prevent memory leaks)
### Optimizations:
- ZFS queries limited to max depth 2
- Snapshots limited to 50 by default (can be increased with `?limit=N`)
- Subprocess timeout: 5s
- In-memory TTL cache (no Redis required)
## Production Deployment
1. Copy backend to `/opt/zmb-webui/backend`
2. Install systemd service: `sudo cp deploy/zmb-webui-backend.service /etc/systemd/system/`
3. Update users: `python3 -c "from services.auth import auth_service; auth_service.add_user('yourusername', 'strongpassword')"`
4. Start service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable zmb-webui-backend
sudo systemctl start zmb-webui-backend
```
## Troubleshooting
### ZFS commands not working
- Check: `zpool list` runs without errors
- Check: Running as root or with proper sudo permissions
- Check: ZFS kernel module is loaded: `lsmod | grep zfs`
### Memory usage growing
- Check: `ps aux | grep uvicorn` for VSZ/RSS
- Restart service: `systemctl restart zmb-webui-backend`
- Increase frequency of restarts in crontab if needed
### Slow responses
- Check: `zpool status` output (large pool = slow scrub)
- Clear cache: `curl -X POST /api/pools/clear-cache` (with auth)
- Consider increasing cache TTLs in `zfs_runner.py`
## Development Tips
- Use `curl` or Postman for API testing
- Check logs: `journalctl -u zmb-webui-backend -f`
- Interactive API docs: `http://localhost:8000/docs` (after running)