1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9
10let
11 cfg = config.services.xandikos;
12in
13{
14
15 options = {
16 services.xandikos = {
17 enable = mkEnableOption "Xandikos CalDAV and CardDAV server";
18
19 package = mkPackageOption pkgs "xandikos" { };
20
21 address = mkOption {
22 type = types.str;
23 default = "localhost";
24 description = ''
25 The IP address on which Xandikos will listen.
26 By default listens on localhost.
27 '';
28 };
29
30 port = mkOption {
31 type = types.port;
32 default = 8080;
33 description = "The port of the Xandikos web application";
34 };
35
36 routePrefix = mkOption {
37 type = types.str;
38 default = "/";
39 description = ''
40 Path to Xandikos.
41 Useful when Xandikos is behind a reverse proxy.
42 '';
43 };
44
45 extraOptions = mkOption {
46 default = [ ];
47 type = types.listOf types.str;
48 example = literalExpression ''
49 [ "--autocreate"
50 "--defaults"
51 "--current-user-principal user"
52 "--dump-dav-xml"
53 ]
54 '';
55 description = ''
56 Extra command line arguments to pass to xandikos.
57 '';
58 };
59
60 nginx = mkOption {
61 default = { };
62 description = ''
63 Configuration for nginx reverse proxy.
64 '';
65
66 type = types.submodule {
67 options = {
68 enable = mkOption {
69 type = types.bool;
70 default = false;
71 description = ''
72 Configure the nginx reverse proxy settings.
73 '';
74 };
75
76 hostName = mkOption {
77 type = types.str;
78 description = ''
79 The hostname use to setup the virtualhost configuration
80 '';
81 };
82 };
83 };
84 };
85
86 };
87
88 };
89
90 meta.maintainers = with lib.maintainers; [ _0x4A6F ];
91
92 config = mkIf cfg.enable (mkMerge [
93 {
94
95 systemd.services.xandikos = {
96 description = "A Simple Calendar and Contact Server";
97 after = [ "network.target" ];
98 wantedBy = [ "multi-user.target" ];
99
100 serviceConfig = {
101 User = "xandikos";
102 Group = "xandikos";
103 DynamicUser = "yes";
104 RuntimeDirectory = "xandikos";
105 StateDirectory = "xandikos";
106 StateDirectoryMode = "0700";
107 PrivateDevices = true;
108 # Sandboxing
109 CapabilityBoundingSet = "CAP_NET_RAW CAP_NET_ADMIN";
110 ProtectSystem = "strict";
111 ProtectHome = true;
112 PrivateTmp = true;
113 ProtectKernelTunables = true;
114 ProtectKernelModules = true;
115 ProtectControlGroups = true;
116 RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX AF_PACKET AF_NETLINK";
117 RestrictNamespaces = true;
118 LockPersonality = true;
119 MemoryDenyWriteExecute = true;
120 RestrictRealtime = true;
121 RestrictSUIDSGID = true;
122 ExecStart = ''
123 ${cfg.package}/bin/xandikos \
124 --directory /var/lib/xandikos \
125 --listen-address ${cfg.address} \
126 --port ${toString cfg.port} \
127 --route-prefix ${cfg.routePrefix} \
128 ${lib.concatStringsSep " " cfg.extraOptions}
129 '';
130 };
131 };
132 }
133
134 (mkIf cfg.nginx.enable {
135 services.nginx = {
136 enable = true;
137 virtualHosts."${cfg.nginx.hostName}" = {
138 locations."/" = {
139 proxyPass = "http://${cfg.address}:${toString cfg.port}/";
140 };
141 };
142 };
143 })
144 ]);
145}