at master 3.9 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 cfg = config.services.paisa; 9 settingsFormat = pkgs.formats.yaml { }; 10 11 args = lib.concatStringsSep " " [ 12 "--config /var/lib/paisa/paisa.yaml" 13 ]; 14 15 settings = 16 if (cfg.settings != null) then 17 builtins.removeAttrs 18 ( 19 cfg.settings 20 // { 21 journal_path = cfg.settings.dataDir + cfg.settings.journalFile; 22 db_path = cfg.settings.dataDir + cfg.settings.dbFile; 23 } 24 ) 25 [ 26 "dataDir" 27 "journalFile" 28 "dbFile" 29 ] 30 else 31 null; 32 33 configFile = (settingsFormat.generate "paisa.yaml" settings).overrideAttrs (_: { 34 checkPhase = ""; 35 }); 36in 37{ 38 options.services.paisa = with lib.types; { 39 enable = lib.mkEnableOption "Paisa personal finance manager"; 40 41 package = lib.mkPackageOption pkgs "paisa" { }; 42 43 openFirewall = lib.mkOption { 44 default = false; 45 type = bool; 46 description = "Open ports in the firewall for the Paisa web server."; 47 }; 48 49 mutableSettings = lib.mkOption { 50 default = true; 51 type = bool; 52 description = '' 53 Allow changes made on the web interface to persist between service 54 restarts. 55 ''; 56 }; 57 58 host = lib.mkOption { 59 type = str; 60 default = "0.0.0.0"; 61 description = "Host bind IP address."; 62 }; 63 64 port = lib.mkOption { 65 type = port; 66 default = 7500; 67 description = "Port to serve Paisa on."; 68 }; 69 70 settings = lib.mkOption { 71 default = null; 72 type = nullOr (submodule { 73 freeformType = settingsFormat.type; 74 options = { 75 dataDir = lib.mkOption { 76 type = lib.types.str; 77 default = "/var/lib/paisa/"; 78 description = "Path to paisa data directory."; 79 }; 80 81 journalFile = lib.mkOption { 82 type = lib.types.str; 83 default = "main.ledger"; 84 description = "Filename of the main journal / ledger file."; 85 }; 86 87 dbFile = lib.mkOption { 88 type = lib.types.str; 89 default = "paisa.sqlite3"; 90 description = "Filename of the Paisa database."; 91 }; 92 93 }; 94 }); 95 description = '' 96 Paisa configuration. Please refer to 97 <https://paisa.fyi/reference/config/> for details. 98 99 On start and if `mutableSettings` is `true`, these options are merged 100 into the configuration file on start, taking precedence over 101 configuration changes made on the web interface. 102 ''; 103 }; 104 }; 105 config = lib.mkIf cfg.enable { 106 assertions = [ ]; 107 108 systemd.services.paisa = { 109 description = "Paisa: Web Application"; 110 after = [ "network.target" ]; 111 wantedBy = [ "multi-user.target" ]; 112 unitConfig = { 113 StartLimitIntervalSec = 5; 114 StartLimitBurst = 10; 115 }; 116 117 preStart = lib.optionalString (settings != null) '' 118 if [ -e "$STATE_DIRECTORY/paisa.yaml" ] && [ "${toString cfg.mutableSettings}" = "1" ]; then 119 # do not write directly to the config file 120 ${lib.getExe pkgs.yaml-merge} "$STATE_DIRECTORY/paisa.yaml" "${configFile}" > "$STATE_DIRECTORY/paisa.yaml.tmp" 121 mv "$STATE_DIRECTORY/paisa.yaml.tmp" "$STATE_DIRECTORY/paisa.yaml" 122 else 123 cp --force "${configFile}" "$STATE_DIRECTORY/paisa.yaml" 124 chmod 600 "$STATE_DIRECTORY/paisa.yaml" 125 fi 126 ''; 127 128 serviceConfig = { 129 DynamicUser = true; 130 ExecStart = "${lib.getExe cfg.package} serve ${args}"; 131 AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; 132 Restart = "always"; 133 RestartSec = 5; 134 RuntimeDirectory = "paisa"; 135 StateDirectory = "paisa"; 136 }; 137 }; 138 networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ cfg.port ]; 139 }; 140 141 meta = { 142 maintainers = with lib.maintainers; [ skowalak ]; 143 doc = ./paisa.md; 144 }; 145}