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"; + }; + }; + }; +} diff --git a/pkgs/servers/asterisk/default.nix b/pkgs/servers/asterisk/default.nix new file mode 100644 index 00000000000..c37292d385f --- /dev/null +++ b/pkgs/servers/asterisk/default.nix @@ -0,0 +1,61 @@ +{ stdenv, fetchurl, fetchgit, jansson, libxml2, libxslt, ncurses, openssl, sqlite, utillinux }: + +stdenv.mkDerivation rec { + name = "asterisk-${version}"; + version = "13.3.2"; + + src = fetchurl { + url = "http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-${version}.tar.gz"; + sha256 = "19dafvy6ch4v8949bjim64fff456k78156m30dy2yvhm94m5k1zz"; + }; + + # Note that these sounds are included with the release tarball. They are + # provided here verbatim for the convenience of anyone wanting to build + # Asterisk from other sources. + coreSounds = fetchurl { + url = http://downloads.asterisk.org/pub/telephony/sounds/releases/asterisk-core-sounds-en-gsm-1.4.26.tar.gz; + sha256 = "2300e3ed1d2ded6808a30a6ba71191e7784710613a5431afebbd0162eb4d5d73"; + }; + mohSounds = fetchurl { + url = http://downloads.asterisk.org/pub/telephony/sounds/releases/asterisk-moh-opsound-wav-2.03.tar.gz; + sha256 = "449fb810d16502c3052fedf02f7e77b36206ac5a145f3dacf4177843a2fcb538"; + }; + # TODO: Sounds for other languages could be added here + + buildInputs = [ jansson libxml2 libxslt ncurses openssl sqlite utillinux ]; + + patches = [ + # Disable downloading of sound files (we will fetch them + # ourselves if needed). + ./disable-download.patch + + # We want the Makefile to install the default /var skeleton + # under ${out}/var but we also want to use /var at runtime. + # This patch changes the runtime behavior to look for state + # directories in /var rather than ${out}/var. + ./runtime-vardirs.patch + ]; + + # Use the following preConfigure section when building Asterisk from sources + # other than the release tarball. +# preConfigure = '' +# ln -s ${coreSounds} sounds/asterisk-core-sounds-en-gsm-1.4.26.tar.gz +# ln -s ${mohSounds} sounds/asterisk-moh-opsound-wav-2.03.tar.gz +# ''; + + # The default libdir is $PREFIX/usr/lib, which causes problems when paths + # compiled into Asterisk expect ${out}/usr/lib rather than ${out}/lib. + configureFlags = "--libdir=\${out}/lib"; + + postInstall = '' + # Install sample configuration files for this version of Asterisk + make samples + ''; + + meta = with stdenv.lib; { + description = "Software implementation of a telephone private branch exchange (PBX)"; + homepage = http://www.asterisk.org/; + license = licenses.gpl2; + maintainers = with maintainers; [ auntie ]; + }; +} diff --git a/pkgs/servers/asterisk/disable-download.patch b/pkgs/servers/asterisk/disable-download.patch new file mode 100644 index 00000000000..8b15ecdfaaa --- /dev/null +++ b/pkgs/servers/asterisk/disable-download.patch @@ -0,0 +1,12 @@ +diff -ruN asterisk-13.2.0/sounds/Makefile asterisk-13.2.0-patched/sounds/Makefile +--- asterisk-13.2.0/sounds/Makefile 2014-09-09 14:01:11.000000000 -0600 ++++ asterisk-13.2.0-patched/sounds/Makefile 2015-03-31 16:12:00.549133670 -0600 +@@ -89,7 +89,7 @@ + ) && touch "$(1)$(if $(3),/$(3),)/$$@"; \ + fi + +-asterisk-$(2)$(if $(3),-$(3),)-%.tar.gz: have_download ++asterisk-$(2)$(if $(3),-$(3),)-%.tar.gz: + ifneq ($(SOUNDS_CACHE_DIR),) + $(CMD_PREFIX) \ + if test ! -f "$(1)$(if $(3),/$(3),)/.$$(subst .tar.gz,,$$@)"; then \ diff --git a/pkgs/servers/asterisk/runtime-vardirs.patch b/pkgs/servers/asterisk/runtime-vardirs.patch new file mode 100644 index 00000000000..dfc00186d13 --- /dev/null +++ b/pkgs/servers/asterisk/runtime-vardirs.patch @@ -0,0 +1,50 @@ +diff -rupN asterisk-13.3.2/build_tools/make_defaults_h asterisk-13.3.2-patched/build_tools/make_defaults_h +--- asterisk-13.3.2/build_tools/make_defaults_h 2012-01-30 14:21:16.000000000 -0700 ++++ asterisk-13.3.2-patched/build_tools/make_defaults_h 2015-04-15 19:07:46.760351155 -0600 +@@ -1,4 +1,13 @@ + #!/bin/sh ++ ++ASTLOGDIR=/var/log/asterisk ++ASTVARRUNDIR=/var/run/asterisk ++ASTVARLIBDIR=/var/lib/asterisk ++ASTDBDIR=${ASTVARLIBDIR} ++ASTDATADIR=${ASTVARLIBDIR} ++AGI_DIR=${ASTDATADIR}/agi-bin ++ASTSPOOLDIR=/var/spool/asterisk ++ + cat << END + /* + * defaults.h +@@ -9,21 +18,21 @@ cat << END + + #define DEFAULT_CONFIG_DIR "${INSTALL_PATH}${ASTETCDIR}" + #define DEFAULT_MODULE_DIR "${INSTALL_PATH}${ASTMODDIR}" +-#define DEFAULT_AGI_DIR "${INSTALL_PATH}${AGI_DIR}" +-#define DEFAULT_LOG_DIR "${INSTALL_PATH}${ASTLOGDIR}" ++#define DEFAULT_AGI_DIR "${AGI_DIR}" ++#define DEFAULT_LOG_DIR "${ASTLOGDIR}" + +-#define DEFAULT_RUN_DIR "${INSTALL_PATH}${ASTVARRUNDIR}" +-#define DEFAULT_SOCKET "${INSTALL_PATH}${ASTVARRUNDIR}/asterisk.ctl" +-#define DEFAULT_PID "${INSTALL_PATH}${ASTVARRUNDIR}/asterisk.pid" ++#define DEFAULT_RUN_DIR "${ASTVARRUNDIR}" ++#define DEFAULT_SOCKET "${ASTVARRUNDIR}/asterisk.ctl" ++#define DEFAULT_PID "${ASTVARRUNDIR}/asterisk.pid" + +-#define DEFAULT_VAR_DIR "${INSTALL_PATH}${ASTVARLIBDIR}" +-#define DEFAULT_DB "${INSTALL_PATH}${ASTDBDIR}/astdb" ++#define DEFAULT_VAR_DIR "${ASTVARLIBDIR}" ++#define DEFAULT_DB "${ASTDBDIR}/astdb" + +-#define DEFAULT_DATA_DIR "${INSTALL_PATH}${ASTDATADIR}" +-#define DEFAULT_KEY_DIR "${INSTALL_PATH}${ASTDATADIR}/keys" ++#define DEFAULT_DATA_DIR "${ASTDATADIR}" ++#define DEFAULT_KEY_DIR "${ASTDATADIR}/keys" + +-#define DEFAULT_SPOOL_DIR "${INSTALL_PATH}${ASTSPOOLDIR}" +-#define DEFAULT_TMP_DIR "${INSTALL_PATH}${ASTSPOOLDIR}/tmp" ++#define DEFAULT_SPOOL_DIR "${ASTSPOOLDIR}" ++#define DEFAULT_TMP_DIR "${ASTSPOOLDIR}/tmp" + + #define DEFAULT_SBIN_DIR "${INSTALL_PATH}${ASTSBINDIR}" + END diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index af2507320c0..dd09411733a 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -8250,6 +8250,8 @@ let apcupsd = callPackage ../servers/apcupsd { }; + asterisk = callPackage ../servers/asterisk { }; + sabnzbd = callPackage ../servers/sabnzbd { }; bind = callPackage ../servers/dns/bind { };