diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index dcefd1c51a7..fcbac4c7f54 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 a1bb9b89f38..08b232272ff 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 00000000000..b079cb22730 --- /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"; + }; + }; + }; +}