Apache 2.4 – Subdirectories Configuration Guide

apache-2.4subdomain

I am currently setting up a website on Ubuntu 18.04 with Apache2.4.

What I am trying to do is restrict HTTP(S) access to my subdomains to certain IPs.
Those subdomains are either used for development tests or are admin tools (phpMyAdmin, etc.), so I definitely don't want those subdomains to be public.
I also want domain.com to be public.

What is the current state of the website:

  • domain.com is publicly accessible
  • domain.com is showing /var/www/html/ content
  • sub1.domain.com is publicly accessible
  • sub1.domain.com is showing /var/www/html/sub1 content
  • sub2.domain.com is publicly accessible
  • sub2.domain.com is showing /var/www/html/sub2 content

What is the expected result:

  • domain.com is publicly accessible
  • sub1.domain.com is restricted to several IPs
  • sub2.domain.com is restricted to several IPs

This is my configuration so far:

DNS entries:

Name   Type   TTL  Target
        A     300  ServerIP
sub1   CNAME  300  domain.com
sub2   CNAME  300  domain.com
www    CNAME  300  domain.com

apache2.conf:

[...]
<Directory /var/www/html>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

<Directory /var/www/html/sub1>
    AllowOverride All
    Require all denied
</Directory>
[...]

/etc/apache2/sites-enabled/000-default.conf

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ServerName domain.com
    ServerAlias domain.com

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

/etc/apache2/sites-available/sub1.domain.com.conf

<VirtualHost *:80>
    ServerName sub1.domain.com
    DocumentRoot /var/www/html/sub1
    <Directory /var/www/html/sub1>
        Options -Indexes +FollowSymLinks +MultiViews
        AllowOverride All
        Require all denied
    </Directory>

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =sub1.domain.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Symbolic links are made from /etc/apache2/sites-available/sub*.domain.com.conf to /etc/apache2/sites-enabled

Something I also don't understand is if I try to add a .htaccess file in /var/www/html/php56, it isn't taken into account, despite the AllowOverride All

Another thing I am trying to do, is to redirect domain.com/sub1 requests to sub1.domain.com instead of throwing a 403 error, but without a .htaccess file, so I minimize the number of config files.

Note: For testing purposes, I intentionally set Require all denied instead of Require ip x.x.x.x

What I am doing wrong?

If I forgot to provide any required info, please let me know.

Thanks for your help

UPDATE:

Thanks to Tom's advice, I figured out what was wrong.
In my /etc/apache2/sites-available/sub1.domain.com.conf I had a redirection from HTTP to HTTPS. Actually, Let's Encrypt created a /etc/apache2/sites-available/sub1.domain.com-le-ssl.conf file (during the certificate setup, I chose to force HTTPS redirection), and in that file there were Require all granted so, that file was overwriting my sub1.domain.com.conf file.

Finally, I changed my directories setup according to Tom's answer – much clearer that way, thanks!
It also solved my redirection question, as now my root folder for domain.com is /var/www/domain.com/www

Best Answer

I would not make the root directory of the subdomain a subfolder of the root domain. Instead of:

/var/www/html/
    - sub1/
    - sub2/
    - sub3/

I would do it myself like this:

/var/www/domain.com/
    - www/ (the root)
    - sub1/
    - sub2/
    - sub3/

This makes it a lot easier to limit access to files. In your current setup, perhaps access is limited by a VirtualHost but the same data can be accessed by going via the root domain: http://www.example.com/sub1/data.

Related Topic