The best of a bad lot
« Photos from the Freezepop Boston JourneyReal Time Photo: The nicest-looking cloud I've seen in awhile »

Asterisk and FreePBX under Ubuntu 9.04 and Lighttpd on a Linode VPS

Permalink 08/03/09 20:19, by Ryan, Categories: Geekery, Howto , Tags: , , , , , , , , , , , , , , , , , ,

Are you looking for tips on doing this with Ubuntu 9.10 (Karmic)? The procedure is different! See the updated blog post here.


FreePBX is a popular front end for the Asterisk PBX system written in PHP. It adapts the complex yet very flexible Asterisk configuration system into something easier to use (yet still very extensible). When I worked for a business-class VoIP provider back in the day, we used FreePBX (and its predecessor, AMP) for most of our customer-premise PBX servers. I do like using FreePBX to configure my Asterisk system. However, I can't justify an entire server for Asterisk, so I need it to coexist with a number of other applications. What I can justify is a VPS with relatively little memory, so some tuning is required.

Rationale

The usual installation instructions assume the use of CentOS, Apache and mod_php for the stack. There are a few downsides to this configuration.

...

Since mod_php runs the PHP interpreter "within" Apache, it is restricted to running PHP code with Apache's permissions. For the purposes of FreePBX, which needs to edit configuration files owned by the "asterisk" user, this means setting Apache to run as "asterisk." Not an ideal configuration from a security standpoint, especially when the server is not dedicated to Asterisk. The PHP folks strongly recommend that Apache use the prefork MPM with mod_php due to threading concerns. This is not a big deal for a dedicated Asterisk/FreePBX server, but if you're sharing it with a web server that might have popularity and limited memory, this can be a problem under high load. For this reason, I use lighttpd and PHP via FastCGI to service dynamic PHP content. This allows the web server to run threaded while PHP does its own thing, running under more specific uids. I've also found the availability of software for CentOS to be lacking, so I've standardized on Ubuntu to avoid straying from the repositories as much as possible. As of this writing, I'm using Ubuntu 8.04 LTS on servers and Ubuntu 9.04 on desktops, although I am using 9.04 for this example. So, time to get FreePBX operating properly in an entirely foreign environment!

The setup

The following was used as a base for this installation:

The steps

I'm starting from the beginning, as I am doing this in a testbed. You can probably skip some steps if you already have a working system. Additionally, you might want to browse http://library.linode.com/ for more general advice on deploying, securing, and configuring a general purpose server.

Prepare the system

I used Linode's Distribution Wizard to deploy a barebones Ubuntu 9.04 image using the defaults. First, I log in and do my normal Linux prep:

Code:

# vi /etc/apt/sources.list
  [uncomment to enable the universe repositories]
# apt-get update
  [output deleted]
  Fetched 2025kB in 2s (680kB/s)                            
  Reading package lists... Done
# apt-get install language-pack-en
  [to clear locales errors]
