Add Ansible template

This commit is contained in:
Mike Jones 2025-05-09 23:45:18 +01:00
parent 1115e86296
commit fa1a1138d6
Signed by: mike
GPG key ID: 1C2C25F83140EF49
22 changed files with 699 additions and 3 deletions

View file

@ -0,0 +1,4 @@
- name: Reload Asterisk
ansible.builtin.service:
name: asterisk
state: reloaded

View file

@ -0,0 +1,140 @@
- name: Check if Asterisk is already installed
ansible.builtin.stat:
path: /usr/sbin/asterisk
register: asterisk_installed
- name: Set external signaling address
ansible.builtin.set_fact:
external_signaling_address: "{{ hostvars[groups['asterisk'][0]].ansible_host }}"
when: external_signaling_address is not defined or external_signaling_address == ""
- name: Install build dependencies for Asterisk
ansible.builtin.apt:
name:
- build-essential
- libasound2-dev
- libedit-dev
- libjansson-dev
- libncurses5-dev
- libsqlite3-dev
- libssl-dev
- libxml2-dev
- uuid-dev
- wget
state: present
update_cache: true
- name: Create a directory for PJSIP source
ansible.builtin.file:
path: /usr/local/src/pjsip
state: directory
mode: '0755'
when: not asterisk_installed.stat.exists
- name: Download PJSIP source
ansible.builtin.get_url:
url: https://github.com/pjsip/pjproject/archive/refs/tags/2.14.tar.gz
dest: /usr/local/src/pjsip/pjproject-2.14.tar.gz
mode: '0644'
when: not asterisk_installed.stat.exists
- name: Extract PJSIP source
ansible.builtin.unarchive:
src: /usr/local/src/pjsip/pjproject-2.14.tar.gz
dest: /usr/local/src/pjsip/
remote_src: yes
when: not asterisk_installed.stat.exists
- name: Build and install PJSIP
ansible.builtin.shell:
cmd: |
./configure CFLAGS="-DNDEBUG -DPJ_HAS_IPV6=1" --prefix=/usr --libdir=/usr/lib
make -j$(nproc)
make install
chdir: /usr/local/src/pjsip/pjproject-2.14
args:
creates: /usr/lib/libpj.so
when: not asterisk_installed.stat.exists
- name: Download Asterisk source
ansible.builtin.get_url:
url: "https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-{{ asterisk_version }}.tar.gz"
dest: "/usr/local/src/asterisk-{{ asterisk_version }}.tar.gz"
mode: '0644'
when: not asterisk_installed.stat.exists
- name: Extract Asterisk source
ansible.builtin.unarchive:
src: "/usr/local/src/asterisk-{{ asterisk_version }}.tar.gz"
dest: /usr/local/src/
remote_src: true
creates: "/usr/local/src/asterisk-{{ asterisk_version }}"
when: not asterisk_installed.stat.exists
- name: Configure Asterisk
ansible.builtin.command:
cmd: ./configure
chdir: "{{ asterisk_src_dir }}"
when: not asterisk_installed.stat.exists
- name: Enable PJSIP modules
ansible.builtin.command:
cmd: make menuselect.makeopts
chdir: "{{ asterisk_src_dir }}"
when: not asterisk_installed.stat.exists
- name: Compile Asterisk
ansible.builtin.command:
cmd: make
chdir: "{{ asterisk_src_dir }}"
when: not asterisk_installed.stat.exists
- name: Install Asterisk
ansible.builtin.command:
cmd: make install
chdir: "{{ asterisk_src_dir }}"
when: not asterisk_installed.stat.exists
- name: Verify that PJSIP modules are installed
ansible.builtin.stat:
path: /usr/lib/asterisk/modules/chan_pjsip.so
register: pjsip_module
- name: Fail if PJSIP modules are missing
ansible.builtin.fail:
msg: "PJSIP module not found! Check if libpjsip-dev was installed before building."
when: not pjsip_module.stat.exists
- name: Install Asterisk samples
ansible.builtin.command:
cmd: make samples
chdir: "{{ asterisk_src_dir }}"
- name: Install Asterisk startup scripts
ansible.builtin.command:
cmd: make config
chdir: "{{ asterisk_src_dir }}"
- name: Enable and start the Asterisk service
ansible.builtin.service:
name: asterisk
state: started
enabled: true
- name: Deploy PJSIP configuration
ansible.builtin.template:
src: pjsip.conf.j2
dest: "{{ asterisk_config_dir }}/pjsip.conf"
owner: root
group: root
mode: '0644'
notify: Reload Asterisk
- name: Deploy extensions configuration
ansible.builtin.template:
src: extensions.conf.j2
dest: "{{ asterisk_config_dir }}/extensions.conf"
owner: root
group: root
mode: '0644'
notify: Reload Asterisk

