If you've ever tried to move away from Google Calendar or iCloud and gone looking for a self-hosted replacement, you've probably run into the same wall: most "calendar server" projects are either abandoned, ridiculously heavy, or built for enterprise groupware suites you don't need. Radicale is the opposite of that. It's a small Python server that does exactly one job — store calendars and contacts and let your devices sync with them — and it runs comfortably in a container with a fraction of a CPU core.

This guide walks you through installing Radicale inside an LXC container on Proxmox VE, setting up authentication so it's not wide open to the world, and connecting a real calendar app to it. You don't need any prior experience with CalDAV or CardDAV. We'll explain those as we go.

What You Will Learn

  • What Radicale is and what CalDAV and CardDAV actually do
  • Why you'd want to run your own calendar server instead of using Google or Apple
  • How to create a lightweight LXC container for it in Proxmox VE
  • How to install and configure Radicale with password authentication
  • How to connect a calendar app on your phone or desktop
  • Common errors people hit on their first setup, and how to fix them

What Is This Feature?

Radicale is an open-source CalDAV and CardDAV server. CalDAV is the protocol your calendar app uses to sync events with a remote server — it's the same underlying standard Google Calendar and iCloud use, it's just not exclusive to them. CardDAV is the equivalent protocol for contacts. Any app that speaks CalDAV or CardDAV, which is almost every calendar and contacts app on iOS, Android, macOS, Windows, and Linux, can talk to Radicale without knowing or caring that it's not a big tech company's server.

Radicale itself stores everything as plain .ics and .vcf files on disk, organized into folders per user and per calendar. There's no database to manage, no background workers, and no web dashboard to get lost in. That simplicity is the whole appeal — and also the reason it's a good fit for a small LXC container rather than a full VM.

Why Would You Use It?

The honest answer is privacy and control. Your calendar contains more personal information than most people realize — where you'll be, who you're meeting, sometimes video call links and addresses. Handing all of that to a third party forever is a choice, not a requirement.

There's a practical angle too. If you're already running Proxmox VE for a homelab, adding one more lightweight LXC container costs you almost nothing in resources. Radicale idles at well under 50 MB of RAM and barely registers on the CPU graph. Compare that to standing up a full groupware server like Nextcloud just for calendar sync, and Radicale wins easily if calendars and contacts are all you actually need.

I'll be upfront about the tradeoff: Radicale has no web UI for browsing your events, no built-in sharing dashboard, and no mobile app of its own. You're relying entirely on your existing calendar and contacts apps to do the syncing. For most people that's fine, since those apps already work well. If you want a full self-hosted groupware suite with a browser-based calendar view, Radicale isn't that tool.

Prerequisites

Before you start, make sure you have the following:

  • A working Proxmox VE host, version 8.x or 9.x. This guide was written against Proxmox VE 9.2.
  • A Debian 12 (Bookworm) LXC template downloaded, or the ability to download one through the Proxmox web interface. Debian 13 doesn't have an official LXC template yet as of this writing, so Debian 12 is the safe choice for containers right now.
  • At least 512 MB of RAM and 2 GB of disk space set aside for the container. Radicale itself needs far less, but you want room for Debian's base packages and your growing collection of .ics files.
  • Root or sudo access on the Proxmox host, and basic comfort typing commands in a terminal.
  • A calendar or contacts app you plan to connect afterward — Thunderbird, Apple Calendar/Contacts, or the DAVx5 app on Android all work well.

Step-by-Step Tutorial

1. Create the LXC container

Log in to the Proxmox web interface and click Create CT in the top right. On the General tab, give it a hostname like radicale and set a root password. On the Template tab, pick the Debian 12 Standard template. If you don't see it listed, go to your storage, open the CT Templates tab, click Templates, and download debian-12-standard before continuing.

