ModemManager

Revision as of 17:29, 25 February 2026 by Manu (talk | contribs) (Removed information that is accurate only if the other services defined under the section "Unreliable suspend/resume" are enabled.)

ModemManager is a DBus-activated daemon which manages cellular modems (2G, 3G, 4G and 5G) and establishes cellular data connections.[1]

Configuration

It is possible to enable the modem with:

networking.modemmanager.enable = true;

A good rule of thumb is to use NetworkManager as much as possible and rely on ModemManager functionality directly only when necessary (e.g., when having to insert a PIN to unlock the SIM card).

Tips and Tricks

Prevention of WWAN connection on boot

Due concerns related to tracking and privacy, it may be wished to never automatically establish a cellular connection on boot. The custom Serviced service below allows to achieve exactly this goal.

# Ensure that the modem does not establish a cellular connection
# on boot.
systemd.services.NetworkManager-radio-wwan-initial-setup = {
  description = "Disable WWAN radio on first ModemManager start";
  wantedBy = [ "multi-user.target" ];
  before = [ "ModemManager.service" ];
  after = [ "NetworkManager.service" ]; # Wait for NetworkManager
  requires = [ "NetworkManager.service" ]; # Ensure NetworkManager is running

  serviceConfig = {
    Type = "oneshot";
    RemainAfterExit = true; # The service won't run again on successive ModemManager activations.
    ExecStart = "${pkgs.networkmanager}/bin/nmcli radio wwan off";
  };
};

Note that the state of the cellular connection will be retained even if ModemManager is restarted (as long as the system has not been rebooted).

Troubleshooting

Unreliable suspend/resume

Some modems, such as the Fibocom 350-GL, cause the system to automatically wake up from sleep. The behavior is inconsistent: sometimes it happens immediately, but it can also happen a few seconds or minutes after the machine is in suspended. Other times the machine correctly stays in sleep mode and does not wake up. Other times a loop of continuous suspensions and resumes is experienced.

As a workaround to the unreliability of such WWAN modules, the user needs to stop the ModemManager service before sleep. At this point, suspend should no longer cause the problems mentioned above. The user needs to restart the ModemManager service once the computer is resumed if they intend to connect to cellular data.

It is possible to automate this behavior by creating tailored Systemd services:

# Stop ModemManager before sleep.target is reached
# due to a bug with the WWAN module, which otherwise
# wakes up the system immediately after suspend.
systemd.services.ModemManager-stop-before-sleep = {
  wantedBy = [ "sleep.target" ];
  before = [ "sleep.target" ];

  serviceConfig = {
    Type = "oneshot";
    ExecStart = "${pkgs.systemd}/bin/systemctl stop ModemManager.service";
  };
};

# Restart ModemManager shortly after resume from suspend.
# This way the modem can be easily enabled within
# the desktop environment's networks' applet or the CLI.
systemd.services.ModemManager-restart-after-resume = {
  description = "Restart ModemManager after resume";
  wantedBy = [ "post-resume.target" ];
  after = [
    "systemd-suspend.service"
    "systemd-hibernate.service"
    "systemd-hybrid-sleep.service"
  ];

  serviceConfig = {
    Type = "oneshot";
    ExecStart = "${pkgs.systemd}/bin/systemctl restart ModemManager.service";
  };
};