nix-community / nixos-generators

Collection of image builders [maintainer=@Lassulus]
MIT License
1.88k stars 146 forks source link

/etc/nixos/configuration.nix doesn't exist #193

Open ashraffouda opened 2 years ago

ashraffouda commented 2 years ago

I built a qcow image and now /etc/nixos/configuration.nix doesn't exist doesn't exist any clue how to make it exists by default on the resulting image also executing nix-shell doesn't work

[root@cloud:/etc/nixos]# nix-shell
error: getting status of '/etc/nixos/default.nix': No such file or directory

shouldn't those files shipped by default on the images?

Lassulus commented 2 years ago

nix-shell without arguments needs either a default.nix or a shell.nix file. not sure what that should do here. since the build image is generated out of the source there is no "need" to ship the configuration in the image itself. but you can put it in the image yourself. sometimes system.copySystemConfiguration is enough, but this usually breaks if your configuration consists of multiple files.

ashraffouda commented 2 years ago

and what about /etc/nixos/configuration.nix? I built the image with system.copySystemConfiguration = true; and after I booted the image /etc/nixos/configuration.nix doesn't exist, is it normal? I don't have enough experience about nixos

ashraffouda commented 2 years ago

also what does system.copySystemConfiguration = true; actually do? from where does it copy the files?

Lassulus commented 2 years ago

ah, interesting. I imaged system.copySystemConfiguration = true; working at some point but I haven't tested it in a while.

I guess the best way forward would be to copy the current workingDirectory via nix. Sadly this is quite advanced and not sure if really useful. can't you just rsync/scp the configuration.nix in there or maybe git clone it? What are you trying to do?

ashraffouda commented 2 years ago

I'm just trying to build an image for our cloud infrastructure, now I managed to build it, but not sure if configuration.nix should be there? or the user should add it him self after his machine is deployed

Lassulus commented 2 years ago

also what does system.copySystemConfiguration = true; actually do? from where does it copy the files?

good question, I checked the sourcecode, it just symlinks $NIXOS_CONFIG from $NIX_PATH to system.build.out/configuration.nix. So it's not really useful here

I'm just trying to build an image for our cloud infrastructure, now I managed to build it, but not sure if configuration.nix should be there? or the user should add it him self after his machine is deployed

usually the usecase for this repo is to build a "final" image which is not updated further through itself but instead rebuild. I guess you can do this anyway, but it's not really straight forward right now sadly

JustinLex commented 9 months ago

I was struggling with this myself, as I use nixos-generators to generate fresh boot disks for my nodes, and I want my nodes to be able to autoupdate themselves without me re-flashing their boot disks.

I have now solved this for my needs using flakes. In flake.nix, I have defined both a nixosGenerate as an attr in packages.x86_64-linux and a nixosSystem as an attr in nixosConfigurations. I define both attrs for each node I want to deploy with nixos-generators. I then include this flake in the nix store for use with system.autoUpgrade.

Using this, I can generate a disk image for a flash drive using nix build .#<hostname>, while making sure that nixos-upgrade.service also has access to the flake to be able to generate a new profile for itself after deployment. This automation is super useful for me to ensure that the configuration running on the machine is always in sync with my git repository, even if I leave it running for months without interacting with it; While also still staying up to date with the latest nixos updates.

