nixos: update-locatedb - harden via systemd (#7220)

Also, use systemd timers.

Most of the work is by @thoughtpolice but I changed enough of it to warrant changing commit author.

+105 -94
+40 -34
nixos/doc/manual/development/writing-modules.xml
··· 107 107 by other modules (typically the user’s 108 108 <filename>configuration.nix</filename>): 109 109 <option>services.locate.enable</option> (whether the database should 110 - be updated) and <option>services.locate.period</option> (when the 110 + be updated) and <option>services.locate.interval</option> (when the 111 111 update should be done). It implements its functionality by defining 112 112 two options declared by other modules: 113 113 <option>systemd.services</option> (the set of all systemd services) 114 - and <option>services.cron.systemCronJobs</option> (the list of 115 - commands to be executed periodically by <command>cron</command>).</para> 114 + and <option>systemd.timers</option> (the list of commands to be 115 + executed periodically by <command>systemd</command>).</para> 116 116 117 117 <example xml:id='locate-example'><title>NixOS Module for the “locate” Service</title> 118 118 <programlisting> ··· 120 120 121 121 with lib; 122 122 123 - let locatedb = "/var/cache/locatedb"; in 123 + let 124 + cfg = config.services.locate; 125 + in { 126 + options.services.locate = { 127 + enable = mkOption { 128 + type = types.bool; 129 + default = false; 130 + description = '' 131 + If enabled, NixOS will periodically update the database of 132 + files used by the <command>locate</command> command. 133 + ''; 134 + }; 124 135 125 - { 126 - options = { 127 - 128 - services.locate = { 129 - 130 - enable = mkOption { 131 - type = types.bool; 132 - default = false; 133 - description = '' 134 - If enabled, NixOS will periodically update the database of 135 - files used by the <command>locate</command> command. 136 - ''; 137 - }; 138 - 139 - period = mkOption { 140 - type = types.str; 141 - default = "15 02 * * *"; 142 - description = '' 143 - This option defines (in the format used by cron) when the 144 - locate database is updated. The default is to update at 145 - 02:15 at night every day. 146 - ''; 147 - }; 136 + interval = mkOption { 137 + type = types.str; 138 + default = "02:15"; 139 + example = "hourly"; 140 + description = '' 141 + Update the locate database at this interval. Updates by 142 + default at 2:15 AM every day. 148 143 144 + The format is described in 145 + <citerefentry><refentrytitle>systemd.time</refentrytitle> 146 + <manvolnum>7</manvolnum></citerefentry>. 147 + ''; 149 148 }; 150 149 150 + # Other options omitted for documentation 151 151 }; 152 152 153 153 config = { 154 - 155 154 systemd.services.update-locatedb = 156 155 { description = "Update Locate Database"; 157 156 path = [ pkgs.su ]; 158 157 script = 159 158 '' 160 - mkdir -m 0755 -p $(dirname ${locatedb}) 161 - exec updatedb --localuser=nobody --output=${locatedb} --prunepaths='/tmp /var/tmp /run' 159 + mkdir -m 0755 -p $(dirname ${toString cfg.output}) 160 + exec updatedb \ 161 + --localuser=${cfg.localuser} \ 162 + ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \ 163 + --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags} 162 164 ''; 163 165 }; 164 166 165 - services.cron.systemCronJobs = optional config.services.locate.enable 166 - "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service"; 167 - 167 + systemd.timers.update-locatedb = mkIf cfg.enable 168 + { description = "Update timer for locate database"; 169 + partOf = [ "update-locatedb.service" ]; 170 + wantedBy = [ "timers.target" ]; 171 + timerConfig.OnCalendar = cfg.interval; 172 + }; 168 173 }; 169 - }</programlisting> 174 + } 175 + </programlisting> 170 176 </example> 171 177 172 178 <xi:include href="option-declarations.xml" />
+65 -60
nixos/modules/misc/locate.nix
··· 1 - { config, lib, pkgs, ... }: 1 + { config, options, lib, pkgs, ... }: 2 2 3 3 with lib; 4 4 5 5 let 6 6 cfg = config.services.locate; 7 7 in { 8 + options.services.locate = { 9 + enable = mkOption { 10 + type = types.bool; 11 + default = false; 12 + description = '' 13 + If enabled, NixOS will periodically update the database of 14 + files used by the <command>locate</command> command. 15 + ''; 16 + }; 8 17 9 - ###### interface 18 + interval = mkOption { 19 + type = types.str; 20 + default = "02:15"; 21 + example = "hourly"; 22 + description = '' 23 + Update the locate database at this interval. Updates by 24 + default at 2:15 AM every day. 10 25 11 - options = { 26 + The format is described in 27 + <citerefentry><refentrytitle>systemd.time</refentrytitle> 28 + <manvolnum>7</manvolnum></citerefentry>. 29 + ''; 30 + }; 12 31 13 - services.locate = { 32 + # This is no longer supported, but we keep it to give a better warning below 33 + period = mkOption { visible = false; }; 14 34 15 - enable = mkOption { 16 - type = types.bool; 17 - default = false; 18 - description = '' 19 - If enabled, NixOS will periodically update the database of 20 - files used by the <command>locate</command> command. 21 - ''; 22 - }; 35 + extraFlags = mkOption { 36 + type = types.listOf types.str; 37 + default = [ ]; 38 + description = '' 39 + Extra flags to pass to <command>updatedb</command>. 40 + ''; 41 + }; 23 42 24 - period = mkOption { 25 - type = types.str; 26 - default = "15 02 * * *"; 27 - description = '' 28 - This option defines (in the format used by cron) when the 29 - locate database is updated. 30 - The default is to update at 02:15 at night every day. 31 - ''; 32 - }; 43 + output = mkOption { 44 + type = types.path; 45 + default = "/var/cache/locatedb"; 46 + description = '' 47 + The database file to build. 48 + ''; 49 + }; 33 50 34 - extraFlags = mkOption { 35 - type = types.listOf types.str; 36 - default = [ ]; 37 - description = '' 38 - Extra flags to pass to <command>updatedb</command>. 39 - ''; 40 - }; 41 - 42 - output = mkOption { 43 - type = types.path; 44 - default = "/var/cache/locatedb"; 45 - description = '' 46 - The database file to build. 47 - ''; 48 - }; 49 - 50 - localuser = mkOption { 51 - type = types.str; 52 - default = "nobody"; 53 - description = '' 54 - The user to search non-network directories as, using 55 - <command>su</command>. 56 - ''; 57 - }; 58 - 59 - includeStore = mkOption { 60 - type = types.bool; 61 - default = false; 62 - description = '' 63 - Whether to include <filename>/nix/store</filename> in the locate database. 64 - ''; 65 - }; 66 - 51 + localuser = mkOption { 52 + type = types.str; 53 + default = "nobody"; 54 + description = '' 55 + The user to search non-network directories as, using 56 + <command>su</command>. 57 + ''; 67 58 }; 68 59 60 + includeStore = mkOption { 61 + type = types.bool; 62 + default = false; 63 + description = '' 64 + Whether to include <filename>/nix/store</filename> in the locate database. 65 + ''; 66 + }; 69 67 }; 70 68 71 - ###### implementation 72 - 73 69 config = { 70 + warnings = let opt = options.services.locate.period; in optional opt.isDefined "The `period` definition in ${showFiles opt.files} has been removed; please replace it with `interval`, using the new systemd.time interval specifier."; 71 + 74 72 systemd.services.update-locatedb = 75 73 { description = "Update Locate Database"; 76 74 path = [ pkgs.su ]; ··· 84 82 ''; 85 83 serviceConfig.Nice = 19; 86 84 serviceConfig.IOSchedulingClass = "idle"; 85 + serviceConfig.PrivateTmp = "yes"; 86 + serviceConfig.PrivateNetwork = "yes"; 87 + serviceConfig.NoNewPrivileges = "yes"; 88 + serviceConfig.ReadOnlyDirectories = "/"; 89 + serviceConfig.ReadWriteDirectories = cfg.output; 87 90 }; 88 91 89 - services.cron.systemCronJobs = optional config.services.locate.enable 90 - "${config.services.locate.period} root ${config.systemd.package}/bin/systemctl start update-locatedb.service"; 91 - 92 + systemd.timers.update-locatedb = mkIf cfg.enable 93 + { description = "Update timer for locate database"; 94 + partOf = [ "update-locatedb.service" ]; 95 + wantedBy = [ "timers.target" ]; 96 + timerConfig.OnCalendar = cfg.interval; 97 + }; 92 98 }; 93 - 94 99 }