View file

@ -0,0 +1,7 @@
[phones]
{% for extension in extensions %}
exten => {{ extension.number }},1,Dial(PJSIP/{{ extension.number }})
exten => {{ extension.number }},n,Voicemail({{ extension.voicemail }})
exten => {{ extension.number }},n,Hangup()
exten => {{ extension.number }},hint,PJSIP/{{ extension.number }}
{% endfor %}

View file

@ -0,0 +1,42 @@
[global]
realm=asterisk
external_signaling_port=5060
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
{% for extension in extensions %}
[{{ extension.number }}]
type=endpoint
transport=transport-udp
context=phones
disallow=all
allow=ulaw,alaw
aors={{ extension.number }}
auth={{ extension.number }}-auth
direct_media=no
rtp_symmetric=yes
force_rport=no
rewrite_contact=no
[{{ extension.number }}]
type=aor
max_contacts=1
remove_existing=yes
contact=sip:{{ extension.number }}@{{ extension.ipv4_address }}
qualify_frequency=10
[{{ extension.number }}-auth]
type=auth
auth_type=userpass
username={{ extension.number }}
password={{ extension.password }}
[{{ extension.number }}-identify]
type=identify
endpoint={{ extension.number }}
match={{ extension.ipv4_address }}
{% endfor %}

View file

@ -0,0 +1,4 @@
- name: Run APT updates
ansible.builtin.apt:
update_cache: yes
upgrade: dist

View file

@ -0,0 +1,4 @@
- name: Reload NGINX
ansible.builtin.service:
name: nginx
state: reloaded

View file

@ -0,0 +1,31 @@
- name: Install NGINX
ansible.builtin.package:
name: nginx
state: present
- name: Enable and start the NGINX service
ansible.builtin.service:
name: nginx
state: started
enabled: true
- name: Deploy NGINX site configuration
ansible.builtin.template:
src: default
dest: /etc/nginx/sites-available/default
mode: '0644'
notify: Reload NGINX
- name: Ensure phone XML directory exists
ansible.builtin.file:
path: /var/www/html/phones
state: directory
mode: '0755'
owner: root
group: root
- name: Upload directory.xml
ansible.builtin.template:
src: directory.xml.j2
dest: /var/www/html/phones/directory.xml
mode: '0644'

View file

@ -0,0 +1,96 @@
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /phone/ {
default_type text/xml;
autoindex off;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}

View file

@ -0,0 +1,10 @@
<CiscoIPPhoneDirectory>
<Title>Company Directory</Title>
<Prompt>Select a contact</Prompt>
{% for extension in extensions %}
<DirectoryEntry>
<Name>{{ extension.callername }}</Name>
<Telephone>{{ extension.number }}</Telephone>
</DirectoryEntry>
{% endfor %}
</CiscoIPPhoneDirectory>

View file

@ -0,0 +1,3 @@
<DIALTEMPLATE>
<TEMPLATE MATCH="*" Timeout="2"/>
</DIALTEMPLATE>

View file

@ -0,0 +1,4 @@
- name: Restart TFTP
ansible.builtin.service:
name: tftpd-hpa
state: restarted

46
roles/tftp/tasks/main.yml Normal file
View file

