{ config, pkgs, lib, ... }: let cfg = config.bagel.s3.garage; inherit (lib) mkEnableOption mkIf mkOption types; # TODO: send me back upstream to cl.forkos.org. wrap = pkg: name: pkgs.writeShellScriptBin name '' set -a [[ -z "''${GARAGE_RPC_SECRET:-}" ]] && source ${config.age.secrets.garage.path} set +a exec ${lib.getExe pkg} "$@" ''; # TODO: generalize this idea rootDomains = { lix = "lix.systems"; floral = "floral.systems"; }; in { options.bagel.s3.garage = { enable = mkEnableOption "the Garage implementation of S3"; tenant = mkOption { type = types.enum [ "lix" "floral" ]; }; api.address = mkOption { type = types.str; default = "127.0.0.1:3900"; }; rootDomain = mkOption { type = types.str; default = rootDomains.${cfg.tenant}; }; dataDir = mkOption { type = types.str; }; metadataDir = mkOption { default = "/var/lib/garage/metadata"; }; }; imports = [ (import ./garage-ephemeral-key.nix { inherit wrap; }) ]; config = mkIf cfg.enable { bagel.secrets.files = [ "garage-environment" ]; services.garage = { enable = true; # Slightly evil, but we have to wrap it here so the garage cli Just # Works(tm) from the shell. It will no-op in the wrapper if the env is # already set. package = wrap pkgs.garage_0_9 "garage"; settings = { data_dir = cfg.dataDir; metadata_dir = cfg.metadataDir; db_engine = "lmdb"; replication_mode = "none"; compression_level = 7; rpc_bind_addr = "[::]:3901"; rpc_public_addr = "127.0.0.1:3901"; s3_api = { s3_region = "garage"; api_bind_addr = cfg.api.address; root_domain = ".s3.${cfg.rootDomain}"; }; s3_web = { bind_addr = "127.0.0.1:3902"; root_domain = ".web.${cfg.rootDomain}"; index = "index.html"; }; k2v_api.api_bind_addr = "[::]:3904"; # FIXME(raito): api bind address should be secured. # admin.api_bind_addr = "[${wnlib.generateIPv6Address "monitoring" "cache"}]:3903"; }; environmentFile = config.age.secrets.garage-environment.path; }; systemd.services.garage.serviceConfig = { User = "garage"; ReadWriteDirectories = [ cfg.dataDir ]; StateDirectory = "garage"; }; users.users.garage = { isSystemUser = true; group = "garage"; }; users.groups.garage = { }; }; }