feat(ops/terraform): add module for deploying NixOS system closures
This module makes it fairly easy to deploy NixOS system closures using Terraform, while properly separating the evaluation of a derivation (to determine whether a deploy is needed) from the building and copying of the closure itself. This has been on my stack for a while. It was originally developed for Resoptima, who agreed to open-sourcing it in depot back when we completed our work with them. Their contribution has been acknowledged in the README. Co-Authored-By: Florian Klink <flokli@flokli.de> Change-Id: Ica4c170658cd25f1fb7072c9a45735fcc4351474 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7950 Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
This commit is contained in:
parent
0b64577702
commit
dbca46d052
5 changed files with 187 additions and 0 deletions
98
ops/terraform/deploy-nixos/main.tf
Normal file
98
ops/terraform/deploy-nixos/main.tf
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# 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_name" {
|
||||
description = "unique name of the target machine"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "target_host" {
|
||||
description = "address (IP or hostname) at which the target is reachable"
|
||||
type = string
|
||||
}
|
||||
|
||||
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
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
# Fetch the derivation hash for the NixOS system.
|
||||
data "external" "nixos_system" {
|
||||
program = ["${path.module}/nixos-eval.sh"]
|
||||
|
||||
query = {
|
||||
attrpath = var.attrpath
|
||||
}
|
||||
}
|
||||
|
||||
# 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 = {
|
||||
nixos_drv = data.external.nixos_system.result.drv
|
||||
attrpath = var.attrpath
|
||||
target_host = var.target_host
|
||||
target_name = var.target_name
|
||||
}
|
||||
}
|
||||
|
||||
output "nixos_drv" {
|
||||
value = data.external.nixos_system.result
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue