diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index dcefd1c51a7f..fcbac4c7f543 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -217,6 +217,7 @@
ihaskell = 189;
i2p = 190;
lambdabot = 191;
+ asterisk = 192;
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
@@ -411,6 +412,7 @@
ihaskell = 189;
i2p = 190;
lambdabot = 191;
+ #asterisk = 192; # unused
# When adding a gid, make sure it doesn't match an existing
# uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index a1bb9b89f38f..08b232272ffe 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -242,6 +242,7 @@
./services/network-filesystems/yandex-disk.nix
./services/networking/aiccu.nix
./services/networking/amuled.nix
+ ./services/networking/asterisk.nix
./services/networking/atftpd.nix
./services/networking/avahi-daemon.nix
./services/networking/bind.nix
diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix
new file mode 100644
index 000000000000..b079cb227303
--- /dev/null
+++ b/nixos/modules/services/networking/asterisk.nix
@@ -0,0 +1,223 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.asterisk;
+
+ asteriskUser = "asterisk";
+
+ varlibdir = "/var/lib/asterisk";
+ spooldir = "/var/spool/asterisk";
+ logdir = "/var/log/asterisk";
+
+ asteriskEtc = pkgs.stdenv.mkDerivation
+ ((mapAttrs' (name: value: nameValuePair
+ # Fudge the names to make bash happy
+ ((replaceChars ["."] ["_"] name) + "_")
+ (value)
+ ) cfg.confFiles) //
+ {
+ confFilesString = concatStringsSep " " (
+ attrNames cfg.confFiles
+ );
+
+ name = "asterisk.etc";
+
+ # Default asterisk.conf file
+ # (Notice that astetcdir will be set to the path of this derivation)
+ asteriskConf = ''
+ [directories]
+ astetcdir => @out@
+ astmoddir => ${pkgs.asterisk}/lib/asterisk/modules
+ astvarlibdir => /var/lib/asterisk
+ astdbdir => /var/lib/asterisk
+ astkeydir => /var/lib/asterisk
+ astdatadir => /var/lib/asterisk
+ astagidir => /var/lib/asterisk/agi-bin
+ astspooldir => /var/spool/asterisk
+ astrundir => /var/run/asterisk
+ astlogdir => /var/log/asterisk
+ astsbindir => ${pkgs.asterisk}/sbin
+ '';
+ extraConf = cfg.extraConfig;
+
+ # Loading all modules by default is considered sensible by the authors of
+ # "Asterisk: The Definitive Guide". Secure sites will likely want to
+ # specify their own "modules.conf" in the confFiles option.
+ modulesConf = ''
+ [modules]
+ autoload=yes
+ '';
+
+ # Use syslog for logging so logs can be viewed with journalctl
+ loggerConf = ''
+ [general]
+
+ [logfiles]
+ syslog.local0 => notice,warning,error
+ '';
+
+ buildCommand = ''
+ mkdir -p "$out"
+
+ # Create asterisk.conf, pointing astetcdir to the path of this derivation
+ echo "$asteriskConf" | sed "s|@out@|$out|g" > "$out"/asterisk.conf
+ echo "$extraConf" >> "$out"/asterisk.conf
+
+ echo "$modulesConf" > "$out"/modules.conf
+
+ echo "$loggerConf" > "$out"/logger.conf
+
+ # Config files specified in confFiles option override all other files
+ for i in $confFilesString; do
+ conf=$(echo "$i"_ | sed 's/\./_/g')
+ echo "''${!conf}" > "$out"/"$i"
+ done
+ '';
+ });
+in
+
+{
+ options = {
+ services.asterisk = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable the Asterisk PBX server.
+ '';
+ };
+
+ extraConfig = mkOption {
+ default = "";
+ type = types.lines;
+ example = ''
+ [options]
+ verbose=3
+ debug=3
+ '';
+ description = ''
+ Extra configuration options appended to the default
+ asterisk.conf file.
+ '';
+ };
+
+ confFiles = mkOption {
+ default = {};
+ type = types.attrsOf types.str;
+ example = literalExample
+ ''
+ {
+ "extensions.conf" = '''
+ [tests]
+ ; Dial 100 for "hello, world"
+ exten => 100,1,Answer()
+ same => n,Wait(1)
+ same => n,Playback(hello-world)
+ same => n,Hangup()
+
+ [softphones]
+ include => tests
+
+ [unauthorized]
+ ''';
+ "sip.conf" = '''
+ [general]
+ allowguest=no ; Require authentication
+ context=unauthorized ; Send unauthorized users to /dev/null
+ srvlookup=no ; Don't do DNS lookup
+ udpbindaddr=0.0.0.0 ; Listen on all interfaces
+ nat=force_rport,comedia ; Assume device is behind NAT
+
+ [softphone](!)
+ type=friend ; Match on username first, IP second
+ context=softphones ; Send to softphones context in
+ ; extensions.conf file
+ host=dynamic ; Device will register with asterisk
+ disallow=all ; Manually specify codecs to allow
+ allow=g722
+ allow=ulaw
+ allow=alaw
+
+ [myphone](softphone)
+ secret=GhoshevFew ; Change this password!
+ ''';
+ "logger.conf" = '''
+ [general]
+
+ [logfiles]
+ ; Add debug output to log
+ syslog.local0 => notice,warning,error,debug
+ ''';
+ }
+ '';
+ description = ''
+ Sets the content of config files (typically ending with
+ .conf) in the Asterisk configuration directory.
+
+ Note that if you want to change asterisk.conf, it
+ is preferable to use the
+ option over this option. If "asterisk.conf" is
+ specified with the option (not recommended),
+ you must be prepared to set your own astetcdir
+ path.
+
+ See
+
+ for more examples of what is possible here.
+ '';
+ };
+
+ extraArguments = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ example =
+ [ "-vvvddd" "-e" "1024" ];
+ description = ''
+ Additional command line arguments to pass to Asterisk.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ users.extraUsers = singleton
+ { name = asteriskUser;
+ uid = config.ids.uids.asterisk;
+ description = "Asterisk daemon user";
+ home = varlibdir;
+ };
+
+ systemd.services.asterisk = {
+ description = ''
+ Asterisk PBX server
+ '';
+
+ wantedBy = [ "multi-user.target" ];
+
+ preStart = ''
+ # Copy skeleton directory tree to /var
+ for d in '${varlibdir}' '${spooldir}' '${logdir}'; do
+ # TODO: Make exceptions for /var directories that likely should be updated
+ if [ ! -e "$d" ]; then
+ cp --recursive ${pkgs.asterisk}/"$d" "$d"
+ chown --recursive ${asteriskUser} "$d"
+ find "$d" -type d | xargs chmod 0755
+ fi
+ done
+ '';
+
+ serviceConfig = {
+ ExecStart =
+ let
+ # FIXME: This doesn't account for arguments with spaces
+ argString = concatStringsSep " " cfg.extraArguments;
+ in
+ "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C ${asteriskEtc}/asterisk.conf ${argString} -F";
+ Type = "forking";
+ PIDFile = "/var/run/asterisk/asterisk.pid";
+ };
+ };
+ };
+}