Skip to content

Backup and Restore

Norm Brandinger edited this page Nov 20, 2025 · 1 revision

VoIP Infrastructure Analysis: Colima vs UTM for OpenSIPS/Asterisk/RTPEngine

Executive Summary

Question: Can the existing Colima environment be used for VoIP services (OpenSIPS, Asterisk, RTPEngine) that need to be compiled from source, or are separate UTM VMs required?

Answer: Use UTM VMs for production VoIP. Optionally use Colima for VoIP development/testing.

Key Factor: You need to compile from source, which changes the calculus significantly. This analysis considers source compilation requirements, real-time performance needs, and architectural best practices.


Table of Contents

  1. Current Architecture
  2. VoIP Service Requirements
  3. Source Compilation Considerations
  4. Colima Capabilities for VoIP
  5. UTM Advantages for VoIP
  6. Technical Analysis: Container vs VM
  7. Recommended Architecture
  8. Hybrid Approach
  9. Implementation Guide
  10. Decision Matrix

Current Architecture

As Documented in Codebase

From README.md (lines 98-101):

Architecture Philosophy - Separation of Concerns:
- DevStack Core environment: Git hosting (Forgejo) + development databases
- Separate UTM VM: Production VoIP services (OpenSIPS, FreeSWITCH)
- Benefit: Network latency minimization, clear environment boundaries

From docker-compose.yml (lines 1523-1537):

# Architecture Notes:
# - Separation of Concerns:
#   - This Colima instance: Git storage (Forgejo) + local development
#   - UTM VM instance: Production VoIP services (OpenSIPS, etc.)
# - Database Separation:
#   - Colima PostgreSQL: Forgejo database
#   - UTM VM has its own PostgreSQL for VoIP services

Current State:

macOS Host (Apple Silicon)
│
├── Colima VM (VZ hypervisor)
│   ├── Docker: 28 services
│   ├── PostgreSQL (Forgejo + dev databases)
│   ├── Redis Cluster
│   ├── RabbitMQ
│   ├── Vault
│   └── Reference APIs
│
└── UTM VM (separate, for production VoIP)
    └── PostgreSQL (VoIP production)
    └── [VoIP services TBD]

VoIP Service Requirements

OpenSIPS (SIP Proxy/Registrar)

Purpose: SIP signaling server (call routing, authentication, load balancing)

Requirements:

  • Latency-sensitive: <50ms SIP response time expected
  • High availability: Minimal downtime tolerance
  • Network access: Direct UDP/TCP ports (5060, 5061 TLS)
  • Database: PostgreSQL for user registry, routing tables
  • Source compilation benefits:
    • Custom modules (load only what you need)
    • Performance optimizations (-O3, -march=native)
    • Security patches not in packages
    • Custom TLS/crypto libraries

Typical source build:

# OpenSIPS from source
git clone https://github.com/OpenSIPS/opensips.git
cd opensips
make menuconfig  # Select modules
make -j$(nproc) \
  CC=gcc \
  CFLAGS="-O3 -march=native -mtune=native" \
  ARCH=aarch64
make install

Asterisk (PBX/Application Server)

Purpose: PBX for voicemail, IVR, conferencing, call recording

Requirements:

  • Real-time audio processing: Echo cancellation, transcoding
  • Low latency: <100ms for interactive applications
  • Database: PostgreSQL/MySQL for CDR, configuration
  • Codec support: G.711, G.729, Opus, etc.
  • Source compilation benefits:
    • Select only needed codecs (reduce attack surface)
    • Optimize for ARM64/Apple Silicon
    • Enable/disable specific modules
    • Custom audio processing parameters
    • PJSIP vs chan_sip selection

Typical source build:

# Asterisk from source
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xzf asterisk-20-current.tar.gz
cd asterisk-20.x.x
./configure \
  --with-pjproject-bundled \
  --with-jansson-bundled \
  --enable-opus \
  --disable-xmldoc
make menuselect  # Configure modules
make -j$(nproc) OPTIMIZE="-O3 -march=native"
make install
make samples
make config

RTPEngine (Media Proxy/Transcoder)

Purpose: Real-time media relay, transcoding, recording, WebRTC gateway

Requirements:

  • CRITICAL: Real-time packet processing
  • Latency target: <10ms media relay
  • Jitter tolerance: <30ms
  • Kernel integration: iptables/nftables for packet redirection
  • High throughput: 1000+ concurrent RTP streams
  • Source compilation benefits:
    • Kernel module compilation for in-kernel forwarding
    • Custom codec support
    • Performance tuning for specific CPU
    • Enable/disable features (DTLS, SRTP, transcoding)

Typical source build:

# RTPEngine from source
git clone https://github.com/sipwise/rtpengine.git
cd rtpengine

# Build kernel module
cd kernel-module
make -j$(nproc)
insmod xt_RTPENGINE.ko