On the Disks tab, 2 GB is plenty to start — you can always grow it later. On the CPU tab, 1 core is enough. On the Memory tab, 512 MB is comfortable; Radicale won't come close to using it all, but Debian's base services need some headroom. On the Network tab, either let it grab an address from DHCP or assign a static IP on your vmbr0 bridge — a static IP is worth the extra step since you'll be pointing calendar apps at this container's address permanently.

Finish the wizard, start the container, and open its console from the Proxmox web UI (or SSH in once it has an IP).

2. Update the container and install Radicale

Once you're inside the container's shell, update the package list and install Radicale along with the tools you'll need for password authentication:

apt update
apt install -y radicale python3-passlib apache2-utils

python3-passlib and apache2-utils together give you the htpasswd command, which we'll use in a minute to create login credentials.

3. Configure Radicale

Open the main config file:

nano /etc/radicale/config

Replace its contents with something like this:

[server]
hosts = 0.0.0.0:5232

[auth]
type = htpasswd
htpasswd_filename = /etc/radicale/users
htpasswd_encryption = bcrypt

[storage]
filesystem_folder = /var/lib/radicale/collections

[rights]
type = owner_only

That hosts = 0.0.0.0:5232 line matters more than it looks. Radicale's default only listens on localhost, which means nothing outside the container — not even other devices on your LAN — can reach it. Binding to 0.0.0.0 tells it to accept connections from any network interface, so your phone and laptop can actually connect.

The owner_only rights setting means each user can only see and edit their own calendars and contacts, which is the sane default for a personal server. Save the file and exit (Ctrl+O, Enter, Ctrl+X in nano).

4. Create a user account

Radicale doesn't ship with any users by default, which is good — you don't want a blank server sitting open. Create your first login with:

htpasswd -B -c /etc/radicale/users yourname

It'll prompt you to type and confirm a password. The -c flag creates the file, so only use it the first time — if you add a second user later, drop the -c or you'll overwrite the file and lock out the first account. The -B flag uses bcrypt hashing, matching the htpasswd_encryption = bcrypt line from the config.

5. Enable and start the service

systemctl enable --now radicale
systemctl status radicale

You should see active (running) in green. If it says failed instead, skip ahead to the Troubleshooting section below.

6. Test it from a browser

From any device on your network, visit http://<container-ip>:5232. You'll get a login prompt — enter the username and password you created with htpasswd. A successful login shows a plain page confirming the server is reachable and lists the (currently empty) collections for your user. That's Radicale's entire web interface, and it's intentionally bare.

7. Connect a calendar app

Here's where it gets useful. In Thunderbird, install the Lightning calendar add-on if it's not already there, right-click in the calendar pane, choose New Calendar, then On the Network, and pick CalDAV. Enter http://<container-ip>:5232/yourname/calendar/ as the location and sign in with your credentials.

On Android, install DAVx5 from F-Droid or the Play Store, add an account, choose "Login with URL and username," and point it at http://<container-ip>:5232/yourname/. It'll discover your calendars and contacts automatically and offer to sync them into your device's native calendar and contacts apps.

On iOS or macOS, go to Settings > Calendar > Accounts > Add Account > Other > Add CalDAV Account, and use the same server address, username, and password.

Commands Explained

CommandWhat It Does
apt install radicale python3-passlib apache2-utilsInstalls the Radicale server plus the password-hashing tools needed for the htpasswd command.
htpasswd -B -c /etc/radicale/users yournameCreates a new user file with bcrypt-hashed passwords. Drop -c after the first user, or you'll wipe out existing accounts.
systemctl enable --now radicaleStarts Radicale immediately and configures it to launch automatically on every container boot.
systemctl status radicaleShows whether the service is currently running and prints its most recent log lines — your first stop when something's wrong.
journalctl -u radicale -fStreams Radicale's logs live, which is useful while you're testing a new client connection.

Common Errors

Connection refused when visiting port 5232. Almost always means the hosts line in /etc/radicale/config is still set to localhost instead of 0.0.0.0, or the service simply isn't running yet.

