From e4bcbab2240bbb1fef4c420fcf8fb6a17590aeae Mon Sep 17 00:00:00 2001 From: Colin Date: Sun, 2 Jun 2024 09:48:17 +0000 Subject: [PATCH] hosts: networking: switch to using nixos NetworkManager/ModemManager/etc, just patched for hardening --- hosts/common/net/default.nix | 5 +- hosts/common/net/modemmanager.nix | 60 ++++++ hosts/common/net/networkmanager.nix | 166 ++++++++++++++++ hosts/common/programs/assorted.nix | 2 + hosts/common/programs/default.nix | 3 - hosts/common/programs/eg25-control.nix | 2 +- hosts/common/programs/modemmanager.nix | 90 --------- hosts/common/programs/networkmanager.nix | 230 ----------------------- hosts/common/programs/sway/default.nix | 1 - hosts/common/programs/wpa_supplicant.nix | 80 -------- 10 files changed, 233 insertions(+), 406 deletions(-) create mode 100644 hosts/common/net/modemmanager.nix create mode 100644 hosts/common/net/networkmanager.nix delete mode 100644 hosts/common/programs/modemmanager.nix delete mode 100644 hosts/common/programs/networkmanager.nix delete mode 100644 hosts/common/programs/wpa_supplicant.nix diff --git a/hosts/common/net/default.nix b/hosts/common/net/default.nix index 6531cf0b..a7588e66 100644 --- a/hosts/common/net/default.nix +++ b/hosts/common/net/default.nix @@ -4,6 +4,8 @@ imports = [ ./dns.nix ./hostnames.nix + ./modemmanager.nix + ./networkmanager.nix ./upnp.nix ./vpn.nix ]; @@ -57,7 +59,8 @@ # # i don't use these, and notably they drag in huge dependency sets and don't cross compile well. # e.g. openconnect drags in webkitgtk (for SSO)! - networking.networkmanager.plugins = lib.mkForce []; + # networking.networkmanager.plugins = lib.mkForce []; + networking.networkmanager.enableDefaultPlugins = false; # keyfile.path = where networkmanager should look for connection credentials networking.networkmanager.settings.keyfile.path = "/var/lib/NetworkManager/system-connections"; diff --git a/hosts/common/net/modemmanager.nix b/hosts/common/net/modemmanager.nix new file mode 100644 index 00000000..634d1a31 --- /dev/null +++ b/hosts/common/net/modemmanager.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: +{ + networking.modemmanager.package = pkgs.modemmanager-split.daemon.overrideAttrs (upstream: { + # patch to allow the dbus endpoints to be owned by networkmanager user + postInstall = (upstream.postInstall or "") + '' + substitute $out/share/dbus-1/system.d/org.freedesktop.ModemManager1.conf \ + $out/share/dbus-1/system.d/networkmanager-org.freedesktop.ModemManager1.conf \ + --replace-fail 'user="root"' 'group="networkmanager"' + ''; + }); + + systemd.services.ModemManager = { + # aliases = [ "dbus-org.freedesktop.ModemManager1.service" ]; + # after = [ "polkit.service" ]; + # requires = [ "polkit.service" ]; + wantedBy = [ "network.target" ]; #< default is `multi-user.target`, somehow it doesn't auto-start with that... + # path = [ "/run/current-system/sw" ]; #< so it can find `sanebox` + + # serviceConfig.Type = "dbus"; + # serviceConfig.BusName = "org.freedesktop.ModemManager1"; + + # only if started with `--debug` does mmcli let us issue AT commands like + # `mmcli --modem any --command=` + serviceConfig.ExecStart = [ + "" # first blank line is to clear the upstream `ExecStart` field. + "${lib.getExe' config.networking.modemmanager.package "ModemManager"} --debug" + ]; + # --debug sets DEBUG level logging: so reset + serviceConfig.ExecStartPost = "${lib.getExe config.sane.programs.mmcli.package} --set-logging=INFO"; + + # v this is what upstream ships + # serviceConfig.Restart = "on-abort"; + # serviceConfig.StandardError = "null"; + # serviceConfig.CapabilityBoundingSet = "CAP_SYS_ADMIN CAP_NET_ADMIN"; + # serviceConfig.ProtectSystem = true; + # serviceConfig.ProtectHome = true; + # serviceConfig.PrivateTmp = true; + # serviceConfig.RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR"; + # serviceConfig.NoNewPrivileges = true; + + # TODO: sandbox more aggressively + # - CAP_NET_ADMIN *only*? + # it needs these paths: + # - # "/" + # - "/dev" #v modem-power + net are not enough + # - # "/dev/modem-power" + # - # "/dev/net" + # - "/proc" + # - # /run #v can likely be reduced more + # - "/run/dbus" + # - "/run/NetworkManager" + # - "/run/resolvconf" + # - "/run/systemd" + # - "/run/udev" + # - "/sys" + }; + + # so that ModemManager can discover when the modem appears + # services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ]; +} diff --git a/hosts/common/net/networkmanager.nix b/hosts/common/net/networkmanager.nix new file mode 100644 index 00000000..31531856 --- /dev/null +++ b/hosts/common/net/networkmanager.nix @@ -0,0 +1,166 @@ +{ config, pkgs, ... }: +let + networkmanager = pkgs.networkmanager.overrideAttrs (upstream: { + src = pkgs.fetchFromGitea { + domain = "git.uninsane.org"; + owner = "colin"; + repo = "NetworkManager"; + # patched to fix polkit permissions (with `nmcli`) when NetworkManager runs as user networkmanager + rev = "dev-sane-1.46.0"; + hash = "sha256-S5ZiOfCpwtVVVO+DP6OPodJqzSc/LW4waI42DRkT+RA="; + }; + # patches = []; + }); + # split the package into `daemon` and `nmcli` outputs, because the networkmanager *service* + # doesn't need `nmcli`/`nmtui` tooling + networkmanager-split = pkgs.networkmanager-split.override { inherit networkmanager; }; +in { + networking.networkmanager.enable = true; + networking.networkmanager.enableDefaultPlugins = false; + networking.networkmanager.package = networkmanager-split.daemon.overrideAttrs (upstream: { + # postPatch = (upstream.postPatch or "") + '' + # substituteInPlace src/{core/org.freedesktop.NetworkManager,nm-dispatcher/nm-dispatcher}.conf --replace-fail \ + # 'user="root"' 'user="networkmanager"' + # ''; + postInstall = (upstream.postInstall or "") + '' + # allow the bus to owned by either root or networkmanager users + # use the group here, that way ordinary users can be elevated to control networkmanager + # (via e.g. `nmcli`) + for f in org.freedesktop.NetworkManager.conf nm-dispatcher.conf ; do + substitute $out/share/dbus-1/system.d/$f \ + $out/share/dbus-1/system.d/networkmanager-$f \ + --replace-fail 'user="root"' 'group="networkmanager"' + done + + # remove unused services to prevent any unexpected interactions + rm $out/etc/systemd/system/{nm-cloud-setup.service,nm-cloud-setup.timer,nm-priv-helper.service} + ''; + }); + + # fixup the services to run as `networkmanager` and with less permissions + systemd.services.NetworkManager = { + serviceConfig.RuntimeDirectory = "NetworkManager"; #< tells systemd to create /run/NetworkManager + # serviceConfig.StateDirectory = "NetworkManager"; #< tells systemd to create /var/lib/NetworkManager + serviceConfig.User = "networkmanager"; + serviceConfig.Group = "networkmanager"; + serviceConfig.AmbientCapabilities = [ + # "CAP_DAC_OVERRIDE" + "CAP_NET_ADMIN" + "CAP_NET_RAW" + "CAP_NET_BIND_SERVICE" #< this *does* seem to be necessary, though i don't understand why. DHCP? + # "CAP_SYS_MODULE" + "CAP_AUDIT_WRITE" #< allow writing to the audit log + # "CAP_KILL" + ]; + # TODO: it needs these directories: + # - "/proc/net" + # - "/proc/sys/net" + # - "/run/NetworkManager" + # - "/run/systemd" # for trust-dns-nmhook + # - "/run/udev" + # - # "/run/wg-home.priv" + # - "/sys/class" #< TODO: specify this more precisely + # - "/sys/devices" + # - "/var/lib/NetworkManager" + # - "/var/lib/trust-dns" #< for trust-dns-nmhook + # - "/run/systemd" + }; + + systemd.services.NetworkManager-wait-online = { + serviceConfig.User = "networkmanager"; + serviceConfig.Group = "networkmanager"; + }; + + # fix NetworkManager-dispatcher to actually run as a daemon, + # and sandbox it a bit + systemd.services.NetworkManager-dispatcher = { + after = [ "trust-dns-localhost.service" ]; #< so that /var/lib/trust-dns will exist + # serviceConfig.ExecStart = [ + # "" # first blank line is to clear the upstream `ExecStart` field. + # "${cfg.package}/libexec/nm-dispatcher --persist" # --persist is needed for it to actually run as a daemon + # ]; + # serviceConfig.Restart = "always"; + # serviceConfig.RestartSec = "1s"; + serviceConfig.User = "networkmanager"; + serviceConfig.Group = "networkmanager"; + # TODO: it needs access only to the above mentioned directories + }; + + # harden wpa_supplicant (used by NetworkManager) + systemd.services.wpa_supplicant = { + serviceConfig.User = "networkmanager"; + serviceConfig.Group = "networkmanager"; + serviceConfig.AmbientCapabilities = [ + "CAP_NET_ADMIN" + "CAP_NET_RAW" + ]; + # TODO: it needs only these paths: + # - "/dev/net" + # - "/dev/rfkill" + # - "/proc/sys/net" + # - "/sys/class/net" + # - "/sys/devices" + # - "/run/systemd" + }; + + networking.networkmanager.settings = { + # wifi.backend = "wpa_supplicant"; + # wifi.scan-rand-mac-address = true; + + # logging.audit = false; + logging.level = "INFO"; + + # main.dhcp = "internal"; + main.dns = if config.services.resolved.enable then + "systemd-resolved" + else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then + "none" + else + "internal" + ; + main.systemd-resolved = false; + }; + environment.etc."NetworkManager/system-connections".source = "/var/lib/NetworkManager/system-connections"; + + # allow networkmanager to control systemd-resolved, + # which it needs to do to apply new DNS settings when using systemd-resolved. + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if (subject.isInGroup("networkmanager") && action.id.indexOf("org.freedesktop.resolve1.") == 0) { + return polkit.Result.YES; + } + }); + ''; + + users.users.networkmanager = { + isSystemUser = true; + group = "networkmanager"; + extraGroups = [ "trust-dns" ]; + }; + + # there is, unfortunately, no proper interface by which to plumb wpa_supplicant into the NixOS service, except by overlay. + nixpkgs.overlays = [(self: super: { + wpa_supplicant = super.wpa_supplicant.overrideAttrs (upstream: { + # postPatch = (upstream.postPatch or "") + '' + # substituteInPlace wpa_supplicant/dbus/dbus-wpa_supplicant.conf --replace-fail \ + # 'user="root"' 'user="networkmanager"' + # ''; + postInstall = (upstream.postInstall or "") + '' + substitute $out/share/dbus-1/system.d/dbus-wpa_supplicant.conf \ + $out/share/dbus-1/system.d/networkmanager-wpa_supplicant.conf \ + --replace-fail 'user="root"' 'group="networkmanager"' + ''; + + postFixup = (upstream.postFixup or "") + '' + # nixpkgs wpa_supplicant generates a dbus file which has a path like + # /nix/store/abc-wpa_supplicant/nix/store/abc-wpa_supplicant/sbin/... + # upstreaming status: + substituteInPlace $out/share/dbus-1/system-services/* --replace-fail \ + "$out$out" "$out" + + # remove unused services to avoid unexpected interactions + rm $out/etc/systemd/system/{wpa_supplicant-nl80211@,wpa_supplicant-wired@,wpa_supplicant@}.service + ''; + }); + })]; +} diff --git a/hosts/common/programs/assorted.nix b/hosts/common/programs/assorted.nix index b2227cf4..6e47eb6d 100644 --- a/hosts/common/programs/assorted.nix +++ b/hosts/common/programs/assorted.nix @@ -71,12 +71,14 @@ in "man-pages" "man-pages-posix" # "miniupnpc" + "mmcli" "nano" # "ncdu" # ncurses disk usage. doesn't cross compile (zig) "neovim" "netcat" "nethogs" "nmap" + "nmcli" "nvme-cli" # nvme # "openssl" "parted" diff --git a/hosts/common/programs/default.nix b/hosts/common/programs/default.nix index 7b19be82..7259d85c 100644 --- a/hosts/common/programs/default.nix +++ b/hosts/common/programs/default.nix @@ -81,13 +81,11 @@ ./mepo.nix ./mimeo ./mmcli.nix - ./modemmanager.nix ./mopidy.nix ./mpv ./msmtp.nix ./nautilus.nix ./neovim.nix - ./networkmanager.nix ./newsflash.nix ./nheko.nix ./nicotine-plus.nix @@ -144,7 +142,6 @@ ./wine.nix ./wireplumber.nix ./wireshark.nix - ./wpa_supplicant.nix ./wvkbd.nix ./xarchiver.nix ./xdg-desktop-portal.nix diff --git a/hosts/common/programs/eg25-control.nix b/hosts/common/programs/eg25-control.nix index 3d110900..0379933f 100644 --- a/hosts/common/programs/eg25-control.nix +++ b/hosts/common/programs/eg25-control.nix @@ -4,7 +4,7 @@ let in { sane.programs.eg25-control = { - suggestedPrograms = [ "modemmanager" ]; + suggestedPrograms = [ "mmcli" ]; services.eg25-control-powered = { description = "eg25-control-powered: power to the Qualcomm eg25 modem used by PinePhone"; diff --git a/hosts/common/programs/modemmanager.nix b/hosts/common/programs/modemmanager.nix deleted file mode 100644 index 297ee43b..00000000 --- a/hosts/common/programs/modemmanager.nix +++ /dev/null @@ -1,90 +0,0 @@ -{ config, lib, pkgs, ... }: -let - cfg = config.sane.programs.modemmanager; -in -{ - sane.programs.modemmanager = { - packageUnwrapped = pkgs.modemmanager-split.daemon.overrideAttrs (upstream: { - postInstall = (upstream.postInstall or "") + '' - substitute $out/share/dbus-1/system.d/org.freedesktop.ModemManager1.conf \ - $out/share/dbus-1/system.d/networkmanager-org.freedesktop.ModemManager1.conf \ - --replace-fail 'user="root"' 'group="networkmanager"' - ''; - - meta = upstream.meta // { - mainProgram = "ModemManager"; - }; - }); - # mmcli needs /run/current-system/sw/share/dbus-1 files to function - enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true; - - suggestedPrograms = [ "mmcli" ]; - - # bwrap sandboxing works, but requires the real user to be root. - # landlock sandboxing works, and allows the real user to be someone else (like `networkmanager`). - # non-root is very important, because of how many things in e.g. /dev are r/w based on uid=0. - # TODO: have the services run as `networkmanager` user - sandbox.method = "bwrap"; - # sandbox.method = "landlock"; - sandbox.wrapperType = "inplace"; #< .pc files, GIR files with absolute paths, - sandbox.net = "all"; #< needed for modem bringup - # sandbox.isolatePids = false; - sandbox.capabilities = [ - "net_admin" - "net_raw" - ]; - sandbox.extraPaths = lib.warn "TODO: modemmanager: sandbox more aggressively" [ - # "/" - "/dev" #v modem-power + net are not enough - # "/dev/modem-power" - # "/dev/net" - "/proc" - # /run #v can likely be reduced more - "/run/dbus" - "/run/NetworkManager" - "/run/resolvconf" - "/run/systemd" - "/run/udev" - "/sys" - # "/var" - ]; - }; - - networking.modemmanager = { - enable = cfg.enabled; - package = cfg.package; - }; - - systemd.services.ModemManager = lib.mkIf cfg.enabled { - # aliases = [ "dbus-org.freedesktop.ModemManager1.service" ]; - # after = [ "polkit.service" ]; - # requires = [ "polkit.service" ]; - # wantedBy = [ "network.target" ]; - path = [ "/run/current-system/sw" ]; #< so it can find `sanebox` - - # serviceConfig.Type = "dbus"; - # serviceConfig.BusName = "org.freedesktop.ModemManager1"; - - # only if started with `--debug` does mmcli let us issue AT commands like - # `mmcli --modem any --command=` - serviceConfig.ExecStart = [ - "" # first blank line is to clear the upstream `ExecStart` field. - "${lib.getExe cfg.package} --debug" - ]; - # --debug sets DEBUG level logging: so reset - serviceConfig.ExecStartPost = "${lib.getExe config.sane.programs.mmcli.package} --set-logging=INFO"; - - # v this is what upstream ships - # serviceConfig.Restart = "on-abort"; - # serviceConfig.StandardError = "null"; - # serviceConfig.CapabilityBoundingSet = "CAP_SYS_ADMIN CAP_NET_ADMIN"; - # serviceConfig.ProtectSystem = true; - # serviceConfig.ProtectHome = true; - # serviceConfig.PrivateTmp = true; - # serviceConfig.RestrictAddressFamilies = "AF_NETLINK AF_UNIX AF_QIPCRTR"; - # serviceConfig.NoNewPrivileges = true; - }; - - # so that ModemManager can discover when the modem appears - # services.udev.packages = lib.mkIf cfg.enabled [ cfg.package ]; -} diff --git a/hosts/common/programs/networkmanager.nix b/hosts/common/programs/networkmanager.nix deleted file mode 100644 index beab97c8..00000000 --- a/hosts/common/programs/networkmanager.nix +++ /dev/null @@ -1,230 +0,0 @@ -# Network Manager: -# i manage this myself because the nixos service is not flexible enough. -# - it unconditionally puts modemmanager onto the system path, preventing me from patching modemmanager's service file (without an overlay). -# -# XXX: it's normal to see error messages on an ethernet-only host, even when using nixos' official networkmanager service: -# - `Couldn't initialize supplicant interface: Failed to D-Bus activate wpa_supplicant service` -{ config, lib, pkgs, ... }: -let - cfg = config.sane.programs.networkmanager; - networkmanager = pkgs.networkmanager.overrideAttrs (upstream: { - src = pkgs.fetchFromGitea { - domain = "git.uninsane.org"; - owner = "colin"; - repo = "NetworkManager"; - rev = "dev-sane-1.46.0"; - hash = "sha256-S5ZiOfCpwtVVVO+DP6OPodJqzSc/LW4waI42DRkT+RA="; - }; - # patches = []; - }); - networkmanager-split = pkgs.networkmanager-split.override { inherit networkmanager; }; -in -{ - config = lib.mkMerge [ - { - sane.programs.networkmanager = { - packageUnwrapped = networkmanager-split.daemon.overrideAttrs (upstream: { - # postPatch = (upstream.postPatch or "") + '' - # substituteInPlace src/{core/org.freedesktop.NetworkManager,nm-dispatcher/nm-dispatcher}.conf --replace-fail \ - # 'user="root"' 'user="networkmanager"' - # ''; - postInstall = (upstream.postInstall or "") + '' - # allow the bus to owned by either root or networkmanager users - # use the group here, that way ordinary users can be elevated to control networkmanager - # (via e.g. `nmcli`) - for f in org.freedesktop.NetworkManager.conf nm-dispatcher.conf ; do - substitute $out/share/dbus-1/system.d/$f \ - $out/share/dbus-1/system.d/networkmanager-$f \ - --replace-fail 'user="root"' 'group="networkmanager"' - done - - # remove unused services to prevent any unexpected interactions - rm $out/etc/systemd/system/{nm-cloud-setup.service,nm-cloud-setup.timer,nm-priv-helper.service} - ''; - }); - - suggestedPrograms = [ "nmcli" "wpa_supplicant" ]; - enableFor.system = lib.mkIf (builtins.any (en: en) (builtins.attrValues cfg.enableFor.user)) true; - - # this contains both the NetworkManager service and the NetworkManager-dispatcher service - # the latter of which calls a lot of user code. - # as a result, this needs all the perms which my hook in modules/services/trust-dns/trust-dns-nmhook needs. - sandbox.method = "landlock"; - sandbox.capabilities = [ - # "dac_override" - "net_admin" - "net_raw" - "net_bind_service" #< TODO: is this needed? why? (DNS?) - # "sys_module" - "audit_write" #< allow writing to the audit log - # "kill" - ]; - sandbox.extraPaths = [ - "/proc/net" - "/proc/sys/net" - "/run/NetworkManager" - "/run/systemd" # for trust-dns-nmhook - "/run/udev" - # "/run/wg-home.priv" - "/sys/class" #< TODO: specify this more precisely - "/sys/devices" - "/var/lib/NetworkManager" - "/var/lib/trust-dns" #< for trust-dns-nmhook - ]; - - sandbox.whitelistDbus = [ "system" ]; - }; - } - - (lib.mkIf cfg.enabled { - # add to systemd.packages so we get the service file it ships, then override what we need to customize (taken from nixpkgs) - # systemd.packages = [ cfg.package ]; - networking.networkmanager.enable = true; - networking.networkmanager.enableDefaultPlugins = false; - networking.networkmanager.package = cfg.package; - systemd.services.NetworkManager = { - # wantedBy = [ "network.target" ]; - aliases = [ "dbus-org.freedesktop.NetworkManager.service" ]; - - path = [ "/run/current-system/sw" ]; #< so it can find `sanebox` - serviceConfig.RuntimeDirectory = "NetworkManager"; #< tells systemd to create /run/NetworkManager - # serviceConfig.StateDirectory = "NetworkManager"; #< tells systemd to create /var/lib/NetworkManager - serviceConfig.User = "networkmanager"; - serviceConfig.Group = "networkmanager"; - serviceConfig.AmbientCapabilities = [ - # "CAP_DAC_OVERRIDE" - "CAP_NET_ADMIN" - "CAP_NET_RAW" - "CAP_NET_BIND_SERVICE" #< this *does* seem to be necessary, though i don't understand why. DHCP? - # "CAP_SYS_MODULE" - "CAP_AUDIT_WRITE" #< allow writing to the audit log - # "CAP_KILL" - ]; - }; - - systemd.services.NetworkManager-wait-online = { - path = [ "/run/current-system/sw" ]; #< so `nm-online` can find `sanebox` - # wantedBy = [ "network-online.target" ]; - serviceConfig.User = "networkmanager"; - serviceConfig.Group = "networkmanager"; - }; - - systemd.services.NetworkManager-dispatcher = { - # wantedBy = [ "NetworkManager.service" ]; - after = [ "trust-dns-localhost.service" ]; #< so that /var/lib/trust-dns will exist - path = [ "/run/current-system/sw" ]; #< so it can find `sanebox` - # to debug, add NM_DISPATCHER_DEBUG_LOG=1 - serviceConfig.ExecStart = [ - "" # first blank line is to clear the upstream `ExecStart` field. - "${cfg.package}/libexec/nm-dispatcher --persist" # --persist is needed for it to actually run as a daemon - ]; - serviceConfig.Restart = "always"; - serviceConfig.RestartSec = "1s"; - serviceConfig.User = "networkmanager"; - serviceConfig.Group = "networkmanager"; - }; - - networking.networkmanager.settings = { - # wifi.backend = "wpa_supplicant"; - # wifi.scan-rand-mac-address = true; - - # logging.audit = false; - logging.level = "INFO"; - - # main.dhcp = "internal"; - main.dns = if config.services.resolved.enable then - "systemd-resolved" - else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then - "none" - else - "internal" - ; - main.systemd-resolved = false; - }; - - environment.etc = { - "NetworkManager/system-connections".source = "/var/lib/NetworkManager/system-connections"; - # "NetworkManager/NetworkManager.conf".text = '' - # [device] - # # wifi.backend: wpa_supplicant or iwd - # wifi.backend=wpa_supplicant - # wifi.scan-rand-mac-address=true - - # [logging] - # audit=false - # # level: TRACE, DEBUG, INFO, WARN, ERR, OFF - # level=INFO - # # domain=... - - # [main] - # # dhcp: - # # - `internal` (default) - # # - `dhclient` (requires dhclient to be installed) - # # - `dhcpcd` (requires dhcpcd to be installed) - # dhcp=internal - # # dns: - # # - `default`: update /etc/resolv.conf with nameservers provided by the active connection - # # - `none`: NM won't update /etc/resolv.conf - # # - `systemd-resolved`: push DNS config to systemd-resolved - # # - `dnsmasq`: run a local caching nameserver - # dns=${if config.services.resolved.enable then - # "systemd-resolved" - # else if config.sane.services.trust-dns.enable && config.sane.services.trust-dns.asSystemResolver then - # "none" - # else - # "internal" - # } - # plugins=keyfile - # # rc-manager: how NM should write to /etc/resolv.conf - # # - regardless of this setting, NM will write /var/lib/NetworkManager/resolv.conf - # rc-manager=unmanaged - # # systemd-resolved: send DNS config to systemd-resolved? - # # this setting has no effect if dns="systemd-resolved"; it's supplementary, not absolute. - # systemd-resolved=false - # # debug=... (see also: NM_DEBUG env var) - # ''; - }; - - # hardware.wirelessRegulatoryDatabase = true; - # networking.useDHCP = false; - # services.udev.packages = [ cfg.package ]; - # security.polkit.enable = lib.mkDefault true; - - # security.polkit.extraConfig = lib.concatStringsSep "\n" [ - # # allow networkmanager unbounded control over modemmanager. - # # i believe this was sourced from the default nixpkgs config. - # '' - # polkit.addRule(function(action, subject) { - # if (subject.isInGroup("networkmanager") - # && ( - # action.id.indexOf("org.freedesktop.NetworkManager.") == 0 - # || action.id.indexOf("org.freedesktop.ModemManager") == 0 - # ) - # ) { - # return polkit.Result.YES; - # } - # }); - # '' - - # allow networkmanager to control systemd-resolved, - # which it needs to do to apply new DNS settings when using systemd-resolved. - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if (subject.isInGroup("networkmanager") && action.id.indexOf("org.freedesktop.resolve1.") == 0) { - return polkit.Result.YES; - } - }); - ''; - - # users.groups.networkmanager.gid = config.ids.gids.networkmanager; - users.users.networkmanager = { - isSystemUser = true; - group = "networkmanager"; - extraGroups = [ "trust-dns" ]; - }; - - # boot.kernelModules = [ "ctr" ]; #< TODO: needed (what even is this)? - # TODO: NetworkManager-ensure-profiles? - }) - ]; -} diff --git a/hosts/common/programs/sway/default.nix b/hosts/common/programs/sway/default.nix index a8ec788e..c00a4bfb 100644 --- a/hosts/common/programs/sway/default.nix +++ b/hosts/common/programs/sway/default.nix @@ -140,7 +140,6 @@ in "fontconfig" # "gnome.gnome-bluetooth" # XXX(2023/05/14): broken # "gnome.gnome-control-center" # XXX(2023/06/28): depends on webkitgtk4_1 - "networkmanager" "pipewire" "playerctl" # for waybar & particularly to have playerctld running "rofi" # menu/launcher diff --git a/hosts/common/programs/wpa_supplicant.nix b/hosts/common/programs/wpa_supplicant.nix deleted file mode 100644 index 535b9bd1..00000000 --- a/hosts/common/programs/wpa_supplicant.nix +++ /dev/null @@ -1,80 +0,0 @@ -{ config, lib, pkgs, ... }: -let - cfg = config.sane.programs.wpa_supplicant; -in -{ - config = lib.mkMerge [ - { - sane.programs.wpa_supplicant = { - packageUnwrapped = pkgs.wpa_supplicant.overrideAttrs (upstream: { - # postPatch = (upstream.postPatch or "") + '' - # substituteInPlace wpa_supplicant/dbus/dbus-wpa_supplicant.conf --replace-fail \ - # 'user="root"' 'user="networkmanager"' - # ''; - postInstall = (upstream.postInstall or "") + '' - substitute $out/share/dbus-1/system.d/dbus-wpa_supplicant.conf \ - $out/share/dbus-1/system.d/networkmanager-wpa_supplicant.conf \ - --replace-fail 'user="root"' 'group="networkmanager"' - ''; - - postFixup = (upstream.postFixup or "") + '' - # nixpkgs wpa_supplicant generates a dbus file which has a path like - # /nix/store/abc-wpa_supplicant/nix/store/abc-wpa_supplicant/sbin/... - # upstreaming status: - substituteInPlace $out/share/dbus-1/system-services/* --replace-fail \ - "$out$out" "$out" - - # remove unused services to avoid unexpected interactions - rm $out/etc/systemd/system/{wpa_supplicant-nl80211@,wpa_supplicant-wired@,wpa_supplicant@}.service - ''; - }); - # bwrap sandboxing works, but requires the real user to be root. - # landlock sandboxing works, and allows the real user to be someone else (like `networkmanager`). - # non-root is very important, because of how many things in e.g. /dev are r/w based on uid=0. - # sandbox.method = "bwrap"; - sandbox.method = "landlock"; - sandbox.capabilities = [ - # see also: - "net_admin" "net_raw" - ]; - # sandbox.extraConfig = [ "--sanebox-keep-namespace" "all" ]; - sandbox.net = "all"; - sandbox.extraPaths = [ - "/dev/net" - "/dev/rfkill" - "/proc/sys/net" - "/sys/class/net" - "/sys/devices" - ]; - sandbox.whitelistDbus = [ "system" ]; - }; - } - (lib.mkIf cfg.enabled { - #v TODO: networkmanager module enforces that it install this for us... - # if i relly want to avoid that, maybe i implement some `apply` override for `environment.systemPackages`, & others - # or switch to the `iwd` backend, which is more patchable. - # services.udev.packages = [ cfg.package ]; - # systemd.packages = [ cfg.package ]; #< needs to be on systemd.packages so we get its service file - systemd.services.wpa_supplicant = { - path = [ "/run/current-system/sw" ]; #< so it can find `sanebox` - serviceConfig.User = "networkmanager"; - serviceConfig.Group = "networkmanager"; - serviceConfig.AmbientCapabilities = [ - "CAP_NET_ADMIN" - "CAP_NET_RAW" - ]; - }; - # systemd.services.wpa_supplicant = { - # aliases = [ "dbus-fi.w1.wpa_supplicant1.service" ]; - # before = [ "network.target" ]; - # wantedBy = [ "network.target" ]; - # serviceConfig = { - # Type = "dbus"; - # BusName = "fi.w1.wpa_supplicant1"; - # ExecStart = "${cfg.package}/bin/wpa_supplicant -u"; - # Restart = "always"; - # }; - # }; - }) - ]; -}