mirror of
https://github.com/ItsDrike/nixdots
synced 2024-12-26 19:04:33 +00:00
Update installation guide
This commit is contained in:
parent
a6cf555b00
commit
718a55f595
166
INSTALLATION.md
166
INSTALLATION.md
|
@ -62,18 +62,6 @@ btrfs subvolume create /mnt/nix
|
||||||
btrfs subvolume create /mnt/log
|
btrfs subvolume create /mnt/log
|
||||||
btrfs subvolume create /mnt/persist
|
btrfs subvolume create /mnt/persist
|
||||||
btrfs subvolume create /mnt/data
|
btrfs subvolume create /mnt/data
|
||||||
```
|
|
||||||
|
|
||||||
We will now take a read-only snapshot of the root subvolume.
|
|
||||||
This snapshot will be eventually used for rolling back to on every boot (impermanence).
|
|
||||||
|
|
||||||
```shell
|
|
||||||
btrfs subvolume snapshot -r /mnt/root /mnt/root-blank
|
|
||||||
```
|
|
||||||
|
|
||||||
And finally, we can unmount the btrfs root.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
umount /mnt
|
umount /mnt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -226,7 +214,11 @@ fileSystems."/" =
|
||||||
### Subvolumes needed for boot
|
### Subvolumes needed for boot
|
||||||
|
|
||||||
In order to correctly persist `/var/log`, the respective subvolume need to be mounted early enough in
|
In order to correctly persist `/var/log`, the respective subvolume need to be mounted early enough in
|
||||||
the boot process. To do this, we will want to add `neededForBoot = true;`, so the entry will look like this:
|
the boot process. To do this, we will want to add `neededForBoot = true;`. Additionally, we will also
|
||||||
|
need to add this parameter for our `/persisr` subvolume. This is because we will be storing the user
|
||||||
|
password (including root password) in a password file there (mentioned later on).
|
||||||
|
|
||||||
|
So the entries will look like this:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
fileSystems."/var/log" =
|
fileSystems."/var/log" =
|
||||||
|
@ -235,10 +227,14 @@ fileSystems."/var/log" =
|
||||||
options = [ "subvol=log" "noatime" "compress=zstd:3" ];
|
options = [ "subvol=log" "noatime" "compress=zstd:3" ];
|
||||||
neededForBoot = true;
|
neededForBoot = true;
|
||||||
};
|
};
|
||||||
```
|
|
||||||
|
|
||||||
Additionally, we will also need to add `neededForBoot = true;` to our `/persist` subvolume. This is because
|
fileSystems."/persist" =
|
||||||
we will be storing the root users password file in there.
|
{ device = "/dev/disk/by-label/NIXFS";
|
||||||
|
fsType = "btrfs";
|
||||||
|
options = [ "subvol=persist" "noatime" "compress=zstd:3" ];
|
||||||
|
neededForBoot = true;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## Minimal config
|
## Minimal config
|
||||||
|
|
||||||
|
@ -310,12 +306,11 @@ screen. Log in as root, set your password (`passwd itsdrike`), log out and re-lo
|
||||||
|
|
||||||
This is an optional step, if you don't want your root partition to get auto-reset on each boot, you can simply skip this.
|
This is an optional step, if you don't want your root partition to get auto-reset on each boot, you can simply skip this.
|
||||||
|
|
||||||
### Auto-restore root-blank snapshot
|
### Auto-wipe root partition
|
||||||
|
|
||||||
Remember how we create the empty snapshot of our root subvolume? Well now comes the time when we put it to use. We will
|
To reset the root subvolume on every boot, we can simply delete it and create a new one in its place. We will be doing
|
||||||
restore this snapshot from initrd, which runs in a temporary file-system, before our actual file-system is even mounted.
|
this from initrd, which runs in a temporary file-system, before the actual file-system is properly mounted (following
|
||||||
This makes it a perfect place to run a script which will restore our root subvolume to the blank snapshot before each
|
fstab). This makes it a perfect place to run a script, which will wipe the root subvolume before each boot.
|
||||||
boot.
|
|
||||||
|
|
||||||
I will set this up using a systemd-based initrd, because I will need systemd for TPM unlocking later on. If you don't
|
I will set this up using a systemd-based initrd, because I will need systemd for TPM unlocking later on. If you don't
|
||||||
care about that, it is also possible to do this without systemd. You can a guide for such setup
|
care about that, it is also possible to do this without systemd. You can a guide for such setup
|
||||||
|
@ -338,41 +333,37 @@ boot.initrd.systemd = {
|
||||||
unitConfig.DefaultDependencies = "no";
|
unitConfig.DefaultDependencies = "no";
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
script = ''
|
script = ''
|
||||||
mkdir -p /mnt
|
# Mount the BTRFS root to /mnt so we can manipulate btrfs subvolumes
|
||||||
|
mount --mkdir /dev/mapper/cryptfs /mnt
|
||||||
|
|
||||||
# We first mount the btrfs root to /mnt
|
# Simply deleting a subvolume with btrfs subvolume delete will not work,
|
||||||
# so we can manipulate btrfs subvolumes.
|
# if that subvolume contains other btrfs subvolumes. Because of that, we
|
||||||
mount /dev/mapper/cryptfs /mnt
|
# instead use this function to delete subvolumes, whihc will first perform
|
||||||
|
# a recursive deletion of any nested subvolumes.
|
||||||
# While we're tempted to just delete /root and create
|
|
||||||
# a new snapshot from /root-blank, /root is already
|
|
||||||
# populated at this point with a number of subvolumes,
|
|
||||||
# which makes `btrfs subvolume delete` fail.
|
|
||||||
# So, we remove them first.
|
|
||||||
#
|
#
|
||||||
# /root contains subvolumes:
|
# This is necessary, because the root subvolume will actually usually contain
|
||||||
# - /root/var/lib/portables
|
# other subvolumes, even if the user haven't created those explicitly. It seems
|
||||||
# - /root/var/lib/machines
|
# that NixOS creates these automatically. Namely, I observed these in root subvol:
|
||||||
#
|
# - root/srv
|
||||||
# These are probably related to systemd-nspawn, but
|
# - root/var/lib/portables
|
||||||
# since I don't use it, I'm not 100% sure.
|
# - root/var/lib/machines
|
||||||
# Anyhow, deleting these subvolumes hasn't resulted in
|
# - root/var/tmp
|
||||||
# any issues so far, except for fairly benign-looking
|
delete_subvolume_recursively() {
|
||||||
# errors from systemd-tmpfiles.
|
IFS=$'\n'
|
||||||
btrfs subvolume list -o /mnt/root |
|
for x in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
|
||||||
cut -f9 -d' ' |
|
delete_subvolume_recursively "/mnt/$x"
|
||||||
while read subvolume; do
|
done
|
||||||
echo "deleting /$subvolume subvolume..."
|
|
||||||
btrfs subvolume delete "/mnt/$subvolume"
|
|
||||||
done &&
|
|
||||||
echo "deleting /root subvolume..." &&
|
|
||||||
btrfs subvolume delete /mnt/root
|
|
||||||
|
|
||||||
echo "restoring blank /root subvolume..."
|
echo "Deleting subvolume $1"
|
||||||
btrfs subvolume snapshot /mnt/root-blank /mnt/root
|
btrfs subvolume delete "$1"
|
||||||
|
}
|
||||||
|
|
||||||
# Once we're done rolling back to a blank snapshot,
|
# Recreate the root subvolume
|
||||||
# we can unmount /mnt and continue on the boot process.
|
delete_subvolume_recursively "/mnt/root"
|
||||||
|
echo "Re-creating root subvolume"
|
||||||
|
btrfs subvolume create "/mnt/root"
|
||||||
|
|
||||||
|
# we can now unmount /mnt and continue on the boot process.
|
||||||
umount /mnt
|
umount /mnt
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -407,12 +398,6 @@ in
|
||||||
];
|
];
|
||||||
files = [
|
files = [
|
||||||
"/etc/machine-id"
|
"/etc/machine-id"
|
||||||
|
|
||||||
# ssh stuff
|
|
||||||
"/etc/ssh/ssh_host_ed25519_key"
|
|
||||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
|
||||||
"/etc/ssh/ssh_host_rsa_key"
|
|
||||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -422,6 +407,21 @@ in
|
||||||
"L /var/lib/NetworkManager/seen-bssids - - - - /persist/system/var/lib/NetworkManager/seen-bssids"
|
"L /var/lib/NetworkManager/seen-bssids - - - - /persist/system/var/lib/NetworkManager/seen-bssids"
|
||||||
"L /var/lib/NetworkManager/timestamps - - - - /persist/system/var/lib/NetworkManager/timestamps"
|
"L /var/lib/NetworkManager/timestamps - - - - /persist/system/var/lib/NetworkManager/timestamps"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Define host key paths in the persistent mount point instead of using impermanence for these.
|
||||||
|
# This works better, because these keys also get auto-created if they don't already exist.
|
||||||
|
services.openssh.hostKeys = mkForce [
|
||||||
|
{
|
||||||
|
bits = 4096;
|
||||||
|
path = "/persist/system/etc/ssh/ssh_host_rsa_key";
|
||||||
|
type = "rsa";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bits = 4096;
|
||||||
|
path = "/persist/system/etc/ssh/ssh_host_ed25519_key";
|
||||||
|
type = "ed25519";
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -436,23 +436,25 @@ Note that with impermanence, your user passwords will get erased too (with the `
|
||||||
you can create password files, which will contain the password hashes for each user:
|
you can create password files, which will contain the password hashes for each user:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkpasswd -m sha-512 > /persist/system/passwords/root
|
mkdir -p /persist/passwords
|
||||||
mkpasswd -m sha-512 > /persist/system/passwords/itsdrike
|
chmod 700 /persist/passwords
|
||||||
|
mkpasswd -m sha-512 > /persist/passwords/root
|
||||||
|
mkpasswd -m sha-512 > /persist/passwords/itsdrike
|
||||||
|
chmod 600 /persist/passwords/*
|
||||||
```
|
```
|
||||||
|
|
||||||
And declare these in our `configuration.nix` or `impermanence.nix`
|
And declare these in our `configuration.nix` or `impermanence.nix`
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
users = {
|
users = {
|
||||||
# This option makes it that users are not mutable outside our configuration
|
# This option makes it that users are not mutable outside of our configuration.
|
||||||
# If you are using impermanence, this will actually be the case regardless of this setting,
|
# If you're using root impermanence, this will actually be the case regardless
|
||||||
# however, setting this explicitly is a good idea, because nix will warn us if
|
# of this setting, however, setting this explicitly is a good idea, because nix
|
||||||
# our users don't have passwords set
|
# will warn us if our users don't have passwords set, preventing lock outs.
|
||||||
mutableUsers = false;
|
mutableUsers = false;
|
||||||
|
|
||||||
# Each existing user needs to have a password file defined here
|
# Each existing user needs to have a password file defined here, otherwise
|
||||||
# otherwise, they will not be available to login.
|
# they will not be available to login. These password files can be generated with:
|
||||||
# These password files can be generated using the following command:
|
|
||||||
# mkpasswd -m sha-512 > /persist/passwords/myuser
|
# mkpasswd -m sha-512 > /persist/passwords/myuser
|
||||||
users = {
|
users = {
|
||||||
root = {
|
root = {
|
||||||
|
@ -601,7 +603,6 @@ The resulting file should then look something like this:
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
./impermanence.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.supportedFilesystems = [ "btrfs" ];
|
boot.supportedFilesystems = [ "btrfs" ];
|
||||||
|
@ -625,6 +626,21 @@ The resulting file should then look something like this:
|
||||||
system = {
|
system = {
|
||||||
hostname = "anduril";
|
hostname = "anduril";
|
||||||
username = "itsdrike";
|
username = "itsdrike";
|
||||||
|
|
||||||
|
impermanence = {
|
||||||
|
root = {
|
||||||
|
enable = true;
|
||||||
|
# Some people use /nix/persist/system for this, leaving persistent files in /nix subvolume
|
||||||
|
# I much prefer using a standalone subvolume for this though.
|
||||||
|
persistentMountPoint = "/persist";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure automatic root subvolume wiping on boot from initrd
|
||||||
|
autoWipeBtrfs = {
|
||||||
|
enable = true;
|
||||||
|
devices."/dev/disk/by-label/NIXROOT".subvolumes = [ "root" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
device = {
|
device = {
|
||||||
virtual-machine = false;
|
virtual-machine = false;
|
||||||
|
@ -646,12 +662,14 @@ The resulting file should then look something like this:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!WARNING]
|
> [!NOTE]
|
||||||
> I'm currently working on making impermanence config in my flake directly. This will mean you will eventually be
|
> You may notice that this configuration also includes custom options for impermanence,
|
||||||
> expected to just enable impermanence through myOptions. Right now, the config above includes `impermanence.nix`
|
> and that the impermanence.nix is no longer declared in imports. This is because my
|
||||||
> that we have enabled earlier. This will work, however note that flakes are a bit stricter with fetchTarball, and
|
> flake already contains a fully custom support (mostly similar to what I've shown here)
|
||||||
> require a sha256 hash to be specified. You can specify it, or use the `--impure` flag for now. Once impermanence
|
> to handle impermanence. This allows me to re-use this impermanence across multiple
|
||||||
> will be integrated into my flake, it will be handled as an input, and you won't have to worry about anything.
|
> machines very easily.
|
||||||
|
>
|
||||||
|
> You can now therefore delete the `impermanence.nix` file.
|
||||||
|
|
||||||
### Commit and switch
|
### Commit and switch
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue