Docs: README komplett neu geschrieben (aktueller Stack: HTMX+Jinja2)
Next.js, Node.js, deploy/-Ordner-Referenzen entfernt. Spiegelt den echten Stand wider: FastAPI + HTMX, PAM-Auth, Samba Registry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,491 +1,189 @@
|
||||
# ZMB Webui - Installation Guide
|
||||
# ZMB Webui
|
||||
|
||||
ZMB Webui ist eine moderne Web-UI für ZFS und Samba/NFS Verwaltung auf Linux-Systemen. Dieses Dokument beschreibt die Installation auf Ubuntu/Debian.
|
||||
Web-UI für ZFS und Samba/NFS-Verwaltung auf Linux-Systemen. Ersetzt Cockpit auf dem Raspberry Pi.
|
||||
|
||||
**Stack:** Python/FastAPI + HTMX + Jinja2 — kein Node.js, kein Build-Schritt.
|
||||
|
||||
**Zielplattformen:**
|
||||
- Raspberry Pi (ARM64, 4GB RAM+)
|
||||
- Raspberry Pi (ARM64, 4GB RAM+) — Primärziel
|
||||
- Debian/Ubuntu Server (x86_64 oder ARM64)
|
||||
- LXC Container
|
||||
- LXC Container (privilegiert)
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
### System
|
||||
- **OS:** Ubuntu 20.04+ oder Debian 11+
|
||||
- **RAM:** Minimal 2GB (4GB empfohlen)
|
||||
- **Disk:** Minimal 500MB für Installation
|
||||
- **Root-Zugang** erforderlich
|
||||
|
||||
### Abhängigkeiten
|
||||
```bash
|
||||
# ZFS und System-Tools
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
python3.9+ \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
zfsutils-linux \
|
||||
samba \
|
||||
nfs-kernel-server \
|
||||
nginx \
|
||||
curl \
|
||||
git
|
||||
|
||||
# Node.js (für Frontend-Build)
|
||||
# Optional, nur wenn du das Frontend selbst bauen möchtest
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
apt-get install -y nodejs
|
||||
|
||||
# Samba-Admin-Tools
|
||||
apt-get install -y samba-client samba-dsdb-modules
|
||||
python3 python3-pip python3-venv python3-pam \
|
||||
zfsutils-linux samba nfs-kernel-server nginx curl git
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Repository klonen
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone https://gitea.perlbach24.de/patrick/zmb-webui.git
|
||||
git clone https://gitea.perlbach24.de/scripte/zmb-webui.git zmb-webui
|
||||
cd zmb-webui
|
||||
```
|
||||
|
||||
### 2. Backend Setup
|
||||
|
||||
#### 2.1 Python Virtual Environment erstellen
|
||||
### 2. Python Virtual Environment
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install --upgrade pip setuptools wheel
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 2.2 Admin-Benutzer erstellen
|
||||
### 3. Systemd Service
|
||||
|
||||
```bash
|
||||
python3 << 'EOF'
|
||||
from services.auth import auth_service
|
||||
|
||||
# Erstelle einen Admin-Benutzer
|
||||
username = input("Benutzername: ")
|
||||
password = input("Passwort: ")
|
||||
|
||||
auth_service.add_user(username, password)
|
||||
print(f"✓ Benutzer '{username}' erstellt")
|
||||
EOF
|
||||
```
|
||||
|
||||
Oder über System-Benutzer:
|
||||
```bash
|
||||
# Erstelle einen System-Benutzer
|
||||
useradd -m -s /bin/false webadmin
|
||||
echo "webadmin:mypassword123" | chpasswd
|
||||
|
||||
# Der Benutzer kann sich dann mit diesem Passwort anmelden
|
||||
```
|
||||
|
||||
### 3. Frontend Setup
|
||||
|
||||
#### 3.1 Frontend bauen (empfohlen auf schnellerem System)
|
||||
|
||||
**Option A: Lokal bauen und deployen (schneller)**
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
|
||||
# Abhängigkeiten installieren
|
||||
npm install
|
||||
|
||||
# Build für statischen Export
|
||||
npm run build
|
||||
# Erstellt ./out/ mit fertigen HTML-Dateien
|
||||
|
||||
# Output prüfen
|
||||
ls -la out/ | grep -E "\.html|index"
|
||||
```
|
||||
|
||||
**Option B: Direkt auf dem Ziel-System bauen**
|
||||
|
||||
```bash
|
||||
# Auf dem Ziel-System
|
||||
ssh root@192.168.1.179 # oder deine IP
|
||||
|
||||
cd /opt/zmb-webui/frontend
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 4. Deployment auf Ziel-System
|
||||
|
||||
#### 4.1 Backend deployen
|
||||
|
||||
```bash
|
||||
# Von deinem lokalen Rechner
|
||||
scp -r backend root@192.168.1.179:/opt/zmb-webui/
|
||||
|
||||
# Oder via rsync
|
||||
rsync -avz backend/ root@192.168.1.179:/opt/zmb-webui/backend/
|
||||
```
|
||||
|
||||
#### 4.2 Frontend deployen
|
||||
|
||||
```bash
|
||||
# Von deinem lokalen Rechner (nach npm run build)
|
||||
rsync -avz --delete frontend/out/ root@192.168.1.179:/opt/zmb-webui/frontend/
|
||||
```
|
||||
|
||||
### 5. Systemd Service Setup
|
||||
|
||||
#### 5.1 Service-Datei erstellen
|
||||
|
||||
```bash
|
||||
sudo cp deploy/zfs-manager-backend.service /etc/systemd/system/zmb-webui-backend.service
|
||||
```
|
||||
|
||||
Überprüfe die Datei:
|
||||
```bash
|
||||
sudo cat /etc/systemd/system/zmb-webui-backend.service
|
||||
```
|
||||
|
||||
**Inhalt sollte etwa so aussehen:**
|
||||
```ini
|
||||
sudo tee /etc/systemd/system/zmb-webui-backend.service > /dev/null << 'EOF'
|
||||
[Unit]
|
||||
Description=ZMB Webui Backend API
|
||||
Description=ZMB Webui Backend
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/zmb-webui/backend
|
||||
Environment="PATH=/opt/zmb-webui/venv/bin"
|
||||
ExecStart=/opt/zmb-webui/venv/bin/python -m uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
ExecStart=/opt/zmb-webui/backend/venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 8000
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
EOF
|
||||
|
||||
#### 5.2 Service aktivieren und starten
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable zmb-webui-backend
|
||||
sudo systemctl start zmb-webui-backend
|
||||
|
||||
# Status prüfen
|
||||
sudo systemctl enable --now zmb-webui-backend
|
||||
sudo systemctl status zmb-webui-backend
|
||||
```
|
||||
|
||||
### 6. Nginx Konfiguration
|
||||
|
||||
#### 6.1 Nginx Config erstellen
|
||||
### 4. Nginx (HTTPS Reverse Proxy auf Port 8090)
|
||||
|
||||
```bash
|
||||
sudo tee /etc/nginx/sites-available/zmb-webui > /dev/null << 'EOF'
|
||||
server {
|
||||
listen 8090 ssl http2;
|
||||
listen [::]:8090 ssl http2;
|
||||
|
||||
server_name _;
|
||||
|
||||
# SSL-Zertifikate (self-signed für Entwicklung)
|
||||
ssl_certificate /etc/nginx/ssl/zmb-webui.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/zmb-webui.key;
|
||||
|
||||
root /opt/zmb-webui/frontend;
|
||||
index index.html;
|
||||
|
||||
# Frontend - statische HTML
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
expires 1h;
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
}
|
||||
|
||||
# Backend API - Proxy
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
# WebSocket
|
||||
location /ws {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
|
||||
# Health check
|
||||
location /health {
|
||||
proxy_pass http://127.0.0.1:8000/health;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
#### 6.2 Self-signed SSL-Zertifikat erstellen
|
||||
|
||||
```bash
|
||||
# SSL-Verzeichnis erstellen
|
||||
sudo mkdir -p /etc/nginx/ssl
|
||||
|
||||
# Self-signed Zertifikat (gültig 365 Tage)
|
||||
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
# Self-signed Zertifikat
|
||||
mkdir -p /etc/nginx/ssl
|
||||
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
|
||||
-keyout /etc/nginx/ssl/zmb-webui.key \
|
||||
-out /etc/nginx/ssl/zmb-webui.crt \
|
||||
-subj "/CN=zmb-webui/O=Home/C=DE"
|
||||
chmod 600 /etc/nginx/ssl/zmb-webui.key
|
||||
|
||||
sudo chmod 600 /etc/nginx/ssl/zmb-webui.key
|
||||
# Nginx Config
|
||||
tee /etc/nginx/sites-available/zmb-webui > /dev/null << 'EOF'
|
||||
server {
|
||||
listen 8090 ssl http2;
|
||||
listen [::]:8090 ssl http2;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/zmb-webui.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/zmb-webui.key;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
ln -s /etc/nginx/sites-available/zmb-webui /etc/nginx/sites-enabled/
|
||||
nginx -t && systemctl restart nginx
|
||||
```
|
||||
|
||||
#### 6.3 Nginx aktivieren und neustarten
|
||||
### 5. Samba Registry (empfohlen)
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/zmb-webui /etc/nginx/sites-enabled/
|
||||
sudo rm -f /etc/nginx/sites-enabled/default
|
||||
|
||||
# Konfiguration testen
|
||||
sudo nginx -t
|
||||
|
||||
# Neustarten
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
### 7. Samba Registry Setup (optional aber empfohlen)
|
||||
|
||||
```bash
|
||||
# Samba konfigurieren um Registry statt smb.conf zu nutzen
|
||||
sudo bash /opt/zmb-webui/deploy/setup-samba-registry.sh
|
||||
```
|
||||
|
||||
Oder manuell:
|
||||
|
||||
```bash
|
||||
# Minimale smb.conf erstellen
|
||||
sudo tee /etc/samba/smb.conf > /dev/null << 'EOF'
|
||||
tee /etc/samba/smb.conf > /dev/null << 'EOF'
|
||||
[global]
|
||||
include = registry
|
||||
EOF
|
||||
|
||||
# Samba neustarten
|
||||
sudo systemctl restart smbd
|
||||
systemctl restart smbd
|
||||
```
|
||||
|
||||
## Erste Schritte
|
||||
|
||||
### 1. Zugriff auf WebUI
|
||||
|
||||
Öffne in deinem Browser:
|
||||
```
|
||||
https://192.168.1.179:8090
|
||||
```
|
||||
|
||||
(Ersetze die IP mit deiner Ziel-System IP)
|
||||
|
||||
### 2. Login
|
||||
|
||||
- **Benutzername:** Der Admin-Benutzer, den du erstellt hast
|
||||
- **Passwort:** Das Passwort, das du gesetzt hast
|
||||
|
||||
### 3. Navigation
|
||||
|
||||
Nach Login siehst du:
|
||||
- **Dashboard** - Pool Status, Quick Stats
|
||||
- **Shares** - Samba und NFS Shares verwalten
|
||||
- **File Sharing** - Samba Global Config (Samba Registry Parameter)
|
||||
- **Navigator** - Datei-Browser
|
||||
- **Identities** - Benutzer und Gruppen
|
||||
- **Logs** - System Logs
|
||||
|
||||
## Samba Global Configuration
|
||||
|
||||
Die Samba Global Configuration wird vom **Samba Registry** gelesen:
|
||||
|
||||
```bash
|
||||
# Zeige alle Global Parameters
|
||||
net conf list
|
||||
|
||||
# Zeige einen Parameter
|
||||
net conf getparm global "log level"
|
||||
|
||||
# Setze einen Parameter
|
||||
net conf setparm global "log level" 3
|
||||
```
|
||||
|
||||
Diese Parameter können auch über die WebUI unter `/shares` → "Samba Config" Tab bearbeitet werden.
|
||||
|
||||
## NFS Configuration
|
||||
|
||||
NFS Exports werden in `/etc/exports` gespeichert:
|
||||
|
||||
```bash
|
||||
# Zeige alle Exports
|
||||
cat /etc/exports
|
||||
|
||||
# Reload nach Änderungen
|
||||
exportfs -r
|
||||
```
|
||||
|
||||
Diese können auch über die WebUI unter `/shares` → "NFS" Tab bearbeitet werden.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Backend startet nicht
|
||||
|
||||
```bash
|
||||
# Logs prüfen
|
||||
sudo journalctl -u zmb-webui-backend -n 50 -f
|
||||
|
||||
# Manuell starten (für Fehlerausgabe)
|
||||
cd /opt/zmb-webui/backend
|
||||
source venv/bin/activate
|
||||
python -m uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### Frontend lädt nicht
|
||||
|
||||
```bash
|
||||
# Nginx logs
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
|
||||
# Überprüfe Dateien
|
||||
ls -la /opt/zmb-webui/frontend/
|
||||
```
|
||||
|
||||
### Samba Fehler
|
||||
|
||||
```bash
|
||||
# Samba Config testen
|
||||
sudo testparm -s
|
||||
|
||||
# Samba Logs
|
||||
sudo tail -f /var/log/samba/log.smbd
|
||||
```
|
||||
|
||||
### API Fehler 401 (Unauthorized)
|
||||
|
||||
- Token ist abgelaufen → Neu anmelden
|
||||
- Falsche Anmeldedaten → Benutzer überprüfen
|
||||
|
||||
```bash
|
||||
# Benutzer überprüfen/erstellen
|
||||
cd /opt/zmb-webui/backend
|
||||
source venv/bin/activate
|
||||
python3 << 'EOF'
|
||||
from services.auth import auth_service
|
||||
auth_service.add_user("admin", "newpassword")
|
||||
EOF
|
||||
```
|
||||
|
||||
## Performance Optimierung
|
||||
|
||||
### Auf Raspberry Pi
|
||||
|
||||
```bash
|
||||
# Gunicorn mit weniger Workers (spart RAM)
|
||||
# In zmb-webui-backend.service:
|
||||
# ExecStart=/opt/zmb-webui/venv/bin/gunicorn main:app \
|
||||
# --workers 2 --worker-class uvicorn.workers.UvicornWorker \
|
||||
# --bind 0.0.0.0:8000
|
||||
|
||||
# Cache TTL erhöhen (in services/zfs_runner.py)
|
||||
CACHE_TTL = 120 # 2 Minuten statt 30 Sekunden
|
||||
|
||||
# Memory Monitor
|
||||
free -h
|
||||
watch -n 1 free -h
|
||||
```
|
||||
|
||||
### Auf x86_64 Server
|
||||
|
||||
```bash
|
||||
# Mehr Workers nutzen
|
||||
ExecStart=... --workers 4 ...
|
||||
|
||||
# Redis Cache (optional)
|
||||
# Siehe CLAUDE.md für Details
|
||||
```
|
||||
|
||||
## Automatisches Update von Gitea
|
||||
|
||||
```bash
|
||||
# Deploy-Script kopieren
|
||||
cp deploy/update-from-gitea.sh /opt/zmb-webui/
|
||||
|
||||
# Executable machen
|
||||
chmod +x /opt/zmb-webui/update-from-gitea.sh
|
||||
|
||||
# Cronjob erstellen (tägliches Auto-Update)
|
||||
sudo tee /etc/cron.daily/zmb-webui-update > /dev/null << 'EOF'
|
||||
#!/bin/bash
|
||||
cd /opt/zmb-webui
|
||||
./update-from-gitea.sh
|
||||
EOF
|
||||
sudo chmod +x /etc/cron.daily/zmb-webui-update
|
||||
```
|
||||
|
||||
## Sicherheit
|
||||
|
||||
⚠️ **Für Produktion:**
|
||||
|
||||
1. **SSL-Zertifikat:** Self-signed durch echtes Zertifikat ersetzen
|
||||
2. **CORS:** In `backend/main.py` ändern:
|
||||
```python
|
||||
allow_origins = ["https://deine-domain.de"] # statt ["*"]
|
||||
```
|
||||
3. **Passwörter:** Starke Passwörter verwenden
|
||||
4. **Firewall:** Port 8090 nur für vertrauenswürdige IPs freigeben
|
||||
5. **Updates:** Regelmäßig git pull und neu bauen
|
||||
|
||||
## Dateistruktur nach Installation
|
||||
|
||||
```
|
||||
/opt/zmb-webui/
|
||||
├── backend/
|
||||
│ ├── venv/ # Python Virtual Environment
|
||||
│ ├── main.py
|
||||
│ ├── routers/ # API Endpoints
|
||||
│ ├── services/ # Business Logic
|
||||
│ ├── models/ # Pydantic Models
|
||||
│ ├── requirements.txt
|
||||
│ └── README.md
|
||||
├── frontend/
|
||||
│ ├── _next/ # Next.js Build Output
|
||||
│ ├── app/ # Next.js Pages
|
||||
│ ├── components/ # React Components
|
||||
│ ├── lib/ # Utilities & API Client
|
||||
│ ├── public/ # Static Files
|
||||
│ ├── package.json
|
||||
│ ├── *.html # Generated Static Pages
|
||||
│ └── README.md
|
||||
├── deploy/
|
||||
│ ├── zfs-manager-backend.service
|
||||
│ ├── setup-samba-registry.sh
|
||||
│ ├── update-from-gitea.sh
|
||||
│ └── samba-template.conf
|
||||
├── INSTALLATION.md # Diese Datei
|
||||
├── CLAUDE.md # Entwickler-Dokumentation
|
||||
└── README.md # Feature-Übersicht
|
||||
```
|
||||
|
||||
## Weitere Dokumentation
|
||||
|
||||
- **CLAUDE.md** - Architektur, Entwicklung, Deployment
|
||||
- **backend/README.md** - API-Endpoints, curl Beispiele
|
||||
- **frontend/README.md** - Frontend-Konfiguration, Build-Options
|
||||
|
||||
---
|
||||
|
||||
**Support:** Bei Fragen oder Problemen, siehe CLAUDE.md oder kontaktiere patrick@perlbach24.de
|
||||
## Benutzerverwaltung
|
||||
|
||||
Jeder Linux-Systembenutzer mit Login-Shell kann sich anmelden. Kein separates User-Management nötig.
|
||||
|
||||
```bash
|
||||
# Benutzer anlegen
|
||||
useradd -m -s /bin/bash username
|
||||
passwd username
|
||||
|
||||
# Zugang entziehen
|
||||
usermod -s /usr/sbin/nologin username
|
||||
```
|
||||
|
||||
> Der Backend-Dienst muss als root laufen (PAM benötigt `/etc/shadow`-Zugang).
|
||||
|
||||
---
|
||||
|
||||
## Deployment-Update
|
||||
|
||||
```bash
|
||||
# Backend synchronisieren
|
||||
rsync -a backend/ root@<ziel-ip>:/opt/zmb-webui/backend/
|
||||
|
||||
# Service neu starten
|
||||
ssh root@<ziel-ip> 'systemctl restart zmb-webui-backend'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logs & Diagnose
|
||||
|
||||
```bash
|
||||
# Live-Logs
|
||||
journalctl -u zmb-webui-backend -f
|
||||
|
||||
# Service-Status
|
||||
systemctl status zmb-webui-backend
|
||||
|
||||
# API-Docs (lokal)
|
||||
curl http://localhost:8000/docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
```
|
||||
backend/
|
||||
├── main.py # FastAPI App, Router-Mounting
|
||||
├── routers/ # API-Endpunkte + HTML-Seiten
|
||||
│ ├── pages.py # Jinja2-Seitenrouten + HTMX-Fragmente
|
||||
│ ├── auth.py # JWT Login
|
||||
│ ├── pools.py # ZFS Pools
|
||||
│ ├── datasets.py # ZFS Datasets
|
||||
│ ├── snapshots.py # ZFS Snapshots
|
||||
│ ├── shares.py # Samba/NFS Shares
|
||||
│ ├── identities.py # Benutzer/Gruppen
|
||||
│ ├── navigator.py # Datei-Browser
|
||||
│ └── system.py # System-Infos
|
||||
├── services/ # Business Logic
|
||||
├── templates/ # Jinja2 HTML Templates
|
||||
├── static/ # htmx.min.js, pico.min.css (vendored)
|
||||
├── models/ # Pydantic Models
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hinweise
|
||||
|
||||
- **ZFS auf LXC:** Privilegierter Container benötigt `zpool`-Binary. ZFS-Verfügbarkeit wird beim Start geprüft, graceful degradation wenn nicht vorhanden.
|
||||
- **Container-Erkennung:** `systemd-detect-virt` — Disk-I/O-Stats werden auf LXC ausgeblendet.
|
||||
- **CORS:** Standard `*` (Entwicklung). Für Produktion `ZMB_CORS_ORIGINS` Umgebungsvariable setzen.
|
||||
- **Samba Config:** Registry-basiert (`net conf`). Werte mit `-` am Anfang brauchen `--`-Separator bei `net conf setparm`.
|
||||
|
||||
Reference in New Issue
Block a user