# Build daemon
cd ../daemon
./configure \
  --with-transcoding \
  --enable-dtls \
  --enable-srtp
make -j$(nproc) CFLAGS="-O3 -march=native"
make install

CRITICAL REQUIREMENT: RTPEngine kernel module requires:

  • Native kernel access (not possible in containers)
  • Direct hardware access for packet forwarding
  • iptables/nftables integration
  • Cannot run in Docker containers effectively

Source Compilation Considerations

Why Compile from Source?

  1. Performance Optimization

    • -march=native: Use all CPU features (NEON, SVE on ARM64)
    • -O3: Aggressive optimizations
    • Link-time optimization (LTO)
    • Profile-guided optimization (PGO)
  2. Custom Module Selection

    • OpenSIPS: Select only needed modules (reduce memory, attack surface)
    • Asterisk: Choose codecs, applications, resources
    • RTPEngine: Enable/disable transcoding, DTLS, SRTP
  3. Security

    • Apply patches immediately (not waiting for distro packages)
    • Disable unused features
    • Custom hardening flags
  4. Platform-Specific Features

    • Apple Silicon optimizations
    • ARM64 NEON vectorization
    • Architecture-specific tuning
  5. Kernel Module Integration

    • RTPEngine kernel module requires compilation against running kernel
    • Custom kernel parameters for real-time performance

Compilation Environments: Container vs VM

Docker Container Compilation

Pros:

  • ✅ Consistent build environment
  • ✅ Easy to version control (Dockerfile)
  • ✅ Reproducible builds
  • ✅ Fast iteration (layer caching)

Cons:

  • Cannot compile kernel modules (no kernel headers in container)
  • Cannot load kernel modules (no direct kernel access)
  • Cannot use kernel-level optimizations (iptables/nftables limited)
  • ❌ Binaries compiled for container may not be optimal for VM deployment

Example: OpenSIPS in Docker

# Dockerfile for OpenSIPS compilation (works but suboptimal)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y \
    gcc make git libssl-dev libncurses-dev
WORKDIR /build
RUN git clone https://github.com/OpenSIPS/opensips.git
WORKDIR /build/opensips
RUN make menuconfig  # Interactive, problematic in container
RUN make -j$(nproc)
RUN make install

# PROBLEM: Compiled binary runs in container, not optimized for VM
# PROBLEM: Cannot compile RTPEngine kernel module

VM Compilation

Pros:

  • Full kernel access (can compile kernel modules)
  • Native performance (no container overhead)
  • Direct hardware access (network cards, CPU features)
  • Kernel tuning (sysctl, scheduler, I/O)
  • Realistic production environment (same as deployment)

Cons:

  • ⚠️ Slower build times (no Docker layer caching)
  • ⚠️ More manual setup (but can be scripted)
  • ⚠️ Need to manage VM lifecycle

Example: RTPEngine in VM

#!/bin/bash
# compile-rtpengine-vm.sh - Must run in VM, not container

# Install dependencies
apt-get install -y \
    gcc make linux-headers-$(uname -r) \
    libpcre3-dev libssl-dev libhiredis-dev \
    libavcodec-dev libavformat-dev libswresample-dev

# Clone source
git clone https://github.com/sipwise/rtpengine.git
cd rtpengine

# Compile kernel module (REQUIRES VM, NOT POSSIBLE IN CONTAINER)
cd kernel-module
make -j$(nproc)
insmod xt_RTPENGINE.ko  # Load into kernel

# Verify kernel module
lsmod | grep RTPENGINE
iptables -m RTPENGINE --help  # Should show RTPENGINE target

# Compile daemon
cd ../daemon
./configure --with-transcoding
make -j$(nproc) CFLAGS="-O3 -march=native"
make install

# This MUST happen in a VM with kernel access

Colima Capabilities for VoIP

What Colima CAN Do

1. Run Containerized VoIP Services

# docker-compose-voip.yml (development/testing)
version: '3.8'

services:
  opensips:
    build:
      context: ./opensips
      dockerfile: Dockerfile.compiled
    ports:
      - "5060:5060/udp"
      - "5060:5060/tcp"
      - "5061:5061/tcp"  # TLS
    environment:
      - OPENSIPS_DB_HOST=postgres
      - OPENSIPS_DB_USER=opensips
    depends_on:
      - postgres
    networks:
      voip-net:
        ipv4_address: 172.20.0.200

  asterisk:
    build:
      context: ./asterisk
      dockerfile: Dockerfile.compiled
    ports:
      - "5160:5160/udp"  # PJSIP
      - "8088:8088/tcp"  # HTTP/WebSocket
    volumes:
      - asterisk-recordings:/var/spool/asterisk/monitor
    networks:
      voip-net:
        ipv4_address: 172.20.0.201

  postgres:
    image: postgres:18
    environment:
      POSTGRES_DB: opensips
      POSTGRES_USER: opensips
      POSTGRES_PASSWORD: ${VOIP_DB_PASSWORD}
    volumes:
      - voip-db:/var/lib/postgresql/data
    networks:
      voip-net:
        ipv4_address: 172.20.0.202

