1 { config, pkgs, lib, ... }:
3 inherit (lib) mkOption types mkIf;
4 cfg = config.services.atuin;
9 enable = lib.mkEnableOption "Atuin server for shell history sync";
11 package = lib.mkPackageOption pkgs "atuin" { };
13 openRegistration = mkOption {
16 description = "Allow new user registrations with the atuin server.";
22 description = "A path to prepend to all the routes of the server.";
27 default = "127.0.0.1";
28 description = "The host address the atuin server should listen on.";
31 maxHistoryLength = mkOption {
34 description = "The max length of each history item the atuin server should store.";
40 description = "The port the atuin server should listen on.";
43 openFirewall = mkOption {
46 description = "Open ports in the firewall for the atuin server.";
50 createLocally = mkOption {
53 description = "Create the database and database user locally.";
57 type = types.nullOr types.str;
58 default = "postgresql:///atuin?host=/run/postgresql";
59 example = "postgresql://atuin@localhost:5432/atuin";
62 Can be set to null in which case ATUIN_DB_URI should be set through an EnvironmentFile
69 config = mkIf cfg.enable {
72 assertion = cfg.database.createLocally -> config.services.postgresql.enable;
73 message = "Postgresql must be enabled to create a local database";
77 services.postgresql = mkIf cfg.database.createLocally {
81 ensureDBOwnership = true;
83 ensureDatabases = [ "atuin" ];
86 systemd.services.atuin = {
87 description = "atuin server";
88 requires = lib.optionals cfg.database.createLocally [ "postgresql.service" ];
89 after = [ "network.target" ] ++ lib.optionals cfg.database.createLocally [ "postgresql.service" ];
90 wantedBy = [ "multi-user.target" ];
93 ExecStart = "${lib.getExe cfg.package} server start";
94 RuntimeDirectory = "atuin";
95 RuntimeDirectoryMode = "0700";
99 CapabilityBoundingSet = "";
100 LockPersonality = true;
101 NoNewPrivileges = true;
102 MemoryDenyWriteExecute = true;
103 PrivateDevices = true;
104 PrivateMounts = true;
109 ProtectControlGroups = true;
111 ProtectHostname = true;
112 ProtectKernelLogs = true;
113 ProtectKernelModules = true;
114 ProtectKernelTunables = true;
115 ProtectProc = "invisible";
116 ProtectSystem = "full";
118 RestrictAddressFamilies = [
121 # Required for connecting to database sockets,
124 RestrictNamespaces = true;
125 RestrictRealtime = true;
126 RestrictSUIDSGID = true;
127 SystemCallArchitectures = "native";
136 ATUIN_HOST = cfg.host;
137 ATUIN_PORT = toString cfg.port;
138 ATUIN_MAX_HISTORY_LENGTH = toString cfg.maxHistoryLength;
139 ATUIN_OPEN_REGISTRATION = lib.boolToString cfg.openRegistration;
140 ATUIN_PATH = cfg.path;
141 ATUIN_CONFIG_DIR = "/run/atuin"; # required to start, but not used as configuration is via environment variables
142 } // lib.optionalAttrs (cfg.database.uri != null) {
143 ATUIN_DB_URI = cfg.database.uri;
147 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];