# docker_copyparty Ansible-Rolle zum Deployment von [copyparty](https://github.com/9001/copyparty/) mittels Docker Compose. Copyparty ist ein portabler File-Server mit accelerierten resumable Uploads, Deduplizierung, WebDAV, FTP, TFTP, Zeroconf, Media-Indexierung und vielem mehr. ## Voraussetzungen - Docker und Docker Compose müssen installiert sein - Die `dockerhost` Rolle oder äquivalent sollte bereits ausgeführt worden sein ## Variablen Die Rolle verwendet folgende Variablen (siehe `defaults/main.yml`): ```yaml copyparty: port: 3923 # Port auf dem copyparty lauscht reverse_proxy: false # true wenn hinter Reverse-Proxy (Caddy/nginx/etc.) xff_src: "" # IP des Reverse-Proxy (z.B. "192.168.0.85") accounts: [] # Liste von Benutzerkonten volumes: [] # Liste von freigegebenen Verzeichnissen (copyparty volumes) ``` ## Verwendung ### Minimale Konfiguration ```yaml copyparty: port: 3923 reverse_proxy: false # Kein Reverse-Proxy accounts: - user: admin password: "sicheres_passwort" volumes: - path: /srv/dockerdata/copyparty/data/public accs: - r: "*" # Jeder kann lesen A: admin # Admin hat volle Rechte ``` ### Vollständiges Beispiel In `host_vars/.yml` oder `group_vars/.yml`: ```yaml copyparty: port: 3923 accounts: - user: admin password: "secure_password" - user: user2 password: "another_password" volumes: - path: /srv/dockerdata/copyparty/data/public name: public # Optional: URL-Name (default: Verzeichnisname) accs: - r: "*" # Alle können lesen A: admin # Admin hat volle Rechte - path: /mnt/nas/music name: music accs: - r: "admin,user2" # Admin und user2 können lesen rw: admin # Nur Admin kann schreiben - path: /srv/dockerdata/copyparty/data/upload name: upload accs: - w: "*" # Jeder kann hochladen (aber nicht lesen!) A: admin # Nur Admin kann alles flags: - e2ds # Filesystem indexing (für vmaxb/vmaxn erforderlich) - vmaxb: 50g # Max 50 GiB Gesamtgröße - df: 50g # Min 50 GiB freier Speicher - lifetime: 864000 # 10 Tage (in Sekunden) - nosub # Keine Unterverzeichnisse - path: /mnt/data accs: - r: admin # Nur Admin hat Zugriff ``` ### In einem Playbook ```yaml - hosts: docker-host become: true gather_facts: true roles: - docker_copyparty ``` ## Accounts Die `accounts` Liste definiert Benutzerkonten: ```yaml accounts: - user: username password: "password" ``` **Wichtig:** Die Rolle aktiviert `usernames` global, daher: - Login erfordert **Username UND Passwort** (z.B. `admin:secure_password`) - Das verhindert, dass User mit gleichem Passwort sich gegenseitig als der andere einloggen können - Ohne `usernames` würde nur das Passwort zählen (Username wird ignoriert) ### Password-Hashing Copyparty unterstützt gehashte Passwörter (argon2id). Diese Rolle aktiviert **automatisch**: - `ah-alg: argon2` - Aktiviert argon2id Password-Hashing - `ah-salt: ` - Verwendet einen fixen Salt für konsistente Hashes - `usernames` - Erfordert Username+Passwort für Login **Wichtig:** Mit `usernames` aktiviert hasht Copyparty intern **nur das Passwort**, nicht `username:password`! #### Hash generieren mit dem pw-helper Tool Diese Rolle enthält ein Helper-Script zum Generieren von Hashes: ```bash cd roles/docker_copyparty python3 pw-helper.py # Beispiel: python3 pw-helper.py docker-util01 kiney my_secure_password ``` Das Script: 1. Liest den `ah_salt` aus `host_vars/.yml` 2. Generiert einen korrekten argon2id-Hash für das Passwort 3. Gibt den Hash aus, den du in die Config kopieren kannst **Ausgabe-Beispiel:** ``` Reading ah_salt for docker-util01... ✓ Found ah_salt: wtqmz7laJtCiu95GRjNa... Generating hash for user 'kiney' with password '***'... NOTE: With 'usernames' enabled, copyparty hashes only the password. ✓ Generated hash: $argon2id$v=19$m=262144,t=3,p=1$wtqmz7laJtCiu95GRjNatFnxf7WUMQhG7mY0upnXmKU$zXHlgJEGbbUst7T8WeGtLbdEHxZ0BHzDfemnL+Q46ss Add to host_vars/docker-util01.yml: accounts: - user: kiney password: "$argon2id$v=19$m=262144,t=3,p=1$wtqmz7laJtCiu95GRjNatFnxf7WUMQhG7mY0upnXmKU$zXHlgJEGbbUst7T8WeGtLbdEHxZ0BHzDfemnL+Q46ss" ``` #### Manuelle Hash-Generierung (ohne pw-helper) Wenn du lieber direkt mit copyparty arbeitest: ```bash # Im laufenden Container: docker exec -it copyparty copyparty --ah-alg argon2 --ah-salt "YOUR_SALT_HERE" --ah-cli # Oder lokal wenn copyparty installiert ist: python3 copyparty-sfx.py --ah-alg argon2 --ah-salt "YOUR_SALT_HERE" --ah-cli ``` **WICHTIG:** Mit `usernames` aktiviert musst du **nur das Passwort** hashen, **NICHT** `username:password`! Beispiel: ``` # FALSCH (alt, ohne usernames): Eingabe: admin:secret123 Hash: $argon2id$v=19$m=262144,t=3,p=1$...$hash_von_admin:secret123 # RICHTIG (mit usernames): Eingabe: secret123 Hash: $argon2id$v=19$m=262144,t=3,p=1$...$hash_von_secret123 ``` #### Hash in Config eintragen ```yaml copyparty: ah_salt: "wtqmz7laJtCiu95GRjNatFnxf7WUMQhG7mY0upnXmKU=" accounts: - user: admin password: "$argon2id$v=19$m=262144,t=3,p=1$wtqmz7laJtCiu95GRjNatFnxf7WUMQhG7mY0upnXmKU$zXHlgJEGbbUst7T8WeGtLbdEHxZ0BHzDfemnL+Q46ss" ``` **Hinweise:** - Der `ah_salt` muss für alle Accounts gleich sein (wird automatisch aus host_vars gelesen) - Ohne fixen Salt generiert jeder Copyparty-Container einen neuen Salt → alte Hashes funktionieren nicht mehr - Der Salt sollte 32 Bytes Base64-encoded sein (z.B. via `openssl rand -base64 32`) ## Volumes Die `volumes` Liste definiert die freigegebenen Verzeichnisse (in copyparty-Terminologie: volumes): ```yaml volumes: - path: /pfad/zum/verzeichnis # Pfad auf dem Host (erforderlich) name: urlname # Optional: Name in der URL (default: Verzeichnisname) accs: # Zugriffskontrolle - permission: user1,user2 permission2: user3 flags: # Optional: Volume-spezifische Flags - e2ds # String-Flags (ohne Wert) - vmaxb: 10g # Key-Value Flags ``` **Wichtig:** Copyparty unterscheidet zwischen: - **Volumes** (was wir hier konfigurieren): Dauerhafte Verzeichnisse die als Mountpoints exponiert werden - **Shares** (Feature in der UI): Temporäre Links die User in der Web-UI erstellen können (via `shr: /shr` in der Config aktiviert) ### Berechtigungen Copyparty unterstützt folgende Berechtigungen (kombinierbar): - `r` (read): Verzeichnis browsen, Dateien herunterladen - `w` (write): Dateien hochladen, in diesen Ordner verschieben - `m` (move): Dateien/Ordner aus diesem Ordner verschieben - `d` (delete): Dateien/Ordner löschen - `a` (admin): Upload-Zeit und Uploader-IPs sehen, Config-Reload - `.` (dots): Dotfiles in Listings anzeigen - `A` ("all"): Kurzform für `rwmda.` (alle Rechte) Spezialwerte: - `*` = alle (auch nicht-authentifizierte Benutzer) - `username` = spezifischer Benutzer - `user1,user2,user3` = mehrere Benutzer ### Beispiele für Volume-Konfigurationen #### Public-Upload mit Read-Only für alle ```yaml volumes: - path: /srv/dockerdata/copyparty/data/public accs: - r: "*" # Jeder kann lesen w: "*" # Jeder kann hochladen d: admin # Nur Admin kann löschen ``` #### Privates Volume nur für bestimmte User ```yaml volumes: - path: /mnt/nas/private accs: - A: admin,bob # Admin und Bob haben volle Rechte ``` #### Read-Only Volume für alle eingeloggten User ```yaml volumes: - path: /mnt/nas/media accs: - r: "@acct" # Alle authentifizierten Benutzer A: admin # Admin kann alles ``` #### Media-Library mit Deduplication (btrfs/NFS) ```yaml volumes: - path: /mnt/media # btrfs via NFS 4.2 name: music accs: - r: "*" # Jeder kann browsen/downloaden A: admin # Admin kann alles flags: - e2ds # Filesystem indexing (für dedup erforderlich) - e2ts # Media-Tags indexieren (Artist, Album, etc.) - dedup # Deduplication aktivieren - reflink # CoW/reflink auf btrfs (spart Speicher, sicher) ``` **Hinweis:** `reflink` ist die sicherste Dedup-Methode (CoW = Copy-on-Write). Dateien können bearbeitet/gelöscht werden ohne andere Kopien zu beeinflussen. Funktioniert nur auf btrfs/xfs! #### Write-Only Upload Volume mit Limits (Drop-Zone) ```yaml volumes: - path: /srv/dockerdata/copyparty/data/upload name: upload accs: - w: "*" # Jeder kann hochladen, aber nichts sehen A: admin # Admin kann alles (lesen, verwalten, löschen) flags: - e2ds # Filesystem indexing (erforderlich für vmaxb/vmaxn) - vmaxb: 50g # Maximale Gesamtgröße: 50 GiB - vmaxn: 5000 # Maximale Anzahl Dateien: 5000 - df: 50g # Mindestens 50 GiB freier Speicher - lifetime: 864000 # Dateien werden nach 10 Tagen gelöscht - sz: 1k-500m # Dateigröße zwischen 1 KiB und 500 MiB - nosub # Keine Unterverzeichnisse erlaubt - maxb: 100m,3600 # Rate-Limit: 100 MiB pro Stunde pro IP - maxn: 10,3600 # Rate-Limit: 10 Dateien pro Stunde pro IP ``` ## Volume Flags Pro Volume können verschiedene Limits und Regeln als `flags` gesetzt werden: ### Größen-Limits: - `vmaxb: 10g` - Maximale Gesamtgröße des Volumes (suffixes: `b`, `k`, `m`, `g`) - `vmaxn: 1000` - Maximale Anzahl Dateien im Volume - `df: 4g` - Mindestens X GiB freier Speicher muss verfügbar bleiben - `sz: 1k-100m` - Erlaubte Dateigröße (min-max) ### Time-Limits: - `lifetime: 86400` - Dateien werden nach X Sekunden gelöscht (86400 = 24h, 864000 = 10 Tage) ### Rate-Limits (per IP): - `maxb: 100m,3600` - Max X Bytes in Y Sekunden pro IP (100m = 100 MiB, 3600 = 1 Stunde) - `maxn: 50,3600` - Max X Dateien in Y Sekunden pro IP ### Indexierung: - `e2ds` - Filesystem indexing aktivieren (**erforderlich** für `vmaxb`/`vmaxn`/`dedup`!) - `e2ts` - Media-Tags indexieren (Artist, Album, Title, etc. für Musik/Videos) - `d2t` - Deaktiviert e2ts für dieses Volume (auch wenn global gesetzt) ### Deduplication: - `dedup` - Aktiviert Deduplication (benötigt `e2ds`!) - `reflink` - Benutzt CoW/reflink statt symlinks (nur btrfs/xfs auf Linux 5.3+, Python 3.14+) - `hardlinkonly` - Benutzt hardlinks statt symlinks für Dedup - `noclone` - Deaktiviert Dedup-Erkennung komplett ### Sonstige: - `nosub` - Keine Unterverzeichnisse erlaubt - `dotpart` - Dateien während Upload verstecken - `norobots` - Verhindert Suchmaschinen-Indexierung für dieses Volume **Wichtig:** - Für `vmaxb`, `vmaxn` und `dedup` muss das `e2ds` Flag gesetzt sein! - `reflink` funktioniert nur auf btrfs/xfs Filesystemen (z.B. via NFS 4.2) - `reflink` funktioniert **nicht** auf ext4! ## Verzeichnisstruktur Die Rolle erstellt folgende Verzeichnisse: ``` /srv/dockerdata/copyparty/ ├── config/ │ └── copyparty.conf # Generierte Konfigurationsdatei ├── data/ │ ├── public/ # Standard-Volume (immer erstellt) │ └── upload/ # Upload-Volume (immer erstellt) ├── hists/ # Datenbank, Thumbnails, etc. └── docker-compose.yml ``` **Wichtig:** - Die Verzeichnisse `public` und `upload` unter `/srv/dockerdata/copyparty/data/` werden automatisch erstellt. - Andere Verzeichnisse unter `/srv/dockerdata/copyparty/` werden ebenfalls automatisch erstellt. - Verzeichnisse außerhalb (z.B. `/mnt/torrent`) müssen bereits existieren! ## Features Die Rolle konfiguriert copyparty mit folgenden **globalen Features**: - **Filesystem-Indexierung** (`e2dsa`): Scannt und indexiert alle Dateien in allen Volumes beim Start - **No-Robots** (`no-robots`): Verhindert Suchmaschinen-Indexierung global - **Usernames** (`usernames`): Login erfordert Username+Passwort (verhindert gleiche Passwörter) - **Zeroconf + QR** (`z, qr`): LAN-Discovery (mDNS/SSDP) und QR-Code für einfachen Zugang vom Handy - **Shares-Feature** (`shr: /shr`): Ermöglicht das Erstellen von temporären Links in der UI - **WebDAV, FTP, TFTP**: Alle Protokolle sind verfügbar (werden nicht automatisch aktiviert) **Per-Volume Features** können individuell für jedes Volume aktiviert werden: - **Media-Tags** (`e2ts`): Indexiert Metadaten aus Audio/Video-Dateien (Artist, Album, Title, etc.) - **Deduplication** (`dedup`, `reflink`, `hardlinkonly`): Spart Speicherplatz bei identischen Dateien - `reflink`: Nur für btrfs/xfs (am sichersten, CoW) - `hardlinkonly`: Für alle Filesysteme (Dateien teilen Inodes) - Default: Symlinks (muss mit e2dsa verwaltet werden) ## Zugriff Nach dem Deployment ist copyparty erreichbar unter: - **Direktzugriff:** `http://:3923` - **Via Reverse-Proxy:** `https://` (wenn konfiguriert) - Volumes sind unter `/volumename` verfügbar, z.B. `http://:3923/music` - **Login:** Username und Passwort erforderlich (z.B. `admin` + `secure_password`) - Passwort kann auch als `username:password` im Username-Feld eingegeben werden ## Reverse-Proxy Setup Wenn copyparty hinter einem Reverse-Proxy (Caddy, nginx, etc.) läuft: ```yaml copyparty: port: 3923 reverse_proxy: true xff_src: "192.168.1.10" # IP des Reverse-Proxy accounts: - user: admin password: "secure" volumes: - path: /srv/dockerdata/copyparty/data/public accs: - r: "*" A: admin ``` **Caddy-Konfiguration** (auf dem Reverse-Proxy Host): ```yaml caddy: sites: - name: copyparty template: proxy_open external_url: https://files.example.com internal_url: http://backend-server:3923 ``` **Was passiert:** - Caddy terminiert TLS und setzt automatisch `X-Forwarded-For` Header - copyparty liest die echte Client-IP aus diesem Header - `xff_src` verhindert IP-Spoofing (nur dieser Proxy wird vertraut) - `rproxy: 1` bedeutet es gibt nur eine IP im Header (direkter Proxy) **Wichtig:** - Ohne korrekte `xff_src` Konfiguration sieht copyparty alle Requests vom Proxy als von der Proxy-IP kommend - Dies kann zu falschen Bans führen und Rate-Limiting funktioniert nicht richtig ## Selektive Ausführung ```bash # Nur copyparty deployen ansible-playbook site.yml --tags copyparty # Alle Docker-Rollen ansible-playbook site.yml --tags docker ``` ## Erweiterte Konfiguration ### Mehrere Volumes vom selben Benutzer mit unterschiedlichen Features ```yaml copyparty: accounts: - user: filemaster password: "secure123" volumes: - path: /mnt/nas/movies # btrfs via NFS accs: - r: "*" A: filemaster flags: - e2ds - e2ts # Media-Tags für Videos - dedup - reflink # CoW auf btrfs - path: /mnt/nas/music # btrfs via NFS accs: - r: "*" A: filemaster flags: - e2ds - e2ts # Media-Tags für Musik - dedup - reflink # CoW auf btrfs - path: /srv/data/books # ext4 (kein reflink!) accs: - r: "filemaster" # Nur filemaster kann zugreifen flags: - e2ds # KEIN reflink, weil ext4 das nicht unterstützt ``` ### Write-Only Upload-Ordner (ohne Dedup auf ext4) ```yaml volumes: - path: /srv/dockerdata/copyparty/data/dropbox accs: - w: "*" # Jeder kann uploaden rm: admin # Nur Admin kann lesen und Dateien verschieben flags: - e2ds # Indexing für potenzielle Limits # KEIN dedup/reflink auf ext4 ``` ### Kombination: Media + Upload + Reverse-Proxy ```yaml copyparty: port: 3923 reverse_proxy: true xff_src: "192.168.1.10" # IP des Reverse-Proxy accounts: - user: admin password: "secure" volumes: - path: /mnt/media # btrfs via NFS 4.2 name: media accs: - r: "*" A: admin flags: - e2ds - e2ts - dedup - reflink # CoW auf btrfs - sicher und effizient - path: /srv/dockerdata/copyparty/data/upload # ext4 name: upload accs: - w: "*" A: admin flags: - e2ds - vmaxb: 50g - lifetime: 864000 # KEIN reflink auf ext4! ``` ## Troubleshooting ### Volume-Mount-Fehler Wenn copyparty mit Fehlern startet, überprüfe: 1. Existiert das Verzeichnis auf dem Host? 2. Hat der Docker-Container Zugriff auf das Verzeichnis? ```bash docker logs copyparty ``` ### Permissions-Probleme ```bash # Permissions für Volume-Verzeichnisse checken ls -la /mnt/torrent ls -la /srv/dockerdata/copyparty/data/public ``` ## Links - [copyparty GitHub](https://github.com/9001/copyparty/) - [copyparty Dokumentation](https://github.com/9001/copyparty/blob/hovudstraum/README.md) - [Docker Hub](https://hub.docker.com/r/copyparty/ac) - [copyparty Accounts & Volumes Doku](https://github.com/9001/copyparty/blob/hovudstraum/README.md#accounts-and-volumes)