1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 inherit (lib) types;
9 cfg = config.services.taskchampion-sync-server;
10in
11{
12 options.services.taskchampion-sync-server = {
13 enable = lib.mkEnableOption "TaskChampion Sync Server for Taskwarrior 3";
14 package = lib.mkPackageOption pkgs "taskchampion-sync-server" { };
15 user = lib.mkOption {
16 description = "Unix User to run the server under";
17 type = types.str;
18 default = "taskchampion";
19 };
20 group = lib.mkOption {
21 description = "Unix Group to run the server under";
22 type = types.str;
23 default = "taskchampion";
24 };
25 host = lib.mkOption {
26 description = "Host address on which to serve";
27 type = types.str;
28 default = "127.0.0.1";
29 example = "0.0.0.0";
30 };
31 port = lib.mkOption {
32 description = "Port on which to serve";
33 type = types.port;
34 default = 10222;
35 };
36 openFirewall = lib.mkEnableOption "Open firewall port for taskchampion-sync-server";
37 dataDir = lib.mkOption {
38 description = "Directory in which to store data";
39 type = types.path;
40 default = "/var/lib/taskchampion-sync-server";
41 };
42 snapshot = {
43 versions = lib.mkOption {
44 description = "Target number of versions between snapshots";
45 type = types.ints.positive;
46 default = 100;
47 };
48 days = lib.mkOption {
49 description = "Target number of days between snapshots";
50 type = types.ints.positive;
51 default = 14;
52 };
53 };
54 allowClientIds = lib.mkOption {
55 description = "Client IDs to allow (can be repeated; if not specified, all clients are allowed)";
56 type = types.listOf types.str;
57 default = [ ];
58 };
59 };
60
61 config = lib.mkIf cfg.enable {
62 users.users.${cfg.user} = {
63 isSystemUser = true;
64 inherit (cfg) group;
65 };
66 users.groups.${cfg.group} = { };
67 networking.firewall.allowedTCPPorts = lib.mkIf (cfg.openFirewall) [ cfg.port ];
68 systemd.tmpfiles.settings = {
69 "10-taskchampion-sync-server" = {
70 "${cfg.dataDir}" = {
71 d = {
72 inherit (cfg) group user;
73 mode = "0750";
74 };
75 };
76 };
77 };
78
79 systemd.services.taskchampion-sync-server = {
80 wantedBy = [ "multi-user.target" ];
81 after = [ "network.target" ];
82 serviceConfig = {
83 User = cfg.user;
84 Group = cfg.group;
85 DynamicUser = false;
86 ExecStart = ''
87 ${lib.getExe cfg.package} \
88 --listen "${cfg.host}:${builtins.toString cfg.port}" \
89 --data-dir ${cfg.dataDir} \
90 --snapshot-versions ${builtins.toString cfg.snapshot.versions} \
91 --snapshot-days ${builtins.toString cfg.snapshot.days} \
92 ${lib.concatMapStringsSep " " (id: "--allow-client-id ${id}") cfg.allowClientIds}
93 '';
94 };
95 };
96 };
97}