Flexisip 2.4.1, Flexisip Account Manager on Podman

FlexisipのPodmanベースの動作検証(コンテナ)から開始し、コンテナからPod構成へ移行、最終的にはKubernetesクラスタ上での動作確認まで一連の検証を行います。

Podmanを利用したコンテナ構成では、Dockerによるそれと異なり、アカウントマネージャコンテナ(php-fpm)とFlexisipコンテナを完全分離します。

Flexisip Ver.2.4.1

  • Dockerfile
# https://wiki.linphone.org/xwiki/wiki/public/view/Flexisip/1.%20Installation/    
RUN echo 'deb [arch=amd64] http://linphone.org/snapshots/ubuntu jammy stable' > /etc/apt/sources.list.d/belledonne.list
RUN wget https://www.linphone.org/snapshots/ubuntu/pubkey.gpg -O - | apt-key add -
RUN apt-get update && apt-get install -y bc-flexisip

Flexisip Account Manager Ver.1.6

Lime Server Ver.1.3

File Transfer Server Ver.1.1

トラブルシュート

mysqli::real_connect(): (HY000/1040): Too many connections

MariaDB/MySQL の接続上限** (max_connections) を超えたため、新しい接続を拒否。アカウントマネージャの500エラー、SIPアカウントの登録エラー。

$ podman compose exec flexisip-mariadb bash
# mysql -u root -p
MariaDB [(none)]> SHOW FULL PROCESSLIST;
+-----+-----------------+----------------+----------+---------+------+-----------------------------+-----------------------+----------+
| Id  | User            | Host           | db       | Command | Time | State                       | Info                  | Progress |
+-----+-----------------+----------------+----------+---------+------+-----------------------------+-----------------------+----------+
|   1 | event_scheduler | localhost      | NULL     | Daemon  | 1132 | Waiting for next activation | NULL                  |    0.000 |
|   4 | flexisip        | 10.8.8.5:40800 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|   5 | flexisip        | 10.8.8.5:40804 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|   6 | flexisip        | 10.8.8.5:40806 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|   7 | flexisip        | 10.8.8.5:40818 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|   8 | flexisip        | 10.8.8.5:40828 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|   9 | flexisip        | 10.8.8.5:40830 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
|  10 | flexisip        | 10.8.8.5:40834 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
.....
.....
.....
| 153 | flexisip        | 10.8.8.5:42140 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
| 154 | flexisip        | 10.8.8.5:42146 | flexisip | Sleep   | 1132 |                             | NULL                  |    0.000 |
| 162 | root            | localhost      | NULL     | Query   |    0 | starting                    | SHOW FULL PROCESSLIST |    0.000 |
+-----+-----------------+----------------+----------+---------+------+-----------------------------+-----------------------+----------+
153 rows in set (0.001 sec)

原因はFlexisipの以下の設定でMariaDBのデフォルトの上限接続数が150を超えたため。以下のFlexisipで設定した接続数を見直すか、MariaDBコンテナの上限接続数を変更する環境変数 : --max-connections=500 をdocker-compose.ymlファイルに追加。

flexisip.conf

[presence-server]

# Max number of threads.
# Default: 50
rls-database-max-thread=50

[module::Authentication]

# Size of the pool of connections that Soci will use. A thread is
# opened for each DB query, and this pool will allow each thread
# to get a connection.
# The threads are blocked until a connection is released back to
# the pool, so increasing the pool size will allow more connections
# to occur simultaneously.
# On the other hand, you should not keep too many open connections
# to your DB at the same time.
# Default: 100
soci-poolsize=100

docker-compose.yml

##### mariadb
  mariadb-flexisip:
    container_name: mariadb-flexisip
    image: mariadb
    restart: unless-stopped
    ports:
      - 3306:3306
    command: --event-scheduler=ON --max-connections=500

flexisi-account-managerのfirebase環境変数名変更

flexisip-account-manager Ver.1.5以降APP_FLEXISIP_PUSHER_FIREBASE_KEY からAPP_FLEXISIP_PUSHER_FIREBASE_KEYSMAP へ変更

flexiapi/.env

APP_LINPHONE_DAEMON_UNIX_PATH=/tmp/ld
APP_FLEXISIP_PUSHER_PATH=/opt/belledonne-communications/bin/flexisip_pusher
# APP_FLEXISIP_PUSHER_FIREBASE_KEY=xxxxxxxxxx
APP_FLEXISIP_PUSHER_FIREBASE_KEYSMAP=xxxxxxxxxx

Podman REST API

Flexisip-Account-ManagerコンテナからFlexisipコンテナへのAPIリクエスト

