CentOS 7: public_html with httpd userdir module

This article will describe installing httpd and userdir module, and running web server for each user.


1 Install httpd

Install httpd with yum.

$ sudo yum install -y httpd
$ sudo systemctl enable httpd
$ sudo systemctl restart httpd

2 firewall-cmd

Open port with service file which names http.

$ sudo firewall-cmd --add-service=http --permanent
$ sudo firewall-cmd --reload

3 SELinux

Allow read access under public_html files like public_html/index.html.

$ sudo setsebool -P httpd_read_user_content on

4 userdir.conf

Enable UserDir directive.

$ diff -uprN /etc/httpd/conf.d/userdir.conf{.org,}
--- /etc/httpd/conf.d/userdir.conf.org  2016-06-03 08:55:49.392462419 +0900
+++ /etc/httpd/conf.d/userdir.conf      2016-06-03 08:56:05.820317791 +0900
@@ -14,14 +14,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


5 Home directory permission 701/710

If you do not change permission from 700 to 701, 403 Forbidden error will be occurred.

This is because httpd does not have exec permission and cannot open public_html.

$ chmod 701 ~

But permission 701 gives exec permission to all local users, local user can access files and directories under home directory.

[foobar@centos-7 ~]$ ls /home/hiroom2/
ls: cannot open directory /home/hiroom2/: Permission denied
[foobar@centos-7 ~]$ ls /home/hiroom2/Downloads

So this article will change group of home directory to apache and use 710 permission.

$ sudo chown hiroom2:apache ~
$ chmod 710 ~

If you hide directories and files under home directory, you need create 700 permission directory and put all into there.

6 public_html

Create public_html with 755 permission.

$ mkdir ~/public_html
$ chmod 755 ~/public_html

Now accessing to below URL returns below HTML. If you need to provide file downloader, you only put your file to public_html directory.



A index.html or index.cgi will be loaded by DirectoryIndex when accessing to URL.


7 Digest authentication

Create public_html/.htaccess as below. "hiroom2" is a realm for digest authentication.

AuthType Digest
AuthName "hiroom2"
AuthUserFile /home/hiroom2/.htdigest
require valid-user

Add user to accessing to realm "hiroom2" with htdigest.

$ htdigest -c ~/.htdigest "hiroom2" hiroom2
Adding password for hiroom2 in realm hiroom2.
New password:
Re-type new password:

Username and password is required when accessing to URL.



A userdir module does not allow ExecCGI by default.

It may be better to use container like LXC for ExecCGI.


Add ExecCGI to Options in userdir.conf.

$ diff -uprN /etc/httpd/conf.d/userdir.conf{.org,}
--- /etc/httpd/conf.d/userdir.conf.org  2016-06-03 11:07:41.421962082 +0900
+++ /etc/httpd/conf.d/userdir.conf      2016-06-03 12:19:32.778261136 +0900
@@ -30,7 +30,7 @@
 <Directory "/home/*/public_html">
     AllowOverride FileInfo AuthConfig Limit Indexes
-    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+    Options ExecCGI MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
     Require method GET POST OPTIONS

Create public_html/.htaccess as below.

AddHandler cgi-script .cgi

This article created public_html/index.cgi as below. Change permission to 755 and append httpd_sys_script_exec_t SELinux label.

$ cat <<EOF > ~/public_html/index.cgi

echo "Content-type: text/html"
echo ""
echo "hello"
$ chmod 755 ~/public_html/index.cgi
$ chcon -t httpd_sys_script_exec_t ~/public_html/index.cgi

Accessing to URL returned HTML generated by index.cgi.