Configuring a KVM based VPS server for NixOS ISO

So your provider only supports bootable ISO for their provided servers? And maybe they don't even have their own DHCP server and you need to configure this yourself!

Manually configuring the network from the commandline

Even if NixOS does everything declaratively, the install itself requires access to the internet to fetch the required packages. My provider gave me the IP address, the netmask and gateway. This was all new to me but the procedure itself isn't super difficult.

First check what interfaces are accessible. The interface is basically your access point to other machines. It's often eth0 (ethernet 0) but at my host it was ens18. To check your interface, simply run the command ifconfig

It should spit out your interface (all the way to the left), the IP address will be wrong at the time. So let's fix that!

Run
sudo ifconfig <interface name> <server ip address> netmask <netmask>

That should configure the interface with the correct netmask and ip address. But that's not all, we also need to tell the computer where to send all the traffic on that interface. That's why we need to configure a default gateway.
The gateway IP should also be provided by your server provider.

The command to run to configure your default gateway is:
sudo route add default gw <gateway IP> <interface name>

If you get any errors, double check that the interface name is correct. If everything is correct, you should now have internet access! But not DNS lookups! That means you can't exactly access domain names (i.e google.com) but you can access IP addresses. Let's test it by pinging 8.8.4.4 (the google DNS servers), if the command isn't obvious, it's ping 8.8.4.4

Hopefully the connection is established and you got it working!

So putting it all together, here's a list of what you need to run:

  1. sudo ifconfig <interface name> <server ip address> netmask <netmask>
  2. sudo route add default gw <gateway IP> <interface name>
  3. ping 8.8.4.4 (to test if it worked)

Setting up NixOS

After you've set up the network. You can start by partitioning and installing the OS itself. I won't cover this because the NixOS manual is pretty well made and it may change in the future. The link (at time of writing) is:
https://nixos.org/manual/nixos/stable/index.html#sec-installation-partitioning

My server provider was running KVM and I could only get it to work with legacy boot (MBR) and not UEFI.

After generating the configuration.nix file

After you have generated the configuration file, you need to:
A. add your gateway, DNS servers (we're using Google's servers) and other network settings (i.e firewall)
B. Add SSH (if you want SSH access)

Also you gotta remember to add your hw-config which was generated for you.
My file looks like this (remember to fill in your own IP/Gateway):

{ config, pkgs, ... }:
{
  imports =
  [ # Include the results of the hardware scan.
    ./hw-config.nix
  ];
  
  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;
  # boot.loader.grub.efiSupport = true;
  # boot.loader.grub.efiInstallAsRemovable = true;
  # boot.loader.efi.efiSysMountPoint = "/boot/efi";
  # Define on which hard drive you want to install Grub.
  boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
  # Add your required packages
  environment.systemPackages = with pkgs; [
    wget
    cron
  ];
  # Manually configure network
  networking.interfaces.ens18.useDHCP = false;
  networking.interfaces.ens18.ipv4.addresses = [{
      address = target;
      prefixLength = 24;
  }];
  networking.defaultGateway = <gateway ip here>;
  # We use the Google DNS servers as an example here
  networking.nameservers = ["8.8.4.4" "8.8.8.8"];
  # Set keyboard locale, I'm using the Norwegian locale here
  i18n.defaultLocale = "nb_NO.UTF-8";
  services.openssh = {
    enable = true;
    passwordAuthentication = false;
    permitRootLogin = "yes";
  };

};
}

That's all! Congrats, after a reboot, NixOS should be working and accessible.

NixOps bonus example

After setting up NixOS on your server, you might want to control the server through NixOps. As a bonus, a deployment file (hardware declaration) can look something like this:

let 
  target = "<your server ip>";
  gateway =  "<gateway ip>";
in {
  ExampleServerName = 
    { config, pkgs, ... }:
    {
      # Remember to add the hw-config.nix in the same folder as this config file
      imports =
      [ # Include the results of the hardware scan.
        ./hw-config.nix
      ];

      deployment.targetHost = target;
      boot.loader.grub.enable = true;
      boot.loader.grub.version = 2;
      # boot.loader.grub.efiSupport = true;
      # boot.loader.grub.efiInstallAsRemovable = true;
      # boot.loader.efi.efiSysMountPoint = "/boot/efi";
      # Define on which hard drive you want to install Grub.
      boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
      
      environment.systemPackages = with pkgs; [
        wget
        cron
      ];
      # Manually configure network
      networking.interfaces.ens18.useDHCP = false;
      networking.interfaces.ens18.ipv4.addresses = [{
          address = target;
          prefixLength = 24;
      }];
      networking.firewall.allowedTCPPorts = [ 22 ];
      networking.defaultGateway = gateway;
      # We use the Google DNS servers as an example here
      networking.nameservers = ["8.8.4.4" "8.8.8.8"];
      # Set keyboard locale, I'm using the Norwegian locale here
      i18n.defaultLocale = "nb_NO.UTF-8";
      services.openssh = {
        enable = true;
        passwordAuthentication = false;
        permitRootLogin = "yes";
      };

    };
}

Now you just need to write your NixOps service logic and you're off to the races!