summaryrefslogtreecommitdiff
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
parent7c4275017db7b31da2bd9299c83e28ead981b5ed (diff)
script it
-rw-r--r--flake.nix38
-rw-r--r--kj-laptop01/configuration.nix2
-rw-r--r--nixos-update.rb127
3 files changed, 138 insertions, 29 deletions
diff --git a/flake.nix b/flake.nix
index f898318..6d5f636 100644
--- a/flake.nix
+++ b/flake.nix
@@ -49,38 +49,20 @@
let
pkgs = nixpkgs-stable.legacyPackages.${system};
- install-script = pkgs.writers.writeRubyBin "install" {
- libraries = [];
- } /* ruby */ ''
- require 'tmpdir'
- require 'open3'
- require 'json'
- require 'fileutils'
+ nixos-update = pkgs.writers.writeRubyBin "nixos-update" {
+ libraries = [ pkgs.rubyPackages.tty-command ];
+ runtimeInputs = [
+ pkgs.sops
+ pkgs.nixos-anywhere
+ pkgs.nixos-rebuild
+ ];
+ } (builtins.readFile ./nixos-update.rb);
- system_flake = ARGV[0]
- ENV['SOPS_AGE_KEY_FILE'] ||= File.expand_path("~/.config/sops/age/keys.txt")
- sops_exe = "${pkgs.sops}/bin/sops"
- nixos_anywhere_exe = "${pkgs.nixos-anywhere}/bin/nixos-anywhere"
-
- secret_data_raw, status = Open3.capture2(sops_exe, "decrypt", "--output-type", "json", "#{system_flake}/secrets.yaml")
- raise "Failed to decrypt secrets.yaml" unless status.success?
- secret_data = JSON.parse(secret_data_raw)
-
- Dir.mktmpdir("secrets") do |secret_dir|
- FileUtils.mkdir_p(File.join(secret_dir, 'copy_dir/etc/ssh'))
- File.write(File.join(secret_dir, 'copy_dir/etc/ssh/ssh_host_ed25519_key'), secret_data["ssh_host_key_ed25519"])
- File.write(File.join(secret_dir, 'luks_passphrase'), secret_data["luks_passphrase"])
-
- system nixos_anywhere_exe, "--disk-encryption-keys", File.join(secret_dir, 'luks_passphrase'),
- "--extra-files", File.join(secret_dir, 'copy_dir'), "--flake", ".##{system_flake}", *ARGV[1..-1],
- exception: true
- end
- '';
in
{
- install = {
+ nixos-update = {
type = "app";
- program = "${install-script}/bin/install";
+ program = "${nixos-update}/bin/nixos-update";
};
});
};
diff --git a/kj-laptop01/configuration.nix b/kj-laptop01/configuration.nix
index 2ad9ebd..ae4c54d 100644
--- a/kj-laptop01/configuration.nix
+++ b/kj-laptop01/configuration.nix
@@ -40,7 +40,7 @@
isNormalUser = true;
description = "KJ Tsanaktsidis";
group = "kjtsanaktsidis";
- extraGroups = [ "wheel" ];
+ extraGroups = [ "wheel" "networkmanager" ];
hashedPasswordFile = config.sops.secrets.kj_hashed_password.path;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAC/BtvW1c1RbBI8eeGo7oOH2y9byBaxWVDHsErgaE+s kjtsanaktsidis@KJMacbookGroq.local"
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