-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
basic config set that makes the service at least start add secmod helpers and taler-global runtime dir support for includes taler denominations Only enable services if taler is enabled fix wirewatch service name use correct permissions for database schema The current permissions don't work or aren't enough and cause the wirewatch and closer services to fail. nixos/libeufin: init module libeufin: refactor module libeufin: add main service nixos/taler: configure settings using options Works, but can be refactored further taler: refactor settings options trim settings defaults to the absolutely necessary ones nixos/libeufin: refactor and move to separate dir nixos/libeufin: set defaultText nixos/libeufin: use getExe nixos/libeufin-bank: move to own dir nixos/libeufin: move libeufin related config into its own config file nixos/libeufin/bank: extract dbinitServiceName into var nixos/libeufin: move script to ExecStart nixos/libeufin: fix config file name nixos/taler: refactor config file nixos/taler-exchange: grant delete to taler-exchange-aggregator Would repeatedly attempt to delete in a table where it wasn't allowed to and cause insane spam in the postgres log. nixos/taler/exchange: move exchange-specific options to exchange nixos/taler: move generic taler settings into taler system module nixos/taler: import exchange in module-list.nix nixos/taler-exchange: refactor services group name nixos/taler-exchange: use taler-harness to generate coins The taler-wallet-cli does not have the deployment subcommand anymore, but the docs still say that it should be used to generate the keys. For now, the keys should be generated with taler-harness. nixos/taler-exchange: add option to enable accounts nixos/taler: add missing descriptions nixos/taler(exchange): add description & use getExe' nixos/taler(merchant): init submodule nixos/taler: use correct script for db access nixos/taler: merchant add depositcheck path nixos/taler: review suggestions nixos/taler: make runtimeDir into an option, refactor nixos/taler: init mkTalerModule nixos/taler: use mkTalerModule for exchange nixos/taler: exchange fixups nixos/taler: use mkTalerModule for merchant nixos/taler: improve how dbInit script is created nixos/taler: remove exchange enableAccounts option nixos/taler: explicitly specify psql user Sometimes the dbinit service fails to find the user. nixos/taler: add openFirewall option; install package feat: add assertions, remove throw feat(taler): use module system instead of functions Also: - remove throw from denominateConfig - rename `utils.nix` to `common.nix` feat(taler): refactor modules feat: move taler module to services/finance refactor(exchange): replace throw with assert refactor(exchange,merchant): settings options fix(taler): manpage URLs fix(exchange): public key assert refactor(taler): use configFile feat(taler): include component configs directly Makes services detect config changes better.
- Loading branch information
1 parent
f571531
commit 7c51b85
Showing
5 changed files
with
477 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# TODO: create a common module generator for Taler and Libeufin? | ||
{ | ||
talerComponent ? "", | ||
servicesDB ? [ ], | ||
servicesNoDB ? [ ], | ||
... | ||
}: | ||
{ | ||
lib, | ||
pkgs, | ||
config, | ||
... | ||
}: | ||
let | ||
cfg = cfgTaler.${talerComponent}; | ||
cfgTaler = config.services.taler; | ||
|
||
settingsFormat = pkgs.formats.ini { }; | ||
|
||
configFile = config.environment.etc."taler/taler.conf".source; | ||
componentConfigFile = settingsFormat.generate "generated-taler-${talerComponent}.conf" cfg.settings; | ||
|
||
services = servicesDB ++ servicesNoDB; | ||
|
||
dbName = "taler-${talerComponent}-httpd"; | ||
groupName = "taler-${talerComponent}-services"; | ||
|
||
inherit (cfgTaler) runtimeDir; | ||
in | ||
{ | ||
options = { | ||
services.taler.${talerComponent} = { | ||
enable = lib.mkEnableOption "the GNU Taler ${talerComponent}"; | ||
package = lib.mkPackageOption pkgs "taler-${talerComponent}" { }; | ||
# TODO: make option accept multiple debugging levels? | ||
debug = lib.mkEnableOption "debug logging"; | ||
openFirewall = lib.mkOption { | ||
type = lib.types.bool; | ||
default = false; | ||
description = "Whether to open ports in the firewall"; | ||
}; | ||
}; | ||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
services.taler.enable = cfg.enable; | ||
services.taler.includes = [ componentConfigFile ]; | ||
|
||
systemd.services = lib.mergeAttrsList [ | ||
# Main services | ||
(lib.genAttrs (map (n: "taler-${talerComponent}-${n}") services) (name: { | ||
serviceConfig = { | ||
DynamicUser = true; | ||
User = name; | ||
Group = groupName; | ||
ExecStart = toString [ | ||
(lib.getExe' cfg.package name) | ||
"-c ${configFile}" | ||
(lib.optionalString cfg.debug " -L debug") | ||
]; | ||
RuntimeDirectory = name; | ||
StateDirectory = name; | ||
CacheDirectory = name; | ||
ReadWritePaths = [ runtimeDir ]; | ||
Restart = "always"; | ||
RestartSec = "10s"; | ||
}; | ||
requires = [ "taler-${talerComponent}-dbinit.service" ]; | ||
after = [ "taler-${talerComponent}-dbinit.service" ]; | ||
wantedBy = [ "multi-user.target" ]; # TODO slice? | ||
})) | ||
# Database Initialisation | ||
{ | ||
"taler-${talerComponent}-dbinit" = { | ||
path = [ config.services.postgresql.package ]; | ||
serviceConfig = { | ||
Type = "oneshot"; | ||
DynamicUser = true; | ||
User = dbName; | ||
Restart = "on-failure"; | ||
RestartSec = "5s"; | ||
}; | ||
requires = [ "postgresql.service" ]; | ||
after = [ "postgresql.service" ]; | ||
}; | ||
} | ||
]; | ||
|
||
users.groups.${groupName} = { }; | ||
systemd.tmpfiles.settings = { | ||
"10-taler-${talerComponent}" = { | ||
"${runtimeDir}" = { | ||
d = { | ||
group = groupName; | ||
user = "nobody"; | ||
mode = "070"; | ||
}; | ||
}; | ||
}; | ||
}; | ||
|
||
networking.firewall = lib.mkIf cfg.openFirewall { | ||
allowedTCPPorts = [ cfg.settings."${talerComponent}".PORT ]; | ||
}; | ||
|
||
environment.systemPackages = [ cfg.package ]; | ||
|
||
services.postgresql = { | ||
enable = true; | ||
ensureDatabases = [ dbName ]; | ||
ensureUsers = map (service: { name = "taler-${talerComponent}-${service}"; }) servicesDB ++ [ | ||
{ | ||
name = dbName; | ||
ensureDBOwnership = true; | ||
} | ||
]; | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
{ | ||
lib, | ||
config, | ||
options, | ||
pkgs, | ||
... | ||
}: | ||
|
||
let | ||
cfg = cfgTaler.exchange; | ||
cfgTaler = config.services.taler; | ||
|
||
talerComponent = "exchange"; | ||
|
||
# https://docs.taler.net/taler-exchange-manual.html#services-users-groups-and-file-system-hierarchy | ||
servicesDB = [ | ||
"httpd" | ||
"aggregator" | ||
"closer" | ||
"wirewatch" | ||
]; | ||
|
||
servicesNoDB = [ | ||
"secmod-cs" | ||
"secmod-eddsa" | ||
"secmod-rsa" | ||
]; | ||
in | ||
|
||
{ | ||
imports = [ | ||
(import ./common.nix { inherit talerComponent servicesDB servicesNoDB; }) | ||
]; | ||
|
||
options.services.taler.exchange = { | ||
settings = lib.mkOption { | ||
description = '' | ||
Configuration options for the taler exchange config file. | ||
For a list of all possible options, please see the man page [`taler-exchange.conf(5)`](https://docs.taler.net/manpages/taler-exchange.conf.5.html) | ||
''; | ||
type = lib.types.submodule { | ||
inherit (options.services.taler.settings.type.nestedTypes) freeformType; | ||
options = { | ||
# TODO: do we want this to be a sub-attribute or only define the exchange set of options here | ||
exchange = { | ||
AML_THRESHOLD = lib.mkOption { | ||
type = lib.types.str; | ||
default = "${cfgTaler.settings.taler.CURRENCY}:1000000"; | ||
defaultText = "1000000 in {option}`CURRENCY`"; | ||
description = "Monthly transaction volume until an account is considered suspicious and flagged for AML review."; | ||
}; | ||
DB = lib.mkOption { | ||
type = lib.types.enum [ "postgres" ]; | ||
default = "postgres"; | ||
description = "Plugin to use for the database."; | ||
}; | ||
MASTER_PUBLIC_KEY = lib.mkOption { | ||
type = lib.types.str; | ||
default = ""; | ||
description = "Used by the exchange to verify information signed by the offline system."; | ||
}; | ||
PORT = lib.mkOption { | ||
type = lib.types.port; | ||
default = 8081; | ||
description = "Port on which the HTTP server listens."; | ||
}; | ||
}; | ||
exchangedb-postgres = { | ||
CONFIG = lib.mkOption { | ||
type = lib.types.nonEmptyStr; | ||
default = "postgres:///taler-exchange-httpd"; | ||
description = "Database connection URI."; | ||
}; | ||
}; | ||
}; | ||
}; | ||
default = { }; | ||
}; | ||
denominationConfig = lib.mkOption { | ||
type = lib.types.lines; | ||
defaultText = "None, you must set this yourself."; | ||
example = '' | ||
[COIN-KUDOS-n1-t1718140083] | ||
VALUE = KUDOS:0.1 | ||
DURATION_WITHDRAW = 7 days | ||
DURATION_SPEND = 2 years | ||
DURATION_LEGAL = 6 years | ||
FEE_WITHDRAW = KUDOS:0 | ||
FEE_DEPOSIT = KUDOS:0.1 | ||
FEE_REFRESH = KUDOS:0 | ||
FEE_REFUND = KUDOS:0 | ||
RSA_KEYSIZE = 2048 | ||
CIPHER = RSA | ||
''; | ||
description = '' | ||
This option configures the cash denomination for the coins that the exchange offers. | ||
For more information, consult the [upstream docs](https://docs.taler.net/taler-exchange-manual.html#coins-denomination-keys). | ||
You can either write these manually or you can use the `taler-harness deployment gen-coin-config` | ||
command to generate it. | ||
Warning: Do not modify existing denominations after deployment. | ||
Please see the upstream docs for how to safely do that. | ||
''; | ||
}; | ||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
assertions = [ | ||
{ | ||
assertion = cfg.settings.exchange.MASTER_PUBLIC_KEY != ""; | ||
message = '' | ||
You must provide `config.services.taler.exchange.settings.exchange.MASTER_PUBLIC_KEY` with the | ||
public part of your master key. | ||
This will be used by the auditor service to get information about the exchange. | ||
For more information, see https://docs.taler.net/taler-auditor-manual.html#initial-configuration | ||
To generate this key, you must run `taler-exchange-offline setup`, which will print the public key. | ||
''; | ||
} | ||
]; | ||
|
||
services.taler.includes = [ | ||
(pkgs.writers.writeText "exchange-denominations.conf" cfg.denominationConfig) | ||
]; | ||
|
||
systemd.services.taler-exchange-wirewatch = { | ||
requires = [ "taler-exchange-httpd.service" ]; | ||
after = [ "taler-exchange-httpd.service" ]; | ||
}; | ||
|
||
# Taken from https://docs.taler.net/taler-exchange-manual.html#exchange-database-setup | ||
# TODO: Why does aggregator need DELETE? | ||
systemd.services."taler-${talerComponent}-dbinit".script = | ||
let | ||
deletePerm = name: lib.optionalString (name == "aggregator") ",DELETE"; | ||
dbScript = pkgs.writers.writeText "taler-exchange-db-permissions.sql" ( | ||
lib.pipe servicesDB [ | ||
(map (name: '' | ||
GRANT SELECT,INSERT,UPDATE${deletePerm name} ON ALL TABLES IN SCHEMA exchange TO "taler-exchange-${name}"; | ||
GRANT USAGE ON SCHEMA exchange TO "taler-exchange-${name}"; | ||
'')) | ||
lib.concatStrings | ||
] | ||
); | ||
in | ||
'' | ||
${lib.getExe' cfg.package "taler-exchange-dbinit"} | ||
psql -U taler-exchange-httpd -f ${dbScript} | ||
''; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
{ | ||
lib, | ||
config, | ||
options, | ||
pkgs, | ||
... | ||
}: | ||
let | ||
cfg = cfgTaler.merchant; | ||
cfgTaler = config.services.taler; | ||
|
||
talerComponent = "merchant"; | ||
|
||
# https://docs.taler.net/taler-merchant-manual.html#launching-the-backend | ||
servicesDB = [ | ||
"httpd" | ||
"webhook" | ||
"wirewatch" | ||
"depositcheck" | ||
"exchange" | ||
]; | ||
in | ||
{ | ||
imports = [ | ||
(import ./common.nix { inherit talerComponent servicesDB; }) | ||
]; | ||
|
||
options.services.taler.merchant = { | ||
settings = lib.mkOption { | ||
description = '' | ||
Configuration options for the taler merchant config file. | ||
For a list of all possible options, please see the man page [`taler-merchant.conf(5)`](https://docs.taler.net/manpages/taler-merchant.conf.5.html) | ||
''; | ||
type = lib.types.submodule { | ||
inherit (options.services.taler.settings.type.nestedTypes) freeformType; | ||
options = { | ||
merchant = { | ||
DB = lib.mkOption { | ||
type = lib.types.enum [ "postgres" ]; | ||
default = "postgres"; | ||
description = "Plugin to use for the database."; | ||
}; | ||
PORT = lib.mkOption { | ||
type = lib.types.port; | ||
default = 8083; | ||
description = "Port on which the HTTP server listens."; | ||
}; | ||
SERVE = lib.mkOption { | ||
type = lib.types.enum [ | ||
"tcp" | ||
"unix" | ||
]; | ||
default = "tcp"; | ||
description = '' | ||
Whether the HTTP server should listen on a UNIX domain socket ("unix") or on a TCP socket ("tcp"). | ||
''; | ||
}; | ||
LEGAL_PRESERVATION = lib.mkOption { | ||
type = lib.types.str; | ||
default = "10 years"; | ||
description = "How long to keep data in the database for tax audits after the transaction has completed."; | ||
}; | ||
}; | ||
merchantdb-postgres = { | ||
CONFIG = lib.mkOption { | ||
type = lib.types.nonEmptyStr; | ||
default = "postgres:///taler-merchant-httpd"; | ||
description = "Database connection URI."; | ||
}; | ||
SQL_DIR = lib.mkOption { | ||
type = lib.types.str; | ||
internal = true; | ||
default = "${cfg.package}/share/taler/sql/merchant/"; | ||
description = "The location for the SQL files to setup the database tables."; | ||
}; | ||
}; | ||
}; | ||
}; | ||
default = { }; | ||
}; | ||
}; | ||
|
||
config = lib.mkIf cfg.enable { | ||
systemd.services.taler-merchant-depositcheck = { | ||
# taler-merchant-depositcheck needs its executable is in the PATH | ||
# NOTE: couldn't use `lib.getExe` to only get that single executable | ||
path = [ cfg.package ]; | ||
}; | ||
|
||
systemd.services."taler-${talerComponent}-dbinit".script = | ||
let | ||
# NOTE: not documented, but is necessary | ||
dbScript = pkgs.writers.writeText "taler-merchant-db-permissions.sql" ( | ||
lib.concatStrings ( | ||
map (name: '' | ||
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA merchant TO "taler-merchant-${name}"; | ||
GRANT USAGE ON SCHEMA merchant TO "taler-merchant-${name}"; | ||
'') servicesDB | ||
) | ||
); | ||
in | ||
'' | ||
${lib.getExe' cfg.package "taler-merchant-dbinit"} | ||
psql -U taler-${talerComponent}-httpd -f ${dbScript} | ||
''; | ||
}; | ||
} |
Oops, something went wrong.