Split DocumentRoot using Apache Alias per request path - apache

I'm trying to slowly take over an existing website, route per route. I found Apache's Alias(Match) which seems to allow me to set a different (content) document root per request. But I'm failing with trailing slashes and more complex paths.
My goal now is to have the old website serve everything as it is used to. And to have a new website, serving a first specific request, say /foo and /foo/*.
I have my vhost setup like this:
<VirtualHost *:80>
ServerName example.com
UseCanonicalName on
AliasMatch ^/foo/(.*)$ /www/new/$1
AliasMatch ^/foo$ /www/new/$1
<Directory /www/new/>
Options +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
DocumentRoot /www/old
<Directory /www/old/>
Options +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
In both directories I have an .htaccess with:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php/$1 [L]
The index.php's show 'old' or 'new' depending on their directory.
What happens to the different routes I test:
When requesting example.com/bar it shows 'old'.
When requesting example.com/foo it redirects too /foo/, and then shows 'new'.
When requesting example.com/foo/bar it shows 'old'.
I don't want the forced redirect of /foo to /foo/. And I want /foo/bar to show 'new'.
I've been following Apache's mod_alias to get the multiple AliasMatch directives to catch anything after /foo but apparently that's not working correctly. Also, I don't read anything there of the trailing slash being added magically.
Anyone knows the magic tricks?

I've been able to fix this by adjusting the Alias to point to the index.php directly:
AliasMatch ^/foo/(.*)$ /www/new/index.php
AliasMatch ^/foo$ /www/new/index.php
Then /bar and anything else goes to the old website, and /foo, /foo/ and /foo/bar goes to the new website.
There's two downsides to this method:
The .htaccess in the new website is skipped completely. But as I mainly use that for letting the index.php pick up every route, that's fine for now.
Frontend resources like css/js go to the old website. Fix that with another simple alias: example.com/frontend/app.css + Alias /frontend /www/new/public_html/frontend.

Related

VirtualHost config causing 301 redirect loop

I am trying to setup a virtual server to host multiple websites,
each site's content is in /var/www/html/site.com/public_html.
There have a VirtualHost config for each site under /etc/apache2/sites-available/site.com.conf as seen here:
/etc/apache2/sites-available/site1.com.conf:
<VirtualHost *:443>
DocumentRoot /var/www/html/site1.com/public_html
ServerName site1.com
<Directory /var/www/html/site1.com/public_html/>
AllowOverride None
</Directory>
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/html/site1.com/public_html
serverName site1.com
<Directory /var/www/html/site1.com/public_html/>
AllowOverride None
</Directory>
</VirtualHost>
All this config is needing to do is direct the incoming domain request to its root directory, nothing else. however the moment I apply apply this config file it will cause a 301 redirect loop.
As you can see I have disabled AllowOverride to avoid interference from .htaccess to eliminate that variable, by enabling AllowOverride to all it also results in a redirect loop with no change in behaviour. In case needed hear is the httpd.conf file that's not getting applied:
.htaccess:
# BEGIN WordPress
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
I have also tried completely removing the .htaccess file to eliminate that variable and it still resulted in a redirect loop.
Additionally if I where to manually change the URL to point to a file in the site like /index.php or /wp-admin/ it will result in a 302 redirect loop to that same file or folder.
index.php also does not refer back to itself but rather starts the wordpress program, and php.ini also does not have any redirect config.
I cannot find where the redirects may be happening, some guidance on potential faults in the current config of what other files may be causing redirects would be much appreciated.

mod_rewrite entire website to front page ONLY of new website

Now I've written dozens of redirects in my time, some with tricky regex, some more tame, but today, the very simplest redirect is stumping me on a CentOS server, running Apache 2.2.3.
All I'd like to do is redirect every single request on an old domain, regardless of path and query string, to the front page only of a new site. This is why, for example, a mod_alias Redirect directive isn't appropriate, since it appends the path to the new address.
In an Apache conf file, where the virtual server is defined, I now have
<VirtualHost THE.IP.ADDRESS:80>
DocumentRoot "/var/www/html/SITE_ROOT"
ServerName OLD_DOMAIN.com
<Directory "/var/www/html/SITE_ROOT">
Options FollowSymLinks
RewriteEngine On
RewriteRule ^$ https://NEW_DOMAIN [R=301,L]
AllowOverride None
</Directory>
</VirtualHost>
While the redirect to https://NEW_DOMAIN occurs as expected, the path of the original request is always appended, leading to 404 errors on the new site.
For example, visiting http://OLD_DOMAIN.com/asdf
redirects to https://NEW_DOMAIN.com/asdf
...when I'd actually want to arrive at https://NEW_DOMAIN.com/
Why is the path being appended, even though I'm not collecting a pattern match, and am not specifying such a match in the destination?
There are plenty of answers like this on SO already:
Apache redirect to a clean URL
https://stackoverflow.com/a/11590814/1738274
But I can't find a discrepancy comparing these solutions against my own configuration. Any ideas?
RewriteRule ^(.*)$ https://NEW_DOMAIN [R=301,NC,L] should work. I have tested with various URLs and it always redirects to https://NEW_DOMAIN
My config structure looks a bit different:
<VirtualHost *:80>
ServerName OLD_DOMAIN.com
DocumentRoot "C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs"
<IfModule mod_rewrite.c>
RewriteEngine on
Options FollowSymLinks
RewriteRule ^(.*)$ https://NEW_DOMAIN [R=301,NC,L]
.......
.......

Why is Apache Permanent Redirect removing the slash between the domain and the path?

I'm using Apache 2.4, and I set up two virtual directories. One requires SSL, and the other one redirects to it.
If a user attempts to visit https://www.derp.com/derp without /derp existing, they correctly get a 404. But when a user visits http://www.derp.com/derp, Apache incorrectly redirects the user to https://www.derp.comderp, removing the slash between the path and the domain name.
I have no idea what would be causing this.
The following is the setup of my Virtual Host.
<VirtualHost *:443>
ServerAdmin derp#derp.com
ServerName www.derp.com
ServerAlias derp.com
DocumentRoot "C:\Users\derp\Documents\Web Projects\derp"
SSLEngine on
SSLCertificateFile "C:\Apache24\certs\cert.cer"
SSLCertificateKeyFile "C:\Apache24\certs\key.key"
</VirtualHost>
<VirtualHost *:80>
ServerAdmin derp#derp.com
ServerName www.derp.com
ServerAlias derp.com
Redirect permanent / https://www.derp.com/
</VirtualHost>
<Directory "C:\Users\derp\Documents\Web Projects\derp">
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require all granted
SSLRequireSSL
</Directory>
Why would Apache be behaving this way?
Bonus Question: Should redirects be handled in my virtual host definition, or should it be handled in the .htaccess file in the web site's physical directory?
Edit:
I'm starting a Laravel project, and by default the public folder does contain a .htaccess file, so here's that guy:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Edit Two:
I tried:
adding a slash at the end of the DirectoryRoot path
replacing the backslashes with forward slashes in the DirectoryRoot path
replacing the backslashes with double backslashes in the DirectoryRoot path
I also removed the .htaccess file from the directory completely.
It redirects correctly when you go from http://www.derp.com to https://www.derp.com. It's just when you specify a path and attempt https that it removes the slash between the domain and the path.
Edit Three:
I also attempted the following suggestion:
Redirect permanent / https://www.derp.com/
Try
RedirectMatch permanent /(.*) https://www.derp.com/$1
or
RedirectMatch permanent (.*) https://www.derp.com/$1
... and instead of redirecting to https://www.derp.comderp, it instead does not redirect, attempts and gives a 404 for http://www.derp.com/derp, but using Apache's 404, instead of throwing a Not Found Exception, as Laravel does without configuration.
Edit Four:
I have also tried:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
In the .htaccess file and the behavior did not change at all.
I got it.
The issue did not lay with the rewriting at all, it was the SSLRequireSSL directive under my Directory definition that was causing the problem.
I simply removed this directive, refreshed the cache in all of my browsers, and the site then continued to work correctly. This was discovered through the process of elimination.
The documentation notes:
This directive forbids access unless HTTP over SSL (i.e. HTTPS) is enabled for the current connection. This is very handy inside the SSL-enabled virtual host or directories for defending against configuration errors that expose stuff that should be protected. When this directive is present all requests are denied which are not using SSL.
The emphasis is my own. SSLRequireSSL may have Apache only return a 403 or 404 if HTTP over SSL is not enabled, interfering with the Redirect rule. A rewrite rule such as the one in this answer on Server Fault may be a better alternative depending on your use case:
RewriteEngine On
RewriteCond %{SERVER_PORT} !443
RewriteRule ^(/(.*))?$ https://%{HTTP_HOST}/$1 [R=301,L]
My issue was related to browser caching.
I tried it in a different browser and it worked and then tried again in a private session in the first browser and it also worked.

Multiple Zend framework sites on one server

I'm having trouble setting up my httpd.conf or .htaccess files to recognize multiple zend framework sites on one server.
For development, I have just one server and I'm trying to setup the sites so I can access them like localhost/app1, localhost/app2, etc.
So right now, when I go to localhost/app1 it does successfully redirect to localhost/app1/public/index.php, however when I go to localhost/app1/index/index I get a 404.
Here is my vhosts file:
<VirtualHost *:80>
ServerAdmin webmaster#localhost
DocumentRoot "/var/www"
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory "/var/www/app1/public">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
ErrorLog logs/error.log
CustomLog logs/access.log common
</VirtualHost>
and here is my .htaccess file from the /var/www/app1 directory:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ /app1/public/index.php [NC,R,L]
If I change the DocumentRoot line in the vhosts file to DocumentRoot "/var/www/app1/public" then app1 does work correctly, but I can only access that one... at http://localhost. Is this possible? What I want to happen is if /var/www is the document root, then if I go to localhost/app1, those requests need to redirect to localhost/app1/public/index.php and if I go to localhost/app2 those requests need to redirect to localhost/app2/public/index.php.
I hope I explained this clearly, any help is appreciated.
In the end
I liked Phil's solution best because I didn't want to have to change my local hosts file and use the ServerName directive. It would be fine in a production environment if you own a separate domain name for each app, but not for development.
In addition to that, I was having a 403 forbidden problem when using an alternate directory for serving up web content. As I stated, the perms seemed correct the problem was with SE_Linux, and the security context of the files not being set to httpd_sys_content_t. I'm posting that solution that i found here, as it deals specifically with the issue. Thanks.
Here's what I'd do...
Install your applications somewhere arbitrary but outside the document root, eg /home/sudol/apps/app1 and /home/sudol/apps/app2. Make sure your Apache user can traverse this path and read the files.
Alias the public directories in your <VirtualHost> section
Alias /app1 /home/sudol/apps/app1/public
Alias /app2 /home/sudol/apps/app2/public
Setup your access and rewrite rules in the appropriate <Directory> sections (one for each app), eg
<Directory "/home/sudol/apps/app1/public">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
RewriteEngine On
RewriteBase /app1
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</Directory>
Delete the .htaccess files as you will no longer need them
Addendum
Make sure you set unique session names in your application config. You can also set specific cookie paths but this is optional, eg
; app1/application/configs/application.ini
resources.session.name = "app1"
resources.session.cookie_path = "/app1/"
; app2/application/configs/application.ini
resources.session.name = "app2"
resources.session.cookie_path = "/app2/"
Its better to use subdomain i.e app1.localhost then localhost/app1 . Since the way cookies are stored (including session cookie) can give you problem latter . They will mismatch or can even overlap .
Here is a good tutorial to setup the preferred way
http://www.dennisplucinik.com/blog/2007/08/16/setting-up-multiple-virtual-hosts-in-wamp/

Using mod_vhost_alias with CakePHP (which uses mod_rewrite)

I am not an apache guru. But I want to configure my server for mass virtual hosting using CakePHP. The idea is that we will be able to easily set up multiple versions of the same application based on directory location:
production.domain.com
testv1.domain.com
etc...
So I know I have mod_vhost_alias working just fine. I have a basic directory set up where I have added a test index.html file (/var/www/htdocs/cake/test/webroot). When I point my browser to the location (test.domain.com), the index.html is displayed in the browser. My vhost is configured to pull %1 from the URL to know what directory to point to:
VirtualDocumentRoot /var/www/htdocs/cake/%1/webroot
But when I point my browser to the cake application, I get a page not found error. I suspect it has something to do with the mod_rewrite in the .htaccess file. Here are the full configs for both:
mod_vhost_alias (in .conf file)
<VirtualHost *:80>
ServerAlias *
UseCanonicalName Off
VirtualDocumentRoot /var/www/htdocs/cake/%1/webroot
<Directory /var/www/htdocs/cake/%1/webroot>
AllowOverride All
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
.htaccess (in webroot - default as it comes from CakePHP)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
Any ideas how to get them to work together?
Turns out all it needed was:
DirectoryIndex index.html index.php