diff options
Diffstat (limited to 'ops/terraform/deploy-nixos/main.tf')
-rw-r--r-- | ops/terraform/deploy-nixos/main.tf | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/ops/terraform/deploy-nixos/main.tf b/ops/terraform/deploy-nixos/main.tf new file mode 100644 index 000000000000..00023fba69b2 --- /dev/null +++ b/ops/terraform/deploy-nixos/main.tf @@ -0,0 +1,113 @@ +# SPDX-FileCopyrightText: 2023 The TVL Authors +# +# SPDX-License-Identifier: MIT + +# This module deploys a NixOS host by building a system closure +# located at the specified attribute in the current repository. +# +# The closure's derivation path is persisted in the Terraform state to +# determine after Nix evaluation whether the system closure has +# changed and needs to be built/deployed. +# +# The system configuration is then built (or substituted) on the +# machine that runs `terraform apply`, then copied and activated on +# the target machine using `nix-copy-closure`. + +variable "attrpath" { + description = "attribute set path pointing to the NixOS system closure" + type = string +} + +variable "target_host" { + description = "address (IP or hostname) at which the target is reachable" + type = string +} + +variable "entrypoint" { + description = <<EOT + Path to a .nix file (or directory containing `default.nix` file) + that provides the attrset specified in `closure`. + If unset, asks git for the root of the repository. + EOT + type = string + default = "" +} + +variable "target_user" { + description = "username on the target machine" + type = string +} + +variable "target_user_ssh_key" { + description = "SSH key to use for connecting to the target" + type = string + default = "" + sensitive = true +} + +variable "triggers" { + type = map(string) + description = "Triggers for deploy" + default = {} +} + +# Fetch the derivation hash for the NixOS system. +data "external" "nixos_system" { + program = ["${path.module}/nixos-eval.sh"] + + query = { + attrpath = var.attrpath + entrypoint = var.entrypoint + } +} + +# Deploy the NixOS configuration if anything changed. +resource "null_resource" "nixos_deploy" { + connection { + type = "ssh" + host = var.target_host + user = var.target_user + private_key = var.target_user_ssh_key + } + + # 1. Wait for SSH to become available. + provisioner "remote-exec" { + inline = ["true"] + } + + # 2. Build NixOS system. + provisioner "local-exec" { + command = "nix-build ${data.external.nixos_system.result.drv} --no-out-link" + } + + # 3. Copy closure to the target. + provisioner "local-exec" { + command = "${path.module}/nixos-copy.sh" + + environment = { + SYSTEM_DRV = data.external.nixos_system.result.drv + TARGET_HOST = var.target_host + DEPLOY_KEY = var.target_user_ssh_key + TARGET_USER = var.target_user + } + } + + # 4. Activate closure on the target. + provisioner "remote-exec" { + inline = [ + "set -eu", + "SYSTEM=$(nix-build ${data.external.nixos_system.result.drv} --no-out-link)", + "sudo nix-env --profile /nix/var/nix/profiles/system --set $SYSTEM", + "sudo $SYSTEM/bin/switch-to-configuration switch", + ] + } + + triggers = merge({ + nixos_drv = data.external.nixos_system.result.drv + target_host = var.target_host + }, var.triggers) +} + +output "nixos_drv" { + value = data.external.nixos_system.result +} |