Short answer: Paste sip.conf peers, friends, templates and register => lines, and the converter writes the matching pjsip.conf sections: an endpoint, auth and aor for each peer, an identify section for IP-authenticated trunks, a registration for each register line and a UDP transport from [general]. It follows the mappings in Asterisk’s own sip_to_pjsip.py script and lists every option it could not convert.
Built and tested in Chromium on 6 Oct 2026; runs entirely in your browser.
Table of Contents
How to use the converter
- Copy the sections you want to convert from
sip.conf(orsip_additional.confon older FreePBX), including any templates they inherit from. - Paste them into the box. Type
exampleto convert a sample trunk, template and phone. - Optionally enter the transport name your endpoints should use, such as
transport-udp. - Press Convert to PJSIP, review the result and the “Options not converted” table, then copy pjsip.conf.
- Load it on a test system first, then check with
pjsip show endpointsandpjsip show registrationsin the Asterisk CLI.
chan_sip was removed in Asterisk 21. On older versions where chan_sip is still loaded, chan_sip and PJSIP cannot both listen on UDP port 5060, so move one of them or unload chan_sip.
What the output means
| sip.conf | pjsip.conf |
|---|---|
[peer] section | type=endpoint and type=aor with the same name, plus [peer-auth] when there is a secret. |
host=dynamic | aor max_contacts=1; the phone registers to the aor. |
host=203.0.113.20, port | aor contact=sip:user@host:port, and [peer-identify] with match= for type=peer or friend. |
secret, defaultuser/username | auth password and username. Trunks get outbound_auth=; phones get auth=. |
nat=force_rport,comedia | force_rport, rewrite_contact and rtp_symmetric. |
dtmfmode=rfc2833 | dtmf_mode=rfc4733. |
directmedia / canreinvite | direct_media and related options. |
fromuser, fromdomain, context, disallow/allow, callerid, mailbox | from_user, from_domain, context, codec lines in order, callerid, mailboxes. |
register => user:secret@host/ext | type=registration plus an auth section, named reg_host and auth_reg_host as sip_to_pjsip.py does. |
Three additions go beyond sip_to_pjsip.py and are marked in the notes: qualify=yes becomes qualify_frequency=60 (chan_sip’s default qualify interval), insecure=invite leaves auth= off a trunk so calls matched by its identify section are not challenged, and auth_type is left out so each Asterisk version uses its own default. Every option name in the output was checked against the res_pjsip configuration reference.
Examples
; sip.conf
[provider]
type=peer
host=sip.provider.example
defaultuser=12345
secret=s3cret
fromuser=12345
insecure=port,invite
context=from-trunk
disallow=all
allow=ulaw
allow=alaw
dtmfmode=rfc2833
; pjsip.conf
[provider]
type=endpoint
from_user=12345
context=from-trunk
disallow=all
allow=ulaw
allow=alaw
dtmf_mode=rfc4733
outbound_auth=provider-auth
aors=provider
[provider-auth]
type=auth
username=12345
password=s3cret
[provider]
type=aor
contact=sip:12345@sip.provider.example
[provider-identify]
type=identify
endpoint=provider
match=sip.provider.example
Common mistakes
- Leaving out the templates. If
[1001](phones)is pasted without[phones](!), the inherited options are missing. The tool tells you which templates were not found. - Expecting [general] NAT settings on endpoints. externip and localnet move to the transport. For a full NAT setup use the PJSIP NAT generator.
- Registrations over TCP or TLS without a transport. The tool only creates transport-udp; add transport-tcp or transport-tls yourself.
- Assuming permit/deny work per peer. They become a type=acl section, which applies globally in PJSIP.
- FreePBX users editing pjsip.conf by hand. FreePBX writes its own files; recreate trunks and extensions in the GUI and use this output as a checklist.
Official documentation: Asterisk: sip_to_pjsip script · docs.asterisk.org: Configuring res_pjsip
Related: PJSIP Behind NAT: Asterisk and FreePBX Settings for Two-Way Audio · PJSIP NAT Settings Generator: Asterisk, FreePBX, Issabel, VitalPBX, 3CX · Install Asterisk 22 LTS on Debian 13: Step-by-Step Guide · SIP Trace Analyzer: Find NAT, Codec and Dropped-Call Problems in a SIP Log · Troubleshoot SIP Calls with sngrep and the Asterisk PJSIP Logger
See also: chan_sip to PJSIP Migration: sip_to_pjsip.py, Option Mapping, Tests · Asterisk CLI Commands Cheat Sheet: PJSIP, Calls, Dialplan, Logs · PJSIP Endpoint Unreachable or Unavailable: Fix Qualify and NAT · FreePBX PJSIP Trunk Setup: Registration, IP Auth, Routes, NAT
Frequently asked questions
Does this tool send my sip.conf anywhere?
No. The conversion runs in your browser, so passwords in the file stay on your computer.
Is the result the same as Asterisk’s sip_to_pjsip.py?
It follows the same mappings, with three marked additions (qualify, insecure and auth_type) and names auth and identify sections peer-auth and peer-identify for readability.
What happens to insecure=port,invite?
PJSIP identifies the trunk by IP through the identify section, whatever the source port, and the endpoint gets no auth= line, so the provider’s calls are not challenged.
Why is qualify converted to qualify_frequency=60?
chan_sip’s qualify=yes checked the peer every 60 seconds by default. PJSIP does not qualify unless qualify_frequency is set on the aor.
Which options are not converted?
Anything without a PJSIP equivalent or not in the mapping list. They appear in the Options not converted table with a hint.