@ -0,0 +1,46 @@
- name: Fail if firmware files are missing
ansible.builtin.stat:
path: "roles/tftp/files/firmware/{{ item }}"
register: firmware_stat
loop: "{{ firmware_files }}"
failed_when: not firmware_stat.stat.exists
- name: Install TFTP server
ansible.builtin.package:
name: tftpd-hpa
state: present
- name: Enable and start TFTP service
ansible.builtin.service:
name: tftpd-hpa
state: started
enabled: true
- name: Configure TFTP server
ansible.builtin.template:
src: tftpd-hpa.j2
dest: /etc/default/tftpd-hpa
owner: root
group: root
mode: '0644'
notify: Restart TFTP
- name: Upload SEPMAC configuration files
ansible.builtin.template:
src: SEPMAC.cnf.xml.j2
dest: "{{ tftp_root_dir }}/{{ item.mac }}.cnf.xml"
mode: '0644'
loop: "{{ extensions }}"
- name: Upload firmware files
ansible.builtin.copy:
src: "firmware/{{ item }}"
dest: "{{ tftp_root_dir }}/{{ item }}"
mode: '0644'
loop: "{{ firmware_files }}"
- name: Upload dialplan file
ansible.builtin.copy:
src: "dialplan.xml"
dest: "{{ tftp_root_dir }}/dialplan.xml"
mode: '0644'

View file

