nix: add module + VM configs
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -22,4 +22,6 @@ dist/
|
||||
|
||||
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`
|
||||
|
||||
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 {
|
||||
apps = forAllSystems (system: pkgs: let
|
||||
mkApp = package: {
|
||||
mkApp = program: description: {
|
||||
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 {
|
||||
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: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
@@ -66,8 +87,6 @@
|
||||
};
|
||||
});
|
||||
|
||||
overlays.default = final: prev: self.packages.${final.system};
|
||||
|
||||
packages = forAllSystems (system: pkgs: {
|
||||
default = self.packages.${system}.worblehat;
|
||||
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