From 87d394e4c144eb07363a0be260ecf6cce79d49df Mon Sep 17 00:00:00 2001 From: Vegard Bieker Matthey Date: Tue, 17 Mar 2026 14:22:48 +0100 Subject: [PATCH] drumknotty WIP --- flake.lock | 46 +++++++- flake.nix | 6 +- modules/drumknotty.nix | 255 +++++++++++++++++++++++++++++++++++++++++ modules/wasted.nix | 15 --- 4 files changed, 305 insertions(+), 17 deletions(-) create mode 100644 modules/drumknotty.nix delete mode 100644 modules/wasted.nix diff --git a/flake.lock b/flake.lock index 870c0d4..9c1862c 100644 --- a/flake.lock +++ b/flake.lock @@ -124,6 +124,27 @@ "url": "https://git.pvv.ntnu.no/Grzegorz/grzegorz-clients.git" } }, + "libdib": { + "inputs": { + "nixpkgs": [ + "worblehat", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769338528, + "narHash": "sha256-t18ZoSt9kaI1yde26ok5s7aFLkap1Q9+/2icVh2zuaE=", + "ref": "refs/heads/main", + "rev": "7218348163fd8d84df4a6f682c634793e67a3fed", + "revCount": 13, + "type": "git", + "url": "https://git.pvv.ntnu.no/Projects/libdib.git" + }, + "original": { + "type": "git", + "url": "https://git.pvv.ntnu.no/Projects/libdib.git" + } + }, "matrix-next": { "inputs": { "nixpkgs": [ @@ -353,7 +374,8 @@ "pvv-nettsiden": "pvv-nettsiden", "qotd": "qotd", "roowho2": "roowho2", - "sops-nix": "sops-nix" + "sops-nix": "sops-nix", + "worblehat": "worblehat" } }, "roowho2": { @@ -461,6 +483,28 @@ "repo": "sops-nix", "type": "github" } + }, + "worblehat": { + "inputs": { + "libdib": "libdib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1770887951, + "narHash": "sha256-6LGqM9yhONtfCXHtPNn3S0GFsmB2dCchyozHDevwmiQ=", + "ref": "main", + "rev": "911063041f24d594a772a2a699d71d3d94953ce8", + "revCount": 101, + "type": "git", + "url": "https://git.pvv.ntnu.no/Projects/worblehat.git" + }, + "original": { + "ref": "main", + "type": "git", + "url": "https://git.pvv.ntnu.no/Projects/worblehat.git" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b36146b..029fcaf 100644 --- a/flake.nix +++ b/flake.nix @@ -193,8 +193,12 @@ modules = [ inputs.disko.nixosModules.disko inputs.dibbler.nixosModules.default + inputs.worblehat.nixosModules.default + ]; + overlays = [ + inputs.dibbler.overlays.default + inputs.worblehat.overlyas.default ]; - overlays = [inputs.dibbler.overlays.default]; }; shark = stableNixosConfig "shark" { }; wenche = stableNixosConfig "wenche" { }; diff --git a/modules/drumknotty.nix b/modules/drumknotty.nix new file mode 100644 index 0000000..3464fd6 --- /dev/null +++ b/modules/drumknotty.nix @@ -0,0 +1,255 @@ +{ + config, + pkgs, + lib, + ... +}: +let + cfg = config.services.drumknotty; + + format = pkgs.formats.toml { }; +in +{ + options.services.drumknotty = { + enable = lib.mkEnableOption "DrumknoTTY"; + + dibblerPackage = lib.mkPackageOption pkgs "dibbler" { }; + worblehatPackage = lib.mkPackageOption pkgs "worblehat" { }; + screenPackage = lib.mkPackageOption pkgs "screen" { }; + + screenSessionName = lib.mkOption { + type = lib.types.str; + default = "drumknotty"; + example = "myscreensessionname"; + description = '' + Sets the screen session name. + ''; + }; + + createLocalDatabase = lib.mkEnableOption "" // { + description = '' + Whether to set up a local postgres database automatically. + + ::: {.note} + You must set up postgres manually before enabling this option. + ::: + ''; + }; + + kioskMode = lib.mkEnableOption "" // { + description = '' + Whether to let dibbler take over the entire machine. + + This will restrict the machine to a single TTY and make the program unquittable. + You can still get access to PTYs via SSH and similar, if enabled. + ''; + }; + + limitScreenHeight = lib.mkOption { + type = with lib.types; nullOr ints.unsigned; + default = null; + example = 42; + description = '' + If set, limits the height of the screen dibbler uses to the given number of lines. + ''; + }; + + limitScreenWidth = lib.mkOption { + type = with lib.types; nullOr ints.unsigned; + default = null; + example = 80; + description = '' + If set, limits the width of the screen dibbler uses to the given number of columns. + ''; + }; + + dibblerSettings = lib.mkOption { + description = "Configuration for dibbler"; + default = { }; + type = lib.types.submodule { + freeformType = format.type; + }; + }; + + worblehatSettings = lib.mkOption { + description = "Configuration for worblehat"; + default = { }; + type = lib.types.submodule { + freeformType = format.type; + }; + }; + + }; + + config = lib.mkIf cfg.enable ( + { + environment.systemPackages = [ + cfg.dibblerPackage + cfg.worblehatPackage + ]; + + environment.etc."dibbler/dibbler.toml".source = format.generate "dibbler.toml" cfg.dibblerSettings; + environment.etc."worblehat/config.toml".source = + format.generate "worblehat-config.toml" cfg.worblehatSettings; + + users = { + users.drumknotty = { + group = "drumknotty"; + isNormalUser = true; + }; + groups.drumknotty = { }; + }; + + services.dibbler.settings.database = lib.mkIf cfg.createLocalDatabase { + type = "postgresql"; + postgresql.host = "/run/postgresql"; + }; + + services.postgresql = lib.mkIf cfg.createLocalDatabase { + ensureDatabases = [ + "dibbler" + "worblehat" + ]; + ensureUsers = [ + { + name = "drumknotty"; + ensureDBOwnership = true; + ensureClauses.login = true; + } + ]; + }; + + systemd.services.dibbler-setup-database = lib.mkIf cfg.createLocalDatabase { + description = "Dibbler database setup"; + wantedBy = [ "default.target" ]; + after = [ "postgresql.service" ]; + unitConfig = { + ConditionPathExists = "!/var/lib/dibbler/.db-setup-done"; + }; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${lib.getExe cfg.dibblerPackage} --config /etc/dibbler/dibbler.toml create-db"; + ExecStartPost = "${lib.getExe' pkgs.coreutils "touch"} /var/lib/dibbler/.db-setup-done"; + StateDirectory = "dibbler"; + + User = "drumknotty"; + Group = "drumknotty"; + }; + }; + + systemd.services.worblehat-setup-database = lib.mkIf cfg.createLocalDatabase { + description = "Worblehat database setup"; + wantedBy = [ "default.target" ]; + after = [ "postgresql.service" ]; + unitConfig = { + ConditionPathExists = "!/var/lib/worblehat/.db-setup-done"; + }; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${lib.getExe cfg.worblehatPackage} --config /etc/worblehat/config.toml create-db"; + ExecStartPost = "${lib.getExe' pkgs.coreutils "touch"} /var/lib/worblehat/.db-setup-done"; + StateDirectory = "worblehat"; + + User = "drumknotty"; + Group = "drumknotty"; + }; + }; + + } + ( + lib.mkIf cfg.kioskMode { + boot.kernelParams = [ + "console=tty1" + ]; + + users.users.drumknotty = { + extraGroups = [ "lp" ]; + shell = + (pkgs.writeShellScriptBin "login-shell" "${lib.getExe' cfg.screenPackage "screen"} -x ${cfg.screenSessionName}") + // { + shellPath = "/bin/login-shell"; + }; + }; + + services.drumknotty.settings.general = { + quit_allowed = false; + stop_allowed = false; + }; + + systemd.services.drumknotty-screen-session = { + description = "Drumknotty Screen Session"; + wantedBy = [ + "default.target" + ]; + after = + if cfg.createLocalDatabase then + [ + "postgresql.service" + "dibbler-setup-database.service" + "worblehat-setup-database.service" + ] + else + [ + "network.target" + ]; + serviceConfig = + let + dibblerArgs = lib.cli.toCommandLineShellGNU { } { + config = "/etc/dibbler/dibbler.toml"; + }; + + worblehatArgs = lib.cli.toCommandLineShellGNU { } { + config = "/etc/worblehat/config.toml"; + }; + + in + { + Type = "forking"; + RemainAfterExit = false; + Restart = "always"; + RestartSec = "5s"; + SuccessExitStatus = 1; + + User = "drumknotty"; + Group = "drumknotty"; + + ExecStartPre = "-${lib.getExe' cfg.screenPackage "screen"} -X -S ${cfg.screenSessionName} kill"; + ExecStart = + let + screenArgs = lib.escapeShellArgs [ + # -dm creates the screen in detached mode without accessing it + "-dm" + + # Session name + "-S" + "drumknotty" + + # Window name + "-t" + "dibbler" + + # Set optimal output mode instead of VT100 emulation + "-O" + + # Enable login mode, updates utmp entries + "-l" + ]; + + in + "${lib.getExe' cfg.screenPackage "screen"} ${screenArgs} ${lib.getExe cfg.dibblerPackage} ${dibblerArgs} loop"; + ExecStartPost = + "${lib.getExe' cfg.screenPackage "screen"} -X -S ${cfg.screenSessionName} -t worblehat ${lib.getExe cfg.worblehatPackage} ${worblehatArgs} cli" + ++ lib.optionals (cfg.limitScreenWidth != null) [ + "${lib.getExe' cfg.screenPackage "screen"} -X -S ${cfg.screenSessionName} width ${toString cfg.limitScreenWidth}" + ] + ++ lib.optionals (cfg.limitScreenHeight != null) [ + "${lib.getExe' cfg.screenPackage "screen"} -X -S ${cfg.screenSessionName} height ${toString cfg.limitScreenHeight}" + ]; + }; + }; + + services.getty.autologinUser = "drumknotty"; + } + ) + ); +} diff --git a/modules/wasted.nix b/modules/wasted.nix deleted file mode 100644 index 97933a5..0000000 --- a/modules/wasted.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ - config, - lib, - pkgs, - unstablePkgs, - values, - ... -}: -let - dibbler = config.services.dibbler; - worblehat = config.services.worblehat; - machine = config.networking.hostName; -in -{ -}