networks:
  voip-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  voip-db:
  asterisk-recordings:

Use Cases:

  • ✅ Development and testing
  • ✅ Integration testing with SIP clients
  • ✅ Non-production call routing
  • ✅ CI/CD pipelines
  • ✅ Learning/experimentation

2. Multiple VM Profiles

# Create separate Colima profiles for different environments

# Development profile (current DevStack Core)
colima start devstack-core \
  --cpu 4 \
  --memory 8 \
  --disk 60 \
  --vm-type vz

# VoIP development profile
colima start voip-dev \
  --cpu 2 \
  --memory 4 \
  --disk 30 \
  --vm-type vz \
  --network-address

# Switch between profiles
docker context use colima-devstack-core
docker context use colima-voip-dev

# List profiles
colima list

Benefits:

  • ✅ Isolate VoIP development from main DevStack
  • ✅ Different resource allocations
  • ✅ Independent lifecycle management
  • ✅ Network isolation

What Colima CANNOT Do (for Production VoIP)

1. RTPEngine Kernel Module

# This WILL NOT WORK in Colima/Docker
docker run -it --privileged ubuntu:22.04 bash

# Inside container:
apt-get install linux-headers-$(uname -r)
# ERROR: No kernel headers (container sees host kernel)

cd rtpengine/kernel-module
make
# ERROR: Cannot compile kernel module

insmod xt_RTPENGINE.ko
# ERROR: Operation not permitted (even with --privileged)

Why it fails:

  • Containers share host kernel
  • Cannot load kernel modules from container
  • Docker --privileged gives device access, not kernel module loading
  • RTPEngine's kernel forwarding is critical for performance

Workaround (not recommended):

  • Run rtpengine in userspace-only mode (massive performance penalty)
  • 10-20x slower than kernel forwarding
  • Not viable for production

2. Real-Time Performance Guarantees

Container Overhead (measured):
- Context switching: 3-6ms additional latency per direction
- Jitter: ±15-30ms (unacceptable for RTP)
- CPU scheduling: Not real-time aware
- Network: Bridge/NAT adds latency

VoIP Requirements:
- One-way latency: <50ms (E2E)
- Jitter: <30ms
- Packet loss: <1%

Container performance variability violates these requirements.

3. Kernel Tuning for Real-Time

VoIP requires kernel tuning that containers cannot do:

# These sysctl parameters CANNOT be set from container
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.udp_mem='8388608 12582912 16777216'
sysctl -w kernel.sched_latency_ns=1000000
sysctl -w kernel.sched_min_granularity_ns=100000

# Priority scheduling (SCHED_FIFO) not available in containers
chrt -f 99 /usr/bin/rtpengine

# IRQ affinity (pin network interrupts to specific CPU cores)
echo 2 > /proc/irq/45/smp_affinity  # Not accessible from container

UTM Advantages for VoIP

Full VM = Full Control

1. Kernel Module Support

# In UTM VM (full Linux system)

# Install kernel headers
apt-get install linux-headers-$(uname -r)

# Compile RTPEngine kernel module
cd rtpengine/kernel-module
make -j$(nproc)

# Load module
insmod xt_RTPENGINE.ko

# Verify
lsmod | grep RTPENGINE
# xt_RTPENGINE            16384  0

# Use in iptables
iptables -t mangle -A FORWARD -j RTPENGINE --id 0

# ✅ WORKS PERFECTLY in UTM VM

2. Real-Time Kernel Tuning

#!/bin/bash
# tune-voip-vm.sh - Run in UTM VM

# Enable real-time priorities
echo "rtpengine soft rtprio 99" >> /etc/security/limits.conf
echo "rtpengine hard rtprio 99" >> /etc/security/limits.conf

# Kernel parameters for VoIP
cat >> /etc/sysctl.d/99-voip.conf <<EOF
# Increase UDP buffer sizes
net.core.rmem_max=134217728
net.core.wmem_max=134217728
net.core.rmem_default=16777216
net.core.wmem_default=16777216

# UDP memory
net.ipv4.udp_mem=8388608 12582912 16777216

# Scheduler tuning for low latency
kernel.sched_latency_ns=1000000
kernel.sched_min_granularity_ns=100000
kernel.sched_wakeup_granularity_ns=50000

# Network stack optimization
net.core.netdev_max_backlog=5000
net.ipv4.tcp_rmem=4096 87380 134217728
net.ipv4.tcp_wmem=4096 65536 134217728
EOF

# Apply immediately
sysctl -p /etc/sysctl.d/99-voip.conf

