Aller au contenu

Déployer Asterisk 22 LTS sur Debian 13

Monter un IPBX Asterisk sur Debian 13 réserve une mauvaise surprise dès la première commande : le paquet n’existe plus. Il faut compiler, ce qui change la nature de l’exercice et engage sur le suivi de sécurité. Voici la procédure complète, avec les cinq endroits où j’ai réellement buté.

Pourquoi compiler plutôt qu’installer un paquet

Section intitulée « Pourquoi compiler plutôt qu’installer un paquet »

Sur Debian 13, apt install asterisk échoue :

Fenêtre de terminal
apt-cache policy asterisk
asterisk:
Installé : (aucun)
Candidat : (aucun)

Le paquet a été retiré de Debian avant la sortie de trixie, faute de mainteneurs pour absorber la charge de suivi des failles. Seuls survivent dans les dépôts les paquets de sons (asterisk-core-sounds-fr, asterisk-prompt-fr-armelle), dont la source amont est distincte du moteur. Asterisk est revenu dans testing en 22.10.1 le 26 juillet 2026, donc trop tard pour trixie, et aucun trixie-backports ne le fournit.

Trois voies restent ouvertes, une seule est raisonnable :

Méthode Verdict
Compilation depuis les sources Retenue. Version amont récente, modules à la carte, maintenance manuelle assumée
Épinglage APT du paquet testing À éviter. Tire des dépendances de testing sur un système stable, casse au premier apt upgrade
Conteneur Docker Défendable, mais complique le RTP, qui demande le mode host ou une large plage de ports publiée

Asterisk est un IPBX logiciel. Il enregistre des téléphones SIP, les authentifie, route les appels selon un plan de numérotation, et transporte la voix en RTP. Autour de ce noyau viennent la messagerie vocale, les serveurs vocaux interactifs, les files d’attente, l’enregistrement et le raccordement aux opérateurs.

Cet article monte le socle : deux postes internes qui s’appellent, plus deux numéros de service pour valider la chaîne audio. Le raccordement à un trunk opérateur et le durcissement feront l’objet d’articles distincts.

/usr/sbin/asterisk <- binaire
/usr/lib/asterisk/modules/ <- 327 modules .so
/etc/asterisk/ <- configuration
├── asterisk.conf <- runuser, rungroup, chemins
├── pjsip.conf <- transport, endpoints, auth, aors
├── extensions.conf <- plan de numerotation
└── logger.conf <- journalisation
/var/lib/asterisk/sounds/fr/ <- 1069 fichiers, core-fr 1.6.1
/var/log/asterisk/ <- messages.log + full
/var/spool/asterisk/ <- messagerie, enregistrements
/var/run/asterisk/ <- socket CLI, pid

Plan de numérotation cible :

Numéro Rôle
6001, 6002 postes internes, enregistrement SIP avec authentification
600 test d’écho, valide le RTP dans les deux sens
601 annonce de l’heure, valide la langue et les sons

La machine de test : 4 vCPU, 1,9 Go de RAM, 40 Go libres, adresse fixe 192.168.1.76/24.

Fenêtre de terminal
sudo apt update
sudo apt install -y build-essential pkg-config autoconf automake libtool \
wget curl git bison flex bzip2 patch xmlstarlet \
libedit-dev libjansson-dev libsqlite3-dev uuid-dev libxml2-dev \
libssl-dev libncurses-dev libcurl4-openssl-dev libsrtp2-dev \
libopus-dev libogg-dev libvorbis-dev libspeex-dev libspeexdsp-dev \
libgsm1-dev libsndfile1-dev libunbound-dev

Les cinq bibliothèques de la troisième ligne sont les seules réellement obligatoires. Le reste ouvre les codecs, le SRTP et la résolution DNS de PJSIP.

Vérification :

Fenêtre de terminal
cat /etc/debian_version # 13.6
gcc --version | head -1 # gcc (Debian 14.2.0-19) 14.2.0
Fenêtre de terminal
mkdir -p ~/src && cd ~/src
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-22-current.tar.gz
tar xzf asterisk-22-current.tar.gz
cd asterisk-22.11.0

Le lien asterisk-22-current suit la branche 22, qui est la LTS courante. Une LTS Asterisk est maintenue quatre ans, avec correctifs de sécurité pendant cinq. Ne partez pas sur une branche impaire, elle est en support standard un an seulement.

Fenêtre de terminal
./configure --with-pjproject-bundled --with-jansson-bundled \
--prefix=/usr --sysconfdir=/etc --localstatedir=/var

Deux points méritent l’attention.

--with-pjproject-bundled compile la pile SIP PJPROJECT fournie avec les sources, ici la 2.17, plutôt que d’utiliser celle du système. C’est la méthode recommandée en amont : Asterisk applique ses propres correctifs à PJPROJECT, et une version système divergente est une source classique de plantages difficiles à diagnostiquer.

Les trois chemins alignent l’installation sur l’arborescence Debian. Sans eux, tout atterrit sous /usr/local, ce qui fonctionne mais complique les unités systemd et les scripts de sauvegarde.

Sortie de fin de configuration :

configure: Package configured for:
configure: OS type : linux-gnu
configure: Host CPU : x86_64
Fenêtre de terminal
make menuselect.makeopts

Les modules SIP sont déjà actifs par défaut, inutile d’y toucher :

Fenêtre de terminal
menuselect/menuselect --list-options menuselect.makeopts \
| grep -E "chan_pjsip|res_pjsip |res_srtp"
+ chan_pjsip MENUSELECT_CHANNELS
+ res_pjsip MENUSELECT_RES
+ res_srtp MENUSELECT_RES

Le + signale un module retenu. En revanche les sons livrés par défaut sont en anglais, il faut demander le français explicitement :

Fenêtre de terminal
menuselect/menuselect \
--enable CORE-SOUNDS-FR-WAV \
--enable CORE-SOUNDS-FR-G722 \
--enable CORE-SOUNDS-FR-GSM \
--enable MOH-OPSOUND-WAV \
--enable MOH-OPSOUND-G722 \
menuselect.makeopts

Trois formats pour une raison simple : Asterisk choisit le fichier dont le codec correspond à celui négocié, ce qui évite un transcodage. G.722 pour la HD sur le LAN, GSM en repli, WAV pour le reste.

L’interface interactive reste disponible avec make menuselect si vous préférez naviguer dans les catégories.

Fenêtre de terminal
make -j2

Durée relevée : 3 min 36 s pour 4 vCPU à -j2.

+--------- Asterisk Build Complete ---------+
+ Asterisk has successfully been built, and +
+ can be installed by running: +
+ make install +
+-------------------------------------------+

Créer le compte de service avant l’installation, pour que les répertoires soient créés avec les bons propriétaires :

Fenêtre de terminal
sudo groupadd -f asterisk
sudo useradd -r -d /var/lib/asterisk -g asterisk -s /usr/sbin/nologin asterisk
Fenêtre de terminal
sudo make install
sudo make samples

make install télécharge au passage les archives de sons sélectionnées à l’étape précédente. make samples dépose les configurations d’exemple dans /etc/asterisk, abondamment commentées : c’est la documentation de référence la plus utile, gardez-la.

Contrôle :

Fenêtre de terminal
/usr/sbin/asterisk -V
ls /var/lib/asterisk/sounds/fr/ | wc -l
Asterisk 22.11.0
1069
Fenêtre de terminal
sudo chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk \
/var/log/asterisk /var/spool/asterisk /usr/lib/asterisk
sudo mkdir -p /var/run/asterisk
sudo chown asterisk:asterisk /var/run/asterisk

Puis décommenter les deux directives d’abaissement de privilèges dans /etc/asterisk/asterisk.conf :

Fenêtre de terminal
sudo sed -i 's/^;runuser = asterisk/runuser = asterisk/; s/^;rungroup = asterisk/rungroup = asterisk/' /etc/asterisk/asterisk.conf
grep -E '^(runuser|rungroup)' /etc/asterisk/asterisk.conf
runuser = asterisk
rungroup = asterisk

Un Asterisk qui tourne en root est une faute : le service parle SIP à des inconnus, c’est exactement le profil de processus qu’il faut contenir.

Les sources fournissent un script sysvinit via make config, daté. Une unité native vaut mieux.

/etc/systemd/system/asterisk.service
[Unit]
Description=Asterisk PBX
Documentation=https://docs.asterisk.org/
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=asterisk
Group=asterisk
ExecStart=/usr/sbin/asterisk -f -C /etc/asterisk/asterisk.conf
ExecReload=/usr/sbin/asterisk -rx 'core reload'
Restart=on-failure
RestartSec=5
RuntimeDirectory=asterisk
RuntimeDirectoryMode=0750
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictSUIDSGID=true
[Install]
WantedBy=multi-user.target
Fenêtre de terminal
sudo systemctl daemon-reload
sudo systemctl enable --now asterisk
systemctl is-active asterisk

Le -f maintient Asterisk au premier plan, ce qu’attend Type=simple. Sans lui, le processus se détache et systemd considère le service comme terminé aussitôt. RuntimeDirectory=asterisk recrée /var/run/asterisk à chaque démarrage, ce qui règle définitivement la question du tmpfs.

PJSIP remplace l’ancien pilote chan_sip, supprimé depuis Asterisk 21. Sa configuration est plus verbeuse, mais chaque objet a un rôle net :

Objet Rôle
transport socket d’écoute, protocole, réseau local
endpoint identité d’appel : codecs, contexte, langue
auth identifiants de connexion
aor où joindre le poste, alimenté par l’enregistrement

Le fichier /etc/asterisk/pjsip.conf testé, avec des modèles pour ne pas répéter les mêmes réglages à chaque poste :

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.168.1.0/24
[endpoint-interne](!)
type=endpoint
context=interne
disallow=all
allow=g722,alaw,ulaw
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
language=fr
[auth-userpass](!)
type=auth
auth_type=userpass
[aor-simple](!)
type=aor
max_contacts=1
remove_existing=yes
qualify_frequency=30
[6001](endpoint-interne)
auth=6001
aors=6001
callerid=Poste 6001 <6001>
[6001](auth-userpass)
username=6001
password=Trixie2026-6001
[6001](aor-simple)
[6002](endpoint-interne)
auth=6002
aors=6002
callerid=Poste 6002 <6002>
[6002](auth-userpass)
username=6002
password=Trixie2026-6002
[6002](aor-simple)

La syntaxe (!) déclare un modèle, (nom-du-modele) en hérite. Ajouter un poste se réduit alors à six lignes.

Quelques directives qui méritent d’être comprises plutôt que recopiées :

Directive Effet
disallow=all puis allow= liste blanche de codecs, dans l’ordre de préférence. Sans le disallow, tous les codecs compilés sont proposés
direct_media=no le RTP transite par Asterisk. Indispensable dès qu’il y a du NAT, de l’enregistrement ou de la supervision
rtp_symmetric et force_rport renvoient les flux vers l’adresse réellement observée, pas celle annoncée dans le SDP
remove_existing=yes avec max_contacts=1, le dernier enregistrement chasse le précédent, plutôt que d’être refusé
language=fr fait chercher les sons dans sounds/fr/ avant sounds/en/

/etc/asterisk/extensions.conf :

