at master 5.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.garage; 12 toml = pkgs.formats.toml { }; 13 configFile = toml.generate "garage.toml" cfg.settings; 14in 15{ 16 meta = { 17 doc = ./garage.md; 18 maintainers = with lib.maintainers; [ 19 mjm 20 cything 21 ]; 22 }; 23 24 options.services.garage = { 25 enable = mkEnableOption "Garage Object Storage (S3 compatible)"; 26 27 extraEnvironment = mkOption { 28 type = types.attrsOf types.str; 29 description = "Extra environment variables to pass to the Garage server."; 30 default = { }; 31 example = { 32 RUST_BACKTRACE = "yes"; 33 }; 34 }; 35 36 environmentFile = mkOption { 37 type = types.nullOr types.path; 38 description = "File containing environment variables to be passed to the Garage server."; 39 default = null; 40 }; 41 42 logLevel = mkOption { 43 type = types.enum [ 44 "error" 45 "warn" 46 "info" 47 "debug" 48 "trace" 49 ]; 50 default = "info"; 51 example = "debug"; 52 description = "Garage log level, see <https://garagehq.deuxfleurs.fr/documentation/quick-start/#launching-the-garage-server> for examples."; 53 }; 54 55 settings = mkOption { 56 type = types.submodule { 57 freeformType = toml.type; 58 59 options = { 60 metadata_dir = mkOption { 61 default = "/var/lib/garage/meta"; 62 type = types.path; 63 description = "The metadata directory, put this on a fast disk (e.g. SSD) if possible."; 64 }; 65 66 data_dir = mkOption { 67 default = "/var/lib/garage/data"; 68 example = [ 69 { 70 path = "/var/lib/garage/data"; 71 capacity = "2T"; 72 } 73 ]; 74 type = with types; either path (listOf attrs); 75 description = '' 76 The directory in which Garage will store the data blocks of objects. This folder can be placed on an HDD. 77 Since v0.9.0, Garage supports multiple data directories, refer to <https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#data_dir> for the exact format. 78 ''; 79 }; 80 }; 81 }; 82 description = "Garage configuration, see <https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/> for reference."; 83 }; 84 85 package = mkOption { 86 type = types.package; 87 description = "Garage package to use, needs to be set explicitly. If you are upgrading from a major version, please read NixOS and Garage release notes for upgrade instructions."; 88 }; 89 }; 90 91 config = mkIf cfg.enable { 92 environment.etc."garage.toml" = { 93 source = configFile; 94 }; 95 96 # For administration 97 environment.systemPackages = [ 98 (pkgs.writeScriptBin "garage" '' 99 # make it so all future variables set are automatically exported as environment variables 100 set -a 101 102 # source the set environmentFile (since systemd EnvironmentFile is supposed to be a minor subset of posix sh parsing) (with shell arg escaping to avoid quoting issues) 103 [ -f ${lib.escapeShellArg cfg.environmentFile} ] && . ${lib.escapeShellArg cfg.environmentFile} 104 105 # exec the program with quoted args (also with shell arg escaping for the program path to avoid quoting issues there) 106 exec ${lib.escapeShellArg (lib.getExe cfg.package)} "$@" 107 '') 108 ]; 109 110 systemd.services.garage = { 111 description = "Garage Object Storage (S3 compatible)"; 112 after = [ 113 "network.target" 114 "network-online.target" 115 ]; 116 wants = [ 117 "network.target" 118 "network-online.target" 119 ]; 120 wantedBy = [ "multi-user.target" ]; 121 restartTriggers = [ 122 configFile 123 ] 124 ++ (lib.optional (cfg.environmentFile != null) cfg.environmentFile); 125 serviceConfig = 126 let 127 paths = lib.flatten ( 128 with cfg.settings; 129 [ 130 metadata_dir 131 ] 132 # data_dir can either be a string or a list of attrs 133 # if data_dir is a list, the actual path will in in the `path` attribute of each item 134 # see https://garagehq.deuxfleurs.fr/documentation/reference-manual/configuration/#data_dir 135 ++ lib.optional (lib.isList data_dir) (map (item: item.path) data_dir) 136 ++ lib.optional (lib.isString data_dir) [ data_dir ] 137 ); 138 isDefault = lib.hasPrefix "/var/lib/garage"; 139 isDefaultStateDirectory = lib.any isDefault paths; 140 in 141 { 142 ExecStart = "${cfg.package}/bin/garage server"; 143 144 StateDirectory = lib.mkIf isDefaultStateDirectory "garage"; 145 DynamicUser = lib.mkDefault true; 146 ProtectHome = true; 147 NoNewPrivileges = true; 148 EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile; 149 ReadWritePaths = lib.filter (x: !(isDefault x)) (lib.flatten [ paths ]); 150 # Upstream recommendation https://garagehq.deuxfleurs.fr/documentation/cookbook/systemd/ 151 LimitNOFILE = 42000; 152 }; 153 environment = { 154 RUST_LOG = lib.mkDefault "garage=${cfg.logLevel}"; 155 } 156 // cfg.extraEnvironment; 157 }; 158 }; 159}