Note fmzakari 9 days ago

NixOS on exe.dev

exe.dev can boot a NixOS VM from a Docker image. Build NixOS as a container image and set its CMD to the system's init. exe.dev starts it as PID 1 and NixOS brings up systemd. You don't need an SSH server in the image because exe.dev provides one.

The NixOS module:

# exe.dev provides the kernel.
boot.isContainer = true;

# The kernel's ip= argument already configures eth0.
networking.useDHCP = false;

# exe-init sets the hostname from the kernel's ip= argument.
networking.hostName = "";

# exe.dev's DNS resolver.
networking.nameservers = [ "169.254.169.254" ];

# exe.dev runs its own sshd on port 22.
services.openssh.enable = false;

# console=hvc0 makes systemd wait for a getty on a device that never
# appears without udev, so boot stays in "starting" forever.
systemd.units."serial-getty@hvc0.service".enable = false;

# The user exe.dev's sshd logs in as, named by the image's
# exe.dev/login-user label.
users.users.exedev = {
  isNormalUser = true;
  uid = 1000;
  extraGroups = [ "wheel" ];
};

# Passwordless sudo for that user, as on exe.dev's default image.
security.sudo.wheelNeedsPassword = false;

Pack it with dockerTools.streamLayeredImage like so:

# The NixOS system built from the module above.
toplevel = nixos.config.system.build.toplevel;

# A Docker image holding the system. Booting it runs NixOS's init, which
# sets up /etc and starts systemd.
image = pkgs.dockerTools.streamLayeredImage {
  name = "nixos";
  tag = "latest";
  config = {
    Cmd = [ "${toplevel}/init" ];
    # The user exe.dev's SSH logs you in as.
    Labels."exe.dev/login-user" = "exedev";
  };
};

To keep the image private, run a registry on another VM as in
https://hub.exe.dev/docs/private-image#run-a-registry-on-an-exedev-vm.
To push a Nix-built image from your own machine, tunnel to that registry:

ssh -f -N -L 15000:localhost:8000 myregistry.exe.xyz
nix build .#image && ./result > image.tar
skopeo copy --dest-tls-verify=false docker-archive:image.tar docker://localhost:15000/nixos:v1
ssh exe.dev new --name=mynixos --image=myregistry.exe.xyz/nixos:v1

One gotcha: exe.dev's sshd runs its own /exe.dev/bin/sh, not the login
shell from /etc/passwd. Interactive logins get the NixOS PATH;
ssh vm cmd does not. Run commands through a login shell instead:

ssh mynixos.exe.xyz '/run/current-system/sw/bin/bash -lc "systemctl status"'

0 Comments

No comments yet.