diff --git a/docs/nix/README.md b/docs/nix/README.md new file mode 100644 index 0000000..740f72d --- /dev/null +++ b/docs/nix/README.md @@ -0,0 +1,9 @@ +# Nix Package Manager + +[Nix](https://nixos.org/nix/) is a package manager that manages software and their dependencies independently from the underlying OS. With Nix, all software and their dependencies are contained in a single dedicated file system location. This makes Nix a good fit when hacking M2, which ships with only minimal command-line tools available by default. + +With Nix installed, you may not need to install additional packages into the OS. You also may not need to use `devel-su` or `nerdctl` for most of the command-line tools or libraries you might need. + +* [Installation](install.md) +* [Home Manager](home-manager.md) +* [Tailscale](tailscale.md) diff --git a/docs/nix/home-manager.md b/docs/nix/home-manager.md new file mode 100644 index 0000000..95d111d --- /dev/null +++ b/docs/nix/home-manager.md @@ -0,0 +1,104 @@ +# Manage your environment with Home Manager + +Home Manager is a [Nix](install.md)-powered tool for reproducible management of the contents of users’ home directories. This includes programs, configuration files, environment variables, and systemd user service management. + + +## Prerequisites + +Home Manager is a part of the Nix ecosystem. If you haven't installed Nix yet, follow the [installation guide](install.md) first. + + +## Install Home Manager + +Once you have Nix installed, you can install Home Manager by running the following commands: + +```console +nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager +nix-channel --update +nix-shell '' -A install +``` + + +## First-time activation + +After installation, you should be able to use Home Manager with: + +```console +. $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh +home-manager switch +``` + +Usually Home Manager should be activated automatically when you start a new shell, thanks to `.profile` created during the [Nix installation](install.md). + + +## First-time configuration + +Your Home Manager configuration is managed with updating `/home/defaultuser/.config/home-manager/home.nix` and running `home-manager switch` to apply the changes. + +Home Manager installs with example `home.nix` with a lot of examples. To see the forest for the trees, it might be good to put that aside and start with a minimal configuration with: + +```console +mv /home/defaultuser/.config/home-manager/home.nix /home/defaultuser/.config/home-manager/home.nix.example +``` + +and + +```console +cat << EOF > /home/defaultuser/.config/home-manager/home.nix +{ config, pkgs, lib, ... }: +{ + home.username = "defaultuser"; + home.homeDirectory = "/home/defaultuser"; + home.stateVersion = "24.11"; + home.packages = [ + pkgs.nano + ]; + programs.home-manager.enable = true; + programs.bash.enable = true; + home.file.".profile".source = lib.mkForce (builtins.toFile "profile" '' + if [ -e "$HOME/.nix-profile/etc/profile.d/nix.sh" ]; then + . "$HOME/.nix-profile/etc/profile.d/nix.sh" + exec bash + fi + ''); +} +EOF +``` + +with `home-manager switch -b backup` to apply the changes. + +This configuration installs `nano` as a minimal editor and enables full `bash` and updates `.profile` that activates Nix on every new shell with Home Manager managed version. (The previous version of `.profile` is backed up as `.profile.backup`.) + +After this first-time configuration, you can start adding more packages and configurations to your `home.nix` and using `home-manager switch` to apply the changes. + + +## Manage Nix configuration + +Nix has a few [configuration options](https://nix.dev/manual/nix/2.24/command-ref/conf-file.html?highlight=min-free#available-settings) that can be set in `~/.config/nix/nix.conf`. Home Manager can manage these options with `nix.extraOptions` in `home.nix`. + +You should at least configure automatic garbage collection with `min-free` and `max-free` options. For example: + +```nix + nix.package = pkgs.nix; + nix.extraOptions = '' + min-free = 1G + max-free = 10G + ''; +``` + +Possibly, later you might want to enable experimental features like `nix-command` and `flakes` for [the next-generation Nix command-line interface](https://nix.dev/manual/nix/2.24/command-ref/experimental-commands): + +```nix + nix.package = pkgs.nix; + nix.extraOptions = '' + min-free = 1G + max-free = 10G + experimental-features = nix-command flakes + ''; +``` + + +## Additional resources + +* [Home Manager manual](https://nix-community.github.io/home-manager/index.xhtml) +* [All Home Manager options](https://nix-community.github.io/home-manager/options.xhtml) diff --git a/docs/nix/install.md b/docs/nix/install.md new file mode 100644 index 0000000..8894453 --- /dev/null +++ b/docs/nix/install.md @@ -0,0 +1,150 @@ +# How to install Nix on M2 + +[Nix](https://nixos.org/nix/) has an easy-to-use command line install script, but it relies on the availability of a few specific command line tools (`curl` and `xz`) and the ability to create the `/nix` directory using `sudo`. Therefore, you must take a few extra steps to get started. + + +## State directory + +First, you must create the `/nix` state directory, which will contain everything downloaded and managed by Nix. + +But you don't want to take the chance that `/nix` will ever take all free space from the system partition. That's why you create a directory under the home directory instead. + +```console +mkdir /home/defaultuser/Nix +``` + +and only then go to super user + +```console +devel-su +``` + +and bind mount the directory from the home directory into `/nix`. + +```console +mkdir /nix +mount --bind /home/defaultuser/Nix /nix +``` + +At any point, all the space taken by Nix could be released (uninstalled) by just removing the state directory. + + +## Mount on boot + +While the state directory could be bind mounted manually after every boot, it is possible to configure a systemd job to do it for you. Just enter super user mode: + +```console +devel-su +``` + +and create the systemd unit + +```console +cat << EOF > /etc/systemd/system/bind-mount-nix.service +[Unit] +Description=Bind mount /home/defaultuser/Nix to /nix +After=local-fs.target +Requires=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/mount --bind /home/defaultuser/Nix /nix + +[Install] +WantedBy=multi-user.target +EOF +``` + +and enable it. + +```console +systemctl daemon-reload +systemctl enable bind-mount-nix.service +systemctl start bind-mount-nix.service +``` + +Now `/nix` should be (bind) mounted on every boot. + + +## Bootstrap + +Next, you are able to do the required bootstrapping for the final installation. As a super user + +```console +devel-su +``` + +start a minimal container with `/nix` mounted, install the required dependencies `curl` and `xz`, and run the installer for a single user "rootless" Nix installation: + +```console +nerdctl run --rm -ti -v /nix:/nix debian:stable-slim +apt-get update +apt-get install curl xz-utils +sh <(curl -L https://nixos.org/nix/install) --no-daemon +``` + +This initial installation may report some errors, but don't worry. Since it is being run in a container, it can only write to the mounted `/nix` directory. + +Once you have exited the container, you may remove the image: + +```console +nerdctl rmi debian:stable-slim +``` +and change the ownership of the installed files to `defaultuser`. + +```console +chown -R defaultuser:defaultuser /nix +``` + +Remember to exit the super user mode before continuing with the final installation. The rest of the installation should be done as `defaultuser`. + + +```console +exit +``` + + +## Install + +Now you can finally run the installation as `defaultuser`, and going super user is no longer needed for Nix: + +```console +/nix/store/*-nix-*/bin/nix shell nixpkgs#curl nixpkgs#xz --extra-experimental-features nix-command --extra-experimental-features flakes +sh <(curl -L https://nixos.org/nix/install) --no-daemon +``` + +It's good to know that the installation creates the following symlinks: + +``` console +/home/defaultuser/.nix-channels/ +/home/defaultuser/.nix-defexpr/ +/home/defaultuser/.nix-profile/ +``` + + +## Activate + +Installed Nix must be activated by sourcing its activation script in the shell with + +```console +. "$HOME/.nix-profile/etc/profile.d/nix.sh" +``` + +This can be automated by creating `/home/defaultuser/.profile` (or adding to an existing file) with the activation command: + +```console +cat << EOF > /home/defaultuser/.profile +if [ -e "$HOME/.nix-profile/etc/profile.d/nix.sh" ]; then + . "$HOME/.nix-profile/etc/profile.d/nix.sh" +fi +EOF +``` + +Now Nix should be activated on every new shell on M2. As a safeguard, the activation is skipped if the bind mount of `/nix` fails for any reason. + + +## Additional resources + +* [Nix manual on package management](https://nix.dev/manual/nix/2.24/package-management/) +* [Home Manager for more than just package management](https://nix-community.github.io/home-manager/index.xhtml#sec-install-standalone) \ No newline at end of file diff --git a/docs/nix/tailscale.md b/docs/nix/tailscale.md new file mode 100644 index 0000000..a4ddec4 --- /dev/null +++ b/docs/nix/tailscale.md @@ -0,0 +1,77 @@ +# Activating Tailscale + +[Tailscale](https://tailscale.com/) is a VPN service that allows you to connect to your devices securely. It is a good fit for M2, which is a headless device that you may want to access remotely, and also works when run in user space (as `defaultuser`). + + +## Prerequisites + +Before you start, you need to have Nix installed and Home Manager activated. If you haven't installed Nix yet, follow the [installation guide](install.md) first and activate Home Manager as described in the [Home Manager guide](home-manager.md). + + +## Register machine + +To use Tailscale, you need to register your machine for your Tailnet. + +Because `tailscale` command does not support custom socket path, the registration must be done with the default socket path. + +This means that you enter super user mode + +```console +devel-su +``` + +and create the default socket path before continuing with the registration. + +```console +mkdir -p /var/run/tailscale +chown defaultuser:defaultuser /var/run/tailscale/ +``` + +Then you can return to `defaultuser` mode. + +```console +exit +``` + +Now you may manually start the tailscale daemon with user space networking, but with the default socket path + +```console +nix-shell -p tailscale --run "tailscaled --tun=userspace-networking" +``` + +and then run the registration in another shell + +```console +nix-shell -p tailscale --run "tailscale up" +``` + +and follow the instructions. + +This should already bring your M2 into your Tailnet, until you break the daemon with `Ctrl+C`. + + +## Register service + +To make sure that Tailscale starts automatically when you start your M2, you can create a systemd user service for it in your `home.nix` configuration: + +```nix + systemd.user.services.tailscaled = { + Unit = { + Description = "Tailscale client daemon"; + After = [ "network.target" ]; + }; + Service = { + ExecStart = "${pkgs.tailscale}/bin/tailscaled --tun=userspace-networking --socket ${config.home.homeDirectory}/.local/share/tailscale/tailscaled.sock"; + Restart = "always"; + RestartSec = 5; + }; + Install = { + WantedBy = [ "default.target" ] ; + }; + }; + systemd.user.startServices = true; +``` + +When ready, run `home-manager switch` to apply the changes and `systemctl --user start tailscaled` to start the service for the first time. Later it will be automatically started e.g. after a system reboot. + +This will start the Tailscale daemon with user space networking and the custom socket path when you start your M2.