You don't have to run one yourself. Some networks like Rizon provide bouncers themselves. Otherwise there are a few third-party-hosted bouncers like chat.sr.ht. But yes, self-hosting is always an option.
That said, having set up self-hosted ZNC (the de facto IRC bouncer) last week, it's a damn PITA if you want the same experience as what you get with newer messaging stacks.
First, the default operation of ZNC is to replay the last lines from the client buffer regardless of whether your client already has them or not. To work around that, you have to install the non-built-in "playback" module. The OS I run ZNC on (Debian 11) doesn't package that, so it needs to be compiled from source with znc-buildmod, which means installing a C++ compiler. This also makes auto-updates harder because the module has to be recompiled out-of-band every time the ZNC package is updated by the package manager.
Second, the playback module uses a ZNC-specific capability which your client may not have support for, in which case you'd need a script to work with it.
Third, the playback module only operates in terms of server time. Your client asks the bouncer to replay all messages since timestamp T, where T is presumably the timestamp of the last message you received from the bouncer before the disconnect. But because of precision errors, this ends up replaying the message you received at time T, the one you already have, so your client ends up getting that message duplicated.
If you were to artificially add some milliseconds to T to work around that, you could miss out on any other messages that did occur in that time, so that's not a good solution. (Message loss is worse than duplicate messages, especially when the point of setting up a bouncer is to not have message loss.)
IRCv3 doesn't fix it either. The IRCv3 version of the CAP allows the server (bouncer) to implement either server time or "message IDs" or both. Message IDs would indeed solve this problem, but since server time is an option you can expect bouncers to only implement server time and not message IDs. Indeed, from a brief glance at the ZNC playback module code it seems ZNC itself makes it hard to add message ID support to that module, and even the new soju bouncer only supports server time.
Another alternative to the classic bouncers is using quassel or weechat-relay.
Both have the core running on a server and both use a custom protocol to the clients, which allows you to have multiple different clients (desktop, mobile) connected with synchronized history.
Of course this limits the choice of available client software by a lot, but it's an option to keep in mind.
If you want to package and maintain znc-playback for Debian, I'll be happy to sponsor it for sid and backports. I expect that we can come up with some mechanism to solve the auto-update issue, although I notice there aren't any third-party ZNC plugins in Debian yet, so we will probably need to talk to the Debian ZNC maintainer about it. Either go through the normal procedure for new packages and I'll notice the request for sponsor mail, or just contact me directly.
That said, having set up self-hosted ZNC (the de facto IRC bouncer) last week, it's a damn PITA if you want the same experience as what you get with newer messaging stacks.
First, the default operation of ZNC is to replay the last lines from the client buffer regardless of whether your client already has them or not. To work around that, you have to install the non-built-in "playback" module. The OS I run ZNC on (Debian 11) doesn't package that, so it needs to be compiled from source with znc-buildmod, which means installing a C++ compiler. This also makes auto-updates harder because the module has to be recompiled out-of-band every time the ZNC package is updated by the package manager.
Second, the playback module uses a ZNC-specific capability which your client may not have support for, in which case you'd need a script to work with it.
Third, the playback module only operates in terms of server time. Your client asks the bouncer to replay all messages since timestamp T, where T is presumably the timestamp of the last message you received from the bouncer before the disconnect. But because of precision errors, this ends up replaying the message you received at time T, the one you already have, so your client ends up getting that message duplicated.
If you were to artificially add some milliseconds to T to work around that, you could miss out on any other messages that did occur in that time, so that's not a good solution. (Message loss is worse than duplicate messages, especially when the point of setting up a bouncer is to not have message loss.)
IRCv3 doesn't fix it either. The IRCv3 version of the CAP allows the server (bouncer) to implement either server time or "message IDs" or both. Message IDs would indeed solve this problem, but since server time is an option you can expect bouncers to only implement server time and not message IDs. Indeed, from a brief glance at the ZNC playback module code it seems ZNC itself makes it hard to add message ID support to that module, and even the new soju bouncer only supports server time.