Skip to content

quinneden/virby-nix-darwin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

179 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Virby - Linux Builder for Nix-darwin

Virby is a module for nix-darwin that configures a lightweight linux VM as a remote build machine for nix, allowing linux packages to be built on macOS. This project is modeled after nix-rosetta-builder, which provides a similar service, using lima to manage the VM. Some parts of the code in this repository are directly borrowed and adapted from that project.

Quick Start

Add virby to your flake inputs:

{
  inputs = {
    virby.url = "github:quinneden/virby-nix-darwin";
    # It is important that you dont add the line:
    # 
    #   inputs.nixpkgs.follows = "nixpkgs";
    #
    # until after you've activated with `darwin-rebuild`. This way, the cached
    # image can be used and you won't have to build from source (which requires
    # an existing aarch64-linux builder).
  };

  outputs = { virby, ... }: {
    darwinConfigurations."myHost" = {
      # Import the module
      modules = [ virby.darwinModules.default ];
    };
  };
}

Important

When enabling Virby for the first time, you must add the binary cache to your Nix configuration. This ensures that the prebuilt VM image is available for download, rather than having to be built locally, which requires an existing linux builder. You can do this in one of two ways:

Add the binary cache to your configuration before enabling Virby:

{
  nix.settings.extra-substituters = [ "https://virby-nix-darwin.cachix.org" ];
  nix.settings.extra-trusted-public-keys = [
    "virby-nix-darwin.cachix.org-1:z9GiEZeBU5bEeoDQjyfHPMGPBaIQJOOvYOOjGMKIlLo="
  ];
  
  services.virby.enable = false;
}

Run darwin-rebuild, then enable Virby:

{
  nix.settings.extra-substituters = [ "https://virby-nix-darwin.cachix.org" ];
  nix.settings.extra-trusted-public-keys = [
    "virby-nix-darwin.cachix.org-1:z9GiEZeBU5bEeoDQjyfHPMGPBaIQJOOvYOOjGMKIlLo="
  ];
  
  # Don't configure any other Virby options until after you've switched to the new
  # configuration. If the hash for the disk image derivation doesn't match the one
  # in the binary cache, then nix will try to build the image locally.
  services.virby.enable = true;
}

Finally, rebuild again.

OR

Run the darwin-rebuild command with the following options:

sudo darwin-rebuild switch --flake .#myHost \
  --option "extra-substituters" "https://virby-nix-darwin.cachix.org" \
  --option "extra-trusted-public-keys" "virby-nix-darwin.cachix.org-1:z9GiEZeBU5bEeoDQjyfHPMGPBaIQJOOvYOOjGMKIlLo="

If you prefer building the image locally, you can enable the nix.linux-builder option before enabling Virby:

{
  nix.linux-builder.enable = true;

  services.virby.enable = false;
}

Key Features

  • On-demand activation (optional) - VM is started when needed, then shuts down after a period of inactivity
  • Rosetta support (optional) - Build x86_64-linux packages on Apple Silicon using Rosetta translation
  • Secure by default - Host-only access via loopback (i.e. 127.0.0.1), with automatic ED25519 key generation
  • Fully configurable - Adjust VM resources and add custom NixOS modules

Configuration

Available Options

Option Type Default Description
enable bool false Enable the service
allowUserSsh bool false Allow non-root users to SSH into the VM
cores int 8 CPU cores allocated to VM
debug bool false Enable debug logging for the VM
driver string ("vfkit" or "krunkit") "vfkit" The virtualization driver used to run the VM
diskSize string "100GiB" VM disk size
extraConfig module {} Additional NixOS modules to include in the VM's system configuration
memory int or string 6144 Memory in MiB or string format (e.g. "6GiB")
onDemand.enable bool false Enable on-demand activation of the VM
onDemand.ttl int 180 The number of minutes of inactivity which must pass before the VM shuts down
port int 31222 SSH port for VM access
rosetta bool true Enable Rosetta support for the VM
sharedDirectories attrs of string {} An attribute set of directories that will be shared with the VM as virtio-fs devices
speedFactor int 1 Speed factor for Nix build machine
supportDeterminateNix bool false Enable support for using Virby with Determinate Nix

Use krunkit instead of vfkit

By default, vfkit is used to run the VM. Optionally, you can configure Virby to use krunkit instead:

{
  services.virby.driver = "krunkit";
}

Unlike vfkit, krunkit does not support NAT networking, so the network is proxied via vmnet-helper.

On-demand Activation

{
  services.virby.onDemand.enable = true;
  services.virby.onDemand.ttl = 180;  # Idle timeout in minutes
}

Rosetta Support

{
  services.virby.rosetta = true;
}

Custom NixOS Configuration

Warning

This option allows you to arbitrarily change the NixOS configuration, which could expose the VM to security risks.

{
  services.virby.extraConfig = {
    inherit (config.nix) settings;
    # Some NixOS options which are defined in the default VM configuration cannot
    # be overridden, such as `networking.hostName`. Others may be overridden with
    # `lib.mkForce`. Also note that anything changed here will cause a rebuild of
    # the VM image, and SSH keys will be regenerated.
  };
}

Debug Options (insecure, for troubleshooting only)

{
  services.virby.debug = true;         # Enable verbose logging
  services.virby.allowUserSsh = true;  # Allow non-root SSH access with a separate shared key copy
}

Architecture

Virby integrates three components:

  • nix-darwin Module - Configures VM as a Nix build machine for host
  • VM Image - Minimal NixOS disk image configured for secure ssh access and build isolation
  • VM Runner - Go package managing VM lifecycle and SSH proxying

Security model:

  • VM doesn't accept remote connections as it binds to the loopback interface
  • SSH keys are generated and copied to the VM on first run.
  • builder user has minimal permissions, root access is restricted by default

Troubleshooting

Debug logging

{
  # Enable debug logging to `/tmp/virbyd.log`
  services.virby.debug = true;
}
# View daemon logs
tail -f /tmp/virbyd.log

SSH into VM

# Requires `allowUserSsh = true`
ssh virby-vm
# or use sudo

Acknowledgments


License: MIT - see LICENSE file for details.

Used by

Contributors

Languages