Build a Twilio Hard Phone with SIP from Twilio, Raspberry Pi, Asterisk, FreePBX, and the Obihai OBi100

This post used the Dial and SIP TwiML verbs and the Twilio Message Rest API

If you have worked with Twilio before, you have surely heard that sweet, sweet ring of your phone many times. But today, we are entering uncharted territory – you are going to learn how to make a phone ring without it even being connected to a traditional phone network! All you need are some simple pieces of hardware and that old landline phone that got shoved into the back of your closet years ago.

Twilio Hard Phone

Now, you may have seen our previous Arduino-focused tutorials on building your own Twilio Robot and automating your home with Twilio SMS but today we are going to try something new and use the amazing miniature computer called Raspberry Pi.

Getting Started

First things first, we need some parts. You will need to get a Raspberry Pi, an Obihai OBi100, and a traditional landline phone. For the Raspberry Pi, you will also need an SD card (I recommend a 4GB one), an Ethernet cable, and a Micro-USB power cable. I would also recommend having a USB keyboard and mouse as well as an HDMI monitor handy if for some reason you can’t SSH into your Raspberry Pi.

Once you have gathered all your parts, we can kick things off right and set up our Raspberry Pi – but we wont plug it in just yet. Before turning it on, we need to install an operating system on the SD card that serves as the Pi’s hard drive. Normally, you would use Raspbian – an optimized version of Debian made for Raspberry Pi. However, for our purposes, we are going to use a pre-built Raspbian image called RasPBX which comes with Asterisk and FreePBX pre-installed.

Installing RasPBX on your Raspberry Pi

The installation process can be somewhat tricky, but I have worked out some step-by-step instructions for those of you using Mac OS X. If you have any trouble or are running a different operating system, I highly recommend reading through these installation instructions.

Step 1: Download our RasPBX image here. Once it is finished downloading, unzip the archive.

Step 2: Put the SD card into your computer and open up Disk Utility (just type it in to the Spotlight search) – in the Disk Utility you should see your SD card in the list on the left. Format it with a FAT partition. You will need to be on an account with Administrator permissions for this SD card setup process! (Instructions paraphrased from RPi Easy Setup Guide)

Step 3: Open a Terminal window and type ‘df -h‘ to see a list of your disk mounts.

df -h

Step 4: Unmount the disk using ‘sudo diskutil unmount /dev/disk3s1′ – replace /dev/disk3s1 with whatever the filesystem name of your SD card is in the previous results

Unmount your SD Card

Step 5: Work out the raw device name for the SD Card by removing ‘s1’ and replacing ‘disk’ with ‘rdisk’if you use the wrong device name, you could wipe your entire hard drive – be careful!)

For example, on my system /dev/disk3s1 becomes /dev/rdisk3

Then run the following command (replacing /dev/rdisk3 with your own SD card device name and replacing the raspbx.img file location with the location where you unzipped it on your system). Make sure you have the right device or you can wipe your entire system!

sudo dd bs=1m if=/Users/jonmarkgo/Downloads/raspbx-04-11-2012/raspbx-04-11-2012.img of=/dev/rdisk3

This will take some time to execute, so go grab a snack while you wait. When you come back, you should see output similar to what I have in my terminal below:

Output from writing image to SD Card

Step 6: Eject your SD card by typing ‘sudo diskutil eject /dev/rdisk3’ (replacing rdisk3 with your own SD card device name)

Eject your SD Card

Step 7: Plug it into your Raspberry Pi, and turn that baby on. You should also have plugged your Raspberry PI into your Ethernet router as well. Look at all the blinky lights!

Raspberry Pi


Configuring RasPBX and your Raspberry Pi

Now that we have our Raspberry Pi booted up running our modified RasPBX distro of Linux, we can get started with the soft configuration. The first thing to do is either SSH into your Raspberry Pi or use the keyboard/mouse/monitor hookup to get a terminal window open. On Mac, you can use ‘ssh root@raspbx.local‘ or on Windows ‘ssh root@raspbx‘ – the default username is root and the password is raspberry.

A successful login looks something like this:

Log in to Raspberry Pi

At this point we need to configure some basic settings on our Raspberry Pi, as well as find out its IP Address. To find out its IP Address, use ‘ifconfig‘ and to begin configuration type ‘raspi-config‘ – there are many options to use and play around with but for now we are just going to use ‘expand_rootfs’ as in the following image – after expanding the filesystem, reboot the device (you will be prompted to do so) and then log back in to the terminal:

Get IP Address and then begin raspi-config

Expand root fs

Now we can go ahead and start configuring FreePBX (which controls Asterisk’s configuration files). You can log in to FreePBX by opening http://raspbx.local/ (or whichever hostname you used to access it) in your browser and then clicking on ‘FreePBX Administration’. The default username and password are both admin. Now we are going to configure Asterisk to accept incoming calls from Twilio and pass them through to our OBi100.

Step 1: Go to Settings->Asterisk SIP Settings and configure your NAT settings. In my case, I set up my Static and local IP addresses manually though you may need to configure it differently based on how your network is set up. Note that you will need the Raspberry Pi to be exposed to the web via a public IP address of some sort.

In my configuration, I simply opened up a DMZ on my network (note: this is not a secure setup) but you may need to have a different setup based on your network configuration.

DMZ Setup on Cisco E3000

You will also want to uncheck every codec except for ‘ulaw’, as this is the only one that Twilio currently supports.

Configuring Asterisk SIP Settings


Step 2: Go to the Applications tab and add a new ‘Generic SIP Device’ – this is where we configure the extension that Asterisk will forward to our OBi100 and eventually our land line phone. I am going to use extension number ‘1337’ so I will enter this number into the User Extension and Display Name fields.

Configure your Obihai extension number in Asterisk

Then you need to enter a password (called a secret) under the Device Options heading. I am going to make mine somewhat insecure and simply set my secret as ‘obihai100’.  Believe it or not, that is all the configuration we need to do to allow Asterisk to work with our OBi100.

Enter your secret (password for Obihai)

Now just click ‘Submit’ – we will apply the configuration later.

Step 3: Next we need to configure Asterisk to accept inbound calls from Twilio. This requires some manual configuration via our Terminal, so lets head back over there and use our editor of choice to modify the file ‘/etc/asterisk/sip_custom_post.conf’

We will then paste in the following configuration:

Lets head back over into FreePBX and click that big red ‘Apply Config’ button now to save all of our settings and restart Asterisk. Now we are finished configuring our Raspberry Pi, FreePBX, and Asterisk.

Setting up our Obihai OBi100

With our Raspberry Pi fully configured, we can now finish things off by setting up our OBi100 device. Lets plug it in to both a power outlet, your landline phone, and an Ethernet router using the included cables (thanks Obihai!) – once it is fully started up, you can open the control panel in your browser by heading to the OBi100’s local IP address. In order to find this, I needed to log into my router’s control panel and find out what IP address had been assigned to my device – this may take some experimentation if you have not used your router’s control panel before.

Obihai OBi100 and Landline Phone

Once you have found the IP address of your OBi100 and opened it in your browser, you should get presented with an authentication dialog. The username and password are again both admin. Now we need to do some configuration.

Step 1: Click on the Voice Services->SP1 Service. Here you will need to configure the SIP Credentials. Your AuthUserName is the extension number that you configured in FreePBX (1337 for me), the AuthPassword is your secret (obihai100 for me). Then just click Submit to save your changes.

Set your SIP Credentials on OBi100

Step 2: Click on Service Providers->ITSP Profile A->SIP. Here we have some more configuration to do – we need to tell the OBi100 where to find our Asterisk server. First we need to set the ProxyServer variable to point to the local IP address of our Raspberry Pi.

Enter local IP Address of Raspberry Pi

Then we should change the X_SpoofCallerID to be active so that the Caller ID gets forwarded along properly from Asterisk.

Set X_SpoofCallerID to be active

Click Submit again to save your changes and then click the Reboot button in the top bar to restart your OBi100. All of your hardware is now configured, the next thing to do is set up a Twilio number that can call our new system.

Setting up Twilio

If you are brand new to Twilio I recommend watching our SMS Quickstart Screencastwhich shows you how to buy a number for the first time. Otherwise, simply go ahead and buy a number. Configure the Voice URL to point to a new TwiML file that we will create below.

Configure Twilio Voice URL

In the TwiML file at that URL, enter the following:

The main change you have to make in this TwiML is to update the Uri that is being dialed. The format is <extension>@<ip address>, so in the example my extension is 1337 and my IP address is

Update: We have heard that some users are experiencing issues with the IP-based authorization. It is possible to reconfigure Asterisk to accept any incoming connections regardless of authorization – this is an insecure solution, but should be a fine temporary one if you would like to test out the system!

