Last active 1 month ago

kg's Avatar kg revised this gist 1 month ago. Go to revision

1 file changed, 10 insertions, 3 deletions

deploy-host.nix

@@ -1,4 +1,4 @@
1 - (pkgs.writers.writeNuBin "deploy"
1 + (writeNuBin "deploy"
2 2 {
3 3 makeWrapperArgs = [
4 4 "--prefix"
@@ -18,7 +18,14 @@
18 18 }
19 19 # nu
20 20 ''
21 - def main [host: string, ip: string, ...args: string]: nothing -> nothing {
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 {
22 29 # Work on raw YAML text for anchors
23 30 let raw = open --raw .sops.yaml
24 31
@@ -72,7 +79,7 @@
72 79 print # needed so that updatekeys output is shown
73 80 }
74 81
75 - nixos-anywhere --flake $".#($host)" --target-host $"root@($ip)" --extra-files $tempdir ...$args
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
76 83
77 84 # Remove lingering temp directory.
78 85 # We only care about the successful case because

kg's Avatar kg revised this gist 1 month ago. Go to revision

1 file changed, 1 insertion, 1 deletion

deploy-host.nix

@@ -1,4 +1,4 @@
1 - (writeNuBin "deploy"
1 + (pkgs.writers.writeNuBin "deploy"
2 2 {
3 3 makeWrapperArgs = [
4 4 "--prefix"

kg's Avatar kg revised this gist 1 month ago. Go to revision

1 file changed, 83 insertions

deploy-host.nix(file created)

@@ -0,0 +1,83 @@
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 + def main [host: string, ip: string, ...args: string]: nothing -> nothing {
22 + # Work on raw YAML text for anchors
23 + let raw = open --raw .sops.yaml
24 +
25 + let anchor = $"host_($host)"
26 + if not ($raw | str contains $"&($anchor)") {
27 + error make $"Host anchor ($anchor) not found in .sops.yaml"
28 + }
29 +
30 + let old_age_key = $raw
31 + | parse --regex $"&($anchor) \(?<key>age[0-9a-z]+\)"
32 + | get key.0
33 + if ($old_age_key | is-empty) {
34 + error make $"Failed to extract old age key for ($anchor)"
35 + }
36 +
37 + # Create temp dir
38 + let tempdir = mktemp -d
39 + let ssh_dir = ($tempdir)/etc/ssh
40 + mkdir $ssh_dir
41 +
42 + let rsa_key = $"($ssh_dir)/ssh_host_rsa_key"
43 + let ed25519_key = $"($ssh_dir)/ssh_host_ed25519_key"
44 +
45 + ssh-keygen -t rsa -b 4096 -f $rsa_key -N "" -C $host
46 + ssh-keygen -t ed25519 -f $ed25519_key -N "" -C $host
47 +
48 + let age_pub = open --raw $"($ed25519_key).pub" | ssh-to-age
49 +
50 + # Replace anchor in raw YAML
51 + $raw
52 + | str replace -r $"&($anchor) age[0-9a-z]+" $"&($anchor) ($age_pub)"
53 + | save --force .sops.yaml
54 +
55 + print $"Updated .sops.yaml for ($host)"
56 +
57 + let git_files = git ls-files | lines
58 +
59 + (open .sops.yaml).creation_rules
60 + | where {|rule|
61 + $rule.key_groups | any {|kg|
62 + $kg.age | any {|k| $k == $age_pub }
63 + }
64 + }
65 + | get path_regex
66 + | par-each {|regex| $git_files | where {|f| $f =~ $regex } }
67 + | flatten
68 + | uniq
69 + | each {|file_to_reencrypt|
70 + print $"Re-encrypting ($file_to_reencrypt)"
71 + sops updatekeys $file_to_reencrypt
72 + print # needed so that updatekeys output is shown
73 + }
74 +
75 + nixos-anywhere --flake $".#($host)" --target-host $"root@($ip)" --extra-files $tempdir ...$args
76 +
77 + # Remove lingering temp directory.
78 + # We only care about the successful case because
79 + # failing means the keys won't be used anyway
80 + rm -rf $tempdir
81 + }
82 + ''
83 + )
Newer Older