Compare commits

..

No commits in common. "6a4eb906581591043bca5e60e03970e2165a5d8c" and "1f5977468c81ceb684bdc058ffc94e7fc788a8fe" have entirely different histories.

9 changed files with 72 additions and 93 deletions

2
launch/.gitignore vendored
View file

@ -1,5 +1,5 @@
.auto.tfvars.json .auto.tfvars.json
.npins.json module.auto.tfvars.json
.terraform/ .terraform/
.terraform.tfstate.lock.info .terraform.tfstate.lock.info
terraform.tfstate* terraform.tfstate*

View file

@ -2,13 +2,12 @@
## usage ## usage
<-- TODO: port to just --> ### updating TF modules
### updating npins
```sh ```sh
$ npins update terraform-nixos
$ cd launch/ $ cd launch/
$ echo "$(nix eval --json -f ../npins)" > .npins.json $ echo "{\"terraform-nixos\": $(nix-instantiate --eval --json -E '(import ../npins).terraform-nixos.outPath')}" > module.auto.tfvars.json
``` ```
### local development ### local development

View file

@ -16,7 +16,7 @@ in
shell = pkgs.mkShellNoCC { shell = pkgs.mkShellNoCC {
packages = [ packages = [
pkgs.npins pkgs.npins
pkgs.jaq # tf pkgs.gnugrep # used in terraform-nixos
(import ./tf.nix { inherit lib pkgs; }) (import ./tf.nix { inherit lib pkgs; })
]; ];
}; };

View file