Podmanを動かすユーザー側で以下を実行(podman composeコマンドを有効にするため既に実行済)。

$ systemctl --user enable --now podman.socket

これで Podman の REST API ソケットが起動します。パスは以下のようになります。

  • rootless(ユーザー): /run/user/1000/podman/podman.sock
  • root権限: /run/podman/podman.sock

Podman REST API : exec

rootlessモードのAPIソケットを、php-fpm(Laravel)コンテナと共有するため、ボリュームマッピングを追加。

このソケットを介して、flexisipコンテナのflexisip_pusherの実行をリクエストできるようにします。

docker-compose.yml

......
......
  php-fpm:
    container_name: php-fpm
    .....
    .....
    volumes:
      ......
      ......
      # for execution of flexisip_pusher on ubuntu-flexisip container by podman api socket
      - /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock
      .....
      .....

php-fpmコンテナ内でcurlによるテストを実施

実行セッションを作成(セッションID取得)

# curl --unix-socket /run/user/1000/podman/podman.sock  \
 -X POST http://d/v4.0.0/libpod/containers/ubuntu-flexisip/exec  \
 -H "Content-Type: application/json"  \
 -d '{                                                                                                                             
        "Cmd": ["/opt/belledonne-communications/bin/flexisip_pusher", "--pn-provider", "xxx", "--pn-param", "yyy", "--pn-prid", "zzz", "--customPayload", "{\"token\":\"abc123\"}"],
        "AttachStdout": true,
        "AttachStderr": true
      }'

{"Id":"45317c07503b74f6c807ac0cc85f8651eff882d8cf0857340236039c644340af"}

セッションIDを指定して実行

# curl --unix-socket /run/user/1000/podman/podman.sock  \
 -X POST http://d/v4.0.0/libpod/exec/45317c07503b74f6c807ac0cc85f8651eff882d8cf0857340236039c644340af/start  \
 -H "Content-Type: application/json"  \
 -d '{"Detach":false,"Tty":false,"AttachStdout":true,"AttachStderr":true}'  \
 --output -

VWriting logs in : /var/opt/belledonne-communications/log/flexisip/flexisip-pusher.log
DError, caught an unexpected exception: provider [xxx] not supported
O2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [B2bua]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [DoSProtection]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Authentication]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Capabilities]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [ContactRouteInserter]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Forward]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [GarbageIn]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [GatewayAdapter]...
V2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [LoadBalancer]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [MediaRelay]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [NatHelper]...
R2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Redirect]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Presence]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [PushNotification]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [RegEvent]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Registrar]...
�2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Router]...
2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [SanityChecker]...
]2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [StatisticsCollector]...
T2025-04-26 02:06:11:590 flexisip-message- Unregistering module info [Transcoder]...

sendToke() をAPIリクエスト対応へ入換え(追加箇所のみ掲載)

flexiapi/app/Libraries/FlexisipPusherConnector.php


use Illuminate\Support\Facades\Http;

   public function sendToken(string $token)
    {
        $payload = json_encode(['token' => $token]);
    
        if (!empty($this->pusherPath)) {

            $cmd = [
                $this->pusherPath,
                '--pn-provider', $this->pnProvider,
                '--pn-param', $this->pnParam,
                '--pn-prid', $this->pnPrid,
                '--customPayload', $payload,
            ];
    
            if (in_array($this->pnProvider, ['apns', 'apns.dev'])) {
                $cmd[] = '--apple-push-type';
                $cmd[] = 'Background';
            }
    
            if ($this->pusherFirebaseKey) {
                $cmd[] = '--key';
                $cmd[] = $this->pusherFirebaseKey;
            }
    
            $containerId = 'ubuntu-flexisip';
            $socketPath = '/run/user/1000/podman/podman.sock';
    
            // create exec session 
            $execCreate = Http::withOptions([
                'curl' => [
                    CURLOPT_UNIX_SOCKET_PATH => $socketPath,
                ]
            ])->withHeaders([
                'Content-Type' => 'application/json',
            ])->post("http://d/v4.0.0/libpod/containers/{$containerId}/exec", [
                'cmd' => $cmd,
                'tty' => false,
                'detach' => false,
            ]);
    
            if (!$execCreate->successful()) {
                Log::error('Failed to create exec session', ['body' => $execCreate->body()]);
                return false;
            }
    
            $execId = $execCreate->json()['Id'] ?? null;
            if (!$execId) {
                Log::error('Exec ID missing');
                return false;
            }
    
            // execute exec session
            $execStart = Http::withOptions([
                'curl' => [
                    CURLOPT_UNIX_SOCKET_PATH => $socketPath,
                ]
            ])->withHeaders([
                'Content-Type' => 'application/json',
            ])->post("http://d/v4.0.0/libpod/exec/{$execId}/start", [
                'Detach' => false,
                'Tty' => false,
            ]);
    
            if (!$execStart->successful()) {
                Log::error('Failed to start exec session', ['body' => $execStart->body()]);
                return false;
            }
    
            Log::info('Pusher executed via Podman', ['output' => $execStart->body()]);
            return true;
        }
    
        Log::error('Pusher path not configured');
        return false;
    }   

