diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 3ccdfe8e0c0473..4e8ebd64aaf559 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -613,6 +613,7 @@
./services/networking/hylafax/default.nix
./services/networking/i2pd.nix
./services/networking/i2p.nix
+ ./services/networking/create_ap.nix
./services/networking/iodine.nix
./services/networking/iperf3.nix
./services/networking/ircd-hybrid/default.nix
diff --git a/nixos/modules/services/networking/create_ap.nix b/nixos/modules/services/networking/create_ap.nix
new file mode 100644
index 00000000000000..3d5e2da98e6828
--- /dev/null
+++ b/nixos/modules/services/networking/create_ap.nix
@@ -0,0 +1,134 @@
+{ config, lib, pkgs, ... }:
+with lib;
+
+let
+ cfg = config.services.create_ap;
+
+ valueToText =
+ let
+ conversions = {
+ string = id;
+ int = toString;
+ bool = value: if value then "1" else "0";
+ };
+ in value: conversions.${builtins.typeOf value} value;
+
+ configFile = pkgs.writeText "create_ap.conf"
+ (concatStrings (mapAttrsToList (name: value:
+ "${name}=${valueToText value}\n"
+ ) (filterAttrs (_: value: value != null) cfg.settings)));
+
+ wifiIface = cfg.settings.WIFI_IFACE;
+ inetIface = cfg.settings.INTERNET_IFACE;
+
+in {
+
+ options.services.create_ap = with types; {
+ enable = mkEnableOption "Enable Create Access Point Service";
+
+ settings = mkOption {
+ type = attrsOf (nullOr (oneOf [ str int bool ]));
+ description = ''
+ create_ap configuration, see
+ for information on supported values.
+ '';
+ example = literalExample ''
+ {
+ HIDDEN = true;
+ FREQ_BAND = 5;
+ DHCP_DNS = "1.1.1.1";
+ COUNTRY = "US";
+ }
+ '';
+ };
+
+ wifiInterface = mkOption {
+ description = ''
+ Wi-Fi interface to use (Use ip link show to list available).
+ '';
+ type = str;
+ example = "wlan0";
+ };
+
+ internetInterface = mkOption {
+ description = ''
+ Interface to use for internet connection (Use ip link show to list available).
+ '';
+ type = str;
+ example = "enp0";
+ };
+
+ ssid = mkOption {
+ description = "SSID of the access point.";
+ type = str;
+ example = "MyAccessPoint";
+ };
+
+ passphrase = mkOption {
+ description = "Passphrase to use for access point.";
+ type = str;
+ example = "12345678";
+ };
+
+ gateway = mkOption {
+ description = "IPv4 Gateway for the Access Point.";
+ type = str;
+ default = "192.168.12.1";
+ example = "10.0.0.1";
+ };
+
+ channel = mkOption {
+ type = either str int;
+ example = 1;
+ default = "default";
+ description = "WLAN Channel number.";
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ services.create_ap.settings = {
+ DAEMONIZE = false;
+ CHANNEL = mkDefault cfg.channel;
+ GATEWAY = mkDefault cfg.gateway;
+ WIFI_IFACE = mkDefault cfg.wifiInterface;
+ INTERNET_IFACE = mkDefault cfg.internetInterface;
+ SSID = mkDefault cfg.ssid;
+ PASSPHRASE = mkDefault cfg.passphrase;
+ };
+
+ environment.systemPackages = [ pkgs.create_ap ];
+
+ systemd.services.create_ap = {
+ description = "Create AP Service";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target"
+ "sys-subsystem-net-devices-${wifiIface}.device"
+ "sys-subsystem-net-devices-${inetIface}.device" ];
+ bindsTo = [ "sys-subsystem-net-devices-${wifiIface}.device"
+ "sys-subsystem-net-devices-${inetIface}.device" ];
+ serviceConfig =
+ let capabilities = [
+ "CAP_CHOWN"
+ "CAP_DAC_OVERRIDE"
+ "CAP_DAC_READ_SEARCH"
+ "CAP_KILL"
+ "CAP_NET_ADMIN"
+ "CAP_NET_RAW"
+ "CAP_NET_BIND_SERVICE"
+ ]; in {
+ KillSignal = "SIGINT";
+ Restart = "on-failure";
+ RestartSec = 5;
+ DynamicUser = true;
+ ProtectSystem = "strict";
+ ProtectHome = true;
+ # create_ap parses and updates NetworkManager.conf
+ ReadWritePaths = "-/etc/NetworkManager/";
+ AmbientCapabilities = capabilities;
+ CapabilityBoundingSet = capabilities;
+ ExecStart = "${pkgs.create_ap}/bin/create_ap --config ${configFile}";
+ };
+ };
+ };
+}