summaryrefslogtreecommitdiff
path: root/Omni/Cloud/Cal.nix
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-03-21 23:34:31 -0400
committerBen Sima <ben@bsima.me>2025-04-11 12:30:29 -0400
commita95231a35106193a68d29a48e5dc23999232af9f (patch)
tree9e443c5985d5c0d99b5da09f3ba1b82d77510765 /Omni/Cloud/Cal.nix
parentae011f80c7e85d23edc185876e3d026704221454 (diff)
Factor out radicale and fix shared calendar
Having this in its own file makes it easier to work on. Then I was able to figure out (with lots of debugging and trial+error with Claude) the actual permissions settings that result in a shared calendar. It's very fiddly because it is matching on usernames and directories using regex, and I think it's order-dependent as well.
Diffstat (limited to 'Omni/Cloud/Cal.nix')
-rw-r--r--Omni/Cloud/Cal.nix81
1 files changed, 81 insertions, 0 deletions
diff --git a/Omni/Cloud/Cal.nix b/Omni/Cloud/Cal.nix
new file mode 100644
index 0000000..3c3c46c
--- /dev/null
+++ b/Omni/Cloud/Cal.nix
@@ -0,0 +1,81 @@
+{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;
+ '';
+ };
+}