sendToken()テスト

tests/Feature/FlexisipPusherTest.php

<?php

namespace Tests\Feature;

use Tests\TestCase;
use App\Libraries\FlexisipPusherConnector;

class FlexisipPusherTest extends TestCase
{
    public function test_send_token()
    {
        // Dummy data for testing
        $provider = 'fcm';
        $param = 'yourappid';
        $prid = 'yourprid';
        $token = 'dummy_push_token';

        // Create instance
        $pusher = new FlexisipPusherConnector($provider, $param, $prid);

        // Execute
        $result = $pusher->sendToken($token);

        // Assert the result
        $this->assertTrue($result, 'Pusher should return true');
    }
}

テスト実行

# php artisan test --filter=FlexisipPusherTest

またはPHPUnitで直接実行

# vendor/bin/phpunit --filter=FlexisipPusherTest

flexisip_pusher help

# /opt/belledonne-communications/bin/flexisip_pusher --help
usage: /opt/belledonne-communications/bin/flexisip_pusher [options] --pn-provider {apns,apns.dev,fcm} --pn-param <param> --pn-prid <prid> [<prid> ...]

A tool to send push notifications to Android and iOS applications, based on parameters defined by RFC8599.

Mandatory parameters:
---------------------
  --pn-provider {apns,apns.dev,fcm}  The service in charge to send the push notification.
                                       * 'apns'     for iOS production applications;
                                       * 'apns.dev' for iOS development applications;
                                       * 'fcm'      for Android applications.

  --pn-param <param>                 Provider specific ID of the application.
                                       * Android:   Firebase Project ID.
                                       * iOS:       <TeamID>.<BundleID>[.voip], where '.voip' is only added
                                                    for VoIP push notification.


  --pn-prid <prid>                   Provider specific ID of the targeted application instance.
                                       * Android:   Registration token.
                                       * iOS:       Device token.


General options:
----------------
  -h, --help                         Show this help message and exit.
  --debug                            Print all debug messages on the standard output.

  --customPayload <payload>          Add custom parameters in the PN request body. <payload> must be a JSON structure
								     and will be placed in the top-level JSON attribute.

  --call-id <callID>                 Call-ID to use in the push notification payload.


Android specific options:
-------------------------
  --key <SecretKey>                  Specify the secret key to put in the HTTP/2 headers to be authenticated
                                     by Firebase push notification service.


iOS specific options:
---------------------
  --prefix <path>                    Path to the directory where the APNS certificates are stored. The certificates
                                     must actually be placed in a subdirectory named 'apns' just like a standard
                                     Flexisip configuration directory.

  --apple-push-type {Background,RemoteWithMutableContent,PushKit}
                                     The kind of push notification to send to the iOS device. Default: PushKit.
                                       * Background: only wake the application up without displaying anything to
                                         the user;
                                       * RemoteWithMutableContent: a message is displayed to the user;
                                       * PushKit: require the application to use CallKit API to display the incoming
                                         call view.

Examples:
---------
* Send a data push notification to an Android application:

    ./flexisip_pusher --key '<SecretKey>' --pn-provider 'fcm' --pn-param '<ProjectID>' --pn-prid '<token>'


* Send a data push notification to an Android application using FirebaseV1 API:

    ./flexisip_pusher --key '<FirebaseServiceAccountFile>' --pn-provider 'fcm' --pn-param '<ProjectID>' --pn-prid '<token>'


* Send a remote message push notification to an iOS production application:

    ./flexisip_pusher --prefix /etc/flexisip --pn-provider 'apns' --pn-param '<TeamID>.<BundleID>'
                      --pn-prid '<token>' --apple-push-type RemoteWithMutableContent


* Send a remote message push notification to an iOS development application:

    ./flexisip_pusher --prefix /etc/flexisip --pn-provider 'apns.dev' --pn-param '<TeamID>.<BundleID>'
                      --pn-prid '<token>' --apple-push-type RemoteWithMutableContent