@ -1,3 +1,7 @@
variable "terraform-nixos" {
type = string
}
variable "domain" { variable "domain" {
type = string type = string
default = "fediversity.net" default = "fediversity.net"
@ -47,6 +51,7 @@ variable "initialUser" {
} }
} }
# TODO: could this straight-up be added in the child module instead?
variable "ssh_private_key_file" { variable "ssh_private_key_file" {
type = string type = string
description = "Path to private key used to connect to the target_host" description = "Path to private key used to connect to the target_host"
@ -61,11 +66,11 @@ variable "deploy_environment" {
locals { locals {
system = "x86_64-linux" system = "x86_64-linux"
pins = jsondecode(file("${path.module}/.npins.json")) pins = data.external.pins.result
peripheral_configs = { peripheral_services = {
garage = "test01" garage = "test01"
} }
application_configs = { applications = {
mastodon = { mastodon = {
cfg = var.mastodon cfg = var.mastodon
hostname = "test06" hostname = "test06"
@ -79,98 +84,51 @@ locals {
hostname = "test03" hostname = "test03"
} }
} }
peripherals = { for name, inst in local.peripheral_configs : name => { peripheral = { for name, inst in local.peripheral_services : name => {
hostname = inst hostname = inst
cfg = { cfg = {
enable = anytrue([for _, app in local.application_configs: app.cfg.enable]) enable = anytrue([for _, app in local.applications: 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? data "external" "pins" {
# FIXME calculate separately to reduce false positives program = ["nix", "eval", "--json", "-f", "${path.root}/../npins"]
data "external" "hash" {
program = ["echo", "{\"hash\":\"$(nix-hash ..)\"}"]
} }
# merge instantiate/deploy, cuz i don't want 24+s instantiates when nothing changed. module "deploy" {
# terraform-nixos separates these to only deploy if instantiate changed. source = "${var.terraform-nixos}//deploy_nixos"
# FIXME find a better solution for this. current considerations were:
# - `resource null_resource` cannot have outputs, while we want info from the instantiation (unless built on host?).
# - `data external` always runs, which is undesirable for steps like deploy/instantiation.
# FIXME null_resource docs recommend terraform_data over null_resource
resource "null_resource" "deploy_nixos" {
for_each = {for name, inst in merge( for_each = {for name, inst in merge(
local.peripherals, local.peripheral,
local.applications, local.applications,
) : name => inst if inst.cfg.enable} ) : name => inst if inst.cfg.enable}
ssh_private_key_file = var.ssh_private_key_file
triggers = data.external.hash.result target_host = "${each.value.hostname}.abundos.eu"
target_user= "root" # FIXME: #24
provisioner "local-exec" { target_system = local.system
working_dir = path.root NIX_PATH = join(":", [for name, path in local.pins : "${name}=${path}"])
environment = merge(var.deploy_environment, { deploy_environment = var.deploy_environment
NIX_PATH = join(":", [for name, path in local.pins : "${name}=${path}"]), config_pwd = path.root
}) config = <<-EOT
# TODO: refactor back to command="ignoreme" interpreter=concat([]) to protect sensitive data from error logs? {
# TODO: build on target? terraform = builtins.fromJSON ''${jsonencode({
command = <<-EOF domain = var.domain
set -euo pipefail hostname = each.value.hostname
initialUser = var.initialUser
# INSTANTIATE })}'';
command=( imports = [
nix-instantiate ${path.root}/options.nix
--expr ${path.root}/shared.nix
'let ${path.root}/${each.key}.nix
os = import <nixpkgs/nixos> { # FIXME: get VM details from TF
system = "${local.system}"; ${path.root}./infra/test-machines/${each.value.hostname}
configuration = { ];
terraform = builtins.fromJSON "${replace(jsonencode({ }
domain = var.domain EOT
hostname = each.value.hostname perform_gc = false
initialUser = var.initialUser build_on_target = false
}), "\"", "\\\"")}"; triggers = {
imports = [ pins = jsonencode(local.pins)
${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.binaryCaches;
trusted_public_keys = builtins.concatStringsSep " " os.config.nix.binaryCachePublicKeys;
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
} }
} }

View file

@ -0,0 +1 @@
{"terraform-nixos": "/nix/store/7rx25dwsw2xv9462rk2vkwy4qv33w76x-source"}

View file

@ -13,14 +13,24 @@ pkgs.stdenv.mkDerivation {
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
pushd launch/ pushd launch/
echo '${lib.strings.toJSON sources}' > .npins.json
# pass terraform-nixos path to TF through variable
# when switching TF to nix take this directly from `inputs`
# https://codeberg.org/kiara/e2ed-hetzner/commit/84b2a349d3e48ea2a17340bceff762d834fd4046
echo "{\"terraform-nixos\": \"${sources.terraform-nixos}\"}" > module.auto.tfvars.json
# point to the relevant providers
tofu init -input=false tofu init -input=false
popd popd
runHook postBuild runHook postBuild
''; '';
# FIXME: can the above even work without a connection?
installPhase = '' installPhase = ''
runHook preInstall runHook preInstall
cp -r . $out cp -r . $out
runHook postInstall runHook postInstall
''; '';
} }

View file

@ -71,6 +71,18 @@
"name": "nixpkgs-unstable", "name": "nixpkgs-unstable",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.05pre777917.b7ba7f9f45c5/nixexprs.tar.xz", "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.05pre777917.b7ba7f9f45c5/nixexprs.tar.xz",
"hash": "0jb6b7sv66bn06pchj2l88z0i5dlz0c2vb3z6pjjlq2p8q11zigg" "hash": "0jb6b7sv66bn06pchj2l88z0i5dlz0c2vb3z6pjjlq2p8q11zigg"
},
"terraform-nixos": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "KiaraGrouwstra",
"repo": "terraform-nixos"
},
"branch": "fediversity",
"revision": "54c57ae2e8c312c1b9f69524462d588966ed23b4",
"url": "https://github.com/KiaraGrouwstra/terraform-nixos/archive/54c57ae2e8c312c1b9f69524462d588966ed23b4.tar.gz",
"hash": "1yxps17ac5sljd1ri2p1q1x9h8dcxfpcf0hh6wcpic8ydwy45qql"
} }
}, },
"version": 3 "version": 3

View file

@ -10,7 +10,7 @@
pkgs.coreutils pkgs.coreutils
pkgs.openssh pkgs.openssh
pkgs.git pkgs.git
pkgs.jaq # tf pkgs.gnugrep # used in terraform-nixos
(import ../launch/tf.nix { inherit lib pkgs; }) (import ../launch/tf.nix { inherit lib pkgs; })
]; ];
SSH_PRIVATE_KEY_FILE = ""; SSH_PRIVATE_KEY_FILE = "";

View file

@ -161,7 +161,6 @@ class DeploymentStatus(ConfigurationForm):
f"-state={cwd}/terraform.tfstate", # FIXME: separate users' state f"-state={cwd}/terraform.tfstate", # FIXME: separate users' state
"--auto-approve", "--auto-approve",
"-lock=false", "-lock=false",
"-parallelism=1" # limit OOM risk
] ]
deployment_result = subprocess.run(cmd, cwd=cwd, env=env) deployment_result = subprocess.run(cmd, cwd=cwd, env=env)
logger.debug("deployment_result: %s", deployment_result) logger.debug("deployment_result: %s", deployment_result)