Fediversity/launch/main.tf

183 lines
5.2 KiB
HCL

variable "domain" {
type = string
default = "fediversity.net"
}
variable "mastodon" {
type = object({
enable = bool
})
default = {
enable = false
}
}
variable "pixelfed" {
type = object({
enable = bool
})
default = {
enable = false
}
}
variable "peertube" {
type = object({
enable = bool
})
default = {
enable = false
}
}
variable "initialUser" {
type = object({
displayName = string
username = string
email = string
# TODO: mark (nested) credentials as sensitive
# https://discuss.hashicorp.com/t/is-it-possible-to-mark-an-attribute-of-an-object-as-sensitive/24649/2
password = string
})
default = {
displayName = "Testy McTestface"
username = "test"
email = "test@test.com"
password = "testtest"
}
}
variable "ssh_private_key_file" {
type = string
description = "Path to private key used to connect to the target_host"
default = ""
}
variable "deploy_environment" {
type = map(string)
description = "Extra environment variables to be set during deployment."
default = {}
}
locals {
system = "x86_64-linux"
pins = jsondecode(file("${path.module}/.npins.json"))
peripheral_configs = {
garage = "test01"
}
application_configs = {
mastodon = {
cfg = var.mastodon
hostname = "test06"
}
pixelfed = {
cfg = var.pixelfed
hostname = "test04"
}
peertube = {
cfg = var.peertube
hostname = "test05"
}
}
peripherals = { for name, inst in local.peripheral_configs : name => {
hostname = inst
cfg = {
enable = anytrue([for _, app in local.application_configs: app.cfg.enable])
}
}
}
applications = { for name, inst in local.application_configs : name => merge(inst, {
# depends_on = [for name in local.peripheral_configs : module.deploy[name]]
})
}
}
# 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.
resource "terraform_data" "nixos" {
for_each = {for name, inst in merge(
local.peripherals,
local.applications,
) : name => inst if inst.cfg.enable}
triggers_replace = [
data.external.hash.result,
var.deploy_environment,
var.domain,
var.initialUser,
local.system,
each.key,
each.value,
]
provisioner "local-exec" {
working_dir = path.root
environment = merge(var.deploy_environment, {
NIX_PATH = join(":", [for name, path in local.pins : "${name}=${path}"]),
})
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs?
# TODO: build on target?
command = <<-EOF
set -euo pipefail
# INSTANTIATE
command=(
nix-instantiate
--expr
'let
os = import <nixpkgs/nixos> {
system = "${local.system}";
configuration = {
terraform = builtins.fromJSON "${replace(jsonencode({
domain = var.domain
hostname = each.value.hostname
initialUser = var.initialUser
}), "\"", "\\\"")}";
imports = [
${path.root}/options.nix
${path.root}/shared.nix
${path.root}/${each.key}.nix
# FIXME: get VM details from TF
${path.root}/../infra/test-machines/${each.value.hostname}
];
};
};
in {
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;
}'
)
"$${command[@]}" -A out_path
json="$("$${command[@]}" --eval --strict --json)"
# DEPLOY
declare substituters trusted_public_keys drv_path
eval "export $(echo $json | jaq -r 'to_entries | map("\(.key)=\(.value)") | @sh')"
host="root@${each.value.hostname}.abundos.eu" # FIXME: #24
buildArgs=(
--option extra-binary-caches https://cache.nixos.org/
--option substituters $substituters
--option trusted-public-keys $trusted_public_keys
)
sshOpts=(
-o StrictHostKeyChecking=no
-o BatchMode=yes
-o "IdentityFile='${var.ssh_private_key_file}'"
)
outPath=$(nix-store --realize "$drv_path" "$${buildArgs[@]}")
NIX_SSHOPTS="$${sshOpts[*]}" nix-copy-closure --to "$host" "$outPath" --gzip --use-substitutes
ssh "$${sshOpts[@]}" "$host" "nix-env --profile /nix/var/nix/profiles/system --set $outPath; $outPath/bin/switch-to-configuration switch"
EOF
}
}