* Send a VoIP push notification to an iOS production application:

    ./flexisip_pusher --prefix /etc/flexisip --pn-provider 'apns' --pn-param '<TeamID>.<BundleID>.voip'
                      --pn-prid '<token>' --apple-push-type PushKit


* Send a background push notification (remote PN without alert section) to an iOS production application:

    ./flexisip_pusher --prefix /etc/flexisip --pn-provider 'apns' --pn-param '<TeamID>.<BundleID>'
                      --pn-prid '<token>' --apple-push-type Background


Environment Variables:
----------------------
  FS_LOG_DIR    The directory to write logs into. Defaults to /var/opt/belledonne-communications/log/flexisip

Podによる構成

Podと役割

Pod名 ホスト名(コンテナ) 用途/サービス ポート公開
pod-nginx nginx.flexisip リバースプロキシ (Let’s Encrypt対応) 9080, 9443
pod-apache apache.flexisip HTTPファイル転送サーバ (HFT) 8080, 8443
pod-php-fpm php-fpm.flexisip LaravelベースのAccount Manager 9000
pod-mariadb mariadb.flexisip データベース (MariaDB) 3306
pod-phpmyadmin phpmyadmin.flexisip DB管理ツール 9000 (Nginx経由)
pod-redis redis.flexisip Redisキャッシュ 6379
pod-flexisip sip-proxy.flexisip Flexisipコア (SIP/UDP対応) 5060, 5061, 3478, 10000-10500/UDP

Network

$ podman network create \
  --subnet 10.8.8.0/24 \
  --ip-range 10.8.8.0/24 \
  --gateway 10.8.8.1 \
  --ipv6 \
  --subnet fd6c::8::/64 \
  --gateway fd6c::8::1 \
  net.flexisip

pod-redis

$ podman pod create \
  --name pod-redis \
  --hostname redis.flexisip \
  --network net.flexisip \
  --ip 10.8.8.2 \
  --ip6 fd6c::8::2 \
  -p 127.0.0.1:6379:6379

$ podman create \
  --name redis \
  --pod pod-redis \
  --restart=always \
  -v $(pwd)/redis:/etc/redis \
  redis:alpine \
  redis-server /etc/redis/redis.conf
  
$ echo 'vm.overcommit_memory=1' | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p

pod-nginx

$ podman pod create \
  --name pod-nginx \
  --hostname nginx.flexisip \
  --network net.flexisip \
  --ip 10.8.8.3 \
  --ip6 fd6c::8::3 \
  -p 8080:80 \
  -p 8443:443

$ podman create \
  --name nginx \
  --pod pod-nginx \
  --restart=always \
  -v $(pwd)/nginx:/etc/nginx/conf.d \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  -v $(pwd)/flexisip-account-manager/flexiapi:/var/www/html/flexiapi \
  -v phpmyadmin:/var/www/html/phpmyadmin \
  -v $(pwd)/lime-server/lime:/var/www/html/lime \
  nginx:alpine

pod-apache

$ podman pod create \
  --name pod-apache \
  --hostname apache.flexisip \
  --network net.flexisip \
  --ip 10.8.8.4 \
  --ip6 fd6c::8::4 \
  -p 9080:80 \
  -p 9443:443

$ podman create \
  --name apache \
  --pod pod-apache  \
  --restart=always \
  -v $(pwd)/apache/httpd_ft.conf:/usr/local/apache2/conf/httpd.conf \
  -v $(pwd)/apache/extra/httpd-ssl.conf:/usr/local/apache2/conf/extra/httpd-ssl.conf \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  -v $(pwd)/hft:/opt/belledonne-communications/share/flexisip-http-file-transfer-server \
  -v $(pwd)/hft-tmp:/var/opt/belledonne-communications/flexisip-http-file-transfer-tmp \
  -v $(pwd)/hft_conf/flexisip-http-file-transfer-server.conf:/etc/flexisip-http-file-transfer-server/flexisip-http-file-transfer-server.conf \
  -v $(pwd)/log/flexisip-http-file-transfer-server.log:/var/opt/belledonne-communications/log/flexisip-http-file-transfer-server.log \
  httpd:alpine

pod-mariadb

$ podman pod create \
  --name pod-mariadb \
  --hostname mariadb.flexisip \
  --network net.flexisip \
  --ip 10.8.8.5 \
  --ip6 fd6c::8::5 \
  -p 127.0.0.1:3306:3306

$ podman create \
  --pod pod-mariadb \
  --name mariadb \
  --restart=always \
  --env-file $(pwd)/.env \
  -v $(pwd)/db:/var/lib/mysql \
  mariadb:11.7 \
  --event-scheduler=ON \
  --max-connections=300

