Installing NixOS on a Hetzner VPS

In this guide, I will explain how to install NixOS on a Hetzner VPS from a local machine using flakes and Nix itself.

Requirements

  • A linux os with the latest systemd, I'm using ubuntu24.04
  • A machine with Nix already installed (I have written a blog post on this topic).
  • Root privileges to run commands.

That's it!

We will use nixos-anywhere and disko to install Nix and create declarable partitions. First, we'll import them into our flake. The directory structure should look like this:

Screenshot 2024-07-02 at 12 38 41

You'll want to change wood to something else, i'm just imagining the host name for myvps as wolf.

  • flake.nix
  {
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    disko.url = "github:nix-community/disko";
    disko.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, disko, ... }: {
    nixosConfigurations.wolf = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          disko.nixosModules.disko
          ./configuration.nix
          ./disk-config.nix
        ];
      };
  };
}

We'll import our configuration.nix and disk-config.nix inside our flake. Add your public ssh keys in authorized_keys for accessing the server after installation.

  • configuration.nix
{ modulesPath, config, lib, pkgs, ... }: {
  imports = [
    (modulesPath + "/installer/scan/not-detected.nix")
    (modulesPath + "/profiles/qemu-guest.nix")
    ./disk-config.nix
  ];
  boot.loader.grub = {
    efiSupport = true;
    efiInstallAsRemovable = true;
  };
  services.openssh.enable = true;

  environment.systemPackages = map lib.lowPrio [
    pkgs.curl # define your more packages here
    pkgs.gitMinimal
  ];

  users.users.root.openssh.authorizedKeys.keys = [
    "You're public ssh key"
  ];

  system.stateVersion = "23.11";
}

Now regarding the disk, I'm using the default disk partitions required and recommended by disko, If you happen to change you can. This disk partions are for bios compatible gpt partition.

  • disk-config.nix
# Example to create a bios compatible gpt partition
{ lib, ... }:
{
  disko.devices = {
    disk.disk1 = {
      device = lib.mkDefault "/dev/sda";
      type = "disk";
      content = {
        type = "gpt";
        partitions = {
          boot = {
            name = "boot";
            size = "1M";
            type = "EF02";
          };
          esp = {
            name = "ESP";
            size = "500M";
            type = "EF00";
            content = {
              type = "filesystem";
              format = "vfat";
              mountpoint = "/boot";
            };
          };
          root = {
            name = "root";
            size = "100%";
            content = {
              type = "lvm_pv";
              vg = "pool";
            };
          };
        };
      };
    };
    lvm_vg = {
      pool = {
        type = "lvm_vg";
        lvs = {
          root = {
            size = "100%FREE";
            content = {
              type = "filesystem";
              format = "ext4";
              mountpoint = "/";
              mountOptions = [
                "defaults"
              ];
            };
          };
        };
      };
    };
  };
}

Now, we'll have to run our flake to install nix on the vps.

 nix run github:nix-community/nixos-anywhere -- --flake .#wolf root@<server-ip>
Screenshot 2024-07-02 at 12 51 42
It'll ask for password to install the base of nix.
Screenshot 2024-07-02 at 12 55 31

And now, you should be able to log-in into the vps using the ssh keys , regardless of the password being empty.

Screenshot 2024-07-02 at 12 53 43