Solution for Slow Rebuilds and Upgrades

How can one have a cache of built packages to decrease the time it takes to switch or upgrade a system at any given moment?

This has been my number one gripe with NixOS given how much time I’ve wasted waiting for packages to build on my system. From my understanding this is apparently only an issue for unfree packages, but I’ve still seen it with non-free packages taking long to build (or maybe I’m hallucinating…).

I’m still very new to this OS so please fill me in if I’m missing anything important. Any ideas/recommendations are welcome. I’m not against hosting a cache if thats the best route, but wondering if there are any other solutions. Maybe I don’t fully understand it.

So, what derivations are you spending significant time building? That’d be most important to know.

Building locally only happens if all configured binary caches don’t contain the desired paths.

Hydra builds all attributes of Nixpkgs that are reachable from pkgs (e.g. from sets that have recurseIntoAttrs = true) and aren’t broken, unavailable or unfree.

If your closure only contains derivations exactly as they are in pkgs and you don’t depend on unfree or broken stuff, you should face no significant local builds, only what I’d call “aggregator” builds; lightweight builds that just e.g. build a tree of symlinks out of all your packages.

There are common things you might do that would cause a package to differ from what it is in upstream Nixpkgs:

  • Overrides
  • Overlays
  • generator functions

Generally, anything that you customise causes a build of some sort. If you change what packages are in the global environment, that will only change the derivation containing the global environment and similar derivations depending on it up to the root of your closure.
If you modify a significant build such as a package, you’ll need to build the entire package. Changing a package that many others depend on via an overlay will cause all dependent packages to be rebuilt.

Please post your configuration, especially the overlays and overrides you apply.

Also, which channel are you using? *-small channels will not wait on Hydra to have built all packages for instance and using one would mean you’ll frequently have to build things locally that hydra would have built at some later point in time.

2 Likes

Sorry for the late response, a lot of the things you mention in your post are foreign concepts to me! I think I need to do a little more nix learning then. I’d also guess it builds packages that are non-free that take up most of the time. I’m not too sure, here’s my main config file.

# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

let
  unstableTarball =
    fetchTarball
      https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz;