401 Unauthorized on every request. Double-check the username matches exactly what you passed to htpasswd (it's case-sensitive), and confirm htpasswd_encryption in the config matches the flag you used when creating the password — bcrypt in the config needs a password created with -B, not -5 or plain MD5.

Calendar client says "no calendars found." This usually happens on the very first login, before you've created any calendar yet. Most clients, including Thunderbird and DAVx5, will offer to create a default calendar on first connect. If yours doesn't, log in to the browser interface at your server's URL and look for a "create calendar" option there.

Permission denied errors in the logs. The radicale system user needs write access to /var/lib/radicale/collections. If you changed the storage path in the config, make sure the new directory is owned by the radicale user: chown -R radicale:radicale /path/to/folder.

Troubleshooting

Start with the basics: run systemctl status radicale and read whatever error it prints. Nine times out of ten the answer is right there in the last few lines.

If the service is active but nothing outside the container can reach it, check whether the container's firewall (if you enabled one in Proxmox) is blocking port 5232. Also confirm you're using the container's IP and not the Proxmox host's IP — it's an easy mix-up when you're used to accessing everything through port 8006.

If logins fail even with the right password, run journalctl -u radicale -f in one terminal and try logging in again from your client. Radicale logs each authentication attempt, and the log line will usually tell you exactly why it rejected the request — wrong hash type is the most common culprit.

If a client connects but syncing seems to stall or events don't appear on other devices, give it a minute. Most CalDAV clients sync on an interval rather than instantly, and DAVx5 in particular defaults to syncing every few hours unless you trigger a manual sync or shorten that interval in its settings.

Best Practices

Don't expose port 5232 straight to the internet. Radicale itself has no built-in TLS, so anything you send over an unencrypted connection — including your password on every login — is readable to anyone on the path. If you want remote access, put a reverse proxy with a real SSL certificate in front of it, or connect over a VPN like WireGuard or Tailscale instead.

Back up /var/lib/radicale/collections regularly. It's just flat files, so a simple vzdump backup of the whole container covers it, but don't skip it — there's no cloud copy to fall back on the way there would be with a hosted calendar.

Create a separate user account per person, not per device. Radicale's owner_only rights model keeps each account's data private by default, and sharing one login across multiple people makes it impossible to tell whose event is whose later.

Keep the container's Debian packages up to date with regular apt update && apt upgrade runs. Radicale is small, but it's still a network-facing service, and skipping updates on it is no different than skipping them anywhere else.

Frequently Asked Questions

Does Radicale work with the default Calendar and Contacts apps on iPhone?

Yes. Both support standard CalDAV and CardDAV accounts through Settings > Calendar > Accounts, with no extra app required.

Can multiple people share one Radicale server?

Yes, create a separate htpasswd account for each person. With the default owner_only rights setting, everyone's calendars stay private from each other.

Do I need a domain name to use Radicale?

No. A local IP address works fine for home network use. You'd only need a domain if you're putting it behind a reverse proxy for remote access with a proper SSL certificate.

Is Radicale actively maintained?

Yes, it's an active open-source project on GitHub with regular releases, and it's packaged directly in Debian's repositories.

How much storage will my calendars actually use?

Barely any. Even years of daily events and a few hundred contacts typically adds up to a few megabytes, since everything is stored as small plain-text .ics and .vcf files.

Conclusion

You now have a working calendar and contacts server that costs you almost nothing in container resources and keeps your schedule off someone else's servers. It's not going to replace Google Workspace for a business team, and it was never meant to. For a household, a small team, or just one person who wants their own calendar data, it's about as low-maintenance as self-hosting gets.

From here, the natural next steps are putting a reverse proxy in front of it for a proper HTTPS address, and adding it to your regular Proxmox backup schedule so a container mishap doesn't cost you five years of birthdays and appointments.