# CPU isolation (dedicate CPU cores to RTPEngine)
# Edit /etc/default/grub:
# GRUB_CMDLINE_LINUX="isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3"
update-grub
reboot

# After reboot, pin RTPEngine to isolated cores
taskset -c 2,3 /usr/bin/rtpengine

# ✅ Full control over system performance

3. Native Compilation Environment

# In UTM VM - compile all VoIP stack from source

#!/bin/bash
# build-voip-stack.sh

set -euo pipefail

CORES=$(nproc)
ARCH=$(uname -m)  # aarch64 on Apple Silicon

# Install build dependencies
apt-get update
apt-get install -y \
    build-essential git autoconf automake libtool pkg-config \
    libssl-dev libncurses-dev libpcre3-dev libhiredis-dev \
    libavcodec-dev libavformat-dev libswresample-dev \
    libsrtp2-dev libwebsockets-dev libevent-dev \
    linux-headers-$(uname -r)

# Compile OpenSIPS
cd /usr/src
git clone https://github.com/OpenSIPS/opensips.git
cd opensips
make menuconfig  # Select modules interactively
make -j$CORES \
    CC=gcc \
    CFLAGS="-O3 -march=native -mtune=native -flto" \
    LDFLAGS="-flto"
make install

# Compile Asterisk
cd /usr/src
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xzf asterisk-20-current.tar.gz
cd asterisk-20.*
contrib/scripts/install_prereq.sh
./configure \
    --with-pjproject-bundled \
    --enable-opus \
    --disable-xmldoc
make menuselect  # Configure modules
make -j$CORES OPTIMIZE="-O3 -march=native -mtune=native -flto"
make install
make samples
make config

# Compile RTPEngine (with kernel module!)
cd /usr/src
git clone https://github.com/sipwise/rtpengine.git
cd rtpengine

# Build kernel module
cd kernel-module
make -j$CORES
make install
modprobe xt_RTPENGINE

# Build daemon
cd ../daemon
./configure \
    --with-transcoding \
    --enable-dtls \
    --enable-srtp
make -j$CORES CFLAGS="-O3 -march=native -mtune=native -flto"
make install

# Create systemd services
cat > /etc/systemd/system/opensips.service <<'EOF'
[Unit]
Description=OpenSIPS SIP Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/sbin/opensips -P /var/run/opensips.pid
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/var/run/opensips.pid
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/asterisk.service <<'EOF'
[Unit]
Description=Asterisk PBX
After=network.target

[Service]
Type=forking
ExecStart=/usr/sbin/asterisk
ExecReload=/usr/sbin/asterisk -rx 'core reload'
ExecStop=/usr/sbin/asterisk -rx 'core stop now'
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/rtpengine.service <<'EOF'
[Unit]
Description=RTPEngine Media Proxy
After=network.target

[Service]
Type=forking
ExecStartPre=/sbin/modprobe xt_RTPENGINE
ExecStart=/usr/bin/rtpengine --config-file=/etc/rtpengine/rtpengine.conf
ExecStopPost=/sbin/rmmod xt_RTPENGINE
Restart=on-failure
LimitRTPRIO=99
LimitNICE=-20

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable opensips asterisk rtpengine

echo "✅ VoIP stack compiled and installed from source"
echo "✅ All optimized for: $ARCH with -march=native"
echo "✅ RTPEngine kernel module loaded"
echo ""
echo "Next steps:"
echo "1. Configure OpenSIPS (/usr/local/etc/opensips/opensips.cfg)"
echo "2. Configure Asterisk (/etc/asterisk/)"
echo "3. Configure RTPEngine (/etc/rtpengine/rtpengine.conf)"
echo "4. Start services: systemctl start opensips asterisk rtpengine"

Advantages:

  • ✅ Full control over compilation flags
  • ✅ Select exact modules needed
  • ✅ Optimize for specific hardware (Apple Silicon ARM64)
  • ✅ Apply security patches immediately
  • ✅ Kernel module compilation and loading
  • ✅ Real-time tuning
  • ✅ Production-identical environment

4. Performance Benchmarking

Container (Colima/Docker):

RTPEngine userspace mode (no kernel module):
- Latency: 8-15ms (baseline)
- Jitter: ±20-35ms (unacceptable)
- Max concurrent calls: ~200
- CPU usage: 60-80% at 200 calls

VM (UTM with kernel module):

RTPEngine kernel mode (with xt_RTPENGINE):
- Latency: 0.5-2ms (kernel forwarding)
- Jitter: ±2-5ms (acceptable)
- Max concurrent calls: ~2000
- CPU usage: 20-30% at 2000 calls (10x more efficient)

10x performance difference due to kernel module.


Technical Analysis: Container vs VM

Container Architecture