in
{
  imports =
    [ # Include the results of the hardware scan.
      /etc/nixos/hardware-configuration.nix
    ];


  # Allow unstable for specific things
  nixpkgs.config = {
    packageOverrides = pkgs: {
      unstable = import unstableTarball {
        config = config.nixpkgs.config;
      };
    };
  };
  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  
  # Mount SMB
  # sudo mount -t cifs //IP/server-username/repos /home/username/repos -o username=username,password=password
  fileSystems."/home/username/repos" = {
    device = "//172.16.44.2/server-username/repos";
    fsType = "cifs";
    options = [ "username=username" "password=password" "x-systemd.automount" "noauto" "uid=1000" "gid=1000" "file_mode=0644" "dir_mode=0755" ];
  };

  networking.hostName = "hostname"; # Define your hostname.
  #networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.

  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";

  # Enable networking
  networking.networkmanager.enable = true;

  # environment vars
  nixpkgs.config.qt5 = {
    enable = true;
    platformTheme = "qt5ct";
      style = {
        package = pkgs.utterly-nord-plasma;
        name = "Utterly Nord Plasma";
      };
  };
  environment.variables.QT_QPA_PLATFORMTHEME="qt5ct";
  # Set your time zone.
  time.timeZone = "America/Chicago";

  # Select internationalisation properties.
  i18n.defaultLocale = "en_US.UTF-8";
  i18n.supportedLocales = [
      "en_US.UTF-8/UTF-8"
      "ja_JP.UTF-8/UTF-8"
    ];
  #i18n.inputMethod.enabled = "fcitx5";
  #i18n.inputMethod.fcitx5.addons = [
  #  pkgs.fcitx5-mozc
  #  pkgs.fcitx5-gtk
  #  pkgs.fcitx5-configtool
  #];
  # environment.variables.GLFW_IM_MODULE = "ibus";
  i18n.inputMethod.enabled = "ibus";
  i18n.inputMethod.ibus.engines = with pkgs.ibus-engines; [mozc];

  i18n.extraLocaleSettings = {
    LC_ADDRESS = "en_US.UTF-8";
    LC_IDENTIFICATION = "en_US.UTF-8";
    LC_MEASUREMENT = "en_US.UTF-8";
    LC_MONETARY = "en_US.UTF-8";
    LC_NAME = "en_US.UTF-8";
    LC_NUMERIC = "en_US.UTF-8";
    LC_PAPER = "en_US.UTF-8";
    LC_TELEPHONE = "en_US.UTF-8";
    LC_TIME = "en_US.UTF-8";
   };

  services.xserver = {
    enable = true;
    displayManager.gdm.enable = true;
    windowManager.i3.enable = true;
    desktopManager.runXdgAutostartIfNone = true;
    xkb.layout = "us";
    #xkb.variant = "dvorak";
    #xkb.options = "grp:win_space_toggle";
    videoDrivers = [ "amdgpu" ];
    #libinput.enable = true;
    #libinput.touchpad.naturalScrolling = true;
  };
    systemd.timers."hello-world" = {
    wantedBy = [ "timers.target" ];
        timerConfig = {
        OnCalendar = "Tue *-*-01 10:00:00";
        Persistent = true;
        Unit = "hello-world.service";
        };
    };

    systemd.services."hello-world" = {
    script = ''
        set -eu
        XDG_RUNTIME_DIR=/run/user/1000 DISPLAY=:0 /run/current-system/sw/bin/notify-send 'Testing Sirens' 'Sirens are being tested, do not fret!' -u critical
    '';
    serviceConfig = {
        Type = "oneshot";
        User = "username";
    };
};

services.xserver.deviceSection = ''Option "TearFree" "true"'';
  services.picom = {
     enable = false;
     vSync = true;
  };

  # Enable CUPS to print documents.
  services.printing.enable = true;

  # Enable sound with pipewire.
  hardware.pulseaudio.enable = false;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
    # If you want to use JACK applications, uncomment this
    #jack.enable = true;
  };

  hardware.bluetooth.enable = true;
  hardware.bluetooth.powerOnBoot = true;
  services.blueman.enable = true;
  #hardware.pulseaudio.extraConfig = "load-module module-combine-sink";
  security.rtkit.enable = true;
  #sound.mediaKeys = {
  #  enable = true;
  #  volumeStep = "5%";
  #};

  networking.extraHosts =
  ''
