feat(actualbudget): add NixOS guest
This commit was merged in pull request #42.
This commit is contained in:
@@ -18,6 +18,8 @@ The domain model (Host, Module, Skeleton, Auto-loader, Enable convention, overla
|
|||||||
|
|
||||||
## Gotchas
|
## Gotchas
|
||||||
|
|
||||||
|
- Actual Budget's NixOS service runs `actual-server` with `WorkingDirectory = services.actual.settings.dataDir`, and the `actual-server` CLI wrapper sets `ACTUAL_CONFIG_PATH=./config.json` when that current directory contains `config.json`, overriding the NixOS module's generated config path before the server loads configuration.
|
||||||
|
When migrating old community-script state to the normal upstream `/data` shape, move or rewrite a copied `/data/config.json` so it cannot shadow the declarative module settings.
|
||||||
- Subagent completion delivery is non-blocking through immediate spawn, milestone notifications, retained terminal entries, and `subagent_list` or `subagent_result` retrieval.
|
- Subagent completion delivery is non-blocking through immediate spawn, milestone notifications, retained terminal entries, and `subagent_list` or `subagent_result` retrieval.
|
||||||
`subagent_wait` intentionally blocks the parent tool call until its condition or timeout, so do not use it merely to keep background work alive during an interactive workflow.
|
`subagent_wait` intentionally blocks the parent tool call until its condition or timeout, so do not use it merely to keep background work alive during an interactive workflow.
|
||||||
- Nixvim's flake input following the root nixpkgs source does not make its Home Manager module reuse the host's `pkgs` instance.
|
- Nixvim's flake input following the root nixpkgs source does not make its Home Manager module reuse the host's `pkgs` instance.
|
||||||
|
|||||||
50
guests/actualbudget.nix
Normal file
50
guests/actualbudget.nix
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
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.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
limits = {
|
||||||
|
memory = lib.mkDefault "2G";
|
||||||
|
cpu = lib.mkDefault "200%";
|
||||||
|
tasksMax = lib.mkDefault 512;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,14 +20,45 @@
|
|||||||
|
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
networks."10-uplink" = {
|
netdevs = {
|
||||||
matchConfig.MACAddress = "78:55:36:07:af:49";
|
"40-br-vlan20".netdevConfig = {
|
||||||
networkConfig.DHCP = "yes";
|
Name = "br-vlan20";
|
||||||
linkConfig.RequiredForOnline = "routable";
|
Kind = "bridge";
|
||||||
|
};
|
||||||
|
"40-vlan20" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = "vlan20";
|
||||||
|
Kind = "vlan";
|
||||||
|
};
|
||||||
|
vlanConfig.Id = 20;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networks = {
|
||||||
|
"10-uplink" = {
|
||||||
|
matchConfig = {
|
||||||
|
Name = "enp2s0";
|
||||||
|
MACAddress = "78:55:36:07:af:49";
|
||||||
|
};
|
||||||
|
networkConfig.DHCP = "yes";
|
||||||
|
vlan = [ "vlan20" ];
|
||||||
|
linkConfig.RequiredForOnline = "routable";
|
||||||
|
};
|
||||||
|
"40-vlan20" = {
|
||||||
|
matchConfig.Name = "vlan20";
|
||||||
|
networkConfig.Bridge = "br-vlan20";
|
||||||
|
linkConfig.RequiredForOnline = "no";
|
||||||
|
};
|
||||||
|
"40-br-vlan20" = {
|
||||||
|
matchConfig.Name = "br-vlan20";
|
||||||
|
linkConfig.RequiredForOnline = "no";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
networking.useDHCP = false;
|
networking.useDHCP = false;
|
||||||
|
|
||||||
|
modules.network.vlans = [ 20 ];
|
||||||
|
|
||||||
boot.zfs.forceImportRoot = false;
|
boot.zfs.forceImportRoot = false;
|
||||||
|
|
||||||
modules.zfs = {
|
modules.zfs = {
|
||||||
@@ -43,6 +74,13 @@
|
|||||||
modules.git.enable = true;
|
modules.git.enable = true;
|
||||||
modules.toolkit.enable = true;
|
modules.toolkit.enable = true;
|
||||||
|
|
||||||
|
guests.actualbudget = {
|
||||||
|
enable = true;
|
||||||
|
vlan = 20;
|
||||||
|
mac = "BC:24:11:C1:CD:28";
|
||||||
|
dataPath = "/pikachu/data/actualbudget";
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
pciutils
|
pciutils
|
||||||
smartmontools
|
smartmontools
|
||||||
|
|||||||
61
modules/services/actualbudget.nix
Normal file
61
modules/services/actualbudget.nix
Normal file
@@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user