When migrating an old Apache server of mine to CentOS 7, it broke horribly because my old web server relied on a slightly modified suexec binary which was compiled to use a different document root. This is because all of my web sites live under "/home" and not under "/var/www".
It took me a few hours to figure out, mostly because there seems to be very few good articles on the subject. Anyway, I finally got it working in a sort of hackish way.
Before we go any further, I have to assume you know the very basics of compiling software. You'll need to have installed some basic stuff like gcc, kernel headers and such or you won't get very far. This article focuses on the specifics of getting the suexec binary built. Nothing more. Seriously, you won't even get a complete Apache web server by following this advice. Just a working suexec.
Still with me? Good :-)
0. Install RPM dev tools. This should set you up with a nice set of directories under ~/rpmbuild
$ yum install rpmdevtools
$ cd ~/rpmbuild/SOURCES
1. Download the newest Apache source (you need the .bz2, not the .tgz)
$ wget http://apache.uib.no/httpd/httpd-2.4.10.tar.bz2
2. Try to build the RPM to get a list of dependencies (it will most likely fail)
$ rpmbuild -tb httpd-2.4.10.tar.bz2
error: Failed build dependencies:
libselinux-devel is needed by httpd-2.4.10-1.x86_64
libuuid-devel is needed by httpd-2.4.10-1.x86_64
apr-devel >= 1.4.0 is needed by httpd-2.4.10-1.x86_64
apr-util-devel >= 1.4.0 is needed by httpd-2.4.10-1.x86_64
pcre-devel >= 5.0 is needed by httpd-2.4.10-1.x86_64
openldap-devel is needed by httpd-2.4.10-1.x86_64
lua-devel is needed by httpd-2.4.10-1.x86_64
libxml2-devel is needed by httpd-2.4.10-1.x86_64
distcache-devel is needed by httpd-2.4.10-1.x86_64
openssl-devel is needed by httpd-2.4.10-1.x86_64
3. We don't want to have to recompile those, so let's just install the RPMs
$ yum install libselinux-devel libuuid-devel apr-devel apr-util-devel pcre-devel openldap-devel lua-devel libxml2-devel distcache-devel openssl-devel
4. Notice that 'distcache' still doesn't work
$ rpmbuild -tb httpd-2.4.10.tar.bz2
error: Failed build dependencies:
distcache-devel is needed by httpd-2.4.10-1.x86_64
5. Get the Fedora source RPM for that, build it and install it
$ wget http://www.gtlib.gatech.edu/pub/fedora.redhat/linux/releases/18/Fedora/source/SRPMS/d/distcache-1.4.5-23.src.rpm
$ rpmbuild --rebuild distcache-1.4.5-23.src.rpm
$ rpm -ivh ~/rpmbuild/RPMS/x86_64/distcache-1.4.5-23.x86_64.rpm ~/rpmbuild/RPMS/x86_64/distcache-devel-1.4.5-23.x86_64.rpm
6. Now try again to build the vanilla Apache server
$ rpmbuild -tb httpd-2.4.10.tar.bz2
For me, it still failed with a "file not found" but only AFTER it had successfully compiled "suexec" so it doesn't matter:
$ ~/rpmbuild/BUILDROOT/httpd-2.4.10-1.x86_64/usr/sbin/suexec -V
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
7. Delete the "suexec" binary that we just compiled. Trust me.
rm ~/rpmbuild/BUILDROOT/httpd-2.4.10-1.x86_64/usr/sbin/suexec
8. Now edit the file "~/rpmbuild/SPECS/httpd.spec" which controls exactly how the source gets compiled.
We need to make two changes:
1) At the very beginning of the file, add the following line:
%define homedir /home
2) Locate the following line:
--with-suexec-docroot=%{contentdir} \
replace with
--with-suexec-docroot=%{homedir} \
9. Now build the (slightly) modified Apache server (notice the different rpmbuild command)
$ rpmbuild -bb ~/rpmbuild/SPECS/httpd.spec
10. It failed the last time around so expect it to fail this time too. We're still only interested in the "suexec" binary though, so let's check it out:
$ ~/rpmbuild/BUILDROOT/httpd-2.4.10-1.x86_64/usr/sbin/suexec -V
-D AP_DOC_ROOT="/home"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
Notice anything else you'd like to change while you're at it? Go back and edit the .spec file, now that you know how. I wouldn't go changing anything in the actual source code though, because unless you're an expert and know EXACTLY what you're doing, you will most likely introduce a security vulnerability. Seriously, don't.
11. Copy the fresh binary into your web server and you should be all set to restart Apache:
$ cp ~/rpmbuild/BUILDROOT/httpd-2.4.10-1.x86_64/usr/sbin/suexec /usr/sbin/suexec
cp: overwrite ‘/usr/sbin/suexec’? y
$ systemctl restart httpd
12. Now, there's a couple of more things you should consider.
Because the suexec that ships with CentOS is "improved" to use syslog instead of a plain old log file and the version we just compiled uses a plain old logfile, you need to create that log file and make it writable for the 'apache' user, or these error messages will appear in your error_log file:
[Mon Dec 01 12:38:50.919555 2014] [cgi:error] [pid 17535] [client 10.1.1.53:55449] AH01215: suexec failure: could not open log file, [...]
[Mon Dec 01 12:38:50.919615 2014] [cgi:error] [pid 17535] [client 10.1.1.53:55449] AH01215: fopen: Permission denied, [...]
$ chmod 755 /var/log/httpd
$ touch /var/log/httpd/suexec.log
$ chown apache:apache /var/log/httpd/suexec.log
$ chmod u+s /usr/sbin/suexec
You will also want to edit the file "/etc/logrotate.d/httpd" and insert the keyword "create":
/var/log/httpd/*log {
missingok
notifempty
sharedscripts
delaycompress
create
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
This will ensure that when logrotate periodically removes the log file, a new (empty) log file is created in its place with the correct permissions/ownership.
If this worked for you, please consider letting me know. If it didn't, then please try to figure out why and then let me know :-)