# apt-get upgrade
# adduser rtucker
  Adding user `rtucker' ...
  [dialogue deleted]
# echo "rtucker ALL=(ALL) ALL" >> /etc/sudoers
 
(log back in as rtucker)
 
$ sudo vi /etc/ssh/sshd_config
  [edit to set PermitRootLogin no
$ sudo /etc/init.d/ssh restart
$ mkdir -m 700 .ssh
$ cat > .ssh/authorized_keys
  [paste ssh public key here, followed by ctrl-D]
 
(log back in and make sure it uses the key!)
You may also want to set your timezone, configure your IP address statically, and change your hostname.

OPTIONAL: Configure the system to use Ubuntu's stock kernel

To make Asterisk's MeetMe subsystem happy, one needs the ztdummy kernel module to provide timing. This is optional, and can be done with the stock Linode kernels, but you can run your distribution's stock kernel via PV-GRUB and thus "do what needs doing" without compiling.

Code:

$ sudo apt-get install linux-image-server grub
  [output deleted]
$ sudo mkdir /boot/grub
$ sudo update-grub
  [dialogue deleted... yes, you want it to generate menu.lst for you]
  [yeah, it'll complain about a non-Xen kernel.  See below.]
If you're running Ubuntu 9.04, you'll then want to edit /boot/grub/menu.lst per the instructions in Linode's wiki; in short, change groot=biglongthing to groot=(hd0) and set indomU=false, then run update-grub again. You don't need to uncomment the lines. You will also want to edit /etc/event.d/tty1 to change:
 exec /sbin/getty 38400 tty1
to:
 exec /sbin/getty 38400 hvc0
In Linode's dashboard, click on your configuration profile and change the kernel to pv-grub-x86_32. Save it, send a reboot, and watch the fireworks via the lish console. Getting an error on boot like "close blk: backend at ..."? See comment #3 from Quinn Ebert, below.

Installing Asterisk

You can download and install Asterisk from source, but if you're a wimp like me, Ubuntu's packages work just fine:

Code:

$ sudo apt-get install asterisk asterisk-config asterisk-doc asterisk-mp3 asterisk-mysql asterisk-sounds-main asterisk-sounds-extra
If you need ztdummy, and are using the Ubuntu kernel per the pv_grub instructions above, now is a good time to grab the zaptel stuff. module-assistant will pause to install anything it needs to produce the zaptel kernel modules.

Code:

$ sudo apt-get install zaptel zaptel-source
$ sudo module-assistant update
$ sudo module-assistant auto-install zaptel
$ sudo modprobe ztdummy
Note: if it fails due to:

Code:

ztdummy.c: In function 'ztdummy_hr_int':
ztdummy.c:203: error: 'struct hrtimer' has no member named 'expires'
... you are probably running into Launchpad bug 353024, which is an incompatibility between zaptel and the 2.6.28 kernel. Grab patched zaptel and zaptel-source packages from Darik Horn's PPA to fix this for now.

Code:

$ sudo apt-get install wget
$ wget https://launchpad.net/...
$ sudo dpkg -i zaptel*dajhorn*.deb
$ sudo module-assistant auto-install zaptel
$ sudo modprobe ztdummy
$ lsmod
  [holy crap, there's ztdummy]

Time for a Courtesy Reboot

Alrighty, you've installed Asterisk and Zaptel, it's probably time to do a reboot to make sure everything comes up right.

Code:

$ sudo reboot
Go grab a sandwich and come back in five minutes. It's time for a breather. When it comes back, make sure lsmod still shows ztdummy and Asterisk is still running. Is it? Good.

Installing lighttpd, PHP, MySQL, and FreePBX

It's time to install our web server, lighttpd, as well as the necessary muffins to execute PHP code. As mentioned above, we're using the FastCGI method to handle PHP requests. We'll also grab MySQL, and the necessary libraries to tie it all together. MySQL will want you to set a root password; remember what this is, for you will need it later on.

Code:

$ sudo apt-get install lighttpd php5-cgi php-pear php-db php5-mysql mysql-server mysql-client
Also, before we get too far down the road, let's save a copy of /etc/asterisk/modules.conf. There's a bit of a difference in philosophy between Debian/Ubuntu and FreePBX as far as what should be in this file. You'll need to copy this back in later...

Code:

$ sudo cp /etc/asterisk/modules.conf /etc/asterisk/modules.conf.original
With luck, you should now be able to connect to your server on port 80. Let's go ahead and get FreePBX going. I'm going to adapt the installation instructions for CentOS here. Grab the URL of the latest version from FreePBX's web site; as of this writing, it's freepbx-2.5.1.tar.gz. Put that over in /usr/src.

Code:

$ cd /usr/src
/usr/src$ sudo wget http://mirror.freepbx.org/freepbx-2.5.1.tar.gz
/usr/src$ sudo tar -zxf freepbx-2.5.1.tar.gz
/usr/src$ cd freepbx-2.5.1
The following database initialization commands will ask for your MySQL root password you entered when you installed MySQL above. This is to test your memory ;-) You'll also need to set a password for communication between FreePBX and MySQL... enter this instead of "secret" in the GRANT commands below.

Code:

/usr/src/freepbx-2.5.1$ sudo mysqladmin -p create asterisk
/usr/src/freepbx-2.5.1$ sudo mysqladmin -p create asteriskcdrdb
/usr/src/freepbx-2.5.1$ sudo mysql -p asterisk < SQL/newinstall.sql
/usr/src/freepbx-2.5.1$ sudo mysql -p asteriskcdrdb < SQL/cdr_mysql_table.sql
/usr/src/freepbx-2.5.1$ sudo mysql -p
mysql> GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO asteriskuser@localhost IDENTIFIED BY 'secret';
mysql> GRANT ALL PRIVILEGES ON asterisk.* TO asteriskuser@localhost IDENTIFIED BY 'secret';
mysql> flush privileges;
mysql> \q
Now, let's fire off the FreePBX installer. (Oh boy.)

Code:

/usr/src/freepbx-2.5.1$ sudo ./install_amp --username=asteriskuser --password=secret
  [...]
Enter your USERNAME to connect to the 'asterisk' database:
[asteriskuser] (press enter here)
Enter your PASSWORD to connect to the 'asterisk' database:
[secret] (press enter here)
Enter the hostname of the 'asterisk' database:
[localhost] (press enter here)
Enter a USERNAME to connect to the Asterisk Manager interface:
[admin] (press enter here)
Enter a PASSWORD to connect to the Asterisk Manager interface:
[amp111] (set something for this password!)
Enter the path to use for your AMP web root:
[/var/www/html] /var/www/freepbx (a reasonable path)
Created /var/www/freepbx
Enter the IP ADDRESS or hostname used to access the AMP web-admin:
[x.xx.xx.xx] (put your real hostname/IP here)
Enter a PASSWORD to perform call transfers with the Flash Operator Panel:
[passw0rd] (press enter here)
Use simple Extensions [extensions] admin or separate Devices and Users [deviceanduser]?
[extensions] (press enter here)
Enter directory in which to store AMP executable scripts:
[/var/lib/asterisk/bin] (press enter here)
Created /var/lib/asterisk/bin
Enter directory in which to store super-user scripts:
[/usr/local/sbin] (press enter here)
 
/etc/amportal.conf writtenAssuming new install, --install-moh
added to command line
OK
[... and away it goes!]
 
Please update your modules and reload Asterisk by visiting http://...
 
**********************************************
* Some Warning That Isn't Relevant Right Now *
**********************************************
Wow, that was fast and furious. Wow. Don't bother going to that URL just yet; we'll get there soon enough. Let's make a couple tweaks to configuration files. First, edit /etc/amportal.conf. This holds the configuration for FreePBX itself, and we want to change "AUTHTYPE=none" to "AUTHTYPE=database" around line 57. Second, pop open /etc/php5/cgi/php.ini. Change memory_limit = 16M (around line 270) to 100M, and change magic_quotes_gpc = On to Off (around line 457). This will make FreePBX happy. Before I forget, let's install a mail transport agent so e-mailing of voicemails and FreePBX plugin update reminders can work.

Code:

$ sudo apt-get install postfix
  [Choose "Internet Site" unless you know you need something else.]
  [Also go with the default for System Mail Name, usually.]

Making it all work

Right now, FreePBX is installed and in control of Asterisk, Asterisk is installed and should be working, and lighttpd is there. However, we do need to do some more work to get the lighttpd/PHP/FreePBX chain working. Using the current version of lighttpd in its default configuration, it will spawn its own PHP handlers (see /etc/lighttpd/conf-available/10-fastcgi.conf to see what I mean). Unfortunately, it can only spawn children as www-data, its own username. This makes privilege separation difficult. To fix this, we're going to start our own php-cgi handlers with asterisk's username, and tell lighttpd to use them when requests come in for FreePBX. We'll do this by adding a line to rc.local and by creating a configuration module for lighttpd. To /etc/rc.local, I added (before the exit 0):

Code:

echo -n "Starting FCGI handler for FreePBX... "
/usr/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 4001 -C 2 -u asterisk -g asterisk
echo "done."
This, on boot, starts php-cgi to listen on localhost:4001 with two children spawned. Additionally, and importantly, it is running as user and group "asterisk". This gives the FreePBX scripts the opportunity to modify the Asterisk configuration. Go ahead and run the spawn-fcgi line now (as root), to get things going. (It might be a good idea to do this from an init script instead, so stopping/restarting is easier. This will be your homework.) Now, lighttpd needs to be made aware of your fastcgi handler. I do this by creating a file called /etc/lighttpd/conf-available/10-freepbx.conf:

Code:

server.modules  += ( "mod_fastcgi", "mod_access" )
 
$HTTP["host"] == "your.http.hostname.here" {
    # deny access to scary places
    $HTTP["url"] =~ "^/freepbx/admin/modules/" {
        url.access-deny = ("")
    }
    else $HTTP["url"] =~ "^/freepbx/" {
        dir-listing.activate = "disable"
        alias.url += ( "/freepbx/" => "/var/www/freepbx/" )
        fastcgi.server = (
            ".php" =>
                ( "freepbx" => (
                        "host" => "127.0.0.1",
                        "port" => 4001
            )))
    }
}
Change line three (the $HTTP["host"] line) to match the hostname or IP address with which you'll be accessing FreePBX. Now, a couple permissions tweaks...

Code:

$ cd /var/www/freepbx
/var/www/freepbx$ sudo find . -type d | sudo xargs chmod 755
$ cd /usr/share/asterisk
/usr/share/asterisk$ sudo chgrp -R asterisk agi-bin
/usr/share/asterisk$ sudo chmod -R 770 agi-bin
Then, enable the module and restart lighttpd!

Code:

$ sudo lighty-enable-mod freepbx
Available modules: auth cgi fastcgi freepbx proxy rrdtool simple-vhost ssi ssl status userdir
Already enabled modules:
Enabling freepbx: ok
Run /etc/init.d/lighttpd force-reload to enable changes
$ sudo /etc/init.d/lighttpd force-reload
Syntax OK
* Stopping web server lighttpd                                          [ OK ]
Syntax OK
* Starting web server lighttpd                                          [ OK ]
You should then be able to go to http://yourhostname/freepbx/ and access the FreePBX server by clicking on FreePBX Administration. Hooray! Click on the big "Apply Configuration Changes" banner and life should be good. Remember how you copied /etc/asterisk/modules.conf a little while ago? Let's go ahead and put that back in.

Code:

$ sudo cp /etc/asterisk/modules.conf /etc/asterisk/modules.conf.freepbx
$ sudo cp /etc/asterisk/modules.conf.original /etc/asterisk/modules.conf
This would be a great time to reboot and make sure everything comes back up! You can now add extensions, trunks, et cetera as you normally would with FreePBX! Head over to the Getting Started documentation on FreePBX's site and have fun! If anything didn't work right, or if you have questions, feel free to comment below and I'll take a look.

15 comments

Comment from: Quinn Ebert [Visitor] Email
****-
Quinn EbertRyan,

In trying to "run through" your guide here, I've run into a bit of a problem (I am running on Linode, BTW)...

Once I get around to booting pvGrub with the Ubuntu-Server kernel, after taking a goodly amount of time to boot, things seem to "panic/hang" with the following output:
--LISH OUTPUT BELOW--
Press `ESC' to enter the menu... 0
Booting 'Ubuntu 9.04, kernel 2.6.28-14-server'

