Moving my band chat from Discord to Snikket XMPP running on a Raspberry Pi in my house
Just under three months ago, I spun up an XMPP chat server on a 2011 Raspberry Pi so my band could, hopefully, ditch Discord. I know it was three months ago because I have the date 5/13 burned in my brain as the date the SSL certificates will expire, attempt to renew, and almost certainly fail. So I have some maintenance to do around now before that happens. I've been meaning to write about setting this up since I did it, and it's always nice to have a little distraction from impending doom. Now that's what I call productive procrastination!
I chose Snikket because it seemed like a good entrypoint to XMPP and comes with a server and mobile apps, which was helpful for my smartphone-inclined bandmates. In typical XMPP fashion, the server works with other clients—I use Dino—with the caveat that the Snikket mobile apps only expose features that the Snikket server supports. That makes my life as a system administrator easier. I don't have to explain why some features don't work, because anything in the Snikket apps works with the Snikket server. Coming from a VC-funded, proprietary app like Discord, I wanted the transition to feel as smooth as possible to minimize resistance to change. All in all, it's proven to a be a solid choice. We eclipsed the one-week trial period I suggested without anyone batting an eye, despite a few annoyances and bugs encountered along the way.
The other big reason I chose Snikket was its compatibility with the old Raspberry Pi 2B v1.1 that's been collecting dust in my box of ancient tech relics. I carefully excavated the Pi from the mound of unused devices with all the lithium batteries I'm avoiding doing anything about until it's too late, and got to work.
Speaking of avoiding things, one of the coolest things I learned that I had been avoiding learning was how the internet works. I still can't tell you what all the layers are and what they're for, but I can tell you with low-to-medium confidence that your router establishes a good old fashioned Local Area Network (LAN). By connecting the Pi to the router I could ssh into the Pi from my desktop computer, which was also connected to the router, without needing to let anyone else on the internet ssh into the Pi. Which is good, because if you're not careful, ssh is a great way to let hackers hack a device, and for all I know, other devices on the same LAN.
But hang on, if my bandmates are supposed to connect to the server to chat, how can they do that without also being on my LAN? Enter port forwarding. Port forwarding is a weird name to say, "let people connect to a device in my LAN without their device being connected to my LAN". Which is a long-winded way of saying "let people connect their computer to my computer from afar". Oversimplifications which might not be accurate aside, port forwarding is configuring a router to forward stuff going to a specific port to go to that same port on a different device on the LAN. XMPP needs to use a few ports, which Snikket documentation helpfully lists out, so I logged into my router's admin panel and configured those ports to forward to the Pi. Port forwarding is only part of the story to let my bandmates talk to the Pi server. The other part is DNS.
One of the fun parts about making websites is picking a domain name. Once we picked one, it was time for a less fun part: DNS. From my domain registrar's control panel, I added the DNS records Snikket needed. I also added a couple others with the intention of hosting our yet-to-be-made band website on the Pi, coexisting with Snikket behind a reverse proxy. A reverse proxy is a little bit like a port forwarding router. It takes incoming requests and routes them to a specific port based on things like the hostname of the request. For example, requests to the hostname chat.mywebsite.com were set to go to the Snikket service, while requests to www.mywebsite.com were set to go to the web service over standard HTTP(S) ports 80 and 443.
With port forwarding and DNS set up, I installed Snikket on the Pi. I had actually done a test installation prior to adding the reverse proxy and it was smooth as butter. The Snikket documentation is excellent and the provided Docker images and Compose file made configuring and deploying a breeze. When I added the reverse proxy to the mix, things got a little hairy. Snikket requires SSL certificates, which get set up automatically. But with Snikket behind the reverse proxy, it took a lot of trial and error to get the certificates. I eventually got the SSL certificates working. Unfortunately, in my excitement I hastily reworked the reverse proxy configuration so that both Snikket and web services were fully functional, but failed to document the configuration that worked to get SSL certificates. So now I have the great fun of figuring that out again.
There are two improvements I'd like to make to this system. One, painfully obviously, is figuring out the reverse proxy configuration that works for both SSL certificates and functional services. If I can't figure this out, I might remove the reverse proxy and host the website on a separate server. The second improvement is dynamic DNS. A detail I left out regarding DNS is that it's common for residential ISPs such as Verizon to assign a dynamic IP address to your router. This means from time to time, Verizon changes the IP address. That IP address is used in the DNS records so that requests to *.mywebsite.com go to the right place: my router. So when Verizon changes my IP address, the DNS records are outdated and neither Snikket nor our website work. The workaround so far has been to update the records manually whenever Verizon changes my IP address, which fortunately doesn't seem to happen often. In the three months of running this setup, I've only had to update DNS records to a new IP address twice. It's also not hard to do when it does happen, and only results in an hour or so of downtime. This could probably be mitigated by adjusted the time-to-live (TTL) value. If we were chatting more or had any website visitors, an hour of downtime would not be ideal. For now it's tolerable, especially considering how infrequently it occurs.
And that's a wrap! Thanks for reading. I hope this was helpful or inspiring if you're considering ditching Discord and looking for a low-cost, open-source, and decentralized solution. If you have any questions or comments, feel free to send me an email and I might make some more posts about my experiences. Let's take back the internet together.