diff --git a/README.md b/README.md index 803d914f..fc4bd9ab 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ data has been migrated. - The machine must be reachable over the public internet or local network. Nixos-anywhere does not support wifi networks. If a VPN is needed, define a custom installer via the --kexec flag which connects to your VPN. - - Must have at least 1.5 GB of RAM, excluding swap. + - (when `kexec` is used) must have at least 1.5 GB of RAM, excluding swap. ## How to use nixos-anywhere diff --git a/docs/cli.md b/docs/cli.md index aa07efa4..5fa38353 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -9,7 +9,7 @@ Options: set the flake to install the system from * -s, --store-paths set the store paths to the disko-script and nixos-system directly - if this is give, flake is not needed + if this is given, flake is not needed * --kexec url use another kexec tarball to bootstrap NixOS * --debug diff --git a/docs/howtos/no-os.md b/docs/howtos/no-os.md index dec5e521..28095901 100644 --- a/docs/howtos/no-os.md +++ b/docs/howtos/no-os.md @@ -11,7 +11,7 @@ has detailed instructions on how to boot the installer. When you run `nixos-anywhere`, it will determine whether a NixOS installer is present by checking whether the `/etc/os-release` file contains the identifier -`VARIANT=installer`. This identifier is available on releases NixOS 23.05 or +`VARIANT_ID=installer`. This identifier is available on releases NixOS 23.05 or later. If an installer is detected, `nixos-anywhere` will not attempt to `kexec` into diff --git a/docs/howtos/use-without-flakes.md b/docs/howtos/use-without-flakes.md index c0097c5a..e3cca750 100644 --- a/docs/howtos/use-without-flakes.md +++ b/docs/howtos/use-without-flakes.md @@ -13,37 +13,37 @@ Before you can use `nixos-anywhere` without flakes, you'll need to manually generate the paths for the NixOS system toplevel and disk image. The paths are generated using `nix-build` and are necessary for executing `nixos-anywhere`. -### Generating NixOS System Toplevel: +### Generating Disk Image without Dependencies: -Execute the following command to generate the store path for the NixOS system -toplevel: +To generate the disk image without dependencies, execute: ```bash -nix-build -I nixos-config=/etc/nixos/configuration.nix -E '(import {}).config.system.build.toplevel' +nix-build -I nixos-config=/etc/nixos/configuration.nix -E '(import {}).config.system.build.diskoNoDeps' ``` -This will output a path in `/nix/store` that corresponds to the system toplevel, -which includes all the software and configurations for the system. Make note of -this path for later use. +This will output a script path in `/nix/store` that will format your disk. Make +note of this path for later use. -### Generating Disk Image without Dependencies: +### Generating NixOS System Toplevel: -To generate the disk image without dependencies, execute: +Execute the following command to generate the store path for the NixOS system +toplevel: ```bash -nix-build -I nixos-config=/etc/nixos/configuration.nix -E '(import {}).config.system.build.diskoNoDeps' +nix-build -I nixos-config=/etc/nixos/configuration.nix -E '(import {}).config.system.build.toplevel' ``` -This will also output a script path in `/nix/store` that will format your disk. -Keep this path handy as well. +This will output a path in `/nix/store` that corresponds to the system toplevel, +which includes all the software and configurations for the system. Keep this +path handy as well. ## Running NixOS-Anywhere With both paths in hand, you can execute `nixos-anywhere` as follows: ```bash -nixos-anywhere --store-paths /nix/store/[your-toplevel-path] /nix/store/[your-disk-image-path] +nixos-anywhere --store-paths /nix/store/[your-disk-image-path] /nix/store/[your-toplevel-path] ``` -Replace `[your-toplevel-path]` and `[your-disk-image-path]` with the +Replace `[your-disk-image-path]` and `[your-toplevel-path]` with the corresponding store paths you generated earlier. diff --git a/src/default.nix b/src/default.nix index cd503602..dd7a9bc6 100644 --- a/src/default.nix +++ b/src/default.nix @@ -1,7 +1,6 @@ { stdenv , openssh , gitMinimal -, rsync , nixVersions , nix , coreutils @@ -28,12 +27,11 @@ let findutils gnused # needed by ssh-copy-id sshpass # used to provide password for ssh-copy-id - rsync # used to upload extra-files ]; in stdenv.mkDerivation { pname = "nixos-anywhere"; - version = "1.0.0"; + version = "1.2.0"; src = ./..; nativeBuildInputs = [ makeWrapper ]; installPhase = '' @@ -41,8 +39,6 @@ stdenv.mkDerivation { # We prefer the system's openssh over our own, since it might come with features not present in ours: # https://github.com/nix-community/nixos-anywhere/issues/62 - # - # We also prefer system rsync to prevent crashes between rsync and ssh. makeShellWrapper $out/libexec/nixos-anywhere/nixos-anywhere.sh $out/bin/nixos-anywhere \ --prefix PATH : ${lib.makeBinPath runtimeDeps} --suffix PATH : ${lib.makeBinPath [ openssh ]} ''; diff --git a/src/get-facts.sh b/src/get-facts.sh index e23bb433..cc79f694 100755 --- a/src/get-facts.sh +++ b/src/get-facts.sh @@ -11,7 +11,7 @@ is_kexec=$(if test -f /etc/is_kexec; then echo "y"; else echo "n"; fi) is_nixos=$is_nixos is_installer=$(if [ "$is_nixos" = "y" ] && grep -q VARIANT_ID=installer /etc/os-release; then echo "y"; else echo "n"; fi) is_container=$(if [ "$(has systemd-detect-virt)" = "y" ]; then systemd-detect-virt --container; else echo "none"; fi) -has_ipv6_only=$(if [[ "$(has ip)" == "n" ]] || ip r g 1 >/dev/null 2>/dev/null || ! ip -6 r g :: >/dev/null 2>/dev/null; then echo "n"; else echo "y"; fi) +has_ipv6_only=$(if [ "$(has ip)" = "n" ] || ip r g 1 >/dev/null 2>/dev/null || ! ip -6 r g :: >/dev/null 2>/dev/null; then echo "n"; else echo "y"; fi) has_tar=$(has tar) has_sudo=$(has sudo) has_doas=$(has doas) diff --git a/src/nixos-anywhere.sh b/src/nixos-anywhere.sh index adb04ae2..fce186ac 100755 --- a/src/nixos-anywhere.sh +++ b/src/nixos-anywhere.sh @@ -33,8 +33,9 @@ Options: copy over existing /etc/ssh/ssh_host_* host keys to the installation * --stop-after-disko exit after disko formatting, you can then proceed to install manually or some other way -* --extra-files - files to copy into the new nixos installation +* --extra-files + path to a directory to copy into the root of the new nixos installation. + Copied files will be owned by root. * --disk-encryption-keys copy the contents of the file or pipe in local_path to remote_path in the installer environment, after kexec but before installation. Can be repeated. @@ -419,7 +420,8 @@ fi # Installation will fail if non-root user is used for installer. # Switch to root user by copying authorized_keys. if [[ ${is_installer-n} == "y" ]] && [[ ${ssh_user} != "root" ]]; then - ssh_ "${maybe_sudo} mkdir -p /root/.ssh; ${maybe_sudo} cp ~/.ssh/authorized_keys /root/.ssh" + # Allow copy to fail if authorized_keys does not exist, like if using /etc/ssh/authorized_keys.d/ + ssh_ "${maybe_sudo} mkdir -p /root/.ssh; ${maybe_sudo} cp ~/.ssh/authorized_keys /root/.ssh || true" ssh_connection="root@${ssh_host}" fi @@ -474,15 +476,9 @@ elif [[ ${build_on_remote-n} == "y" ]]; then fi if [[ -n ${extra_files-} ]]; then - if [[ -d $extra_files ]]; then - extra_files="$extra_files/" - fi step Copying extra files - rsync -rlpv -FF \ - -e "ssh -i \"$ssh_key_dir\"/nixos-anywhere -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${ssh_args[*]}" \ - "$extra_files" \ - "${ssh_connection}:/mnt/" - ssh_ "chmod 755 /mnt" # rsync also changes permissions of /mnt + tar -C "$extra_files" -cpf- . | ssh_ "${maybe_sudo} tar -C /mnt -xf- --no-same-owner" + ssh_ "chmod 755 /mnt" # tar also changes permissions of /mnt fi step Installing NixOS diff --git a/terraform/all-in-one.md b/terraform/all-in-one.md index c40e6143..2ed356ff 100644 --- a/terraform/all-in-one.md +++ b/terraform/all-in-one.md @@ -48,7 +48,7 @@ mkdir -p etc/ssh var/lib/secrets SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" umask 0177 -sops --extract '["initrd_ssh_key"]' -d "$SCRIPT_DIR/secrets.yaml" >./var/lib/secrets/initrd_ssh_key +sops --extract '["initrd_ssh_key"]' --decrypt "$SCRIPT_DIR/secrets.yaml" >./var/lib/secrets/initrd_ssh_key # restore umask umask 0022 @@ -59,7 +59,7 @@ for keyname in ssh_host_rsa_key ssh_host_rsa_key.pub ssh_host_ed25519_key ssh_ho else umask 0177 fi - sops --extract '["'$keyname'"]' -d "$SCRIPT_DIR/secrets.yaml" >"./etc/ssh/$keyname" + sops --extract '["'$keyname'"]' --decrypt "$SCRIPT_DIR/secrets.yaml" >"./etc/ssh/$keyname" done ``` @@ -72,7 +72,7 @@ set -euo pipefail SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" cd "$SCRIPT_DIR" -sops --extract '["zfs-key"]' -d "$SCRIPT_DIR/secrets.yaml" >"./etc/ssh/$keyname" +sops --extract '["zfs-key"]' --decrypt "$SCRIPT_DIR/secrets.yaml" ``` ## See also @@ -111,12 +111,13 @@ No resources. | [deployment\_ssh\_key](#input_deployment_ssh_key) | Content of private key used to deploy to the target\_host after initial installation. To ensure maximum security, it is advisable to connect to your host using ssh-agent instead of relying on this variable | `string` | `null` | no | | [disk\_encryption\_key\_scripts](#input_disk_encryption_key_scripts) | Each of these script files will be executed locally and the output of each of them will be made present at the given path to disko during installation. The keys will be not copied to the final system |
list(object({
path = string
script = string
}))
| `[]` | no | | [extra\_environment](#input_extra_environment) | Extra environment variables to be set during installation. This can be usefull to set extra variables for the extra\_files\_script or disk\_encryption\_key\_scripts | `map(string)` | `{}` | no | -| [extra\_files\_script](#input_extra_files_script) | A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is rsynced to the target host during installation to the / directory. | `string` | `null` | no | +| [extra\_files\_script](#input_extra_files_script) | A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is copied to the target host during installation to the / directory. | `string` | `null` | no | | [file](#input_file) | Nix file containing the nixos\_system\_attr and nixos\_partitioner\_attr. Use this if you are not using flake | `string` | `null` | no | | [install\_ssh\_key](#input_install_ssh_key) | Content of private key used to connect to the target\_host during initial installation | `string` | `null` | no | | [install\_user](#input_install_user) | SSH user used to connect to the target\_host, before installing NixOS. If null than the value of `target_host` is used | `string` | `null` | no | | [instance\_id](#input_instance_id) | The instance id of the target\_host, used to track when to reinstall the machine | `string` | `null` | no | | [kexec\_tarball\_url](#input_kexec_tarball_url) | NixOS kexec installer tarball url | `string` | `null` | no | +| [nix\_options](#input_nix_options) | the options of nix | `map(string)` | `null` | no | | [nixos\_partitioner\_attr](#input_nixos_partitioner_attr) | Nixos partitioner and mount script i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.diskoNoDeps or just your-evaluated.config.system.build.diskNoDeps. `config.system.build.diskNoDeps` is provided by the disko nixos module | `string` | n/a | yes | | [nixos\_system\_attr](#input_nixos_system_attr) | The nixos system to deploy i.e. your-flake#nixosConfigurations.your-evaluated-nixos.config.system.build.toplevel or just your-evaluated-nixos.config.system.build.toplevel if you are not using flakes | `string` | n/a | yes | | [no\_reboot](#input_no_reboot) | Do not reboot after installation | `bool` | `false` | no | @@ -127,8 +128,8 @@ No resources. ## Outputs -| Name | Description | -| ----------------------------------------------------- | ---------------------------------------------------------- | -| [result](#output_result) | The resulting store path from building `nixos_system_attr` | +| Name | Description | +| ----------------------------------------------------- | ----------- | +| [result](#output_result) | n/a | diff --git a/terraform/all-in-one/variables.tf b/terraform/all-in-one/variables.tf index 272801bf..d9575c4b 100644 --- a/terraform/all-in-one/variables.tf +++ b/terraform/all-in-one/variables.tf @@ -77,7 +77,7 @@ variable "stop_after_disko" { variable "extra_files_script" { type = string - description = "A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is rsynced to the target host during installation to the / directory." + description = "A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is copied to the target host during installation to the / directory." default = null } diff --git a/terraform/install.md b/terraform/install.md index 7b81824d..218ad275 100644 --- a/terraform/install.md +++ b/terraform/install.md @@ -51,7 +51,7 @@ No requirements. ## Modules -No modules..../joerg/.data/nvim/lazy/ +No modules. ## Resources @@ -61,22 +61,24 @@ No modules..../joerg/.data/nvim/lazy/ ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | -------- | :------: | -| [debug\_logging](#input_debug_logging) | Enable debug logging | `bool` | `false` | no | -| [disk\_encryption\_key\_scripts](#input_disk_encryption_key_scripts) | Each of these script files will be executed locally and the output of each of them will be made present at the given path to disko during installation. The keys will be not copied to the final system |
list(object({
path = string
script = string
}))
| `[]` | no | -| [extra\_environment](#input_extra_environment) | Extra environment variables to be set during installation. This can be usefull to set extra variables for the extra\_files\_script or disk\_encryption\_key\_scripts | `map(string)` | `{}` | no | -| [extra\_files\_script](#input_extra_files_script) | A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is rsynced to the target host during installation to the / directory. | `string` | `null` | no | -| [instance\_id](#input_instance_id) | The instance id of the target\_host, used to track when to reinstall the machine | `string` | `null` | no | -| [kexec\_tarball\_url](#input_kexec_tarball_url) | NixOS kexec installer tarball url | `string` | `null` | no | -| [nixos\_partitioner](#input_nixos_partitioner) | nixos partitioner and mount script | `string` | n/a | yes | -| [nixos\_system](#input_nixos_system) | The nixos system to deploy | `string` | n/a | yes | -| [no\_reboot](#input_no_reboot) | Do not reboot the machine after installation | `bool` | `false` | no | -| [ssh\_private\_key](#input_ssh_private_key) | Content of private key used to connect to the target\_host | `string` | `""` | no | -| [stop\_after\_disko](#input_stop_after_disko) | Exit after disko formatting | `bool` | `false` | no | -| [target\_host](#input_target_host) | DNS host to deploy to | `string` | n/a | yes | -| [target\_port](#input_target_port) | SSH port used to connect to the target\_host | `number` | `22` | no | -| [target\_user](#input_target_user) | SSH user used to connect to the target\_host | `string` | `"root"` | no | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------- | :------: | +| [build\_on\_remote](#input_build_on_remote) | Build the closure on the remote machine instead of building it locally and copying it over | `bool` | `false` | no | +| [debug\_logging](#input_debug_logging) | Enable debug logging | `bool` | `false` | no | +| [disk\_encryption\_key\_scripts](#input_disk_encryption_key_scripts) | Each of these script files will be executed locally and the output of each of them will be made present at the given path to disko during installation. The keys will be not copied to the final system |
list(object({
path = string
script = string
}))
| `[]` | no | +| [extra\_environment](#input_extra_environment) | Extra environment variables to be set during installation. This can be usefull to set extra variables for the extra\_files\_script or disk\_encryption\_key\_scripts | `map(string)` | `{}` | no | +| [extra\_files\_script](#input_extra_files_script) | A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is copied to the target host during installation to the / directory. | `string` | `null` | no | +| [flake](#input_flake) | The flake to install the system from | `string` | `""` | no | +| [instance\_id](#input_instance_id) | The instance id of the target\_host, used to track when to reinstall the machine | `string` | `null` | no | +| [kexec\_tarball\_url](#input_kexec_tarball_url) | NixOS kexec installer tarball url | `string` | `null` | no | +| [nixos\_partitioner](#input_nixos_partitioner) | nixos partitioner and mount script | `string` | `""` | no | +| [nixos\_system](#input_nixos_system) | The nixos system to deploy | `string` | `""` | no | +| [no\_reboot](#input_no_reboot) | Do not reboot the machine after installation | `bool` | `false` | no | +| [ssh\_private\_key](#input_ssh_private_key) | Content of private key used to connect to the target\_host | `string` | `""` | no | +| [stop\_after\_disko](#input_stop_after_disko) | Exit after disko formatting | `bool` | `false` | no | +| [target\_host](#input_target_host) | DNS host to deploy to | `string` | n/a | yes | +| [target\_port](#input_target_port) | SSH port used to connect to the target\_host | `number` | `22` | no | +| [target\_user](#input_target_user) | SSH user used to connect to the target\_host | `string` | `"root"` | no | ## Outputs diff --git a/terraform/install/variables.tf b/terraform/install/variables.tf index 60bd9cdf..c91243b1 100644 --- a/terraform/install/variables.tf +++ b/terraform/install/variables.tf @@ -61,7 +61,7 @@ variable "stop_after_disko" { variable "extra_files_script" { type = string - description = "A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is rsynced to the target host during installation to the / directory." + description = "A script file that prepares extra files to be copied to the target host during installation. The script expected to write all its files to the current directory. This directory is copied to the target host during installation to the / directory." default = null } diff --git a/terraform/nix-build.md b/terraform/nix-build.md index 932b8fde..68eb23c6 100644 --- a/terraform/nix-build.md +++ b/terraform/nix-build.md @@ -7,6 +7,8 @@ file. - See [install](install.md) or [nixos-rebuild](nixos-rebuild.md) + + ## Requirements No requirements. @@ -29,10 +31,11 @@ No modules. ## Inputs -| Name | Description | Type | Default | Required | -| ------------------------------------------------------------ | -------------------------------------------------- | -------- | ------- | :------: | -| [attribute](#input_attribute) | the attribute to build, can also be a flake | `string` | n/a | yes | -| [file](#input_file) | the nix file to evaluate, if not run in flake mode | `string` | `null` | no | +| Name | Description | Type | Default | Required | +| ------------------------------------------------------------------- | -------------------------------------------------- | ------------- | ------- | :------: | +| [attribute](#input_attribute) | the attribute to build, can also be a flake | `string` | n/a | yes | +| [file](#input_file) | the nix file to evaluate, if not run in flake mode | `string` | `null` | no | +| [nix\_options](#input_nix_options) | the options of nix | `map(string)` | `null` | no | ## Outputs