Vor zwölf Jahren habe ich hier beschrieben, wie der Familienkalender meiner Frau in die ownCloud gewandert ist. Vorher gab es ein Büchlein in ihrer Tasche und einen großen Kalender an der Wand, und beide waren selten einer Meinung. Seitdem liegen Termine und Kontakte unter eigener Kontrolle, und alles Mögliche greift darauf zu. Nur ein Gerät hat es nie getan: das Telefon am Schreibtisch.
Das hat mich lange nicht gestört, bis ich es einmal ausprobiert habe. Ein Anruf kommt rein, auf dem Bildschirm steht eine nackte Rufnummer, und ich sitze vor einem Rechner, auf dem 144 Kontakte mit genau dieser Nummer liegen. Das ist albern.
Mein sipgate-Konto ist alt. Wie alt genau, wusste ich selbst nicht mehr. In diesem Blog taucht sipgate erstmals im August 2009 auf, und 2015 habe ich beim Abschalten meiner alten 01801-Nummer geschrieben, ich hätte sie „vor ? 13 ? Jahren“ bekommen. Die Fragezeichen waren schon damals meine. Also habe ich einfach den Support gefragt, ausdrücklich nur aus Neugier. Die Antwort kam am nächsten Morgen: angemeldet am 30. April 2005. Da sipgate 2004 mit den Basis-Accounts gestartet ist, bin ich also aus dem ersten Jahr dabei, gut zwanzig Jahre. Dass sich jemand die Mühe macht, so eine reine Neugier-Frage überhaupt zu beantworten, finde ich bemerkenswert.
Was ich wollte, war jedenfalls nichts Exotisches: ein Softphone unter Linux, das an diesem Konto hängt und beim Klingeln in mein eigenes Adressbuch schaut statt in gar keines. Dazu am besten noch die Kalender, damit ich beim Telefonieren sehe, ob der Termin, über den gerade gesprochen wird, überhaupt frei ist.
Der Weg dahin war überraschend kurz, aber die naheliegenden Kandidaten führen alle in die Irre. Deshalb schreibe ich beides auf.
Warum der naheliegende Weg nicht funktioniert
Der erste Reflex ist, das Softphone des Anbieters zu nehmen. Bei sipgate steht dazu im eigenen Hilfecenter, dass es unter Linux nicht installiert, sondern nur ausgeführt wird, dass es kein 64 Bit kann, also weder auf x86_64 noch auf ARM läuft, und dass der Support in Kürze eingestellt wird und keine Updates mehr kommen. Das ist eine erfrischend ehrliche Ansage, hilft aber nicht weiter.
Der zweite Reflex heißt Linphone, und das ist die Falle, in der ich am längsten gesteckt habe. Linphone kann CardDAV wirklich, die Funktionen stecken vollständig in der Bibliothek liblinphone. Nur hat die Oberfläche der paketierten Version keinen einzigen Schalter dafür, dort gibt es bei den Adressbuchquellen ausschließlich LDAP. In die Oberfläche kam CardDAV erst mit Version 6.0, und die liegt in keinem einzigen Linux-Distributionsrepo. Ein Blick auf Repology zeigt für linphone-desktop gerade einmal AUR bei 6.1.2, alles andere hängt bei 4.x oder 5.x, Debian unstable bei 5.2.6. Der Hersteller selbst liefert für Linux ausschließlich AppImages aus, ohne veröffentlichte Prüfsumme und ohne eingebettete Update-Information. Wer sich nicht um Aktualisierungen kümmern will, ist damit an der falschen Adresse.
Blink fällt aus, weil es zwar ein ausgereifter SIP-Client ist, beim Adressbuch aber nur Google Contacts kennt. GNOME Calls wäre technisch ein Weg, ist aber für Telefone gebaut und als Desktop-Softphone dünn.
Nebenbei: die Frage wird gestellt. Im Nextcloud-Forum steht ein Thread vom August 2025 mit genau diesem Wunsch, und der Fragesteller verweist darin auf einen älteren Thread zum selben Thema, der ohne Ergebnis blieb. Die Antworten waren eine kommerzielle Lösung und ein Umweg über die FRITZ!Box. Was ich jetzt benutze, kam in keinem der beiden vor.
Die Kette, die tatsächlich funktioniert
Der Trick besteht darin, dass das Softphone gar nicht mit der Nextcloud sprechen muss. Unter Linux gibt es dafür längst eine Zwischenschicht, und die heißt evolution-data-server. Sie ist auf so gut wie jedem Desktop installiert, weil Kalender- und Kontaktanwendungen darauf aufsetzen. Und sie spricht CalDAV und CardDAV von Haus aus.
Nextcloud
|
+-- GNOME Online Accounts Provider owncloud, CalDAV und CardDAV
|
+-- evolution-data-server
|
+-- Softphone (GOnnect, Adressbuchquelle "EDS")
Das Softphone ist damit austauschbar, und die Zugangsdaten der Cloud liegen genau an einer Stelle statt in jeder Anwendung noch einmal. Als Softphone nehme ich GOnnect von der GONICUS GmbH, einem Open-Source-UC-Client, den es als Flatpak auf Flathub gibt. Er kann als Adressbuchquellen LDAP, CardDAV, CSV und eben evolution-data-server.
Dass er über Flathub kommt, war für mich das Ausschlusskriterium gegen alles andere. Ein AppImage müsste ich von Hand nachziehen, ein Flatpak läuft mit flatpak update einfach mit.
Schritt 1: Die Nextcloud in die Online-Konten hängen
Unter Linux Mint findest du das unter „Online-Konten“, dahinter steckt gnome-online-accounts-gtk. Dort legst du ein Konto vom Typ Nextcloud an, trägst die Adresse deiner Instanz, deinen Benutzernamen und ein App-Passwort ein und hakst Kalender und Kontakte an.

