422 lines
15 KiB
Markdown
422 lines
15 KiB
Markdown
<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 (75–89 %), 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)
|