Self-host your own digital island
1{ pkgs, config, lib, ... }: 2 3with lib; 4let 5 cfg = config.eilean; 6 domain = config.networking.domain; 7 passwdDir = "/var/lib/radicale/users"; 8 passwdFile = "${passwdDir}/passwd"; 9 userOps = { name, ... }: { 10 options = { 11 name = mkOption { 12 type = types.str; 13 readOnly = true; 14 default = name; 15 }; 16 passwordFile = mkOption { 17 type = types.nullOr types.str; 18 }; 19 }; 20 }; 21in { 22 options.eilean.radicale = { 23 enable = mkEnableOption "radicale"; 24 users = mkOption { 25 type = with types; attrsOf (submodule userOps); 26 default = { }; 27 }; 28 }; 29 30 config = mkIf cfg.radicale.enable { 31 services.radicale = { 32 enable = true; 33 settings = { 34 server = { 35 hosts = [ "0.0.0.0:5232" ]; 36 }; 37 auth = { 38 type = "htpasswd"; 39 htpasswd_filename = passwdFile; 40 htpasswd_encryption = "bcrypt"; 41 }; 42 storage = { 43 filesystem_folder = "/var/lib/radicale/collections"; 44 }; 45 }; 46 }; 47 48 systemd.services.radicale = { 49 serviceConfig.ReadWritePaths = [ "/var/lib/radicale" ]; 50 preStart ='' 51 if (! test -d "${passwdDir}"); then 52 mkdir "${passwdDir}" 53 chmod 755 "${passwdDir}" 54 fi 55 56 umask 077 57 58 cat <<EOF > ${passwdFile} 59 60 ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: 61 "$(${pkgs.apacheHttpd}/bin/htpasswd -nbB \"${name}\" \"$(head -n 2 ${value.passwordFile})\")" 62 ) cfg.radicale.users)} 63 EOF 64 ''; 65 }; 66 67 services.nginx = { 68 enable = true; 69 recommendedProxySettings = true; 70 virtualHosts = { 71 "cal.${domain}" = { 72 forceSSL = true; 73 enableACME = true; 74 locations."/" = { 75 proxyPass = "http://localhost:5232"; 76 }; 77 }; 78 }; 79 }; 80 81 eilean.dns.enable = true; 82 eilean.services.dns.zones.${domain}.records = [{ 83 name = "cal"; 84 type = "CNAME"; 85 data = "vps"; 86 }]; 87 }; 88}