Just a basic programmer living in California

  • 6 Posts
  • 16 Comments
Joined 2 years ago
cake
Cake day: February 23rd, 2024

help-circle
  • Whoops! Guess I was wrong. After some experimenting it looks like the flake system parses, but does not evaluate flake.nix to read inputs. I also experimented with string concatenation, and that failed with the same error:

    nixpkgs.url = "github:nixos/nixpkgs" ++ "/nixos-25.05"; # error: expected a string or path, but got a thunk
    

    A “thunk” is an expression whose evaluation has been delayed. It’s a key piece of lazy evaluation. Remember that every expression in Nix is lazily evaluated.

    It looks only literal attribute set, string, and path expressions will work in inputs. I think that means it is not possible to split inputs over multiple files.



  • I think you can use import to load the expression from each file, and the // operator to combine imported attribute sets. Like this:

    Edit: This doesn’t work - see replies

    # flake.nix
    {
      inputs =
        import ./inputs/nixpkgs.nix //
        import ./inputs/nix-index.nix;
    
      # ...
    }
    
    # inputs/nixpkgs.nix
    {
      nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
      nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";
    }
    
    # inputs/nix-index.nix
    {
      nix-index-database = {
        url = "github:Mic92/nix-index-database";
        inputs.nixpkgs.follows = "nixpkgs";
      };
    }
    


  • No, if something goes wrong with the VPN then the confined service will be unable to reach the internet. The setup runs the confined process in a network namespace that does not have a route to your default wifi or ethernet interfaces. If the VPN interface isn’t set up correctly, or stops working there is no other route out.

    You can test this with or without setting up VPN-Confinement. To do a quick test without any VPN setup, create a test service like this:

    systemd.services.test-unit = {
      serviceConfig = {
        NetworkNamespacePath = "/run/netns/test";
        Type = "oneshot";
      };
      script = ''
        ${pkgs.iputils}/bin/ping 1.1.1.1
      '';
    };
    

    Create a matching network namespace that doesn’t route anywhere:

    sudo ip netns add test
    

    Then set the unit running, and watch its output:

    sudo systemctl start test-unit.service
    journalctl -u test-unit.service -f
    

    You’ll see ping report that the network is unreachable. If you delete the namespace while ping is running it will continue to report that the network is unreachable.

    sudo ip netns del test
    

    (If you don’t want to bother with a systemd unit, you can run a process in a given network namespace using sudo ip netns exec <namespace> <command>. For example, sudo ip netns exec test ping 1.1.1.1.)

    If the namespace wasn’t set up for whatever reason the confined service won’t start. (See the edit on the post.)

    I also did some tests with the VPN-Confinement setup with this test unit:

    systemd.services.test-unit = {
      serviceConfig = {
        Type = "oneshot";
      };
      script = ''
        while true; do
          ${pkgs.curl}/bin/curl https://am.i.mullvad.net/connected
          sleep 5
        done
      '';
      vpnConfinement = {
        enable = true;
        inherit vpnNamespace;
      };
    };
    

    If I set vpnNamespace to a name that doesn’t match a configured vpnNamespace then the service won’t start.

    If I bring down the VPN namespace while that curl loop is running with sudo systemctl stop wg.service then test-unit also stops, because of the systemd dependencies that systemd.services.<name>.vpnConfinement sets up.

    If I bring down the network namespace manually while the curl loop is running with sudo ip netns del wg then the curl loop keeps running, and continues to report that it is connected to Mullvad. I guess the network namespace continues to exist while a running process is using it.

    If I bring down the VPN network interface with sudo ip -n wg link set dev wg0 down then curl fails with status=6/NOTCONFIGURED



  • I haven’t gotten much into flake-parts, but my understanding is that it creates a module system very similar to NixOS modules and Home Manager modules. Except that instead of defining a system configuration, flake-parts modules define flake outputs.

    So I don’t think you would use it in your NixOS configuration. If your configuration uses a flake there might be use cases for using it at the flake level. For example your flake defines a nixosConfigurations output, which is a set with an attribute for each host. If you had some unusually complicated code in that flake output you might use flake-parts to modularize it.

    Or I suppose flake-parts is largely aimed at simplifying per-system outputs like packages and devShells. Once again, if you wanted to split those definitions over multiple files flake-parts can do that. Or you can use it just to get flake-parts’ eachDefaultSystem helper if you don’t want to use equivalent functionality from flake-utils, or the built-in genAttrs function.

    Although I love the NixOS module system, I haven’t used flake-parts because I haven’t had a case where I want reusable modules in the context of flake outputs. Usually my flakes are a pretty uncomplicated combination of genAttrs, basic devShells, basic overlays, and package expressions that I build with callPackage.





  • At this point I don’t know what the difference is between waylandFull and the other wine packages. Last I checked waylandFull pointed to a much older wine version. But I see that’s just changed. Since Wayland is not in Wine’s main branch my guess is there’s no need for a Wayland-specific package.

    When I was working on this yesterday (I think) only the staging and unstable wine packages were on Wine 10. But yes, it looks like today all of the Wine packages in NixOS unstable are updated to Wine 10 so you could use wineWowPackages.stableFull, or whatever you want.

    I’m sorry about the Bottles issue! I was using Bottles, but I couldn’t figure out how to get a Wine 10 runner, or how to get it to use the system Wine which is why I went to Lutris.


  • Good point! There is also a spot you can set this in game settings in Lutris.

    I haven’t tried this in Steam. Steam still requires X11. Can Steam spawn a native Wayland window if it’s running in xwayland? I assumed not which is why I went through Lutris. But if it can that would be great!

    Edit: Oh yeah, Steam can launch native Wayland games! Now that I think about it that makes sense - Steam spawns a sub-process that manages its own windows so the sub-process doesn’t get stuck in X11 land. This is great! I thought I was going to have to wait forever for Valve to release a Steam update with Wayland support!

    I think the Proton options that Steam provides are not updated to Wine 10 yet so they won’t run in Wayland without the special registry setting that the previous Wine version requires? I tried hacking in a custom compatibility runner that runs wine from the Nix package, but I got a message saying that a running instance of steam could not be found. But I was able to get a runner that works from wine-tkg-git by following instructions here.

    • from that link click, under the “Proton nightly builds” heading click on “Wine Master”
    • click the latest workflow run
    • under “Artifacts” click to download proton-tkg-build
    • unzip and then untar the file, put the extracted directory in ~/.steam/root/compatibilitytools.d/
    • you’ll see a new runner option in the compatibility settings for games


  • Docker Compose runs services, manages dependencies between services, isolates each service in a container, manages a private network. Out-of-the-box flakes don’t do any of that - except arguably running one service at a time. What flakes do is build software, which is the thing that Docker Compose doesn’t really do. (Or doesn’t do well.)

    I’d compare flakes to Makefiles with waaay more expressiveness and reproducibility. Or maybe a comparison could be to a Dockerfile, minus containerization, with waaay more expressiveness and reproducibility.

    There are tools you can add on to get Nix to do what Docker Compose does:

    Arion is a Nix frontend for Docker Compose. You’re still using Docker Compose, but it layers on the extra expressiveness and reproducibility of Nix flakes, or other kinds of Nix expressions.

    process compose flake is similar, but instead of Docker Compose it is a frontend for Process Compose. You get a similar result, but without containerization. That can potentially avoid the need to run in a VM on non-Linux systems that don’t natively support containers.




  • It’s possible (and I think advisable) to set your flake nixos config to set the system flake registry to point to the same nixpkgs revision that your flake uses. The nixos-starter-configs standard template has two lines that do this:

    # Opinionated: make flake registry and nix path match flake inputs
    registry = lib.mapAttrs (_: flake: {inherit flake;}) flakeInputs;
    nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
    

    That actually adds all of your flake inputs to the system flake registry. So for example if in addition to your nixpkgs input you also have an input you named nixpkgs-unstable then can also reference that with stuff like nix shell. For example:

    nix shell nixpkgs#hello nixpkgs-unstable#cowsay