From 6ad580f49e7412eb428b45b4fa03039f17fb5c8e Mon Sep 17 00:00:00 2001 From: Kj Tsanaktsidis Date: Sun, 7 Sep 2025 15:39:01 +1000 Subject: script it --- nixos-update.rb | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 nixos-update.rb (limited to 'nixos-update.rb') 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 --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 -- cgit v1.2.3