diff --git a/lib/default.nix b/lib/default.nix index d5450708..ccd40799 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -159,6 +159,7 @@ lib inputs.wsl.nixosModules.wsl { imports = (nixFiles ../platforms/nixos); } module + # (builtins.removeAttrs module [ "home-manager" ]) { home-manager = { extraSpecialArgs = { diff --git a/pkgs/actualtap/package.nix b/pkgs/actualtap/package.nix new file mode 100644 index 00000000..c8dc60ca --- /dev/null +++ b/pkgs/actualtap/package.nix @@ -0,0 +1,43 @@ +{ + lib, + buildNpmPackage, + fetchFromGitHub, + nodejs, +}: + +buildNpmPackage rec { + pname = "actualtap"; + version = "1.0.34"; + + src = fetchFromGitHub { + owner = "MattFaz"; + repo = "actualtap"; + rev = "v${version}"; + hash = "sha256-I2yb3WCOXYx/6RXiKjePlpChrr9G1il44OdON/SeVCw="; + }; + + npmDepsHash = "sha256-LlTLwUt0Yja4NSBLbaYPV/keawSJKffno/28rtSj/oQ="; + + dontNpmBuild = true; + + postPatch = '' + substituteInPlace src/server.js \ + --replace-fail 'port: 3001' 'port: process.env.PORT || 3001' + ''; + + postInstall = '' + mkdir -p $out/bin + cat < $out/bin/actualtap + #!/bin/sh + exec ${lib.getExe nodejs} $out/lib/node_modules/actualtap/src/server.js "\$@" + EOF + chmod +x $out/bin/actualtap + ''; + + meta = with lib; { + description = "Automatically create transactions in Actual Budget when you use Tap-to-Pay on a mobile device"; + homepage = "https://github.com/MattFaz/actualtap"; + license = licenses.gpl3Only; + maintainers = [ ]; + }; +} diff --git a/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix index e3545ef5..4cc0e04d 100644 --- a/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix +++ b/platforms/nixos/modules/nmasur/presets/services/actualbudget/actualbudget.nix @@ -109,8 +109,9 @@ in }; # Allow web traffic to Caddy - nmasur.presets.services.caddy.routes = [ + nmasur.presets.services.caddy.routes = lib.mkAfter [ { + group = "actual"; match = [ { host = [ hostnames.budget ]; } ]; handle = [ { diff --git a/platforms/nixos/modules/nmasur/presets/services/actualtap/actualtap.nix b/platforms/nixos/modules/nmasur/presets/services/actualtap/actualtap.nix new file mode 100644 index 00000000..4a362d63 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualtap/actualtap.nix @@ -0,0 +1,122 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + inherit (config.nmasur.settings) hostnames; + cfg = config.nmasur.presets.services.actualtap; + + actualtapConfigType = lib.types.submodule { + options = { + port = lib.mkOption { + type = lib.types.port; + description = "Port to use for the actualtap instance localhost"; + }; + path = lib.mkOption { + type = lib.types.str; + description = "Path prefix for this actualtap instance on the reverse proxy"; + }; + budgetIdFile = lib.mkOption { + type = lib.types.path; + description = "Path to the age encrypted file containing the budget ID"; + }; + apiKeyFile = lib.mkOption { + type = lib.types.path; + description = "Path to the age encrypted file containing the API key"; + }; + }; + }; + +in + +{ + options.nmasur.presets.services.actualtap = { + enable = lib.mkEnableOption "ActualTap instances"; + instances = lib.mkOption { + type = lib.types.attrsOf actualtapConfigType; + default = { }; + description = "Attribute set of ActualTap instances."; + }; + }; + + config = lib.mkIf cfg.enable { + + users.users.actualtap = { + isSystemUser = true; + group = "shared"; + uid = 981; + }; + + systemd.services = lib.mapAttrs' ( + name: instance: + lib.nameValuePair "actualtap-${name}" { + enable = true; + description = "ActualTap - ${name}"; + after = [ + "network.target" + "actual.service" + ]; + wantedBy = [ "multi-user.target" ]; + + environment = { + PORT = builtins.toString instance.port; + ACTUAL_URL = "http://127.0.0.1:${builtins.toString config.nmasur.presets.services.actualbudget.port}"; + }; + + serviceConfig = { + User = config.users.users.actualtap.name; + Group = config.users.users.actualtap.group; + EnvironmentFile = [ + config.secrets."actualbudget-password".dest + config.secrets."actualtap-${name}-budget-id".dest + config.secrets."actualtap-${name}-api-key".dest + ]; + ExecStart = lib.getExe pkgs.nmasur.actualtap; + Restart = "on-failure"; + WorkingDirectory = "/var/lib/actualtap-${name}"; + StateDirectory = "actualtap-${name}"; + }; + } + ) cfg.instances; + + secrets = lib.mkMerge ( + lib.mapAttrsToList (name: instance: { + "actualtap-${name}-budget-id" = { + source = instance.budgetIdFile; + dest = "${config.secretsDirectory}/actualtap-${name}-budget-id"; + owner = config.users.users.actualtap.name; + group = config.users.users.actualtap.group; + }; + "actualtap-${name}-api-key" = { + source = instance.apiKeyFile; + dest = "${config.secretsDirectory}/actualtap-${name}-api-key"; + owner = config.users.users.actualtap.name; + group = config.users.users.actualtap.group; + }; + }) cfg.instances + ); + + nmasur.presets.services.caddy.routes = lib.mapAttrsToList (name: instance: { + group = "actual"; + match = [ + { + host = [ hostnames.budget ]; + path = [ "${instance.path}*" ]; + } + ]; + handle = [ + { + handler = "rewrite"; + strip_path_prefix = instance.path; + } + { + handler = "reverse_proxy"; + upstreams = [ { dial = "localhost:${builtins.toString instance.port}"; } ]; + } + ]; + }) cfg.instances; + }; +} diff --git a/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-api-key.age b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-api-key.age new file mode 100644 index 00000000..080a6ef2 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-api-key.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBIUkxs +RmFmNmo3L2MwVVhmeTdUVGdXOWRIVDd5c21EVnhtWWUwTVpWbW5zCnNSS1luUHNW +YlIwbmVrbTJTUUdOQkpCbGpNQm1tYlRrbDhaWEhJUDRHaDQKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIHJIYTd4eFo3aklGQ1Evb0JPOGZSWDh1Q1pXU3ExZ1pmR29qT2lP +bFcwREkKTWFXMlZCeXpoMi92OXdtN3plekE2dFlCbk44YncxLzJYZzE2amNIVnEz +QQotPiBzc2gtZWQyNTUxOSBuanZYNUEgWi8rNnV4VWtwUEEzbys4Skl1Z0p0Ly9r +ZS82dzFJeEhHVHpSNU04WU5CVQpIMWhQcDdNeU45dVpkVyswQW1RK2Q0aXpkZXMz +MXAraG9KUFBDUVdFcTRVCi0+IHNzaC1lZDI1NTE5IENxSU9VQSBUQWQvU0JwdTlX +UkJYakdYTjU1YlBzWHEzY3FQa1dhMmp6UjE0RTJYN1ZBCmk0SWc0Ym1mUTdVL1NJ +ZXJFVkNmckRaVnlkSmUxL0dSUlo5VER0b2x3WVUKLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IHBIQllKcmczOVJvSzRMZW9mVjZjTFo1ZjVJNDRvUG9pSnlRZDBUWEtoV2sK +aGhPeUpkVEZ0QWxDM1VJZzlDWEZ2VnFuTFRCVDkzY2JLVWNQTUE2STMyRQotLS0g +cXhWR2lQWnkxOUZhRzhOTS96UDJWVmZEQVpZTkF1MmlpNCtEbDZzRGZaYwof4Y/t +N5osO/bY+ojbarYoCBq12NSaKKlL6MNy1OQZOuOF0IP1CZ0fLY+R9DgJcNol3I73 +q4JyXbfohWtG/2NdIwhRXumQ/OnY1maVvg== +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-id.age b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-id.age new file mode 100644 index 00000000..57c48d26 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget1-id.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyAyRTF0 +L3Y3ZVJ0YlJSbzR6cnNWeVNRd2czNUVKWmtQNFA3VFRlb053d1dRCmxmTGRGSFhL +UmlSdUVQNzVPcktIdE0yVWFhVGpGYVRPMEpNQll6Z0owNFEKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIHE5L09YNWFaT0JLT0o0YjdQY01GRDByeFVXeE9LMXNFNGFCWkFO +ZStBd28KamhUYzd1VXhlL3RqY3hlMG5UeGFJemY2ajRhVGZ2ZDJNb1hSRHkrUFNt +NAotPiBzc2gtZWQyNTUxOSBuanZYNUEgbDdMVzNTT1Y2VmVsZyt2WTh0RWdUVEpY +c0RoRWE2S2ZyZXFuTllFU1FVWQpmeDF0MEp2NEYxS2k1ZlJaTVNWMWdRRlJ1UWh2 +Wm0xbHhGYXhoWGtDbVkwCi0+IHNzaC1lZDI1NTE5IENxSU9VQSBJeERSTUpPbzhu +NGQrZXRoWGJEalBlMHdQUmlsVkF2TEZBOStOZ3ExN2lzClRZeE5yZG1uY3ZRRDNy +am5uTjRiTnpLSkhURWZTNzgyVVdOVDA2WlpqZmsKLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IGticUNqWDJ0RTJTZmdXdzVWM0xsejBvYUJ3MXZvNWw1OWE3aUJMTCtSQ2MK +KzMyZW5jZUNIV1puVFlLMEdyeUdoUUt3MjlzTUgvWlFob0QwME9ZZ1VVNAotLS0g +VU5nOFA0Nzd3ckhnRHdSNkVSNG9tZks5VmVoZnlmU1R6bzl4ZVdMcGlLTQqZWLkP +VdZPvgCJ8A9UcKWl+5f8Jjlc79d6ib8wwfMRl0zK4SNQJGgcXr6sFuieY3H4DzRb +MuqKZQBBIKtPAmrvmzcKgNSeiJoZjG801Jqd3lpkJEA= +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-api-key.age b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-api-key.age new file mode 100644 index 00000000..327579ca --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-api-key.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBSR2tx +b2FyZ2t0d2xONGIvYjJrcVU1VTNHT3RVbjlWT1IyUW1CM1BkNVNzCmJmNFFFbUR6 +WG9ncmhuakFzVHhSVEtZUlR4dWg3cWRzUXc2ZmVpZ3NqZ1EKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIGFFRmFsVjdkTkFZY29XdWo4akVDaEZHMTdXRDY4N2U5WE13a1JD +QWdXMkUKbnVXazZpSzZqTHJqamFUdDJMMUpiTEhLeTJqcVNmV2dncjVvZlNNT09M +WQotPiBzc2gtZWQyNTUxOSBuanZYNUEgTzV0eGpSU2plaTFCTXZTbFB2R1VOQnFn +d01EUXcza3JuR3RFUzE3N2MzawpqT0ZRQ1hPTFcvZ2ZOQjNGcThYL1lSdURXbWlv +NkRSRERJQ1IvSHdMa2M4Ci0+IHNzaC1lZDI1NTE5IENxSU9VQSBvQjZkYVJjYy9H +L3BSVWRPczlOOGV2RkRBSGlIakF1cG1yQk9tbXNWdWlZCnZGaGxvdkZVWXp2THhK +RnRBQ2VSNkErU0VnOWlYbkY2U1JCZTlBSFFUK0UKLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IFQrdUtDdENRK2dnN2t3dVBsN0oxYkNRSm43aDREa3ZJQjhvTWpxM0FWVEkK +OTNCVFRTclFFckFkQXBzWnBybWxKRm92TEFqRU5ZWkprdytJQm5RT2tOYwotLS0g +Nk5WZXhZM0VXaHpVK2EzeGFqNS9hZUlLQjlJRU9EMnVLL3VRV3RKTkVRcwpA8GqA +24oLFT1VIE5eNl/Ltd102W4J6jafmiizCEu3/7EULI/X5oh2LvjSjOuivW6y+Gbu +rXITu245mDM6ZqE2LikYR6134QSC2lmNvw== +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-id.age b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-id.age new file mode 100644 index 00000000..3b28ca28 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/actualtap/budget2-id.age @@ -0,0 +1,17 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyAyakVC +ZGZqMitTVVc0KzJSV0c3V3Ryc2JSWXp0V2I4YURmektyVGh5a2hBCjlCaGQ4SmxQ +VzhBRWw4SW9QamdVZDVvK3laVkNuWTRhMW1hR1ZmS1lqOWsKLT4gc3NoLWVkMjU1 +MTkgWXlTVU1RIE5oVVdMWHZlSEJ2akc1UVcrdnNNOWgzaGFhb2VWNlNxQU5yQzM0 +dGk3eGsKaE1Ba3BneC9yQTBpcXo3YWhqcDZheUJnbE5vS0Z0WUNzYnQ1a2o5OVN4 +YwotPiBzc2gtZWQyNTUxOSBuanZYNUEgcitOTmNKS04xc01LNTZKbE9QblVKRUVr +ZHdyY0Q2VWtUQ1VOQnFZTjNpbwp0RmNTV2RwR2RlcG5odE81VEFxNGhJOVFYd3Zk +TU9IanIzMFkxVU1GUlQwCi0+IHNzaC1lZDI1NTE5IENxSU9VQSBmRC92WjRkTVFz +eGlFa1VhcEk1NVpkVnFVVkpZRTdzMGR1aWNuWW9ZTFFVCkFRaVM5a1hjcjV3dU1m +WHNnSWhSN1l4ZVEwUkhXZVg3UFRZQStSVllFcEEKLT4gc3NoLWVkMjU1MTkgejFP +Y1p3IFUreGtraXo5aXM2OTFKcjZkL2p0ZEVwaEFXL3B5R2M1Q1J2elZYVityRUkK +bk80bnp1UzgzdmFqV0RJaVFhaytPWnJpQ0Y4Wmg1M2xLbGJyUzZzazlMUQotLS0g +dlZiRzZVSkYwbEVDaEVzZUhoRUkwMUpTM3pyOWJBaHUzZG8vejdmVklBYwpirejN +5cR1roLwVsunUkn+gnaMCYk+tDlaZABGXAC94k9RQVF06KquxeK0S17KOeQNn9Gb +N70JDklLLfuDsWbry6rIDYqsiEmTKi0WXhn44E1PaXQ= +-----END AGE ENCRYPTED FILE----- diff --git a/platforms/nixos/modules/nmasur/profiles/communications.nix b/platforms/nixos/modules/nmasur/profiles/communications.nix index 2e6e7118..0a22ceb1 100644 --- a/platforms/nixos/modules/nmasur/profiles/communications.nix +++ b/platforms/nixos/modules/nmasur/profiles/communications.nix @@ -21,6 +21,23 @@ in }; services = { actualbudget.enable = lib.mkDefault true; + actualtap = { + enable = lib.mkDefault true; + instances = { + budget1 = { + port = 3031; + path = "/actualtap1"; + budgetIdFile = ../presets/services/actualtap/budget1-id.age; + apiKeyFile = ../presets/services/actualtap/budget1-api-key.age; + }; + budget2 = { + port = 3032; + path = "/actualtap2"; + budgetIdFile = ../presets/services/actualtap/budget2-id.age; + apiKeyFile = ../presets/services/actualtap/budget2-api-key.age; + }; + }; + }; caddy.enable = lib.mkDefault true; cloudflare.enable = lib.mkDefault true; cloudflared.enable = lib.mkDefault true;