Enable UserDir with Centos 6 and SELinux

I had unfortunate opportunity to play with RedHat / Fedora / CentOS distribution today. I have to say that as much as I hate Ubuntu, CentOS is even worse than it was few years ago when CentOS5 was still current.

And now we're ignoring RHEL7 / CentOS7 where headless server installer requires GUI that's optimized for touch screen and tries to imitate Ipad. Recommended solution? Use VNC to connect installer. Aargh! I should probably have Ipad to run that VNC client - for improved user experience you know.

One of main culprits with near sane CentSO6 is still SELinux (and NetworkManager, you can't hate NetworkManager enough).

I wanted to enable http://server.example/~haxor/ style urls. Well that's easy, right? Enable UserDir in apache conf, create ~haxor/public_html and allow apache process to read it. Not quite so.

Of course this is documented -- and all available documentation is incorrect. Internet is full of blog posts just copy-pasting that flawed documentation followed by comments how no one got it working.

Time to set things right. Because this one works. At least on CentOS 6.6 x64, wouldn't surprise a bit anymore if it's different with CentOS 6.5 and upcoming 6.7.

# Install apache
yum -y install httpd

# Edit config file /etc/httpd/conf/httpd.conf
--- httpd.conf.old      2014-12-13 01:21:09.144233371 +0200
+++ httpd.conf  2014-12-13 01:49:58.478233709 +0200
@@ -363,14 +363,14 @@
     # of a username on the system (depending on home directory
     # permissions).
-    UserDir disabled
+    #UserDir disabled

     # To enable requests to /~user/ to serve the user's public_html
     # directory, remove the "UserDir disabled" line above, and uncomment
     # the following line instead:
-    #UserDir public_html
+    UserDir public_html


@@ -378,18 +378,19 @@
 # Control access to UserDir directories.  The following is an example
 # for a site where these directories are restricted to read-only.
-#<Directory /home/*/public_html>
-#    AllowOverride FileInfo AuthConfig Limit
-#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
-#    <Limit GET POST OPTIONS>
-#        Order allow,deny
-#        Allow from all
-#    </Limit>
-#    <LimitExcept GET POST OPTIONS>
-#        Order deny,allow
-#        Deny from all
-#    </LimitExcept>
+<Directory /home/*/public_html>
+    AllowOverride FileInfo AuthConfig Limit
+    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec Indexes
+    IndexOptions FancyIndexing
+        Order allow,deny
+        Allow from all
+    </Limit>
+    <LimitExcept GET POST OPTIONS>
+        Order deny,allow
+        Deny from all
+    </LimitExcept>

 # DirectoryIndex: sets the file that Apache will serve if a directory

# Restart service and autostart after reboot
service httpd restart
chkconfig httpd on

# Create public_html and set permissions
mkdir -p /home/haxor/public_html
chmod 0711 /home/haxor
chmod 0755 /home/haxor/public_html

# That's the fairy standard Linux way to set it up.
# The way which does NOT work on SELinux infected systems.

# This is the part that most documents have 
setsebool -P httpd_enable_homedirs true

# Except you need this as well which most forget to do
setsebool -P httpd_read_user_content true

# But there's still plenty of more to do
chcon -R -t httpd_sys_content_t /home/haxor/public_html

# No, we're not done yet
chcon -t httpd_sys_content_t /home/haxor

# Think that's it? Still one more that's missing from docs
chcon -t httpd_sys_content_t /home

# Done. Now it's working.

# Feel free to tell how it doesn't work for you so I can
# reply how I could care less. :)