tenseleyflow/hyprkvm / 1042579

Browse files

feat: add home-manager module and improve packaging

- Add home-manager module for declarative service management
- Users can now enable with: services.hyprkvm.enable = true
- Module supports settings for auto-generating config file
- Update contrib/systemd service for system-installed binary
- Remove dev template (users can manually adapt if needed)
Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
10425796ac77153455ddf6c64b089d2d41e3b22f
Parents
c5eafea
Tree
2c5e603

2 changed files

StatusFile+-
M contrib/systemd/hyprkvm.service 2 4
M flake.nix 202 113
contrib/systemd/hyprkvm.servicemodified
@@ -5,10 +5,8 @@ PartOf=graphical-session.target
55
 
66
 [Service]
77
 Type=simple
8
-# Set WorkingDirectory to your hyprKVM repo path
9
-WorkingDirectory=%h/path/to/hyprKVM
10
-# Uses nix develop to provide required libraries
11
-ExecStart=/bin/sh -c 'exec nix develop --command ./target/release/hyprkvm daemon'
8
+# For system-installed binaries (AUR, RPM, etc.)
9
+ExecStart=/usr/bin/hyprkvm daemon
1210
 Restart=on-failure
1311
 RestartSec=1
1412
 
flake.nixmodified
@@ -11,134 +11,223 @@
1111
   };
1212
 
1313
   outputs = { self, nixpkgs, flake-utils, rust-overlay }:
14
-    flake-utils.lib.eachDefaultSystem (system:
15
-      let
16
-        pkgs = import nixpkgs {
17
-          inherit system;
18
-          overlays = [ rust-overlay.overlays.default ];
19
-        };
20
-
21
-        # Build dependencies
22
-        buildDeps = with pkgs; [
23
-          pkg-config
24
-        ];
25
-
26
-        # Runtime/library dependencies
27
-        libDeps = with pkgs; [
28
-          # Wayland
29
-          wayland
30
-          wayland-protocols
31
-
32
-          # For smithay-client-toolkit
33
-          libxkbcommon
34
-
35
-          # TLS
36
-          openssl
37
-
38
-          # GUI (Iced) dependencies
39
-          vulkan-loader
40
-          libGL
41
-          xorg.libX11
42
-          xorg.libXcursor
43
-          xorg.libXrandr
44
-          xorg.libXi
45
-        ];
46
-
47
-        rustToolchain = pkgs.rust-bin.stable.latest.default.override {
48
-          extensions = [ "rust-src" "rust-analyzer" ];
49
-        };
50
-      in
51
-      {
52
-        # Development shell
53
-        devShells.default = pkgs.mkShell {
54
-          buildInputs = buildDeps ++ libDeps ++ [
55
-            rustToolchain
56
-          ];
57
-
58
-          # Set up pkg-config paths
59
-          PKG_CONFIG_PATH = pkgs.lib.makeSearchPath "lib/pkgconfig" libDeps;
60
-
61
-          # For wayland-scanner
62
-          WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols";
63
-
64
-          # Graphics library paths for GUI
65
-          LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath libDeps;
66
-
67
-          shellHook = ''
68
-            echo "HyprKVM development shell"
69
-            echo "Rust: $(rustc --version)"
70
-            echo ""
71
-            echo "Run 'cargo build' to compile"
72
-          '';
73
-        };
14
+    let
15
+      # System-independent outputs
16
+      systemIndependent = {
17
+        # Home-manager module for easy service management
18
+        homeManagerModules.default = { config, lib, pkgs, ... }:
19
+          let
20
+            cfg = config.services.hyprkvm;
21
+          in {
22
+            options.services.hyprkvm = {
23
+              enable = lib.mkEnableOption "HyprKVM daemon";
24
+
25
+              package = lib.mkOption {
26
+                type = lib.types.package;
27
+                default = self.packages.${pkgs.system}.default;
28
+                defaultText = lib.literalExpression "pkgs.hyprkvm";
29
+                description = "The HyprKVM package to use.";
30
+              };
31
+
32
+              settings = lib.mkOption {
33
+                type = lib.types.attrs;
34
+                default = {};
35
+                description = ''
36
+                  Configuration for HyprKVM. Will be written to
37
+                  ~/.config/hyprkvm/hyprkvm.toml
38
+                '';
39
+                example = lib.literalExpression ''
40
+                  {
41
+                    machines = {
42
+                      self_name = "my-machine";
43
+                      neighbors = [
44
+                        { name = "other-machine"; direction = "right"; address = "192.168.1.100:24850"; }
45
+                      ];
46
+                    };
47
+                    network = {
48
+                      listen_port = 24850;
49
+                    };
50
+                  }
51
+                '';
52
+              };
53
+
54
+              extraFlags = lib.mkOption {
55
+                type = lib.types.listOf lib.types.str;
56
+                default = [];
57
+                description = "Extra command-line flags to pass to the daemon.";
58
+              };
59
+            };
60
+
61
+            config = lib.mkIf cfg.enable {
62
+              # Install the package
63
+              home.packages = [ cfg.package ];
64
+
65
+              # Generate config file if settings provided
66
+              xdg.configFile."hyprkvm/hyprkvm.toml" = lib.mkIf (cfg.settings != {}) {
67
+                source = (pkgs.formats.toml {}).generate "hyprkvm.toml" cfg.settings;
68
+              };
69
+
70
+              # Systemd user service
71
+              systemd.user.services.hyprkvm = {
72
+                Unit = {
73
+                  Description = "HyprKVM Daemon - Hyprland-native software KVM switch";
74
+                  After = [ "graphical-session.target" ];
75
+                  PartOf = [ "graphical-session.target" ];
76
+                };
77
+
78
+                Service = {
79
+                  Type = "simple";
80
+                  ExecStart = "${cfg.package}/bin/hyprkvm daemon ${lib.concatStringsSep " " cfg.extraFlags}";
81
+                  Restart = "on-failure";
82
+                  RestartSec = 1;
83
+                  # Exit code 75 triggers restart for direction changes
84
+                  RestartForceExitStatus = [ 75 ];
85
+                  Environment = [ "WAYLAND_DISPLAY=wayland-1" ];
86
+                };
87
+
88
+                Install = {
89
+                  WantedBy = [ "graphical-session.target" ];
90
+                };
91
+              };
92
+            };
93
+          };
7494
 
75
-        # Package (without GUI for smaller binary)
76
-        packages.default = pkgs.rustPlatform.buildRustPackage {
77
-          pname = "hyprkvm";
78
-          version = "0.5.1";
79
-          src = ./.;
95
+        # Alias for backwards compatibility
96
+        homeManagerModules.hyprkvm = self.homeManagerModules.default;
97
+      };
8098
 
81
-          cargoLock = {
82
-            lockFile = ./Cargo.lock;
99
+      # System-specific outputs (packages, devShells)
100
+      systemSpecific = flake-utils.lib.eachDefaultSystem (system:
101
+        let
102
+          pkgs = import nixpkgs {
103
+            inherit system;
104
+            overlays = [ rust-overlay.overlays.default ];
83105
           };
84106
 
85
-          nativeBuildInputs = buildDeps;
86
-          buildInputs = libDeps;
107
+          # Build dependencies
108
+          buildDeps = with pkgs; [
109
+            pkg-config
110
+          ];
87111
 
88
-          # Builds both hyprkvm (daemon) and hyprkvm-ctl (CLI)
89
-          # buildRustPackage automatically installs all workspace binaries
112
+          # Runtime/library dependencies
113
+          libDeps = with pkgs; [
114
+            # Wayland
115
+            wayland
116
+            wayland-protocols
117
+
118
+            # For smithay-client-toolkit
119
+            libxkbcommon
120
+
121
+            # TLS
122
+            openssl
123
+
124
+            # GUI (Iced) dependencies
125
+            vulkan-loader
126
+            libGL
127
+            xorg.libX11
128
+            xorg.libXcursor
129
+            xorg.libXrandr
130
+            xorg.libXi
131
+          ];
90132
 
91
-          meta = with pkgs.lib; {
92
-            description = "Hyprland-native software KVM switch";
93
-            longDescription = ''
94
-              HyprKVM enables seamless keyboard/mouse control transfer between
95
-              Linux machines running Hyprland. Move past your last workspace
96
-              to switch to another machine.
133
+          rustToolchain = pkgs.rust-bin.stable.latest.default.override {
134
+            extensions = [ "rust-src" "rust-analyzer" ];
135
+          };
136
+        in
137
+        {
138
+          # Development shell
139
+          devShells.default = pkgs.mkShell {
140
+            buildInputs = buildDeps ++ libDeps ++ [
141
+              rustToolchain
142
+            ];
143
+
144
+            # Set up pkg-config paths
145
+            PKG_CONFIG_PATH = pkgs.lib.makeSearchPath "lib/pkgconfig" libDeps;
146
+
147
+            # For wayland-scanner
148
+            WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols";
149
+
150
+            # Graphics library paths for GUI
151
+            LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath libDeps;
152
+
153
+            shellHook = ''
154
+              echo "HyprKVM development shell"
155
+              echo "Rust: $(rustc --version)"
156
+              echo ""
157
+              echo "Run 'cargo build' to compile"
97158
             '';
98
-            homepage = "https://github.com/tenseleyFlow/hyprKVM";
99
-            license = licenses.mit;
100
-            platforms = platforms.linux;
101
-            mainProgram = "hyprkvm";
102159
           };
103
-        };
104160
 
105
-        # Package with GUI support
106
-        packages.gui = pkgs.rustPlatform.buildRustPackage {
107
-          pname = "hyprkvm";
108
-          version = "0.5.1";
109
-          src = ./.;
110
-
111
-          cargoLock = {
112
-            lockFile = ./Cargo.lock;
161
+          # Package (without GUI for smaller binary)
162
+          packages.default = pkgs.rustPlatform.buildRustPackage {
163
+            pname = "hyprkvm";
164
+            version = "0.5.1";
165
+            src = ./.;
166
+
167
+            cargoLock = {
168
+              lockFile = ./Cargo.lock;
169
+            };
170
+
171
+            nativeBuildInputs = buildDeps;
172
+            buildInputs = libDeps;
173
+
174
+            # Builds both hyprkvm (daemon) and hyprkvm-ctl (CLI)
175
+            # buildRustPackage automatically installs all workspace binaries
176
+
177
+            meta = with pkgs.lib; {
178
+              description = "Hyprland-native software KVM switch";
179
+              longDescription = ''
180
+                HyprKVM enables seamless keyboard/mouse control transfer between
181
+                Linux machines running Hyprland. Move past your last workspace
182
+                to switch to another machine.
183
+              '';
184
+              homepage = "https://github.com/tenseleyFlow/hyprKVM";
185
+              license = licenses.mit;
186
+              platforms = platforms.linux;
187
+              mainProgram = "hyprkvm";
188
+            };
113189
           };
114190
 
115
-          nativeBuildInputs = buildDeps ++ [ pkgs.makeWrapper ];
116
-          buildInputs = libDeps;
191
+          # Package with GUI support
192
+          packages.gui = pkgs.rustPlatform.buildRustPackage {
193
+            pname = "hyprkvm";
194
+            version = "0.5.1";
195
+            src = ./.;
117196
 
118
-          # Build with GUI feature
119
-          buildFeatures = [ "gui" ];
197
+            cargoLock = {
198
+              lockFile = ./Cargo.lock;
199
+            };
120200
 
121
-          # Wrap binary to include graphics library paths
122
-          postInstall = ''
123
-            wrapProgram $out/bin/hyprkvm \
124
-              --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath libDeps}
125
-          '';
201
+            nativeBuildInputs = buildDeps ++ [ pkgs.makeWrapper ];
202
+            buildInputs = libDeps;
126203
 
127
-          meta = with pkgs.lib; {
128
-            description = "Hyprland-native software KVM switch (with GUI)";
129
-            longDescription = ''
130
-              HyprKVM enables seamless keyboard/mouse control transfer between
131
-              Linux machines running Hyprland. Move past your last workspace
132
-              to switch to another machine.
204
+            # Build with GUI feature
205
+            buildFeatures = [ "gui" ];
133206
 
134
-              This package includes the GUI configuration tool.
207
+            # Wrap binary to include graphics library paths
208
+            postInstall = ''
209
+              wrapProgram $out/bin/hyprkvm \
210
+                --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath libDeps}
135211
             '';
136
-            homepage = "https://github.com/tenseleyFlow/hyprKVM";
137
-            license = licenses.mit;
138
-            platforms = platforms.linux;
139
-            mainProgram = "hyprkvm";
212
+
213
+            meta = with pkgs.lib; {
214
+              description = "Hyprland-native software KVM switch (with GUI)";
215
+              longDescription = ''
216
+                HyprKVM enables seamless keyboard/mouse control transfer between
217
+                Linux machines running Hyprland. Move past your last workspace
218
+                to switch to another machine.
219
+
220
+                This package includes the GUI configuration tool.
221
+              '';
222
+              homepage = "https://github.com/tenseleyFlow/hyprKVM";
223
+              license = licenses.mit;
224
+              platforms = platforms.linux;
225
+              mainProgram = "hyprkvm";
226
+            };
140227
           };
141
-        };
142
-      }
143
-    );
228
+        }
229
+      );
230
+    in
231
+    # Merge system-independent and system-specific outputs
232
+    systemIndependent // systemSpecific;
144233
 }