Last active 1 month ago

deploy-host.nix Raw
1(writeNuBin "deploy"
2 {
3 makeWrapperArgs = [
4 "--prefix"
5 "PATH"
6 ":"
7 (lib.makeBinPath (
8 with pkgs;
9 [
10 sops
11 git
12 ssh-to-age
13 nixos-anywhere
14 openssh
15 ]
16 ))
17 ];
18 }
19 # nu
20 ''
21 # A deployment script utilizing nixos-anywhere
22 #
23 # 1. Generates new SSH and Age Keys
24 # 2. Updates all secrets of that host
25 # 3. Deploys config with new Keys
26 @example "Deploy Zarqa" {deploy zarqa 192.168.2.201}
27 @example "Deploy Zarqa and generate facter.json" {deploy zarqa 192.168.2.201 --generate-hardware-report}
28 def main [host: string, ip: string, --generate-hardware-report]: nothing -> nothing {
29 # Work on raw YAML text for anchors
30 let raw = open --raw .sops.yaml
31
32 let anchor = $"host_($host)"
33 if not ($raw | str contains $"&($anchor)") {
34 error make $"Host anchor ($anchor) not found in .sops.yaml"
35 }
36
37 let old_age_key = $raw
38 | parse --regex $"&($anchor) \(?<key>age[0-9a-z]+\)"
39 | get key.0
40 if ($old_age_key | is-empty) {
41 error make $"Failed to extract old age key for ($anchor)"
42 }
43
44 # Create temp dir
45 let tempdir = mktemp -d
46 let ssh_dir = ($tempdir)/etc/ssh
47 mkdir $ssh_dir
48
49 let rsa_key = $"($ssh_dir)/ssh_host_rsa_key"
50 let ed25519_key = $"($ssh_dir)/ssh_host_ed25519_key"
51
52 ssh-keygen -t rsa -b 4096 -f $rsa_key -N "" -C $host
53 ssh-keygen -t ed25519 -f $ed25519_key -N "" -C $host
54
55 let age_pub = open --raw $"($ed25519_key).pub" | ssh-to-age
56
57 # Replace anchor in raw YAML
58 $raw
59 | str replace -r $"&($anchor) age[0-9a-z]+" $"&($anchor) ($age_pub)"
60 | save --force .sops.yaml
61
62 print $"Updated .sops.yaml for ($host)"
63
64 let git_files = git ls-files | lines
65
66 (open .sops.yaml).creation_rules
67 | where {|rule|
68 $rule.key_groups | any {|kg|
69 $kg.age | any {|k| $k == $age_pub }
70 }
71 }
72 | get path_regex
73 | par-each {|regex| $git_files | where {|f| $f =~ $regex } }
74 | flatten
75 | uniq
76 | each {|file_to_reencrypt|
77 print $"Re-encrypting ($file_to_reencrypt)"
78 sops updatekeys $file_to_reencrypt
79 print # needed so that updatekeys output is shown
80 }
81
82 nixos-anywhere --flake $".#($host)" (if $generate_hardware_report { $"--generate-hardware-config nixos-facter ./modules/hosts/($host)/facter.json" } else { "" }) --target-host $"root@($ip)" --extra-files $tempdir
83
84 # Remove lingering temp directory.
85 # We only care about the successful case because
86 # failing means the keys won't be used anyway
87 rm -rf $tempdir
88 }
89 ''
90)