-
-
Notifications
You must be signed in to change notification settings - Fork 0
Backup and Restore
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.
- Current Architecture
- VoIP Service Requirements
- Source Compilation Considerations
- Colima Capabilities for VoIP
- UTM Advantages for VoIP
- Technical Analysis: Container vs VM
- Recommended Architecture
- Hybrid Approach
- Implementation Guide
- Decision Matrix
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 servicesCurrent 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]
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 installPurpose: 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 configPurpose: 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 installCRITICAL 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
-
Performance Optimization
-
-march=native: Use all CPU features (NEON, SVE on ARM64) -
-O3: Aggressive optimizations - Link-time optimization (LTO)
- Profile-guided optimization (PGO)
-
-
Custom Module Selection
- OpenSIPS: Select only needed modules (reduce memory, attack surface)
- Asterisk: Choose codecs, applications, resources
- RTPEngine: Enable/disable transcoding, DTLS, SRTP
-
Security
- Apply patches immediately (not waiting for distro packages)
- Disable unused features
- Custom hardening flags
-
Platform-Specific Features
- Apple Silicon optimizations
- ARM64 NEON vectorization
- Architecture-specific tuning
-
Kernel Module Integration
- RTPEngine kernel module requires compilation against running kernel
- Custom kernel parameters for real-time performance
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 modulePros:
- ✅ 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# 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
# 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 listBenefits:
- ✅ Isolate VoIP development from main DevStack
- ✅ Different resource allocations
- ✅ Independent lifecycle management
- ✅ Network isolation
# 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
--privilegedgives 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
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.
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# 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#!/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# 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
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.
┌─────────────────────────────────────────┐
│ 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
┌─────────────────────────────────────────┐
│ 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)
| 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 | ✅ 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 | ✅ Build and load | |
| Production-ready | ❌ No (dev/test only) | ✅ Yes |
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:
-
Development:
- Edit OpenSIPS/Asterisk configs in your IDE
- Test in Colima
voip-devprofile (optional, quick iteration) - Use SIPp for load testing
-
Compilation:
- SSH into UTM
voip-productionVM - Compile from source with optimizations
- Install as systemd services
- SSH into UTM
-
Production:
- Run from UTM VM with kernel modules
- Monitor via Prometheus (in Colima devstack-core)
- Logs aggregated to Loki (in Colima devstack-core)
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
# 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 here1. 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
# 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)#!/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)"# Create systemd service files (already shown earlier)
# See "UTM Advantages for VoIP" section
sudo systemctl daemon-reload
sudo systemctl enable opensips asterisk rtpengine# 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# 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✅ 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
✅ 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
┌─────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────┘
- RTPEngine requires kernel module → MUST use VM (UTM)
- Source compilation benefits → Better in VM (native environment)
- Real-time performance → VM has full kernel control
- Production separation → VoIP isolated from dev infrastructure
- Flexibility → Optional Colima profile for rapid VoIP dev
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
Answer: Use UTM VMs for production VoIP services that need source compilation.
Key Reasons:
- ✅ RTPEngine kernel module is critical for performance (10x faster than userspace)
- ✅ Source compilation benefits from native VM environment
- ✅ Real-time kernel tuning requires full kernel access
- ✅ Production VoIP must be isolated from development infrastructure
- ✅ 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