From 67a91d11e990fb32c28775f4e515b9dc35150b96 Mon Sep 17 00:00:00 2001 From: alexion Date: Tue, 11 Aug 2026 08:27:04 -0400 Subject: [PATCH] refactor(actualbudget): split service and guest config --- guests/actualbudget.nix | 60 ++++++++++++++++++++---------- hosts/pikachu/default.nix | 2 +- modules/services/actualbudget.nix | 61 +++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 modules/services/actualbudget.nix diff --git a/guests/actualbudget.nix b/guests/actualbudget.nix index d191a0a..b81e2eb 100644 --- a/guests/actualbudget.nix +++ b/guests/actualbudget.nix @@ -1,23 +1,43 @@ -args@{ my, ... }: -# Actual Budget in a NixOS guest, with durable state bind-mounted from the host. -my.guest { - name = "actualbudget"; - interior = { - users.users.actual = { - isSystemUser = true; - uid = 20001; - group = "storage"; - }; - - services.actual = { - enable = true; - openFirewall = true; - user = "actual"; - group = "storage"; - settings = { - port = 5006; - dataDir = "/data"; +{ + config, + lib, + my, + ... +}: +let + cfg = config.guests.actualbudget; + dataDir = "/data"; +in +{ + imports = [ + (my.guest { + name = "actualbudget"; + interior = { + modules.services.actualbudget = { + enable = true; + inherit dataDir; + }; }; + }) + ]; + + options.guests.actualbudget = { + dataPath = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "/srv/actualbudget"; + description = "Host path bind-mounted as Actual Budget's data directory."; }; }; -} args + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = cfg.dataPath != null; + message = "guests.actualbudget.dataPath must point at the host directory that stores Actual Budget data."; + } + ]; + + guests.actualbudget.mounts.${dataDir}.hostPath = cfg.dataPath; + }; +} diff --git a/hosts/pikachu/default.nix b/hosts/pikachu/default.nix index c30ca71..507ecb6 100644 --- a/hosts/pikachu/default.nix +++ b/hosts/pikachu/default.nix @@ -79,7 +79,7 @@ autoStart = false; vlan = 20; mac = "BC:24:11:C1:CD:28"; - mounts."/data".hostPath = "/pikachu/data/actualbudget"; + dataPath = "/pikachu/data/actualbudget"; limits = { memory = "2G"; cpu = "200%"; diff --git a/modules/services/actualbudget.nix b/modules/services/actualbudget.nix new file mode 100644 index 0000000..4ed8b44 --- /dev/null +++ b/modules/services/actualbudget.nix @@ -0,0 +1,61 @@ +{ + config, + lib, + ... +}: +let + cfg = config.modules.services.actualbudget; +in +{ + options.modules.services.actualbudget = { + enable = lib.mkEnableOption "Actual Budget"; + + port = lib.mkOption { + type = lib.types.port; + default = 5006; + description = "Port Actual Budget listens on."; + }; + + dataDir = lib.mkOption { + type = lib.types.str; + default = "/data"; + description = "Directory where Actual Budget stores server and user files."; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "actual"; + description = "User account that runs Actual Budget."; + }; + + uid = lib.mkOption { + type = lib.types.ints.positive; + default = 20001; + description = "Fixed uid for the Actual Budget service user."; + }; + + group = lib.mkOption { + type = lib.types.str; + default = "storage"; + description = "Group account that owns Actual Budget's writable state."; + }; + }; + + config = lib.mkIf cfg.enable { + users.users.${cfg.user} = { + isSystemUser = true; + uid = cfg.uid; + group = cfg.group; + }; + + services.actual = { + enable = true; + openFirewall = true; + user = cfg.user; + group = cfg.group; + settings = { + inherit (cfg) port dataDir; + }; + }; + }; +}