Nimm dafür wirklich ein App-Passwort aus den Sicherheitseinstellungen deiner Nextcloud und nicht dein normales. Falls du später den Zugriff eines einzelnen Rechners zurückziehen willst, geht das damit mit einem Klick, ohne dass du überall sonst neue Zugangsdaten eintragen musst.
Wenn es geklappt hat, sieht die Konfiguration hinterher so aus:
[Account account_1735125820_0] Provider=owncloud Uri=https://cloud.example.org/remote.php/webdav CalendarEnabled=true CalDavUri=https://cloud.example.org/remote.php/dav ContactsEnabled=true CardDavUri=https://cloud.example.org/remote.php/dav FilesEnabled=true AcceptSslErrors=false
Auf AcceptSslErrors=false lohnt ein Blick. Steht dort true, akzeptiert die Verbindung kaputte Zertifikate, und dann kannst du dir den ganzen Rest sparen.
Ab hier haben alle Programme auf dem Rechner Zugriff, die evolution-data-server nutzen. Das Softphone ist nur eines davon.
Schritt 2: GOnnect installieren
flatpak install flathub de.gonicus.gonnect
Das war der ganze Schritt. Rund 310 MB, und beim ersten Start liest GOnnect die Kontakte und Kalender aus evolution-data-server ein, ohne dass du irgendwo CardDAV konfigurieren müsstest. Bei mir standen im Protokoll direkt beim ersten Start:
gonnect.app.addressbook: Found 1 active configurations for address book plugin "EDS" gonnect.app.feeder.EDSAddressBookFeeder: Loaded 144 contact(s) of source "Kontakte"
Ja, und die Kalender ebenfalls, inklusive der Familienkalender aus dem Beitrag von 2014. Die stehen dann rechts im Fenster, unter den Favoriten und neben der Anrufliste.

Und die Suche oben im Fenster greift auf dasselbe Adressbuch zu. Ein paar Buchstaben genügen, dann steht der Treffer da, und darüber die Quelle, aus der er kommt: eds-contacts. Genau darum ging es. Kein Zwischenschritt, kein Export, keine zweite Kontaktverwaltung im Softphone.

