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.

SoftwareVersion or commit
OpenSIPS, from packages4.0.2, the current stable release, from the OpenSIPS project’s own package repository
OpenSIPS, from sourcef46ef9337b, 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 a Record-Route header naming OpenSIPS, so the call’s later requests, the ACK and the BYE, 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_fifo is what lets opensips-cli talk 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:

GuideModules it loadsWith the packages, also install
rtpenginertpengine, rtp_relay, dialognothing: they come with opensips
Homerproto_hep, tracernothing: they come with opensips
Prometheushttpd, prometheusopensips-http-modules, opensips-prometheus-module
Add a vCon serversiprec, b2b_entities, uac_authopensips-siprec-module, opensips-auth-modules
TFPSnonenothing: 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 -C reports could not open module <signaling.so>. The mpath line is missing or names the wrong directory. OpenSIPS does not fall back to its own module directory without it.
  • opensips-cli cannot connect. mi_fifo is not loaded, or its fifo_name is not /run/opensips/opensips_fifo, where opensips-cli looks.
  • opensips-cli says no command 'get_statistics' in module 'mi'. That is the OpenSIPS 3 name. OpenSIPS 4 calls it statistics:get, and the error lists the names it accepts.
  • The test call’s BYE gets 404 Not here. The caller ignored the route set. Use the edited uac_rr.xml, not SIPp’s built-in uac.