diff --git a/.rsync-filter b/.rsync-filter new file mode 100644 index 000000000..d7657cd00 --- /dev/null +++ b/.rsync-filter @@ -0,0 +1,2 @@ +- /.git +- /.graveyard diff --git a/Makefile b/Makefile index 5b898c54c..3798240e1 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,25 @@ deploy infest:;@ export filter=json make -s eval | sh +.PHONY: deploy2 +ifdef target +deploy2: export target-host = $(target) +else +deploy2: export target-host = $(system) +endif +deploy2:;@ + target=$${target-$$system} + result=$$(nix-instantiate \ + --json \ + --eval \ + krebs/populate.nix \ + --arg source 'with (import ~/stockholm {}).users.$(LOGNAME).$(system).config.krebs.build; assert source-version == 2; source' \ + --argstr target-host "$$target" \ + --argstr target-path /var/src) + script=$$(echo "$$result" | jq -r .) + echo "$$script" | sh + ssh root@$$target nixos-rebuild switch -I /var/src + .PHONY: eval eval: @ diff --git a/krebs/3modules/build.nix b/krebs/3modules/build.nix index 7f004cd81..0f8aec89d 100644 --- a/krebs/3modules/build.nix +++ b/krebs/3modules/build.nix @@ -28,48 +28,83 @@ let type = types.user; }; - options.krebs.build.source.dir = mkOption { - type = let - default-host = config.krebs.current.host; - in types.attrsOf (types.submodule ({ config, ... }: { - options = { - host = mkOption { - type = types.host; - default = default-host; - }; - path = mkOption { - type = types.str; - }; - target-path = mkOption { - type = types.str; - default = "/root/${config._module.args.name}"; - }; - url = mkOption { - type = types.str; - default = "file://${config.host.name}${config.path}"; - }; - }; - })); - default = {}; + options.krebs.build.source-version = mkOption { + type = types.enum [ 1 2 ]; + default = 1; }; - options.krebs.build.source.git = mkOption { - type = with types; attrsOf (submodule ({ config, ... }: { - options = { - url = mkOption { - type = types.str; # TODO must be shell safe - }; - rev = mkOption { - type = types.str; - }; - target-path = mkOption { - type = types.str; - default = "/root/${config._module.args.name}"; + options.krebs.build.source = getAttr "v${toString config.krebs.build.source-version}" { + v1 = { + dir = mkOption { + type = let + default-host = config.krebs.current.host; + in types.attrsOf (types.submodule ({ config, ... }: { + options = { + host = mkOption { + type = types.host; + default = default-host; + }; + path = mkOption { + type = types.str; + }; + target-path = mkOption { + type = types.str; + default = "/root/${config._module.args.name}"; + }; + url = mkOption { + type = types.str; + default = "file://${config.host.name}${config.path}"; + }; + }; + })); + default = {}; + }; + + git = mkOption { + type = with types; attrsOf (submodule ({ config, ... }: { + options = { + url = mkOption { + type = types.str; # TODO must be shell safe + }; + rev = mkOption { + type = types.str; + }; + target-path = mkOption { + type = types.str; + default = "/root/${config._module.args.name}"; + }; + }; + })); + default = {}; + }; + }; + + v2 = let + raw = types.either types.str types.path; + url = types.submodule { + options = { + url = mkOption { + type = types.str; + }; + rev = mkOption { + type = types.str; + }; + dev = mkOption { + type = types.str; + }; }; }; - })); - default = {}; + in mkOption { + type = types.attrsOf (types.either types.str url); + apply = let f = mapAttrs (_: value: { + string = value; + path = toString value; + set = f value; + }.${typeOf value}); in f; + default = {}; + }; }; + }; in out diff --git a/krebs/default.nix b/krebs/default.nix index 15d0e8e2e..2cdecaccb 100644 --- a/krebs/default.nix +++ b/krebs/default.nix @@ -171,9 +171,12 @@ let out = { ${b} ''; - get-config = system: - stockholm.users.${current-user-name}.${system}.config + get-config = system: let + config = stockholm.users.${current-user-name}.${system}.config or (abort "unknown system: ${system}, user: ${current-user-name}"); + in + assert config.krebs.build.source-version == 1; + config; nix-install = { system ? current-host-name diff --git a/krebs/populate.nix b/krebs/populate.nix new file mode 100644 index 000000000..9994fda82 --- /dev/null +++ b/krebs/populate.nix @@ -0,0 +1,115 @@ +{ source +, target-user ? "root" +, target-host +, target-path ? "/var/src" +}: +with import ; +with import ~/stockholm/krebs/4lib { + lib = import ; +}; +with builtins; +let + out = '' + #! /bin/sh + set -efu + + echo ${shell.escape git-script} \ + | ssh ${shell.escape "${target-user}@${target-host}"} -T + + tmpdir=$(mktemp -dt stockholm.XXXXXXXX) + trap ' + set +f + rm "$tmpdir"/* + rmdir "$tmpdir" + trap - EXIT INT QUIT + ' EXIT INT QUIT + ${concatStringsSep "\n" + (mapAttrsToList + (name: spec: let dst = removePrefix "symlink:" (get-url spec); in + "ln -s ${shell.escape dst} $tmpdir/${shell.escape name}") + symlink-specs)} + + proot \ + -b $tmpdir:${shell.escape target-path} \ + ${concatStringsSep " \\\n " + (mapAttrsToList + (name: spec: + "-b ${shell.escape "${get-url spec}:${target-path}/${name}"}") + file-specs)} \ + rsync \ + -f ${shell.escape "P /*"} \ + ${concatMapStringsSep " \\\n " + (name: "-f ${shell.escape "R /${name}"}") + (attrNames file-specs)} \ + --delete \ + -vFrlptD \ + ${shell.escape target-path}/ \ + ${shell.escape "${target-user}@${target-host}:${target-path}"} + ''; + + get-schema = uri: + if substring 0 1 uri == "/" + then "file" + else head (splitString ":" uri); + + has-schema = schema: uri: get-schema uri == schema; + + get-url = spec: { + string = spec; + path = toString spec; + set = get-url spec.url; + }.${typeOf spec}; + + git-specs = + filterAttrs (_: spec: has-schema "https" (get-url spec)) source // + filterAttrs (_: spec: has-schema "http" (get-url spec)) source // + filterAttrs (_: spec: has-schema "git" (get-url spec)) source; + + file-specs = + filterAttrs (_: spec: has-schema "file" (get-url spec)) source; + + symlink-specs = + filterAttrs (_: spec: has-schema "symlink" (get-url spec)) source; + + git-script = '' + fetch_git() {( + dst_dir=$1 + src_url=$2 + src_ref=$3 + + if ! test -e "$dst_dir"; then + git clone "$src_url" "$dst_dir" + fi + + cd "$dst_dir" + + if ! url=$(git config remote.origin.url); then + git remote add origin "$src_url" + elif test "$url" != "$src_url"; then + git remote set-url origin "$src_url" + fi + + # TODO resolve src_ref to commit hash + hash=$src_ref + + if ! test "$(git log --format=%H -1)" = "$hash"; then + git fetch origin + git checkout "$hash" -- "$dst_dir" + git checkout "$hash" + fi + + git clean -dxf + )} + + ${concatStringsSep "\n" + (mapAttrsToList + (name: spec: toString (map shell.escape [ + "fetch_git" + "${target-path}/${name}" + spec.url + spec.rev + ])) + git-specs)} + ''; + +in out diff --git a/nixpkgs/default.nix b/nixpkgs/default.nix new file mode 100644 index 000000000..92da82c35 --- /dev/null +++ b/nixpkgs/default.nix @@ -0,0 +1 @@ +import diff --git a/nixpkgs/nixos/default.nix b/nixpkgs/nixos/default.nix new file mode 100644 index 000000000..6c5adf365 --- /dev/null +++ b/nixpkgs/nixos/default.nix @@ -0,0 +1,65 @@ +{ configuration ? import "NIXOS_CONFIG" +, system ? builtins.currentSystem +}: + +let + eval-config = modules: import { + inherit system; + modules = modules ++ [({ config, lib, ... }: with lib; { + imports = filter dir.has-default-nix (concatLists [ + (map (p: p + "/2configs") [ ]) + (map (p: p + "/3modules") [ ]) + ]); + + krebs.current = { + enable = true; + host = config.krebs.hosts.${readFile /proc/sys/kernel/hostname}; + user = config.krebs.users.${getEnv "LOGNAME"}; + }; + + nixpkgs.config.packageOverrides = pkgs: let + kpkgs = import { inherit lib pkgs; }; + upkgs = import { inherit lib; pkgs = pkgs // kpkgs; }; + in kpkgs // upkgs; + })]; + specialArgs = { + lib = let + nlib = import // builtins; + klib = nlib // import { lib = nlib; }; + ulib = klib // (with klib; let p = + "/4lib"; in + optionalAttrs (dir.has-default-nix p) + (import p { lib = klib; })); + in ulib; + }; + }; + + eval = eval-config [ + configuration + ]; + + # This is for `nixos-rebuild build-vm'. + vm = eval-config [ + configuration + + ]; + + # This is for `nixos-rebuild build-vm-with-bootloader'. + vm-with-bootloader = eval-config [ + configuration + + { virtualisation.useBootLoader = true; } + ]; +in + +{ + inherit (eval) config options; + + system = eval.config.system.build.toplevel; + + vm = vm.config.system.build.vm; + + vmWithBootLoader = vm-with-bootloader.config.system.build.vm; + + # The following are used by nixos-rebuild. + nixFallback = eval.pkgs.nixUnstable; +} diff --git a/nixpkgs/nixos/modules b/nixpkgs/nixos/modules new file mode 120000 index 000000000..8fbc4373e --- /dev/null +++ b/nixpkgs/nixos/modules @@ -0,0 +1 @@ +../../upstream-nixpkgs/nixos/modules \ No newline at end of file diff --git a/tv/1systems/cd.nix b/tv/1systems/cd.nix index 8c2a9ae43..b69d7655a 100644 --- a/tv/1systems/cd.nix +++ b/tv/1systems/cd.nix @@ -6,6 +6,11 @@ with lib; krebs.build.host = config.krebs.hosts.cd; krebs.build.target = "root@cd.internet"; + krebs.build.source.upstream-nixpkgs = { + url = https://github.com/NixOS/nixpkgs; + rev = "b7ff030"; + }; + imports = [ ../2configs/hw/CAC-Developer-2.nix ../2configs/fs/CAC-CentOS-7-64bit.nix diff --git a/tv/2configs/default.nix b/tv/2configs/default.nix index dc55a4330..e7197c4c4 100644 --- a/tv/2configs/default.nix +++ b/tv/2configs/default.nix @@ -8,20 +8,23 @@ with lib; krebs.build = { user = config.krebs.users.tv; target = mkDefault "root@${config.krebs.build.host.name}"; - source = { - git.nixpkgs = { - url = mkDefault https://github.com/NixOS/nixpkgs; - rev = mkDefault "77f8f35d57618c1ba456d968524f2fb2c3448295"; - target-path = mkDefault "/var/src/nixpkgs"; + source-version = 2; + source = mapAttrs (_: mkDefault) ({ + nixos-config = "symlink:stockholm-private/1systems/${config.krebs.build.host.name}.nix"; + nixpkgs = symlink:stockholm-nixpkgs; + secrets = "/home/tv/secrets/${config.krebs.build.host.name}"; + secrets-common = "/home/tv/secrets/common"; + stockholm-krebs = "/home/tv/stockholm/krebs"; + stockholm-nixpkgs = "/home/tv/stockholm/nixpkgs"; + stockholm-private = "/home/tv/stockholm/tv"; + upstream-nixpkgs = { + url = https://github.com/NixOS/nixpkgs; + rev = "77f8f35d57618c1ba456d968524f2fb2c3448295"; + dev = "/home/tv/nixpkgs"; }; - dir.secrets = { - path = mkDefault "/home/tv/secrets/${config.krebs.build.host.name}"; - }; - dir.stockholm = { - path = mkDefault "/home/tv/stockholm"; - target-path = mkDefault "/var/src/stockholm"; - }; - }; + } // optionalAttrs config.krebs.build.host.secure { + secrets-master = "/home/tv/secrets/master"; + }); }; networking.hostName = config.krebs.build.host.name; @@ -98,12 +101,7 @@ with lib; }; environment.variables = { - NIX_PATH = - with config.krebs.build.source; with dir; with git; - mkForce (concatStringsSep ":" [ - "nixpkgs=${nixpkgs.target-path}" - "secrets=${stockholm.target-path}/null" - ]); + NIX_PATH = mkForce "/var/src"; }; programs.bash = {