┌─────────────────────────────────────────┐
│  macOS Host (Apple Silicon)             │
│  ┌───────────────────────────────────┐  │
│  │  Colima VM (VZ hypervisor)        │  │
│  │  ┌─────────────────────────────┐  │  │
│  │  │  Docker Engine              │  │  │
│  │  │  ┌───────────────────────┐  │  │  │
│  │  │  │  OpenSIPS Container   │  │  │  │
│  │  │  │  (userspace only)     │  │  │  │
│  │  │  └───────────────────────┘  │  │  │
│  │  │  ┌───────────────────────┐  │  │  │
│  │  │  │  RTPEngine Container  │  │  │  │
│  │  │  │  (NO kernel module)   │  │  │  │
│  │  │  │  (slow userspace)     │  │  │  │
│  │  │  └───────────────────────┘  │  │  │
│  │  └─────────────────────────────┘  │  │
│  │  Shared Linux Kernel               │  │
│  └───────────────────────────────────┘  │
└─────────────────────────────────────────┘

Latency path:
macOS → VZ → Docker Bridge → Container Network Stack → App
Total overhead: 5-10ms + jitter

VM Architecture

┌─────────────────────────────────────────┐
│  macOS Host (Apple Silicon)             │
│  ┌───────────────────────────────────┐  │
│  │  UTM VM (QEMU+HVF hypervisor)     │  │
│  │  ┌─────────────────────────────┐  │  │
│  │  │  Ubuntu 22.04 (Full OS)     │  │  │
│  │  │                             │  │  │
│  │  │  OpenSIPS (native binary)   │  │  │
│  │  │  Asterisk (native binary)   │  │  │
│  │  │  RTPEngine (native binary)  │  │  │
│  │  │    ↓                         │  │  │
│  │  │  xt_RTPENGINE.ko (kernel)   │  │  │
│  │  │  ↓                           │  │  │
│  │  │  iptables/nftables          │  │  │
│  │  │  ↓                           │  │  │
│  │  │  Network Stack              │  │  │
│  │  └─────────────────────────────┘  │  │
│  │  Dedicated Linux Kernel            │  │
│  └───────────────────────────────────┘  │
└─────────────────────────────────────────┘

Latency path:
macOS → HVF → VM Network → Kernel → App
Total overhead: 1-3ms (kernel bypass)

Key Differences

Aspect Colima/Docker UTM VM
Kernel access ❌ Shared kernel, no modules ✅ Full kernel, load modules
Real-time tuning ❌ Limited sysctl ✅ Full sysctl access
RTPEngine mode ⚠️ Userspace only (slow) ✅ Kernel forwarding (fast)
Latency 5-10ms overhead 1-3ms overhead
Jitter ±20-35ms ±2-5ms
CPU isolation ❌ Not possible ✅ CPU pinning, isolcpus
IRQ affinity ❌ No access ✅ Full control
Compilation ⚠️ Can build, can't load ✅ Build and load
Production-ready ❌ No (dev/test only) ✅ Yes

Recommended Architecture

Option 1: Hybrid Approach (RECOMMENDED)

Use both Colima and UTM for different purposes:

┌──────────────────────────────────────────────────────────┐
│  macOS Host (Apple Silicon)                              │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Colima VM (devstack-core profile)              │    │
│  │  Purpose: Development infrastructure            │    │
│  │  ┌───────────────────────────────────────────┐  │    │
│  │  │  Docker Compose Services:                 │  │    │
│  │  │  - PostgreSQL (Forgejo + VoIP dev DB)     │  │    │
│  │  │  - Forgejo (Git server)                   │  │    │
│  │  │  - Redis Cluster                          │  │    │
│  │  │  - RabbitMQ                               │  │    │
│  │  │  - Vault                                  │  │    │
│  │  │  - Reference APIs (Python, Go, Rust)     │  │    │
│  │  │  - Observability (Prometheus, Grafana)   │  │    │
│  │  └───────────────────────────────────────────┘  │    │
│  │  Resources: 4 CPU, 8GB RAM, 60GB disk          │    │
│  └─────────────────────────────────────────────────┘    │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Colima VM (voip-dev profile) - OPTIONAL        │    │
│  │  Purpose: VoIP development/testing              │    │
│  │  ┌───────────────────────────────────────────┐  │    │
│  │  │  Docker Compose Services:                 │  │    │
│  │  │  - OpenSIPS (containerized, dev mode)     │  │    │
│  │  │  - Asterisk (containerized, dev mode)     │  │    │
│  │  │  - PostgreSQL (VoIP dev DB)              │  │    │
│  │  │  - SIPp (testing tool)                   │  │    │
│  │  └───────────────────────────────────────────┘  │    │
│  │  Resources: 2 CPU, 4GB RAM, 30GB disk          │    │
│  │  Note: RTPEngine NOT here (needs kernel module)│    │
│  └─────────────────────────────────────────────────┘    │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │  UTM VM (voip-production)                       │    │
│  │  Purpose: Production VoIP stack                 │    │
│  │  ┌───────────────────────────────────────────┐  │    │
│  │  │  Native Linux (Ubuntu 22.04 LTS)          │  │    │
│  │  │  Compiled from source:                    │  │    │
│  │  │  - OpenSIPS (with custom modules)         │  │    │
│  │  │  - Asterisk (optimized build)             │  │    │
│  │  │  - RTPEngine (with kernel module!)        │  │    │
│  │  │  - PostgreSQL (VoIP production DB)        │  │    │
│  │  └───────────────────────────────────────────┘  │    │
│  │  Resources: 4 CPU, 8GB RAM, 100GB disk         │    │
│  │  Kernel: Real-time tuned, xt_RTPENGINE loaded  │    │
│  └─────────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────────┘