pod-flexisip

$ podman pod create \
  --name pod-flexisip \
  --hostname sip-proxy.flexisip \
  --network host
  
$ podman build -f $(pwd)/docker_files/flex-from-ubuntu22-apt-repo-24 -t ubuntu-flexisip:20250514 $(pwd)/docker_files

$ podman create \
  --pod pod-flexisip \
  --name flexisip \
  --restart=always \
  -v $(pwd)/letsencrypt:/etc/letsencrypt \
  -v $(pwd)/flexisip_conf:/etc/flexisip \
  -v $(pwd)/linphone:/root/.local/share/linphone \
  -v $(pwd)/tmp/ld:/tmp/ld \
  -v $(pwd)/firebase/flexisip-push-notification-firebase-adminsdk-fbsvc-xxxxxxxx.json:/etc/flexisip/flexisip-push-notification-firebase-adminsdk-fbsvc-xxxxxxxx.json \
  ubuntu-flexisip:20250514 ""

pod-php-fpm

$ podman pod create \
  --name pod-php-fpm \
  --hostname php-fpm.flexisip \
  --network net.flexisip \
  --ip 10.8.8.6 \
  --ip6 fd6c::8::6
  
$ podman build -f $(pwd)/docker_files/php-fpm-alpine-laravel -t php-fpm-8.2:20250514 $(pwd)

$ podman create \
  --pod pod-php-fpm \
  --name php-fpm \
  --restart=always \
  -v $(pwd)/php-fpm_conf/php.ini:/usr/local/etc/php/php.ini \
  -v $(pwd)/flexisip-account-manager/flexiapi:/var/www/html/flexiapi \
  -v $(pwd)/xmlrpc:/opt/belledonne-communications/share/flexisip-account-manager/xmlrpc \
  -v $(pwd)/tmp/ld:/tmp/ld \
  -v /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock \
  -v $(pwd)/firebase/flexisip-push-notification-firebase-adminsdk-fbsvc-xxxxxxxx.json:/etc/flexisip/flexisip-push-notification-firebase-adminsdk-fbsvc-xxxxxxxx.json \
  -v $(pwd)/hft:/opt/belledonne-communications/share/flexisip-http-file-transfer-server \
  -v $(pwd)/hft-tmp:/var/opt/belledonne-communications/flexisip-http-file-transfer-tmp \
  -v $(pwd)/hft_conf/flexisip-http-file-transfer-server.conf:/etc/flexisip-http-file-transfer-server/flexisip-http-file-transfer-server.conf \
  -v $(pwd)/log/flexisip-pusher.log:/var/opt/belledonne-communications/log/flexisip/flexisip-pusher.log \
  -v $(pwd)/log/flexisip-http-file-transfer-server.log:/var/opt/belledonne-communications/log/flexisip-http-file-transfer-server.log \
  -v $(pwd)/lime-server/lime:/var/www/html/lime \
  -v $(pwd)/lime-server/lime-server.conf:/etc/lime-server/lime-server.conf \
  -v $(pwd)/lime-server/log/lime-server:/var/opt/belledonne-communications/log/lime-server \
  -v $(pwd)/log/php_errors.log:/var/log/php/php_errors.log \
  php-fpm-8.2:20250514

pod-phpmyadmin

$ podman pod create \
  --name pod-phpmyadmin \
  --hostname phpmyadmin.flexisip \
  --network net.flexisip \
  --ip 10.8.8.7 \
  --ip6 fd6c::8::7
  
$ podman volume create phpmyadmin

$ podman create \
  --pod pod-phpmyadmin \
  --name phpmyadmin \
  --restart=always \
  -e PMA_HOST=mariadb.flexisip \
  -e PMA_PORT=3306 \
  -e PMA_ABSOLUTE_URI=http://localhost/phpmyadmin \
  -v phpmyadmin:/var/www/html \
  -v /sessions \
  phpmyadmin/phpmyadmin:fpm-alpine

上記一連のコマンドでPodを作成し内部にコンテナを配置したらPodman-Desktopで各Podをスタートします。

Podリスト

コンテナリスト

podman composeによるコンテナ運用からpodによる運用へ移行した場合、NginxのFast_CGIパス、Redis、MariaDBへのIPなどを再設定する必要があります。以下再設定が必要なファイルです。

flexisip-account-manager/flexiapi/.env
nginx/default.conf
nginx/lime.conf
lime-server/lime-server.conf
hft_conf/flexisip-http-file-transfer-server.conf


リモート操作

podman(desktop)からのリモート操作については下記参照。