{ config, pkgs, lib, ... }: let cfg = config.services.tangled.migrator; serve = pkgs.writeShellScript "migrator-serve" '' set -eu MIGRATOR_MASTER_KEY="$(cat "$CREDENTIALS_DIRECTORY/master-key")" MIGRATOR_PRIVATE_KEY="$(cat "$CREDENTIALS_DIRECTORY/private-key")" export MIGRATOR_MASTER_KEY MIGRATOR_PRIVATE_KEY exec ${lib.getExe cfg.package} serve ''; in with lib; { options.services.tangled.migrator = { enable = mkEnableOption "tangled centralized github repository importer"; package = mkOption { type = types.package; description = "migrator package to run"; }; listenAddr = mkOption { type = types.str; default = "0.0.0.0:6767"; description = "address the xrpc + did document server binds to"; }; hostname = mkOption { type = types.str; description = "public hostname; derives the migrator's did:web identity"; }; appUrl = mkOption { type = types.nullOr types.str; default = null; description = '' origin the browser is sent back to after an oauth grant (e.g. https://web.tngl.boltless.dev). unset sends users back to the migrator itself, which is never the right page. ''; }; dbPath = mkOption { type = types.str; default = "/var/lib/migrator/migrator.db"; description = "path to the migrator's sqlite database"; }; workDir = mkOption { type = types.str; default = "/var/lib/migrator/scratch"; description = "scratch directory for mirrors; only job- children are ever removed"; }; concurrency = mkOption { type = types.int; default = 3; description = "number of concurrent mirror jobs"; }; jobTimeout = mkOption { type = types.str; default = "55m"; description = "per-job wall clock limit, kept inside the one-hour grant window"; }; maxDiskBytes = mkOption { type = types.int; default = 21474836480; description = "per-job scratch byte limit, including LFS objects"; }; maxPackBytes = mkOption { type = types.int; default = 268435456; description = "largest Git pack handed to the knot"; }; plcUrl = mkOption { type = types.str; default = "https://plc.directory"; description = "plc directory the migrator resolves the dids it authenticates against"; }; masterKeyFile = mkOption { type = types.path; description = "file holding MIGRATOR_MASTER_KEY, the base64 32-byte credential key"; }; privateKeyFile = mkOption { type = types.path; description = "file holding MIGRATOR_PRIVATE_KEY, the service signing key in multibase"; }; environmentFile = mkOption { type = types.nullOr types.path; default = null; description = "extra environment for development overrides"; }; }; config = mkIf cfg.enable { systemd.services.migrator = { description = "tangled centralized github repository importer"; after = ["network-online.target"]; wants = ["network-online.target"]; wantedBy = ["multi-user.target"]; serviceConfig = { StateDirectory = "migrator"; Path = [pkgs.git pkgs.git-lfs]; EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile; Environment = [ "MIGRATOR_LISTEN_ADDR=${cfg.listenAddr}" "MIGRATOR_HOSTNAME=${cfg.hostname}" "MIGRATOR_DB_PATH=${cfg.dbPath}" "MIGRATOR_WORK_DIR=${cfg.workDir}" "MIGRATOR_CONCURRENCY=${toString cfg.concurrency}" "MIGRATOR_JOB_TIMEOUT=${cfg.jobTimeout}" "MIGRATOR_MAX_DISK_BYTES=${toString cfg.maxDiskBytes}" "MIGRATOR_MAX_PACK_BYTES=${toString cfg.maxPackBytes}" "MIGRATOR_PLC_URL=${cfg.plcUrl}" ] ++ lib.optionals (cfg.appUrl != null) [ "MIGRATOR_APP_URL=${cfg.appUrl}" ]; LoadCredential = [ "master-key:${cfg.masterKeyFile}" "private-key:${cfg.privateKeyFile}" ]; ExecStart = "${serve}"; Restart = "always"; }; }; }; }