Ferry ist ein privater Kanal zwischen Maschinen, denen euer Team schon vertraut — einmal gepaart, per laut vorgelesener Phrase verifiziert, danach immer verfügbar. Schickt eine Datei, ein Geheimnis oder eine Nachricht direkt von einer Maschine zur anderen: keine Cloud, kein Konto, kein Server dazwischen, und nichts, das für immer in einem durchsuchbaren Chat-Verlauf liegen bleibt. Geheimnisse tragen ein TTL und löschen sich nach dem ersten Öffnen; jeder Austausch landet stattdessen in einem inhaltsfreien Audit-Log.
Es ist weder eine Chat-App noch AirDrop. Es ist der Kanal für das, was in keinem von beiden sein sollte — Zugangsdaten, Schlüssel, alles mit einem Ablaufdatum.
Kostenlos und Open Source, Apache-2.0. Ein Daemon, drei Zugänge: die ferry-Kommandozeile, eine VS-Code-Erweiterung, und eine Desktop-App.
# Maschine A ferry send laptop-b ./build/app.tar.gz ferry send laptop-b ./.env --burn # weg, sobald sie es öffnen
Pre-Release-Software
Das Übertragungs- und das Speicherformat ändern sich noch, und nichts davon wurde bisher extern auf Sicherheit geprüft. Probiert es aus, verlasst euch nicht darauf — und schickt nichts damit, dessen Verlust oder Leck euch stören würde. Kompatibilität zwischen Versionen wird erst ab 1.0 zugesichert.
Wozu
Eine Cloud-Ablage, eine Paste-Seite, Slack, E-Mail — das Geheimnis landet auf der Festplatte eines Dritten, wird indexiert, gesichert, und ist nur ein Datenleck, einen Export oder eine etwas zu gründliche Suche davon entfernt, von jemandem gefunden zu werden, der es nie hätte sehen sollen. Ferry macht nichts davon. Die Daten verlassen eure Maschine und kommen bei der anderen an, und das ist die ganze Reise. Es gibt keinen Server, in den man einbrechen kann, keinen Kanalverlauf zu löschen, nichts vorzuladen.
Der Kompromiss ist real
Ferry funktioniert nur, wenn beide Maschinen sich tatsächlich erreichen können — dasselbe Büronetz, ein Handy-Hotspot, ein VPN. Es gibt kein Relay und wird nie eines geben, also bahnt es sich keinen Weg durchs Internet für euch. Wenn ihr das braucht, ist Ferry nicht das richtige Werkzeug.
Klare Antworten
So funktioniert's
Beim ersten Start des Daemons erzeugt, nie im Klartext auf Platte geschrieben. Im OS-Schlüsselbund, oder in einer age-verschlüsselten Datei auf einer Maschine ohne Desktop.
Jemand liest einen kurzen Code laut vor; dann bestätigen beide Personen, dass auf beiden Bildschirmen dieselbe Verifizierungsphrase steht. Nie übersprungen, nie standardmäßig bestätigt, nie durch „diesem Netzwerk vertrauen“ umgangen.
Jede Verbindung beginnt mit einem Noise-Handshake, der jeden Schlüssel abweist, der nicht im Roster steht — bevor auch nur ein Befehl gelesen wird. Auf Transportebene durchgesetzt, nie nur im UI.
Dateien werden mit age versiegelt. Geheimnisse bekommen zusätzlich einen eigenen Wegwerfschlüssel, und „nach dem Lesen verbrennen“ zerstört den umhüllten Schlüssel, dann den Chiffretext, dann die Zeile — ein unterbrochener Burn hinterlässt unlesbaren Chiffretext, nie ein offenes Fragment.
TTL und Burn-after-Read werden ab der Zustellung nach der monotonen Uhr des Empfängers gemessen — nie nach einem vom Absender gelieferten Zeitstempel. Stimmen die Uhren nach einem Neustart nicht überein, läuft das Element ab.
Es hält fest, dass etwas passiert ist, wer, welches Element, wann, und mit welchem Ergebnis — und nichts über den Inhalt.
Drei Oberflächen
Der Daemon ist das Einzige, das das Peer-to-Peer-Protokoll spricht. Alles, was ihr anfasst, spricht mit ihm über einen lokalen Socket und nie direkt mit einer anderen Maschine.
Die Binaries ferry und ferry-daemon. ferry send, ferry receive, ferry pair, ferry activity — jeder Befehl startet den Daemon beim ersten Gebrauch selbst, außer ferry status, das immer nur die Wahrheit meldet.
Bringt ihren eigenen Daemon mit — nichts weiter zu installieren. Eine Seitenleiste und ein volles Panel, dieselbe App: Pairing, ein Posteingang, das Sende-Panel und ein Geheimnis-Editor, alles im Editor.
Eine Tauri-Hülle um dieselbe UI, für Maschinen ohne Editor im Spiel. Der Daemon steckt als eigenes Sidecar im Installer — nichts, was separat läuft.
Pairing lebt in der CLI, nicht im kopflosen Daemon — es braucht einen Menschen, der eine Verifizierungsphrase laut vorliest, und ein Schritt, der strukturell einen Menschen braucht, kann nicht in einem Prozess leben, der strukturell keinen erreichen kann.
Die Oberfläche
Eine React-App, drei Hosts. Hier mit Beispieldaten gezeigt.
Opt-in
Standardmäßig macht Ferry keinen Netzwerkaufruf außer einer direkten Übertragung an einen Peer. Zwei Funktionen können mit GitHubs API sprechen — und erst, nachdem ihr remote_features_enabled = true gesetzt und ein Konto verbunden habt. Vorher geht nichts an GitHub, Ferry fällt nie von selbst auf GitHub zurück, und es ausgeschaltet zu lassen kostet euch nur diese zwei Funktionen.
Ihr entscheidet, pro Element, eine bereits versiegelte Kopie als privates Gist auf GitHub abzulegen und jemandem den Link zu geben — für den Fall, dass ihr nicht ins selbe Netzwerk kommt. Der Kompromiss ist real: der Chiffretext verlässt eure Maschine, Burn-after-Read kann nicht mehr eingehalten werden, und GitHub erfährt den öffentlichen Schlüssel des Empfängers und die Dateigröße.
Weist Ferry auf eine Repo-Datei — jede URL, die ihr kontrolliert. Es holt das signierte Roster, zeigt euch, wer es signiert hat, und das genaue Diff der Hinzufügungen/Entfernungen, und importiert erst nach einer zweiten Bestätigung.
Jeder Austausch mit GitHub ist eine Entscheidung, die ihr für genau diese eine Aktion trefft. Keine Hintergrundsynchronisation, keine Telemetrie, kein automatischer Upload.
Architektur
Acht Rust-Crates in einem Cargo-Workspace. Abhängigkeiten zeigen immer nur in eine Richtung, also ist ein Verstoß ein Build-Fehler, keine Code-Review-Gewohnheit.
Abhängigkeitsrichtung
daemon / cli → core → net / store / crypto → proto
crates/proto Typen, Enums und Fehlercodes. Keine Logik. Die TypeScript-Bindings werden hieraus generiert; die CI schlägt bei jedem Diff fehl.
crates/core Jede Domänenentscheidung. Ohne Änderung vom Daemon, der CLI oder einem Test-Harness mit gefälschtem Netzwerk aus ansteuerbar — erwähnt nie einen Socket, eine Datenbank oder React.
crates/net · store · crypto Die Maschinerie: Framing und Transport, SQLite, die geprüften Primitive.
crates/daemon · cli Verdrahten alles und sonst nichts.
crates/remote Die einzige Crate, die weiß, dass HTTP existiert — hinter den standardmäßig deaktivierten GitHub-Funktionen.
Wie „fertig“ gemessen wird
Ferry führt ein Verifizierungsregister: eine Zeile pro nutzerseitigem Ablauf, und eine Zeile wird erst grün, wenn sie auf zwei echten Maschinen in einem echten Netzwerk durchlaufen wurde, einschließlich einer Trennung und Wiederverbindung, wo relevant. Code, der kompiliert, Unit-Tests, die durchlaufen, und das Zwei-Knoten-Harness, das durchläuft, verdienen alle eine niedrigere Note — sie sagen etwas über die Zustandsmaschine aus, nichts über einen Hotspot mit einem schlafenden Laptop dran.
Ein vollständiger Zyklus aus pairen → senden → verbrennen → öffnen läuft heute zwischen zwei Daemons auf einem Host, und zwischen zwei Containern in einem Multicast-Netzwerk in der CI. Jeder Ablauf wird so durchlaufen, bevor er als funktionierend gilt.
350+ Rust-Tests · Zwei-Knoten-Harness im Speicher · CI-Lauf mit zwei Containern · Builds für Windows + macOS
Beschaffung
Jeder Kanal unten kommt aus derselben getaggten Release. Wählt, was passt — eine Archivdatei laden, ein Image ziehen, oder selbst bauen.
.tar.gz (Linux/macOS) oder .zip (Windows) mit ferry + ferry-daemon drin, Ausführungsrecht intakt. Entpacken, auf den PATH legen.
docker pull ghcr.io/firaslamouchi21/ferry, gespiegelt auf Docker Hub. CLI und UI in einem Image, keine Rust- oder Node-Toolchain nötig.
.deb / .AppImage / .rpm unter Linux, .dmg unter macOS, .msi / ein Setup-.exe unter Windows — der Daemon steckt drin. Vorerst unsigniert; was das bedeutet.
Noch nicht im Marketplace — die .vsix eurer Plattform aus der Release nehmen und code --install-extension ferry-. Bringt ihren eigenen Daemon mit.
aus dem Quellcode bauen
git clone https://github.com/firaslamouchi21/Ferry cd Ferry cargo build --release -p ferry-daemon -p ferry cargo test --workspace bash testing/local-two-peer.sh
oder die Einzeiler-Variante: ./dev.sh baut Daemon + CLI und öffnet die UI dagegen — ohne Docker, ohne mehrere Terminals.
Ein erster Durchlauf
ferry daemon start ferry pair listen --name laptop-a ferry pair connect 192.168.1.20:53124 482913 --name laptop-b ferry send laptop-b ./.env --burn ferry receive list ferry receive open <item-id> --out ./.env
ferry send schreibt das Element nur in eine lokale Warteschlange; der Daemon liefert es aus, sobald die andere Maschine wieder da ist. Eine kopflose Maschine — ein CI-Runner, ein NAS — bewahrt ihre Identität in einer verschlüsselten Datei und wird vor dem Deployment von einem Laptop aus gepairt.
Mitwirken
Es gibt eine kurze Liste von Dingen, bei denen Ferry nicht nachgibt — nie ein Server, Roster beim Handshake durchgesetzt, Pairing immer ein Code plus eine bestätigte Phrase, echter Zustand für jedes Element, inhaltsfreies Audit-Log, Kryptografie nur aus geprüften Primitiven. Eine Änderung, die eines davon still bricht, wird zurückgeschickt, egal wie nützlich sie ist; alles andere ist willkommen.
Apache-2.0, und auch als paketierte Builds verkauft — Beiträge kommen unter denselben Bedingungen herein, mit einer DCO-Bestätigung (git commit -s).
Contact
Ein Bug, eine Idee, ein Sicherheitsbedenken, oder ihr wollt helfen, Ferry Richtung v2 zu bringen — das geht direkt in Firas' Posteingang, und ihr bekommt eine automatische Bestätigung. Für Sicherheitslücken die Adresse in SECURITY.md statt dieses Formulars nutzen.