#redacted
  '';


  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.username = {
    isNormalUser = true;
    description = "User";
    extraGroups = [ "networkmanager" "wheel" "docker" "dialout" "tty" "adbusers" "kvm"];
    packages = with pkgs; [
      firefox
      thunderbird
    ];
  };

  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;
  # ADB
  programs.adb.enable = true;
  programs.nix-ld.enable = true;

  # Experimental
  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  # List packages installed in system profile. To search, run:
  # $ nix search wget

  environment.systemPackages = with pkgs;
  let
      polybar = pkgs.polybar.override {
        i3Support = true;
      };
    in
  [
    unstable.zed-editor
    just
    polybar
    vscode
    tor-browser
    tor
    dos2unix
    rpi-imager
    gnome.gnome-keyring
    gcr
    calibre
    snmpcheck
    icu
    anki-bin
    ghidra
    bcompare
    binwalk
    arp-scan
    obs-studio
    davinci-resolve
    mediamtx
    hplip
    vlc
    xwinwrap
    wireshark
    postman
    fclones
    fclones-gui
    nfs-utils
    jadx
    apktool
    bytecode-viewer
    openjdk
    dex2jar
    cool-retro-term
    ntfs3g
    ffmpeg-full
    frei0r
    frida-tools
    nodejs
    unixtools.xxd
    keepassxc
    libsForQt5.kleopatra
    pinentry
    pinentry-curses
    gnupg
    net-snmp
    frp
    qemu-utils
    nmap
    mitmproxy
    openssl
    pkg-config
    radamsa
    tmux
    avahi
    filezilla
    mitmproxy
    python311Packages.mitmproxy-rs
    vagrant
    android-tools
    gradle
    scrcpy
    gdb
    ranger
    lf
    wget
    neovim
    gcc
    clang
    gnumake
    desktop-file-utils
    ripgrep
    lazygit
    bottom
    polkit
    polkit-kde-agent
    gsimplecal
    i3
    x11vnc
    tigervnc
    alacritty
    krita
    figlet
    kitty
    kitty-themes
    kitty-img
    zsh
    gnome.gdm
    dunst
    libnotify
    bind
    p7zip
    ark
    mpvScripts.mpris
    cava
    braa
    qrencode
    zbar
    mpv
    ani-cli
    mpd
    mpd-mpris
    mpd-discord-rpc
    playerctl
    alsa-utils
    pamixer
    xbindkeys
    xorg.xev
    xvfb-run
    xorg.xbacklight
    sxiv
    feh
    xclip
    flameshot
    yt-dlp
    imagemagick
    zathura
    cron
    obsidian
    neofetch
    redshift
    curl
    jq
    wget
    libreoffice-still
    arandr
    xorg.xrandr
    conda
    git
    git-lfs
    sshfs
    openssh
    inetutils
    rsync
    meld
    dolphin
    samba
    resvg
    libsForQt5.ffmpegthumbs
    libsForQt5.kio-extras
    libsForQt5.kdegraphics-thumbnailers
    kdePackages.kdegraphics-thumbnailers
    ffmpeg
    nufraw-thumbnailer
    taglib
    libsForQt5.qt5ct
    python3
    python311Packages.pip
    networkmanagerapplet
    wireguard-tools
    polkit_gnome
    picom
    rofi
    rofi-emoji
    rofi-calc
    usbutils
    subversion
    minicom
    putty
    screen
    autorandr
    killall
    lxappearance
    capitaine-cursors
    libsForQt5.qt5ct
    libsForQt5.breeze-icons
    libsForQt5.ark
    libsForQt5.qtstyleplugin-kvantum
    libsForQt5.qt5ct
    chromium
    lm_sensors
    i3lock-fancy-rapid
    pavucontrol
    cifs-utils
    xlsfonts
    materia-theme
    pciutils
    xorg.xf86videoamdgpu
    vaapiVdpau
    vdpauinfo
    libvdpau-va-gl
    libva-utils
    btop
    htop
    cmatrix
    asciiquarium-transparent
    file
    appimage-run
    polkit
    unetbootin
    gparted
    uuu
    pv
    cdrtools
    cdrkit
    exfatprogs
    ntfs3g
    gnome.nautilus
    rdesktop
    moonlight-qt
    synergy
    #logitech-udev-rules
    gedit
    bc
    busybox
    iperf3
    freerdp
    libsForQt5.qt5ct
    unzip
    ];

  fonts.packages = with pkgs; [
    siji
    nerdfonts
    font-awesome
    noto-fonts
    noto-fonts-cjk-sans
    noto-fonts-cjk-serif
    noto-fonts-color-emoji
    liberation_ttf
    fira-code
    fira-code-symbols
    mplus-outline-fonts.githubRelease
    dina-font
    proggyfonts
    fira-mono
    fira-code
    carlito
    dejavu_fonts
    ipafont
    kochi-substitute
    source-code-pro
    ttf_bitstream_vera
  ];

  # Set default fonts
  fonts.fontconfig.defaultFonts = {
    monospace = [
      "Fira Mono"
      "Noto Sans Mono CJK JP"
    ];

    sansSerif = [
      "Fira Mono"
      "Noto Sans CJK JP"
    ];

    serif = [
      "Fira Mono"
      "Noto Serif CJK JP"
    ];
  };

  nixpkgs.config.permittedInsecurePackages = [
    "electron-25.9.0"
    "python3.11-django-3.1.14"
  ];

  programs.zsh.enable = true;
  users.defaultUserShell = pkgs.zsh;

  systemd = {
    user.services.polkit-gnome-authentication-agent-1 = {
      description = "polkit-gnome-authentication-agent-1";
      wantedBy = [ "graphical-session.target" ];
      wants = [ "graphical-session.target" ];
      after = [ "graphical-session.target" ];
      serviceConfig = {
        Type = "simple";
        ExecStart =
          "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
        Restart = "on-failure";
        RestartSec = 1;
        TimeoutStopSec = 10;
      };
    };
  };
  # DOCKER
  virtualisation.docker.rootless = {
    enable = true;
    setSocketVariable = true;
  };
  users.extraGroups.docker.members = [ "username" ];

  # Enable the OpenSSH daemon.
  services.openssh = {
  enable = true;
  ports = [ 22 ];
  settings = {
    PasswordAuthentication = true;
    AllowUsers = [ "username" ];
    UseDns = true;
    X11Forwarding = true;
    PermitRootLogin = "no"; # "yes", "without-password", "prohibit-password", "forced-commands-only", "no"
  };
};
  services.avahi = {
    enable = true;
    nssmdns4 = true;
    openFirewall = true;
  };

  services.devmon.enable = true;
  services.gvfs.enable = true;
  services.udisks2.enable = true;
  # Open ports in the firewall.
  #networking.firewall.enable = false;
  #networking.firewall.allowedTCPPorts = [ 22 80 443 5000 ];
  #networking.firewall.allowedUDPPorts = [ 51820 69 ];
  # DEFCON
  networking.firewall.enable = false;
  networking.firewall.allowedTCPPorts = [];
  networking.firewall.allowedUDPPorts = [];
  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };
  # This is using a rec (recursive) expression to set and access XDG_BIN_HOME within the expression
  # For more on rec expressions see https://nix.dev/tutorials/first-steps/nix-language#recursive-attribute-set-rec
  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  # services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "23.11"; # Did you read the comment?
  services.libinput.touchpad.naturalScrolling = true;
  programs.light.enable = true;
  services.actkbd = {
    enable = true;
    bindings = [
      { keys = [ 225 ]; events = [ "key" ]; command = "/run/current-system/sw/bin/light -A 10"; }
      { keys = [ 224 ]; events = [ "key" ]; command = "/run/current-system/sw/bin/light -U 10"; }
    ];
  };
  # For kleopatra
  services.pcscd.enable = true;
  programs.gnupg.agent = {
     enable = true;
     enableSSHSupport = true;
  };

  # udev rules for uuu
  services.udev.extraRules = builtins.readFile ./uuu-udev;
  nix.optimise.automatic = true;
  nix.optimise.dates = [ "03:45" ]; # Optional; allows customizing optimisation schedule

  # Newest kernel
  boot.kernelPackages = pkgs.linuxPackages_latest;
  # firefox save dialog
  environment.sessionVariables = {
    MOZ_USE_XINPUT2 = "1";
  };

  xdg.mime.defaultApplications = {
    "text/html" = "firefox.desktop";
    "x-scheme-handler/http" = "firefox.desktop";
    "x-scheme-handler/https" = "firefox.desktop";
    "x-scheme-handler/about" = "firefox.desktop";
    "x-scheme-handler/unknown" = "firefox.desktop";
    "application/pdf" = "org.pwmt.zathura-pdf-mupdf.desktop";

  };

  services.xserver.windowManager.i3.extraSessionCommands = ''
    eval $(gnome-keyring-daemon --daemonize)
    export SSH_AUTH_SOCK
  '';

}

Unset this and remove whatever package depends on such an ancient electron version. Electron is a huge build.

2 Likes

This significantly fixed how long my builds took. Didn’t realize how much time that added. Thank you!

1 Like

Yep, keep in mind electron is basically chromium + more. So you’re building an entire browser (which can take hours).

If I was crazy enough, and needed to use that version, would the best way to do this be to build it on a different server and cache the files that way? Using the binary cache?

https://nixos.wiki/wiki/Binary_Cache

Remote builders or your own build farm.

1 Like

Again, do keep in mind that it’s a browser running arbitrary code, on a known insecure chromium version. I would consider that a security risk.

In general you can use remote builders or caches.

1 Like