root (hd0)
Filesystem type is ext2fs, using whole disk
kernel /boot/vmlinuz-2.6.28-14-server root=/dev/xvda ro
initrd /boot/initrd.img-2.6.28-14-server

close blk: backend at [path erased]
close blk: backend at [path erased]
--LISH OUTPUT ABOVE--

...I'd like to admit right-off-the-bat that it's very possible I missed something in your instructions here (and on the various LinodeLibrary pages as-well), but, I'd love to get your input on what might be causing this one (also, bear in mind that I've obviously already googled around a bit on this one).

BTW, in closing, just like to say this is a great post -- For those of us who choose to do things a "bit differently" (I, for example, am running another FreePBX on CentOS, but not having a "great" experience with it), this kind of top-notch documentation is greatly enjoyed and appreciated, at least by me. ;)

Thanks for your Great Work!
--Quinn
08/05/09 @ 06:34
Comment from: Ryan [Member] Email
RyanHuh. From my Googling, that seems to be an indication that the target kernel isn't Xen-aware. However, the -server kernel should be. Hmmm.

I might recommend opening a ticket or stopping by #linode on irc.oftc.net to make sure there's not an obvious impediment... barring that, I could take a look at your menu.lst or post my (1.3GB) "known good" image somewhere.

Thanks for the kudos! I did use FreePBX+CentOS+Apache for awhile, but did a rebuild this spring and got the FreePBX+Ubuntu+Lighttpd combo going. The pv-grub part is new to me this week (I'm not even using it in production yet), but I'm amazed at how simple it turned out to be. The usual approach to getting ztdummy going involves grabbing the kernel source, half-compiling it, then compiling ztdummy against that, which is probably a little more difficult than it needs to be (especially when kernel upgrades occur).
08/05/09 @ 08:20
Comment from: Quinn Ebert [Visitor] Email
*****
Quinn EbertRyan,

I seem to have figured this out... Oddly enough, it appears that, of all things, using pvGRUB "hiddenmenu" seems to cause Lish to "hitch" and lock like this. I happened to realize this after I tried to hand-compile my own kernel, and it refused to boot (and thus gave me the opportunity to press ESC to return to the GRUB menu -- After pressing ENTER (on a bit of a "hunch") to try booting the "generic" kernel (which is 28-14-server, as-of-this-morning), it booted "just fine"... Seeing this behavior, I removed "hiddenmenu" from the GRUB menu.lst (again, on the same hunch from earlier), and voila, it now comes up "like it should."

...Just figured I'd pass along that bit of "oddness" ... Maybe if it's not the "Irish Luck" kicking-in in my case, it may help somebody else who might come upon the same behaviour in the future...

Again, thanks for the wonderful article, and for taking the time to reply to me on this. ;)

Thanks Again!
--Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 09:07
Comment from: Quinn Ebert [Visitor] Email
****-
Quinn EbertRyan,

Seem to have hit another ("last minute") bug in following your guide here:

After running through all of your instructions here, and doing what you so cleverly call the "courtesy reboot" (I love that, BTW, great term for it), seems /freepbx/admin gives a 403 error... A bit more delving into this issue (after enabling request-trace-debugging, and all that nice stuff) seems to indicate that this setup does *not* actually wind up using the asterisk user/group for the spawned FastCGI server (even when the "-u" and "-g" options are specified -- also, I even went to the extent of using the actual numerical id's for this user on my node, and still saw the same behavior...Other than that, though, looks like everything else (after I figured out the pvGrub issue) works just perfectly.

Any insight you could provide into this last "nagging issue" here? I'll be more than happy to provide any logs/etc that you may find useful.

Thanks Again!
--Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 10:29
Comment from: Ryan [Member] Email
RyanGood to know the pygrub stuff worked out! Exactly the sort of testing this sort of thing needs. :-)

Curious on the -u and -g thing... it only works if the spawn-fcgi is called as root (I was a little unclear about that, so just making sure). What user is it being spawned as?

Thanks!
08/05/09 @ 10:57
Comment from: Quinn Ebert [Visitor] Email
*****
Quinn EbertRyan,

Not sure, but, if you can tell me how to find that out, I can tell you...

But, to give a bit more detail, I enabled the request-tracing feature for lighthttpd, and a bit of digging through error.log wasn't incredibly helpful, but, it seems you forgot to add in the lines for showing users how to enable mod_fastcgi (which is why 403's were appearing)... However, once I enabled fastcgi, and the PHP scripts started being rendered correctly, the admin pages would error-out (Fatal-error-style) with permissions-related errors trying to access the files under /etc/asterisk -- This leads me to the belief that fastcgi (either it, or lighthttpd itself) isn't switching users properly, as a few quick peeks at the permissions under /etc/asterisk reveals that all of the users and permissions are properly assigned (e.g. all of the files *are* assigned to user/group ownership of the "asterisk" user and group).

