• 1 Post
  • 18 Comments
Joined 3 years ago
cake
Cake day: June 14th, 2023

help-circle
  • Hi! Welcome to the Nix community. You’ve made an unfortunate choice for your first package, because VPNs usually need to be integrated with system networking to function properly, and Nix without a daemon or NixOS is not able to do that. A distro has multiple pieces, including package management (putting executables and libraries onto your disk) and system configuration (interacting with the low-level hardware). Nix is a package manager; NixOS is Nix and also system configuration and some other stuff like booting.

    For the specific case of Mullavad, I found this community documentation:

    Warning: Mullvad VPN currently only works if systemd-resolved is enabled.

    All you need to know here is that systemd is part of the system configuration; systemd-resolved is part of how some Linux systems look up names. Nix’s version of Mullavad VPN is only compatible with a specific NixOS configuration.

    Honestly, it’s great to hear that the GUI and nix-env are working for you; those are things that often break on unusual targets. It sounds like the only thing that doesn’t work is something which cannot work as installed.


  • It’s the same controversy as it was last year and the year before that: should the military-industrial complex be allowed to benefit from the Nix commons? It’s disappointing that you don’t think that the ethics of our profession is worth more than the output of our labor, particularly when it comes to exploitation, mass surveillance, war, and genocide.

    Most of us write flakes outside of nixpkgs. I’m still listed as a maintainer and get pinged, but I don’t really care; anything I care about is already being actively developed out-of-tree. I doubt I’m the only maintainer taking that sort of quiet-quitting path.



  • As a relatively heavy solution, you can use a container orchestrator that understands a failure to pull an image as a temporary or transient situation. The lightest orchestrator that I’ve used on NixOS in a homelab is k3s:

    services.k3s.enable = true;
    

    It is more-or-less a cut-down Kubernetes, and as such it will not fail to start merely because one Pod had an error pulling one Image. It will also offer a path forward if you want to continue building up software-defined networking.

    That all said, I’d re-examine what you want from service isolation during OS upgrades; it’s possible for routine NixOS updates to only restart affected services and not reboot. In production, nixos-rebuild switch can do things like upgrade shared libraries, switch webroots, or flip feature flags. Containerization might be unnecessary overhead, and I say that as a Kubernetes proponent.


  • I don’t really like flake-parts or flakelight. I think that part of this is sheer brutalism (I don’t mind writing bare Nix) but part of it is a desire to not rely on flakes which don’t carry their own weight, following Wirth’s principle for compilers.

    That said, github:numtide/flake-utils does carry its own weight by managing multiple system values, especially in flakes that support more systems than upstream nixpkgs, and I’ve found myself using it in nearly everything; flake-utils makes it fairly easy to have leaf packages that are e.g. supported on both amd64 and aarch64. I know flake-parts does this too, but not in a way I enjoyed.

    I just noticed that you said “my configuration.” A machine, perhaps? My NixOS configuration is split into over a dozen NixOS modules and each machine has a list of included module files. I’m not using any flake-management tools for that flake; each machine has a hardcoded system and (like sibling comment from @algernon@lemmy.ml) they’re all crammed into one big flake.nix so that the machine hostnames line up correctly when using the flake in argv:

    $ sudo nixos-rebuild switch --flake git://git.example.local/one.big.flake.git
    

    Seems facetious at first, but it facilitates automatic updates via flakes, just like with classic channels.


  • Can notifications be started from a systemd unit? Kind of. notify-send can be invoked from systemd, but getting the correct user notified is non-trivial and I’m not sure how it would be done on NixOS.

    Can nixos-rebuild have a progress bar? Not really. It’s not a process with a predictable end time.

    Can there be notifications when updates are available? There are scripts out there (like this one which I have never used) which can poll git repositories and run notify-send, but that’s not very useful. Instead, it’s worth knowing that most of the cost of auto-upgrade is running the nixos-rebuild command at all, even if there are no available upgrades!

    Instead, consider setting system.autoUpgrade.dates to a fixed time when you definitely won’t use the computer, and also set system.autoUpgrade.persistent. This will run auto-upgrade on boot in the worst case.

    Also, USB devices should not be disconnecting on every update. If USB disconnections happen under high load, check dmesg for possible hints; you may merely need to add an override to boot.kernelParams.



  • Search the manual for support32Bit configuration options, like hardware.opengl.support32Bit, hardware.pulseaudio.support32Bit, or services.pipewire.alsa.support32Bit. Any 32-bit games, as well as Steam itself, will need these to get their GL and PA/ALSA libraries set up properly.

    You may also want to look up what programs.nix-ld.enable does, although I hear that there’s a better harness builtin as of NixOS 24.05.

    All that said, everything Just Worked when I last tried. I haven’t run Steam in a while, though. I do use Retroarch and OBS without problems, though, streaming PS4 speedruns to Youtube or Peertube, and that all works out-of-box.




  • Oh, right, monoids! Yes, you understand correctly.

    A monoid is a collection of objects that has some sort of addition and zero. (Depending on your maths background, it might equivalently have some sort of multiplication and unit.) Addition must be associative, and addition with zero must not have any effect. Monoids let us think of a system as built from a sequence of operations; each operation adds to the system, preparing its state incrementally.

    Sometimes monoids are commutative, which means that the order of additions is irrelevant to the result. Commutative monoids let us think of a system as built from a collection of operations without worrying about the order in which those operations are applied.

    NixOS modules (and HM modules, etc.) are commutative monoids. The zero is {}. The module system lets options declare their own monoids which ride along, like my example of allowedTCPPorts. Because we can combine sets of port numbers (with set union) and get more sets, we can factor a set of ports into many smaller subsets and put each one in their own file. Here’s my shortest module, for an internal Docker registry, docker-registry.nix:

    {
      networking.firewall.allowedTCPPorts = [ 5000 ];
      services.dockerRegistry = {
        enable = true;
        enableGarbageCollect = true;
      };
    }
    

  • I’m adding some code snippets from my homelab’s flake. Minor details are changed. Note how I have a core.nix and also separate files for adding Avahi (zeroconf) and SSH, and for fixing bufferbloat. I could have them as one file, but it’s easier to come back to them after several years this way. (bufferbloat.nix was last changed in December 2021, for example.)

    I know that some of this code style probably seems weird. Think of it as heavily inspired by Puppet, Chef, Ansible, HCL, etc.; when we are configuring a system, it is very very nice to be able to comment out a single line at a time.

    Click to see code!

    Some common modules, bundled into a NixOS module:

        commonModules = {
          imports = [
            nixpkgs.nixosModules.notDetected
            ./avahi.nix
            ./bufferbloat.nix
            ./core.nix
            ./ssh.nix
          ];
          nix.registry.nixpkgs.flake = self.inputs.nixpkgs;
          nixpkgs.config.packageOverrides = pkgs: {
            mumble = pkgs.mumble.override {
              pulseSupport = true;
            };
          };
          users.users.corbin = {
            isNormalUser = true;
            extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
          };
        };
    

    A NixOS machine definition:

          joker = nixpkgs.lib.nixosSystem {
            inherit system;
            modules = [
              commonModules
              ./joker/configuration.nix
              ./gl.nix
              ./sound.nix
              ./wifi.nix
              ./xserver.nix
            ];
          };
    

  • At scale, you’ll appreciate explicitly spelling out your imports. I currently have 23 importable files, of which two are mutually incompatible (headless vs. Xorg). I don’t want a glob over these files because no machine can have all of them; indeed, most machines only have like five imports from the list.

    What might be more interesting to you is a common collection of modules which must be imported everywhere. To achieve this, I explicitly declare a commonModules at the top of my flake and reuse it in each machine definition. Another approach might be a common.nix module which recursively contains the common modules as its own imports.

    Finally, it doesn’t “defeat[] the point of separating” expressions into multiple files to avoid globbing over them. Because NixOS/HM modules are monoidal, they often factor nicely. When you have a dozen different services, you could stuff all of them into one file with one networking.firewall.allowedTCPPorts if you wanted, or you could put each service into its own file and let each module bring its own port to the combined configuration. The latter is easier at scale; I have nine modules declaring TCP ports and five machine-specific TCP ports as well, and it would be a pain to put all of them in one location.




  • The nix-shell advice is cogent enough that somebody might use it. Instead of a bare bash script, consider direnv, which scopes each shell session to a directory and has upstream builtin Nix support.

    Edit: When laning with two mages in bot, focus on harassing enemy champions instead of farming. For Veigar, line up each Q to hit a minion and a champion, combining the farm and harass into a single action. Do not be aggressive in the early game; AP takes time to build. The deaths at 13min and 15min were due to aggression, and by 18min it looks like tilt. Ward more; at 22min, Veigar is alone in lane with no visibility into nearby bushes, and 4/5 enemy champions can burst him down if he misses his cage. Rod of Ages is a good call, but an Hourglass would be an even better call, as it can nullify damage from Ahri and Zed combos. Finally, don’t do fadeaway ults at the end of Veigar combos; it feels satisfying, but isn’t as much damage as carefully-timed Q.