commit
c132df63df
8 changed files with 365 additions and 0 deletions
|
@ -723,6 +723,7 @@
|
|||
./services/misc/ripple-data-api.nix
|
||||
./services/misc/rippled.nix
|
||||
./services/misc/rmfakecloud.nix
|
||||
./services/misc/rkvm.nix
|
||||
./services/misc/rshim.nix
|
||||
./services/misc/safeeyes.nix
|
||||
./services/misc/sdrplay.nix
|
||||
|
|
164
nixos/modules/services/misc/rkvm.nix
Normal file
164
nixos/modules/services/misc/rkvm.nix
Normal file
|
@ -0,0 +1,164 @@
|
|||
{ options, config, pkgs, lib, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
opt = options.services.rkvm;
|
||||
cfg = config.services.rkvm;
|
||||
toml = pkgs.formats.toml { };
|
||||
in
|
||||
{
|
||||
meta.maintainers = with maintainers; [ ckie ];
|
||||
|
||||
options.services.rkvm = {
|
||||
enable = mkOption {
|
||||
default = cfg.server.enable || cfg.client.enable;
|
||||
defaultText = literalExpression "config.${opt.server.enable} || config.${opt.client.enable}";
|
||||
type = types.bool;
|
||||
description = mdDoc ''
|
||||
Whether to enable rkvm, a Virtual KVM switch for Linux machines.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "rkvm" { };
|
||||
|
||||
server = {
|
||||
enable = mkEnableOption "the rkvm server daemon (input transmitter)";
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule
|
||||
{
|
||||
freeformType = toml.type;
|
||||
options = {
|
||||
listen = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0:5258";
|
||||
description = mdDoc ''
|
||||
An internet socket address to listen on, either IPv4 or IPv6.
|
||||
'';
|
||||
};
|
||||
|
||||
switch-keys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "left-alt" "left-ctrl" ];
|
||||
description = mdDoc ''
|
||||
A key list specifying a host switch combination.
|
||||
|
||||
_A list of key names is available in <https://github.com/htrefil/rkvm/blob/master/switch-keys.md>._
|
||||
'';
|
||||
};
|
||||
|
||||
certificate = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/rkvm/certificate.pem";
|
||||
description = mdDoc ''
|
||||
TLS certificate path.
|
||||
|
||||
::: {.note}
|
||||
This should be generated with {command}`rkvm-certificate-gen`.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
key = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/rkvm/key.pem";
|
||||
description = mdDoc ''
|
||||
TLS key path.
|
||||
|
||||
::: {.note}
|
||||
This should be generated with {command}`rkvm-certificate-gen`.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.str;
|
||||
description = mdDoc ''
|
||||
Shared secret token to authenticate the client.
|
||||
Make sure this matches your client's config.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
default = { };
|
||||
description = mdDoc "Structured server daemon configuration";
|
||||
};
|
||||
};
|
||||
|
||||
client = {
|
||||
enable = mkEnableOption "the rkvm client daemon (input receiver)";
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule
|
||||
{
|
||||
freeformType = toml.type;
|
||||
options = {
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
example = "192.168.0.123:5258";
|
||||
description = mdDoc ''
|
||||
An RKVM server's internet socket address, either IPv4 or IPv6.
|
||||
'';
|
||||
};
|
||||
|
||||
certificate = mkOption {
|
||||
type = types.path;
|
||||
default = "/etc/rkvm/certificate.pem";
|
||||
description = mdDoc ''
|
||||
TLS ceritficate path.
|
||||
|
||||
::: {.note}
|
||||
This should be generated with {command}`rkvm-certificate-gen`.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.str;
|
||||
description = mdDoc ''
|
||||
Shared secret token to authenticate the client.
|
||||
Make sure this matches your server's config.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
default = {};
|
||||
description = mdDoc "Structured client daemon configuration";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
mkBase = component: {
|
||||
description = "RKVM ${component}";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = {
|
||||
server = [ "network.target" ];
|
||||
client = [ "network-online.target" ];
|
||||
}.${component};
|
||||
wants = {
|
||||
server = [ ];
|
||||
client = [ "network-online.target" ];
|
||||
}.${component};
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/rkvm-${component} ${toml.generate "rkvm-${component}.toml" cfg.${component}.settings}";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
Type = "simple";
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
rkvm-server = mkIf cfg.server.enable (mkBase "server");
|
||||
rkvm-client = mkIf cfg.client.enable (mkBase "client");
|
||||
};
|
||||
};
|
||||
|
||||
}
|
|
@ -699,6 +699,7 @@ in {
|
|||
restartByActivationScript = handleTest ./restart-by-activation-script.nix {};
|
||||
restic = handleTest ./restic.nix {};
|
||||
retroarch = handleTest ./retroarch.nix {};
|
||||
rkvm = handleTest ./rkvm {};
|
||||
robustirc-bridge = handleTest ./robustirc-bridge.nix {};
|
||||
roundcube = handleTest ./roundcube.nix {};
|
||||
rshim = handleTest ./rshim.nix {};
|
||||
|
|
18
nixos/tests/rkvm/cert.pem
Normal file
18
nixos/tests/rkvm/cert.pem
Normal file
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC3jCCAcagAwIBAgIUWW1hb9xdRtxAhA42jkS89goW9LUwDQYJKoZIhvcNAQEL
|
||||
BQAwDzENMAsGA1UEAwwEcmt2bTAeFw0yMzA4MjIxOTI1NDlaFw0zMzA4MTkxOTI1
|
||||
NDlaMA8xDTALBgNVBAMMBHJrdm0wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQCuBsh0+LDXN4b2o/PJjzuiZ9Yv9Pz1Oho9WRiXtNIuHTRdBCcht/iu3PGF
|
||||
ICIX+H3dqQOziGSCTAQGJD2p+1ik8d+boJbpa0oxXuHuomsMAT3mib3GpipQoBLP
|
||||
KaEbWEsvQbr3RMx8WOtG4dmRQFzSVVtmAXyM0pNyisd4eUCplyIl9gsRJIvsO/0M
|
||||
OkgOZW9XLfKiAWlZoyXEkBmPAshg3EkwQtmwxPA/NgWbAOW3zJKSChxnnGYiuIIu
|
||||
R/wJ8OQXHP6boQLQGUhCWBKa1uK1gEBmV3Pj6uK8RzTkQq6/47F5sPa6VfqQYdyl
|
||||
TCs9bSqHXZjqMBoiSp22uH6+Lh9RAgMBAAGjMjAwMA8GA1UdEQQIMAaHBAoAAAEw
|
||||
HQYDVR0OBBYEFEh9HEsnY3dfNKVyPWDbwfR0qHopMA0GCSqGSIb3DQEBCwUAA4IB
|
||||
AQB/r+K20JqegUZ/kepPxIU95YY81aUUoxvLbu4EAgh8o46Fgm75qrTZPg4TaIZa
|
||||
wtVejekrF+p3QVf0ErUblh/iCjTZPSzCmKHZt8cc9OwTH7bt3bx7heknzLDyIa5z
|
||||
szAL+6241UggQ5n5NUGn5+xZHA7TMe47xAZPaRMlCQ/tp5pWFjH6WSSQSP5t4Ag9
|
||||
ObhY+uudFjmWi3QIBTr3iIscbWx7tD8cjus7PzM7+kszSDRV04xb6Ox8JzW9MKIN
|
||||
GwgwVgs3zCuyqBmTGnR1og3aMk6VtlyZUYE78uuc+fMBxqoBZ0mykeOp0Tbzgtf7
|
||||
gPkYcQ6vonoQhuTXYj/NrY+b
|
||||
-----END CERTIFICATE-----
|
104
nixos/tests/rkvm/default.nix
Normal file
104
nixos/tests/rkvm/default.nix
Normal file
|
@ -0,0 +1,104 @@
|
|||
import ../make-test-python.nix ({ pkgs, ... }:
|
||||
let
|
||||
# Generated with
|
||||
#
|
||||
# nix shell .#rkvm --command "rkvm-certificate-gen --ip-addresses 10.0.0.1 cert.pem key.pem"
|
||||
#
|
||||
snakeoil-cert = ./cert.pem;
|
||||
snakeoil-key = ./key.pem;
|
||||
in
|
||||
{
|
||||
name = "rkvm";
|
||||
|
||||
nodes = {
|
||||
server = { pkgs, ... }: {
|
||||
imports = [ ../common/user-account.nix ];
|
||||
|
||||
virtualisation.vlans = [ 1 ];
|
||||
|
||||
networking = {
|
||||
useNetworkd = true;
|
||||
useDHCP = false;
|
||||
firewall.enable = false;
|
||||
};
|
||||
|
||||
systemd.network.networks."01-eth1" = {
|
||||
name = "eth1";
|
||||
networkConfig.Address = "10.0.0.1/24";
|
||||
};
|
||||
|
||||
services.getty.autologinUser = "alice";
|
||||
|
||||
services.rkvm.server = {
|
||||
enable = true;
|
||||
settings = {
|
||||
certificate = snakeoil-cert;
|
||||
key = snakeoil-key;
|
||||
password = "snakeoil";
|
||||
switch-keys = [ "left-alt" "right-alt" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
client = { pkgs, ... }: {
|
||||
imports = [ ../common/user-account.nix ];
|
||||
|
||||
virtualisation.vlans = [ 1 ];
|
||||
|
||||
networking = {
|
||||
useNetworkd = true;
|
||||
useDHCP = false;
|
||||
firewall.enable = false;
|
||||
};
|
||||
|
||||
systemd.network.networks."01-eth1" = {
|
||||
name = "eth1";
|
||||
networkConfig.Address = "10.0.0.2/24";
|
||||
};
|
||||
|
||||
services.getty.autologinUser = "alice";
|
||||
|
||||
services.rkvm.client = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = "10.0.0.1:5258";
|
||||
certificate = snakeoil-cert;
|
||||
key = snakeoil-key;
|
||||
password = "snakeoil";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
server.wait_for_unit("getty@tty1.service")
|
||||
server.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
|
||||
server.wait_for_unit("rkvm-server")
|
||||
server.wait_for_open_port(5258)
|
||||
|
||||
client.wait_for_unit("getty@tty1.service")
|
||||
client.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
|
||||
client.wait_for_unit("rkvm-client")
|
||||
|
||||
server.sleep(1)
|
||||
|
||||
# Switch to client
|
||||
server.send_key("alt-alt_r", delay=0.2)
|
||||
server.send_chars("echo 'hello client' > /tmp/test.txt\n")
|
||||
|
||||
# Switch to server
|
||||
server.send_key("alt-alt_r", delay=0.2)
|
||||
server.send_chars("echo 'hello server' > /tmp/test.txt\n")
|
||||
|
||||
server.sleep(1)
|
||||
|
||||
client.systemctl("stop rkvm-client.service")
|
||||
server.systemctl("stop rkvm-server.service")
|
||||
|
||||
server_file = server.succeed("cat /tmp/test.txt")
|
||||
assert server_file.strip() == "hello server"
|
||||
|
||||
client_file = client.succeed("cat /tmp/test.txt")
|
||||
assert client_file.strip() == "hello client"
|
||||
'';
|
||||
})
|
28
nixos/tests/rkvm/key.pem
Normal file
28
nixos/tests/rkvm/key.pem
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCuBsh0+LDXN4b2
|
||||
o/PJjzuiZ9Yv9Pz1Oho9WRiXtNIuHTRdBCcht/iu3PGFICIX+H3dqQOziGSCTAQG
|
||||
JD2p+1ik8d+boJbpa0oxXuHuomsMAT3mib3GpipQoBLPKaEbWEsvQbr3RMx8WOtG
|
||||
4dmRQFzSVVtmAXyM0pNyisd4eUCplyIl9gsRJIvsO/0MOkgOZW9XLfKiAWlZoyXE
|
||||
kBmPAshg3EkwQtmwxPA/NgWbAOW3zJKSChxnnGYiuIIuR/wJ8OQXHP6boQLQGUhC
|
||||
WBKa1uK1gEBmV3Pj6uK8RzTkQq6/47F5sPa6VfqQYdylTCs9bSqHXZjqMBoiSp22
|
||||
uH6+Lh9RAgMBAAECggEABo2V1dBu5E51zsAiFCMdypdLZEyUNphvWC5h3oXowONz
|
||||
pH8ICYfXyEnkma/kk2+ALy0dSRDn6/94dVIUX7Fpx0hJCcoJyhSysK+TJWfIonqX
|
||||
ffYOMeFG8vicIgs+GFKs/hoPtB5LREbFkUqRj/EoWE6Y3aX3roaCwTZC8vaUk0OK
|
||||
54gExcNXRwQtFmfM9BiPT76F2J641NVsddgKumrryMi605CgZ57OFfSYEena6T3t
|
||||
JbQ1TKB3SH1LvSQIspyp56E3bjh8bcwSh72g88YxWZI9yarOesmyU+fXnmVqcBc+
|
||||
CiJDX3Te1C2GIkBiH3HZJo4P88aXrkJ7J8nub/812QKBgQDfCHjBy5uWzzbDnqZc
|
||||
cllIyUqMHq1iY2/btdZQbz83maZhQhH2UL4Zvoa7qgMX7Ou5jn1xpDaMeXNaajGK
|
||||
Fz66nmqQEUFX1i+2md2J8TeKD37yUJRdlrMiAc+RNp5wiOH9EI18g2m6h/nj3s/P
|
||||
MdNyxsz+wqOiJT0sZatarKiFhQKBgQDHv+lPy4OPH1MeSv5vmv3Pa41O/CeiPy+T
|
||||
gi6nEZayVRVog3zF9T6gNIHrZ1fdIppWPiPXv9fmC3s/IVEftLG6YC+MAfigYhiz
|
||||
Iceoal0iJJ8DglzOhlKgHEnxEwENCz8aJxjpvbxHHcpvgXdBSEVfHvVqDkAFTsvF
|
||||
JA5YTmqGXQKBgQCL6uqm2S7gq1o12p+PO4VbrjwAL3aiVLNl6Gtsxn2oSdIhDavr
|
||||
FLhNukMYFA4gwlcXb5au5k/6TG7bd+dgNDj8Jkm/27NcgVgpe9mJojQvfo0rQvXw
|
||||
yIvUd8JZ3SQEgTsU4X+Bb4eyp39TPwKrfxyh0qnj4QN6w1XfNmELX2nRaQKBgEq6
|
||||
a0ik9JTovSnKGKIcM/QTYow4HYO/a8cdnuJ13BDfb+DnwBg3BbTdr/UndmGOfnrh
|
||||
SHuAk/7GMNePWVApQ4xcS61vV1p5GJB7hLxm/my1kp+3d4z0B5lKvAbqeywsFvFr
|
||||
yxA3IWbhqEhLARh1Ny684EdLCXxy3Bzmvk8fFw8pAoGAGkt9pJC2wkk9fnJIHq+f
|
||||
h/WnEO0YrGzYnVA+RyCNKrimRd+GylGHJ/Ev6PRZvMwyGE7RCB+fHVrrEcEJAcxL
|
||||
SaOg5NA8cwrG+UpTQqi4gt6tCW87afVCyL6dC/E8giJlzI0LY9DnFGoVqYL0qJvm
|
||||
Sj4SU0fyLsW/csOLd5T+Bf8=
|
||||
-----END PRIVATE KEY-----
|
47
pkgs/tools/misc/rkvm/default.nix
Normal file
47
pkgs/tools/misc/rkvm/default.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{ lib
|
||||
, fetchFromGitHub
|
||||
, rustPlatform
|
||||
, pkg-config
|
||||
, libevdev
|
||||
, openssl
|
||||
, makeWrapper
|
||||
, nixosTests
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "rkvm";
|
||||
version = "0.5.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "htrefil";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-3IdwBMN+VZBrcoT5vF7pF6xoNWZBn4k/jRJqADlpM7k=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-/SZKJI4gMkike2m8UVzbwfMqj697A8zbJEKAnnbSx3s=";
|
||||
|
||||
nativeBuildInputs = [ pkg-config rustPlatform.bindgenHook makeWrapper ];
|
||||
buildInputs = [ libevdev ];
|
||||
|
||||
postInstall = ''
|
||||
install -Dm444 -t "$out/lib/systemd/system" systemd/rkvm-*.service
|
||||
install -Dm444 example/server.toml "$out/etc/rkvm/server.example.toml"
|
||||
install -Dm444 example/client.toml "$out/etc/rkvm/client.example.toml"
|
||||
|
||||
wrapProgram $out/bin/rkvm-certificate-gen --prefix PATH : ${lib.makeBinPath [ openssl ]}
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) rkvm;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Virtual KVM switch for Linux machines";
|
||||
homepage = "https://github.com/htrefil/rkvm";
|
||||
changelog = "https://github.com/htrefil/rkvm/releases/tag/${version}";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
maintainers = with maintainers; [ ckie ];
|
||||
};
|
||||
}
|
|
@ -12787,6 +12787,8 @@ with pkgs;
|
|||
|
||||
rkflashtool = callPackage ../tools/misc/rkflashtool { };
|
||||
|
||||
rkvm = callPackage ../tools/misc/rkvm { };
|
||||
|
||||
rkrlv2 = callPackage ../applications/audio/rkrlv2 { };
|
||||
|
||||
rmlint = callPackage ../tools/misc/rmlint {
|
||||
|
|
Loading…
Reference in a new issue