about summary refs log tree commit diff
path: root/nixos/modules/services/databases
diff options
context:
space:
mode:
authora-n-n-a-l-e-e <150648636+a-n-n-a-l-e-e@users.noreply.github.com>2024-01-23 23:13:54 -0800
committerGitHub <noreply@github.com>2024-01-23 23:13:54 -0800
commit18cc181b9bb847f8c7c96d6a1213497e8dbfe4bf (patch)
tree5db0001da52ab16897ebf33b717ed1572947cc83 /nixos/modules/services/databases
parent44a14fe2dc4260f60b819d3e86f1e2f4390b5593 (diff)
parentfdf411fb36c721a4769a355a4330f23cb598632d (diff)
Merge pull request #279511 from DanielSidhion/tigerbeetle-service
nixos/tigerbeetle: init module
Diffstat (limited to 'nixos/modules/services/databases')
-rw-r--r--nixos/modules/services/databases/tigerbeetle.md33
-rw-r--r--nixos/modules/services/databases/tigerbeetle.nix115
2 files changed, 148 insertions, 0 deletions
diff --git a/nixos/modules/services/databases/tigerbeetle.md b/nixos/modules/services/databases/tigerbeetle.md
new file mode 100644
index 0000000000000..47394d4430598
--- /dev/null
+++ b/nixos/modules/services/databases/tigerbeetle.md
@@ -0,0 +1,33 @@
+# TigerBeetle {#module-services-tigerbeetle}
+
+*Source:* {file}`modules/services/databases/tigerbeetle.nix`
+
+*Upstream documentation:* <https://docs.tigerbeetle.com/>
+
+TigerBeetle is a distributed financial accounting database designed for mission critical safety and performance.
+
+To enable TigerBeetle, add the following to your {file}`configuration.nix`:
+```
+  services.tigerbeetle.enable = true;
+```
+
+When first started, the TigerBeetle service will create its data file at {file}`/var/lib/tigerbeetle` unless the file already exists, in which case it will just use the existing file.
+If you make changes to the configuration of TigerBeetle after its data file was already created (for example increasing the replica count), you may need to remove the existing file to avoid conflicts.
+
+## Configuring {#module-services-tigerbeetle-configuring}
+
+By default, TigerBeetle will only listen on a local interface.
+To configure it to listen on a different interface (and to configure it to connect to other replicas, if you're creating more than one), you'll have to set the `addresses` option.
+Note that the TigerBeetle module won't open any firewall ports automatically, so if you configure it to listen on an external interface, you'll need to ensure that connections can reach it:
+
+```
+  services.tigerbeetle = {
+    enable = true;
+    addresses = [ "0.0.0.0:3001" ];
+  };
+
+  networking.firewall.allowedTCPPorts = [ 3001 ];
+```
+
+A complete list of options for TigerBeetle can be found [here](#opt-services.tigerbeetle.enable).
+
diff --git a/nixos/modules/services/databases/tigerbeetle.nix b/nixos/modules/services/databases/tigerbeetle.nix
new file mode 100644
index 0000000000000..b90a0703175f5
--- /dev/null
+++ b/nixos/modules/services/databases/tigerbeetle.nix
@@ -0,0 +1,115 @@
+{ config, lib, pkgs, ... }:
+let
+  cfg = config.services.tigerbeetle;
+in
+{
+  meta = {
+    maintainers = with lib.maintainers; [ danielsidhion ];
+    doc = ./tigerbeetle.md;
+    buildDocsInSandbox = true;
+  };
+
+  options = {
+    services.tigerbeetle = with lib; {
+      enable = mkEnableOption (mdDoc "TigerBeetle server");
+
+      package = mkPackageOption pkgs "tigerbeetle" { };
+
+      clusterId = mkOption {
+        type = types.either types.ints.unsigned (types.strMatching "[0-9]+");
+        default = 0;
+        description = lib.mdDoc ''
+          The 128-bit cluster ID used to create the replica data file (if needed).
+          Since Nix only supports integers up to 64 bits, you need to pass a string to this if the cluster ID can't fit in 64 bits.
+          Otherwise, you can pass the cluster ID as either an integer or a string.
+        '';
+      };
+
+      replicaIndex = mkOption {
+        type = types.ints.unsigned;
+        default = 0;
+        description = lib.mdDoc ''
+          The index (starting at 0) of the replica in the cluster.
+        '';
+      };
+
+      replicaCount = mkOption {
+        type = types.ints.unsigned;
+        default = 1;
+        description = lib.mdDoc ''
+          The number of replicas participating in replication of the cluster.
+        '';
+      };
+
+      cacheGridSize = mkOption {
+        type = types.strMatching "[0-9]+(K|M|G)B";
+        default = "1GB";
+        description = lib.mdDoc ''
+          The grid cache size.
+          The grid cache acts like a page cache for TigerBeetle.
+          It is recommended to set this as large as possible.
+        '';
+      };
+
+      addresses = mkOption {
+        type = types.listOf types.nonEmptyStr;
+        default = [ "3001" ];
+        description = lib.mdDoc ''
+          The addresses of all replicas in the cluster.
+          This should be a list of IPv4/IPv6 addresses with port numbers.
+          Either the address or port number (but not both) may be omitted, in which case a default of 127.0.0.1 or 3001 will be used.
+          The first address in the list corresponds to the address for replica 0, the second address for replica 1, and so on.
+        '';
+      };
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    assertions =
+      let
+        numAddresses = builtins.length cfg.addresses;
+      in
+      [
+        {
+          assertion = cfg.replicaIndex < cfg.replicaCount;
+          message = "the TigerBeetle replica index must fit the configured replica count";
+        }
+        {
+          assertion = cfg.replicaCount == numAddresses;
+          message = if cfg.replicaCount < numAddresses then "TigerBeetle must not have more addresses than the configured number of replicas" else "TigerBeetle must be configured with the addresses of all replicas";
+        }
+      ];
+
+    systemd.services.tigerbeetle =
+      let
+        replicaDataPath = "/var/lib/tigerbeetle/${builtins.toString cfg.clusterId}_${builtins.toString cfg.replicaIndex}.tigerbeetle";
+      in
+      {
+        description = "TigerBeetle server";
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ "network.target" ];
+
+        preStart = ''
+          if ! test -e "${replicaDataPath}"; then
+            ${lib.getExe cfg.package} format --cluster="${builtins.toString cfg.clusterId}" --replica="${builtins.toString cfg.replicaIndex}" --replica-count="${builtins.toString cfg.replicaCount}" "${replicaDataPath}"
+          fi
+        '';
+
+        serviceConfig = {
+          Type = "exec";
+
+          DynamicUser = true;
+          ProtectHome = true;
+          DevicePolicy = "closed";
+
+          StateDirectory = "tigerbeetle";
+          StateDirectoryMode = 700;
+
+          ExecStart = "${lib.getExe cfg.package} start --cache-grid=${cfg.cacheGridSize} --addresses=${lib.escapeShellArg (builtins.concatStringsSep "," cfg.addresses)} ${replicaDataPath}";
+        };
+      };
+
+    environment.systemPackages = [ cfg.package ];
+  };
+}