Skip to content

Use OpenSIPS as the SIP Server

github-actions[bot] edited this page Oct 16, 2026 · 1 revision

OpenSIPS is an open-source SIP server. With Kamailio, it is 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 does three things:

  • It installs OpenSIPS.
  • It sets OpenSIPS up as a proxy that routes each call and stays in its signaling path.
  • It proves the setup 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 block on this page ran as written, in order, on 2026-10-01.

  • The machines were clean x86_64 virtual machines with 2 cores and 3 GB of memory:
    • Debian 13 (kernel 6.12.63),
    • Ubuntu 24.04 (kernel 6.8.0).
  • On each machine:
    • The source build ran on a machine with nothing installed.
    • The 4.0 packages ran on the same machine after its uninstall removed the source build. Kamailio was already running on 5062.
  • OpenSIPS and Kamailio on one machine and the uninstall ran on both.
  • Every test call carried audio both ways, counted on the wire.
  • Causing each fault under When something does not work produced the message it quotes, 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: 3.7.3 on Debian 13, 3.7.2 on Ubuntu 24.04

The examples use 192.0.2.10 as the machine's address. Replace it with yours everywhere it appears.

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. The other voice-stack guides build it 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,
  • 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. Its configuration is in /etc/opensips/opensips.cfg. It adds 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. That 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.
  • Only DBG_MALLOC's headers happen to supply it.

The build installs OpenSIPS under /usr/local. Its configuration is 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

Configure OpenSIPS as a proxy

This configuration is a minimal proxy:

  • it routes every call to one destination,
  • it 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. OpenSIPS and Kamailio on one machine explains how. 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.
  • M is the directory your install loads modules from. The script's mpath names it.
# 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.

Place a test call

SIPp plays both ends:

  • a callee on this machine that echoes audio back,
  • a caller that dials through OpenSIPS and plays a recorded G.711 sample.

So the call carries real audio both ways.

  • 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/pcap && cd ~/sipp
ln -sf /usr/share/sip-tester/*.pcap pcap/
sipp -sd uac_pcap > uac_rr.xml
sed -i 's|<recv response="200" rtd="true" crlf="true">|<recv response="200" rtd="true" crlf="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 -rtp_echo -m 1 -trace_msg -message_file uas.msg -bg
sudo sipp -sf uac_rr.xml 192.0.2.10:5060 -i 192.0.2.10 -p 5080 -s echo -m 1 -timeout 90s
awk '/INVITE sip:/{f=1} f' uas.msg | grep -m1 -i '^Record-Route:'

The caller needs sudo because it plays the audio sample through a raw socket.

  • It sends about 7 seconds of audio, then a short DTMF clip, and hangs up.
  • At the end, SIPp's statistics screen shows Successful call at 1.
  • The last line prints the Record-Route OpenSIPS added.

OpenSIPS carries the signaling only. The audio goes straight between the two ends, at the addresses and ports their SDP names. So this proxy never touches it.

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,
  • 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. Its "Before you start" section says 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
rtpproxy rtpproxy, 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.
  • Move Kamailio to 5062, as the Kamailio guide's section describes.
  • Give sipnab both ports with --portrange 5060-5062.

When something does not work

  • apt-get says Could not get lock /var/lib/dpkg/lock-frontend. It is held by process ....
    • Another package tool holds the lock. On a machine that has just booted, this is usually the system's own scheduled update.
    • Wait for it to finish, then run the block again.
  • 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 says FIFO file /var/run/opensips/opensips_fifo does not exist. One of these is true:
    • OpenSIPS is not running.
    • mi_fifo is not loaded.
    • 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.
  • 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_pcap.

Home

Getting started

Using the TUI

CLI & automation

Configuration

Integrations (API & MCP)

Your SIP server

Add to your voice stack

Development & internals

Clone this wiki locally