Skip to content

How to add Cockpit UI for virtual machines to NixOS

Introduction

Cockpit is a cutting-edge web-based graphical interface for server management. It allows you to administer servers effortlessly and includes a built-in terminal.

Personally, I utilize the NixOS package to monitor system logs, network settings, services, system resources, and CPU load and all without needing to touch the command line.

With the Cockpit UI for virtual machines, you can create, run, and manage virtual machines directly in your browser. Since Cockpit runs within NixOS, I thought it would be interesting to test its virtual machines UI. My aim was to replace Proxmox with NixOS, and then it would be useful to be able to create virtual machines. However, I eventually paused my testing and decided to further explore Quickemu along with Quickgui.

How To

Unfortunately, Cockpit machines is not available as a package. However there was an outdated package within the Nix User Repository (NUR), so I decided to add a custom package declaratively.

  1. First create the packages/cockpit directory

    Run the following command:

    # Open your terminal application
    sudo mkdir -p /etc/nixos/packages/cockpit
  2. Create /etc/nixos/packages/cockpit/default.nix

    /etc/nixos/packages/cockpit/default.nix
    # To edit use your text editor application, for example Nano
    { pkgs, ... }:
    {
    virtual-machines = pkgs.callPackage ./virtual-machines.nix { };
    # podman-containers = pkgs.callPackage ./podman-containers.nix { };
    }

    You can add podman-containers.nix in the same way, but we will ignore that for now.

  3. Create /etc/nixos/packages/cockpit/virtual-machines.nix

    /etc/nixos/packages/cockpit/virtual-machines.nix
    # To edit use your text editor application, for example Nano
    { lib, stdenv, fetchzip, gettext }:
    stdenv.mkDerivation rec {
    pname = "cockpit-machines";
    version = "302";
    src = fetchzip {
    url = "https://github.com/cockpit-project/cockpit-machines/releases/download/${version}/cockpit-machines-${version}.tar.xz";
    sha256 = "sha256-3dfB9RzFzN578djOSdANVcb0AZ0vpSq6lIG7uMwzAVU=";
    };
    nativeBuildInputs = [
    gettext
    ];
    makeFlags = [ "DESTDIR=$(out)" "PREFIX=" ];
    postPatch = ''
    substituteInPlace Makefile \
    --replace /usr/share $out/share
    touch pkg/lib/cockpit.js
    touch pkg/lib/cockpit-po-plugin.js
    touch dist/manifest.json
    '';
    postFixup = ''
    gunzip $out/share/cockpit/machines/index.js.gz
    sed -i "s#/usr/bin/python3#/usr/bin/env python3#ig" $out/share/cockpit/machines/index.js
    sed -i "s#/usr/bin/pwscore#/usr/bin/env pwscore#ig" $out/share/cockpit/machines/index.js
    gzip -9 $out/share/cockpit/machines/index.js
    '';
    dontBuild = true;
    meta = with lib; {
    description = "Cockpit UI for virtual machines";
    license = licenses.lgpl21;
    homepage = "https://github.com/cockpit-project/cockpit-machines";
    platforms = platforms.linux;
    maintainers = with maintainers; [ ];
    };
    }

    The above is inspired by this script. Adjust the version if necessary.

  4. Add the cockpit-apps to configuration.nix

    /etc/nixos/configuration.nix
    # To edit use your text editor application, for example Nano
    { config, pkgs, lib, ... }:
    let
    cockpit-apps = pkgs.callPackage packages/cockpit/default.nix { inherit pkgs; };
    in
    {
    imports =
    [ # Include the results of the hardware scan.
    ./hardware-configuration.nix
    ];
    environment.systemPackages = with pkgs; [
    cockpit
    # cockpit-apps.podman-containers
    cockpit-apps.virtual-machines
    libvirt # Needed for virtual-machines
    virt-manager # Needed for virtual-machines
    ];
    # Add the rest of the configuration here
    }

    According to some sources it may be necessary to add libvirtd or qemu-libvirtd to the user’s extraGroups, but I have not tested that further.

  5. Switch NixOS configuration

    Now you can switch to the new NixOS configuration. Run the following command:

    # Open your terminal application
    sudo nix-collect-garbage # Optional: clean up
    sudo nixos-rebuild switch
  6. Check the results

    Now you can browse to Cockpit and the virtual machines UI by opening a web browser and going to: http://localhost:9090. Replace localhost with the relevant IP address or FQDN if needed, and adjust the port if you changed it earlier.

