A privacy-focused XMPP desktop client with per-account proxies and enforced call relaying.
Today, 2026-03-13, at 13:13, we confirmed that Siproxylin installation makes successful calls on Windows
Same code base compiled with GStreamer, gRPC amd Glib works perfectly fine. It is still in the branch, being carefully prepared for a release. The build of C++ part with dependencies on 8 cores and 16GB of RAM takes approximately 4-5h; I will package it to avoid this really complex task.
Since v0.0.21 incoming calls from Conversations.im started working.
The change was switching from Go Pion to C++, however I believe that Pion could have worked either, it was more of a bug on my code side than Pion issues. Anyway, now the AppImage shrank as C++ binary is significanlty smaller, so I plan to stick with C++ and keep Go code just for historical reasons.
# Install GStreamer libraries:
# gir1.2-gstreamer-1.0, gstreamer1.0-alsa, gstreamer1.0-gl, gstreamer1.0-gtk3, gstreamer1.0-libav, gstreamer1.0-nice, gstreamer1.0-pipewire, gstreamer1.0-plugins-bad, gstreamer1.0-plugins-base, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, gstreamer1.0-plugins-good, gstreamer1.0-plugins-ugly, gstreamer1.0-pulseaudio, gstreamer1.0-tools, gstreamer1.0-x, gstreamer1.0-x, libgstreamer-gl1.0-0, libgstreamer-plugins-bad1.0-0, libgstreamer-plugins-base1.0-0, libgstreamer-plugins-base1.0-0, libgstreamer-plugins-base1.0-dev, libgstreamer1.0-0, libgstreamer1.0-0, libgstreamer1.0-dev, libgtk-4-media-gstreamer, qtgstreamer-plugins-qt5, libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev libgrpc++
# Install Qt6:
# libqt6*
# Install hunspell if you want the spell checker
# Build C++ call service
cd drunk_call_service
make clean
make
make install
cd -
# Get Python dependencies
python3 -m venv venv
venv/bin/pip install -r requirements.txt
# Run the app
venv/bin/python main.pyDownload: Latest AppImage (tested on: Debian 12-13, Arch)
Run:
chmod +x Siproxylin-*.AppImage
./Siproxylin-*.AppImage- ✅ Text messaging - 1-to-1 and group chats (MUC)
- ✅ OMEMO encryption - End-to-end encrypted messaging (XEP-0384)
- ✅ Audio calls - Works with Dino and Conversations.im
- ✅ File attachments - HTTP Upload (XEP-0363)
- ✅ Message features - Reactions, replies, corrections, threading
- ✅ Per-account proxy - SOCKS5/HTTP proxy support with zero IP leaks
- ✅ Account registration - XEP-0077 with CAPTCHA support (XEP-0158)
- ✅ Multi-language spell checking - en, de, ru, lt, es, ro, ar
- ✅ Themes - Multiple color schemes (matters at night!)
- ⏳ Video calls - In progress
- ⏳ Screen sharing - Planned
- ⏳ Windows/macOS - Linux-only for now
Yes, it's another XMPP client. But hear me out.
Someone will say "meh, just another XMPP client". Most won't even look here because they simply don't know, nor do they care. They have WhatsApp, some have Signal, most have some popular social media app which supports messaging. "Privacy" is becoming a buzzword without meaning, "self-hosted" sounds like a name of a sex toy, while "convenient" is anything that helps pollute our informational space with another set of filter-applied selfies right now.
But I like XMPP. Since the first time I heard about it back when Google enabled web-driven chat on Gmail, I saw it as a big step forward from IRC. XMPP smelled like progress driven by (let's be honest here) a pretty ugly set of XMLs, but hey, we got a federated network with an extensible standard. And then, after some years, I accidentally ran into Conversations.im and tried their app. I realized that there are more people nostalgic enough to resurrect and enhance something that was great from the beginning and just shamefully forgotten. This flipped my brain: we have e2e encryption, we can self-host isolated or become part of a larger network, and there are people who actually use it and apps that do it. Cool!
But after a short while I realized we don't really have a solid desktop application. Sure there is Dino, and it's good — it even respects HTTPS_PROXY variables to bring you some anonymity — but it lacks many features I'd love to see in an e2e messenger. So I quickly drafted in my head the missing features:
- Proxy per account - Route different identities through different networks
- Enforced call relays - No IP leaks during calls
- Multi-platform - Works everywhere (Linux first, others coming)
- Contacts grouped by account - Clean separation of identities
- Configurable logging - Debug when needed, silent when not
- Local files encryption - Protect config, DB, attachments, logs (available via gocryptfs, see --dot-data-dir option)
- Notifications privacy - Hide text/sender when needed
- Standard classic menus - No twisted GNOME labyrinth, simple File->Add, Edit->Account, intuitive right-click context menus, etc.
- Spell checker - Actually works (Dino's didn't for me)
- Theme support - Dark mode matters, well most of the current design sucks, but themes are separated and easy to tweak.
- Screen sharing - Coming soon
- Group calls - Future goal
Making a fully working client, for a single person who's not even an experienced developer (I'm an infra guy), would take a year. So I was carrying this idea with me, looking for existing options to start with, and then someone asked me: did you try AI-assisted development? I decided to give it a try (honestly I didn't believe we'd get far), but here we go: the version I'm releasing today became functional after 7 weeks of intense work and a considerable amount of non-halal beverages. Russian-Irish mix, which I happen to be, comes with certain cultural obligations... Hence the app core is created using "brewery," "barrels," and "taps" - metaphors wherever they fitted.
No matter how badly I want this app to be perfect, I'm afraid it's not there yet. After all these hours spent testing, code reviewing, and three massive refactoring iterations, I still have some doubts and occasionally find issues. Even the most motivated developer using best-in-class AI assistance can start drifting into quick patches when dealing with a larger codebase, and we're talking about 100+ Python files and 35,000+ lines of code. It took 7 weeks, which means 5k lines per week, or 1,000 lines per day.
So definitely use it with caution, and please don't be shy about reporting issues, I bet you'll find quite a few.
- Platform: Currently Linux-only (Windows/MacOS support planned)
- Unread counters: Sometimes pops up after app restart, investigating
- Unclear process of MUC membership: There is lack of information on how members-only MUC are handled, currently it relies on the mercy of auto-approve by server
Report bugs: GitHub Issues
When I was a kid, I enjoyed chemistry. Pyroxylin (smokeless powder/nitrocellulose) popped into my mind. I was sipping continuously during development, and I badly wanted proxies. Pyroxylin → SipProxyLin. Made sense to me.
Python + SQLite + Qt6 + slixmpp + gRPC + GStreamer (webrtcbin) + C++
I'll confess: I borrowed Dino's DB structure to start, just to not reinvent the wheel. The XMPP part spins around slixmpp. Here slixmpp is wrapped into a client called DrunkXMPP (./drunk_xmpp/), which handles asynchronous signaling for protocol events and implements all required methods for client interactions.
Jingle was difficult. Siproxylin uses XEP-0353 from slixmpp, however XEP-0166, XEP-0167, XEP-0176, XEP-0320 have been added to ./drunk_call_hook/ on the fly. XEP-0158 (media support for CAPTCHA) also wasn't there and had to be added. A few bugs popped up when dealing with slixmpp — runtime patches have been made for them (see ./drunk_xmpp/slixmpp_patches).
DrunkXMPP is loaded by Siproxylin Core (./siproxylin/core/), which connects with the Qt6-based GUI (./siproxylin/gui/). When a call comes in, Jingle requests are passed to CallBridge (./drunk_call_hook/), which translates them into gRPC requests and passes them to the Go service (./drunk_call_service/), which uses GStreamer to handle WebRTC, tricke-ICE, TURN, and audio (video and screen sharing coming soon).
Siproxylin starts as a single Python process with two threads: one for keeping a heartbeat between CallBridge and the Go service, and another for everything else. The Go service is started by CallBridge at application startup. Each component writes logs (defaults to INFO, can be disabled via global and per-account settings), and the app has a built-in log viewer for convenience.
Supported XEPs: 29 total (see Help → About in the app)
If you run python3 main.py (use venv with requirements.txt), the app runs in "dev" mode and creates:
./sip_dev_paths/
├── cache/ # Avatars
├── config/ # User preferences
├── data/ # Database, attachments
└── logs/ # main.log, xmpp-protocol.log, account-{id}-app.log, drunk-call-service.log
For production, two command-line parameters are available:
--xdg- Respects~/.configand~/.localpaths--dot-data-dir- Uses old-fashioned~/.siproxylinwith everything inside
AppImage default: --dot-data-dir because of three reasons:
- Easy to navigate (convenience)
- Easy to delete (security)
- Easy to mount as gocryptfs or equivalent (privacy)
Beware of potential leaks during the calls! After migration from Go / Pion to C++ / GStreamer I noticed that proxies are not applied on all sockets. The work is ongoing an the issues will be fixed.
Siproxylin supports proxies per account. Even the registration wizard asks if you'd like to use a proxy. SOCKS5 and HTTP are both supported, and if you register an account using a proxy, it's automatically saved with that account's settings.
- Don't want to expose your private XMPP server? Add Wireguard directly on your server and use wireproxy with the SOCKS5 socket.
- Sensitive group chats - Joining a group about stuff like flat earth, alcoholism or BDSM for beginers? Install Tor and point Siproxylin to its SOCKS5 socket.
- Corporate network - Only way out is via Squid proxy? Route your account through the HTTP proxy and enjoy texts and calls.
Leak testing: I tested with tcpdump and found zero IP leaks — it seems to be solid
That includes the calls, proxy settings are passed via gRPC and applied in the Go code
Siproxylin supports audio calls with most XMPP clients supporting trickle-ICE. We had issues with incoming calls from Conversations but it seems to be solved since switching from Go/Pion to C++/GStreamer/webrtcbin
Siproxylin forces calls to be relayed to avoid IP leaks. The call window shows technical details: advertised IP addresses of both ends and the connection choice. Siproxylin requests TURN details from your XMPP server (XEP-0215), and if not received, should fall back to the public Jami TURN servers (fallback wasn't properly tested).
Download the latest AppImage from Releases:
chmod +x Siproxylin-*.AppImage
./Siproxylin-*.AppImageSee docs/BUILD.md for build instructions.
Siproxylin is dual-licensed:
For open source projects and personal use, Siproxylin is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
This means:
- ✅ Free to use, modify, and distribute
- ✅ Perfect for open source projects
- ✅ Use in personal/non-commercial projects
⚠️ Network use = distribution - If you run Siproxylin as a service (SaaS, internal corporate tool, etc.), you must open source your entire application under AGPL-3.0
"Free to use for free software. Wanna commercialize it? Let's talk business."
Contributions are welcome! By contributing, you agree that your contributions will be licensed under AGPL-3.0.
Note: This is a solo project built with AI assistance. Progress may be sporadic, but issues are tracked and appreciated.
Found a bug? Have a feature request? Open an issue
- Python 3.11+
- PySide6 (Qt6) - LGPL-3.0
- slixmpp - MIT
- GStreamer - LGPL-2.1+
- gRPC - Apache-2.0
- cryptography - BSD-3-Clause/Apache-2.0
All dependencies are compatible with AGPL-3.0.
As this is a side solo project there is no offcial support, however you can try your luck in a channel siproxylin@conference.conversations.im.







