mirror of
https://github.com/nix-community/nixos-anywhere.git
synced 2024-09-17 11:27:32 +03:00
242 lines
8.5 KiB
Markdown
242 lines
8.5 KiB
Markdown
# How To Guide: nixos-anywhere
|
|
|
|
**_Install NixOS everywhere via ssh_**
|
|
|
|
<img title="" src="https://raw.githubusercontent.com/numtide/nixos-anywhere/main/docs/logo.png" alt="" width="129">
|
|
|
|
[Documentation Index](./INDEX.md)
|
|
|
|
## Contents
|
|
|
|
[Installing on a machine with no operating system](#installing-on-a-machine-with-no-operating-system)
|
|
|
|
[Using your own kexec image](#using-your-own-kexec-image)
|
|
|
|
[Secrets and full disk encryption](#secrets-and-full-disk-encryption)
|
|
|
|
[Use without flakes](#use-without-flakes)
|
|
|
|
## Installing on a machine with no operating system
|
|
|
|
If your machine doesn't currently have an operating system installed, you can
|
|
still run `nixos-anywhere` remotely to automate the install. To do this, you
|
|
would first need to boot the target machine from the standard NixOS installer.
|
|
You can either boot from a USB or use `netboot`.
|
|
|
|
The
|
|
[NixOS installation guide](https://nixos.org/manual/nixos/stable/index.html#sec-booting-from-usb)
|
|
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
|
|
later.
|
|
|
|
If an installer is detected, `nixos-anywhere` will not attempt to `kexec` into
|
|
its own image. This is particularly useful for targets that don't have enough
|
|
RAM for `kexec` or don't support `kexec`.
|
|
|
|
NixOS starts an SSH server on the installer by default, but you need to set a
|
|
password in order to access it. To set a password for the `nixos` user, run the
|
|
following command in a terminal on the NixOS machine:
|
|
|
|
```
|
|
passwd
|
|
```
|
|
|
|
If you don't know the IP address of the installer on your network, you can find
|
|
it by running the following command:
|
|
|
|
```
|
|
$ ip addr
|
|
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
|
|
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
|
|
inet 127.0.0.1/8 scope host lo
|
|
valid_lft forever preferred_lft forever
|
|
inet6 ::1/128 scope host
|
|
valid_lft forever preferred_lft forever
|
|
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
|
|
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
|
|
altname enp0s3
|
|
altname ens3
|
|
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic noprefixroute eth0
|
|
valid_lft 86385sec preferred_lft 75585sec
|
|
inet6 fec0::5054:ff:fe12:3456/64 scope site dynamic mngtmpaddr noprefixroute
|
|
valid_lft 86385sec preferred_lft 14385sec
|
|
inet6 fe80::5054:ff:fe12:3456/64 scope link
|
|
valid_lft forever preferred_lft forever
|
|
```
|
|
|
|
This will display the IP addresses assigned to your network interface(s),
|
|
including the IP address of the installer. In the example output below, the
|
|
installer's IP addresses are `10.0.2.15`, `fec0::5054:ff:fe12:3456`, and
|
|
`fe80::5054:ff:fe12:3456%eth0`:
|
|
|
|
To test if you can connect and your password works, you can use the following
|
|
SSH command (replace the IP address with your own):
|
|
|
|
```
|
|
ssh -v nixos@fec0::5054:ff:fe12:3456
|
|
```
|
|
|
|
You can then use the IP address to run `nixos-anywhere` like this:
|
|
|
|
```
|
|
nix run github:numtide/nixos-anywhere -- --flake '.#myconfig' nixos@fec0::5054:ff:fe12:3456
|
|
```
|
|
|
|
This example assumes a flake in the curent directory containing a configuration
|
|
named `myconfig`.
|
|
|
|
## Using your own kexec image
|
|
|
|
By default, `nixos-anywhere` downloads the kexec image from the
|
|
[NixOS images repository](https://github.com/nix-community/nixos-images#kexec-tarballs).
|
|
|
|
However, you can provide your own `kexec` image file if you need to use a
|
|
different one. This is particularly useful for architectures other than `x86_64`
|
|
and `aarch64`, since they don't have a pre-build image.
|
|
|
|
To do this, use the `--kexec` command line switch followed by the path to your
|
|
image file. The image will be uploaded prior to execution.
|
|
|
|
Here's an example command that demonstrates how to use a custom kexec image with
|
|
`nixos-anywhere`:
|
|
|
|
```
|
|
nix run github:numtide/nixos-anywhere -- \
|
|
--kexec "$(nix build --print-out-paths github:nix-community/nixos-images#packages.aarch64-linux.kexec-installer-nixos-unstable-noninteractive)/nixos-kexec-installer-noninteractive-aarch64-linux.tar.gz" \
|
|
--flake 'github:your-user/your-repo#your-system' \
|
|
root@yourip
|
|
```
|
|
|
|
Make sure to replace `github:your-user/your-repo#your-system` with the
|
|
appropriate Flake URL representing your NixOS configuration.
|
|
|
|
The example above assumes that your local machine can build for aarch64 in one
|
|
of the following ways:
|
|
|
|
- Natively
|
|
|
|
- Through a remote builder
|
|
|
|
- By emulating the architecture with qemu using the following NixOS
|
|
configuration:
|
|
|
|
```nix
|
|
{
|
|
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
|
}
|
|
```
|
|
|
|
## Secrets and full disk encryption
|
|
|
|
The `nixos-anywhere` utility offers the capability to install secrets onto a
|
|
target machine. This feature is particularly beneficial when you want to
|
|
bootstrap secrets management tools such as
|
|
[sops-nix](https://github.com/Mic92/sops-nix) or
|
|
[agenix](https://github.com/ryantm/agenix), which rely on machine-specific
|
|
secrets to decrypt other uploaded secrets.
|
|
|
|
### Example: Decrypting an OpenSSH Host Key with pass
|
|
|
|
In this example, we demonstrate how to use a script to decrypt an OpenSSH host
|
|
key from the `pass` password manager and subsequently pass it to
|
|
`nixos-anywhere` during the installation process:
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
|
|
# Create a temporary directory
|
|
temp=$(mktemp -d)
|
|
|
|
# Function to cleanup temporary directory on exit
|
|
cleanup() {
|
|
rm -rf "$temp"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Create the directory where sshd expects to find the host keys
|
|
install -d -m755 "$temp/etc/ssh"
|
|
|
|
# Decrypt your private key from the password store and copy it to the temporary directory
|
|
pass ssh_host_ed25519_key > "$temp/etc/ssh/ssh_host_ed25519_key"
|
|
|
|
# Set the correct permissions so sshd will accept the key
|
|
chmod 600 "$temp/etc/ssh/ssh_host_ed25519_key"
|
|
|
|
# Install NixOS to the host system with our secrets
|
|
nixos-anywhere --extra-files "$temp" --flake '.#your-host' root@yourip
|
|
```
|
|
|
|
### Example: Uploading Disk Encryption Secrets
|
|
|
|
In a similar vein, `nixos-anywhere` can upload disk encryption secrets, which
|
|
are necessary during formatting with disko. Here's an example that demonstrates
|
|
how to provide your disk encryption password as a file or via the `pass` utility
|
|
to `nixos-anywhere`:
|
|
|
|
```bash
|
|
# Write your disk encryption password to a file
|
|
echo "my-super-safe-password" > /tmp/disk-1.key
|
|
|
|
# Call nixos-anywhere with disk encryption keys
|
|
nixos-anywhere \
|
|
--disk-encryption-keys /tmp/disk-1.key /tmp/disk-1.key \
|
|
--disk-encryption-keys /tmp/disk-2.key <(pass my-disk-encryption-password) \
|
|
--flake '.#your-host' \
|
|
root@yourip
|
|
```
|
|
|
|
In the above example, replace `"my-super-safe-password"` with your actual
|
|
encryption password, and `my-disk-encryption-password` with the relevant entry
|
|
in your pass password store. Also, ensure to replace `'.#your-host'` and
|
|
`root@yourip` with your actual flake and IP address, respectively.
|
|
|
|
## Use without flakes
|
|
|
|
While `nixos-anywhere` is designed to work optimally with Nix Flakes, it also
|
|
supports the traditional approach without flakes. This document outlines how to
|
|
use `nixos-anywhere` without relying on flakes.
|
|
|
|
### Generate Required Store Paths
|
|
|
|
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:
|
|
|
|
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 <nixpkgs/nixos> {}).config.system.build.toplevel'
|
|
```
|
|
|
|
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.
|
|
|
|
#### Generating Disk Image without Dependencies:
|
|
|
|
To generate the disk image without dependencies, execute:
|
|
|
|
```bash
|
|
nix-build -I nixos-config=/etc/nixos/configuration.nix -E '(import <nixpkgs/nixos> {}).config.system.build.diskNoDeps'
|
|
```
|
|
|
|
This will also output a script path in `/nix/store` that will format your disk.
|
|
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]
|
|
```
|
|
|
|
Replace `[your-toplevel-path]` and `[your-disk-image-path]` with the
|
|
corresponding store paths you generated earlier.
|