diff --git a/launch/main.tf b/launch/main.tf index 23c15ee1..7fd13e0c 100644 --- a/launch/main.tf +++ b/launch/main.tf @@ -1,11 +1,12 @@ locals { system = "x86_64-linux" - pins = jsondecode(file("${path.module}/.npins.json")) + # dependency paths pre-calculated from npins + pins = jsondecode(file("${path.root}/.npins.json")) + # nix path: expose pins, use nixpkgs in flake commands (`nix run`) nix_path = "${join(":", [for name, path in local.pins : "${name}=${path}"])}:flake=${local.pins["nixpkgs"]}:flake" - peripheral_configs = { - garage = "test01" - } + # user-facing applications application_configs = { + # FIXME: wrap applications at the interface to grab them in one go? mastodon = { cfg = var.mastodon hostname = "test06" @@ -19,32 +20,43 @@ locals { hostname = "test05" } } - peripherals = { for name, inst in local.peripheral_configs : name => { + # services shared between applications + peripherals = { for name, inst in { + garage = "test01" + } : name => { hostname = inst cfg = { + # enable if any user applications are enabled enable = anytrue([for _, app in local.application_configs: app.cfg.enable]) } } } } +# hash of our code directory, used in dev to trigger re-deploy # FIXME settle for pwd when in /nix/store? # FIXME calculate separately to reduce false positives data "external" "hash" { program = ["sh", "-c", "echo '{\"hash\":\"$(nix-hash ..)\"}'"] } -# merged instantiate/deploy to prevent 24+s instantiates when nothing changed. -# terraform-nixos separates these to only deploy if instantiate changed. -# FIXME find a better solution for this. current considerations were: -# - generic resources cannot have outputs, while we want info from the instantiation (unless built on host?). -# - `data` always runs, which is slow for deploy/instantiation. +# TF resource to build and deploy NixOS instances. resource "terraform_data" "nixos" { + for_each = {for name, inst in merge( local.peripherals, local.application_configs, ) : name => inst if inst.cfg.enable} + # trigger rebuild/deploy if (FIXME?) any potentially used config/code changed, + # preventing these (20+s, build being bottleneck) when nothing changed. + # terraform-nixos separates these to only deploy if instantiate changed, + # yet building even then - which may be not as bad using deploy on remote. + # having build/deploy one resource reflects wanting to prevent no-op rebuilds + # over preventing (with less false positives) no-op deployments, + # as i could not find a way to do prevent no-op rebuilds without merging them: + # - generic resources cannot have outputs, while we want info from the instantiation (unless built on host?). + # - `data` always runs, which is slow for deploy and especially build. triggers_replace = [ data.external.hash.result, var.domain, @@ -55,9 +67,13 @@ resource "terraform_data" "nixos" { ] provisioner "local-exec" { + # directory to run the script from. we use the TF project root dir, + # here as a path relative from where TF is run from. + # note that absolute paths can cause false positives in triggers, + # so are generally discouraged in TF. working_dir = path.root environment = { - # nix path used on deploy + # nix path used on build, lets us refer to e.g. nixpkgs like `` NIX_PATH = local.nix_path } # TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs? @@ -73,11 +89,13 @@ resource "terraform_data" "nixos" { os = import { system = "${local.system}"; configuration = { + # needed info passed in thru json from TF terraform = builtins.fromJSON "${replace(jsonencode({ domain = var.domain hostname = each.value.hostname initialUser = var.initialUser }), "\"", "\\\"")}"; + # note interpolations here TF ones imports = [ ${path.root}/options.nix ${path.root}/shared.nix @@ -89,19 +107,25 @@ resource "terraform_data" "nixos" { nix.nixPath = [ "${local.nix_path}" ]; }; }; - in { + in + # info we want to get back out + { substituters = builtins.concatStringsSep " " os.config.nix.settings.substituters; trusted_public_keys = builtins.concatStringsSep " " os.config.nix.settings.trusted-public-keys; drv_path = os.config.system.build.toplevel.drvPath; out_path = os.config.system.build.toplevel; }' ) + # instantiate the config in /nix/store "$${command[@]}" -A out_path + # get the other info json="$("$${command[@]}" --eval --strict --json)" # DEPLOY declare substituters trusted_public_keys drv_path + # set our variables using the json object eval "export $(echo $json | jaq -r 'to_entries | map("\(.key)=\(.value)") | @sh')" + # FIXME: de-hardcode domain host="root@${each.value.hostname}.abundos.eu" # FIXME: #24 buildArgs=( --option extra-binary-caches https://cache.nixos.org/ @@ -109,11 +133,14 @@ resource "terraform_data" "nixos" { --option trusted-public-keys $trusted_public_keys ) sshOpts=( - -o StrictHostKeyChecking=no -o BatchMode=yes + -o StrictHostKeyChecking=no ) + # get the realized derivation to deploy outPath=$(nix-store --realize "$drv_path" "$${buildArgs[@]}") + # deploy the config by nix-copy-closure NIX_SSHOPTS="$${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes + # switch the remote host to the config ssh "$${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch" EOF }