aboutsummaryrefslogtreecommitdiffstats
path: root/nix/module.nix
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-12 01:54:21 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-06-12 01:54:21 +0200
commitbbdf38018b47328b5faa2cef635c37095045be72 (patch)
tree8983817d547551ae12508a8ae8731b622d990af4 /nix/module.nix
parentfeat(server): Make user stuff stateless (diff)
downloadatuin-bbdf38018b47328b5faa2cef635c37095045be72.zip
feat(server): Really make users stateless (with tests)
This commit also remove another load of unneeded features.
Diffstat (limited to 'nix/module.nix')
-rw-r--r--nix/module.nix144
1 files changed, 144 insertions, 0 deletions
diff --git a/nix/module.nix b/nix/module.nix
new file mode 100644
index 00000000..da6fd02c
--- /dev/null
+++ b/nix/module.nix
@@ -0,0 +1,144 @@
+{
+ config,
+ pkgs,
+ lib,
+ ...
+}: let
+ inherit (lib) mkOption types mkIf;
+ cfg = config.services.turtle;
+in {
+ options = {
+ services.turtle = {
+ enable = lib.mkEnableOption "turtle server for shell history sync";
+
+ package = lib.mkPackageOption pkgs "turtle" {};
+
+ host = mkOption {
+ type = types.str;
+ default = "127.0.0.1";
+ description = "The host address the turtle server should listen on.";
+ };
+
+ port = mkOption {
+ type = types.port;
+ default = 8888;
+ description = "The port the turtle server should listen on.";
+ };
+
+ database = {
+ createLocally = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Create the database and database user locally.";
+ };
+
+ uri = mkOption {
+ type = types.nullOr types.str;
+ default = "postgresql:///turtle?host=/run/postgresql";
+ example = "postgresql://turtle@localhost:5432/turtle";
+ description = ''
+ URI to the database.
+ Can be set to null in which case ATUIN_DB_URI should be set through an EnvironmentFile
+ '';
+ };
+ };
+
+ environmentFile = lib.mkOption {
+ type = lib.types.nullOr lib.types.externalPath;
+ default = null;
+ description = ''
+ Environment file, used to set any secret ATUIN_* environment variables, such as ATUIN_DB_URI containing a password.
+ See https://docs.atuin.sh/cli/self-hosting/server-setup/#configuration for available environment variables.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = cfg.database.createLocally -> config.services.postgresql.enable;
+ message = "Postgresql must be enabled to create a local database";
+ }
+ ];
+
+ services.postgresql = mkIf cfg.database.createLocally {
+ enable = true;
+ ensureUsers = [
+ {
+ name = "turtle";
+ ensureDBOwnership = true;
+ }
+ ];
+ ensureDatabases = ["turtle"];
+ };
+
+ systemd.services.turtle = {
+ description = "turtle server";
+ requires = lib.optionals cfg.database.createLocally ["postgresql.target"];
+ after =
+ [
+ "network-online.target"
+ ]
+ ++ lib.optionals cfg.database.createLocally ["postgresql.target"];
+ wants =
+ [
+ "network-online.target"
+ ]
+ ++ lib.optionals cfg.database.createLocally ["postgresql.target"];
+ wantedBy = ["multi-user.target"];
+
+ serviceConfig = {
+ ExecStart = "${lib.getExe' cfg.package "atuin"} server start";
+ EnvironmentFile = lib.mkIf (cfg.environmentFile != null) [cfg.environmentFile];
+ RuntimeDirectory = "turtle";
+ RuntimeDirectoryMode = "0700";
+ DynamicUser = true;
+
+ # Hardening
+ CapabilityBoundingSet = "";
+ LockPersonality = true;
+ NoNewPrivileges = true;
+ MemoryDenyWriteExecute = true;
+ PrivateDevices = true;
+ PrivateMounts = true;
+ PrivateTmp = true;
+ PrivateUsers = true;
+ ProcSubset = "pid";
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "full";
+ RemoveIPC = true;
+ RestrictAddressFamilies = [
+ "AF_INET"
+ "AF_INET6"
+ # Required for connecting to database sockets,
+ "AF_UNIX"
+ ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [
+ "@system-service"
+ "~@privileged"
+ ];
+ UMask = "0077";
+ };
+
+ environment =
+ {
+ ATUIN_HOST = cfg.host;
+ ATUIN_PORT = toString cfg.port;
+ ATUIN_CONFIG_DIR = "/run/turtle"; # required to start, but not used as configuration is via environment variables
+ }
+ // lib.optionalAttrs (cfg.database.uri != null) {ATUIN_DB_URI = cfg.database.uri;};
+ };
+ };
+}