Some explanation may be required here. Earlier, we configured our Asterisk server to only accept connections from three distinct IP addresses – those that belong to Twilio’s SIPOut API servers. Because of how Asterisk configuration files work, we actually had to create three separate inbound users, one for each IP. Here, we dial all three at the same time as only one of them will be successful (based on which Twilio server is making the request to your Asterisk server).

After that, we are finished setting everything up. Simply call your new Twilio number and your landline phone should ring – AWESOME!

Now go out there and build your own Twilio hard phone or connect Twilio to your existing SIP server using our new SIPOut feature. Happy hacking!

If you have any questions, feedback, or angry rants please feel free to Tweet @jonmarkgo or e-mail me at

  • Song Zheng

    First thing to do when I get home today: Build a Twilio Hard Phone with SIP with Raspberry Pi, Asterisk, FreePBX, and Obihai OBi100

    • Twilio

      That sounds like a great plan. Let us know if you have any questions.

    • Twilio

      Hey, you can build it with those Raspberry Pi’s from the SxSW Developer Trivia!

    • Jungle

      Just FYI, the Obi100 and its successors can be used on their own with a VOIP provider to make and receive calls.

      • trevorep

        Yeah but where’s the fun in that!?

  • Chris Schmitt

    I’m not sure if people realize it, but this set-up replaces a PBX system that in the “old days” used to cost many $1000s. Very cool!

    • Jungle

      A digital PBX system can still cost thousands but it is certainly more capable than anything in the past.

  • LFC

    Does it only receive calls? Or can it dial out too?

    • Twilio

      Right now it can only receive calls, but we are working on adding functionality so it can make and receive calls.

      • Mark Wakeford

        Making calls would be awesome, as to use regular PBX to make calls over Twilio would replace our sip provider.

  • TrademarkInteractive

    That’s nice. I could use my Ooma Telo too – any VOIP solution…ideas…

    • dxjones

      Can Twilio SIP connect directly to Ooma Telo?? Can you tell me how??

    • Jungle

      I think Ooma connects only to its provider. In other words, I don’t think you can configure it with other VOIP providers.

  • Jungle

    There’s also Incredible PBX for the raspberry pi:

    Of course this does not use twilio by default and you don’t need an Obihai device if you have a softphone or desk IP phone.

    A really fancy twilio project with the raspberry pi would involve automation. Text a number and have it turn lights on; someone calls your twilio number and it activates a chain of events. Twilio is really a powerful platform and I’m happy to use it.

  • sprior

    I’ve been a fan of Asterisk for quite some time. Maybe I’m missing something, but it looks to me like all you’re using Asterisk for in this case is access control – accepting connections from only the Twillio servers. Wouldn’t it be simpler to just set up the Raspberry Pi as a firewall (iptables) and skip Asterisk? It doesn’t look like you’re using Asterisk for voicemail or anything.

    • Jonathan Gottfried

      It would indeed be possible to do that, though in this case I wanted to use Asterisk to demonstrate how you might integrate into more traditional PBX software.

  • Brendan

    Is there any way to use Twilio with a Polycom SoundStation IP 5000 instead of using the Obihai OBi100 to connect to an old school phone?

  • Dosaki


    This doesn’t seem to be working for me. I’m testing this with a softphone.
    Instead of having it ring, I get a male voice reading me the entries inside the tag.

    What could be wrong?

    • Dosaki

      The Content-Type of the response was text/plain instead of application/xml

  • Gary

    Great tutorial Jonathan – We are all setup using this for an inbound solution. However, about 50% of the time we get a failed call (it just hangs up). Looking at the Asterisk logs we see these series of errors:

    [2013-04-25 12:50:29] WARNING[1658][C-00000005] chan_sip.c: username mismatch, have , digest has
    [2013-04-25 12:50:29] NOTICE[1658][C-00000005] chan_sip.c: Failed to authenticate device “+1404[number im calling from]” ;tag=23556910_6772d868_b479b64a-b92a-41a3-a0cb-bc03e50d3f38
    [2013-04-25 12:50:29] WARNING[1658][C-00000006] chan_sip.c: username mismatch, have , digest has
    [2013-04-25 12:50:29] NOTICE[1658][C-00000006] chan_sip.c: Failed to authenticate device “+1404[number im calling from]” ;tag=98585749_6772d868_b479b64a-b92a-41a3-a0cb-bc03e50d3f38
    [2013-04-25 12:50:29] WARNING[1658][C-00000007] chan_sip.c: username mismatch, have , digest has
    [2013-04-25 12:50:29] NOTICE[1658][C-00000007] chan_sip.c: Failed to authenticate device “+1404[number im calling from]” ;tag=77062311_6772d868_b479b64a-b92a-41a3-a0cb-bc03e50d3f38

    • Jonathan Gottfried

      One potential (albeit insecure) solution is to remove authorization in Asterisk so that it accepts any incoming calls. It is unfortunately unable to handle as many IP addresses as we are serving requests from and it doesn’t seem to handle CNAMEs either.

  • AK

    If only there was a way to:
    1. Put funds in my Twilio account
    2. Sign in to some Mac SIP client – preferably Telephone – using Twilio/Twilio SIP credentials
    3. Start outgoing and incoming calls as soon as Telephone is running with an Internet connection on my Mac.

    Of course, for personal usage, all this.

  • Tan

    Holy moly, this is amazing. People must be scared to do it because of the many steps… It would be awesome to see Twilio should build a little box like Vonage has! Come-on guys PLEAAAAAASE?!

  • fasterfind

    Could I get a rundown of cost of equipment? Essentially, it sounds like the bottom line is this: You use Twilio with this equipment so that you get a Twilio based phone number that can make and receive phone calls that are routed to your physical phone at home. If monthly phone cost is say $10 / mo, then how long to reach ROI?

    • jonmarkgo

      Hey fasterfind, the minimal equipment is an ObiHai or similar device to bridge your desktop phone to a server, a server of any type (doesn’t have to be Raspberry Pi) to register your SIP endpoint and route calls, and then the phone itself. Upfront cost is certainly <$100 altogether, but monthly cost depends heavily on how many minutes you use (pricing here:

      • svartalf

        In short, this is (based on the pricing I see on the main website) a rocking Business line solution- and a decent home voice solution (so long as you understand, 911 doesn’t work here without other help…) for the skilled.

  • Pinbot

    I turned off SIP guest dialing on the Asterisk/FreePBX ide, and it’s a crap-shoot using the multiple URI username technique that’s then firing out of one of the Twilio N. American Gateway IP addresses ( and quite frequently (and certainly enough for failed calls) it will come out as twilio2 in digest (what servers are sending) that’s then a username mismatch to the host that’s tied into the Asterisk template in sip_custom_post.conf.

    An example of a complete fall-through:

    [2013-09-30 12:20:48] WARNING[23275]: chan_sip.c:14967 check_auth: username mismatch, have , digest has
    [2013-09-30 12:20:48] NOTICE[23275]: chan_sip.c:23253 handle_request_invite: Failed to authenticate device “+1##########” ;tag=XXX
    [2013-09-30 12:20:48] WARNING[23275]: chan_sip.c:14967 check_auth: username mismatch, have , digest has
    [2013-09-30 12:20:48] NOTICE[23275]: chan_sip.c:23253 handle_request_invite: Failed to authenticate device “+1##########” ;tag=XXX
    [2013-09-30 12:20:48] WARNING[23275]: chan_sip.c:14967 check_auth: username mismatch, have , digest has
    [2013-09-30 12:20:48] NOTICE[23275]: chan_sip.c:23253 handle_request_invite: Failed to authenticate device “+1##########” ;tag=XXX
    (where as the +1########## is the caller id phone number that I’m dialing in from)

    I’ve been racking my brain trying to figure out how to use some other method, and have been unsuccessful with instead of even when I change/remove the Asterisk template… I was really hoping for using this in a trunk situation instead.

    On the bright side, with a PHP file and “substr($_ENV[‘PATH_INFO’], 1)” I’m able to dump multiple Twilio numbers onto one PHP path, and turn around and add reciprocal DID into FreePBX since PHP is

    Ideally, I’d like to use Twilio as a trunk same as I do with other SIP ratecenters, and since I don’t know what IP addresses Twilio is going to sling at me (e.g. one of many is, and traces back to Amazon Web Services, and is attempting to come in as UDP on one of the RTP ports) and thus, I’m only accepting traffic from the 7 known Twilio IPs into my IPTables of the server.

    • jonmarkgo

      This seems like a solid approach. The issue I ran into is that Asterisk doesn’t really support CNAME filtering (ie you can’t allow all traffic from regardless of IP)

      I’d definitely be curious how your PHP solution works – is the code public?

  • Guest

    Thanks for the post! I have setup my hard phones with PI and OBIHAI and received incoming calls. But I cannot make any calls out. Can you explain how to setup outgoing calls?

  • Hao Wu

    Thanks for the detailed post. I can easily follow and setup the environment. I can receive incoming calls, but Cannot make outgoing calls from it. Can you explain how to make outgoing calls?

    • jonmarkgo

      Hey Hao,

      You can configure Asterisk to use Twilio SIP for outgoing calls ( though at the moment we do not support SIP registration so you will need to set that up within Asterisk or an alternative provider at the moment.

  • Mike

    Could someone point me in the right direction? This is my first contact with sip, but I have some experience using Twilio. I tried the example above, but I cannot make it work. I get this message from asterisk (at the speaker) “the number you have dialed is not in service”

    And this is the output from asterisk:

    [2014-07-01 13:35:41] VERBOSE[2746] netsock2.c: == Using SIP RTP TOS bits 184

    [2014-07-01 13:35:41] VERBOSE[2746] netsock2.c: == Using SIP RTP CoS mark 5

    [2014-07-01 13:35:41] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:1] ResetCDR(“SIP/211-0000001f”, “”) in new stack

    [2014-07-01 13:35:41] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:2] NoCDR(“SIP/211-0000001f”, “”) in new stack

    [2014-07-01 13:35:41] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:3] Progress(“SIP/211-0000001f”, “”) in new stack

    [2014-07-01 13:35:41] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:4] Wait(“SIP/211-0000001f”, “1”) in new stack

    [2014-07-01 13:35:42] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:5] Progress(“SIP/211-0000001f”, “”) in new stack

    [2014-07-01 13:35:42] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:6] Playback(“SIP/211-0000001f”, “silence/1&cannot-complete-as-dialed&check-number-dial-again,noanswer”) in new stack

    [2014-07-01 13:35:42] VERBOSE[3388] file.c: — Playing ‘silence/1.ulaw’ (language ‘en’)

    [2014-07-01 13:35:43] VERBOSE[3388] file.c: — Playing ‘cannot-complete-as-dialed.ulaw’ (language ‘en’)

    [2014-07-01 13:35:46] VERBOSE[3388] file.c: — Playing ‘check-number-dial-again.ulaw’ (language ‘en’)

    [2014-07-01 13:35:48] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:7] Wait(“SIP/211-0000001f”, “1”) in new stack

    [2014-07-01 13:35:49] VERBOSE[3388] pbx.c: — Executing [88525584215043@from-internal:8] Congestion(“SIP/211-0000001f”, “20”) in new stack

    [2014-07-01 13:35:49] VERBOSE[3388] pbx.c: == Spawn extension (from-internal, 88525584215043, 8) exited non-zero on ‘SIP/211-0000001f’

    [2014-07-01 13:35:49] VERBOSE[3388] pbx.c: — Executing [h@from-internal:1] Hangup(“SIP/211-0000001f”, “”) in new stack

    [2014-07-01 13:35:49] VERBOSE[3388] pbx.c: == Spawn extension (from-internal, h, 1) exited non-zero on ‘SIP/211-0000001f’

    I appreciate any light you can shed on this.

    • Pinbot

      Your Inbound DID isn’t being recognized. I’ve managed to solve that problem, yet I can’t solve the *FREQUENT* issue with SIP fall-through from Twilio to Asterisk; so maybe if you got that to work, then you could share? I posted about it above, and also have found through Google that others seem to be experiencing the same problem.

      I have a PHP file sitting on receiving end for Twilio request URL – Voice:

      • Mike

        I found out the reason it wasn’t working for me is I was using “/etc/asterisk/sip_custom_post.conf” which wasn’t actually being loaded (duh). Then it worked sometimes (depending on which ip was twilio using) and then found this:

        It seems to be working just fine for my needs… so far. Now I want to make outbound calls, but haven’t make it work yet.

  • erdem

    if we need to buy OBi100, what does raspberry pi do?
    Can’t we use raspberry pi instead of OBi100?

    I’m confuse

    • Kevin Jordan

      The OBi100 is an analog to VoIP converter so you can use an old analog phone you have lying around. The Raspberry Pi is what you point the OBi100 at to make it talk with twilio.

  • Spencer

    So using this setup can incoming calls get a phone tree? Can calls be rerouted depending on different conditions? Such as if I am out of the office and they select my ext can the call be sent to my cell?

  • William Meginley

    Not sure if the information we have documented will be a help but wanted to share..