KI-AGENT: Asterisk-Stand ohne FreePBX versionieren
This commit is contained in:
16
.env.example
16
.env.example
@@ -77,19 +77,9 @@ TELEPHONY_DEV_WS_PORT=8088
|
||||
TELEPHONY_DEV_AMI_PORT=5038
|
||||
TELEPHONY_DEV_SIP_PORT=5060
|
||||
TELEPHONY_DEV_RTP_MIN_PORT=10000
|
||||
TELEPHONY_DEV_RTP_MAX_PORT=10020
|
||||
|
||||
# Optionales FreePBX-Diagnoseprofil. Das Profil ist nur als Referenz-PBX für
|
||||
# Provider-Tests gedacht und nutzt eigene Ports, damit der FEDEO-Asterisk
|
||||
# parallel bestehen bleibt.
|
||||
FREEPBX_DEV_IMAGE=escomputers/freepbx:17-nofail2ban
|
||||
FREEPBX_DEV_PLATFORM=linux/amd64
|
||||
FREEPBX_DEV_TZ=Europe/Berlin
|
||||
FREEPBX_DEV_HTTP_PORT=18080
|
||||
FREEPBX_DEV_HTTPS_PORT=18443
|
||||
FREEPBX_DEV_SIP_PORT=15060
|
||||
FREEPBX_DEV_RTP_MIN_PORT=18000
|
||||
FREEPBX_DEV_RTP_MAX_PORT=18100
|
||||
TELEPHONY_DEV_RTP_MAX_PORT=10100
|
||||
TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS=
|
||||
TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS=
|
||||
|
||||
# Externe Telefonie über Telekom/tel.t-online.de. Keine echten Zugangsdaten
|
||||
# einchecken. SIP-ID ist in der Regel die Rufnummer mit Vorwahl ohne Leerzeichen
|
||||
|
||||
@@ -265,6 +265,7 @@ const renderProviderExtensionsConfig = (trunk: any) => {
|
||||
const outboundPrefix = asteriskValue(trunk.outboundPrefix) || "0"
|
||||
const escapedPrefix = outboundPrefix.replace(/[^0-9*#+]/g, "")
|
||||
const callerId = asteriskValue(trunk.callerId) || asteriskValue(trunk.sipUser)
|
||||
const inboundDid = callerId.replace(/[^0-9+]/g, "")
|
||||
|
||||
return [
|
||||
"; Von FEDEO generiert. Änderungen im Container können überschrieben werden.",
|
||||
@@ -282,6 +283,12 @@ const renderProviderExtensionsConfig = (trunk: any) => {
|
||||
" same => n,Hangup()",
|
||||
"",
|
||||
`[from-${providerKey}]`,
|
||||
...(inboundDid ? [
|
||||
`exten => ${inboundDid},1,NoOp(FEDEO eingehend über ${provider.label} DID: $` + "{EXTEN})",
|
||||
` same => n,Dial(PJSIP/${inboundExtension},30)`,
|
||||
" same => n,Hangup()",
|
||||
"",
|
||||
] : []),
|
||||
`exten => s,1,NoOp(FEDEO eingehend über ${provider.label})`,
|
||||
` same => n,Dial(PJSIP/${inboundExtension},30)`,
|
||||
" same => n,Hangup()",
|
||||
@@ -293,6 +300,25 @@ const renderProviderExtensionsConfig = (trunk: any) => {
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
const renderWebRtcConfig = (trunk: any) => {
|
||||
const externalMediaAddress = asteriskValue(trunk?.externalMediaAddress || trunk?.externalSignalingAddress)
|
||||
|
||||
if (!externalMediaAddress) {
|
||||
return [
|
||||
"; Von FEDEO generiert.",
|
||||
"; Kein externes WebRTC-Media-Rewrite konfiguriert.",
|
||||
"",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
return [
|
||||
"; Von FEDEO generiert. Diese Datei wird innerhalb des FEDEO-WebRTC-Templates inkludiert.",
|
||||
`media_address=${externalMediaAddress}`,
|
||||
"bind_rtp_to_media_address=yes",
|
||||
"",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
const renderTelekomTransportConfig = (trunk: any) => {
|
||||
const externalSignalingAddress = asteriskValue(trunk?.externalSignalingAddress)
|
||||
const externalMediaAddress = asteriskValue(trunk?.externalMediaAddress || trunk?.externalSignalingAddress)
|
||||
@@ -339,6 +365,10 @@ const writeAsteriskTrunkConfig = async (trunk: any) => {
|
||||
name: "pjsip.transport.conf",
|
||||
content: renderTelekomTransportConfig(trunk),
|
||||
},
|
||||
{
|
||||
name: "pjsip.webrtc.conf",
|
||||
content: renderWebRtcConfig(trunk),
|
||||
},
|
||||
]
|
||||
|
||||
await Promise.all(files.map(async (file) => {
|
||||
|
||||
@@ -125,6 +125,8 @@ services:
|
||||
- TELEPHONY_TELEKOM_CALLER_ID=${TELEPHONY_TELEKOM_CALLER_ID:-}
|
||||
- TELEPHONY_TELEKOM_INBOUND_EXTENSION=${TELEPHONY_TELEKOM_INBOUND_EXTENSION:-1001}
|
||||
- TELEPHONY_TELEKOM_OUTBOUND_PREFIX=${TELEPHONY_TELEKOM_OUTBOUND_PREFIX:-0}
|
||||
- TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS=${TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS:-}
|
||||
- TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS=${TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS:-}
|
||||
- ASTERISK_GENERATED_DIR=/etc/asterisk/generated
|
||||
command:
|
||||
- /bin/sh
|
||||
@@ -138,50 +140,7 @@ services:
|
||||
- "${TELEPHONY_DEV_WS_PORT:-8088}:8088"
|
||||
- "${TELEPHONY_DEV_AMI_PORT:-5038}:5038"
|
||||
- "${TELEPHONY_DEV_SIP_PORT:-5060}:5060/udp"
|
||||
- "${TELEPHONY_DEV_RTP_MIN_PORT:-10000}-${TELEPHONY_DEV_RTP_MAX_PORT:-10020}:10000-10020/udp"
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
freepbx-dev-db:
|
||||
image: mariadb:10.11
|
||||
restart: unless-stopped
|
||||
profiles:
|
||||
- freepbx-dev
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/freepbx_mysql_root_password
|
||||
MYSQL_USER: freepbxuser
|
||||
MYSQL_PASSWORD_FILE: /run/secrets/freepbx_user_password
|
||||
secrets:
|
||||
- freepbx_mysql_root_password
|
||||
- freepbx_user_password
|
||||
volumes:
|
||||
- freepbx_dev_mysql:/var/lib/mysql
|
||||
- ./telephony/freepbx/my.cnf:/etc/mysql/my.cnf:ro
|
||||
- ./telephony/freepbx/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
freepbx-dev:
|
||||
image: ${FREEPBX_DEV_IMAGE:-escomputers/freepbx:17-nofail2ban}
|
||||
platform: ${FREEPBX_DEV_PLATFORM:-linux/amd64}
|
||||
restart: unless-stopped
|
||||
profiles:
|
||||
- freepbx-dev
|
||||
depends_on:
|
||||
- freepbx-dev-db
|
||||
environment:
|
||||
- TZ=${FREEPBX_DEV_TZ:-Europe/Berlin}
|
||||
secrets:
|
||||
- freepbx_user_password
|
||||
- freepbx_postfix_sasl_passwd
|
||||
volumes:
|
||||
- freepbx_dev_var:/var
|
||||
- freepbx_dev_etc:/etc
|
||||
ports:
|
||||
- "${FREEPBX_DEV_HTTP_PORT:-18080}:80/tcp"
|
||||
- "${FREEPBX_DEV_HTTPS_PORT:-18443}:443/tcp"
|
||||
- "${FREEPBX_DEV_SIP_PORT:-15060}:5060/udp"
|
||||
- "${FREEPBX_DEV_RTP_MIN_PORT:-18000}-${FREEPBX_DEV_RTP_MAX_PORT:-18100}:18000-18100/udp"
|
||||
- "${TELEPHONY_DEV_RTP_MIN_PORT:-10000}-${TELEPHONY_DEV_RTP_MAX_PORT:-10100}:10000-10100/udp"
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
@@ -532,19 +491,6 @@ services:
|
||||
- "./traefik/logs:/logs"
|
||||
networks:
|
||||
- traefik
|
||||
volumes:
|
||||
freepbx_dev_mysql:
|
||||
freepbx_dev_var:
|
||||
freepbx_dev_etc:
|
||||
|
||||
secrets:
|
||||
freepbx_mysql_root_password:
|
||||
file: ./telephony/freepbx/secrets/mysql_root_password.txt
|
||||
freepbx_user_password:
|
||||
file: ./telephony/freepbx/secrets/freepbxuser_password.txt
|
||||
freepbx_postfix_sasl_passwd:
|
||||
file: ./telephony/freepbx/secrets/sasl_passwd.txt
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: false
|
||||
|
||||
@@ -66,38 +66,6 @@ Wenn `TELEPHONY_TELEKOM_AUTH_USER` leer bleibt, verwendet Asterisk automatisch `
|
||||
docker compose --profile telephony-dev up -d asterisk-dev
|
||||
```
|
||||
|
||||
Beim Start erzeugt der Container die Dateien `pjsip.telekom.conf` und `extensions.telekom.conf` in einem Docker-Volume. Ausgehende Anrufe mit Prefix `0` und internationale Ziele mit `+` werden über den Telekom-Trunk geroutet. Eingehende Anrufe landen standardmäßig auf Nebenstelle `1001`.
|
||||
Beim Start erzeugt der Container die Dateien `pjsip.telekom.conf`, `extensions.telekom.conf` und `pjsip.webrtc.conf` in einem Docker-Volume. Ausgehende Anrufe mit Prefix `0` und internationale Ziele mit `+` werden über den Trunk geroutet. Eingehende Anrufe landen standardmäßig auf Nebenstelle `1001`; die konfigurierte Rufnummer wird zusätzlich als DID direkt geroutet.
|
||||
|
||||
## FreePBX als Diagnose-PBX
|
||||
|
||||
Für Provider-Tests kann zusätzlich das optionale Profil `freepbx-dev` gestartet werden. FreePBX ist hier nicht als dauerhafte FEDEO-Abhängigkeit gedacht, sondern als Referenzoberfläche, um Trunk-, NAT-, CLIP- und Routing-Parameter gegen einen Provider wie Easybell zu prüfen.
|
||||
|
||||
```bash
|
||||
docker compose --profile freepbx-dev up -d freepbx-dev-db freepbx-dev
|
||||
```
|
||||
|
||||
Beim ersten Start muss FreePBX einmal gegen die lokale MariaDB installiert werden:
|
||||
|
||||
```bash
|
||||
docker compose --profile freepbx-dev exec -T -w /usr/local/src/freepbx freepbx-dev \
|
||||
bash -lc 'php install -n --dbuser=freepbxuser --dbpass="$(cat /run/secrets/freepbx_user_password)" --dbhost=freepbx-dev-db'
|
||||
```
|
||||
|
||||
Danach ist die Oberfläche lokal unter `http://localhost:18080` erreichbar. Beim ersten Öffnen zeigt FreePBX die Ersteinrichtung für den Web-Admin-Benutzer. Diese Zugangsdaten gelten nur für die FreePBX-Diagnoseoberfläche und sind unabhängig von FEDEO.
|
||||
|
||||
Die Standardports sind bewusst konfliktarm gesetzt:
|
||||
|
||||
- Web: `18080` / `18443`
|
||||
- SIP UDP: `15060`
|
||||
- RTP UDP: `18000-18100`
|
||||
|
||||
Das verwendete FreePBX-Image ist aktuell nur für `linux/amd64` veröffentlicht. Auf Apple-Silicon-Hosts nutzt Docker Desktop deshalb über `FREEPBX_DEV_PLATFORM=linux/amd64` Emulation; für Diagnosezwecke ist das ausreichend, aber nicht als Produktionssetup gedacht.
|
||||
|
||||
Für einen möglichst realistischen Easybell-Test kann der FEDEO-Asterisk kurz gestoppt und FreePBX auf dem üblichen SIP-Port gestartet werden:
|
||||
|
||||
```bash
|
||||
docker compose --profile telephony-dev stop asterisk-dev
|
||||
FREEPBX_DEV_SIP_PORT=5060 docker compose --profile freepbx-dev up -d freepbx-dev
|
||||
```
|
||||
|
||||
In FreePBX sollte der RTP-Bereich unter **Settings -> Asterisk SIP Settings** ebenfalls auf `18000-18100` gesetzt werden, damit er zur Compose-Portfreigabe passt. Wenn der Trunk dort erfolgreich registriert und ein Testanruf möglich ist, können die funktionierenden PJSIP- und NAT-Werte nach FEDEO übernommen werden.
|
||||
Wenn Asterisk auf einem VPS oder hinter NAT läuft, sollten `TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS` und `TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS` auf die öffentliche Asterisk-Adresse gesetzt werden. FEDEO schreibt daraus die WebRTC-Media-Adresse, damit Browser-Clients den RTP/ICE-Pfad sauber aushandeln.
|
||||
|
||||
@@ -31,6 +31,7 @@ force_rport=yes
|
||||
rewrite_contact=yes
|
||||
rtp_symmetric=yes
|
||||
transport=transport-ws
|
||||
#tryinclude generated/pjsip.webrtc.conf
|
||||
from_domain=localhost
|
||||
|
||||
[1001](fedeo-webrtc)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[general]
|
||||
rtpstart=10000
|
||||
rtpend=10020
|
||||
rtpend=10100
|
||||
icesupport=yes
|
||||
strictrtp=no
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
CREATE DATABASE IF NOT EXISTS asterisk;
|
||||
GRANT ALL PRIVILEGES ON `asterisk`.* TO 'freepbxuser'@'%';
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS asteriskcdrdb;
|
||||
GRANT ALL PRIVILEGES ON `asteriskcdrdb`.* TO 'freepbxuser'@'%';
|
||||
|
||||
FLUSH PRIVILEGES;
|
||||
@@ -1,2 +0,0 @@
|
||||
[mysqld]
|
||||
sql_mode=NO_ENGINE_SUBSTITUTION
|
||||
@@ -1 +0,0 @@
|
||||
change-this-freepbx-user-password
|
||||
@@ -1 +0,0 @@
|
||||
change-this-freepbx-root-password
|
||||
@@ -1 +0,0 @@
|
||||
[smtp.example.com]:587 user@example.com:change-this-app-password
|
||||
@@ -6,6 +6,7 @@ mkdir -p "$GENERATED_DIR"
|
||||
|
||||
PJSIP_FILE="$GENERATED_DIR/pjsip.telekom.conf"
|
||||
EXTENSIONS_FILE="$GENERATED_DIR/extensions.telekom.conf"
|
||||
PJSIP_WEBRTC_FILE="$GENERATED_DIR/pjsip.webrtc.conf"
|
||||
|
||||
enabled="${TELEPHONY_TELEKOM_ENABLED:-false}"
|
||||
|
||||
@@ -21,6 +22,9 @@ if [ "$enabled" != "true" ] && [ "$enabled" != "1" ] && [ "$enabled" != "yes" ];
|
||||
EOF
|
||||
cat > "$EXTENSIONS_FILE" <<'EOF'
|
||||
; Telekom-Anbindung ist deaktiviert.
|
||||
EOF
|
||||
cat > "$PJSIP_WEBRTC_FILE" <<'EOF'
|
||||
; Kein externes WebRTC-Media-Rewrite konfiguriert.
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
@@ -32,6 +36,7 @@ password="${TELEPHONY_TELEKOM_PASSWORD:-}"
|
||||
caller_id="${TELEPHONY_TELEKOM_CALLER_ID:-$sip_user}"
|
||||
inbound_extension="${TELEPHONY_TELEKOM_INBOUND_EXTENSION:-1001}"
|
||||
outbound_prefix="${TELEPHONY_TELEKOM_OUTBOUND_PREFIX:-0}"
|
||||
external_media_address="${TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS:-${TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS:-}}"
|
||||
|
||||
if [ -z "$sip_user" ] || [ -z "$password" ]; then
|
||||
cat > "$PJSIP_FILE" <<'EOF'
|
||||
@@ -39,6 +44,9 @@ if [ -z "$sip_user" ] || [ -z "$password" ]; then
|
||||
EOF
|
||||
cat > "$EXTENSIONS_FILE" <<'EOF'
|
||||
; Telekom-Anbindung ist aktiviert, aber nicht vollständig konfiguriert.
|
||||
EOF
|
||||
cat > "$PJSIP_WEBRTC_FILE" <<'EOF'
|
||||
; Kein externes WebRTC-Media-Rewrite konfiguriert.
|
||||
EOF
|
||||
echo "FEDEO Telefonie: Telekom-Anbindung unvollständig, Trunk wird nicht erzeugt." >&2
|
||||
exit 0
|
||||
@@ -108,6 +116,10 @@ exten => _+X.,1,NoOp(FEDEO ausgehend über Telekom: \${EXTEN})
|
||||
same => n,Hangup()
|
||||
|
||||
[from-telekom]
|
||||
exten => $caller_id,1,NoOp(FEDEO eingehend über Telekom DID: \${EXTEN})
|
||||
same => n,Dial(PJSIP/$inbound_extension,30)
|
||||
same => n,Hangup()
|
||||
|
||||
exten => s,1,NoOp(FEDEO eingehend über Telekom)
|
||||
same => n,Dial(PJSIP/$inbound_extension,30)
|
||||
same => n,Hangup()
|
||||
@@ -117,4 +129,16 @@ exten => _X!,1,NoOp(FEDEO eingehend über Telekom: \${EXTEN})
|
||||
same => n,Hangup()
|
||||
EOF
|
||||
|
||||
if [ -n "$external_media_address" ]; then
|
||||
cat > "$PJSIP_WEBRTC_FILE" <<EOF
|
||||
; Automatisch aus Umgebungsvariablen erzeugt. Nicht in Git einchecken.
|
||||
media_address=$external_media_address
|
||||
bind_rtp_to_media_address=yes
|
||||
EOF
|
||||
else
|
||||
cat > "$PJSIP_WEBRTC_FILE" <<'EOF'
|
||||
; Kein externes WebRTC-Media-Rewrite konfiguriert.
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "FEDEO Telefonie: Telekom-Trunk für $sip_user@$registrar erzeugt."
|
||||
|
||||
@@ -5,6 +5,8 @@ TELEPHONY_ENABLED=true
|
||||
TELEPHONY_ASTERISK_HTTP_URL=http://188.245.76.1:8088/ws
|
||||
TELEPHONY_ASTERISK_WS_URL=ws://188.245.76.1:8088/ws
|
||||
TELEPHONY_SIP_DOMAIN=188.245.76.1
|
||||
TELEPHONY_ASTERISK_EXTERNAL_SIGNALING_ADDRESS=188.245.76.1
|
||||
TELEPHONY_ASTERISK_EXTERNAL_MEDIA_ADDRESS=188.245.76.1
|
||||
TELEPHONY_ASTERISK_AMI_HOST=127.0.0.1
|
||||
TELEPHONY_ASTERISK_AMI_PORT=5038
|
||||
TELEPHONY_ASTERISK_AMI_USER=fedeo
|
||||
|
||||
Reference in New Issue
Block a user