aboutsummaryrefslogtreecommitdiffstats
path: root/roles/asterisk
diff options
context:
space:
mode:
authorStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:23:43 -0500
committerStonewall Jackson <stonewall@sacredheartsc.com>2023-02-04 01:52:13 -0500
commit0261e875679f1bf63c8d689da7fc7e014597885d (patch)
tree3f19cd74a0c1070944f75437f30b098d6ef2ffcb /roles/asterisk
downloadselfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.tar.gz
selfhosted-0261e875679f1bf63c8d689da7fc7e014597885d.zip
initial commit
Diffstat (limited to 'roles/asterisk')
-rw-r--r--roles/asterisk/defaults/main.yml74
-rw-r--r--roles/asterisk/files/etc/systemd/system/asterisk.service.d/override.conf6
-rw-r--r--roles/asterisk/handlers/main.yml9
-rw-r--r--roles/asterisk/meta/main.yml4
-rw-r--r--roles/asterisk/tasks/main.yml81
-rw-r--r--roles/asterisk/templates/etc/asterisk/ari.conf.j211
-rw-r--r--roles/asterisk/templates/etc/asterisk/extensions.conf.j27
-rw-r--r--roles/asterisk/templates/etc/asterisk/http.conf.j213
-rw-r--r--roles/asterisk/templates/etc/asterisk/logger.conf.j23
-rw-r--r--roles/asterisk/templates/etc/asterisk/pjsip.conf.j228
-rw-r--r--roles/asterisk/templates/etc/asterisk/pjsip_wizard.conf.j257
-rw-r--r--roles/asterisk/templates/etc/asterisk/queues.conf.j246
-rw-r--r--roles/asterisk/templates/etc/asterisk/rtp.conf.j23
-rw-r--r--roles/asterisk/templates/etc/asterisk/voicemail.conf.j237
-rw-r--r--roles/asterisk/vars/main.yml20
15 files changed, 399 insertions, 0 deletions
diff --git a/roles/asterisk/defaults/main.yml b/roles/asterisk/defaults/main.yml
new file mode 100644
index 0000000..e7e5b74
--- /dev/null
+++ b/roles/asterisk/defaults/main.yml
@@ -0,0 +1,74 @@
+asterisk_local_nets:
+ - 10.0.0.0/8
+ - 172.16.0.0/12
+ - 192.168.0.0/16
+
+asterisk_timezone: '{{ timezone }}'
+asterisk_locale: en_US.UTF-8
+
+asterisk_fqdn: '{{ ansible_fqdn }}'
+asterisk_from_domain: '{{ email_domain }}'
+
+asterisk_rtp_port_start: 10000
+asterisk_rtp_port_end: 10999
+asterisk_sip_port: 5060
+asterisk_sip_tls_port: 5061
+
+asterisk_http_port: 8088
+asterisk_https_port: 8089
+
+asterisk_voicemail_formats:
+ - wav49
+ - gsm
+ - wav
+
+asterisk_mail_from: asterisk-noreply@{{ email_domain }}
+
+asterisk_voicemail_email_subject: 'New voicemail ${VM_MSGNUM} in mailbox ${VM_MAILBOX}'
+asterisk_voicemail_email_body: 'Hi ${VM_NAME},\n\nYou have a new voicemail in mailbox ${VM_MAILBOX}.\n\nFrom: ${VM_CALLERID}\nDate: ${VM_DATE}\nDuration: ${VM_DUR}\nMessage Number: ${VM_MSGNUM}'
+asterisk_voicemail_email_date_format: '%A, %B %d, %Y at %r'
+asterisk_voicemail_min_password: 4
+
+asterisk_voicemail_max_message_count: 100
+asterisk_voicemail_max_message_secs: 300
+asterisk_voicemail_max_greeting_secs: 60
+asterisk_voicemail_max_failed_logins: 3
+
+asterisk_sip_trunks:
+ - name: example
+ host: sip.example.com:5061
+ codecs: g722,ulaw
+ username: testuser
+ password: testpass
+ transport: tls
+ media_encryption: sdes
+
+asterisk_sip_extensions:
+ - name: 6001
+ context: from-internal
+ mailbox: 6001@default
+ cid_name: Test User
+ username: 6001
+ password: testpassword
+ codecs: g722,ulaw
+
+asterisk_queues:
+ - name: home
+ strategy: ringall
+ retry: 1
+ timeout: 30
+ members:
+ - 6001
+ - 6002
+
+asterisk_ari_users:
+ - name: nagios
+ password: nagios
+ readonly: yes
+
+asterisk_voicemail_contexts:
+ default:
+ - address: 6001
+ password: 1234
+ name: John Doe
+ email: john@example.com
diff --git a/roles/asterisk/files/etc/systemd/system/asterisk.service.d/override.conf b/roles/asterisk/files/etc/systemd/system/asterisk.service.d/override.conf
new file mode 100644
index 0000000..88f8d60
--- /dev/null
+++ b/roles/asterisk/files/etc/systemd/system/asterisk.service.d/override.conf
@@ -0,0 +1,6 @@
+[Unit]
+After=nss-lookup.target network-online.target
+
+[Service]
+Restart=on-failure
+RestartSec=4
diff --git a/roles/asterisk/handlers/main.yml b/roles/asterisk/handlers/main.yml
new file mode 100644
index 0000000..b2d74af
--- /dev/null
+++ b/roles/asterisk/handlers/main.yml
@@ -0,0 +1,9 @@
+- name: reload asterisk
+ systemd:
+ name: asterisk
+ state: reloaded
+
+- name: restart asterisk
+ systemd:
+ name: asterisk
+ state: restarted
diff --git a/roles/asterisk/meta/main.yml b/roles/asterisk/meta/main.yml
new file mode 100644
index 0000000..29230f9
--- /dev/null
+++ b/roles/asterisk/meta/main.yml
@@ -0,0 +1,4 @@
+dependencies:
+ - role: yum
+ yum_repositories: epel
+ tags: yum
diff --git a/roles/asterisk/tasks/main.yml b/roles/asterisk/tasks/main.yml
new file mode 100644
index 0000000..7bb259d
--- /dev/null
+++ b/roles/asterisk/tasks/main.yml
@@ -0,0 +1,81 @@
+- name: install packages
+ dnf:
+ name: '{{ asterisk_packages }}'
+ state: present
+
+- name: create systemd override directory
+ file:
+ path: /etc/systemd/system/asterisk.service.d
+ state: directory
+
+- name: create systemd unit override
+ copy:
+ src: etc/systemd/system/asterisk.service.d/override.conf
+ dest: /etc/systemd/system/asterisk.service.d/override.conf
+ notify: restart asterisk
+ register: asterisk_unit
+
+- name: reload systemd units
+ systemd:
+ daemon_reload: yes
+ when: asterisk_unit.changed
+
+- name: download sound files
+ unarchive:
+ src: '{{ item.url }}'
+ remote_src: yes
+ dest: /usr/share/asterisk/sounds
+ creates: '/usr/share/asterisk/sounds/hello-world.{{ item.codec }}'
+ loop: "{{ asterisk_sound_tarballs | dict2items(key_name='codec', value_name='url') }}"
+
+- name: request public TLS certificate
+ include_role:
+ name: certbot
+ vars:
+ certificate_sans: ['{{ asterisk_fqdn }}']
+ certificate_path: '{{ asterisk_certificate_path }}'
+ certificate_key_path: '{{ asterisk_certificate_key_path }}'
+ certificate_owner: asterisk
+ certificate_hook: systemctl reload asterisk
+
+- name: request internal HTTPS certificate
+ include_role:
+ name: getcert_request
+ vars:
+ certificate_sans: ['{{ ansible_fqdn }}']
+ certificate_path: '{{ asterisk_https_certificate_path }}'
+ certificate_key_path: '{{ asterisk_https_certificate_key_path }}'
+ certificate_owner: asterisk
+ certificate_hook: systemctl reload asterisk
+
+- name: generate config files
+ template:
+ src: '{{ item.src }}'
+ dest: /etc/asterisk/{{ item.path | splitext | first }}
+ owner: asterisk
+ group: asterisk
+ mode: 0640
+ loop: "{{ lookup('filetree', '../templates/etc/asterisk', wantlist=True) }}"
+ when: item.state == 'file'
+ notify: reload asterisk
+
+- name: open firewall ports
+ firewalld:
+ permanent: yes
+ immediate: yes
+ port: '{{ item }}'
+ state: enabled
+ loop:
+ - '{{ asterisk_https_port }}/tcp'
+ - '{{ asterisk_sip_port }}/tcp'
+ - '{{ asterisk_sip_port }}/udp'
+ - '{{ asterisk_sip_tls_port }}/tcp'
+ - '{{ asterisk_sip_tls_port }}/udp'
+ - '{{ asterisk_rtp_port_start }}-{{ asterisk_rtp_port_end }}/udp'
+ tags: firewalld
+
+- name: start asterisk
+ systemd:
+ name: asterisk
+ enabled: yes
+ state: started
diff --git a/roles/asterisk/templates/etc/asterisk/ari.conf.j2 b/roles/asterisk/templates/etc/asterisk/ari.conf.j2
new file mode 100644
index 0000000..cc853c4
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/ari.conf.j2
@@ -0,0 +1,11 @@
+[general]
+enabled = yes
+pretty = no
+
+{% for user in asterisk_ari_users %}
+[{{ user.name }}]
+type = user
+read_only = {{ 'yes' if (user.readonly | default(true)) else 'no' }}
+password = {{ user.password | password_hash('sha512', asterisk_password_salt, rounds=5000) }}
+password_format = crypt
+{% endfor %}
diff --git a/roles/asterisk/templates/etc/asterisk/extensions.conf.j2 b/roles/asterisk/templates/etc/asterisk/extensions.conf.j2
new file mode 100644
index 0000000..09345cf
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/extensions.conf.j2
@@ -0,0 +1,7 @@
+[public]
+exten => _X.,1,Hangup(3)
+
+[default]
+exten => _X.,1,Hangup(3)
+
+{{ asterisk_dialplan }}
diff --git a/roles/asterisk/templates/etc/asterisk/http.conf.j2 b/roles/asterisk/templates/etc/asterisk/http.conf.j2
new file mode 100644
index 0000000..d9d92a1
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/http.conf.j2
@@ -0,0 +1,13 @@
+[general]
+servername = Asterisk
+enabled = yes
+bindaddr = 127.0.0.1
+bindport = {{ asterisk_http_port }}
+enable_status = no
+tlsenable = yes
+tlsbindaddr = 0.0.0.0:{{ asterisk_https_port }}
+tlscertfile = {{ asterisk_https_certificate_path }}
+tlsprivatekey = {{ asterisk_https_certificate_key_path }}
+tlsdisablev1 = yes
+tlsdisablev11 = yes
+tlsdisablev12 = no
diff --git a/roles/asterisk/templates/etc/asterisk/logger.conf.j2 b/roles/asterisk/templates/etc/asterisk/logger.conf.j2
new file mode 100644
index 0000000..65595d1
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/logger.conf.j2
@@ -0,0 +1,3 @@
+[logfiles]
+console => verbose(3),notice,warning,error
+messages => verbose(3),notice,warning,error
diff --git a/roles/asterisk/templates/etc/asterisk/pjsip.conf.j2 b/roles/asterisk/templates/etc/asterisk/pjsip.conf.j2
new file mode 100644
index 0000000..d7dedf8
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/pjsip.conf.j2
@@ -0,0 +1,28 @@
+[transport-defaults](!)
+type = transport
+bind = 0.0.0.0
+local_net = 127.0.0.0/8
+{% for cidr in asterisk_local_nets %}
+local_net = {{ cidr }}
+{% endfor %}
+{% if asterisk_external_ip is defined %}
+external_media_address = {{ asterisk_external_ip }}
+external_signaling_address = {{ asterisk_external_ip }}
+{% endif %}
+
+[transport-udp](transport-defaults)
+protocol = udp
+
+[transport-tcp](transport-defaults)
+protocol = tcp
+
+[transport-tls](transport-defaults)
+protocol = tls
+bind = 0.0.0.0:5061
+method = tlsv1_2
+cert_file = {{ asterisk_certificate_path }}
+priv_key_file = {{ asterisk_certificate_key_path }}
+ca_list_file = {{ asterisk_ca_file }}
+verify_client = no
+verify_server = yes
+allow_reload = yes
diff --git a/roles/asterisk/templates/etc/asterisk/pjsip_wizard.conf.j2 b/roles/asterisk/templates/etc/asterisk/pjsip_wizard.conf.j2
new file mode 100644
index 0000000..67a6574
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/pjsip_wizard.conf.j2
@@ -0,0 +1,57 @@
+;;;;;;;;;;;
+; Trunks
+;;;;;;;;;;;
+
+[trunk-defaults](!)
+type = wizard
+sends_auth = yes
+sends_registrations = yes
+endpoint/rtp_symmetric = yes
+endpoint/rewrite_contact = yes
+endpoint/send_rpid = yes
+endpoint/from_domain = {{ asterisk_from_domain }}
+endpoint/allow = !all,ulaw
+aor/qualify_frequency = 30
+
+{% for trunk in asterisk_sip_trunks %}
+[{{ trunk.name }}](trunk-defaults)
+transport = transport-{{ trunk.transport | default('udp') }}
+remote_hosts = {{ trunk.host if trunk.host is string else (trunk.host | join(',')) }}
+endpoint/context = from-{{ trunk.name }}
+{% if trunk.codecs is defined %}
+endpoint/allow = !all,{{ trunk.codecs if trunk.codecs is string else (trunk.codecs | join(',')) }}
+{% endif %}
+endpoint/media_encryption = {{ trunk.media_encryption | default('no') }}
+outbound_auth/username = {{ trunk.username }}
+outbound_auth/password = {{ trunk.password }}
+
+{% endfor %}
+
+
+;;;;;;;;;;;;;
+; Extensions
+;;;;;;;;;;;;;
+
+[extension-defaults](!)
+type = wizard
+accepts_registrations = yes
+accepts_auth = yes
+aor/remove_existing = yes
+aor/qualify_frequency = 30
+endpoint/allow = !all,g722,ulaw
+endpoint/from_domain = {{ asterisk_from_domain }}
+endpoint/subscribe_context = subscribe
+
+{% for ext in asterisk_sip_extensions %}
+[{{ ext.name }}](extension-defaults)
+{% if ext.codecs is defined %}
+endpoint/allow = !all,{{ ext.codecs if ext.codecs is string else (ext.codecs | join(',')) }}
+{% endif %}
+endpoint/context = {{ ext.context }}
+endpoint/mailboxes = {{ ext.mailbox if ext.mailbox is string else (ext.mailbox | join(',')) }}
+endpoint/callerid = {{ ext.cid_name }} <{{ ext.cid_number | default(ext.name) }}>
+inbound_auth/username = {{ ext.username | default(ext.name) }}
+inbound_auth/password = {{ ext.password }}
+aor/max_contacts = {{ ext.max_contacts | default(1) }}
+
+{% endfor %}
diff --git a/roles/asterisk/templates/etc/asterisk/queues.conf.j2 b/roles/asterisk/templates/etc/asterisk/queues.conf.j2
new file mode 100644
index 0000000..badecfb
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/queues.conf.j2
@@ -0,0 +1,46 @@
+[general]
+persistentmembers = yes
+autofill = yes
+monitor-type = MixMonitor
+shared_lastcall = yes
+log_membername_as_agent = yes
+
+
+{% for queue in asterisk_queues %}
+[{{ queue.name }}]
+{% if queue.music_class is defined %}
+musicclass = {{ queue.music_class }}
+{% endif %}
+strategy = {{ queue.strategy }}
+{% if queue.context is defined %}
+context = {{ queue.context }}
+{% endif %}
+timeout = {{ queue.timeout | default(15) }}
+retry = {{ queue.retry | default(5) }}
+timeoutpriority = app
+{% if queue.weight is defined %}
+weight = {{ queue.weight }}
+{% endif %}
+{% if queue.maxlen is defined %}
+maxlen = {{ queue.maxlen }}
+{% endif %}
+announce-frequency = {{ queue.announce_frequency | default(0) }}
+min-announce-frequency = {{ queue.min_announce_frequency | default(15) }}
+announce-holdtime = {{ queue.announce_holdtime | default('no') }}
+announce-position = {{ queue.announce_position | default('no') }}
+periodic-announce-frequency = {{ queue.periodic_announce_frequency | default(0) }}
+{% if queue.peridic_announce is defined %}
+periodic-announce = {{ queue.periodic_announce if queue.periodic_announce is string else (queue.periodic_announce | join(',')) }}
+{% endif %}
+{% if queue.monitor_format is defined %}
+monitor-format = {{ queue.monitor_format if queue.monitor_format is string else (queue.montior_format | join('|')) }}
+{% endif %}
+joinempty = {{ queue.join_empty | default('yes') }}
+leavewhenempty = {{ queue.leave_when_empty | default('no') }}
+ringinuse = {{ 'yes' if (queue.ring_in_use | default(true)) else 'no' }}
+timeoutrestart = yes
+{% for ext in queue.members %}
+member => PJSIP/{{ ext }},0,{{ asterisk_sip_extensions | selectattr('name', '==', ext) | map(attribute='cid_name') | first | default('') }},PJSIP/{{ ext }}
+{% endfor %}
+
+{% endfor %}
diff --git a/roles/asterisk/templates/etc/asterisk/rtp.conf.j2 b/roles/asterisk/templates/etc/asterisk/rtp.conf.j2
new file mode 100644
index 0000000..3d4edc2
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/rtp.conf.j2
@@ -0,0 +1,3 @@
+[general]
+rtpstart={{ asterisk_rtp_port_start }}
+rtpend={{ asterisk_rtp_port_end }}
diff --git a/roles/asterisk/templates/etc/asterisk/voicemail.conf.j2 b/roles/asterisk/templates/etc/asterisk/voicemail.conf.j2
new file mode 100644
index 0000000..32b4d0a
--- /dev/null
+++ b/roles/asterisk/templates/etc/asterisk/voicemail.conf.j2
@@ -0,0 +1,37 @@
+[general]
+format={{ asterisk_voicemail_formats | join('|') }}
+
+serveremail={{ asterisk_mail_from }}
+attach=yes
+; Maximum number of messages per folder
+maxmsg={{ asterisk_voicemail_max_message_count }}
+; Maximum length of a voicemail message in seconds
+maxsecs={{ asterisk_voicemail_max_message_secs }}
+; Minimum length of a voicemail message in seconds for the message to be kept
+maxgreet={{ asterisk_voicemail_max_greeting_secs }}
+; How many milliseconds to skip forward/back when rew/ff in message playback
+skipms=3000
+; How many seconds of silence before we end the recording
+maxsilence=10
+; Silence threshold (what we consider silence: the lower, the more sensitive)
+silencethreshold=128
+; Max number of failed login attempts
+maxlogins={{ asterisk_voicemail_max_failed_logins }}
+
+emailsubject={{ asterisk_voicemail_email_subject }}
+emailbody={{ asterisk_voicemail_email_body }}
+emaildateformat={{ asterisk_voicemail_email_date_format }}
+
+tz=myzone
+locale={{ asterisk_locale }}
+minpassword={{ asterisk_voicemail_min_password }}
+
+[zonemessages]
+myzone={{ asterisk_timezone }}|'vm-received' Q 'digits/at' IMp
+
+{% for item in asterisk_voicemail_contexts | dict2items(key_name='context', value_name='mailboxes') %}
+[{{ item.context }}]
+{% for mailbox in item.mailboxes %}
+{{ mailbox.address }} => {{ mailbox.password }},{{ mailbox.name }},{{ mailbox.email if mailbox.email is string else (mailbox.email | join('|')) }},,,
+{% endfor %}
+{% endfor %}
diff --git a/roles/asterisk/vars/main.yml b/roles/asterisk/vars/main.yml
new file mode 100644
index 0000000..c4bf58a
--- /dev/null
+++ b/roles/asterisk/vars/main.yml
@@ -0,0 +1,20 @@
+asterisk_packages:
+ - asterisk
+ - asterisk-pjsip
+ - asterisk-voicemail-plain
+
+asterisk_sound_tarballs:
+ g722: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-g722-current.tar.gz
+ g729: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-g729-current.tar.gz
+ gsm: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-gsm-current.tar.gz
+ sln16: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-sln16-current.tar.gz
+ ulaw: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-ulaw-current.tar.gz
+ wav: https://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-wav-current.tar.gz
+
+asterisk_certificate_path: /etc/asterisk/asterisk.crt
+asterisk_certificate_key_path: /etc/asterisk/asterisk.key
+asterisk_https_certificate_path: /etc/pki/tls/certs/asterisk-https.crt
+asterisk_https_certificate_key_path: /etc/pki/tls/private/asterisk-https.key
+asterisk_ca_file: /etc/pki/tls/certs/ca-bundle.crt
+
+asterisk_data_dir: /var/spool/asterisk