Some brief searches found a list of potential calendar servers, but the one which stood out to me was radicale. This CalDAV server is a nice simple Python server, with no dependencies besides Python itself. The default configuration is pretty well set up, with a few changes needed before you can start accessing your server.
The default port from which the CalDAV calendars are served is 5232, so I opened up that port on my router so that I could access the calendars from anywhere. I had to install a CalDAV app called CalDAV-sync-beta on my phone to be able to view my calendars on the native calendar widgets. The Lightning plugin for Thunderbird can load the radicale calendars by default. Adding them is a simple walk through the wizard, selecting the option to add a new calendar "On the network:", then choosing CalDAV as the type of calendar. The syntax for the calendar location is
http://your-home-server.com:5232/username/calendarnamereplacing your-home-server.com with either your server's IP address or its URI. Likewise, username should be the user who's launched the radicale daemon (I suggest this is not root). The calendarname value can be anything you like, but it's probably best to make it something memorable, or at least descriptive. For the CalDAV-sync-beta app on Android, the process is similar (Settings > Accounts & sync > Add account and select CalDAV. I found it easier to select "Manual mode" for configuring the calendar. The syntax for the calendar address is similar to the Lightning example above:
http://your-home-server.com:5232/username/except you'll notice I've omitted the calendarname value at the end. This is because CalDAV-sync-beta will search for all the calendars you have at that location and offer you the option of syncing them all or just certain ones. You can specify the full path as in the Lightning example if you know you will only want to connect to a single calendar on this server. The username value needs to contain a value, but you can omit the password (we have not set up a password protected calendar).
I have yet to manage to get radicale to accept a username and password, so the calendars are open to the public, which is probably something of which you should be aware.
Overall, it's been working well, and disentangling myself from at least one Google service is a start.