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