nix-community / raspberry-pi-nix

NixOS modules to aid in configuring NixOS for raspberry pi products
MIT License
144 stars 34 forks source link

Feature Request: sd image copy headless configuration files #21

Closed adminy closed 2 months ago

adminy commented 3 months ago

When building sd images, it would be great if it can start off with pre-configured .zshrc file and a .config folder in the user directory which configures the vpn so that it can run headless. a setup-files param which populates the root folder from the parameter folder. optional and default nothing to copy is fine.

tshakah commented 3 months ago

I use home manager (you can see a stub config here: https://github.com/tstat/raspberry-pi-nix/issues/18#issuecomment-2160761864), which can provide user dotfiles

adminy commented 3 months ago

I hear that home manager creates read-only files though. I prefer to avoid that in the home directory.

Also how does it specify location of files in home manager?

tshakah commented 3 months ago

I am not at my computer at the moment, tomorrow I can dig out an example of how to get writable dotfiles with home manager

tshakah commented 3 months ago

My dotfiles are in a separate repo, and I then use a module like this to symlink them to the correct places with home manager:

{ config, ... }:
let
  symlink = config.lib.file.mkOutOfStoreSymlink;
  dotfiles = "${config.home.homeDirectory}/source/dotfiles";
  paths =
    if builtins.pathExists dotfiles then
      {
        ".Xdefaults".source = symlink "${dotfiles}/xorg/Xdefaults";
        ".Xresources".source = symlink "${dotfiles}/xorg/Xresources";
      }
    else { };
in
{
  home.file = paths;
}

If you don't want to manage a separate repo, then there's at least two more ways:

Activation script

If you pass the flake src as self in flake.nix:

      nixosConfigurations.[YOUR NAME] = nixpkgs.lib.nixosSystem {
        specialArgs = { inherit self; };

Then you can access files in the flake's repository as part of the activation script:

{ self, ... }:

{
  system.activationScripts = { [YOUR NAME].text =
    ''
      cp --no-clobber ${self}/some-file /home/youruser/some-file
      chown youruser:users /home/youruser/some-file
    '';
  };

Populate root commands

If you need the files sooner than that, you can repeat the self as above, but instead of activation scripts you can do:

{ config, self, ... }:

{
  sdImage.populateRootCommands = ''
    mkdir -p ./files/boot
    ${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot

    mkdir -p ./files/home/youruser
    cp ${self}/some-file ./files/home/youruser/some-file
  '';
}

This would be a one-time copy of those files, unlike the activation scripts which run every boot or nixos-rebuild. Note that the ./files/ prefix is required in this instance - look at the docs https://github.com/tstat/raspberry-pi-nix/blob/1570501aba3f62d684c68a4523cde8e6437efb00/sd-image/sd-image.nix#L121.

I use a combination of these two approaches (activation scripts and populate root) to set up sops-nix on my pi SD card images, such that they can then automatically connect to tailscale on boot. That seems like a very similar thing to what you want.

I am certain there are other ways to solve this

adminy commented 2 months ago

thanks @tshakah , I need to set up the token secret for rathole (a tailscale alternative). The activation script makes sense for the dotfiles, Sounds like I'll be using a combination of the two also. I didn't know you can overwrite populateRootCommands to do this, thought it was used for something entirely different. thanks.