Files
zwischenablage-server/README.md
T
duffyduckandClaude Opus 5.5 af51ef5701 Release-Skript mit automatischer Versionierung und Docker-Builds
- scripts/release.py: Version (patch/minor/major) automatisch hochzaehlen, CHANGELOG
  abschliessen, committen, taggen; --build baut alle Pakete in Docker
- docker-build/: Build-Container fuer Windows (Wine + PyInstaller + Inno Setup),
  Linux und Android; Server-Image als docker-save-Archiv
- Versionsanzeige im Desktop-Client und in der Android-App
- Feste Android-Release-Signatur aus secrets/ (nicht im Git)
- Windows-Icon im Repo, damit der Wine-Build ohne Qt-Fenster auskommt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:45:17 +02:00

10 KiB
Raw Blame History

NetClip – Netzwerk-Zwischenablage

Eine gemeinsame Zwischenablage für alle eigenen Geräte (Windows, Linux, macOS, Android) – im Stil von CopyQ, aber über das Netzwerk. Text, Bilder und Dateien/Ordner werden übertragen: Wird auf dem einen Rechner ein Ordner kopiert (Strg+C im Explorer/Finder/Dolphin), fügt Strg+V auf dem anderen Rechner den Ordner in den gerade geöffneten Zielordner ein. Mit Verlauf, um Einträge später erneut einzufügen.

 PC (Windows)        Laptop (Linux)        Mac            Handy (Android)
      │                    │                 │                    │
      └──────── WebSocket + HTTPS (Ende-zu-Ende verschlüsselt) ───┘
                               │
                    NetClip-Server (Docker)
             verbindet nur Clients mit gleichem Token

Funktionsweise

  • Alle Geräte mit demselben Token bilden einen gemeinsamen „Raum“.
  • Der Token verlässt das Gerät nie. Aus ihm werden per PBKDF2 eine Raum-ID (sieht der Server) und ein AES-256-Schlüssel abgeleitet (sieht der Server nicht). Inhalte, Dateinamen, Vorschauen und Gerätenamen sind Ende-zu-Ende verschlüsselt – der Server speichert und verteilt nur undurchsichtige Blobs.
  • Der Server hält einen Verlauf pro Raum (Anzahl, Alter, Speicherplatz begrenzt, siehe .env).
  • Optional schützt ein SERVER_KEY den Server davor, von Fremden benutzt zu werden.

Server (Docker)

cp .env.example .env      # Werte anpassen (CERT_CN, CERT_SAN, SERVER_KEY, ...)
docker compose up -d --build

Die .env ist kommentiert. Die wichtigsten Schalter:

Variable Bedeutung
COMPOSE_PROFILES=nginx nginx als HTTPS-Proxy mit selbstsigniertem Zertifikat mitstarten. Leer lassen, wenn schon ein Reverse-Proxy vorhanden ist (siehe docs/eigener-reverse-proxy.md).
CERT_CN, CERT_SAN Hostname bzw. weitere Namen/IPs im Zertifikat
CERT_DAYS, CERT_RENEW_DAYS Gültigkeit; so viele Tage vor Ablauf wird beim Containerstart automatisch erneuert
CERT_KEY_BITS, CERT_COUNTRY … CERT_OU weitere Zertifikatsfelder
SERVER_KEY optionaler Zugangsschlüssel für den Server
MAX_CLIP_MB maximale Größe eines Clips
HISTORY_MAX, HISTORY_DAYS, ROOM_QUOTA_MB Verlaufsgrenzen pro Token
BIND_ADDR, PORT direkter HTTP-Port des Servers (mit nginx am besten BIND_ADDR=127.0.0.1)

Ändert man CERT_*-Werte, wird das Zertifikat beim nächsten Start neu erzeugt. Eigene Zertifikate: fullchain.pem + privkey.pem nach ./certs legen und ./certs/.selfsigned löschen.

Selbstsignierte Zertifikate in den Clients: entweder „TLS-Zertifikat prüfen“ abschalten (nur im eigenen Netz) oder im Desktop-Client unter „Zertifikat“ die certs/fullchain.pem des Servers hinterlegen.

Mit dem alten docker-compose (v1) funktioniert es genauso: docker-compose up -d --build.

Desktop-Client (Windows, Linux, macOS)

Python + Qt (PySide6), eine Codebasis für alle drei Systeme. Läuft im System-Tray.

  • Tray-Menü: die letzten 10 Einträge zum schnellen Einfügen, Verlauf, Pausieren, Einstellungen
  • Verlaufsfenster: Suche, Doppelklick/Enter = in die Zwischenablage, „Speichern unter …“, Löschen
  • Einstellungen: Server, Token (Erzeugen), Server-Schlüssel, Zertifikat, Gerätename, was synchronisiert wird, Größenlimits, Autostart
  • Verbindung teilen: QR-Code für Android · Exportieren (.netclip-Datei) · Importieren
  • Passwort-Manager-Einträge (KeePassXC, Bitwarden, 1Password …), die als „geheim“ markiert sind, werden nicht synchronisiert.

Empfangene Dateien/Ordner werden in den Cache entpackt (%LOCALAPPDATA%\NetClip\cache, ~/Library/Caches/NetClip, ~/.cache/netclip) und als Datei-Referenz in die Zwischenablage gelegt – Strg+V im Dateimanager kopiert sie dann an den gewünschten Ort. Der Cache wird nach keep_received_days (Standard 7 Tage) aufgeräumt.

Starten aus dem Quellcode

cd client-desktop
python -m venv .venv && . .venv/bin/activate      # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python -m netclip

Pakete bauen

PyInstaller baut immer für das System, auf dem es läuft – also einmal je Betriebssystem:

cd client-desktop
python build.py
System Ergebnis
Windows dist/NetClip/NetClip.exe, danach packaging/windows-installer.iss mit Inno Setup kompilieren → dist/NetClip-Setup-<version>.exe
macOS dist/NetClip.app und dist/NetClip-macos.zip (Menüleisten-App ohne Dock-Symbol)
Linux dist/NetClip-linux-x86_64.tar.gz mit install-linux.sh

Ausrollen

Kommandozeile (alle Systeme):

NetClip --configure-only --server https://clip.example.de --token XYZ [--server-key K] [--insecure] [--autostart]
NetClip --import verbindung.netclip
NetClip --show        # Verlauf der laufenden Instanz öffnen – z.B. auf ein Tastenkürzel legen

Vorgaben für alle Benutzer: eine config.default.json neben die Programmdatei legen, z.B. {"server": "https://clip.example.de", "token": "...", "verify_tls": false}. Sie wird beim ersten Start jedes Benutzers übernommen (Gerätename und Geräte-ID bleiben pro Gerät eindeutig).

  • Windows (GPO/Intune/PDQ): NetClip-<version>-windows-setup.exe /VERYSILENT /SUPPRESSMSGBOXES /SERVER=https://clip.example.de /TOKEN=xyz [/SERVERKEY=k] [/INSECURE=1] – schreibt config.default.json und richtet den Autostart für alle Benutzer ein.
  • Linux: sudo ./install-linux.sh --server https://clip.example.de --token xyz [--insecure]
  • macOS: NetClip.app nach /Applications kopieren, config.default.json nach NetClip.app/Contents/MacOS/ legen.

Hinweis: Wer den Token kennt, sieht die Zwischenablage. Ein gemeinsamer Token für mehrere Personen bedeutet eine gemeinsame Zwischenablage – pro Person/Team einen eigenen Token verwenden.

Plattform-Hinweise

  • Linux/X11: funktioniert direkt (Dolphin, Nautilus, Nemo, Thunar, Caja).
  • Linux/Wayland: Wayland gibt Programmen im Hintergrund keinen Zugriff auf die Zwischenablage. NetClip nutzt dann automatisch wl-clipboard (apt install wl-clipboard). Das funktioniert unter KDE Plasma und wlroots-Desktops (Sway, Hyprland), nicht unter GNOME – dort eine X11-Sitzung nutzen. Mit NETCLIP_BACKEND=qt lässt sich das Qt-Backend erzwingen.
  • macOS: beim ersten Start ggf. in den Systemeinstellungen „Öffnen“ bestätigen (unsigniert).
  • Windows: keine Besonderheiten; Dateien werden als „Kopieren“ (nicht „Ausschneiden“) eingefügt.

Android-Client