Any further ideas?

Thanks!
--Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 11:19
Comment from: Quinn Ebert [Visitor] Email
*****
Quinn EbertRyan,

Sorry for the "extra noise," but, a quick look at the "ps" man page gave me the "tip" I needed; Seems php-cgi after the "courtesy" reboot starts spawning under the "Debian-ish" standard "www-data" user. Any idea of why it might be "resorting" to this?

Thanks!
--Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 11:23
Comment from: Ryan [Member] Email
RyanAh! The default lighttpd config for fastcgi spawns the fastcgi handlers from lighttpd itself. This is done after it drops root privileges, so it can't spawn it as a different user. There's a workaround for this in two parts at the top of the "Making it all work" section above.

In short, you need to:
1) Use spawn-fcgi as root to start the php-cgi handlers, and
2) Tell lighttpd to use it for FreePBX.

The first two bits in that section should do it... note that you might have to tweak the HTTP line (the third one in the 10-freepbx.conf) a little bit to match the URL you're accessing FreePBX with.
08/05/09 @ 11:59
Comment from: Quinn Ebert [Visitor] Email
****-
Quinn EbertRyan,

OK, my apologies, but, I'm obviously misunderstanding your verbiage here... As far as I can tell, I've already handled these (I have both the stuff for the custom "freepbx" module for lighthttpd, and the 3 lines I added to rc.local)... Something I missed, then?