Schritt 3: Das sipgate-Konto eintragen
Hier kommt die Eigenheit von GOnnect, an der man sich einmal stoßen muss: es gibt keinen Einrichtungsassistenten und keinen Einstellungsdialog für das SIP-Konto. Der Client ist dafür gebaut, in Firmen ausgerollt zu werden, und erwartet deshalb eine fertige Konfigurationsdatei. Die liegt hier:
~/.var/app/de.gonicus.gonnect/config/gonnect/99-user.conf
Unter der Haube arbeitet PJSIP, entsprechend sehen die Schlüssel aus. Das hier ist die vollständige Konfiguration, die bei mir mit einem sipgate-Basis-Konto läuft:
[account0] userUri=sip:1234567e0@sipgate.de registrarUri=sip:sipgate.de proxies=sip:sip.sipgate.de:5061;transport=tls auth=auth0 transport=tls srtpUse=mandatory srtpSecureSignaling=1 verifyServer=true caListFile=/etc/ssl/certs/ca-certificates.crt contactRewriteMethod=always-update [auth0] scheme=Digest username=1234567e0 realm=sipgate.de type=digest data=HIER_DER_MD5_HASH
1234567e0 ist deine SIP-ID aus dem sipgate-Konto, nicht deine Rufnummer.
Wichtig ist die Zeile type=digest. Du kannst dort auch dein Passwort im Klartext hinterlegen, aber das musst du nicht. SIP authentifiziert sich per Digest, und der Hash dafür ist schlicht MD5(Benutzer:Realm:Passwort). Den rechnest du dir selbst aus:
printf '%s' '1234567e0:sipgate.de:DEIN_SIP_PASSWORT' | md5sum
Das Ergebnis kommt hinter data=. Danach setzt du die Datei noch auf chmod 600.
Damit steht dein Passwort nicht mehr wörtlich in einer Konfigurationsdatei. Ehrlich bleiben muss man trotzdem: der Hash ist für diesen Realm genauso viel wert wie das Passwort selbst, wer ihn hat, kann sich anmelden. Der Gewinn ist ein anderer. Falls du dieses Passwort irgendwo sonst auch verwendest, liegt es hier nicht lesbar herum.
Ein Detail, das mich beim Ändern der Datei erwischt hat: GOnnect muss dabei beendet sein. Der Client schreibt die Datei beim Beenden aus dem Speicher zurück und überschreibt deine Änderungen sonst kommentarlos.
Was der Desktop davon merkt
Zwei Dinge sind mir erst im Betrieb aufgefallen, und beide gehören zu der Sorte, die man nicht vermisst, solange man sie nicht kennt.
Wenn ein Anruf reinkommt oder du selbst einen startest, pausiert die laufende Medienwiedergabe von selbst. Das YouTube-Video im Firefox hält an, der Musikplayer ebenso, und nach dem Auflegen läuft beides weiter. Dahinter steckt MPRIS, die Schnittstelle, über die sich Medienplayer unter Linux fernsteuern lassen. Für mich war das der Moment, in dem sich das Ding nicht mehr nach Fremdkörper angefühlt hat, sondern nach Teil des Desktops.
Das zweite: sip:-Links auf Webseiten funktionieren. Ein Klick darauf öffnet die Anwendung und wählt sofort. Der Client trägt sich beim Installieren als Handler für dieses Schema ein, du musst dafür nichts konfigurieren.
Verschlüsselung, und warum eine Zeile davon die wichtigste ist
sipgate kann das seit über zwanzig Jahren. Heise hat am 1. Februar 2006 über „sipgate-Crypto“ berichtet, damals schon mit TLS für die Signalisierung und SRTP für die Sprache bis zum Festnetz-Gateway. Das Problem war seinerzeit, dass kaum ein Endgerät mitspielte, weshalb sipgate passende Hardware gleich mit anbot. Zwanzig Jahre später kann es jedes Gerät, und trotzdem steht es in kaum einer Anleitung.
Eingeschaltet ist es nämlich nicht von allein. Die Standardkonfiguration läuft über UDP und unverschlüsselt, du musst zwei Dinge selbst ändern: sip.sipgate.de als Proxy eintragen und die Signalisierung von UDP auf TLS umstellen.
Interessant ist, was danach passiert. In der sipgate-Dokumentation steht dieser Satz:
Bei verschlüsselter Signalisierung erfordern wir ebenfalls, dass die Sprachdaten verschlüsselt werden. Ist diese Einstellung falsch, so werden Anrufe mit Fehler „488 No Acceptable here“ abgewiesen.
Sobald die Signalisierung verschlüsselt ist, erzwingt sipgate also auch die Sprachverschlüsselung. Das ist die angenehmste Sorte Sicherheitsentscheidung, weil sie einem die Wahl abnimmt. srtpUse=mandatory ist damit nicht meine Strenge, sondern schlicht das, was die Gegenseite ohnehin verlangt. Ein optional würde dir nichts retten, der Anruf käme trotzdem nicht zustande, nur mit einer verwirrenderen Fehlermeldung.
Kleine Randbemerkung, weil es mich gefreut hat: gefunden habe ich diesen Satz nicht durch Klicken im Hilfecenter, sondern hier:
curl https://help.sipgate.de/llms-full.txt
Das ist das komplette Hilfecenter als eine Textdatei, rund 350 KB, gedacht als maschinenlesbare Fassung für Sprachmodelle. Zum Durchsuchen mit grep ist das erheblich angenehmer als jede Suchmaske, und es beantwortet Fragen, die im Menü drei Ebenen tief liegen. Ich habe so etwas seit einer Weile selbst auf diesem Blog liegen, und es ist schön zu sehen, dass es sich langsam herumspricht.
Die eigentlich wichtige Zeile ist eine andere, und die steht in keinem Beispiel, das ich gefunden habe:
verifyServer=true caListFile=/etc/ssl/certs/ca-certificates.crt
Die Voreinstellung von PJSIP ist verifyServer=false. Übersetzt heißt das: die Verbindung wird verschlüsselt, aber es wird nicht geprüft, mit wem. Jedes beliebige Zertifikat wird angenommen. Gegen jemanden, der auf dem Weg sitzt und die Verbindung übernimmt, ist so eine Verschlüsselung wertlos, weil er einfach sein eigenes Zertifikat vorzeigt. Erst mit diesen zwei Zeilen wird geprüft, und zwar gegen den Zertifikatsspeicher deines Systems.
Nachmessen statt glauben
Dass die Registrierung mit code=200 klappt, sagt über die Verschlüsselung nichts. Also nachsehen. Der einfachste Test zeigt, wohin die Verbindung überhaupt geht:
ss -tnp | grep 5061
ESTAB [2001:db8::23]:49705 -> [2001:ab7::18]:5061 users:(("gonnect",pid=48721))
ESTAB [2001:db8::23]:38171 -> [2001:ab7::1a]:5061 users:(("gonnect",pid=48721))
Port 5061, und auf Port 5060 liegt nichts mehr, es läuft also kein Klartext-SIP nebenher. Meine eigene Adresse habe ich ersetzt, die Gegenstellen sind echt. Ein whois auf 2001:ab7::/36 nennt die netzquadrat GmbH, und sip.sipgate.de löst genau auf diese Adressen auf. Das Zertifikat dazu:
openssl s_client -connect sip.sipgate.de:5061 -servername sip.sipgate.de </dev/null | openssl x509 -noout -subject -issuer
subject=CN = sip.sipgate.de issuer=C = US, O = DigiCert Inc, CN = GeoTrust TLS RSA CA G1
Wenn du schon dabei bist, kannst du auch gleich nachsehen, was die Gegenstelle überhaupt anbietet. Das geht wie bei jedem anderen TLS-Dienst:
nmap -Pn -p 5061 --script ssl-enum-ciphers sip.sipgate.de
TLSv1.2: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A ... TLSv1.3: TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A cipher preference: server least strength: A
Das Ergebnis ist erfreulich unaufgeregt. Es gibt nur TLS 1.2 und 1.3, die alten Versionen habe ich gegengeprüft und beide werden abgelehnt. Alles bewertet mit A, der Server bestimmt die Reihenfolge, und das Zertifikat ist RSA mit 4096 Bit. Ausgehandelt wird in der Praxis TLS 1.3 mit TLS_AES_256_GCM_SHA384 über X25519.
Ein Schönheitsfehler bleibt: unter TLS 1.2 stehen auch noch reine TLS_RSA_WITH_*-Suiten in der Liste, also solche ohne Forward Secrecy. Weil der Server die Reihenfolge vorgibt und ECDHE oben steht, bekommt sie in der Praxis niemand, sie sind der Rückfall für Uraltgeräte. Schöner wäre es trotzdem ohne.
Bleibt die Sprache. Während des Gesprächs zeigt GOnnect oben links ein grünes Schild, das ist die Verschlüsselungsanzeige.

