nix: add module + VM configs
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -22,4 +22,6 @@ dist/
|
|||||||
|
|
||||||
result
|
result
|
||||||
|
|
||||||
config.toml
|
config.toml
|
||||||
|
|
||||||
|
*.qcow2
|
||||||
|
|||||||
26
README.md
26
README.md
@@ -44,3 +44,29 @@ Unless provided through the `--config` flag, program will automatically look for
|
|||||||
- `/var/lib/worblehat/config.toml`
|
- `/var/lib/worblehat/config.toml`
|
||||||
|
|
||||||
Run `uv run worblehat --help` for more info
|
Run `uv run worblehat --help` for more info
|
||||||
|
|
||||||
|
## Development with nix
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> We have created some nix code to generate a QEMU VM with a setup similar to a production deployment
|
||||||
|
> There is not necessarily any VMs running in a production setup, and if so then at least not this VM.
|
||||||
|
> It is mainly there for easy access to interactive testing, as well as for testing the NixOS module.
|
||||||
|
|
||||||
|
You can easily start developing this with nix, by running the test VM:
|
||||||
|
|
||||||
|
```console
|
||||||
|
nix run .#vm
|
||||||
|
|
||||||
|
# Or if you need access to a proper shell in the VM as well:
|
||||||
|
nix run .#vm-non-kiosk
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also build the nix package, or run the executable directly:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Build package
|
||||||
|
nix build .#
|
||||||
|
|
||||||
|
# Run the executable (after building package)
|
||||||
|
nix run .#
|
||||||
|
```
|
||||||
|
|||||||
29
flake.nix
29
flake.nix
@@ -47,14 +47,35 @@
|
|||||||
|
|
||||||
in {
|
in {
|
||||||
apps = forAllSystems (system: pkgs: let
|
apps = forAllSystems (system: pkgs: let
|
||||||
mkApp = package: {
|
mkApp = program: description: {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = lib.getExe package;
|
program = toString program;
|
||||||
|
meta = {
|
||||||
|
inherit description;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
mkVm = name: mkApp "${self.nixosConfigurations.${name}.config.system.build.vm}/bin/run-nixos-vm";
|
||||||
in {
|
in {
|
||||||
default = mkApp self.packages.${system}.default;
|
default = self.apps.${system}.worblehat;
|
||||||
|
worblehat = mkApp (lib.getExe self.packages.${system}.worblehat) "Run worblehat without any setup";
|
||||||
|
vm = mkVm "vm" "Start a NixOS VM with worblehat installed in kiosk-mode";
|
||||||
|
vm-non-kiosk = mkVm "vm-non-kiosk" "Start a NixOS VM with worblehat installed in nonkiosk-mode";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
nixosModules.default = import ./nix/module.nix;
|
||||||
|
|
||||||
|
nixosConfigurations = {
|
||||||
|
vm = import ./nix/nixos-configurations/vm.nix { inherit self nixpkgs; };
|
||||||
|
vm-non-kiosk = import ./nix/nixos-configurations/vm-non-kiosk.nix { inherit self nixpkgs; };
|
||||||
|
};
|
||||||
|
|
||||||
|
overlays = {
|
||||||
|
default = self.overlays.worblehat;
|
||||||
|
worblehat = final: prev: {
|
||||||
|
inherit (self.packages.${prev.stdenv.hostPlatform.system}) worblehat;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
devShells = forAllSystems (_: pkgs: {
|
devShells = forAllSystems (_: pkgs: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
@@ -66,8 +87,6 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
overlays.default = final: prev: self.packages.${final.system};
|
|
||||||
|
|
||||||
packages = forAllSystems (system: pkgs: {
|
packages = forAllSystems (system: pkgs: {
|
||||||
default = self.packages.${system}.worblehat;
|
default = self.packages.${system}.worblehat;
|
||||||
worblehat = let
|
worblehat = let
|
||||||
|
|||||||
191
nix/module.nix
Normal file
191
nix/module.nix
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
{ config, pkgs, lib, ... }: let
|
||||||
|
cfg = config.services.worblehat;
|
||||||
|
|
||||||
|
format = pkgs.formats.toml { };
|
||||||
|
in {
|
||||||
|
options.services.worblehat = {
|
||||||
|
enable = lib.mkEnableOption "worblehat, the little kiosk library";
|
||||||
|
|
||||||
|
package = lib.mkPackageOption pkgs "worblehat" { };
|
||||||
|
|
||||||
|
screenPackage = lib.mkPackageOption pkgs "screen" { };
|
||||||
|
|
||||||
|
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 worblehat 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 worblehat 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 worblehat uses to the given number of columns.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
settings = lib.mkOption {
|
||||||
|
description = "Configuration for worblehat";
|
||||||
|
default = { };
|
||||||
|
type = lib.types.submodule {
|
||||||
|
freeformType = format.type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
{
|
||||||
|
services.worblehat.settings = lib.pipe ../config-template.toml [
|
||||||
|
builtins.readFile
|
||||||
|
builtins.fromTOML
|
||||||
|
(x: lib.recursiveUpdate x {
|
||||||
|
flask = {
|
||||||
|
TESTING = false;
|
||||||
|
DEBUG = false;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.mapAttrsRecursive (_: lib.mkDefault))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
environment.systemPackages = [ cfg.package ];
|
||||||
|
|
||||||
|
environment.etc."worblehat/config.toml".source = format.generate "worblehat-config.toml" cfg.settings;
|
||||||
|
|
||||||
|
users = {
|
||||||
|
users.worblehat = {
|
||||||
|
group = "worblehat";
|
||||||
|
isNormalUser = true;
|
||||||
|
};
|
||||||
|
groups.worblehat = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
services.worblehat.settings.database.type = "postgresql";
|
||||||
|
services.worblehat.settings.database.postgresql = {
|
||||||
|
host = "/run/postgresql";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = lib.mkIf cfg.createLocalDatabase {
|
||||||
|
ensureDatabases = [ "worblehat" ];
|
||||||
|
ensureUsers = [{
|
||||||
|
name = "worblehat";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
ensureClauses.login = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.worblehat-setup-database = lib.mkIf cfg.createLocalDatabase {
|
||||||
|
description = "Dibbler database setup";
|
||||||
|
wantedBy = [ "default.target" ];
|
||||||
|
after = [ "postgresql.service" ];
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/var/lib/worblehat/.db-setup-done";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${lib.getExe cfg.package} --config /etc/worblehat/config.toml create-db";
|
||||||
|
ExecStartPost = "${lib.getExe' pkgs.coreutils "touch"} /var/lib/worblehat/.db-setup-done";
|
||||||
|
StateDirectory = "worblehat";
|
||||||
|
|
||||||
|
User = "worblehat";
|
||||||
|
Group = "worblehat";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(lib.mkIf cfg.kioskMode {
|
||||||
|
boot.kernelParams = [
|
||||||
|
"console=tty1"
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users.worblehat = {
|
||||||
|
extraGroups = [ "lp" ];
|
||||||
|
shell = (pkgs.writeShellScriptBin "login-shell" "${lib.getExe cfg.screenPackage} -x worblehat") // {
|
||||||
|
shellPath = "/bin/login-shell";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.worblehat.settings.general = {
|
||||||
|
quit_allowed = false;
|
||||||
|
stop_allowed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.worblehat-screen-session = {
|
||||||
|
description = "Worblehat Screen Session";
|
||||||
|
wantedBy = [
|
||||||
|
"default.target"
|
||||||
|
];
|
||||||
|
after = if cfg.createLocalDatabase then [
|
||||||
|
"postgresql.service"
|
||||||
|
"worblehat-setup-database.service"
|
||||||
|
] else [
|
||||||
|
"network.target"
|
||||||
|
];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "forking";
|
||||||
|
RemainAfterExit = false;
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = "5s";
|
||||||
|
SuccessExitStatus = 1;
|
||||||
|
|
||||||
|
User = "worblehat";
|
||||||
|
Group = "worblehat";
|
||||||
|
|
||||||
|
ExecStartPre = "-${lib.getExe cfg.screenPackage} -X -S worblehat kill";
|
||||||
|
ExecStart = let
|
||||||
|
screenArgs = lib.escapeShellArgs [
|
||||||
|
# -dm creates the screen in detached mode without accessing it
|
||||||
|
"-dm"
|
||||||
|
|
||||||
|
# Session name
|
||||||
|
"-S"
|
||||||
|
"worblehat"
|
||||||
|
|
||||||
|
# Set optimal output mode instead of VT100 emulation
|
||||||
|
"-O"
|
||||||
|
|
||||||
|
# Enable login mode, updates utmp entries
|
||||||
|
"-l"
|
||||||
|
];
|
||||||
|
|
||||||
|
worblehatArgs = lib.cli.toCommandLineShellGNU { } {
|
||||||
|
config = "/etc/worblehat/config.toml";
|
||||||
|
};
|
||||||
|
|
||||||
|
in "${lib.getExe cfg.screenPackage} ${screenArgs} ${lib.getExe cfg.package} ${worblehatArgs} cli";
|
||||||
|
ExecStartPost =
|
||||||
|
lib.optionals (cfg.limitScreenWidth != null) [
|
||||||
|
"${lib.getExe cfg.screenPackage} -X -S worblehat width ${toString cfg.limitScreenWidth}"
|
||||||
|
]
|
||||||
|
++ lib.optionals (cfg.limitScreenHeight != null) [
|
||||||
|
"${lib.getExe cfg.screenPackage} -X -S worblehat height ${toString cfg.limitScreenHeight}"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.getty.autologinUser = "worblehat";
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
||||||
54
nix/nixos-configurations/vm-non-kiosk.nix
Normal file
54
nix/nixos-configurations/vm-non-kiosk.nix
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{ self, nixpkgs, ... }:
|
||||||
|
nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
overlays = [
|
||||||
|
self.overlays.worblehat
|
||||||
|
];
|
||||||
|
};
|
||||||
|
modules = [
|
||||||
|
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
|
||||||
|
"${nixpkgs}/nixos/tests/common/user-account.nix"
|
||||||
|
|
||||||
|
self.nixosModules.default
|
||||||
|
|
||||||
|
({ config, ... }: {
|
||||||
|
system.stateVersion = config.system.nixos.release;
|
||||||
|
virtualisation.graphics = false;
|
||||||
|
|
||||||
|
users.motd = ''
|
||||||
|
=================================
|
||||||
|
Welcome to the worblehat non-kiosk vm!
|
||||||
|
|
||||||
|
Try running:
|
||||||
|
${config.services.worblehat.package.meta.mainProgram} cli
|
||||||
|
|
||||||
|
Password for worblehat is 'worblehat'
|
||||||
|
|
||||||
|
To exit, press Ctrl+A, then X
|
||||||
|
=================================
|
||||||
|
'';
|
||||||
|
|
||||||
|
users.users.worblehat = {
|
||||||
|
isNormalUser = true;
|
||||||
|
password = "worblehat";
|
||||||
|
extraGroups = [ "wheel" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.getty.autologinUser = "worblehat";
|
||||||
|
|
||||||
|
programs.vim = {
|
||||||
|
enable = true;
|
||||||
|
defaultEditor = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql.enable = true;
|
||||||
|
|
||||||
|
services.worblehat = {
|
||||||
|
enable = true;
|
||||||
|
createLocalDatabase = true;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
35
nix/nixos-configurations/vm.nix
Normal file
35
nix/nixos-configurations/vm.nix
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{ self, nixpkgs, ... }:
|
||||||
|
nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
overlays = [
|
||||||
|
self.overlays.default
|
||||||
|
];
|
||||||
|
};
|
||||||
|
modules = [
|
||||||
|
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
|
||||||
|
"${nixpkgs}/nixos/tests/common/user-account.nix"
|
||||||
|
|
||||||
|
self.nixosModules.default
|
||||||
|
|
||||||
|
({ config, ... }: {
|
||||||
|
system.stateVersion = config.system.nixos.release;
|
||||||
|
virtualisation.graphics = false;
|
||||||
|
|
||||||
|
services.postgresql.enable = true;
|
||||||
|
|
||||||
|
services.worblehat = {
|
||||||
|
enable = true;
|
||||||
|
createLocalDatabase = true;
|
||||||
|
kioskMode = true;
|
||||||
|
settings = {
|
||||||
|
flask = {
|
||||||
|
TESTING = true;
|
||||||
|
DEBUG = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user