@ -0,0 +1,159 @@
<device>
<deviceProtocol>SIP</deviceProtocol>
<sshUserId>cisco</sshUserId>
<sshPassword>cisco</sshPassword>
<ipAddressMode>0</ipAddressMode>
<directoryURL>http://{{ hostvars[groups['nginx'][0]].ansible_host }}/phones/directory.xml</directoryURL>
<servicesURL>http://{{ hostvars[groups['nginx'][0]].ansible_host }}/phones/directory.xml</servicesURL>
<devicePool>
<dateTimeSetting>
<dateTemplate>D/M/Ya</dateTemplate>
<timeZone>GMT Standard/Daylight Time</timeZone>
<ntps>
<ntp>
<name>{{ ntp_server }}</name>
<ntpMode>Unicast</ntpMode>
</ntp>
</ntps>
</dateTimeSetting>
<callManagerGroup>
<members>
<member priority="0">
<callManager>
<ports>
<ethernetPhonePort>2000</ethernetPhonePort>
<sipPort>5060</sipPort>
</ports>
<processNodeName>{{ hostvars[groups['asterisk'][0]].ansible_host }}</processNodeName>
</callManager>
</member>
</members>
</callManagerGroup>
</devicePool>
<sipProfile>
<sipProxies>
<registerWithProxy>true</registerWithProxy>
</sipProxies>
<sipCallFeatures>
<cnfJoinEnabled>true</cnfJoinEnabled>
<rfc2543Hold>false</rfc2543Hold>
<callHoldRingback>2</callHoldRingback>
<localCfwdEnable>true</localCfwdEnable>
<semiAttendedTransfer>true</semiAttendedTransfer>
<anonymousCallBlock>2</anonymousCallBlock>
<callerIdBlocking>2</callerIdBlocking>
<dndControl>0</dndControl>
<remoteCcEnable>true</remoteCcEnable>
</sipCallFeatures>
<sipStack>
<sipInviteRetx>6</sipInviteRetx>
<sipRetx>10</sipRetx>
<timerInviteExpires>180</timerInviteExpires>
<timerRegisterExpires>300</timerRegisterExpires>
<timerRegisterDelta>5</timerRegisterDelta>
<timerKeepAliveExpires>120</timerKeepAliveExpires>
<timerSubscribeExpires>120</timerSubscribeExpires>
<timerSubscribeDelta>5</timerSubscribeDelta>
<timerT1>500</timerT1>
<timerT2>4000</timerT2>
<maxRedirects>70</maxRedirects>
<remotePartyID>true</remotePartyID>
<userInfo>None</userInfo>
</sipStack>
<autoAnswerTimer>1</autoAnswerTimer>
<autoAnswerAltBehavior>false</autoAnswerAltBehavior>
<autoAnswerOverride>true</autoAnswerOverride>
<transferOnhookEnabled>false</transferOnhookEnabled>
<enableVad>false</enableVad>
<preferredCodec>g711ulaw</preferredCodec>
<dtmfAvtPayload>101</dtmfAvtPayload>
<dtmfDbLevel>3</dtmfDbLevel>
<dtmfOutofBand>avt</dtmfOutofBand>
<alwaysUsePrimeLine>false</alwaysUsePrimeLine>
<alwaysUsePrimeLineVoiceMail>false</alwaysUsePrimeLineVoiceMail>
<kpml>3</kpml>
<natEnabled>false</natEnabled>
<phoneLabel>{{ item.number }}</phoneLabel>
<stutterMsgWaiting>0</stutterMsgWaiting>
<callStats>false</callStats>
<silentPeriodBetweenCallWaitingBursts>10</silentPeriodBetweenCallWaitingBursts>
<disableLocalSpeedDialConfig>false</disableLocalSpeedDialConfig>
<startMediaPort>10000</startMediaPort>
<stopMediaPort>20000</stopMediaPort>
<sipLines>
<line button="1">
<featureID>9</featureID>
<featureLabel>{{ item.number }}</featureLabel>
<proxy>USECALLMANAGER</proxy>
<port>5060</port>
<name>{{ item.number }}</name>
<displayName>{{ item.number }}</displayName>
<autoAnswer>
<autoAnswerEnabled>2</autoAnswerEnabled>
</autoAnswer>
<callWaiting>3</callWaiting>
<authName>{{ item.number }}</authName>
<authPassword>{{ item.password }}</authPassword>
<sharedLine>false</sharedLine>
<messageWaitingLampPolicy>1</messageWaitingLampPolicy>
<messagesNumber>*98</messagesNumber>
<ringSettingIdle>4</ringSettingIdle>
<ringSettingActive>5</ringSettingActive>
<contact>{{ item.number }}</contact>
<forwardCallInfoDisplay>
<callerName>true</callerName>
<callerNumber>true</callerNumber>
<redirectedNumber>false</redirectedNumber>
<dialedNumber>true</dialedNumber>
</forwardCallInfoDisplay>
</line>
</sipLines>
<voipControlPort>5060</voipControlPort>
<dscpForAudio>184</dscpForAudio>
<ringSettingBusyStationPolicy>0</ringSettingBusyStationPolicy>
<dialTemplate>dialplan.xml</dialTemplate>
</sipProfile>
<commonProfile>
<phonePassword></phonePassword>
<backgroundImageAccess>true</backgroundImageAccess>
<callLogBlfEnabled>1</callLogBlfEnabled>
</commonProfile>
<loadInformation>SIP41.8-5-2S</loadInformation>
<vendorConfig>
<disableSpeaker>false</disableSpeaker>
<disableSpeakerAndHeadset>false</disableSpeakerAndHeadset>
<pcPort>0</pcPort>
<settingsAccess>1</settingsAccess>
<garp>0</garp>
<voiceVlanAccess>0</voiceVlanAccess>
<videoCapability>0</videoCapability>
<autoSelectLineEnable>0</autoSelectLineEnable>
<webAccess>0</webAccess>
<spanToPCPort>1</spanToPCPort>
<loggingDisplay>1</loggingDisplay>
<loadServer></loadServer>
</vendorConfig>
<versionStamp>001</versionStamp>
<networkLocale>United_Kingdom</networkLocale>
<networkLocaleInfo>
<name>United_Kingdom</name>
<version>1.0.0.0-4</version>
</networkLocaleInfo>
<deviceSecurityMode>1</deviceSecurityMode>
<authenticationURL></authenticationURL>
<transportLayerProtocol>2</transportLayerProtocol>
<certHash></certHash>
<encrConfig>false</encrConfig>
<dialToneSetting>2</dialToneSetting>
</device>

View file

@ -0,0 +1,4 @@
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="{{ tftp_root_dir }}"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"