PHP mail() not working in chroot vhost (Could not execute mail delivery...)

Written by - 2 comments

Published on - Listed in PHP Linux Mail


In an Apache chroot environment per virtual host, one has to take special care about PHP's mail() function, as it needs more than the actual sendmail binary.
Although this installation was using mini_sendmail (due to the complexity of normal sendmail which would have to be re-installed in every chroot environment), the function didn't work.

By doing some tests of a new hosting platform I also tested the function mail() which threw an error like the following on the browser:

PHP Warning:  mail(): Could not execute mail delivery program '/opt/local/mini_sendmail -t' in /var/www/hosting1/htdocs/mailtest.php on line 2

The mail delivery program, which is defined in php.ini in the sendmail_path variable, is well available and executable in the chroot environment. So there must be another problem with the chroot (I tested the same hosting without chroot and it worked).

On the PHP documentation page for the mail() function, I found the following hint by Sven Riedel:

mail() requires /bin/sh to exist in Unix environments, next to a mail delivery program. This is very relevant when setting up apache in a chroot environment. Unfortunately this isn't anywhere in the documentation and took me several months to figure out.

This is a very important hint! I checked it and although /bin/sh was also available in the chroot environment, it was not executable. Actually /bin/sh was a symlink to /bin/ksh which threw the following error by trying to execute it in the chroot cage:

# chroot /var/www/hosting1

bash-4.1# /bin/sh
/bin/sh: getexecname() failed

To be able to run /bin/sh (or /bin/ksh in this case) /proc needed to be mounted in the chroot environment.
Note: /bin/bash was working and executable...

So once /proc was mounted and /bin/sh was executable, I tried it again, this time by simply using the php cli:

bash-4.1# php -c /opt/local/php.ini mailtest.php
PHP Warning:  mail(): Could not execute mail delivery program '/opt/local/mini_sendmail -t' in /var/www/hosting1/htdocs/mailtest.php on line 2

Same error! The only difference between the "normal" server environment and the chrooted one was the mountpoint /dev. But is /dev necessary to send an e-mail? I decided to trace it down with truss and to my big surprise the answer is yes, it is necessary.
The following files were opened after executing mailtest.php (I removed unnecessary truss-lines):

# truss /var/www/hosting1/opt/local/php -c /var/www/hosting1/opt/local/php.ini /var/www/hosting1/htdocs/mailtest.php
write(2, "\n", 1)                               = 1
stat("/var/www/hosting1/htdocs/mailtest.php", 0x00A51E48) = 0
access("/usr/bin/sh", X_OK)                     = 0
open("/dev/null", O_RDWR)                       = 4
fcntl(4, F_GETFD, 0xFFFFFF22057007E0)           = 0
pipe()                                          = 5 [6]
access("/usr/bin/sh", X_OK)                     = 0
open("/dev/dtrace/helper", O_RDWR)              = 0
ioctl(0, DTRACEHIOC_REMOVE, 0x00000000)         = 0
close(0)                                        = 0

Thanks to truss' output, I saw that /usr/bin/sh (/bin/sh symlinks to it), /dev/null and /dev/dtrace/helper were opened to send the mail.

Long story short: To be able to send e-mails in a chrooted PHP hosting environment you need to have the real /proc and /dev mounted.


Add a comment

Show form to leave a comment

Comments (newest first)

Claudio from Switzerland wrote on Aug 8th, 2012:

Hi Josh. Are you running Linux? I'd launch strace on the php file which is having dns issues. You should then see a similar output like in my article pointing you to the missing files. Just out of the blue I'd say that /proc and /dev needs to be mounted in the chroot environment.


Josh from United States wrote on Aug 8th, 2012:

I\\\'m having dns issues with php-fpm\\\'s chroot feature. Do you know what exactly needs to be in the chroot\\\'s folder for everything to function properly?


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Icingaweb   Icingaweb2   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder   


Update cookies preferences