1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.syncthing;
8 defaultUser = "syncthing";
9
10 header = {
11 description = "Syncthing service";
12 after = [ "network.target" ];
13 environment = {
14 STNORESTART = "yes";
15 STNOUPGRADE = "yes";
16 inherit (cfg) all_proxy;
17 } // config.networking.proxy.envVars;
18 };
19
20 service = {
21 Restart = "on-failure";
22 SuccessExitStatus = "2 3 4";
23 RestartForceExitStatus="3 4";
24 };
25
26 iNotifyHeader = {
27 description = "Syncthing Inotify File Watcher service";
28 after = [ "network.target" "syncthing.service" ];
29 requires = [ "syncthing.service" ];
30 };
31
32 iNotifyService = {
33 SuccessExitStatus = "2";
34 RestartForceExitStatus = "3";
35 Restart = "on-failure";
36 };
37
38in
39
40{
41
42 ###### interface
43
44 options = {
45
46 services.syncthing = {
47
48 enable = mkEnableOption ''
49 Syncthing - the self-hosted open-source alternative
50 to Dropbox and Bittorrent Sync. Initial interface will be
51 available on http://127.0.0.1:8384/.
52 '';
53
54 useInotify = mkOption {
55 type = types.bool;
56 default = false;
57 description = "Provide syncthing-inotify as a service.";
58 };
59
60 systemService = mkOption {
61 type = types.bool;
62 default = true;
63 description = "Auto launch Syncthing as a system service.";
64 };
65
66 user = mkOption {
67 type = types.string;
68 default = defaultUser;
69 description = ''
70 Syncthing will be run under this user (user will be created if it doesn't exist.
71 This can be your user name).
72 '';
73 };
74
75 group = mkOption {
76 type = types.string;
77 default = "nogroup";
78 description = ''
79 Syncthing will be run under this group (group will not be created if it doesn't exist.
80 This can be your user name).
81 '';
82 };
83
84 all_proxy = mkOption {
85 type = types.nullOr types.string;
86 default = null;
87 example = "socks5://address.com:1234";
88 description = ''
89 Overwrites all_proxy environment variable for the syncthing process to
90 the given value. This is normaly used to let relay client connect
91 through SOCKS5 proxy server.
92 '';
93 };
94
95 dataDir = mkOption {
96 type = types.path;
97 default = "/var/lib/syncthing";
98 description = ''
99 Path where the settings and keys will exist.
100 '';
101 };
102
103 package = mkOption {
104 type = types.package;
105 default = pkgs.syncthing;
106 defaultText = "pkgs.syncthing";
107 example = literalExample "pkgs.syncthing";
108 description = ''
109 Syncthing package to use.
110 '';
111 };
112 };
113 };
114
115
116 ###### implementation
117
118 config = mkIf cfg.enable {
119
120 users = mkIf (cfg.user == defaultUser) {
121 extraUsers."${defaultUser}" =
122 { group = cfg.group;
123 home = cfg.dataDir;
124 createHome = true;
125 uid = config.ids.uids.syncthing;
126 description = "Syncthing daemon user";
127 };
128
129 extraGroups."${defaultUser}".gid =
130 config.ids.gids.syncthing;
131 };
132
133 systemd.services = {
134 syncthing = mkIf cfg.systemService (header // {
135 wants = mkIf cfg.useInotify [ "syncthing-inotify.service" ];
136 wantedBy = [ "multi-user.target" ];
137 serviceConfig = service // {
138 User = cfg.user;
139 Group = cfg.group;
140 PermissionsStartOnly = true;
141 ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}";
142 };
143 });
144
145 syncthing-inotify = mkIf (cfg.systemService && cfg.useInotify) (iNotifyHeader // {
146 wantedBy = [ "multi-user.target" ];
147 serviceConfig = iNotifyService // {
148 User = cfg.user;
149 ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -home=${cfg.dataDir} -logflags=0";
150 };
151 });
152 };
153
154 systemd.user.services = {
155 syncthing = header // {
156 serviceConfig = service // {
157 ExecStart = "${cfg.package}/bin/syncthing -no-browser";
158 };
159 };
160
161 syncthing-inotify = mkIf cfg.useInotify (iNotifyHeader // {
162 serviceConfig = iNotifyService // {
163 ExecStart = "${pkgs.syncthing-inotify.bin}/bin/syncthing-inotify -logflags=0";
164 };
165 });
166 };
167
168 };
169}