Docs Use OpenSIPS as your voice stack's SIP server
Use OpenSIPS as your voice stack's SIP server
Install OpenSIPS 4.0 from its packages or build it from source, set it up as a proxy that stays in each call's path, place a test call, and operate it. No sipnab involved.
On this page
OpenSIPS is an open-source SIP server, and with Kamailio one of the two most common SIP proxies in front of phones, PBXes and carriers. The other voice-stack guides add a component beside it: a vCon server, TFPS, rtpengine, Homer, Prometheus.
This guide installs OpenSIPS, sets it up as a proxy that routes each call and stays in its signaling path, and proves it with a test call. This guide does not use sipnab. When you have this working, Run sipnab beside OpenSIPS adds sipnab. If you use Kamailio instead, see Use Kamailio as your voice stack’s SIP server.
Tested on
Every command on this page ran as written, in order, on 2026-09-27, on x86_64 virtual machines with 2 cores and 3 GB of memory. The 4.0 packages ran on a clean Ubuntu 24.04.5 (kernel 6.8.0), and on Debian 13 (kernel 6.12.63) beside Kamailio. The source build ran on a clean Debian 13 and a clean Ubuntu 24.04.5. OpenSIPS and Kamailio on one machine ran on both.
| Software | Version or commit |
|---|---|
| OpenSIPS, from packages | 4.0.2, the current stable release, from the OpenSIPS project’s own package repository |
| OpenSIPS, from source | f46ef9337b, master, 4.1.0-dev |
| SIPp (for the test call) | the distribution’s sip-tester |
The examples use 192.0.2.10 as the machine’s address. Replace it with yours
everywhere it appears.
1. Install OpenSIPS
Choose one of the two installs. The packages are the stable release, and what most people run. The source build is OpenSIPS’s development branch, which the other voice-stack guides build when they install OpenSIPS for you. The steps after this one work with either.
Both add the OpenSIPS project’s package repository: the packages come from it,
and the source build takes opensips-cli, OpenSIPS’s command-line tool, from
it.
# Run all of these, in order.
sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://apt.opensips.org/opensips-org.gpg -o /etc/apt/keyrings/opensips-org.gpg
. /etc/os-release
echo "deb [signed-by=/etc/apt/keyrings/opensips-org.gpg] https://apt.opensips.org $VERSION_CODENAME 4.0-releases" \
| sudo tee /etc/apt/sources.list.d/opensips.list >/dev/null
sudo apt-get update
sudo apt-get install -y opensips-cli
Install the 4.0 packages
# Run all of these, in order.
sudo apt-get install -y opensips
sudo opensips -V | head -1
The package installs OpenSIPS under /usr, with its configuration in
/etc/opensips/opensips.cfg, and a systemd unit that runs it as the
opensips user. It enables the unit but does not start it.
Or build master from source
OpenSIPS master builds with compiler optimizations turned off, which is right for OpenSIPS’s own developers and wrong for a proxy carrying calls. Turn them back on before you build:
# Run all of these, in order.
sudo apt-get install -y --no-install-recommends git build-essential bison flex uuid-dev pkg-config libncurses-dev libssl-dev
sudo mkdir -p /usr/local/src/voice && sudo chown "$USER": /usr/local/src/voice
cd /usr/local/src/voice
git clone https://github.com/OpenSIPS/opensips.git
cd opensips
git checkout f46ef9337b
make Makefile.conf
sed -i 's/^DEFS+= -DCC_O0/#DEFS+= -DCC_O0/' Makefile.conf
make -j2 all
sudo make install
/usr/local/sbin/opensips -V | head -1
Leave DBG_MALLOC as it is. With both it and CC_O0 switched off, this commit
of master does not compile: net/tcp_conn_defs.h calls get_ticks() without
including the header that declares it, and only DBG_MALLOC’s headers happen
to supply it.
The build installs OpenSIPS under /usr/local, with its configuration in
/usr/local/etc/opensips/opensips.cfg. Give it its own user and a systemd
unit, as the package would:
# Run all of these, in order.
sudo useradd --system --home-dir /run/opensips --shell /usr/sbin/nologin opensips
sudo chown root:opensips /usr/local/etc/opensips
sudo chmod 750 /usr/local/etc/opensips
sudo tee /etc/systemd/system/opensips.service >/dev/null <<'EOF'
[Unit]
Description=OpenSIPS SIP server
After=network.target
[Service]
Type=forking
User=opensips
Group=opensips
RuntimeDirectory=opensips
RuntimeDirectoryMode=775
PIDFile=/run/opensips/opensips.pid
ExecStart=/usr/local/sbin/opensips -P /run/opensips/opensips.pid -f /usr/local/etc/opensips/opensips.cfg -m 64 -M 8
Restart=always
TimeoutStopSec=30s
LimitNOFILE=262144
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable opensips
2. Configure OpenSIPS as a proxy
This configuration is a minimal proxy: it routes every call to one destination and stays in the path of the call’s later requests. Your own script does much more (registration, authentication, routing to carriers).
If Kamailio already runs on this machine on 5060, move it to 5062 first, as OpenSIPS and Kamailio on one machine explains. Two SIP servers on one UDP port do not refuse each other: the one that starts last silently receives all of that port’s traffic.
The two installs keep their configuration and their modules in different
places. The first two lines find them: C is your configuration file, and M
the directory your install loads modules from, which the script’s mpath
names.
# Run all of these, in order.
for f in /etc/opensips/opensips.cfg /usr/local/etc/opensips/opensips.cfg; do sudo test -f "$f" && C=$f && break; done
for d in /usr/lib/*/opensips/modules /usr/local/lib64/opensips/modules; do [ -f "$d/tm.so" ] && M=$d && break; done
echo "configuration: $C modules: $M"
sudo tee "$C" >/dev/null <<'EOF'
# OpenSIPS as a SIP proxy that stays in the path of every call.
log_level=3
stderror_enabled=no
syslog_enabled=yes
syslog_facility=LOG_LOCAL0
udp_workers=2
open_files_limit=4096
socket=udp:192.0.2.10:5060 # the address your phones and carriers reach
mpath="MODULES/"
loadmodule "proto_udp.so" # built into the core, but still loaded by name
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "sipmsgops.so"
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/run/opensips/opensips_fifo")
route {
if (!mf_process_maxfwd_header(10)) {
send_reply(483, "Too Many Hops");
exit;
}
if (has_totag()) {
if (is_method("ACK") && t_check_trans()) {
t_relay();
exit;
}
if (!loose_route()) {
send_reply(404, "Not here");
exit;
}
t_relay();
exit;
}
if (is_method("CANCEL")) {
if (t_check_trans())
t_relay();
exit;
}
t_check_trans();
if (!is_method("INVITE")) {
send_reply(405, "Method Not Allowed");
exit;
}
record_route();
# Where the call goes. Here, a test callee on this machine; in your
# stack, lookup("location"), dispatcher or a carrier.
$du = "sip:127.0.0.1:5070";
t_relay();
}
EOF
sudo sed -i "s|^mpath=\"MODULES/\"|mpath=\"$M/\"|" "$C"
sudo chown root:opensips "$C"
sudo chmod 640 "$C"
sudo opensips -C -f "$C"
sudo systemctl restart opensips
systemctl is-active opensips
What the parts do:
record_route()adds aRecord-Routeheader naming OpenSIPS, so the call’s later requests, theACKand theBYE, come back through it.loose_route()routes those later requests along the recorded route.t_relay()forwards the request and handles retransmissions and replies.mi_fifois what letsopensips-clitalk to the running OpenSIPS.
opensips -C checks the configuration and prints config file ok before
anything starts.
3. Place a test call
SIPp plays both ends: a callee on this machine, and a caller that dials through
OpenSIPS. SIPp’s built-in caller ignores the Record-Route header, so its
BYE would miss the proxy and draw 404 Not here. The two route sed lines
make it honor the route set, the way a real phone does. The callee writes what
it receives to uas.msg:
# Run all of these, in order.
sudo apt-get install -y sip-tester
mkdir -p ~/sipp && cd ~/sipp
sipp -sd uac > uac_rr.xml
sed -i 's|<recv response="200" rtd="true">|<recv response="200" rtd="true" rrs="true">|' uac_rr.xml
sed -i -E 's#^( *)(ACK|BYE) sip:\[service\]@\[remote_ip\]:\[remote_port\] SIP/2.0#\1\2 [next_url] SIP/2.0\n\1[routes]#' uac_rr.xml
sipp -sn uas -i 127.0.0.1 -p 5070 -m 1 -trace_msg -message_file uas.msg -bg
sipp -sf uac_rr.xml 192.0.2.10:5060 -i 192.0.2.10 -p 5080 -m 1 -d 1000 -timeout 20s
awk '/INVITE sip:/{f=1} f' uas.msg | grep -m1 -i '^Record-Route:'
At the end SIPp’s statistics screen shows Successful call at 1, and the last
line prints the Record-Route OpenSIPS added.
4. Operate it
See what OpenSIPS has handled. opensips-cli asks the running OpenSIPS
through its management interface. OpenSIPS 4 groups the management commands
by namespace, so statistics:get is what OpenSIPS 3 called get_statistics:
# Run all of these, in order.
sudo opensips-cli -x mi statistics:get rcv_requests
sudo opensips-cli -x mi statistics:get tm:
After the test call, core:rcv_requests is 3: the INVITE, the ACK and the
BYE.
Check health and read the logs.
# Run all of these, in order.
systemctl is-active opensips
sudo opensips-cli -x mi core:uptime
sudo journalctl -u opensips -n 30
Apply a configuration change. Check it first, then restart:
# Run all of these, in order.
for f in /etc/opensips/opensips.cfg /usr/local/etc/opensips/opensips.cfg; do sudo test -f "$f" && C=$f && break; done
sudo opensips -C -f "$C"
sudo systemctl restart opensips
Uninstall. For the packages, purge them. For the source build, remove what
it installed under /usr/local:
# Run all of these, in order.
sudo systemctl disable --now opensips
if dpkg -s opensips >/dev/null 2>&1; then sudo apt-get purge -y opensips; fi
sudo rm -rf /usr/local/sbin/opensips* /usr/local/lib64/opensips /usr/local/etc/opensips /etc/systemd/system/opensips.service
sudo apt-get purge -y opensips-cli
sudo rm /etc/apt/sources.list.d/opensips.list /etc/apt/keyrings/opensips-org.gpg
OpenSIPS in the other voice-stack guides
Each guide works with either install, and says in its “Before you start”
section which of its steps to skip. With the packages, some guides need a
module package beside opensips:
| Guide | Modules it loads | With the packages, also install |
|---|---|---|
| rtpengine | rtpengine, rtp_relay, dialog | nothing: they come with opensips |
| Homer | proto_hep, tracer | nothing: they come with opensips |
| Prometheus | httpd, prometheus | opensips-http-modules, opensips-prometheus-module |
| Add a vCon server | siprec, b2b_entities, uac_auth | opensips-siprec-module, opensips-auth-modules |
| TFPS | none | nothing: TFPS needs nothing from OpenSIPS |
OpenSIPS and Kamailio on one machine
Developers often run both, to compare them or to test against each. They can
share a machine as long as they do not share a port. Keep OpenSIPS on 5060 and
move Kamailio to 5062, as
the Kamailio guide’s section
describes. Give sipnab both ports with --portrange 5060-5062.
When something does not work
opensips -Creportscould not open module <signaling.so>. Thempathline is missing or names the wrong directory. OpenSIPS does not fall back to its own module directory without it.opensips-clicannot connect.mi_fifois not loaded, or itsfifo_nameis not/run/opensips/opensips_fifo, whereopensips-clilooks.opensips-clisaysno command 'get_statistics' in module 'mi'. That is the OpenSIPS 3 name. OpenSIPS 4 calls itstatistics:get, and the error lists the names it accepts.- The test call’s
BYEgets404 Not here. The caller ignored the route set. Use the editeduac_rr.xml, not SIPp’s built-inuac.