Thanks,
Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 12:10
Comment from: Quinn Ebert [Visitor] Email
Quinn EbertRyan,

OK...I figured out what I missed here... Just a bit of a "suggestion" for you here based on an observation... Regarding the portion to your users about editing line 3 of 10-freepbx.conf, I misread into how to edit it -- I'd entered the "linode-given" hostname there (which is what I understood I was supposed to do), but, me just being "the way I am," I somehow found it perplexing when I went through my "usual practice" of accessing a newly-provisioned server directly by IP (and, of course, the way things work with this config setup, that doesn't give *quite* the expected result through the "socketed" fastCGI setup)... So, that one just can be chalked up to "user error" -- not *really* an issue on the part of your guide (although, it could be beneficial to maybe note for your readers that line 3 should be edited "to include the hostname you'll be browsing to later for freePBX admin" or something like that.

Sorry again for the added trouble on your part, and, keep up the good work here...I know I (for one) certainly do appreciate it. ;)

Thanks Again!
--Quinn

On Jul 29, Quinn Ebert wrote "Several BIG Issues with O&O’s New Defrag V11?".

08/05/09 @ 12:48
Comment from: Ryan [Member] Email
RyanGood call... I've edited it to make things more clear in that section. I never did fully explain WHY that needed to be done, hence the confusion. Thanks for the suggestion, and for being the guinea pig! :-)
08/05/09 @ 16:06
Comment from: Maria [Visitor] Email
****-
MariaI recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.



