nixos/networkmanager: split modemmanager into a separate module (#316824)

This commit is contained in:
misuzu 2024-12-20 13:06:35 +02:00 committed by GitHub
commit a01b0bf2fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 322 additions and 189 deletions

View file

@ -30,6 +30,8 @@
- [MaryTTS](https://github.com/marytts/marytts), an open-source, multilingual text-to-speech synthesis system written in pure Java. Available as [services.marytts](options.html#opt-services.marytts).
- [networking.modemmanager](options.html#opt-networking.modemmanager) has been split out of [networking.networkmanager](options.html#opt-networking.networkmanager). NetworkManager still enables ModemManager by default, but options exist now to run NetworkManager without ModemManager.
- [Conduwuit](https://conduwuit.puppyirl.gay/), a federated chat server implementing the Matrix protocol, forked from Conduit. Available as [services.conduwuit](#opt-services.conduwuit.enable).
- [Traccar](https://www.traccar.org/), a modern GPS Tracking Platform. Available as [services.traccar](#opt-services.traccar.enable).

View file

@ -1137,6 +1137,7 @@
./services/networking/miredo.nix
./services/networking/mjpg-streamer.nix
./services/networking/mmsd.nix
./services/networking/modemmanager.nix
./services/networking/monero.nix
./services/networking/morty.nix
./services/networking/mosquitto.nix

View file

@ -0,0 +1,97 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.networking.modemmanager;
in
{
meta = {
maintainers = lib.teams.freedesktop.members;
};
options = with lib; {
networking.modemmanager = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to use ModemManager to manage modem devices.
This is usually used by some higher layer manager such as NetworkManager
but can be used standalone especially if using a modem for non-IP
connectivity (e.g. GPS).
'';
};
package = mkPackageOption pkgs "modemmanager" { };
fccUnlockScripts = mkOption {
type = types.listOf (
types.submodule {
options = {
id = mkOption {
type = types.str;
description = "vid:pid of either the PCI or USB vendor and product ID";
};
path = mkOption {
type = types.path;
description = "Path to the unlock script";
};
};
}
);
default = [ ];
example = literalExpression ''[{ id = "03f0:4e1d"; path = "''${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/03f0:4e1d"; }]'';
description = ''
List of FCC unlock scripts to enable on the system, behaving as described in
https://modemmanager.org/docs/modemmanager/fcc-unlock/#integration-with-third-party-fcc-unlock-tools.
'';
};
};
};
config = lib.mkIf cfg.enable {
environment.etc = builtins.listToAttrs (
map (
e:
lib.nameValuePair "ModemManager/fcc-unlock.d/${e.id}" {
source = e.path;
}
) cfg.fccUnlockScripts
);
systemd.services.ModemManager = {
aliases = [ "dbus-org.freedesktop.ModemManager1.service" ];
path = lib.optionals (cfg.fccUnlockScripts != [ ]) [
pkgs.libqmi
pkgs.libmbim
];
};
/*
[modem-manager]
Identity=unix-group:networkmanager
Action=org.freedesktop.ModemManager*
ResultAny=yes
ResultInactive=no
ResultActive=yes
*/
security.polkit.enable = true;
security.polkit.extraConfig = ''
polkit.addRule(function(action, subject) {
if (
subject.isInGroup("networkmanager")
&& action.id.indexOf("org.freedesktop.ModemManager") == 0
)
{ return polkit.Result.YES; }
});
'';
environment.systemPackages = [ cfg.package ];
systemd.packages = [ cfg.package ];
services.dbus.packages = [ cfg.package ];
services.udev.packages = [ cfg.package ];
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@ -15,14 +20,10 @@ let
plugins = "keyfile";
inherit (cfg) dhcp dns;
# If resolvconf is disabled that means that resolv.conf is managed by some other module.
rc-manager =
if config.networking.resolvconf.enable then "resolvconf"
else "unmanaged";
rc-manager = if config.networking.resolvconf.enable then "resolvconf" else "unmanaged";
};
keyfile = {
unmanaged-devices =
if cfg.unmanaged == [ ] then null
else lib.concatStringsSep ";" cfg.unmanaged;
unmanaged-devices = if cfg.unmanaged == [ ] then null else lib.concatStringsSep ";" cfg.unmanaged;
};
logging = {
audit = config.security.audit.enable;
@ -43,32 +44,29 @@ let
ResultAny=yes
ResultInactive=no
ResultActive=yes
[modem-manager]
Identity=unix-group:networkmanager
Action=org.freedesktop.ModemManager*
ResultAny=yes
ResultInactive=no
ResultActive=yes
*/
polkitConf = ''
polkit.addRule(function(action, subject) {
if (
subject.isInGroup("networkmanager")
&& (action.id.indexOf("org.freedesktop.NetworkManager.") == 0
|| action.id.indexOf("org.freedesktop.ModemManager") == 0
))
&& action.id.indexOf("org.freedesktop.NetworkManager.") == 0
)
{ return polkit.Result.YES; }
});
'';
ns = xs: pkgs.writeText "nameservers" (
concatStrings (map (s: "nameserver ${s}\n") xs)
);
ns = xs: pkgs.writeText "nameservers" (concatStrings (map (s: "nameserver ${s}\n") xs));
overrideNameserversScript = pkgs.writeScript "02overridedns" ''
#!/bin/sh
PATH=${with pkgs; makeBinPath [ gnused gnugrep coreutils ]}
PATH=${
with pkgs;
makeBinPath [
gnused
gnugrep
coreutils
]
}
tmp=$(mktemp)
sed '/nameserver /d' /etc/resolv.conf > $tmp
grep 'nameserver ' /etc/resolv.conf | \
@ -84,7 +82,15 @@ let
};
macAddressOptWifi = mkOption {
type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" "stable-ssid" ]);
type = types.either types.str (
types.enum [
"permanent"
"preserve"
"random"
"stable"
"stable-ssid"
]
);
default = "preserve";
example = "00:11:22:33:44:55";
description = ''
@ -100,7 +106,14 @@ let
};
macAddressOptEth = mkOption {
type = types.either types.str (types.enum [ "permanent" "preserve" "random" "stable" ]);
type = types.either types.str (
types.enum [
"permanent"
"preserve"
"random"
"stable"
]
);
default = "preserve";
example = "00:11:22:33:44:55";
description = ''
@ -114,9 +127,9 @@ let
'';
};
packages = [
pkgs.modemmanager
pkgs.networkmanager
packages =
[
cfg.package
]
++ cfg.plugins
++ lib.optionals (!delegateWireless && !enableIwd) [
@ -148,12 +161,18 @@ in
'';
};
package = mkPackageOption pkgs "networkmanager" { };
connectionConfig = mkOption {
type = with types; attrsOf (nullOr (oneOf [
type =
with types;
attrsOf (
nullOr (oneOf [
bool
int
str
]));
])
);
default = { };
description = ''
Configuration for the [connection] section of NetworkManager.conf.
@ -205,9 +224,7 @@ in
check =
p:
lib.assertMsg
(types.package.check p
&& p ? networkManagerPlugin
&& lib.isString p.networkManagerPlugin)
(types.package.check p && p ? networkManagerPlugin && lib.isString p.networkManagerPlugin)
''
Package ${p.name}, is not a NetworkManager plug-in.
Those need to have a networkManagerPlugin attribute.
@ -223,7 +240,10 @@ in
};
dhcp = mkOption {
type = types.enum [ "dhcpcd" "internal" ];
type = types.enum [
"dhcpcd"
"internal"
];
default = "internal";
description = ''
Which program (or internal library) should be used for DHCP.
@ -231,7 +251,14 @@ in
};
logLevel = mkOption {
type = types.enum [ "OFF" "ERR" "WARN" "INFO" "DEBUG" "TRACE" ];
type = types.enum [
"OFF"
"ERR"
"WARN"
"INFO"
"DEBUG"
"TRACE"
];
default = "WARN";
description = ''
Set the default logging verbosity level.
@ -262,7 +289,10 @@ in
macAddress = macAddressOptWifi;
backend = mkOption {
type = types.enum [ "wpa_supplicant" "iwd" ];
type = types.enum [
"wpa_supplicant"
"iwd"
];
default = "wpa_supplicant";
description = ''
Specify the Wi-Fi backend used for the device.
@ -289,7 +319,12 @@ in
};
dns = mkOption {
type = types.enum [ "default" "dnsmasq" "systemd-resolved" "none" ];
type = types.enum [
"default"
"dnsmasq"
"systemd-resolved"
"none"
];
default = "default";
description = ''
Set the DNS (`resolv.conf`) processing mode.
@ -304,7 +339,8 @@ in
};
dispatcherScripts = mkOption {
type = types.listOf (types.submodule {
type = types.listOf (
types.submodule {
options = {
source = mkOption {
type = types.path;
@ -324,7 +360,8 @@ in
'';
};
};
});
}
);
default = [ ];
example = literalExpression ''
[ {
@ -358,28 +395,10 @@ in
'';
};
fccUnlockScripts = mkOption {
type = types.listOf (types.submodule {
options = {
id = mkOption {
type = types.str;
description = "vid:pid of either the PCI or USB vendor and product ID";
};
path = mkOption {
type = types.path;
description = "Path to the unlock script";
};
};
});
default = [ ];
example = literalExpression ''[{ id = "03f0:4e1d"; path = "''${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/03f0:4e1d"; }]'';
description = ''
List of FCC unlock scripts to enable on the system, behaving as described in
https://modemmanager.org/docs/modemmanager/fcc-unlock/#integration-with-third-party-fcc-unlock-tools.
'';
};
ensureProfiles = {
profiles = with lib.types; mkOption {
profiles =
with lib.types;
mkOption {
type = attrsOf (submodule {
freeformType = ini.type;
@ -473,14 +492,13 @@ in
+ settings.main.no-auto-default = "*";
};
```
''
)
'')
(mkRemovedOptionModule [ "networking" "networkmanager" "enableFccUnlock" ] ''
This option was removed, because using bundled FCC unlock scripts is risky,
might conflict with vendor-provided unlock scripts, and should
be a conscious decision on a per-device basis.
Instead it's recommended to use the
`networking.networkmanager.fccUnlockScripts` option.
`networking.modemmanager.fccUnlockScripts` option.
'')
(mkRemovedOptionModule [ "networking" "networkmanager" "dynamicHosts" ] ''
This option was removed because allowing (multiple) regular users to
@ -493,9 +511,12 @@ in
(mkRemovedOptionModule [ "networking" "networkmanager" "firewallBackend" ] ''
This option was removed as NixOS is now using iptables-nftables-compat even when using iptables, therefore Networkmanager now uses the nftables backend unconditionally.
'')
(mkRenamedOptionModule
[ "networking" "networkmanager" "fccUnlockScripts" ]
[ "networking" "modemmanager" "fccUnlockScripts" ]
)
];
###### implementation
config = mkIf cfg.enable {
@ -512,7 +533,8 @@ in
hardware.wirelessRegulatoryDatabase = true;
environment.etc = {
environment.etc =
{
"NetworkManager/NetworkManager.conf".source = configFile;
# The networkmanager-l2tp plugin expects /etc/ipsec.secrets to include /etc/ipsec.d/ipsec.nm-l2tp.secrets;
@ -521,27 +543,28 @@ in
include ipsec.d/ipsec.nm-l2tp.secrets
'';
}
// builtins.listToAttrs (map
(pkg: nameValuePair "NetworkManager/${pkg.networkManagerPlugin}" {
// builtins.listToAttrs (
map (
pkg:
nameValuePair "NetworkManager/${pkg.networkManagerPlugin}" {
source = "${pkg}/lib/NetworkManager/${pkg.networkManagerPlugin}";
})
cfg.plugins)
// builtins.listToAttrs (map
(e: nameValuePair "ModemManager/fcc-unlock.d/${e.id}" {
source = e.path;
})
cfg.fccUnlockScripts)
// optionalAttrs (cfg.appendNameservers != [ ] || cfg.insertNameservers != [ ])
{
}
) cfg.plugins
)
// optionalAttrs (cfg.appendNameservers != [ ] || cfg.insertNameservers != [ ]) {
"NetworkManager/dispatcher.d/02overridedns".source = overrideNameserversScript;
}
// listToAttrs (lib.imap1
(i: s:
{
name = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
value = { mode = "0544"; inherit (s) source; };
})
cfg.dispatcherScripts);
// listToAttrs (
lib.imap1 (i: s: {
name = "NetworkManager/dispatcher.d/${
dispatcherTypesSubdirMap.${s.type}
}03userscript${lib.fixedWidthNumber 4 i}";
value = {
mode = "0544";
inherit (s) source;
};
}) cfg.dispatcherScripts
);
environment.systemPackages = packages;
@ -590,17 +613,19 @@ in
wantedBy = [ "network-online.target" ];
};
systemd.services.ModemManager = {
aliases = [ "dbus-org.freedesktop.ModemManager1.service" ];
path = lib.optionals (cfg.fccUnlockScripts != []) [ pkgs.libqmi pkgs.libmbim ];
};
systemd.services.NetworkManager-dispatcher = {
wantedBy = [ "network.target" ];
restartTriggers = [ configFile overrideNameserversScript ];
restartTriggers = [
configFile
overrideNameserversScript
];
# useful binaries for user-specified hooks
path = [ pkgs.iproute2 pkgs.util-linux pkgs.coreutils ];
path = [
pkgs.iproute2
pkgs.util-linux
pkgs.coreutils
];
aliases = [ "dbus-org.freedesktop.nm-dispatcher.service" ];
};
@ -609,16 +634,18 @@ in
wantedBy = [ "multi-user.target" ];
before = [ "network-online.target" ];
after = [ "NetworkManager.service" ];
script = let
script =
let
path = id: "/run/NetworkManager/system-connections/${id}.nmconnection";
in ''
in
''
mkdir -p /run/NetworkManager/system-connections
'' + lib.concatMapStringsSep "\n"
(profile: ''
''
+ lib.concatMapStringsSep "\n" (profile: ''
${pkgs.envsubst}/bin/envsubst -i ${ini.generate (lib.escapeShellArg profile.n) profile.v} > ${path (lib.escapeShellArg profile.n)}
'') (lib.mapAttrsToList (n: v: { inherit n v; }) cfg.ensureProfiles.profiles)
+ ''
${pkgs.networkmanager}/bin/nmcli connection reload
${cfg.package}/bin/nmcli connection reload
'';
serviceConfig = {
EnvironmentFile = cfg.ensureProfiles.environmentFiles;
@ -654,13 +681,18 @@ in
})
{
modemmanager.enable = lib.mkDefault true;
networkmanager.connectionConfig = {
"ethernet.cloned-mac-address" = cfg.ethernet.macAddress;
"wifi.cloned-mac-address" = cfg.wifi.macAddress;
"wifi.powersave" =
if cfg.wifi.powersave == null then null
else if cfg.wifi.powersave then 3
else 2;
if cfg.wifi.powersave == null then
null
else if cfg.wifi.powersave then
3
else
2;
};
}
];
@ -670,7 +702,8 @@ in
security.polkit.enable = true;
security.polkit.extraConfig = polkitConf;
services.dbus.packages = packages
services.dbus.packages =
packages
++ optional cfg.enableStrongSwan pkgs.strongswanNM
++ optional (cfg.dns == "dnsmasq") pkgs.dnsmasq;