{ config, pkgs, ... }: let calendarAggregate = pkgs.writers.writePython3 "calendar-aggregate.py" { libraries = [ pkgs.python3Packages.icalendar ]; } '' from pathlib import Path from icalendar import Calendar combined = Calendar() for path in Path("/var/lib/radicale/collections").rglob("*.ics"): with open(path, "rb") as f: cal = Calendar.from_ical(f.read()) for component in cal.walk("VEVENT"): combined.add_component(component) with open("/srv/www/calendar/all.ics", "wb") as f: f.write(combined.to_ical()) ''; in { imports = [ ../../services/nginx.nix ../../services/prometheus-nginx.nix ]; systemd = { services.calendar-aggregate = { script = "${calendarAggregate}"; serviceConfig.Type = "oneshot"; }; timers.calendar-aggregate = { wantedBy = [ "timers.target" ]; timerConfig = { OnBootSec = "5m"; OnUnitActiveSec = "5m"; }; }; }; services = { radicale = { enable = true; rights = { readonly = { user = ""; collection = ".*"; permissions = "r"; }; principal = { user = ".*"; collection = "{user}"; permissions = "rw"; }; collections = { user = ".*"; collection = "{user}/.*"; permissions = "rw"; }; }; settings = { server = { hosts = [ "[::1]:5232" ]; validate_user_value = "strict"; validate_path_value = "strict"; }; auth = { type = "htpasswd"; htpasswd_filename = config.age.secrets.radicale-htpasswd.path; htpasswd_encryption = "bcrypt"; }; storage.filesystem_folder = "/var/lib/radicale/collections"; headers."Access-Control-Allow-Origin" = "*"; }; }; nginx.virtualHosts."dav.${config.networking.domain}" = { default = true; quic = true; kTLS = true; forceSSL = true; enableACME = true; locations = { "/" = { proxyPass = "http://[::1]:5232"; recommendedProxySettings = true; extraConfig = '' proxy_pass_header Authorization; ''; }; "/all.ics".root = "/srv/www/calendar"; }; }; }; }