AI warning: użyte. GLM-5.2

Snippety głównie do wykorzystania przez LLMy, przepycha cały ruch z apki dekstopowej odpalonej przez wrapper przez interfejs wireguardowy w dedykowanym ns. Użyte do odpalenia stremio bez dostępu do sieci spoza mullvada.

mullvad-pl.nix

# mullvad-pl network namespace + Mullvad WireGuard tunnel.
#
# Shared VPN-confinement infrastructure for the per-app modules under
# hosts/tiwi/apps/. Each confined app (popcorntime, stremio, ...) launches into
# the "mullvad-pl" namespace, so only its traffic egresses via Mullvad.
# Tailscale lives in the init namespace and is never touched.
#
# Built with a manual systemd service rather than networking.wireguard.interfaces
# because tiwi uses networking.useNetworkd, with which the namespace/preSetup/
# postShutdown options are incompatible.
{ pkgs, ... }:
let
  netns = "mullvad-pl";
in
{
  # Bring up the mullvad-pl netns + Mullvad WireGuard interface.
  # Interface is created in the init namespace (so its UDP socket egresses via
  # br0 to the endpoint) and then moved into the netns. All addressing and the
  # default route live only inside the netns; Tailscale is never touched.
  systemd.services.mullvad-pl-netns = {
    description = "Mullvad WireGuard tunnel in the ${netns} network namespace";
    wants = [ "network-online.target" ];
    after = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];
    path = with pkgs; [
      iproute2
      wireguard-tools
      kmod
    ];
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
    };
    script = ''
      set -euo pipefail
      ip netns del ${netns} 2>/dev/null || true
      ip netns add ${netns}
      ip -n ${netns} link set lo up
 
      # Create and configure WireGuard in the init namespace, then move it.
      modprobe wireguard || true
      ip link add ${netns} type wireguard
      wg set ${netns} \
        private-key /etc/nixos/secrets/mullvad-privatekey \
        peer nJEWae9GebEY7yJONXQ1j4gbURV4QULjx388woAlbDs= \
        endpoint 45.134.212.79:51820 \
        allowed-ips 0.0.0.0/0,::/0 \
        persistent-keepalive 25
      ip link set ${netns} netns ${netns}
 
      ip -n ${netns} address add 10.65.101.79/32 dev ${netns}
      ip -n ${netns} -6 address add fc00:bbbb:bbbb:bb01::2:654e/128 dev ${netns}
      ip -n ${netns} link set ${netns} up mtu 1420
      ip -n ${netns} route add default dev ${netns}
      ip -n ${netns} -6 route add default dev ${netns}
    '';
    postStop = ''
      ip netns del ${netns} 2>/dev/null || true
    '';
  };
 
  # DNS inside the namespace (ip-netns bind-mounts this over /etc/resolv.conf).
  environment.etc."netns/${netns}/resolv.conf".text = "nameserver 10.64.0.1\n";
}
 

_netns-app.nix

# Helper: confine a GUI app to the mullvad-pl network namespace.
#
# This file is NOT a NixOS module on its own -- it is a function that RETURNS
# one. Usage from a sibling app module:
#
#   { pkgs, ... }: {
#     imports = [ (import ./_netns-app.nix {
#       name = "stremio";
#       package = pkgs.stremio-linux-shell;
#       binary = "stremio";
#       desktopName = "Stremio (VPN)";
#       icon = "${pkgs.stremio-linux-shell}/share/icons/hicolor/scalable/apps/com.stremio.Stremio.svg";
#       extraArgs = [ "--password-store=basic" ];
#     }) ];
#   }
#
# Requires the "mullvad-pl" netns to exist (created by services/mullvad-pl.nix).
{
  name,
  package,
  desktopName,
  icon,
  binary ? package.meta.mainProgram or name,
  extraArgs ? [ ],
  startupWMClass ? null,
  netns ? "mullvad-pl",
  user ? "tv",
}:
{ pkgs, lib, ... }:
let
  launcherName = "${name}-vpn";
  binPath = "${package}/bin/${binary}";
  extraFlags = lib.optionalString (extraArgs != [ ]) " ${lib.concatStringsSep " " extraArgs}";
 
  # Self-elevating launcher: ${user} -> sudo (NOPASSWD+SETENV, scoped to this
  # binary) -> ip netns exec ${netns} setpriv ${user} -> app.
  #
  # `sudo -E` carries ${user}'s full Plasma/Wayland session env across the
  # privilege boundary; `setpriv` drops to ${user} WITHOUT PAM env-rewriting
  # (runuser rewrites via PAM), so the whole environment survives into the
  # namespace -- nothing is hand-set (XDG_RUNTIME_DIR, WAYLAND_DISPLAY, DBUS_*,
  # the correct PULSE_SERVER all come from the inherited session).
  # Fail-closed: if the namespace/tunnel is down, the app has no network.
  launcher = pkgs.writeShellScriptBin launcherName ''
    set -euo pipefail
    if [ "$(id -u)" -ne 0 ]; then
      exec sudo -n -E -- /run/current-system/sw/bin/${launcherName} "$@"
    fi
    exec ${pkgs.iproute2}/bin/ip netns exec ${netns} \
      ${pkgs.util-linux}/bin/setpriv \
        --reuid="$(id -u ${user})" --regid="$(id -g ${user})" --init-groups \
        --inh-caps=-all \
        -- ${binPath}${extraFlags} "$@"
  '';
 
  # The app without its own (leaking) .desktop, so only our VPN entry shows.
  package-noDesktop = pkgs.symlinkJoin {
    name = "${name}-nodesktop";
    paths = [ package ];
    postBuild = "rm -f $out/share/applications/*.desktop";
  };
 
  desktopItem = pkgs.makeDesktopItem ({
    inherit desktopName icon;
    name = launcherName;
    exec = launcherName;
    comment = "${desktopName} (traffic routed via the ${netns} VPN namespace)";
    categories = [
      "AudioVideo"
      "Video"
    ];
    type = "Application";
  } // lib.optionalAttrs (startupWMClass != null) { inherit startupWMClass; });
in
{
  environment.systemPackages = [
    package-noDesktop
    launcher
    desktopItem
  ];
 
  # ${user} may launch only this one wrapper as root, no password.
  security.sudo.extraRules = [
    {
      users = [ user ];
      runAs = "root";
      commands = [
        {
          command = "/run/current-system/sw/bin/${launcherName}";
          options = [
            "NOPASSWD"
            "SETENV"
          ];
        }
      ];
    }
  ];
}
 

stremio.nix

# Stremio client, confined to the mullvad-pl VPN namespace.
# Uses stremio-linux-shell (Rust + CEF + libmpv); the old qt5 stremio was
# removed from nixpkgs on 2026-02-11. Requires nixpkgs.config.allowUnfree
# (its bundled server.js is unfree).
{ pkgs, ... }:
let
  stremio = pkgs.stremio-linux-shell.overrideAttrs (old: {
    patches = (old.patches or [ ]) ++ [ ./stremio-zoom.patch ];
  });
in
{
  imports = [
    (import ./_netns-app.nix {
      name = "stremio";
      package = stremio;
      binary = "stremio";
      desktopName = "Stremio (VPN)";
      icon = "${stremio}/share/icons/hicolor/scalable/apps/com.stremio.Stremio.svg";
      startupWMClass = "stremio";
      extraArgs = [ "--password-store=basic" ];
    })
  ];
}