1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.syncplay;
7
8 cmdArgs =
9 [ "--port" cfg.port ]
10 ++ optionals (cfg.salt != null) [ "--salt" cfg.salt ]
11 ++ optionals (cfg.certDir != null) [ "--tls" cfg.certDir ]
12 ++ cfg.extraArgs;
13
14in
15{
16 options = {
17 services.syncplay = {
18 enable = mkOption {
19 type = types.bool;
20 default = false;
21 description = lib.mdDoc "If enabled, start the Syncplay server.";
22 };
23
24 port = mkOption {
25 type = types.port;
26 default = 8999;
27 description = lib.mdDoc ''
28 TCP port to bind to.
29 '';
30 };
31
32 salt = mkOption {
33 type = types.nullOr types.str;
34 default = null;
35 description = lib.mdDoc ''
36 Salt to allow room operator passwords generated by this server
37 instance to still work when the server is restarted. The salt will be
38 readable in the nix store and the processlist. If this is not
39 intended use `saltFile` instead. Mutually exclusive with
40 <option>services.syncplay.saltFile</option>.
41 '';
42 };
43
44 saltFile = mkOption {
45 type = types.nullOr types.path;
46 default = null;
47 description = lib.mdDoc ''
48 Path to the file that contains the server salt. This allows room
49 operator passwords generated by this server instance to still work
50 when the server is restarted. `null`, the server doesn't load the
51 salt from a file. Mutually exclusive with
52 <option>services.syncplay.salt</option>.
53 '';
54 };
55
56 certDir = mkOption {
57 type = types.nullOr types.path;
58 default = null;
59 description = lib.mdDoc ''
60 TLS certificates directory to use for encryption. See
61 <https://github.com/Syncplay/syncplay/wiki/TLS-support>.
62 '';
63 };
64
65 extraArgs = mkOption {
66 type = types.listOf types.str;
67 default = [ ];
68 description = lib.mdDoc ''
69 Additional arguments to be passed to the service.
70 '';
71 };
72
73 user = mkOption {
74 type = types.str;
75 default = "nobody";
76 description = lib.mdDoc ''
77 User to use when running Syncplay.
78 '';
79 };
80
81 group = mkOption {
82 type = types.str;
83 default = "nogroup";
84 description = lib.mdDoc ''
85 Group to use when running Syncplay.
86 '';
87 };
88
89 passwordFile = mkOption {
90 type = types.nullOr types.path;
91 default = null;
92 description = lib.mdDoc ''
93 Path to the file that contains the server password. If
94 `null`, the server doesn't require a password.
95 '';
96 };
97 };
98 };
99
100 config = mkIf cfg.enable {
101 assertions = [
102 {
103 assertion = cfg.salt == null || cfg.saltFile == null;
104 message = "services.syncplay.salt and services.syncplay.saltFile are mutually exclusive.";
105 }
106 ];
107 systemd.services.syncplay = {
108 description = "Syncplay Service";
109 wantedBy = [ "multi-user.target" ];
110 after = [ "network-online.target" ];
111
112 serviceConfig = {
113 User = cfg.user;
114 Group = cfg.group;
115 LoadCredential = lib.optional (cfg.passwordFile != null) "password:${cfg.passwordFile}"
116 ++ lib.optional (cfg.saltFile != null) "salt:${cfg.saltFile}";
117 };
118
119 script = ''
120 ${lib.optionalString (cfg.passwordFile != null) ''
121 export SYNCPLAY_PASSWORD=$(cat "''${CREDENTIALS_DIRECTORY}/password")
122 ''}
123 ${lib.optionalString (cfg.saltFile != null) ''
124 export SYNCPLAY_SALT=$(cat "''${CREDENTIALS_DIRECTORY}/salt")
125 ''}
126 exec ${pkgs.syncplay-nogui}/bin/syncplay-server ${escapeShellArgs cmdArgs}
127 '';
128 };
129 };
130}