Docs: backend/README.md neu geschrieben (PAM-Auth, aktuelle Endpunkte)
auth_service-Referenzen entfernt, Cookie-basierte Auth dokumentiert, Endpunkt-Tabellen für alle Router ergänzt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+71
-191
@@ -1,227 +1,107 @@
|
|||||||
# ZMB Webui Backend API
|
# ZMB Webui — Backend
|
||||||
|
|
||||||
FastAPI backend for ZFS pool, dataset, and snapshot management.
|
FastAPI-Backend für ZFS-, Samba- und NFS-Verwaltung. Läuft als root (PAM-Auth benötigt `/etc/shadow`).
|
||||||
|
|
||||||
## Quick Start (Local Development)
|
## Lokale Entwicklung
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
- Python 3.11+
|
|
||||||
- ZFS tools installed (`zpool`, `zfs`)
|
|
||||||
|
|
||||||
### Setup
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
|
|
||||||
# Create virtual environment
|
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
pip install -r requirements.txt
|
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
|
python3 main.py
|
||||||
|
# → http://localhost:8000
|
||||||
|
# → http://localhost:8000/docs (API-Docs)
|
||||||
```
|
```
|
||||||
|
|
||||||
Server runs on `http://localhost:8000`
|
Login mit jedem Linux-Systembenutzer der eine Login-Shell hat.
|
||||||
|
|
||||||
## API Endpoints
|
## API-Endpunkte
|
||||||
|
|
||||||
|
Auth-Cookie wird beim Login automatisch gesetzt (`httpOnly`). Für curl-Tests:
|
||||||
|
|
||||||
### Authentication
|
|
||||||
```bash
|
```bash
|
||||||
# Login
|
# Login — setzt Cookie
|
||||||
curl -X POST http://localhost:8000/api/auth/login \
|
curl -c cookies.txt -X POST http://localhost:8000/api/auth/login \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"username":"admin","password":"admin"}'
|
-d '{"username":"user","password":"pass"}'
|
||||||
|
|
||||||
# Returns: {"access_token":"...", "token_type":"bearer"}
|
# Alle weiteren Requests mit Cookie
|
||||||
|
curl -b cookies.txt http://localhost:8000/api/pools/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Pools
|
### Pools
|
||||||
```bash
|
| Methode | Pfad | Beschreibung |
|
||||||
# List pools (requires auth)
|
|---------|------|--------------|
|
||||||
curl http://localhost:8000/api/pools \
|
| GET | `/api/pools/` | Alle Pools auflisten |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
| GET | `/api/pools/{name}` | Pool-Status |
|
||||||
|
| POST | `/api/pools/{name}/scrub` | Scrub starten |
|
||||||
# Get pool status
|
| POST | `/api/pools/{name}/scrub/stop` | Scrub stoppen |
|
||||||
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
|
### Datasets
|
||||||
```bash
|
| Methode | Pfad | Beschreibung |
|
||||||
# List datasets
|
|---------|------|--------------|
|
||||||
curl http://localhost:8000/api/datasets \
|
| GET | `/api/datasets/` | Alle Datasets |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
| POST | `/api/datasets/` | Dataset erstellen |
|
||||||
|
| DELETE | `/api/datasets/{name}` | Dataset löschen |
|
||||||
# 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
|
### Snapshots
|
||||||
```bash
|
| Methode | Pfad | Beschreibung |
|
||||||
# List snapshots
|
|---------|------|--------------|
|
||||||
curl http://localhost:8000/api/snapshots \
|
| GET | `/api/snapshots/` | Alle Snapshots |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
| POST | `/api/snapshots/` | Snapshot erstellen |
|
||||||
|
| DELETE | `/api/snapshots/{name}` | Snapshot löschen |
|
||||||
|
| POST | `/api/snapshots/rollback` | Rollback |
|
||||||
|
|
||||||
# Create snapshot
|
### Shares
|
||||||
curl -X POST http://localhost:8000/api/snapshots \
|
| Methode | Pfad | Beschreibung |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
|---------|------|--------------|
|
||||||
-H "Content-Type: application/json" \
|
| GET | `/api/shares/samba` | Samba-Shares auflisten |
|
||||||
-d '{"dataset":"tank/share"}'
|
| POST | `/api/shares/samba` | Share erstellen |
|
||||||
|
| DELETE | `/api/shares/samba/{name}` | Share löschen |
|
||||||
|
| GET | `/api/shares/nfs` | NFS-Exports auflisten |
|
||||||
|
| POST | `/api/shares/nfs` | Export erstellen |
|
||||||
|
| DELETE | `/api/shares/nfs/{path}` | Export löschen |
|
||||||
|
| GET | `/api/shares/samba/config` | Samba Global-Config |
|
||||||
|
| POST | `/api/shares/samba/config` | Parameter setzen |
|
||||||
|
| DELETE | `/api/shares/samba/config/{key}` | Parameter löschen |
|
||||||
|
|
||||||
# Delete snapshot
|
### System
|
||||||
curl -X DELETE http://localhost:8000/api/snapshots/tank/share@2026-04-14-120000 \
|
| Methode | Pfad | Beschreibung |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
|---------|------|--------------|
|
||||||
|
| GET | `/api/system/info` | CPU, RAM, Disk |
|
||||||
|
| GET | `/api/system/logs` | Systemlogs |
|
||||||
|
|
||||||
# Rollback snapshot
|
### Identities
|
||||||
curl -X POST http://localhost:8000/api/snapshots/rollback \
|
| Methode | Pfad | Beschreibung |
|
||||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
|---------|------|--------------|
|
||||||
-H "Content-Type: application/json" \
|
| GET | `/api/identities/users` | Systembenutzer auflisten |
|
||||||
-d '{"snapshot":"tank/share@2026-04-14-120000"}'
|
| POST | `/api/identities/users` | Benutzer anlegen |
|
||||||
```
|
| DELETE | `/api/identities/users/{name}` | Benutzer löschen |
|
||||||
|
| GET | `/api/identities/groups` | Gruppen auflisten |
|
||||||
|
|
||||||
### File Manager (Browse /tank/share)
|
## Caching
|
||||||
```bash
|
|
||||||
# Browse directory
|
|
||||||
curl "http://localhost:8000/api/files/browse?path=/" \
|
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
|
||||||
|
|
||||||
# Get file info
|
ZFS-Befehle sind mit TTL gecacht:
|
||||||
curl "http://localhost:8000/api/files/info?path=/document.pdf" \
|
- Pools: 30s
|
||||||
-H "Authorization: Bearer YOUR_TOKEN"
|
- Datasets/Snapshots: 60s
|
||||||
|
|
||||||
# Read text file (< 10MB)
|
Mutationen (erstellen/löschen) löschen den Cache sofort.
|
||||||
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
|
## Troubleshooting
|
||||||
|
|
||||||
### ZFS commands not working
|
```bash
|
||||||
- Check: `zpool list` runs without errors
|
# Logs live
|
||||||
- Check: Running as root or with proper sudo permissions
|
journalctl -u zmb-webui-backend -f
|
||||||
- Check: ZFS kernel module is loaded: `lsmod | grep zfs`
|
|
||||||
|
|
||||||
### Memory usage growing
|
# Manuell starten (für Fehlerausgabe direkt im Terminal)
|
||||||
- Check: `ps aux | grep uvicorn` for VSZ/RSS
|
cd backend && source venv/bin/activate
|
||||||
- Restart service: `systemctl restart zmb-webui-backend`
|
python3 main.py
|
||||||
- Increase frequency of restarts in crontab if needed
|
|
||||||
|
|
||||||
### Slow responses
|
# ZFS prüfen
|
||||||
- Check: `zpool status` output (large pool = slow scrub)
|
zpool list
|
||||||
- Clear cache: `curl -X POST /api/pools/clear-cache` (with auth)
|
|
||||||
- Consider increasing cache TTLs in `zfs_runner.py`
|
|
||||||
|
|
||||||
## Development Tips
|
# Samba Registry prüfen
|
||||||
|
net conf list
|
||||||
- Use `curl` or Postman for API testing
|
```
|
||||||
- Check logs: `journalctl -u zmb-webui-backend -f`
|
|
||||||
- Interactive API docs: `http://localhost:8000/docs` (after running)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user