Kotlin, ab Android 8. Läuft als Vordergrunddienst mit dauerhafter Benachrichtigung.

  • Einrichten: Einstellungen → QR-Code vom PC scannen (Desktop: Einstellungen → QR-Code für Android) oder .netclip-Datei importieren. Ein netclip://-Link aus einer beliebigen QR-App öffnet ebenfalls direkt die Einstellungen.
  • Empfangen: Text und Bilder landen automatisch in der Zwischenablage. Dateien/Ordner kommen per Benachrichtigung mit Speichern (→ Download/NetClip/, Ordnerstruktur bleibt erhalten) und Teilen.
  • Senden: Android erlaubt Apps im Hintergrund nicht, die Zwischenablage zu lesen. Deshalb:
    • Button Zwischenablage senden in der App oder in der Benachrichtigung
    • Schnelleinstellungs-Kachel „Zwischenablage senden“ (Kacheln bearbeiten → hinzufügen)
    • Teilen → An NetClip senden aus jeder App (Text, Bilder, mehrere Dateien)
    • Text markieren → An NetClip senden im Auswahlmenü
  • Verlauf: antippen = in die Zwischenablage; lange drücken = Speichern, Teilen, Löschen.

Bauen

cd client-android
./gradlew assembleRelease     # app/build/outputs/apk/release/app-release.apk

Das Release-APK ist zum Testen mit dem Debug-Schlüssel signiert; für die Verteilung in app/build.gradle einen eigenen Keystore eintragen.

Release erstellen

Die Version steht zentral in der Datei VERSION. Neue Änderungen kommen laufend in CHANGELOG.md unter ## [Unreleased]. Ein Release:

python3 scripts/release.py              # 1.0.0 -> 1.0.1 (patch), committen + taggen
python3 scripts/release.py minor --build   # 1.0.1 -> 1.1.0 und alle Pakete bauen
python3 scripts/release.py --build-only    # aktuellen Stand nur bauen
git push --follow-tags

Das Skript schreibt die neue Version in Server, Desktop-Client, Windows-Installer und Android-App (versionName, versionCode +1) und macht aus [Unreleased] den neuen Versionsabschnitt. Mit --build wird ausschließlich in Docker gebaut (docker-build/), Ergebnis in releases/v<version>/:

Datei Inhalt
NetClip-<v>-windows-setup.exe Windows-Installer (Inno Setup, unter Wine gebaut)
NetClip-<v>-windows-portable.zip Windows ohne Installation
NetClip-<v>-linux-x86_64.tar.gz Linux (Debian 12 / glibc ≥ 2.36 und neuer)
NetClip-<v>.apk Android
netclip-server-<v>.tar.gz Server-Image für docker load -i … (offline verteilbar)
RELEASE-NOTES.md, SHA256SUMS Änderungen und Prüfsummen

macOS kann nicht in Docker gebaut werden – dafür auf einem Mac in client-desktop/ python build.py. Mit --targets windows,android lassen sich einzelne Pakete bauen.

Android-Signatur: Beim ersten Android-Build wird secrets/netclip-release.jks erzeugt (nicht im Git). Diesen Ordner sichern – ohne den Schlüssel lassen sich installierte Apps nicht mehr aktualisieren.

Tests

# Kompatibilität der Verschlüsselung Python <-> Kotlin
python tools/interop.py gen /tmp/interop
(cd client-android && ./gradlew testDebugUnitTest -Pinterop=/tmp/interop)
python tools/interop.py check /tmp/interop

Protokoll (für eigene Clients)

Methode Pfad Beschreibung
GET /healthz Status
GET /api/v1/info Server-Limits
GET /api/v1/rooms/{room}/clips Verlauf (id, ts, device, size, meta)
POST /api/v1/rooms/{room}/clips Body: 4 Byte Länge (BE) + Meta (Base64) + verschlüsselter Blob; Header X-Device
GET /api/v1/rooms/{room}/clips/{id}/blob verschlüsselten Inhalt laden
DELETE /api/v1/rooms/{room}/clips[/{id}] Verlauf leeren bzw. Eintrag löschen
WS /api/v1/rooms/{room}/ws?device=… Ereignisse hello, clip, deleted, cleared, devices

Mit SERVER_KEY ist bei allen /api/-Aufrufen Authorization: Bearer <key> nötig. Verschlüsselungsformat: siehe Kopf von client-desktop/netclip/crypto.py.