Apache configuration / Catch-all subdomain / Specific subdomain exception - apache

Startting with some simple domain setup :
<VirtualHost *:80>
ServerName site.com
ServerAlias *.site.com
DocumentRoot /path/to/site.com
<Directory /path/to/site.com>
AllowOverride all
Options -MultiViews
</Directory>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$ [NC]
RewriteRule . %1/%2 [R=301,L]
RewriteCond %{HTTP_HOST} ^(.*).site.com$ [NC]
RewriteRule ^(.*)$ http://site.com$1 [R=301]
RailsEnv production
</VirtualHost>
So I'm pretty happy, anything put before my domain will be removed and my urls will always be clean : http://site.com
Cool!
** BUT **
I'd like to set a specific subdomain (an exception in that case) which would point to another site on the same server (another folder, another slightly different apache config, etc…)
This setup above will always precedes the one I would do for my 'exception' dubdomain.
How could I reach the goal described ? Catch-all apache setup with one (or some more) subdomain setup exceptions ?

Try to add you configuration for desired subdomain above this code, it should help.

Related

Stop virtualhost rewrite rules executing if a rule was matched in the global config

I have the following setup.
Apache running with a separate VirtualHost file for each site.
Each of these has their own set of rewrite rules, for http to https for example which is all running fine.
What we would like to happen is this, from the global config we need to be able to check if a request is for a particular subdirectory. If it is then we should allow this request to process as it should but at that point we do not want the individual virtual host file rewrite rules to kick in. Therefore allowing this directory to be served on non https connections and not be redirected to https.
I have set up the rewrite rules and can match on the directories and redirect to an external url if it matches from the global which shows its inheriting but if I try to just allow it through the virtual hosts rewrites kick in and it redirects.
I have tried using L and END but this did not work either.
Is there any way of achieving this without editing the virtual host files that are already configured?
Main httpd config entry
<Directory "/www">
Options Indexes Includes FollowSymLinks MultiViews
AllowOverride All
allow from all
Order allow,deny
Require all granted
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} ^/sub_directory/$ [NC]
RewriteRule ^(.*) $1 [L,END]
#RewriteRule ^(.*) - [L,END]
#RewriteRule ^(.*) http://www.google.com [L,END] # This does get triggered
</Directory>
sample virtual host file.
<VirtualHost *:80>
ServerName urlone.com
ServerAlias urltwo.com
DocumentRoot /www/
RewriteEngine On
# redirect to https
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*) https://urlone.com$1 [R=301,L]
</VirtualHost>
so if I visit urlone.com it should redirect to https://urlone.com but if I visit urlone.com/sub_directory it needs to not allow the redirect to https.
I hope this makes sense to someone and thanks in advance for any help.
In global httpd.conf:
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} ^/sub_directory$ [NC]
RewriteRule ^ - [E=PATH_MATCHED:true]
(if needed, you can add additional rules, or additional flags to the above rule)
In virtual_host.conf
RewriteCond %{ENV:PATH_MATCHED} !=true
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://urlone.com%{REQUEST_URI} [R=301,L]

Apache httpd.conf - Link multiple domains to corresponding subfolders

I need a rule to internally rewrite several domains, with and without www:
www.a.com --> /m/n/o/
b.c.org --> /x/y/z/
The setup is Apache running locally on Windows (XAMPP). I've got the hosts file set up so all the domains point to localhost. I'd like every page to get redirected, i.e. I want to point each domain to it's own different root directory and have it work normally from there. e.g.
/ <-- Top level folder, everything is under here.
/root/of/domain/A/ <-- www.a.com
/root/of/domain/C/ <-- b.c.org
You have two choices.
(1) The one you asked (with mod_rewrite)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?a\.com$ [NC]
RewriteRule ^/(.*)$ /root/of/domain/A/$1 [L]
RewriteCond %{HTTP_HOST} ^b\.c\.org$ [NC]
RewriteRule ^/(.*)$ /root/of/domain/C/$1 [L]
</IfModule>
Note: don't forget to replace example values by real ones. Also, make sure mod_rewrite is enabled.
(2) the cleanest way: configure virtualhosts directly (without mod_rewrite)
NameVirtualHost *:80
<VirtualHost *:80>
DocumentRoot "X:/path/to/root/of/domain/A/"
ServerName a.com
ServerAlias www.a.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "X:/path/to/root/of/domain/C/"
ServerName b.c.org
</VirtualHost>

VirtualHost mod_rewrite multiple domains same DocumentRoot