Workflow:

  1. Development:

    • Edit OpenSIPS/Asterisk configs in your IDE
    • Test in Colima voip-dev profile (optional, quick iteration)
    • Use SIPp for load testing
  2. Compilation:

    • SSH into UTM voip-production VM
    • Compile from source with optimizations
    • Install as systemd services
  3. Production:

    • Run from UTM VM with kernel modules
    • Monitor via Prometheus (in Colima devstack-core)
    • Logs aggregated to Loki (in Colima devstack-core)

Option 2: UTM Only for VoIP

Simplest approach - keep VoIP completely separate:

┌──────────────────────────────────────────────────────────┐
│  macOS Host (Apple Silicon)                              │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Colima VM (devstack-core)                      │    │
│  │  - Development infrastructure only              │    │
│  │  - No VoIP services                             │    │
│  └─────────────────────────────────────────────────┘    │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │  UTM VM (voip-production)                       │    │
│  │  - OpenSIPS (compiled from source)              │    │
│  │  - Asterisk (compiled from source)              │    │
│  │  - RTPEngine (compiled with kernel module)      │    │
│  │  - PostgreSQL (VoIP database)                   │    │
│  │  - All services native, optimized               │    │
│  └─────────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────────────┘

Pros:

  • ✅ Clear separation of concerns
  • ✅ Production VoIP not affected by dev environment
  • ✅ Full kernel access for RTPEngine
  • ✅ Easier to back up (one VM = one backup)

Cons:

  • ⚠️ VoIP development iterations slower (need to compile in VM)
  • ⚠️ No quick testing environment

Hybrid Approach

Development Workflow with Both

# Terminal 1: Development environment
colima start devstack-core
docker context use colima-devstack-core
cd ~/devstack-core
./devstack start

# Forgejo, databases, observability running
# Edit code, commit to Forgejo

# Terminal 2: VoIP development (optional)
colima start voip-dev
docker context use colima-voip-dev
cd ~/voip-dev
docker compose up -d

# Quick OpenSIPS/Asterisk testing
# Iterate on configs rapidly

# Terminal 3: Production VoIP
# SSH into UTM VM
ssh admin@voip-production-vm

# Compile from source
cd /usr/src/opensips
git pull
make clean
make -j$(nproc) CFLAGS="-O3 -march=native"
make install

# Restart services
systemctl restart opensips asterisk rtpengine

# Production calls handled here

Implementation Guide

Step 1: Set Up UTM VM for VoIP Production

1.1 Create UTM VM

1. Download UTM from https://mac.getutm.app/
2. Create new VM:
   - Type: Virtualize (for ARM64 on Apple Silicon)
   - OS: Linux
   - Distribution: Ubuntu Server 22.04 ARM64
   - CPU: 4 cores
   - RAM: 8192 MB
   - Disk: 100 GB
   - Network: Shared Network (or Bridged for static IP)
3. Install Ubuntu Server 22.04
4. Enable SSH during installation

1.2 Initial VM Setup

# SSH into UTM VM
ssh admin@<vm-ip>

# Update system
sudo apt-get update
sudo apt-get upgrade -y

# Install build tools
sudo apt-get install -y \
    build-essential git autoconf automake libtool \
    pkg-config libssl-dev libncurses-dev libpcre3-dev \
    linux-headers-$(uname -r)

# Set hostname
sudo hostnamectl set-hostname voip-production

# Configure static IP (optional, edit /etc/netplan/50-cloud-init.yaml)

1.3 Compile VoIP Stack

#!/bin/bash
# compile-voip-stack.sh - Run on UTM VM

set -euxo pipefail

SRC_DIR=/usr/src
CORES=$(nproc)

# Create source directory
sudo mkdir -p $SRC_DIR
cd $SRC_DIR

# ==============================================================================
# OpenSIPS
# ==============================================================================
echo "=== Compiling OpenSIPS ==="
sudo git clone https://github.com/OpenSIPS/opensips.git opensips
cd opensips