Here is an example of a nix flake that can do this, with some magic to make it easy to define multiple nodes in the same flake: (my full code is available at https://github.com/JustinLex/jlh-h5b/tree/main/nodes)

# flake.nix
{
  inputs = {
    nixpkgs.url = "nixpkgs/nixos-23.11";
    nixos-generators = {
      url = "github:nix-community/nixos-generators";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };
  outputs = { self, nixpkgs, nixos-generators, ... }:
    let
      nodes = [
      # List hostnames here for configuration
        "my-nix-machine"
      ];
      generator = (
        # Function that templates out a value for the `packages` attrset.
        # Used for defining the NixOS generator for a given node.
        # docs: https://github.com/nix-community/nixos-generators/blob/master/README.md
        nodename:
          nixos-generators.nixosGenerate {
            system = "x86_64-linux";
            format = "raw-efi";
            modules = [
               ./common.nix
#               ./nodes/${nodename}.nix  # Can be used to extend config for each node
            ];
            specialArgs = {
                # additional arguments to pass to modules
                self = self;
                nodeHostName = nodename;
            };
          }
      );
      configuration = (
        # Function that templates out a value for the `nixosConfigurations` attrset.
        # Used for bundling a nixos configuration for the node to be used for autoUpgrades after deployment.
        nodename:
          nixpkgs.lib.nixosSystem {
            system = "x86_64-linux";
            modules = [
               ./raw-efi.nix # Duplicate some bits of config from upstream nixox-generators so that we can use nixos-rebuild
               ./common.nix
#               ./nodes/${nodename}.nix  # Can be used to extend config for each node
            ];
            specialArgs = {
                # additional arguments to pass to modules
                self = self;
                nodeHostName = nodename;
            };
          }
      );
    in {

      # This attrset evaluates to: {"my-nix-machine" = nixos-generators.nixosGenerate {...}; ... }
      packages.x86_64-linux = builtins.listToAttrs (
        map
          ( nodename: { "name" = nodename; "value" = generator(nodename); } )
          ( nodes )  # List of nodes to generate images for
      );

      # This attrset evaluates to: {"my-nix-machine" = nixpkgs.lib.nixosSystem {...}; ... }
      nixosConfigurations = builtins.listToAttrs (
        map
          ( nodename: { "name" = nodename; "value" = configuration(nodename); } )
          ( nodes )  # List of nodes to generate NixOS Configurations for
      );
  };
}
# common.nix
{ config, pkgs, self, nodeHostName, ... }:
{
  networking.hostName = nodeHostName;

  environment.systemPackages = with pkgs; [
    htop
  ];

  # Enable automatic updates
  # https://nixos.wiki/wiki/Automatic_system_upgrades
  system.autoUpgrade = {
    enable = true;
#    dates = "Sun *-*-* 03:00 Europe/Stockholm";
#    randomizedDelaySec = "6hr";
    allowReboot = true;
    flake = "path:${self.outPath}#${nodeHostName}";  # flake path must be preceded with "path:" because otherwise nix build will get confused when we ask to build a flake in the nix store
    flags = [
      "--update-input"
      "nixpkgs"
      "-L" # print build logs
    ];
  };

  system.stateVersion = "23.11";
}
# raw-efi.nix
# Duplicate nixox-generators' config so that we can use nixos-rebuild
# https://github.com/nix-community/nixos-generators/blob/master/formats/raw-efi.nix
# Fixes failed assertions with running nixos-rebuild:
#   - The ‘fileSystems’ option does not specify your root file system.
#   - You must set the option ‘boot.loader.grub.devices’ or 'boot.loader.grub.mirroredBoots' to make the system bootable.
{ config, pkgs, ... }:
{
  fileSystems."/" = {
    device = "/dev/disk/by-label/nixos";
    fsType = "ext4";
  };
  fileSystems."/boot" = {
    device = "/dev/disk/by-label/ESP";
    fsType = "vfat";
  };
  boot = {
    growPartition = true;
    kernelParams = ["console=ttyS0"];
    loader.grub = {
      device = "nodev";
      efiSupport = true;
      efiInstallAsRemovable = true;
    };
    loader.timeout = 0;
    initrd.availableKernelModules = ["uas"];
  };
}

I'm super happy that NixOS and NixOS-generators enables this kind of automation for edge/homelab deployments. I hope this configuration helps others also wanting to rebuild NixOS profiles after deployment.

astr0n8t commented 7 months ago

@JustinLex thanks for sharing your config! I wanted to do a very similar thing and ended up making a separate flake that wraps modified versions of your generator and configuration functions along with the right bootloader code for raw-efi and sd-aarch64. I figured I'd post it here for the next person who comes across this so they don't have to struggle as much as I did

https://github.com/astr0n8t/nixos-gitops/