···3333 bufferMinutes = 15;
3434 minNoticeHours = 24;
3535 horizonDays = 28;
3636- # Free/busy is read from every calendar of this radicale user; requests
3737- # and bookings are written to its `calendar` collection (created on demand).
3636+ # lass/calendar is the only calendar (configs/radicale.nix): free/busy is
3737+ # read from it, and requests and bookings are mirrored into it, next to
3838+ # lass's own events and whatever Hermes adds.
3839 caldav = {
3940 url = "http://127.0.0.1:5232";
4041 user = "lass";
4141- calendar = "bookings";
4242+ calendar = "calendar";
4243 };
4344 # Local postfix (configs/mailserver.nix) accepts from localhost and DKIM-signs.
4445 smtp = {
···11+# clan vars generator for one radicale user: a random password plus its
22+# bcrypt htpasswd line. Imported by configs/radicale.nix for every user, and
33+# by the machines of users whose generator is shared (hermes on coaxmetal):
44+# a shared generator must be defined identically on every machine using it.
55+pkgs: user: {
66+ files."htpasswd-line" = { };
77+ files."password" = { };
88+ runtimeInputs = with pkgs; [
99+ apacheHttpd
1010+ coreutils
1111+ ];
1212+ script = ''
1313+ password=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
1414+ echo "$password" > "$out/password"
1515+ htpasswd -nbB ${user} "$password" > "$out/htpasswd-line"
1616+ '';
1717+}
···66 ...
77}:
88let
99- # lass: personal calendars; tools/book reads free/busy from them and writes
1010- # booking requests into lass/bookings.
1111- users = [
1212- "opencrow"
1313- "lass"
1414- ];
99+ # The one and only calendar, lass/calendar: own events (phone via DAVx⁵,
1010+ # calendar.lassul.us), booking requests and bookings mirrored by tools/book
1111+ # (configs/book.nix), and whatever Hermes adds. The rights below make it the
1212+ # only writable collection: nobody can create, delete or replace calendars.
1313+ calendar = "lass/calendar";
15141616- # Generate one var per user with random password
1515+ # lass: phone, web client and tools/book.
1616+ # hermes: the agent on coaxmetal (machines/coaxmetal/hermes.nix). Its var is
1717+ # shared (and declared there too) so coaxmetal's hermes-env can read the
1818+ # password without radicale running there.
1919+ users = [
2020+ "lass"
2121+ "hermes"
2222+ ];
2323+ sharedUsers = [ "hermes" ];
2424+2525+ # One var per user with a random password.
1726 userGenerators = lib.listToAttrs (
1827 map (user: {
1928 name = "radicale-${user}";
2020- value = {
2121- files."htpasswd-line" = { };
2222- files."password" = { };
2323- runtimeInputs = with pkgs; [
2424- apacheHttpd
2525- coreutils
2626- ];
2727- script = ''
2828- password=$(head -c 32 /dev/urandom | base64 | tr -dc 'a-zA-Z0-9' | head -c 24)
2929- echo "$password" > "$out/password"
3030- htpasswd -nbB ${user} "$password" > "$out/htpasswd-line"
3131- '';
2929+ value = import ./radicale-user-generator.nix pkgs user // {
3030+ share = lib.elem user sharedUsers;
3231 };
3332 }) users
3433 );
···8887 type = "internal";
8988 };
9089 };
9090+ # Whitelist, first match wins (sections are emitted sorted by name, hence
9191+ # the numeric prefixes); anything unmatched is denied. Every user reads and
9292+ # writes the events of the one calendar (d/o: but may not delete or
9393+ # overwrite the collection itself) and may only read the root and lass's
9494+ # home, which is enough for CalDAV discovery. No W/w anywhere else, so no
9595+ # MKCALENDAR and no auto-created principals.
9696+ rights =
9797+ let
9898+ anyUser = lib.concatStringsSep "|" users;
9999+ in
100100+ {
101101+ "10-calendar" = {
102102+ user = anyUser;
103103+ collection = calendar;
104104+ permissions = "rwdo";
105105+ };
106106+ "20-root" = {
107107+ user = anyUser;
108108+ collection = "";
109109+ permissions = "R";
110110+ };
111111+ "21-home" = {
112112+ user = anyUser;
113113+ collection = lib.head (lib.splitString "/" calendar);
114114+ permissions = "R";
115115+ };
116116+ };
91117 };
9211893119 systemd.services.radicale.serviceConfig = {