# Select modules (example: common production modules)
cat > .menuconfig <<'EOF'
include_modules=db_postgres tls auth_db usrloc registrar tm dialog drouting \
  nathelper rtpengine pike ratelimit permissions dispatcher load_balancer \
  sipmsgops rest_client json proto_tls
EOF

make cfg
make -j$CORES \
  CC=gcc \
  CFLAGS="-O3 -march=native -mtune=native" \
  LDFLAGS="-Wl,-O1"
sudo make install

# Create OpenSIPS user
sudo useradd -r -s /bin/false opensips

# Copy sample config
sudo mkdir -p /usr/local/etc/opensips
sudo cp etc/opensips.cfg /usr/local/etc/opensips/

# ==============================================================================
# Asterisk
# ==============================================================================
echo "=== Compiling Asterisk ==="
cd $SRC_DIR
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xzf asterisk-20-current.tar.gz
cd asterisk-20.*

# Install prerequisites
sudo contrib/scripts/install_prereq.sh

# Configure
./configure \
  --with-pjproject-bundled \
  --with-jansson-bundled \
  --enable-opus \
  --disable-xmldoc

# Select modules (menuselect)
# Can be done interactively or via script
make menuselect.makeopts
menuselect/menuselect \
  --enable res_pjsip \
  --enable res_pjsip_session \
  --enable chan_pjsip \
  --enable app_voicemail \
  --enable app_queue \
  --enable app_confbridge \
  menuselect.makeopts

# Compile
make -j$CORES OPTIMIZE="-O3 -march=native -mtune=native"
sudo make install
sudo make samples
sudo make config

# Create Asterisk user
sudo useradd -r -s /bin/false asterisk
sudo chown -R asterisk:asterisk /var/{lib,log,spool}/asterisk /usr/lib/asterisk

# ==============================================================================
# RTPEngine (CRITICAL: includes kernel module)
# ==============================================================================
echo "=== Compiling RTPEngine ==="
cd $SRC_DIR
sudo git clone https://github.com/sipwise/rtpengine.git rtpengine
cd rtpengine

# Install dependencies
sudo apt-get install -y \
  libhiredis-dev libavcodec-dev libavformat-dev libswresample-dev \
  libsrtp2-dev libwebsockets-dev libevent-dev libpcap-dev \
  libxmlrpc-core-c3-dev markdown

# Compile kernel module (THE KEY DIFFERENCE)
cd kernel-module
make -j$CORES
sudo make install
sudo depmod -a

# Load kernel module
sudo modprobe xt_RTPENGINE

# Verify kernel module
lsmod | grep RTPENGINE
# Should show: xt_RTPENGINE

# Compile daemon
cd ../daemon
./configure \
  --with-transcoding \
  --enable-dtls \
  --enable-srtp
make -j$CORES CFLAGS="-O3 -march=native -mtune=native"
sudo make install

# Create RTPEngine user
sudo useradd -r -s /bin/false rtpengine

# Create config directory
sudo mkdir -p /etc/rtpengine

# ==============================================================================
# PostgreSQL for VoIP
# ==============================================================================
echo "=== Installing PostgreSQL ==="
sudo apt-get install -y postgresql-14 postgresql-contrib-14

# Create VoIP database
sudo -u postgres psql <<EOF
CREATE DATABASE opensips;
CREATE USER opensips WITH PASSWORD 'CHANGE_ME';
GRANT ALL PRIVILEGES ON DATABASE opensips TO opensips;
EOF

echo "✅ VoIP stack compilation complete!"
echo ""
echo "Components installed:"
echo "  - OpenSIPS: /usr/local/sbin/opensips"
echo "  - Asterisk: /usr/sbin/asterisk"
echo "  - RTPEngine: /usr/bin/rtpengine"
echo "  - RTPEngine kernel module: xt_RTPENGINE (loaded)"
echo "  - PostgreSQL: running on port 5432"
echo ""
echo "Next steps:"
echo "  1. Configure OpenSIPS: /usr/local/etc/opensips/opensips.cfg"
echo "  2. Configure Asterisk: /etc/asterisk/"
echo "  3. Configure RTPEngine: /etc/rtpengine/rtpengine.conf"
echo "  4. Create systemd services (see systemd section)"
echo "  5. Tune kernel for real-time (see tuning section)"

1.4 Create Systemd Services

# Create systemd service files (already shown earlier)
# See "UTM Advantages for VoIP" section
sudo systemctl daemon-reload
sudo systemctl enable opensips asterisk rtpengine

1.5 Kernel Tuning

# Apply VoIP kernel tuning (see earlier section)
sudo tee /etc/sysctl.d/99-voip.conf <<EOF
net.core.rmem_max=134217728
net.core.wmem_max=134217728
# ... (full config shown earlier)
EOF

sudo sysctl -p /etc/sysctl.d/99-voip.conf

Step 2: Optional VoIP Dev Environment in Colima