[general]
static=yes
writeprotect=no
clearglobalvars=no
[globals]
SONNERIE=20
[interne]
exten => _600[12],1,NoOp(Appel interne vers ${EXTEN} depuis ${CALLERID(num)})
same => n,Dial(PJSIP/${EXTEN},${SONNERIE})
same => n,Goto(s-${DIALSTATUS},1)
exten => s-BUSY,1,NoOp(Poste occupe)
same => n,Busy(5)
same => n,Hangup()
exten => s-NOANSWER,1,NoOp(Pas de reponse)
same => n,Playback(vm-nobodyavail)
same => n,Hangup()
exten => _s-.,1,NoOp(Echec d'appel : ${DIALSTATUS})
same => n,Congestion(5)
same => n,Hangup()
exten => 600,1,NoOp(Test d'echo)
same => n,Answer()
same => n,Wait(1)
same => n,Playback(demo-echotest)
same => n,Echo()
same => n,Playback(demo-echodone)
same => n,Hangup()
exten => 601,1,NoOp(Annonce de l'heure)
same => n,Answer()
same => n,Wait(1)
same => n,SayUnixTime(,Europe/Paris,kM)
same => n,Hangup()

Le contexte interne est celui déclaré dans le modèle d’endpoint. Un poste ne peut composer que ce que son contexte expose : c’est le mécanisme de cloisonnement de base d’Asterisk, et le premier rempart contre la fraude à la taxation.

_600[12] est un motif qui couvre 6001 et 6002 en une seule règle. Dial renseigne ${DIALSTATUS}, que le Goto transforme en branchement vers s-BUSY ou s-NOANSWER, avec _s-. en filet pour les autres cas.

Appliquer et contrôler :

Fenêtre de terminal
sudo systemctl reload asterisk
sudo asterisk -rx "dialplan show interne"
'600' => 1. NoOp(Test d'echo) [extensions.conf:38]
'601' => 1. NoOp(Annonce de l'heure) [extensions.conf:47]
's-BUSY' => 1. NoOp(Poste occupe) [extensions.conf:25]
's-NOANSWER' => 1. NoOp(Pas de reponse) [extensions.conf:29]
'_600[12]' => 1. NoOp(Appel interne vers ${EXTEN}...) [extensions.conf:21]
'_s-.' => 1. NoOp(Echec d'appel : ${DIALSTATUS}) [extensions.conf:33]
-= 6 extensions (24 priorities) in 1 context. =-

Un softphone graphique fait l’affaire (Zoiper, Linphone, MicroSIP). Pour valider sans interface, baresip est packagé dans trixie et se pilote en ligne de commande :

Fenêtre de terminal
sudo apt install -y baresip-core
mkdir -p ~/sip/6001 ~/sip/6002
for n in 6001 6002; do baresip -f ~/sip/$n -t 1 >/dev/null 2>&1; done

Sur un serveur sans carte son, il faut remplacer le pilote ALSA par un périphérique factice, dans ~/sip/6001/config et ~/sip/6002/config :

audio_player aubridge,dummy
audio_source aubridge,dummy
audio_alert aubridge,dummy
#module alsa.so
module aubridge.so
module g711.so
module g722.so

Les comptes, un par fichier accounts :

<sip:[email protected]>;auth_pass=Trixie2026-6001;regint=60
<sip:[email protected]>;auth_pass=Trixie2026-6002;regint=60;answermode=auto

L’answermode=auto du 6002 lui fait décrocher seul, ce qui permet de tester sans deuxième opérateur.

Démarrer le 6002 en tâche de fond, puis vérifier côté Asterisk :

Fenêtre de terminal
nohup baresip -f ~/sip/6002 > ~/sip/6002.log 2>&1 &
sleep 5
sudo asterisk -rx "pjsip show endpoints"
Endpoint: 6001/6001 Unavailable 0 of inf
Endpoint: 6002/6002 Not in use 0 of inf
Contact: 6002/sip:[email protected]: b82211ca2b Avail 0.342

Un contact Avail avec son temps d’aller-retour prouve que le transport, l’authentification et l’AOR sont corrects.

L’option -e de baresip exécute la commande au démarrage, avant que le compte soit enregistré, ce qui échoue avec could not find UA for 6002. Il faut passer par un tube nommé :

Fenêtre de terminal
FIFO=/tmp/ctl6001
mkfifo $FIFO
baresip -f ~/sip/6001 < $FIFO > ~/sip/6001.log 2>&1 &
exec 3> $FIFO
sleep 6 # laisser l'enregistrement aboutir
echo "/dial 6002" >&3
sleep 6
sudo asterisk -rx "core show channels"
echo "/hangup" >&3
echo "/quit" >&3
exec 3>&-

Appel vers le test d’écho :

PJSIP/6001-00000002 600@interne:4 Up Playback(demo-echotest)
1 active channel
1 active call
ChannelId UpTime Codec Rx:Count Lost Pct Jitter Tx:Count Lost Pct Jitter
6001-00000002 00:00:05 g722 252 0 0 0.000 202 0 0 0.001

Appel de poste à poste :

PJSIP/6001-00000003 6002@interne:2 Up Dial(PJSIP/6002,20)
PJSIP/6002-00000004 (None) Up AppDial((Outgoing Line))
2 active channels
1 active call
BridgeId ChannelId UpTime Codec Rx:Count Lost Pct Tx:Count Lost Pct
b65d1ef7 6002-00000004 00:00:06 g722 302 0 0 302 0 0

Deux canaux pontés, G.722 négocié, aucun paquet perdu dans les deux sens. La chaîne complète est validée : signalisation SIP, authentification, plan de numérotation, pontage et transport RTP.

Par défaut, /etc/asterisk/logger.conf ne consigne que les avertissements et les erreurs. Pour tracer le déroulé des appels :

[logfiles]
console => notice,warning,error,verbose
messages.log => notice,warning,error
full => notice,warning,error,verbose(5),dtmf
Fenêtre de terminal
sudo asterisk -rx "logger reload"
sudo asterisk -rx "logger show channels"

On obtient alors la résolution effective des fichiers audio, ce qui confirme la prise en compte de la langue :

Fenêtre de terminal
sudo grep -oE "Playing [^ ]+ \(language .[a-z]*.\)" /var/log/asterisk/full
Playing 'demo-echotest.g722' (language 'fr')
Playing 'digits/14.g722' (language 'fr')
Playing 'digits/50.g722' (language 'fr')
Playing 'digits/oclock.g722' (language 'fr')

Les trois derniers viennent de SayUnixTime sur le 601, qui a annoncé 14 h 50 en français.

Penser à la rotation, /etc/logrotate.d/asterisk :

/var/log/asterisk/full
/var/log/asterisk/messages.log {
daily
rotate 30
missingok
notifempty
compress
delaycompress
postrotate
/usr/sbin/asterisk -rx 'logger rotate' > /dev/null 2>&1 || true
endscript
su asterisk asterisk
}
Symptôme Cause Correction
apt install asterisk : paquet introuvable retiré de Debian 13 compiler depuis les sources
install_prereq échoue paquets disparus de trixie utiliser la liste de la section 1
Compilation tuée sans message mémoire insuffisante sur PJPROJECT make -j2, ou ajouter du swap
Le service s’arrête aussitôt lancé -f absent de ExecStart ajouter -f, exigé par Type=simple
Unable to connect to remote asterisk /var/run/asterisk absent après reboot RuntimeDirectory=asterisk dans l’unité
Poste jamais Avail auth ou aors non référencés dans l’endpoint pjsip show endpoint 6001, vérifier les trois objets
Appel décroché puis coupé net source audio incompatible avec le codec côté baresip, aubridge et non ausine
Sonnerie mais audio muet RTP bloqué ouvrir 10000-20000/udp, direct_media=no
Sons en anglais language non posé sur l’endpoint language=fr, sans préfixer les Playback
/var/log/asterisk/full vide niveau de verbosité non précisé verbose(5) et non verbose
could not find UA au lancement -e s’exécute avant l’enregistrement piloter baresip par tube nommé
cdr_custom declined to load section absente de cdr_custom.conf sans effet, ou renseigner la section

Aucune mise à jour ne viendra d’APT. Le cycle est manuel :

Fenêtre de terminal
cd ~/src
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-22-current.tar.gz
tar xzf asterisk-22-current.tar.gz && cd asterisk-22.<nouvelle version>
./configure --with-pjproject-bundled --with-jansson-bundled \
--prefix=/usr --sysconfdir=/etc --localstatedir=/var
cp ../asterisk-22.11.0/menuselect.makeopts . # reprendre la selection precedente
make -j2
sudo systemctl stop asterisk
sudo make install
sudo systemctl start asterisk
sudo asterisk -rx "core show version"

make install ne touche pas à /etc/asterisk, les configurations sont préservées. Recopier menuselect.makeopts évite de refaire la sélection des sons à chaque version.

S’abonner à la liste de sécurité amont est la contrepartie du choix de compiler. Les bulletins sont publiés sur le portail des avis de sécurité Asterisk, avec les versions correctives associées.

Commandes de supervision courantes :

Fenêtre de terminal
sudo asterisk -rx "core show uptime"
sudo asterisk -rx "pjsip show endpoints"
sudo asterisk -rx "pjsip show registrations"
sudo asterisk -rx "core show channels"
sudo asterisk -rx "pjsip show channelstats"
sudo asterisk -rx "module show like pjsip"

Pour une session interactive : sudo asterisk -rvvv, puis core set verbose 3 et pjsip set logger on pour voir passer la signalisation SIP en clair.

Ce socle laisse volontairement de côté trois chantiers, chacun conséquent :

  • Messagerie vocale et SVI : voicemail.conf, app_voicemail, arborescence Background et WaitExten
  • Raccordement opérateur : objets registration, identify et endpoint côté trunk, plan de numérotation entrant et sortant, gestion du NAT
  • Durcissement : fail2ban sur les tentatives d’authentification, restriction des ACL PJSIP, TLS et SRTP, garde-fous contre la fraude à la taxation