1{ config, lib, pkgs, ... }:
2
3with pkgs;
4with lib;
5
6let
7 cfg = config.services.connman;
8 configFile = pkgs.writeText "connman.conf" ''
9 [General]
10 NetworkInterfaceBlacklist=${concatStringsSep "," cfg.networkInterfaceBlacklist}
11
12 ${cfg.extraConfig}
13 '';
14 enableIwd = cfg.wifi.backend == "iwd";
15in {
16
17 imports = [
18 (mkRenamedOptionModule [ "networking" "connman" ] [ "services" "connman" ])
19 ];
20
21 ###### interface
22
23 options = {
24
25 services.connman = {
26
27 enable = mkOption {
28 type = types.bool;
29 default = false;
30 description = lib.mdDoc ''
31 Whether to use ConnMan for managing your network connections.
32 '';
33 };
34
35 enableVPN = mkOption {
36 type = types.bool;
37 default = true;
38 description = lib.mdDoc ''
39 Whether to enable ConnMan VPN service.
40 '';
41 };
42
43 extraConfig = mkOption {
44 type = types.lines;
45 default = "";
46 description = lib.mdDoc ''
47 Configuration lines appended to the generated connman configuration file.
48 '';
49 };
50
51 networkInterfaceBlacklist = mkOption {
52 type = with types; listOf str;
53 default = [ "vmnet" "vboxnet" "virbr" "ifb" "ve" ];
54 description = lib.mdDoc ''
55 Default blacklisted interfaces, this includes NixOS containers interfaces (ve).
56 '';
57 };
58
59 wifi = {
60 backend = mkOption {
61 type = types.enum [ "wpa_supplicant" "iwd" ];
62 default = "wpa_supplicant";
63 description = lib.mdDoc ''
64 Specify the Wi-Fi backend used.
65 Currently supported are {option}`wpa_supplicant` or {option}`iwd`.
66 '';
67 };
68 };
69
70 extraFlags = mkOption {
71 type = with types; listOf str;
72 default = [ ];
73 example = [ "--nodnsproxy" ];
74 description = lib.mdDoc ''
75 Extra flags to pass to connmand
76 '';
77 };
78
79 package = mkOption {
80 type = types.package;
81 description = lib.mdDoc "The connman package / build flavor";
82 default = connman;
83 defaultText = literalExpression "pkgs.connman";
84 example = literalExpression "pkgs.connmanFull";
85 };
86
87 };
88
89 };
90
91 ###### implementation
92
93 config = mkIf cfg.enable {
94
95 assertions = [{
96 assertion = !config.networking.useDHCP;
97 message = "You can not use services.connman with networking.useDHCP";
98 }{
99 # TODO: connman seemingly can be used along network manager and
100 # connmanFull supports this - so this should be worked out somehow
101 assertion = !config.networking.networkmanager.enable;
102 message = "You can not use services.connman with networking.networkmanager";
103 }];
104
105 environment.systemPackages = [ cfg.package ];
106
107 systemd.services.connman = {
108 description = "Connection service";
109 wantedBy = [ "multi-user.target" ];
110 after = [ "syslog.target" ] ++ optional enableIwd "iwd.service";
111 requires = optional enableIwd "iwd.service";
112 serviceConfig = {
113 Type = "dbus";
114 BusName = "net.connman";
115 Restart = "on-failure";
116 ExecStart = toString ([
117 "${cfg.package}/sbin/connmand"
118 "--config=${configFile}"
119 "--nodaemon"
120 ] ++ optional enableIwd "--wifi=iwd_agent"
121 ++ cfg.extraFlags);
122 StandardOutput = "null";
123 };
124 };
125
126 systemd.services.connman-vpn = mkIf cfg.enableVPN {
127 description = "ConnMan VPN service";
128 wantedBy = [ "multi-user.target" ];
129 after = [ "syslog.target" ];
130 before = [ "connman.service" ];
131 serviceConfig = {
132 Type = "dbus";
133 BusName = "net.connman.vpn";
134 ExecStart = "${cfg.package}/sbin/connman-vpnd -n";
135 StandardOutput = "null";
136 };
137 };
138
139 systemd.services.net-connman-vpn = mkIf cfg.enableVPN {
140 description = "D-BUS Service";
141 serviceConfig = {
142 Name = "net.connman.vpn";
143 before = [ "connman.service" ];
144 ExecStart = "${cfg.package}/sbin/connman-vpnd -n";
145 User = "root";
146 SystemdService = "connman-vpn.service";
147 };
148 };
149
150 networking = {
151 useDHCP = false;
152 wireless = {
153 enable = mkIf (!enableIwd) true;
154 dbusControlled = true;
155 iwd = mkIf enableIwd {
156 enable = true;
157 };
158 };
159 networkmanager.enable = false;
160 };
161 };
162}