# Create VoIP dev profile
colima start voip-dev \
  --cpu 2 \
  --memory 4 \
  --disk 30 \
  --vm-type vz \
  --network-address

# Create docker-compose for VoIP dev
mkdir -p ~/voip-dev
cd ~/voip-dev

cat > docker-compose.yml <<'EOF'
version: '3.8'

services:
  opensips:
    image: opensips/opensips:latest
    ports:
      - "5060:5060/udp"
      - "5060:5060/tcp"
    volumes:
      - ./opensips.cfg:/etc/opensips/opensips.cfg:ro
    depends_on:
      - postgres

  postgres:
    image: postgres:14
    environment:
      POSTGRES_DB: opensips
      POSTGRES_USER: opensips
      POSTGRES_PASSWORD: dev_password
    volumes:
      - voip-db:/var/lib/postgresql/data

volumes:
  voip-db:
EOF

# Start dev environment
docker compose up -d

Decision Matrix

Use Colima When:

VoIP development/testing

  • Testing SIP logic
  • Integration testing
  • CI/CD pipelines
  • Learning OpenSIPS/Asterisk

Non-RTPEngine scenarios

  • Pure signaling (OpenSIPS only)
  • No media processing required
  • Call routing logic testing

Quick iterations

  • Config changes
  • Module testing
  • Development workflow

Use UTM VM When:

Production VoIP (REQUIRED)

  • Real calls with actual users
  • RTPEngine kernel module needed
  • Low latency requirements (<50ms)
  • Kernel tuning required

Compiling from source (RECOMMENDED)

  • Need RTPEngine kernel module
  • Custom module selection
  • Performance optimization
  • Architecture-specific builds

Real-time performance (REQUIRED)

  • <10ms media latency
  • <30ms jitter tolerance
  • CPU isolation
  • IRQ affinity

Final Recommendation

┌─────────────────────────────────────────────────────────────┐
│  For Your VoIP Infrastructure:                              │
│                                                              │
│  ✅ PRODUCTION VoIP: Use UTM VM                             │
│     - Compile OpenSIPS, Asterisk, RTPEngine from source     │
│     - Load RTPEngine kernel module (xt_RTPENGINE)           │
│     - Apply kernel tuning for real-time performance         │
│     - Dedicated PostgreSQL in the same VM                   │
│                                                              │
│  ⚠️  DEVELOPMENT (optional): Colima separate profile        │
│     - Quick testing of SIP configs                          │
│     - Integration testing                                   │
│     - NOT for RTPEngine (no kernel module support)          │
│                                                              │
│  ✅ DEVSTACK CORE: Keep existing Colima setup               │
│     - Forgejo, databases, observability                     │
│     - No changes needed                                     │
│     - Completely separate from VoIP                         │
└─────────────────────────────────────────────────────────────┘

Why This Architecture?

  1. RTPEngine requires kernel module → MUST use VM (UTM)
  2. Source compilation benefits → Better in VM (native environment)
  3. Real-time performance → VM has full kernel control
  4. Production separation → VoIP isolated from dev infrastructure
  5. Flexibility → Optional Colima profile for rapid VoIP dev

Implementation Timeline

Week 1: UTM VM Setup
  - Create UTM VM (Ubuntu 22.04 ARM64)
  - Compile OpenSIPS, Asterisk, RTPEngine from source
  - Configure systemd services
  - Apply kernel tuning

Week 2: VoIP Configuration
  - Configure OpenSIPS (routing logic)
  - Configure Asterisk (PBX features)
  - Configure RTPEngine (media handling)
  - Set up PostgreSQL database

Week 3: Testing
  - SIP registration testing
  - Call routing verification
  - Media quality testing (MOS scores)
  - Load testing (SIPp)

Week 4: Production
  - Monitor with Prometheus (from Colima devstack)
  - Logs to Loki (from Colima devstack)
  - Production calls

Optional: VoIP dev environment
  - Create Colima voip-dev profile
  - Docker Compose for quick testing
  - Iterate rapidly on configs

Conclusion

Answer: Use UTM VMs for production VoIP services that need source compilation.

Key Reasons:

  1. ✅ RTPEngine kernel module is critical for performance (10x faster than userspace)
  2. ✅ Source compilation benefits from native VM environment
  3. ✅ Real-time kernel tuning requires full kernel access
  4. ✅ Production VoIP must be isolated from development infrastructure
  5. ✅ Colima containers cannot load kernel modules

Optional: Use separate Colima profile for VoIP development/testing (fast iteration on configs), but always deploy to UTM VM for production.

DevStack Core: Keep existing Colima setup unchanged - it's perfect for what it does (Git, databases, dev tools, observability).


Document Version: 1.0 Date: 2025-11-10 Author: VoIP Infrastructure Analysis Status: Complete

Clone this wiki locally