08/05/09 @ 22:40
Comment from: JT [Visitor]
*****
JTGreat howto. I used it for set up on a stand alone server with Apache and it was the first one that worked straight away for me! Well done. Just one point, I think the line:

sudo mysql -p asterisk <SQL/cdr_mysql_table.sql

should be:

sudo mysql -p asteriskcdrdb <SQL/cdr_mysql_table.sql

That's what I used anyway. Thanks for your clear, well thought out, no BS instructions.
09/22/09 @ 14:18
Comment from: Ryan [Member] Email
RyanJT, I believe you're right. D'oh! I should have caught that.

Thanks for the props... my goal was to go as far off the beaten path as I could, with the hope that individual pieces could be used in other, less-insane situations :-) Glad it worked for you with Apache!
09/27/09 @ 14:24
Comment from: Oddballhero [Visitor]
*****
OddballheroGreat howto, actually used this to configure my pogoplug to run Asterisk, FreePBX, with lighttpd.
09/28/10 @ 19:58

Comments are closed for this post.

Blog posts come from a can. They were put there by a man in a factory downtown.

Recent Twitterings

    Stalk me with RSS

    Search the Blog

     

    Support the Beer Fund

    Powered by Linode: Life's too short for crappy hosting

    [Powered by Linode]

    powered by b2evolution

    © 1962-2014 by Ryan Tucker (Public Key)

    Contact | Help | b2evolution skin by Asevo | blogging tool | blog hosting | Francois