diff --git a/scripts/fresh_install.py b/scripts/fresh_install.py index a706023..d49b419 100755 --- a/scripts/fresh_install.py +++ b/scripts/fresh_install.py @@ -1,11 +1,16 @@ #!/usr/bin/env python3 import argparse import json +import pathlib +import shutil import socket import time from subprocess import check_output +ROOT_DIR = pathlib.Path(__file__).parent.parent +KEYS_FILE = ROOT_DIR / "secrets" / "keys.json" + def _get_available_machines() -> list: output = check_output(["nix", "flake", "show", "--json"]) @@ -14,23 +19,39 @@ def _get_available_machines() -> list: return list(machines) -def _validate_ip(ip: str) -> bool: +def _is_valid_ip(ip: str) -> bool: try: socket.inet_aton(ip) - return False - except socket.error: return True + except socket.error: + return False def _check_ssh_connection(ip: str) -> bool: try: - check_output(["ssh", f"root@{ip}", "echo", "Connected"]) + check_output(["ssh", f"krop@{ip}", "echo", "Connected"]) return True except Exception: return False -def add_key_to_secrets(key: str): - + +def add_key_to_secrets(machine_name: str, key: str): + keys = json.loads(KEYS_FILE.read_text()) + if keys.get("servers").get(machine_name): + raise ValueError(f"Key for {machine_name} already exists, remove it first") + + keys["servers"][machine_name] = key + + for secret in keys.get("secrets"): + keys["secrets"][secret].append(f"servers:{machine_name}") + + KEYS_FILE.write_text(json.dumps(keys, indent=2)) + + +def rekey_secrets(): + agenix_bin = shutil.which("agenix") + check_output([agenix_bin, "-r"], cwd=ROOT_DIR / "secrets") + def bootstrap_machine(ip: str): check_output( @@ -40,7 +61,7 @@ def bootstrap_machine(ip: str): "github:nix-community/nixos-anywhere", "--", "--flake", - '".#bootstrap"', + ".#bootstrap", "--target-host", f"root@{ip}", "--build-on-remote", @@ -48,19 +69,41 @@ def bootstrap_machine(ip: str): ) +def install_machine(machine_name: str, ip: str): + check_output( + [ + "nixos-rebuild", + "boot", + "--flake", + f".#{machine_name}", + "--fast", + "--target-host", + f"krop@{ip}", + "--build-host", + f"krop@{ip}", + "--use-remote-sudo", + ] + ) + + def get_ssh_key(ip: str) -> str: """ This function uses machines ssh-keyscan to get the ssh key and then get the ed25519 key """ - ssh_keys = check_output( - [ - "ssh-keyscan", - "-q", - "-t", - "ed25519", - ip, - ] - ).decode("utf-8").strip().splitlines() + ssh_keys = ( + check_output( + [ + "ssh-keyscan", + "-q", + "-t", + "ed25519", + ip, + ] + ) + .decode("utf-8") + .strip() + .splitlines() + ) if len(ssh_keys) != 1: raise ValueError("Exactly one key should be returned") @@ -69,6 +112,7 @@ def get_ssh_key(ip: str) -> str: return key + def get_machine_config(machine_name: str) -> dict: output = check_output( [ @@ -81,6 +125,17 @@ def get_machine_config(machine_name: str) -> dict: return json.loads(output) +def reboot_machine(ip: str): + check_output( + [ + "ssh", + f"krop@{ip}", + "sudo", + "reboot", + ] + ) + + def main() -> int: parser = argparse.ArgumentParser(description="Install a machine") parser.add_argument( @@ -95,32 +150,32 @@ def main() -> int: f"Machine {machine_name} not found, available machines are: {_get_available_machines()}" ) - if _validate_ip(args.machine_ip): - raise ValueError(f"Invalid IP address {args.machine_ip}") + machine_ip = args.machine_ip + if not _is_valid_ip(machine_ip): + raise ValueError(f"Invalid IP address {machine_ip}") - machine_config = get_machine_config(machine_name) - # We are bootstraping the machine first because we need their ssh keys - print(f"Bootstrapping machine {args.machine_ip}") - bootstrap_machine() + print(f"Bootstrapping machine {machine_ip}") + bootstrap_machine(machine_ip) print("Machine bootstrapped") print("Waiting for ssh connection") - while not _check_ssh_connection(): + while not _check_ssh_connection(machine_ip): time.sleep(5) print("Machine is up and running") print("Getting ssh key") - ssh_key = get_ssh_key(args.machine_ip) + ssh_key = get_ssh_key(machine_ip) + print(f"SSH key: {ssh_key}") print("Adding ssh key to secrets") - add_key_to_secrets(ssh_key) + add_key_to_secrets(machine_name, ssh_key) rekey_secrets() - # Add the ssh key to keys in secrets/keys.json - # and rekey the secrets - - # install_machine() - + print("Installing machine") + install_machine(machine_name, machine_ip) + print("Machine installed, rebooting") + reboot_machine(machine_ip) + print("") return 0 diff --git a/secrets/keys.json b/secrets/keys.json index 9c54dae..53e6e45 100644 --- a/secrets/keys.json +++ b/secrets/keys.json @@ -1,13 +1,16 @@ - { - "hosts": { - "wenar-nix": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJl0Rdo2kHliBeIiPuiO4kYO5M0VZFNXw4siepV1p6Pj", - "lenar": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOUnlAjPnMwJYgZb7YuholdTxifOEFnAyXVqI+xFlHw6" - }, - "servers" : { - "test-server": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID4ioqiTzYe6Y6H0YfFkWyDBbCB25wYs3gKNZIufE/Sn" - }, - "secrets": { - "mypassword.age": ["hosts:wenar-nix", "hosts:lenar", "servers:test-server"] - } -} + "hosts": { + "wenar-nix": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJl0Rdo2kHliBeIiPuiO4kYO5M0VZFNXw4siepV1p6Pj", + "lenar": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOUnlAjPnMwJYgZb7YuholdTxifOEFnAyXVqI+xFlHw6" + }, + "servers": { + "test-server": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID4ioqiTzYe6Y6H0YfFkWyDBbCB25wYs3gKNZIufE/Sn" + }, + "secrets": { + "mypassword.age": [ + "hosts:wenar-nix", + "hosts:lenar", + "servers:test-server" + ] + } +} \ No newline at end of file diff --git a/secrets/mypassword.age b/secrets/mypassword.age index f372b0a..6ae2b05 100644 Binary files a/secrets/mypassword.age and b/secrets/mypassword.age differ