Ein Symbol ist aber nur ein Symbol. Was dahinter passiert, protokolliert der Client erst, wenn du ihn darum bittest:
[logging] level=6
Danach einmal telefonieren und ins Protokoll schauen. Was du sehen willst, sind zwei Dinge. Erstens die Aushandlung, in der beide Seiten RTP/SAVP sprechen statt RTP/AVP:
m=audio 4000 RTP/SAVP 96 97 98 99 3 0 8 9 100 102 103 101 104 105 106 a=crypto:1 AES_256_CM_HMAC_SHA1_80 inline:S3ybiZ92TCP4JuPe48V... a=crypto:3 AES_CM_128_HMAC_SHA1_80 inline:r2RXvwQ31ewSR0xEvuZX...
Und zweitens die Bestätigung, welche der angebotenen Suiten die Gegenstelle genommen hat:
srtp0x... SRTP started, keying=SDES, crypto=AES_256_CM_HMAC_SHA1_80
SRTP status: Active Crypto-suite: AES_256_CM_HMAC_SHA1_80
sipgate hat also die stärkste der vier angebotenen Varianten gewählt. Erst damit weiß ich, dass srtpUse=mandatory wirklich gegriffen hat und nicht still auf „aus“ stand. Nebenbei: mehr als diese vier hat der Client gar nicht im Angebot, alle mit AES im Counter-Modus und HMAC-SHA1. AES-GCM kennt diese PJSIP-Variante nicht, an der Stelle ist also nichts zu optimieren.
Und dann dreh den Loglevel wieder runter. In den Zeilen oben stehen die SRTP-Schlüssel im Klartext, die haben in einer Protokolldatei nichts verloren.
Was dabei nicht verschlüsselt ist
Hier muss ich die gute Laune etwas bremsen, denn „alles verschlüsselt“ wäre falsch.
Verschlüsselt ist die Strecke zwischen deinem Rechner und sipgate. Das ist viel wert, es schützt gegen dein WLAN, gegen fremde Netze und gegen deinen Provider, und zwar sowohl den Gesprächsinhalt als auch die Information, wen du wann anrufst.
Es endet aber bei sipgate. Rufst du ein Mobiltelefon an, läuft der Anruf ab dort durch das normale Telefonnetz, und dort gibt es keine Verschlüsselung. Dazu kommt, dass SDES als Schlüsselaustausch bedeutet, dass die Schlüssel im Signalisierungsweg stehen, den sipgate liest. Der ist zwar durch TLS gegen Dritte geschützt, aber sipgate kennt deine Schlüssel und könnte mithören. Etwas anderes steht auch gar nicht zur Wahl: ZRTP und DTLS-SRTP kommen in der gesamten sipgate-Dokumentation kein einziges Mal vor.
Echte Ende-zu-Ende-Verschlüsselung bekommst du nur zwischen zwei Clients, die direkt miteinander eines von beidem sprechen. Mit einem Anbieter dazwischen ist das, was hier läuft, die Obergrenze. Das ist kein Grund, es zu lassen, man sollte es nur nicht mit etwas verwechseln, das es nicht ist.
Kleinkram, der auffällt
Zwei Meldungen im Protokoll haben mich kurz beunruhigt und sind harmlos. Failed to connect to pipewire instance erscheint, weil das Flatpak den PulseAudio-Socket hat und auf pipewire-pulse zurückfällt. Die Geräte werden danach sauber gesetzt, der Ton funktioniert. Die Fehler des JitsiConnector betreffen die Videokonferenz-Anbindung und nicht das Telefonieren.
Was tatsächlich nicht geht: globale Tastenkürzel. Cinnamon bringt das Portal org.freedesktop.portal.GlobalShortcuts nicht mit, Anrufe per Tastendruck annehmen fällt damit aus. Alles andere, auch das Symbol im Systemabschnitt der Kontrollleiste, funktioniert.
Fazit
Der Teil, den ich für den schwierigen hielt, war der einfachste. Ich musste am Softphone überhaupt kein CardDAV einrichten, weil evolution-data-server das längst erledigt hatte. Ein Konto in den Online-Konten, und die Kontakte und Kalender stehen jedem Programm auf dem Rechner zur Verfügung.
Aufwendig war stattdessen, überhaupt einen Client zu finden, der unter Linux gepflegt wird und den man ohne AppImage-Gefummel aktuell hält. Dass ausgerechnet ein Client, der eigentlich für den Rollout in Firmen gedacht ist und deshalb keinen Einrichtungsdialog hat, für einen einzelnen Basis-Account die beste Wahl ist, hätte ich vorher nicht erwartet.
Und der Familienkalender, der 2014 in die ownCloud gewandert ist, steht jetzt neben dem Telefon. Nur zwölf Jahre später.
Siehe auch:
- ownCloud und Kalender / Kontakte synchronisieren
- Ihre 01801-Rufnummer wird abgeschaltet, sipgate
- Davdroid ownCloud sync
Falls ihr das nachbaut und irgendwo hängen bleibt, oder falls ihr einen besseren Weg kennt, dann dürft ihr mich sehr gerne fragen.