Comments

  • inhumantsar wrote:

    hey! this page was super helpful and i was able to use it to get cockpit-machines running. you were missing libvirt-dbus. i haven't actually tried creating any VMs yet, but everything seems happy atm so i thought i'd share.

    this is how i went about it:

    /etc/nixos/packages/libvirt-dbus/default.nix

    From https://github.com/X01A/nixos/blob/master/packages/libvirt-dbus/pkg.nix

    { lib , stdenv, fetchFromGitLab, meson, pkg-config, glib, libvirt, libvirt-glib, docutils, ninja, pkgs, ...}:
    
    pkgs.stdenv.mkDerivation rec {
      pname = "libvirt-dbus";
      version = "1.4.1";
    
      src = fetchFromGitLab {
        owner = "libvirt";
        repo = "libvirt-dbus";
        rev = "v${version}";
        sha256 = "sha256:112jbkp2b0pk6dpb0p68zg1ba196f4i0y57s1jzjn5vl4f11fv3g";
      };
    
      mesonFlags = [
        "-Dsystem_user=root"
      ];
    
      nativeBuildInputs = [
        meson
        pkg-config
        docutils
        ninja
      ];
      buildInputs = [
        glib
        libvirt
        libvirt-glib
      ];
    
      meta = with lib; {
        description = "DBus protocol binding for libvirt native C API";
        license = licenses.lgpl2Plus;
        homepage = src.meta.homepage;
        platforms = platforms.linux;
        maintainers = with maintainers; [ ];
      };
    }
    

    /etc/nixos/packages/cockpit-machines/default.nix

    From https://github.com/X01A/nixos/blob/master/packages/cockpit-machines/pkg.nix

    { lib, stdenv, fetchzip, gettext, gobject-introspection, osinfo-db-tools, python3Packages, pkgs, ... }:
    
    pkgs.stdenv.mkDerivation rec {
      pname = "cockpit-machines";
      version = "309";
    
      src = fetchzip {
        url = "https://github.com/cockpit-project/cockpit-machines/releases/download/${version}/cockpit-machines-${version}.tar.xz";
        sha256 = "sha256-sVjP3KFmZH3c2tGzlEohAue0u2e7+vAmXBBA+5uuass=";
      };
    
      # gobject-introspection works now, thanks to the post below. but...
      # https://discourse.nixos.org/t/getting-things-gnome-modulenotfounderror-no-module-named-gi/8439/4
      # ...the python script that cockpit-machines runs is failing with a "No such file or directory" error.
      # the script loads properly and i'm not getting an import or gi "Namespace Libosinfo is not available"
      # error, so i'm thinking that the OSINFO_DATA_DIR env var needs to be set. however...
      nativeBuildInputs = [
        gettext
        gobject-introspection
        osinfo-db-tools    
      ];
    
      # ...osinfo-db doesn't show up in nix-support/propagated-build-inputs, and...
      propagatedBuildInputs = with pkgs; [
        python3Packages.pygobject3
        libosinfo
        osinfo-db
      ];
    
      makeFlags = [ "DESTDIR=$(out)" "PREFIX=" ];
    
      postPatch = ''
        touch pkg/lib/cockpit.js
        touch pkg/lib/cockpit-po-plugin.js
        touch dist/manifest.json
      '';
    
      postFixup = ''
        gunzip $out/share/cockpit/machines/index.js.gz
        sed -i "s#/usr/bin/python3#/usr/bin/env python3#ig" $out/share/cockpit/machines/index.js
        sed -i "s#/usr/bin/pwscore#/usr/bin/env pwscore#ig" $out/share/cockpit/machines/index.js
        gzip -9 $out/share/cockpit/machines/index.js
    
        # ...this doesn't work either
        osinfo-db-import --dir "$out/share/osinfo" "${pkgs.osinfo-db.src}"
      '';
    
      dontBuild = true;
    
      meta = with lib; {
        description = "Cockpit UI for virtual machines";
        license = licenses.lgpl21;
        homepage = "https://github.com/cockpit-project/cockpit-machines";
        platforms = platforms.linux;
        maintainers = with maintainers; [ ];
      };
    }
    

    and finally install in configuration.nix

    let
      cockpit-machines = pkgs.callPackage packages/cockpit-machines/default.nix { inherit pkgs; };
      libvirt-dbus = pkgs.callPackage packages/libvirt-dbus/default.nix { inherit pkgs; };
    in
    {
      ...
      environment.systemPackages = with pkgs; [
        cockpit
        cockpit-machines
        virt-manager # needed for cockpit-machines
        libvirt-dbus # needed for cockpit-machines
      ];
      ...
    
    2024-03-26T18:56:17Z
  • inhumantsar wrote:

    well i was never able to get a VM created. can't get the oslibinfo call it makes to populate the OS list to work.

    there's a request open for this and i commented on my progress there in case you want to try again.

    2024-03-26T22:57:50Z
  • fictionbecomesfact wrote:

    Too bad it didn't work out. But good to know, thank you! I'll keep an eye on the package request, if it works I'll definitely give it a try

    2024-03-27T08:11:26Z
  • sophronesis wrote:

    not sure this workaround still works

    2025-04-05T11:15:14Z

No comments found for this note.

Join the discussion for this note on Github. Comments appear on this page instantly.

Copyright 2021-2025 Fiction Becomes Fact