at master 6.8 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.minio; 12 13 legacyCredentials = 14 cfg: 15 pkgs.writeText "minio-legacy-credentials" '' 16 MINIO_ROOT_USER=${cfg.accessKey} 17 MINIO_ROOT_PASSWORD=${cfg.secretKey} 18 ''; 19in 20{ 21 meta.maintainers = with maintainers; [ 22 bachp 23 ryan4yin 24 ]; 25 26 options.services.minio = { 27 enable = mkEnableOption "Minio Object Storage"; 28 29 listenAddress = mkOption { 30 default = ":9000"; 31 type = types.str; 32 description = "IP address and port of the server."; 33 }; 34 35 consoleAddress = mkOption { 36 default = ":9001"; 37 type = types.str; 38 description = "IP address and port of the web UI (console)."; 39 }; 40 41 dataDir = mkOption { 42 default = [ "/var/lib/minio/data" ]; 43 type = types.listOf (types.either types.path types.str); 44 description = "The list of data directories or nodes for storing the objects. Use one path for regular operation and the minimum of 4 endpoints for Erasure Code mode."; 45 }; 46 47 configDir = mkOption { 48 default = "/var/lib/minio/config"; 49 type = types.path; 50 description = "The config directory, for the access keys and other settings."; 51 }; 52 53 certificatesDir = mkOption { 54 default = "/var/lib/minio/certs"; 55 type = types.path; 56 description = "The directory where TLS certificates are stored."; 57 }; 58 59 accessKey = mkOption { 60 default = ""; 61 type = types.str; 62 description = '' 63 Access key of 5 to 20 characters in length that clients use to access the server. 64 This overrides the access key that is generated by minio on first startup and stored inside the 65 `configDir` directory. 66 ''; 67 }; 68 69 secretKey = mkOption { 70 default = ""; 71 type = types.str; 72 description = '' 73 Specify the Secret key of 8 to 40 characters in length that clients use to access the server. 74 This overrides the secret key that is generated by minio on first startup and stored inside the 75 `configDir` directory. 76 ''; 77 }; 78 79 rootCredentialsFile = mkOption { 80 type = types.nullOr types.path; 81 default = null; 82 description = '' 83 File containing the MINIO_ROOT_USER, default is "minioadmin", and 84 MINIO_ROOT_PASSWORD (length >= 8), default is "minioadmin"; in the format of 85 an EnvironmentFile=, as described by {manpage}`systemd.exec(5)`. 86 ''; 87 example = "/etc/nixos/minio-root-credentials"; 88 }; 89 90 region = mkOption { 91 default = "us-east-1"; 92 type = types.str; 93 description = '' 94 The physical location of the server. By default it is set to us-east-1, which is same as AWS S3's and Minio's default region. 95 ''; 96 }; 97 98 browser = mkOption { 99 default = true; 100 type = types.bool; 101 description = "Enable or disable access to web UI."; 102 }; 103 104 package = mkPackageOption pkgs "minio" { }; 105 }; 106 107 config = mkIf cfg.enable { 108 warnings = 109 optional ((cfg.accessKey != "") || (cfg.secretKey != "")) 110 "services.minio.`accessKey` and services.minio.`secretKey` are deprecated, please use services.minio.`rootCredentialsFile` instead."; 111 112 systemd = lib.mkMerge [ 113 { 114 tmpfiles.rules = [ 115 "d '${cfg.configDir}' - minio minio - -" 116 ] 117 ++ (map (x: "d '" + x + "' - minio minio - - ") (builtins.filter lib.types.path.check cfg.dataDir)); 118 119 services.minio = { 120 description = "Minio Object Storage"; 121 wants = [ "network-online.target" ]; 122 after = [ "network-online.target" ]; 123 wantedBy = [ "multi-user.target" ]; 124 serviceConfig = { 125 ExecStart = "${cfg.package}/bin/minio server --json --address ${cfg.listenAddress} --console-address ${cfg.consoleAddress} --config-dir=${cfg.configDir} --certs-dir=${cfg.certificatesDir} ${toString cfg.dataDir}"; 126 Type = "simple"; 127 User = "minio"; 128 Group = "minio"; 129 LimitNOFILE = 65536; 130 EnvironmentFile = 131 if (cfg.rootCredentialsFile != null) then 132 cfg.rootCredentialsFile 133 else if ((cfg.accessKey != "") || (cfg.secretKey != "")) then 134 (legacyCredentials cfg) 135 else 136 null; 137 138 # hardening 139 DevicePolicy = "closed"; 140 CapabilityBoundingSet = ""; 141 RestrictAddressFamilies = [ 142 "AF_INET" 143 "AF_INET6" 144 "AF_NETLINK" 145 "AF_UNIX" 146 ]; 147 DeviceAllow = ""; 148 NoNewPrivileges = true; 149 PrivateDevices = true; 150 PrivateMounts = true; 151 PrivateTmp = true; 152 PrivateUsers = true; 153 ProtectClock = true; 154 ProtectControlGroups = true; 155 ProtectHome = true; 156 ProtectKernelLogs = true; 157 ProtectKernelModules = true; 158 ProtectKernelTunables = true; 159 MemoryDenyWriteExecute = true; 160 LockPersonality = true; 161 RemoveIPC = true; 162 RestrictNamespaces = true; 163 RestrictRealtime = true; 164 RestrictSUIDSGID = true; 165 SystemCallArchitectures = "native"; 166 SystemCallFilter = [ 167 "@system-service" 168 "~@privileged" 169 ]; 170 ProtectProc = "invisible"; 171 ProtectHostname = true; 172 UMask = "0077"; 173 # minio opens /proc/mounts on startup 174 ProcSubset = "all"; 175 }; 176 environment = { 177 MINIO_REGION = "${cfg.region}"; 178 MINIO_BROWSER = "${if cfg.browser then "on" else "off"}"; 179 }; 180 }; 181 } 182 183 (lib.mkIf (cfg.rootCredentialsFile != null) { 184 # The service will fail if the credentials file is missing 185 services.minio.unitConfig.ConditionPathExists = cfg.rootCredentialsFile; 186 187 # The service will not restart if the credentials file has 188 # been changed. This can cause stale root credentials. 189 paths.minio-root-credentials = { 190 wantedBy = [ "multi-user.target" ]; 191 192 pathConfig = { 193 PathChanged = [ cfg.rootCredentialsFile ]; 194 Unit = "minio-restart.service"; 195 }; 196 }; 197 198 services.minio-restart = { 199 description = "Restart MinIO"; 200 201 script = '' 202 systemctl restart minio.service 203 ''; 204 205 serviceConfig = { 206 Type = "oneshot"; 207 Restart = "on-failure"; 208 RestartSec = 5; 209 }; 210 }; 211 }) 212 ]; 213 214 users.users.minio = { 215 group = "minio"; 216 uid = config.ids.uids.minio; 217 }; 218 219 users.groups.minio.gid = config.ids.uids.minio; 220 }; 221}