{config, ...}: let ports = import ./Ports.nix; rootDomain = config.networking.domain; in { networking.firewall.allowedTCPPorts = [ports.radicale]; services.radicale = { enable = true; rights = { # Allow reading root collection for authenticated users root = { user = ".*"; collection = ""; permissions = "R"; }; # Allow reading and writing principal collection (same as username) principal = { user = ".+"; collection = "{user}"; permissions = "RW"; }; # Make shared collection visible as part of root listing shared_principal = { user = ".+"; collection = "shared"; permissions = "RW"; }; # Allow reading and writing calendars and address books that are direct # children of the principal collection calendars = { user = ".+"; collection = "{user}/[^/]+"; permissions = "rw"; }; # Allow ben full access to shared/ben, repeat this for other shared # calendars as needed. ben_shared = { user = "ben"; collection = "shared/ben(/.+)?"; permissions = "rwD"; }; # Must be authed to write to the shared collections shared_write = { user = ".+"; collection = "shared/[^/]+"; permissions = "rw"; }; # Allow any user to read the shared collection shared_read = { user = ".+"; collection = "shared(/.*)?"; permissions = "r"; }; }; settings = { server = { hosts = [ "0.0.0.0:${toString ports.radicale}" "[::]:${toString ports.radicale}" ]; }; auth = { type = "htpasswd"; htpasswd_filename = "/etc/radicale/users"; htpasswd_encryption = "plain"; }; }; }; services.nginx.virtualHosts."cal.${rootDomain}" = { locations."/".proxyPass = "http://localhost:${toString ports.radicale}"; forceSSL = true; useACMEHost = rootDomain; extraConfig = '' proxy_set_header X-Script-Name ""; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass_header Authorization; ''; }; }