1{ options, config, pkgs, lib, ... }:
2
3with lib;
4let
5 opt = options.services.rkvm;
6 cfg = config.services.rkvm;
7 toml = pkgs.formats.toml { };
8in
9{
10 meta.maintainers = with maintainers; [ ckie ];
11
12 options.services.rkvm = {
13 enable = mkOption {
14 default = cfg.server.enable || cfg.client.enable;
15 defaultText = literalExpression "config.${opt.server.enable} || config.${opt.client.enable}";
16 type = types.bool;
17 description = ''
18 Whether to enable rkvm, a Virtual KVM switch for Linux machines.
19 '';
20 };
21
22 package = mkPackageOption pkgs "rkvm" { };
23
24 server = {
25 enable = mkEnableOption "the rkvm server daemon (input transmitter)";
26
27 settings = mkOption {
28 type = types.submodule
29 {
30 freeformType = toml.type;
31 options = {
32 listen = mkOption {
33 type = types.str;
34 default = "0.0.0.0:5258";
35 description = ''
36 An internet socket address to listen on, either IPv4 or IPv6.
37 '';
38 };
39
40 switch-keys = mkOption {
41 type = types.listOf types.str;
42 default = [ "left-alt" "left-ctrl" ];
43 description = ''
44 A key list specifying a host switch combination.
45
46 _A list of key names is available in <https://github.com/htrefil/rkvm/blob/master/switch-keys.md>._
47 '';
48 };
49
50 certificate = mkOption {
51 type = types.path;
52 default = "/etc/rkvm/certificate.pem";
53 description = ''
54 TLS certificate path.
55
56 ::: {.note}
57 This should be generated with {command}`rkvm-certificate-gen`.
58 :::
59 '';
60 };
61
62 key = mkOption {
63 type = types.path;
64 default = "/etc/rkvm/key.pem";
65 description = ''
66 TLS key path.
67
68 ::: {.note}
69 This should be generated with {command}`rkvm-certificate-gen`.
70 :::
71 '';
72 };
73
74 password = mkOption {
75 type = types.str;
76 description = ''
77 Shared secret token to authenticate the client.
78 Make sure this matches your client's config.
79 '';
80 };
81 };
82 };
83
84 default = { };
85 description = "Structured server daemon configuration";
86 };
87 };
88
89 client = {
90 enable = mkEnableOption "the rkvm client daemon (input receiver)";
91
92 settings = mkOption {
93 type = types.submodule
94 {
95 freeformType = toml.type;
96 options = {
97 server = mkOption {
98 type = types.str;
99 example = "192.168.0.123:5258";
100 description = ''
101 An RKVM server's internet socket address, either IPv4 or IPv6.
102 '';
103 };
104
105 certificate = mkOption {
106 type = types.path;
107 default = "/etc/rkvm/certificate.pem";
108 description = ''
109 TLS ceritficate path.
110
111 ::: {.note}
112 This should be generated with {command}`rkvm-certificate-gen`.
113 :::
114 '';
115 };
116
117 password = mkOption {
118 type = types.str;
119 description = ''
120 Shared secret token to authenticate the client.
121 Make sure this matches your server's config.
122 '';
123 };
124 };
125 };
126
127 default = {};
128 description = "Structured client daemon configuration";
129 };
130 };
131
132 };
133
134 config = mkIf cfg.enable {
135 environment.systemPackages = [ cfg.package ];
136
137 systemd.services =
138 let
139 mkBase = component: {
140 description = "RKVM ${component}";
141 wantedBy = [ "multi-user.target" ];
142 after = {
143 server = [ "network.target" ];
144 client = [ "network-online.target" ];
145 }.${component};
146 wants = {
147 server = [ ];
148 client = [ "network-online.target" ];
149 }.${component};
150 serviceConfig = {
151 ExecStart = "${cfg.package}/bin/rkvm-${component} ${toml.generate "rkvm-${component}.toml" cfg.${component}.settings}";
152 Restart = "always";
153 RestartSec = 5;
154 Type = "simple";
155 };
156 };
157 in
158 {
159 rkvm-server = mkIf cfg.server.enable (mkBase "server");
160 rkvm-client = mkIf cfg.client.enable (mkBase "client");
161 };
162 };
163
164}