|
10 | 10 | import subprocess
|
11 | 11 | import sys
|
12 | 12 | import time
|
13 |
| -from contextlib import contextmanager |
| 13 | +from contextlib import ExitStack, contextmanager |
14 | 14 | from dataclasses import dataclass
|
15 | 15 | from pathlib import Path
|
16 | 16 | from tempfile import TemporaryDirectory
|
@@ -246,6 +246,7 @@ class Options:
|
246 | 246 | pixiecore_http_port: int
|
247 | 247 | pause_after_completion: bool
|
248 | 248 | nixos_anywhere_args: list[str]
|
| 249 | + private_key: Path | None = None |
249 | 250 |
|
250 | 251 |
|
251 | 252 | @contextmanager
|
@@ -337,6 +338,12 @@ def parse_args(args: list[str]) -> Options:
|
337 | 338 | help="Skip opening firewall ports",
|
338 | 339 | action="store_true",
|
339 | 340 | )
|
| 341 | + parser.add_argument( |
| 342 | + "-i", |
| 343 | + "--private-key", |
| 344 | + help="Path to private key to use for ssh connection to target machine", |
| 345 | + type=Path, |
| 346 | + ) |
340 | 347 |
|
341 | 348 | parsed, unknown_args = parser.parse_known_args(args)
|
342 | 349 | try:
|
@@ -377,6 +384,7 @@ def parse_args(args: list[str]) -> Options:
|
377 | 384 | pixiecore_http_port=parsed.pixiecore_http_port,
|
378 | 385 | pause_after_completion=parsed.pause_after_completion,
|
379 | 386 | nixos_anywhere_args=unknown_args,
|
| 387 | + private_key=parsed.private_key, |
380 | 388 | )
|
381 | 389 |
|
382 | 390 |
|
@@ -411,12 +419,13 @@ def nixos_anywhere(
|
411 | 419 | "-L",
|
412 | 420 | # do not substitute because we do not have internet and copying locally is faster.
|
413 | 421 | "--no-substitute-on-destination",
|
| 422 | + "-i", |
| 423 | + ssh_private_key, |
414 | 424 | ip,
|
415 | 425 | *nixos_anywhere_args,
|
416 | 426 | ]
|
417 | 427 | run(
|
418 | 428 | cmd,
|
419 |
| - extra_env=dict(SSH_PRIVATE_KEY=ssh_private_key.read_text()), |
420 | 429 | check=False,
|
421 | 430 | )
|
422 | 431 | print("If the installation failed, you may run the install command manually again:")
|
@@ -509,22 +518,36 @@ def run_nixos_anywhere(options: Options) -> None:
|
509 | 518 | pxe_image_store_path = build_pxe_image(options.netboot_image_flake)
|
510 | 519 |
|
511 | 520 | random_hostname = f"nixos-pxe-{binascii.b2a_hex(os.urandom(4)).decode('ascii')}"
|
512 |
| - with ( |
513 |
| - configure_network_interface( |
514 |
| - options.dhcp_interface, |
515 |
| - f"{options.dhcp_server_ip}/{options.dhcp_subnet}", |
516 |
| - ), |
517 |
| - ssh_private_key() as ssh_key, |
518 |
| - open_firewall(options), |
519 |
| - start_pixiecore( |
520 |
| - options.dhcp_server_ip, |
521 |
| - options.pixiecore_http_port, |
522 |
| - ssh_key.public_key, |
523 |
| - pxe_image_store_path, |
524 |
| - random_hostname, |
525 |
| - ), |
526 |
| - start_dnsmasq(options.dhcp_interface, options.dhcp_range) as dnsmasq, |
527 |
| - ): |
| 521 | + |
| 522 | + subprocess.run(["nixos-rebuild", "build", "--flake", options.flake], check=True) |
| 523 | + |
| 524 | + with ExitStack() as stack: |
| 525 | + stack.enter_context( |
| 526 | + configure_network_interface( |
| 527 | + options.dhcp_interface, |
| 528 | + f"{options.dhcp_server_ip}/{options.dhcp_subnet}", |
| 529 | + ) |
| 530 | + ) |
| 531 | + if options.private_key is None: |
| 532 | + ssh_key = stack.enter_context(ssh_private_key()) |
| 533 | + else: |
| 534 | + ssh_key = SshKey( |
| 535 | + private_key=options.private_key, |
| 536 | + public_key=options.private_key.with_suffix(".pub"), |
| 537 | + ) |
| 538 | + stack.enter_context(open_firewall(options)) |
| 539 | + stack.enter_context( |
| 540 | + start_pixiecore( |
| 541 | + options.dhcp_server_ip, |
| 542 | + options.pixiecore_http_port, |
| 543 | + ssh_key.public_key, |
| 544 | + pxe_image_store_path, |
| 545 | + random_hostname, |
| 546 | + ) |
| 547 | + ) |
| 548 | + dnsmasq = stack.enter_context( |
| 549 | + start_dnsmasq(options.dhcp_interface, options.dhcp_range) |
| 550 | + ) |
528 | 551 | print("Waiting for a client to install nixos to. Cancel with Ctrl-C!")
|
529 | 552 | try:
|
530 | 553 | dispatch_dnsmasq(dnsmasq, options, ssh_key, random_hostname)
|
|
0 commit comments