Android, IT

PHP and Lighttpd for Android

Update 7 May 2012: New version released, containing PHP 5.4.2 version (CGI only). It now contains openssl / curl / SQLite modules statically linked within php-cgi executable and thus curlssl works! Beside the version number, all installation instructions below still apply.

If you are already using PHP 5.3.8, just grab the php-cgi file from the 5.4.2 archive system/xbin folder and replace the /system/xbin/php-cgi on the device.

Introduction

Below you can find an bundle of PHP 5.3.8 (CGI only) and Lighttpd 1.4.29 (FastCGI module included) which are cross compiled for ARMv5 CPUs (Android platforms mainly).

As you mail well know, both PHP and Lighttpd offer modules that could be loaded at run-time based on settings within configuration files. The bundle doesn’t include all modules, due to difficulties encountered when compiling for ARM platforms. Those modules that are included are statically linked in the executables (so no additional files are needed) nor configuration files need to be updated to load them.

Screenshots

Below you can see screenshots with the phone browser opening localhost address. Once you unpack the archive, there’s an index.php file which just calls phpinfo() to show the details about the build.

Of course, you can remove the file and put your own scripts πŸ™‚

phpinfo() on Sony Arc

phpinfo() on Sony Arc

phpinfo() on Sony X10 Mini

phpinfo() on Sony X10 Mini

PHP Modules

The list of PHP modules that are statically linked:

[root@arc]/sdcard# php -m
[PHP Modules]
cgi-fcgi
Core
ctype
date
dom
ereg
fileinfo
filter
ftp
gd
hash
iconv
json
libxml
pcre
PDO
pdo_sqlite
Phar
posix
Reflection
session
SimpleXML
soap
sockets
SPL
SQLite
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib

[Zend Modules]

Lighttpd Modules

mod_indexfile
mod_userdir
mod_dirlisting
mod_status
mod_simple_vhost
mod_evhost
mod_secdownload
mod_cgi
mod_fastcgi
mod_scgi
mod_ssi
mod_proxy
mod_staticfile
mod_evasive
mod_compress
mod_usertrack
mod_expire
mod_accesslog

Download

This comes with NO WARRANTY. Use it at your own risk!

php-5.4.2_lighttpd_1.4.29_armv5.tar.gz

php-5.3.8_lighttpd_1.4.29_armv5.tar.gz

License

Please check README.txt file found in /system/README.txt within the bundle.

PHP executable is offered under PHP license, Lighttpd executable under Lighttpd license, all other files in the bundle are offered under New BSD License (3 clause BSD license).

Installing

The bundle tries to mimic as much as possible the layout of a Debian installation of the two files. However, due to file system layout on Android phones (binaries under /system folder), the folders are one step down, under /system folder:

`-- system
    |-- bin
    |   |-- lighttpd -> /system/xbin/lighttpd-static
    |   `-- php -> /system/xbin/php-cgi
    |-- etc
    |   |-- lighttpd
    |   |   `-- lighttpd.conf
    |   `-- php
    |       `-- php.ini
    |-- var
    |   |-- log
    |   `-- www
    |       `-- index.php
    `-- xbin
        |-- fcgiserver
        |-- lighttpd-static
        |-- php-cgi
        |-- reload_fcgi.sh
        `-- reload_lighttpd.sh

Prerequisites:

  • rooted phone with busybox installed.
  • mount the /system partition as RW.

Using DroidSSHd on the phone and connecting with Putty (or equivalent) makes the whole process faster.

After you copy the archive above into the root of your SD Card, installation is easy:

cd /
tar xf /sdcard/php-5.3.8_lighttpd_1.4.29_armv5.tar.gz
reload-fcgi.sh
reload-lighttpd.sh

You might notice that the owner / group of the files is 1000:1000. Ignore that, as long as you execute them as root, there’s no issue (those are the IDs of my username on the PC I created the tar.gz archive and tar tries to conserve the user / creation time / etc from when the archive was created).

The last two commands start the FCGI server (PHP with 4 children processes), and then launch lighttpd server as daemon.

The default port is 80.
Default htdocs folder is /system/var/www.

The configuration files are under /system/etc/lighttpd/lighttpd.conf and /system/etc/php/php.ini. To restart either PHP or Lighttpd, please use one of the commands above.

It is mandatory that you are on the root folder when you extract the archive. tar will take care of creating all the missing folders, creating the links, etc, as long as you are on the root folder.

You can now open the phone’s browser and point it at localhost πŸ™‚ and the phpinfo() page should appear.

Example usage

Installing Simple Machines Forum 2.0.1 on Android

Before executing the commands below, you need the “Full Install” smf_2-0-1_install.tar.gz archive downloaded from SMF and then copied onto your /sdcard root folder.

# cd /system/var/www
# ls
index.php
# mkdir forum
# cd forum
# tar xf /sdcard/smf_2-0-1_install.tar.gz
# reload_fcgi.sh
# reload_lighttpd.sh

Last two commands are optional, if you already started the FastCGI server as well as lighttpd.

You should now connect to http://localhost/forum and finish installation of the forum.

Enjoy πŸ™‚

49 Comments

  1. Darkness Angel

    you don’t need to DEFAULT_LIMIT_REQUEST_LINE

    it will make 413 error when try to attatch large file πŸ™ (default value is 2GB but your httpd has too small value)

    if someone want to increase it

    add this lines on your lighttpd.conf
    server.max-request-size=10240
    server.network-backend=”writev”
    server.upload-dirs=( “/sddata/www/tmp” )

    size=kb
    dirs=must same as upload_tmp_dir on your php.ini

  2. Eric

    Could you let me know how to cross compile it?
    Thanks!

  3. Comment by post author

    To make a long story short, please start here http://buildroot.uclibc.org/ and compile for ARM (generic ARM).

  4. Eric

    Thanks!!

    I have port it to Androd, but the mod_* is *.so, e.g. mod_indexfile.so.
    How to build it static, how to link the mod_* all into a singal binary?

  5. Comment by post author

    You need to know scons and use that to compile lighttpd, just patching configure script didn’t work for me. Scons generates more than configure it also generates plugin-static.h file. BUT it generates it badly.

    Internally, scons uses a dictionary data structure to store what plugins need to be statically compiled; when it writes out the plugin-static.h file, it doesn’t keep the correct order (since dictionaries in Python are not ordered). I’ve described the bug here: http://redmine.lighttpd.net/issues/2343
    Please read the description and solution there. You still need to edit the plugin-static.h file per description above.

    πŸ™‚ Hope it helps…

    Also, I found it helpfull to work with the ldd command (built for your target) as well as strace on the phone itself.

  6. Eric

    Thanks so much!!! It’s very helpful.

  7. phpdevloper

    There are no binaries included.

  8. Comment by post author

    @phpdevloper – where did you look for them πŸ™‚ ? They are there, please check /system/xbin folder in the archive.

  9. phpdeveloper

    @viulian: I got it it was symlinked.

    But now I am finding out to get it at work, I got a 503 error because of port 9001.

    2011-10-17 17:39:05: (src/log.c.166) server started
    2011-10-17 17:39:27: (src/mod_fastcgi.c.2904) establishing connection failed: Connection refused socket: tcp:127.0.0.1:9001
    2011-10-17 17:39:27: (src/mod_fastcgi.c.2910) backend is overloaded; we’ll disable it for 1 seconds and send the request to another backend instead: reconnects: 0 load: 1
    2011-10-17 17:39:29: (src/mod_fastcgi.c.2852) fcgi-server re-enabled: tcp:127.0.0.1:9001

  10. phpdeveloper

    Works fine but some PHP sites run very slowly (20 seconds or more to load page). I use lots of regexp thay maybe the problem ?
    On other devices I used lighttpd as well with success : the Nokia N810 and iPad 2 (the latter I stell have).

  11. Comment by post author

    1. It is compiled for ARMv6 without FPU support (so it should be slow for math operations). Dunno about regexp – but it might be that they are slow too ?
    2. I also noticed that if processing is involved, phone tends to be slow. I put in some -O3 optimisations and so on, but since it is not using any advanced ARM instructions (but generic ARM) it might be the reason why it is slow.

    I will try to compile these days using ARMv7 (since the goal was to have a release that runs on many phones), and also fix the system bug (PHP has the /bin/sh path hardcoded) – and will post an update. But probably towards the end of the week.

  12. phpdevloper

    Thanks ! Well done !
    And I also had to change the paths as the /system partition is nearly full (rooted Galaxy S2 with Busybox), so I put the logging, configs and the php (10MB) and lighttpd binaries on the /data partition which also has the advantage of reverting the /system partition readonly after installing.
    Even on a ‘normal’ unrooted Galaxy the /system partition is nearly full.
    I symlinked the htdocs (var/www) to a user-accessible folder on /mnt/sdcard.

  13. phpdevloper

    @Viulian: If you are interested in a test script you can send me an email (email address is logged here).

  14. phpdeveloper

    After some research, the slowness of my sites running on your PHP / lighttpd is not your server software, but a bug in Android / busybox which does not resolve hostnames. That results in that the PHP gethostbyname() function waits for 10-20 seconds which makes the webserver seemingly slow.
    The same issue occurs when you open a terminal to a rooted Android device, (e.g. via ssh) and then run “ping google.com” or “wget facebook.com” which result in “Bad address”.

    I think your compiled version can even run on non-rooted devices, as long the software is installed on user-accessible folders such as /mnt/sdcard, and therefore no symlinks are used (this is a FAT filesystem). Maybe /data/data can be used as well because this folder is ext3 and thus does allow symlinks and running shellscripts. E.g. the sshdroid app from the Market has a ‘busybox’ which can be used on non-rooted devices. Moreover the port number should be above 1024. That is all.

    @viulian if you have questions, feel free to mail me.

  15. Comment by post author

    @phpdeveloper – thank you for all the feedback πŸ™‚ I was busy these days.

    I did not want to make a complex installer (messing with SD Card, partitioning and so on) so that the PHP is available for most phones out there.

    So far the requests were about startup scripts as well as being able to locate it somewhere else. I have the installer that installs Midnight Commander, and I will probably update it to install all the apps that I’ve manage to cross-compile. One of the options would indeed be where to extract all the archives (but if you won’t use /system/xbin – then probably it’s up to the user to add the PATHs to the environment, etc).

  16. Rafael

    When I try to untar the file on my phone it says “tar: invalid tar magic”.
    what do i do?

  17. Comment by post author

    What extraction command are you using ?

    With a version of busybox that I have tar xf does the job.

  18. Comment by post author

    system(…) but is fixed!

    Actually, even if PHP has /bin/sh hardcoded within proc_open.c, it seemed not used in case of system/exec. It is in fact delegating to the underlying libc , by using the standard system() call of libc. I have recompiled the libc with the /system/bin/sh and now it is working.

    The archive is updated, please redownload.

  19. Anyone know of a MySQL server as well?

  20. krzych

    @phpdeveloper – it’s not android bug, it’s just yours busybox bug (probably included with sshdroid – mine buggy version was from there). Try to download TitaniumBackup (it has busybox compiled by their dev’s and it’s working well with resolving, additionally it’s optimised). Remember to change PATH and symlinks if you want to use their busybox systemwide.

    We need real sshd… Viulian? πŸ˜€

  21. Comment by post author

    I wanted to mention that the libc used to build this PHP is uClibc – and not Android’s libc (the default one).
    However, uClibc is actually following the standard and using /bin/sh for system(..) calls.

    The trouble is the Google decided to use a specific /system/bin/sh instead of /bin/sh – so I had to change the source code of uClibc to hardcode /system/bin/sh instead of /bin/sh – to obtain an executable that works properly on Android.

  22. haiyyu

    Hey.
    I hope you’re reading this.
    I have tried installing PHP and lighttpd by following the instructions in your post.
    Unfortunately I couldn’t extract the tar.gz archive using the tar command on my phone (BusyBox is installed) as it kept telling me the “magic number” of the archive was invalid.
    So what I did is I extracted every single file to the specific folder (example: archive.tar/system/etc/lighttpd/lighttpd.conf to /system/etc/lighttpd/lighttpd.conf) after extracting the archive on my computer (it worked there). My problem is that I seem to be unable to copy “php-cgi” to the folder it’s supposed to be copied into (/system/xbin). I keep getting told copying the file failed.
    I’m running Android 2.3.5 on a rooted Samsung Galaxy S2.

    I would really appreciate it if you helped me as I would really like to run a webserver on my phone. πŸ™‚

  23. haiyyu

    What I forgot to mention in my last comment: Yes, I’m copying it as root. Every other file worked. I could even copy all the other files that were supposed to go into /system/xbin. Only “php-cgi” is refused to get copied.

  24. adoet_t

    can’t extract tar file,,

    tar xf /sdcard/php-5.3.8_lighttpd_1.4.29_armv5.tar.gz
    tar: invalid tar magic

    which version busybox you use?

    sorry my poor english

  25. phpdevloper

    @haiyyu:

    You must make the /system partition r/w as it is readonly be default. This can be done by SuperManager file browser in the Options.

    A better option is to put cgi-bin in the /data partition and symlink /system/xbin/php-cgi to the copy on the /data partition (You still need to r/w the system partition for one time). This keeps the system partition clean and it is already nearly full.

  26. When i try to copy a file in paw server directory from a web site URL fails, why?
    This is error message:

    Warning: copy(): php_network_getaddresses: gethostbyname failed. errno=111

    There seems to be a problem with the name resolution.

  27. Comment by post author

    About gethostbyname failed. errno=111

    I remember a similar issue when reading about OpenVPN. The static glibc that is bundled with OpenVPN needs to have access to /etc/resolv.conf, but Android doesn’t have it. You can manually add it.

    I suspect a similar problem happens with this PHP too, please check /etc/resolv.conf or /etc/hosts to make sure they have valid data.

    I will also check it out.

  28. Little Zhao

    There are some devices that the /system/xbin directory can’t be mounted r/w.So I tried to copy the php-cgi , lighttpd , fcgiserver to /system/bin. And it works!

  29. Comment by post author

    Thank you for feedback! Can you please tell an example of the said device ?
    I expect them to work since the path is not hardcoded, and everything is statically linked, so they should run on any ARMv5 CPU from wherever you have the rights to execute them. Only the default configuration files might need change.
    But is true, I could modify the installer to allow user to specify other install folder.

  30. Little Zhao

    It’s “HTC magic”,the second android phone of the world. “/system/xbin” is not a normal directory of “/system”,it’s another partition and it can’t be mounted r/w, leastways I cannot!
    Another questions was that the php process have a high CPU load and all php pages will be halt, only the static pages work will.
    My English is not well, I hope you can understand!

  31. Wow! this is so cool! I will try this on my android tablet later!

  32. Joris

    Hi, I’m using PAW for Android which is using your PHP as a plugin. I’m trying to use fopen() to open another website but I’m getting this error (Same problem as Salvatore Bianchi):

    Warning: fopen(): php_network_getaddresses: gethostbyname failed. errno=111

    You responded with:
    “… please check /etc/hosts to make sure they have valid data.”
    I did check the hosts file, and there is only one line:
    127.0.0.1 localhost
    Is that what you call “valid data”?

    I’m not using a rooted Tablet, could that be the problem?
    Is there any other way to open or get the contents of another website (file_get_contents() gives the same error)?

  33. Comment by post author

    @Joris, what about /etc/resolv.conf ?

    I’ve wrote a small script to test:

    [sourcecode language=”php”]
    <?php
    $time = file_get_contents(‘lovetime.ro/time.php’);
    echo($time);
    ?>[/sourcecode]

    and it hanged for a while then died with:

    [sourcecode lang=”php”]failed to open stream: php_network_getaddresses: gethostbyname failed. errno=111[/sourcecode]

    I’ve then created the /etc/resolv.conf and checked again:

    [sourcecode lang=”php”]
    [root@arc]/system/var/www# cat /etc/resolv.conf
    nameserver 208.67.220.220
    nameserver 208.67.222.222
    [root@arc]/system/var/www# php time.php
    X-Powered-By: PHP/5.3.8
    Content-type: text/html

    Original Time: 01:50:08
    <br/>New Time: 01:50:08
    [/sourcecode]

  34. Joris

    Hi viulian,
    Thanks for your answer. I tried your solution, but as I said: I haven’t rooted my Samsung Galaxy tab 8.9, so I don’t have write acces in the directory /etc/. The App PAW Server that I’m using also has an ‘etc’ folder in ‘/mnt/sdcard/paw/etc/’ folder, so I put resolv.conf in that folder, but that didn’t help. I also tried creating an ‘etc’ folder in the webroot folder of PAW: ‘/mnt/sdcard/paw/html/etc/’. Didn’t work either.

    I did solve the problem by opening a socket to the right IP address with fsockopen() and then create a HTTP request with the right headers. This worked for me. But the ‘file_get_contents’ function would be easier in use.
    Does this mean it isn’t possible to solve this problem without a rooted device?

    Thanks for your support.

  35. Comment by post author

    Good workaround πŸ™‚

    Well, I think the trouble with /etc/resolv.conf is that I guess it is hardcoded into ucLibc (as it follows glibc standard which assumes /etc/ exists).
    I had a similar issue in the past, where the PHP exec() would call /bin/sh to invoke the script – and the trouble was not in PHP but in the glibc – again hardcoded value for /bin/sh – I had to recompile and have it hardcoded to /system/bin/sh ..

    I would probably have to search glibc for /etc/resolv.conf (and /etc/hosts, /etc/nsswitch.conf) and made them configurable somehow – but I still need to figure out a way – since I can’t assume anything if the Android device is not rooted.

  36. Joris

    Thanks. Well, that explains it a bit. I hope you’ll come up with a solution. I’ll just check back on your website once in a while to see if there is a new version. For now, the socket solution works good enough.

    And if you need a new build to be (bΓ©ta) tested on a non-rooted device, I’m happy to help.

  37. shxish

    No armV7 architecture version

  38. aks

    when will be a curl library included…???

  39. Dean

    Do you think php5.4 can be compiled for android? 5.4 has it’s own built-in webserver!
    I’ve tried with buildroot but it seems to ignore php’s configure.in file…

  40. Comment by post author

    @Dean: I will give it a try in the weekend to see.

    I will also investigate about curl issue to see what’s up with it.

  41. Comment by post author

    I have successfully build 5.4.1 with curl and SSL option πŸ™‚

    It was nasty, I think I will put a “Donate” button on the page.

    Anyway, here’s an update:

    [sourcecode lang=”bash”]
    [root@arc]/system/var/www# php -v
    PHP 5.4.1 (cgi-fcgi) (built: Apr 28 2012 03:52:49)
    Copyright (c) 1997-2012 The PHP Group
    Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies

    [root@arc]/system/var/www# php -m
    [PHP Modules]
    cgi-fcgi
    Core
    ctype
    curl
    date
    dom
    ereg
    fileinfo
    filter
    ftp
    gd
    hash
    iconv
    json
    libxml
    openssl
    pcre
    PDO
    pdo_sqlite
    Phar
    posix
    Reflection
    session
    SimpleXML
    soap
    sockets
    SPL
    sqlite3
    standard
    tokenizer
    xml
    xmlreader
    xmlwriter
    zlib

    [Zend Modules]

    [/sourcecode]

  42. shxish

    $ su
    # reload_fcgi.sh
    could not kill pid -9: No such process
    # reload_lighttpd.sh
    could not kill pid -9: No such process

    How to solve this problem???(ARMv7 cpu ,android2.3.4)

  43. Comment by post author

    I think those message only mean that the processes are not found (debug messages) and thus it had nothing to kill (probably the processes were not running).
    If they are not running, then you have to check the logs to see why they failed to start.

  44. Dean

    Hi, that’s great about 5.4! So are you going to open-source it or otherwise document how to get it done?
    I tried a bit the other week but I’m still quite new to cross-compiling…
    A donate button would be a great idea πŸ™‚

  45. phpdevloper

    Where can I download 5.4.1 ?

    And is it affected by the PHP bug depicted here ?

    http://www.php.net/archive/2012.php#id2012-05-03-1

  46. Comment by post author

    I did not release it yet since I got caught up in other ports … I’m working to see if I can get GCC running on Android itself and compiling things directly on the phone.

    If 5.4.1 had the bug, then yes, but I will actually cross compile 5.4.2 then to not have the issue.

  47. Comment by post author

    [sourcecode lang=”bash”]
    [root@arc]/system/xbin# php-cgi -v
    PHP 5.4.2 (cgi-fcgi) (built: May 6 2012 10:40:15)
    Copyright (c) 1997-2012 The PHP Group
    Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    [/sourcecode]

    About the source code, I did not modify anything … only that the build scripts that are heavily depended on my environment so not really reusable.

  48. phpdevloper

    You meant did not change anything since 5,3,8 ?
    But you have a workable binary ?

Leave a Reply