summaryrefslogtreecommitdiff
path: root/nixos-update.rb
diff options
context:
space:
mode:
authorKj Tsanaktsidis <kjtsanaktsidis@groq.com>2025-09-07 15:39:01 +1000
committerKj Tsanaktsidis <kjtsanaktsidis@groq.com>2025-09-07 15:39:01 +1000
commit6ad580f49e7412eb428b45b4fa03039f17fb5c8e (patch)
tree6e49c1dab1ccf2738fba2d1084a02d8b5b04ae19 /nixos-update.rb
parent7c4275017db7b31da2bd9299c83e28ead981b5ed (diff)
script it
Diffstat (limited to 'nixos-update.rb')
-rw-r--r--nixos-update.rb127
1 files changed, 127 insertions, 0 deletions
diff --git a/nixos-update.rb b/nixos-update.rb
new file mode 100644
index 0000000..b6f3607
--- /dev/null
+++ b/nixos-update.rb
@@ -0,0 +1,127 @@
+#!/usr/bin/env ruby
+
+require 'tmpdir'
+require 'json'
+require 'fileutils'
+require 'tty-command'
+require 'etc'
+require 'optparse'
+
+class NixOSUpdater
+ def initialize
+ @options = parse_options
+ @system_flake = ARGV[0]
+ @target_host = ARGV[1]
+
+ validate_args!
+
+ ENV['SOPS_AGE_KEY_FILE'] ||= File.expand_path('~/.config/sops/age/keys.txt')
+ end
+
+ def run
+ if @options[:install]
+ perform_install
+ else
+ perform_update
+ end
+ end
+
+ private
+
+ def parse_options
+ options = {}
+
+ OptionParser.new do |opts|
+ opts.banner = 'Usage: nixos-update.rb [--install] --system-def <def> --target <target>'
+
+ opts.on('--install', 'Perform initial installation with nixos-anywhere') do
+ options[:install] = true
+ end
+
+ opts.on('-h', '--help', 'Show this help message') do
+ puts opts
+ exit
+ end
+
+ opts.on('--system-def', 'what system configuration to install') do |defn|
+ @system_def = defn
+ end
+
+ opts.on('--target', 'what user@host to install to') do |target|
+ @target = target
+ end
+
+ opts.on('--build-on', 'what user@host to build on') do |build_on|
+ @build_on = build_on
+ end
+ end.parse!
+
+ options
+ end
+
+ def validate_args!
+ if @system_def.nil?
+ warn 'Error: --system-def argument is required'
+ exit 1
+ end
+
+ @target = "#{Etc.getlogin}@#{@system_def}" if @target.nil?
+ @build_on = @target if @build_on.nil? && RUBY_PLATFORM !~ /linux/
+ end
+
+ def decrypt_secrets
+ cmd = TTY::Command.new(printer: :null)
+ result = cmd.run(sops_exe, 'decrypt', '--output-type', 'json', "#{@system_flake}/secrets.yaml")
+ JSON.parse(result.out)
+ end
+
+ def perform_install
+ puts "### Performing initial installation of #{@system_flake} to #{@target_host} ###"
+
+ secrets = decrypt_secrets
+
+ Dir.mktmpdir('secrets') do |dir|
+ FileUtils.mkdir_p("#{dir}/copy_dir/etc/ssh")
+ File.write("#{dir}/copy_dir/etc/ssh/ssh_host_ed25519_key", secrets['ssh_host_key_ed25519'])
+ File.write("#{dir}/luks_passphrase", secrets['luks_passphrase'])
+
+ cmd_args = [
+ 'nixos-anywhere',
+ '--disk-encryption-keys', "#{dir}/luks_passphrase", "#{dir}/luks_passphrase",
+ '--extra-files', "#{dir}/copy_dir",
+ '--flake', ".##{@system_flake}"
+ ]
+
+ cmd_args << '--build-on-remote' if RUBY_PLATFORM !~ /linux/
+ cmd_args << @target_host
+
+ # Execute nixos-anywhere
+ cmd = TTY::Command.new
+ cmd.run(*cmd_args)
+ end
+ end
+
+ def perform_update
+ puts "### Updating #{@system_flake} configuration on #{@target_host} ###"
+
+ cmd_args = [
+ 'nixos-rebuild-ng',
+ 'switch',
+ '--flake', ".##{@system_flake}",
+ '--sudo', '--ask-sudo-passowrd'
+ ]
+
+ if @target_host
+ cmd_args << '--target-host' << @target_host
+ cmd_args << '--use-remote-sudo'
+ end
+
+ cmd_args << '--build-on' << @build_on if @build_on
+
+ cmd = TTY::Command.new
+ cmd.run(*cmd_args)
+ end
+end
+
+# Run the updater
+NixOSUpdater.new.run