1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7let
8 cfg = config.services.duplicati;
9
10 parametersFile =
11 if cfg.parametersFile != null then
12 cfg.parametersFile
13 else
14 pkgs.writeText "duplicati-parameters" cfg.parameters;
15in
16{
17 options = {
18 services.duplicati = {
19 enable = lib.mkEnableOption "Duplicati";
20
21 package = lib.mkPackageOption pkgs "duplicati" { };
22
23 port = lib.mkOption {
24 default = 8200;
25 type = lib.types.port;
26 description = ''
27 Port serving the web interface
28 '';
29 };
30
31 dataDir = lib.mkOption {
32 type = lib.types.str;
33 default = "/var/lib/duplicati";
34 description = ''
35 The directory where Duplicati stores its data files.
36
37 ::: {.note}
38 If left as the default value this directory will automatically be created
39 before the Duplicati server starts, otherwise you are responsible for ensuring
40 the directory exists with appropriate ownership and permissions.
41 :::
42 '';
43 };
44
45 interface = lib.mkOption {
46 default = "127.0.0.1";
47 type = lib.types.str;
48 description = ''
49 Listening interface for the web UI
50 Set it to "any" to listen on all available interfaces
51 '';
52 };
53
54 user = lib.mkOption {
55 default = "duplicati";
56 type = lib.types.str;
57 description = ''
58 Duplicati runs as it's own user. It will only be able to backup world-readable files.
59 Run as root with special care.
60 '';
61 };
62
63 parameters = lib.mkOption {
64 default = "";
65 type = lib.types.lines;
66 example = ''
67 --webservice-allowedhostnames=*
68 '';
69 description = ''
70 This option can be used to store some or all of the options given to the
71 commandline client.
72 Each line in this option should be of the format --option=value.
73 The options in this file take precedence over the options provided
74 through command line arguments.
75 <link xlink:href="https://duplicati.readthedocs.io/en/latest/06-advanced-options/#parameters-file">Duplicati docs: parameters-file</link>
76 '';
77 };
78
79 parametersFile = lib.mkOption {
80 default = null;
81 type = lib.types.nullOr lib.types.path;
82 description = ''
83 This file can be used to store some or all of the options given to the
84 commandline client.
85 Each line in the file option should be of the format --option=value.
86 The options in this file take precedence over the options provided
87 through command line arguments.
88 <link xlink:href="https://duplicati.readthedocs.io/en/latest/06-advanced-options/#parameters-file">Duplicati docs: parameters-file</link>
89 '';
90 };
91 };
92 };
93
94 config = lib.mkIf cfg.enable {
95 environment.systemPackages = [ cfg.package ];
96
97 assertions = [
98 {
99 assertion = !(cfg.parametersFile != null && cfg.parameters != "");
100 message = "cannot set both services.duplicati.parameters and services.duplicati.parametersFile at the same time";
101 }
102 ];
103
104 systemd.services.duplicati = {
105 description = "Duplicati backup";
106 after = [ "network.target" ];
107 wantedBy = [ "multi-user.target" ];
108 serviceConfig = lib.mkMerge [
109 {
110 User = cfg.user;
111 Group = "duplicati";
112 ExecStart = "${cfg.package}/bin/duplicati-server --webservice-interface=${cfg.interface} --webservice-port=${toString cfg.port} --server-datafolder=${cfg.dataDir} --parameters-file=${parametersFile}";
113 Restart = "on-failure";
114 }
115 (lib.mkIf (cfg.dataDir == "/var/lib/duplicati") {
116 StateDirectory = "duplicati";
117 })
118 ];
119 };
120
121 users.users = lib.optionalAttrs (cfg.user == "duplicati") {
122 duplicati = {
123 uid = config.ids.uids.duplicati;
124 home = cfg.dataDir;
125 group = "duplicati";
126 };
127 };
128 users.groups.duplicati.gid = config.ids.gids.duplicati;
129
130 };
131}