at master 4.6 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7let 8 inherit (lib) mkOption types mkIf; 9 cfg = config.services.atuin; 10in 11{ 12 options = { 13 services.atuin = { 14 enable = lib.mkEnableOption "Atuin server for shell history sync"; 15 16 package = lib.mkPackageOption pkgs "atuin" { }; 17 18 openRegistration = mkOption { 19 type = types.bool; 20 default = false; 21 description = "Allow new user registrations with the atuin server."; 22 }; 23 24 path = mkOption { 25 type = types.str; 26 default = ""; 27 description = "A path to prepend to all the routes of the server."; 28 }; 29 30 host = mkOption { 31 type = types.str; 32 default = "127.0.0.1"; 33 description = "The host address the atuin server should listen on."; 34 }; 35 36 maxHistoryLength = mkOption { 37 type = types.int; 38 default = 8192; 39 description = "The max length of each history item the atuin server should store."; 40 }; 41 42 port = mkOption { 43 type = types.port; 44 default = 8888; 45 description = "The port the atuin server should listen on."; 46 }; 47 48 openFirewall = mkOption { 49 type = types.bool; 50 default = false; 51 description = "Open ports in the firewall for the atuin server."; 52 }; 53 54 database = { 55 createLocally = mkOption { 56 type = types.bool; 57 default = true; 58 description = "Create the database and database user locally."; 59 }; 60 61 uri = mkOption { 62 type = types.nullOr types.str; 63 default = "postgresql:///atuin?host=/run/postgresql"; 64 example = "postgresql://atuin@localhost:5432/atuin"; 65 description = '' 66 URI to the database. 67 Can be set to null in which case ATUIN_DB_URI should be set through an EnvironmentFile 68 ''; 69 }; 70 }; 71 }; 72 }; 73 74 config = mkIf cfg.enable { 75 assertions = [ 76 { 77 assertion = cfg.database.createLocally -> config.services.postgresql.enable; 78 message = "Postgresql must be enabled to create a local database"; 79 } 80 ]; 81 82 services.postgresql = mkIf cfg.database.createLocally { 83 enable = true; 84 ensureUsers = [ 85 { 86 name = "atuin"; 87 ensureDBOwnership = true; 88 } 89 ]; 90 ensureDatabases = [ "atuin" ]; 91 }; 92 93 systemd.services.atuin = { 94 description = "atuin server"; 95 requires = lib.optionals cfg.database.createLocally [ "postgresql.target" ]; 96 after = [ 97 "network-online.target" 98 ] 99 ++ lib.optionals cfg.database.createLocally [ "postgresql.target" ]; 100 wants = [ 101 "network-online.target" 102 ] 103 ++ lib.optionals cfg.database.createLocally [ "postgresql.target" ]; 104 wantedBy = [ "multi-user.target" ]; 105 106 serviceConfig = { 107 ExecStart = "${lib.getExe cfg.package} server start"; 108 RuntimeDirectory = "atuin"; 109 RuntimeDirectoryMode = "0700"; 110 DynamicUser = true; 111 112 # Hardening 113 CapabilityBoundingSet = ""; 114 LockPersonality = true; 115 NoNewPrivileges = true; 116 MemoryDenyWriteExecute = true; 117 PrivateDevices = true; 118 PrivateMounts = true; 119 PrivateTmp = true; 120 PrivateUsers = true; 121 ProcSubset = "pid"; 122 ProtectClock = true; 123 ProtectControlGroups = true; 124 ProtectHome = true; 125 ProtectHostname = true; 126 ProtectKernelLogs = true; 127 ProtectKernelModules = true; 128 ProtectKernelTunables = true; 129 ProtectProc = "invisible"; 130 ProtectSystem = "full"; 131 RemoveIPC = true; 132 RestrictAddressFamilies = [ 133 "AF_INET" 134 "AF_INET6" 135 # Required for connecting to database sockets, 136 "AF_UNIX" 137 ]; 138 RestrictNamespaces = true; 139 RestrictRealtime = true; 140 RestrictSUIDSGID = true; 141 SystemCallArchitectures = "native"; 142 SystemCallFilter = [ 143 "@system-service" 144 "~@privileged" 145 ]; 146 UMask = "0077"; 147 }; 148 149 environment = { 150 ATUIN_HOST = cfg.host; 151 ATUIN_PORT = toString cfg.port; 152 ATUIN_MAX_HISTORY_LENGTH = toString cfg.maxHistoryLength; 153 ATUIN_OPEN_REGISTRATION = lib.boolToString cfg.openRegistration; 154 ATUIN_PATH = cfg.path; 155 ATUIN_CONFIG_DIR = "/run/atuin"; # required to start, but not used as configuration is via environment variables 156 } 157 // lib.optionalAttrs (cfg.database.uri != null) { ATUIN_DB_URI = cfg.database.uri; }; 158 }; 159 160 networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; 161 }; 162}