at 25.11-pre 8.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 cfg = config.services.locate; 10 isMLocate = lib.hasPrefix "mlocate" cfg.package.name; 11 isPLocate = lib.hasPrefix "plocate" cfg.package.name; 12in 13{ 14 imports = [ 15 (lib.mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ]) 16 (lib.mkRenamedOptionModule [ "services" "locate" "locate" ] [ "services" "locate" "package" ]) 17 (lib.mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths") 18 (lib.mkRemovedOptionModule [ "services" "locate" "localuser" ] 19 "The services.locate.localuser option has been removed because support for findutils locate has been removed." 20 ) 21 ]; 22 23 options.services.locate = { 24 enable = lib.mkOption { 25 type = lib.types.bool; 26 default = false; 27 description = '' 28 If enabled, NixOS will periodically update the database of 29 files used by the {command}`locate` command. 30 ''; 31 }; 32 33 package = lib.mkPackageOption pkgs [ "plocate" ] { 34 example = "mlocate"; 35 }; 36 37 interval = lib.mkOption { 38 type = lib.types.str; 39 default = "02:15"; 40 example = "hourly"; 41 description = '' 42 Update the locate database at this interval. Updates by 43 default at 2:15 AM every day. 44 45 The format is described in 46 {manpage}`systemd.time(7)`. 47 48 To disable automatic updates, set to `"never"` 49 and run {command}`updatedb` manually. 50 ''; 51 }; 52 53 extraFlags = lib.mkOption { 54 type = lib.types.listOf lib.types.str; 55 default = [ ]; 56 description = '' 57 Extra flags to pass to {command}`updatedb`. 58 ''; 59 }; 60 61 output = lib.mkOption { 62 type = lib.types.path; 63 default = "/var/cache/locatedb"; 64 description = '' 65 The database file to build. 66 ''; 67 }; 68 69 pruneFS = lib.mkOption { 70 type = lib.types.listOf lib.types.str; 71 default = [ 72 "afs" 73 "anon_inodefs" 74 "auto" 75 "autofs" 76 "bdev" 77 "binfmt" 78 "binfmt_misc" 79 "ceph" 80 "cgroup" 81 "cgroup2" 82 "cifs" 83 "coda" 84 "configfs" 85 "cramfs" 86 "cpuset" 87 "curlftpfs" 88 "debugfs" 89 "devfs" 90 "devpts" 91 "devtmpfs" 92 "ecryptfs" 93 "eventpollfs" 94 "exofs" 95 "futexfs" 96 "ftpfs" 97 "fuse" 98 "fusectl" 99 "fusesmb" 100 "fuse.ceph" 101 "fuse.glusterfs" 102 "fuse.gvfsd-fuse" 103 "fuse.mfs" 104 "fuse.rclone" 105 "fuse.rozofs" 106 "fuse.sshfs" 107 "gfs" 108 "gfs2" 109 "hostfs" 110 "hugetlbfs" 111 "inotifyfs" 112 "iso9660" 113 "jffs2" 114 "lustre" 115 "lustre_lite" 116 "misc" 117 "mfs" 118 "mqueue" 119 "ncpfs" 120 "nfs" 121 "NFS" 122 "nfs4" 123 "nfsd" 124 "nnpfs" 125 "ocfs" 126 "ocfs2" 127 "pipefs" 128 "proc" 129 "ramfs" 130 "rpc_pipefs" 131 "securityfs" 132 "selinuxfs" 133 "sfs" 134 "shfs" 135 "smbfs" 136 "sockfs" 137 "spufs" 138 "sshfs" 139 "subfs" 140 "supermount" 141 "sysfs" 142 "tmpfs" 143 "tracefs" 144 "ubifs" 145 "udev" 146 "udf" 147 "usbfs" 148 "vboxsf" 149 "vperfctrfs" 150 ]; 151 description = '' 152 Which filesystem types to exclude from indexing 153 ''; 154 }; 155 156 prunePaths = lib.mkOption { 157 type = lib.types.listOf lib.types.path; 158 default = [ 159 "/tmp" 160 "/var/tmp" 161 "/var/cache" 162 "/var/lock" 163 "/var/run" 164 "/var/spool" 165 "/nix/store" 166 "/nix/var/log/nix" 167 ]; 168 description = '' 169 Which paths to exclude from indexing 170 ''; 171 }; 172 173 pruneNames = lib.mkOption { 174 type = lib.types.listOf lib.types.str; 175 default = [ 176 ".bzr" 177 ".cache" 178 ".git" 179 ".hg" 180 ".svn" 181 ]; 182 defaultText = lib.literalMD '' 183 `[ ".bzr" ".cache" ".git" ".hg" ".svn" ]`, if 184 supported by the locate implementation (i.e. mlocate or plocate). 185 ''; 186 description = '' 187 Directory components which should exclude paths containing them from indexing 188 ''; 189 }; 190 191 pruneBindMounts = lib.mkOption { 192 type = lib.types.bool; 193 default = false; 194 description = '' 195 Whether not to index bind mounts 196 ''; 197 }; 198 199 }; 200 201 config = lib.mkIf cfg.enable { 202 users.groups = lib.mkMerge [ 203 (lib.mkIf isMLocate { mlocate = { }; }) 204 (lib.mkIf isPLocate { plocate = { }; }) 205 ]; 206 207 security.wrappers = 208 let 209 common = { 210 owner = "root"; 211 permissions = "u+rx,g+x,o+x"; 212 setgid = true; 213 setuid = false; 214 }; 215 mlocate = lib.mkIf isMLocate { 216 group = "mlocate"; 217 source = "${cfg.package}/bin/locate"; 218 }; 219 plocate = lib.mkIf isPLocate { 220 group = "plocate"; 221 source = "${cfg.package}/bin/plocate"; 222 }; 223 in 224 { 225 locate = lib.mkMerge [ 226 common 227 mlocate 228 plocate 229 ]; 230 plocate = lib.mkIf isPLocate ( 231 lib.mkMerge [ 232 common 233 plocate 234 ] 235 ); 236 }; 237 238 environment = { 239 # write /etc/updatedb.conf for manual calls to `updatedb` 240 etc."updatedb.conf".text = '' 241 PRUNEFS="${lib.concatStringsSep " " cfg.pruneFS}" 242 PRUNENAMES="${lib.concatStringsSep " " cfg.pruneNames}" 243 PRUNEPATHS="${lib.concatStringsSep " " cfg.prunePaths}" 244 PRUNE_BIND_MOUNTS="${if cfg.pruneBindMounts then "yes" else "no"}" 245 ''; 246 247 systemPackages = [ cfg.package ]; 248 }; 249 250 systemd.services.update-locatedb = { 251 description = "Update Locate Database"; 252 253 # mlocate's updatedb takes flags via a configuration file or 254 # on the command line, but not by environment variable. 255 script = 256 let 257 toFlags = 258 x: lib.optional (cfg.${x} != [ ]) "--${lib.toLower x} '${lib.concatStringsSep " " cfg.${x}}'"; 259 args = lib.concatLists ( 260 map toFlags [ 261 "pruneFS" 262 "pruneNames" 263 "prunePaths" 264 ] 265 ); 266 in 267 '' 268 exec ${cfg.package}/bin/updatedb \ 269 --output ${toString cfg.output} ${lib.concatStringsSep " " args} \ 270 --prune-bind-mounts ${if cfg.pruneBindMounts then "yes" else "no"} \ 271 ${lib.concatStringsSep " " cfg.extraFlags} 272 ''; 273 serviceConfig = { 274 CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_CHOWN"; 275 Nice = 19; 276 IOSchedulingClass = "idle"; 277 IPAddressDeny = "any"; 278 LockPersonality = true; 279 MemoryDenyWriteExecute = true; 280 NoNewPrivileges = true; 281 PrivateTmp = "yes"; 282 PrivateDevices = true; 283 PrivateNetwork = "yes"; 284 ProtectClock = true; 285 ProtectControlGroups = true; 286 ProtectHostname = true; 287 RestrictAddressFamilies = "AF_UNIX"; 288 RestrictNamespaces = true; 289 RestrictRealtime = true; 290 RestrictSUIDSGID = true; 291 ReadOnlyPaths = "/"; 292 # Use dirOf cfg.output because mlocate creates temporary files next to 293 # the actual database. We could specify and create them as well, 294 # but that would make this quite brittle when they change something. 295 # NOTE: If /var/cache does not exist, this leads to the misleading error message: 296 # update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory 297 ReadWritePaths = dirOf cfg.output; 298 SystemCallArchitectures = "native"; 299 SystemCallFilter = "@system-service @chown"; 300 }; 301 }; 302 303 systemd.timers.update-locatedb = lib.mkIf (cfg.interval != "never") { 304 description = "Update timer for locate database"; 305 partOf = [ "update-locatedb.service" ]; 306 wantedBy = [ "timers.target" ]; 307 timerConfig = { 308 OnCalendar = cfg.interval; 309 Persistent = true; 310 }; 311 }; 312 }; 313 314 meta.maintainers = with lib.maintainers; [ SuperSandro2000 ]; 315}