I have a VirtualHost with many ServerAlias domains defined. Using mod rewrite in the VirtualHost, I would like the following to occur:
sub.abc.com changes to sub.abc.com/?client_id=ABC
sub.def.com changes to sub.def.com/?client_id=DEF
sub2.abc.com changes to sub2.abc.com/?client_id=GHI
[... and so on ...]
My current configuration is:
<VirtualHost 1.2.3.4:8080>
ServerName sub.abc.com
ServerAlias sub.def.com sub2.abc.com
DocumentRoot /var/www/prod/
[... some other things ...]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^sub\.abc\.com
RewriteRule ^/([0-9]+)/?$ login.php?client_id=ABC [NC,L]
RewriteCond %{HTTP_HOST} ^sub\.def\.com
RewriteRule ^/([0-9]+)/?$ login.php?client_id=DEF [NC,L]
RewriteCond %{HTTP_HOST} ^sub2\.abc\.com
RewriteRule ^/([0-9]+)/?$ login.php?client_id=GHI [NC,L]
</IfModule>
</VirtualHost>
But this doesn't actually do the rewrite .. I am pretty sure my Cond or Rule is messed up (lol .. I guess that is pretty obvious). Any ideas?
Suggestion :
Let's say your domain name sub.abc.com is pointing to X ip address. Consider creating two additional records sub.def.com and sub2.abc.com under the same ip address X.
This practice is called as Shared Web Hosting
This way you can maintain separate configuration files for your three different domains.
So if a Client accesses sub2.abc.com - the configuration file for sub2.abc.com will come into picture and request will be served accordingly.
I hope this helps! Good Luck!

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.

Apache cookie-based transparent proxy / redirect

I have a number of sites running on the same machine, served by httpd. Each of the sites is set up as a VirtualHost on a different subdomain. Furthermore, for each subdomain, there are two VirtualHosts on different ports: one for the 'stable' version, one for the 'beta' version. The stable version is hosted on port 80.
Upon logging into the (stable version of the) sites, a cookie is set if the backend determines the user should be using the beta version.
I'd like Apache to detect this cookie on subsequent requests to the stable version and (without the user being aware) redirect the request to the beta version.
How can I achieve this?
I've tried using RewriteCond / RewriteRule in httpd.conf, but it doesn't seem to have any effect - perhaps Apache ignoring it in favour of the matching VirtualHost, or is sensitive to ordering (I think the VirthalHost definitions are being included first)? Perhaps I should be using mod_proxy, anyway?
Config
I've included (anonymised) snippets of my config below
httpd.conf
Listen 80
NameVirtualHost *:80
Listen 81
NameVirtualHost *:81
Include "/path/to/checkout/config/[stage]/apache2/*.conf" # VirtualHosts of sites
Include "/path/to/checkout/config/common/apache2/*.conf" # My attempted redirect
config/[stage]/apache2/[site]/apache2/[app-stable].conf
<VirtualHost *:80>
ServerName [app.hostname]
ServerAlias [alternative-app-name.hostname]
DocumentRoot "/var/www-application/release-base/current/app/public"
<Directory "/var/www-application/release-base/current/app/public/">
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
<!-- snip -->
</VirtualHost>
config/[stage]/apache2/[site]/apache2/[app-beta].conf
<VirtualHost *:81>
ServerName [app.hostname]
ServerAlias [alternative-app-name.hostname]
DocumentRoot "/var/www-application/beta-release-base/current/app/public"
<Directory "/var/www-application/beta-release-base/current/app/public/">
Options Indexes FollowSymLinks
AllowOverride All
</Directory>
<!-- snip -->
</VirtualHost>
config/common/apache2/common.conf
# !!! This has no effect !!!
RewriteEngine On
RewriteCond %{HTTP_COOKIE} cookiename
RewriteCond %{SERVER_PORT} !8081
RewriteRule ^ https://%{HTTP_HOST}:8081%{REQUEST_URI} [R,L] # (R for debugging)
App .htaccess (in case it's relevant)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
You have two problems:
The redirects in global scope are ignored; move them to vhost scope
The "%{HTTP_HOST}" var includes the port number, so you are redirecting to http://hostname:80:81/foo (hence your "hang")
In order to make this transparent, you need to use the [P] flag on the RewriteRule, and include a ProxyPassReverse directive. Your final directives (in each 'stable' conf file) should be as follows:
RewriteCond %{HTTP_COOKIE} absVersion
RewriteRule ^/(.*) http://hostname:81/$1 [P]
ProxyPassReverse / http://hostname:81/
Note that this requires mod_proxy (and any necessary submodules, e.g. mod_proxy_http) to be enabled.