Files
PiCopy/README.md

422 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div align="center">
<img src="PiCopy_Logo.png" alt="PiCopy Logo" width="160">
</div>
# PiCopy
**Automatische USB-Backup-Station für den Raspberry Pi mit Web-Interface**
PiCopy verwandelt deinen Raspberry Pi in ein eigenständiges Backup-Gerät. Stecke eine Quell-USB (Speicherkarte, USB-Stick) und ein Ziel-Laufwerk ein PiCopy kopiert die Daten automatisch, organisiert sie in Datumsordnern, prüft die Integrität und kann danach auf ein NAS hochladen.
---
## Features
| | Feature | Beschreibung |
|---|---|---|
| 📋 | **Automatisches Kopieren** | Startet sofort wenn Quelle und Ziel eingesteckt werden |
| 🌐 | **Web-Interface** | Konfiguration und Status von jedem Gerät im Netzwerk |
| 📂 | **Datei-Explorer** | Inhalt verbundener Laufwerke direkt im Browser durchsuchen |
| 🗂️ | **Smarte Organisation** | Erstellt automatisch Datumsordner (`2024-01-15_143022/`) |
| 🔍 | **Dateifilter** | Nur Fotos, nur Videos oder beliebige Dateitypen kopieren |
| 🔄 | **Duplikat-Behandlung** | Überspringen / Überschreiben / Umbenennen |
| ✅ | **MD5-Verifizierung** | Jede Datei nach dem Kopieren auf Integrität prüfen |
| 🗑️ | **Quelle leeren** | Quelldateien nach erfolgreichem Kopieren löschen (Move-Modus) |
| 🔀 | **Mehrere Quellen** | Mehrere USB-Quell-Ports gleichzeitig auf ein Ziel kopieren |
| 💾 | **Interner Speicher** | Pi-interne SD-Karte als Kopierziel verwenden |
| 🖧 | **NAS / SMB Upload** | Nach dem lokalen Backup auf ein Netzlaufwerk hochladen |
| 📁 | **Samba-Freigabe** | Internen Speicher als SMB-Netzwerkfreigabe bereitstellen |
| 📡 | **WiFi-Fallback** | Erstellt einen eigenen Hotspot wenn kein WLAN verfügbar ist |
| 🔒 | **WireGuard VPN** | VPN-Verbindung für sicheren Fernzugriff |
| 📊 | **System-Monitoring** | CPU-Temperatur, RAM- und SD-Karten-Auslastung im Dashboard |
| 💽 | **Speicherplatz-Panel** | Füllstand aller verbundenen Laufwerke (Quelle, Ziel, intern) mit Fortschrittsbalken |
| ⚠️ | **Speicherplatz-Warnung** | Vor dem Kopieren wird geprüft ob genug Platz vorhanden ist Warnung wenn nicht |
| 🕐 | **Kopier-Verlauf** | Die letzten 100 Kopiervorgänge werden gespeichert |
| ⚡ | **Headless-Betrieb** | Kein Monitor, keine Tastatur nötig |
| 🔁 | **Autostart** | Startet automatisch beim Pi-Boot via systemd |
| 💿 | **Laufwerk formatieren** | Ziel-USB direkt im Browser formatieren (exFAT / FAT32 / NTFS) |
---
## Voraussetzungen
- Raspberry Pi (2, 3, 4, 5 oder Zero 2W)
- Raspberry Pi OS **Bookworm** (Debian 12) oder neuer
- Mindestens 2 USB-Ports (Quelle + Ziel)
- WLAN oder LAN für das Web-Interface
---
## Installation
### Option A Direkt vom Git-Repo (empfohlen)
```bash
git clone https://git.leuschner.dev/Tobias/PiCopy
cd PiCopy
sudo bash install.sh
```
### Option B One-Liner
```bash
curl -sSL https://git.leuschner.dev/Tobias/PiCopy/raw/branch/main/install.sh | sudo bash
```
Nach der Installation ist das Web-Interface unter folgender Adresse erreichbar:
```
http://<raspberry-pi-ip>:8080
```
Die IP-Adresse wird am Ende der Installation angezeigt.
---
## Schnellstart
1. **Web-Interface öffnen**`http://<pi-ip>:8080`
2. **USB-Gerät einstecken** das als Quelle dienen soll
3. **Port konfigurieren** → Unter *USB Port Konfiguration* das Gerät in der Dropdown-Liste wählen → *Als feste Quelle speichern*
4. **Ziel konfigurieren** → Ziel-Laufwerk einstecken, Port wählen → *Als festes Ziel speichern*
5. **Auto-Kopie aktivieren** → Haken bei *Automatisch kopieren wenn Quelle & Ziel verbunden*
6. **Fertig** → Jetzt beide Laufwerke einstecken → Kopie startet automatisch
> **Wichtig:** PiCopy merkt sich den **physischen Port** (Anschluss), nicht das spezifische Gerät. Ein anderer USB-Stick im gleichen Anschluss wird automatisch als Quelle/Ziel erkannt.
---
## Web-Interface
### Kopierstatus
Zeigt den Live-Fortschritt mit:
- Prozentualer Fortschritt + Fortschrittsbalken
- Dateizähler (`23 / 147 Dateien`)
- Übertragene Datenmenge (`1.2 GB / 3.5 GB`)
- Geschwindigkeit (`⚡ 12.4 MB/s`)
- Verbleibende Zeit (`⏱ ~4 Min.`)
- Aktuelle Datei
- Phasen-Anzeige: *Kopieren → Verifizieren → Quelle leeren*
Nach dem Abschluss: Zusammenfassung mit ✕-Button (verschwindet nach 5 Minuten automatisch).
Ein laufender Kopiervorgang kann jederzeit über die *Abbrechen*-Schaltfläche gestoppt werden.
**Speicherplatz-Warnung:** Vor dem Start prüft PiCopy ob das Ziel-Laufwerk genug freien Speicher hat. Reicht der Platz nicht aus, erscheint ein gelbes Warnfeld im Log-Bereich mit der benötigten und verfügbaren Datenmenge. Die *Quelle leeren*-Funktion wird in diesem Fall automatisch deaktiviert.
### USB Port Konfiguration & Datei-Explorer
```
┌─────────────────┬─────────────────┬──────────────────────┐
│ ▲ QUELLE │ ▼ ZIEL │ ⬆ Quelle ⬇ Ziel ↻ │
│ ● Port 2-2 │ ○ Port 1-1 │ ──────────────────── │
│ Samsung USB │ Nicht verbunden│ 📁 DCIM │
│ │ │ 📁 MISC │
│ [Als Quelle ▾] │ [Als Ziel ▾] │ 🖼 IMG_001.jpg 4 MB │
└─────────────────┴─────────────────┴──────────────────────┘
```
- **Grüner Punkt** = Gerät verbunden und bereit
- **Grauer Punkt** = Port konfiguriert, kein Gerät eingesteckt
- **Datei-Explorer** zum Durchsuchen der verbundenen Laufwerke
#### Mehrere Quell-Ports
Es können mehrere USB-Ports als Quellen konfiguriert werden. Beim Start eines Kopiervorgangs werden alle verbundenen Quell-Ports nacheinander auf das Ziel kopiert, jeweils in einen eigenen Unterordner. Die Ports lassen sich über *Port-Zuweisung zurücksetzen* auf einmal löschen.
#### Interner Speicher als Ziel
Statt eines USB-Laufwerks kann der interne Speicher des Raspberry Pi (`/opt/picopy/internal`) als Kopierziel gewählt werden. Dies ist nützlich wenn kein Ziel-USB-Gerät vorhanden ist oder als Zwischenpuffer.
### Kopier-Einstellungen
| Einstellung | Standard | Beschreibung |
|---|---|---|
| Datumsformat | `JJJJ-MM-TT` | Format des Zielordners |
| Uhrzeit | ✓ | Uhrzeit im Ordnernamen (`_143022`) |
| Unterordner | ✓ | Unterordner nach Gerätebezeichnung |
| Auto-Kopie | ✓ | Automatisch starten wenn beide verbunden |
| Dateifilter | *leer* | Nur bestimmte Dateitypen kopieren |
| Systemdateien | ✓ | `.DS_Store`, `Thumbs.db`, `RECYCLER` usw. ausschließen |
| Duplikate | Überspringen | Skip / Überschreiben / Umbenennen |
| MD5-Verify | ✗ | Jede Datei nach dem Kopieren prüfen |
| Quelle leeren | ✗ | Quelldateien nach Kopieren löschen |
#### Dateifilter Schnell-Presets
| Preset | Dateitypen |
|---|---|
| 📷 Fotos | jpg, jpeg, heic, raw, cr2, nef, arw, dng, png |
| 🎬 Videos | mp4, mov, avi, mkv, mts, m2ts, wmv |
| 📷+🎬 Beides | Fotos + Videos kombiniert |
| ✕ Alle | Kein Filter alle Dateien kopieren |
### Laufwerk formatieren
Das Ziel-Laufwerk kann direkt im Web-Interface formatiert werden, ohne einen PC zu benötigen. Der *Formatieren*-Button erscheint im Ziel-Card sobald ein USB-Gerät in der Dropdown-Liste ausgewählt ist.
| Dateisystem | Mac | Windows | Dateigrößen | Empfehlung |
|---|---|---|---|---|
| **exFAT** | ✅ lesen/schreiben | ✅ lesen/schreiben | unbegrenzt | Empfohlen für Foto/Video-Backup |
| **FAT32** | ✅ lesen/schreiben | ✅ lesen/schreiben | max. 4 GB | Ältere Geräte / maximale Kompatibilität |
| **NTFS** | ✅ lesen / ✗ schreiben | ✅ lesen/schreiben | unbegrenzt | Windows-only Workflows |
> **Hinweis:** Das Formatieren löscht alle Daten auf dem Laufwerk unwiderruflich. PiCopy fordert vor dem Start eine Bestätigung an.
>
> Die benötigten Pakete (`exfatprogs`, `dosfstools`, `ntfs-3g`) werden beim Installieren von PiCopy automatisch mitinstalliert.
### Kopier-Verlauf
Jeder abgeschlossene Kopiervorgang wird im Verlauf gespeichert (bis zu 100 Einträge). Der Verlauf zeigt:
- Start-Zeitpunkt und Dauer
- Anzahl kopierter, übersprungener und fehlerhafter Dateien
- Übertragene Datenmenge
- Eventuelle Fehlermeldung
Der Verlauf kann über das Web-Interface vollständig gelöscht werden.
### System-Monitoring
Das Dashboard zeigt live:
| Wert | Beschreibung |
|---|---|
| CPU-Temperatur | Aktuell in °C (aus `/sys/class/thermal/`) |
| RAM gesamt / genutzt | In MB und als Prozentwert |
| SD-Karte gesamt / genutzt | In GB und als Prozentwert |
#### Speicherplatz-Panel
Unterhalb der Systemwerte zeigt ein Speicherplatz-Panel den Füllstand aller verbundenen Laufwerke:
- **Quelle** (grün), **Ziel** (blau) und **sonstige** Geräte werden farblich unterschieden
- Anzeige: genutzter / gesamter Speicher, freier Speicher und prozentualer Füllstand
- Fortschrittsbalken wechselt die Farbe: grün (< 75 %), gelb (7589 %), rot (≥ 90 %)
- Interner Speicher wird ebenfalls angezeigt wenn er als Ziel konfiguriert ist
### Fernkopie NAS / SMB
Nach dem lokalen Kopieren lädt PiCopy auf konfigurierte NAS-Freigaben hoch:
1. * NAS-Ziel hinzufügen* klicken
2. Name, Server-IP, Freigabename, Benutzer und Passwort eingeben
3. *Speichern & Verbindung testen* PiCopy testet die Verbindung sofort
4. Mehrere NAS-Ziele möglich, jedes einzeln aktivierbar
### Samba-Freigabe (Interner Speicher)
Der interne Speicher des Pi kann als SMB-Netzwerkfreigabe bereitgestellt werden:
- Freigabename: `PiCopy`
- Samba wird bei erster Aktivierung automatisch installiert
- Zugreifbar von Windows, macOS und Linux im gleichen Netzwerk
```
\\<pi-ip>\PiCopy
```
### WiFi-Einstellungen
| Modus | Beschreibung |
|---|---|
| **Heimnetz** | WLAN-Netzwerke scannen und verbinden |
| **Hotspot (AP)** | Eigenes WLAN wenn kein Heimnetz erreichbar |
- Verfügbare Netzwerke können direkt im Web-Interface gescannt und ausgewählt werden
- Fällt die Heimnetz-Verbindung weg, wird der Hotspot automatisch aktiviert
**Hotspot-Standardwerte:**
- SSID: `PiCopy`
- Passwort: `PiCopy,`
- IP im Hotspot-Modus: `http://10.42.0.1:8080`
Der Hotspot startet automatisch beim Boot wenn das konfigurierte WLAN nicht verfügbar ist.
### WireGuard VPN
PiCopy unterstützt WireGuard für sicheren Fernzugriff (z. B. aus dem Internet):
1. *WireGuard installieren* klicken installiert `wireguard` und `openresolv` via apt
2. WireGuard-Konfigurationsdatei (`.conf`) in das Textfeld einfügen
3. *Verbinden* klicken
4. Optional: *Automatisch verbinden beim Start* aktivieren
Zum Trennen *Trennen* klicken oder WireGuard über das Interface deinstallieren.
> **Hinweis:** Der Private Key wird in der Anzeige maskiert (`****`), ist aber auf dem Pi gespeichert.
---
## Ordnerstruktur auf dem Ziel
```
/ziel-laufwerk/
└── 2024-01-15_143022/ ← Datum + Uhrzeit (konfigurierbar)
└── Samsung_USB/ ← Gerätebezeichnung (wenn Unterordner aktiv)
├── DCIM/
│ └── 100CANON/
│ ├── IMG_0001.JPG
│ ├── IMG_0001.CR2
│ └── IMG_0002.MP4
└── MISC/
└── notes.txt
```
Bei mehreren Quell-Ports erhält jede Quelle ihren eigenen Unterordner:
```
/ziel-laufwerk/
└── 2024-01-15_143022/
├── Samsung_USB/
└── SanDisk_Extreme/
```
---
## Update
### Automatische Update-Benachrichtigung
PiCopy prüft alle **6 Stunden** automatisch ob eine neue Version verfügbar ist. Sobald ein Update bereitsteht, erscheint in der Topbar des Web-Interfaces ein gelbes Badge:
```
↑ v1.1.0 verfügbar
```
Ein Klick auf das Badge → Bestätigungsdialog → PiCopy lädt die neue Version herunter, verifiziert sie und startet sich selbst neu. Das Interface ist dabei ca. 10 Sekunden nicht erreichbar.
### Manuelles Update
**Option A über das Web-Interface:**
Topbar-Badge klicken (falls Update verfügbar) oder direkt:
`http://<pi-ip>:8080` → Badge erscheint automatisch
**Option B per SSH:**
```bash
cd PiCopy
git pull
sudo cp app.py /opt/picopy/app.py
sudo systemctl restart picopy
```
**Option C One-Liner:**
```bash
curl -sSL https://git.leuschner.dev/Tobias/PiCopy/raw/branch/main/app.py \
| sudo tee /opt/picopy/app.py > /dev/null && sudo systemctl restart picopy
```
---
## Deinstallation
```bash
sudo systemctl stop picopy
sudo systemctl disable picopy
sudo rm /etc/systemd/system/picopy.service
sudo rm -rf /opt/picopy
sudo systemctl daemon-reload
```
---
## Service-Verwaltung
```bash
# Status prüfen
sudo systemctl status picopy
# Live-Logs
journalctl -u picopy -f
# Neustart
sudo systemctl restart picopy
# Stoppen
sudo systemctl stop picopy
```
---
## Technische Details
| Komponente | Technologie |
|---|---|
| Backend | Python 3 + Flask |
| USB-Erkennung | `lsblk` + `udevadm` |
| USB-Monitoring | `pyudev` (udev-Events) |
| WiFi-Verwaltung | NetworkManager (`nmcli`) |
| VPN | WireGuard (`wg-quick`) |
| NAS-Sync | `rclone` (SMB) |
| Netzwerkfreigabe | Samba (`smbd`) |
| Service | systemd (Autostart, Auto-Restart) |
**Dateipfade auf dem Pi:**
| Pfad | Inhalt |
|---|---|
| `/opt/picopy/app.py` | Hauptanwendung |
| `/opt/picopy/config.json` | Konfiguration (Ports, WiFi, Einstellungen) |
| `/opt/picopy/state.json` | Letzter Kopierstatus (persistiert) |
| `/opt/picopy/history.json` | Kopier-Verlauf (max. 100 Einträge) |
| `/opt/picopy/rclone.conf` | NAS-Zugangsdaten (rclone) |
| `/opt/picopy/internal/` | Interner Speicher als Kopierziel |
| `/opt/picopy/logs/picopy.log` | Log-Datei |
| `/opt/picopy/version.txt` | Aktuelle Versionsnummer |
| `/etc/wireguard/picopy.conf` | WireGuard-Konfiguration |
| `/etc/systemd/system/picopy.service` | Systemd-Service |
---
## Getestete Hardware
| Gerät | Status |
|---|---|
| Raspberry Pi 4 Model B | ✅ Vollständig getestet |
| Raspberry Pi 5 | ✅ Kompatibel |
| Raspberry Pi 3 Model B+ | ✅ Kompatibel |
| Raspberry Pi Zero 2W | ⚠️ Langsamer, nur 1 USB-Port (Hub benötigt) |
---
## Neue Version veröffentlichen (für Maintainer)
So wird ein neues Release erstellt, das alle Nutzer automatisch als Update angezeigt bekommen:
**1. Version erhöhen**
In `version.txt`:
```
1.0.72
```
**2. Committen & pushen**
```bash
git add version.txt
git commit -m "Release v1.0.72"
git push
```
**3. Release/Tag in Gitea erstellen** *(optional, aber empfohlen)*
Unter [git.leuschner.dev/Tobias/PiCopy/releases](https://git.leuschner.dev/Tobias/PiCopy/releases) → *Neues Release* → Tag `v1.0.72` setzen.
**Das war's.** Alle laufenden PiCopy-Instanzen erkennen das Update innerhalb von 6 Stunden automatisch und zeigen das Badge im Web-Interface an.
> **Hinweis:** `version.txt` ist die Quelle der Wahrheit. `app.py` liest diese Datei beim Start und der Installer/Updater legt sie neben der App unter `/opt/picopy/version.txt` ab.
---
## Lizenz
MIT License siehe [LICENSE](LICENSE)
---
## Autor
Tobias Leuschner [info@leuschner.dev](mailto:info@leuschner.dev)