diff --git a/docs/howtos/extra-files.md b/docs/howtos/extra-files.md index 9b3819da..8bae5aa9 100644 --- a/docs/howtos/extra-files.md +++ b/docs/howtos/extra-files.md @@ -75,6 +75,14 @@ during installation. When the files are extracted on the remote the copied data will be owned by root. +If you wish to change the ownership after the files are copied onto the system, +you can use the `--chown` option. + +For example, if you did `--chown /home/myuser/.ssh 1000:100`, this would equate +to running `chown -R /home/myuser/.ssh 1000:100` where the uid is 1000 and the +gid is 100. **Only do this when you can _guarantee_ what the uid and gid will +be.** + ### Symbolic Links Do not create symbolic links to reference data to copy. diff --git a/docs/reference.md b/docs/reference.md index b6c0c620..844d3abe 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -49,7 +49,10 @@ Options: copy over existing /etc/ssh/ssh_host_* host keys to the installation * --extra-files contents of local are recursively copied to the root (/) of the new NixOS installation. Existing files are overwritten - Copied files will be owned by root. See documentation for details. + Copied files will be owned by root unless specified by --chown option. See documentation for details. +* --chown + change ownership of recursively. Recommended to use uid:gid as opposed to username:groupname for ownership. + Option can be specified more than once. * --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. diff --git a/src/nixos-anywhere.sh b/src/nixos-anywhere.sh index fed359fa..7dd7b52c 100755 --- a/src/nixos-anywhere.sh +++ b/src/nixos-anywhere.sh @@ -58,6 +58,7 @@ trap 'rm -rf "$sshKeyDir"' EXIT mkdir -p "$sshKeyDir" declare -A diskEncryptionKeys=() +declare -A extraFilesOwnership=() declare -a nixCopyOptions=() declare -a sshArgs=() @@ -98,7 +99,10 @@ Options: copy over existing /etc/ssh/ssh_host_* host keys to the installation * --extra-files contents of local are recursively copied to the root (/) of the new NixOS installation. Existing files are overwritten - Copied files will be owned by root. See documentation for details. + Copied files will be owned by root unless specified by --chown option. See documentation for details. +* --chown + change ownership of recursively. Recommended to use uid:gid as opposed to username:groupname for ownership. + Option can be specified more than once. * --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. @@ -233,6 +237,11 @@ parseArgs() { extraFiles=$2 shift ;; + --chown) + extraFilesOwnership["$2"]="$3" + shift + shift + ;; --disk-encryption-keys) diskEncryptionKeys["$2"]="$3" shift @@ -590,6 +599,9 @@ nixosInstall() { if [[ -n ${extraFiles} ]]; then step Copying extra files tar -C "$extraFiles" -cpf- . | runSsh "tar -C /mnt -xf- --no-same-owner" + # shellcheck disable=SC2016 + printf "%s\n" "${!extraFilesOwnership[@]}" "${extraFilesOwnership[@]}" | pr -2t | runSsh 'while read file ownership; do chown -R "$ownership" "/mnt/$file"; done' + runSsh "chmod 755 /mnt" # tar also changes permissions of /mnt fi diff --git a/tests/from-nixos.nix b/tests/from-nixos.nix index 05f1f686..875a092d 100644 --- a/tests/from-nixos.nix +++ b/tests/from-nixos.nix @@ -34,6 +34,10 @@ start_all() installer.succeed("mkdir -p /tmp/extra-files/var/lib/secrets") installer.succeed("echo value > /tmp/extra-files/var/lib/secrets/key") + installer.succeed("mkdir -p /tmp/extra-files/home/user/.ssh") + installer.succeed("echo secretkey > /tmp/extra-files/home/user/.ssh/id_ed25519") + installer.succeed("echo publickey > /tmp/extra-files/home/user/.ssh/id_ed25519.pub") + installer.succeed("chmod 600 /tmp/extra-files/home/user/.ssh/id_ed25519") ssh_key_path = "/etc/ssh/ssh_host_ed25519_key.pub" ssh_key_output = installer.wait_until_succeeds(f""" ssh -i /root/.ssh/install_key -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \ @@ -46,6 +50,7 @@ --kexec /etc/nixos-anywhere/kexec-installer \ --extra-files /tmp/extra-files \ --store-paths /etc/nixos-anywhere/disko /etc/nixos-anywhere/system-to-install \ + --chown /home/user 1000:100 \ --copy-host-keys \ root@installed >&2 """) @@ -62,6 +67,10 @@ assert "value" == content, f"secret does not have expected value: {content}" ssh_key_content = new_machine.succeed(f"cat {ssh_key_path}").strip() assert ssh_key_content in ssh_key_output, "SSH host identity changed" + priv_key_perms = new_machine.succeed("stat -c %a /home/user/.ssh/").strip() + assert priv_key_perms == "600", f"unexpected permissions for private key: {priv_key_perms}" + user_dir_ownership = new_machine.succeed("stat -c %u:%g /home/user").strip() + assert user_dir_ownership == "1000:100", f"unexpected user home dir permissions: {user_dir_ownership}" ''; } )