265 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{ config, lib, pkgs, ... }:
 | 
						|
 | 
						|
with lib;
 | 
						|
 | 
						|
let
 | 
						|
  cfg = config.services.asterisk;
 | 
						|
 | 
						|
  asteriskUser = "asterisk";
 | 
						|
  asteriskGroup = "asterisk";
 | 
						|
 | 
						|
  varlibdir = "/var/lib/asterisk";
 | 
						|
  spooldir = "/var/spool/asterisk";
 | 
						|
  logdir = "/var/log/asterisk";
 | 
						|
 | 
						|
  # Add filecontents from files of useTheseDefaultConfFiles to confFiles, do not override
 | 
						|
  defaultConfFiles = subtractLists (attrNames cfg.confFiles) cfg.useTheseDefaultConfFiles;
 | 
						|
  allConfFiles =
 | 
						|
    cfg.confFiles //
 | 
						|
    builtins.listToAttrs (map (x: { name = x;
 | 
						|
                                    value = builtins.readFile (cfg.package + "/etc/asterisk/" + x); })
 | 
						|
                              defaultConfFiles);
 | 
						|
 | 
						|
  asteriskEtc = pkgs.stdenv.mkDerivation
 | 
						|
  ((mapAttrs' (name: value: nameValuePair
 | 
						|
        # Fudge the names to make bash happy
 | 
						|
        ((replaceChars ["."] ["_"] name) + "_")
 | 
						|
        (value)
 | 
						|
      ) allConfFiles) //
 | 
						|
  {
 | 
						|
    confFilesString = concatStringsSep " " (
 | 
						|
      attrNames allConfFiles
 | 
						|
    );
 | 
						|
 | 
						|
    name = "asterisk-etc";
 | 
						|
 | 
						|
    # Default asterisk.conf file
 | 
						|
    # (Notice that astetcdir will be set to the path of this derivation)
 | 
						|
    asteriskConf = ''
 | 
						|
      [directories]
 | 
						|
      astetcdir => /etc/asterisk
 | 
						|
      astmoddir => ${cfg.package}/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 => ${cfg.package}/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
 | 
						|
          <literal>asterisk.conf</literal> 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
 | 
						|
          <literal>.conf</literal>) in the Asterisk configuration directory.
 | 
						|
 | 
						|
          Note that if you want to change <literal>asterisk.conf</literal>, it
 | 
						|
          is preferable to use the <option>services.asterisk.extraConfig</option>
 | 
						|
          option over this option. If <literal>"asterisk.conf"</literal> is
 | 
						|
          specified with the <option>confFiles</option> option (not recommended),
 | 
						|
          you must be prepared to set your own <literal>astetcdir</literal>
 | 
						|
          path.
 | 
						|
 | 
						|
          See
 | 
						|
          <link xlink:href="http://www.asterisk.org/community/documentation"/>
 | 
						|
          for more examples of what is possible here.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      useTheseDefaultConfFiles = mkOption {
 | 
						|
        default = [ "ari.conf" "acl.conf" "agents.conf" "amd.conf" "calendar.conf" "cdr.conf" "cdr_syslog.conf" "cdr_custom.conf" "cel.conf" "cel_custom.conf" "cli_aliases.conf" "confbridge.conf" "dundi.conf" "features.conf" "hep.conf" "iax.conf" "pjsip.conf" "pjsip_wizard.conf" "phone.conf" "phoneprov.conf" "queues.conf" "res_config_sqlite3.conf" "res_parking.conf" "statsd.conf" "udptl.conf" "unistim.conf" ];
 | 
						|
        type = types.listOf types.str;
 | 
						|
        example = [ "sip.conf" "dundi.conf" ];
 | 
						|
        description = ''Sets these config files to the default content. The default value for
 | 
						|
          this option contains all necesscary files to avoid errors at startup.
 | 
						|
          This does not override settings via <option>services.asterisk.confFiles</option>.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
 | 
						|
      extraArguments = mkOption {
 | 
						|
        default = [];
 | 
						|
        type = types.listOf types.str;
 | 
						|
        example =
 | 
						|
          [ "-vvvddd" "-e" "1024" ];
 | 
						|
        description = ''
 | 
						|
          Additional command line arguments to pass to Asterisk.
 | 
						|
        '';
 | 
						|
      };
 | 
						|
      package = mkOption {
 | 
						|
        type = types.package;
 | 
						|
        default = pkgs.asterisk;
 | 
						|
        defaultText = "pkgs.asterisk";
 | 
						|
        description = "The Asterisk package to use.";
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = mkIf cfg.enable {
 | 
						|
    environment.systemPackages = [ cfg.package ];
 | 
						|
 | 
						|
    environment.etc.asterisk.source = asteriskEtc;
 | 
						|
 | 
						|
    users.extraUsers.asterisk =
 | 
						|
      { name = asteriskUser;
 | 
						|
        group = asteriskGroup;
 | 
						|
        uid = config.ids.uids.asterisk;
 | 
						|
        description = "Asterisk daemon user";
 | 
						|
        home = varlibdir;
 | 
						|
      };
 | 
						|
 | 
						|
    users.extraGroups.asterisk =
 | 
						|
      { name = asteriskGroup;
 | 
						|
        gid = config.ids.gids.asterisk;
 | 
						|
      };
 | 
						|
 | 
						|
    systemd.services.asterisk = {
 | 
						|
      description = ''
 | 
						|
        Asterisk PBX server
 | 
						|
      '';
 | 
						|
 | 
						|
      wantedBy = [ "multi-user.target" ];
 | 
						|
 | 
						|
      # Do not restart, to avoid disruption of running calls. Restart unit by yourself!
 | 
						|
      restartIfChanged = false;
 | 
						|
 | 
						|
      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
 | 
						|
            mkdir -p "$d"
 | 
						|
            cp --recursive ${cfg.package}/"$d"/* "$d"/
 | 
						|
            chown --recursive ${asteriskUser}:${asteriskGroup} "$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
 | 
						|
          "${cfg.package}/bin/asterisk -U ${asteriskUser} -C /etc/asterisk/asterisk.conf ${argString} -F";
 | 
						|
        ExecReload = ''${cfg.package}/bin/asterisk -x "core reload"
 | 
						|
          '';
 | 
						|
        Type = "forking";
 | 
						|
        PIDFile = "/var/run/asterisk/asterisk.pid";
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
}
 |