How Can I Have A Conditional .htaccess Block? - apache

This is an Apache question you've probably come across before. I want to have one source package that I can deploy to my workstation, my staging server, and my production server, but for it to load different .htaccess settings based on what the URL was.
Note that I was using a kludge with an IfModule call, but that won't work with our new production server because it shares all the same modules as my staging server.
Note I need to bundle SetEnv with these rewrites. Currently if you use RewriteCond, it only ties to the following RewriteRule, but not the SetEnv underneath.

Instead of using SetEnv, use the environment variable setting capabilities of RewriteRule itself:
RewriteCond %{HTTP_HOST} =foo.com
RewriteRule ^ - [E=VARNAME:foo]
RewriteCond %{HTTP_HOST} =bar.com
RewriteRule ^ - [E=VARNAME:bar]
Although I prefer doing this sort of thing by passing flags to the httpd process at startup and looking for them using IfDefine blocks.
<IfDefine FOO>
SetEnv VARNAME foo
</IfDefine>
<IfDefine BAR>
SetEnv VARNAME bar
</IfDefine>

On Ubuntu Linux, the IfDefine's variable is set in
/etc/apache2/envvars
and is called APACHE_ARGUMENTS. So, at the bottom of that file I had to add:
export APACHE_ARGUMENTS="-D dev"
...and then bounce the server with:
/etc/init.d/apache2 stop
/etc/init.d/apache2 start
On other systems:
However, there's a Debian article on this topic that discusses this here. In that example, the file to edit is /etc/default/apache2 and the variable is called APACHE_DEFINES.
Likewise, on some systems it is a variable named OPTIONS that is set in /etc/sysconfig/httpd.
So, what you really need to do is look for the start section in your apache2ctl file. So, begin by doing a whereis apache2ctl to find where that script is, cat it out and find the start section with the apache2 directive in it, and see if the variable it passes is OPTIONS, APACHE_ARGUMENTS, APACHE_DEFINES, or something else. Then, see which file you need to edit by experimentation with either /etc/sysconfig/httpd, /etc/default/apache2, or /etc/apache2/envvars.

I tried the IfDefine method and it didn't work, even though the defined variable i'd passed into the Apache startup was definitely showing up in phpinfo() on the APACHE_ARGUMENTS line.
I tried another method and it worked perfectly. In your .htaccess file you need something like:
# Is the domain local (i wanted to check two names)?
<If "%{SERVER_NAME} != 'localhost' && %{SERVER_NAME} != 'myproject.localhost'">
# I wanted to password protect the production server only
AuthType Basic
AuthName "Restricted area"
AuthUserFile /app/.htpasswd
require valid-user
</If>
I'm using Apache 2.4. Might not work for earlier versions.

Here is a simple example that should be enough for you to change it to meet your requirements:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^localhost
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule (.*) http://www.%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

Related

htaccess Map One Directory To Another One Level Up

So here’s what I’m trying to accomplish. I have this link:
https://www.mydomain.com/foo/bar/
Now, the directory "foo" actually has a site in it that is up and operational. For the sake of organization I have had to create another site like this:
https://www.mydomain.com/fubar/
So in reality the link https://www.mydomain.com/foo/bar/ isn’t really a directory with anything it. What I would rather like to happen is when people go to https://www.mydomain.com/foo/bar/ that this address doesn’t change in the address bar, but rather on the backend the software actually brings up and uses https://www.mydomain.com/fubar/.
EXAMPLE:
When someone goes to https://www.mydomain.com/foo/bar/sign_up.php they still see this in their address bar, but what they're actually getting is https://www.mydomain.com/fubar/sign_up.php.
What I've tried so far to no avail:
htaccess at https://www.mydomain.com/foo/
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteRule ^bar/(.*) ../fubar/$1 [NC,L]
Also
RewriteCond %{PATH_INFO} ^bar/(.*)$ RewriteRule ^.*$ ../fubar/%1 [L]
htaccess at https://www.mydomain.com/
RewriteRule ^foo/bar/(.*) /fubar/$1 [L]
UPDATE: The directory https://www.mydomain.com/foo/ is actually the root directory for https://www.anotherdomain.com/. So https://www.anotherdomain.com/bar should be bringing up https://www.mydomain.com/fubar/
You can’t do things like have ../ parent directory references like that for rewrite rules:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteRule ^bar/(.*) ../fubar/$1 [NC,L]
What you need to do is set something like this in the .htaccess of your site’s root on https://www.mydomain.com/:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteRule ^foo/bar/?(.*)$ fubar/$1 [QSA,NC,L]
The last line basically grabs any URL that has foo/bar in it’s path, the /? makes the trailing slash optional, and the (.*)$ captures the values passed as parameters.
Now, not 100% sure on my addition of QSA (Query String Append) to the rewrite rule flags, but the idea is the query string values get fully passed to the destination when you use. Which I assume you would need, but if you don’t just use this instead:
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
RewriteRule ^foo/bar/?(.*)$ fubar/$1 [NC,L]
Also, there is a nice way to debug rules like this without reloading the browser all of the time which can be a headache & cause issues when content is cached. And that is to temporarilly add the R (Rewrite) flag & use curl -I to view response headers directly while debugging.
For example, on my local MAMP (Mac OS X LAMP) setup I see this when I run curl -I to http://localhost:8888/foo/bar/ with the R flag set:
curl -I http://localhost:8888/foo/bar/
HTTP/1.1 302 Found
Date: Mon, 23 Jun 2014 14:11:11 GMT
Server: Apache/2.2.23 (Unix) mod_ssl/2.2.23 OpenSSL/0.9.8y DAV/2 PHP/5.4.10
Location: http://localhost:8888/fubar/
Content-Type: text/html; charset=iso-8859-1
As you can see the Location changes to Location: http://localhost:8888/fubar/ when using the R flag. Which is what you want. Then when you are done tweaking your rules, just remove the R flag & you should be good to go.
EDIT: Since the original poster states this desired behavior in their update to the question, a rewrite rule will never work:
The directory https://www.mydomain.com/foo/ is actually the root
directory for https://www.anotherdomain.com/. So
https://www.anotherdomain.com/bar should be bringing up
https://www.mydomain.com/fubar/.
For a case like this, mod_rewrite is the wrong tool for the job. Use mod_proxy instead. First enable it in Apache like this; example assumes you are on Ubuntu 12.04 but should work on most any Linux Apache install
sudo a2enmod proxy proxy_http
Then set this to enable a reverse proxy on https://www.anotherdomain.com from your path of /bar/ to https://www.mydomain.com/fubar/:
<IfModule mod_proxy.c>
# Proxy specific settings
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
AddDefaultCharset off
Order deny,allow
Allow from all
</Proxy>
ProxyPass /bar/ https://www.mydomain.com/fubar/
ProxyPassReverse /bar/ https://www.mydomain.com/fubar/
</IfModule>

Can htaccess read a server environment variable set in Apache?

When you set a server environment variable in your Apache settings, it's possible to read that variable from PHP using built in functions.
But can you read the variable from an htaccess file?
What I'm trying to accomplish in my htaccess is something along the lines of:
<If var=="stuff">
do things here
</if>
<if var=="different stuff">
do different things here
</if>
Yes it is.
You will probably want to use mod_setenvif functionality, so that module will need to be turned on.
Then you simply do something like:
SetEnvIf Request_URI "\.gif$" image_type=gif
Which would set the environmental variable image_type with a value of gif if the requested file name ends with .gif.
You could then access this (like in RewriteCond) like this:
RewriteCond %{ENV:image_type} gif
RewriteRule ^(.*) $.gif
You can read the full documentation here: http://httpd.apache.org/docs/2.2/env.html
As I had a lot of problems setting up a similar thing to recognise my home localhost as distinct to my work set up, here's what I ended up doing.
First and foremost, The <IF ..> directive does not recognise SetEnv. From http://httpd.apache.org/docs/current/env.html : "The SetEnv directive runs late during request processing meaning that directives such as SetEnvIf and RewriteCond will not see the variables set with it."
So, try to use SetEnvIf if you can. I was lazy and just put this in my httpd.conf file. It checks that it's running on localhost - which is obviously is - then sets the variable:
SetEnvIf Server_Addr ^127\.0\.0\.1$ home_variable
Then, elsewhere, in my htaccess file I had this:
# IfVersion needs mod_version - you could do an ifmodule before all this i guess
# we use ifversion because If was introduced in apache 2.4
<IfVersion >= 2.4>
# check if the home variable exists/isn't: empty, "0", "off", "false", or "no"
<If "-T reqenv('home_variable')">
... do home-y stuff
</If>
<Else>
... do work-y stuff
</Else>
</IfVersion>
# fallback
<IfVersion < 2.4>
.. fallback?
</IfVersion>
Alternatively, you could just have one variable for each environment and give it a specific value:
SetEnvIf Server_Addr ^127\.0\.0\.1$ check_location=home
Then the rest would be the same, except that first<If ..> statement:
<If "%{ENV:check_location} == 'home'">....</If>
I've tested both of those between a home environment with 2.4 and a work environment with 2.2, both of which had mod_version enabled (hence not bothering with the ifmod).
(I also haven't tested for more than two environments but Apache 2.4 does give an <ElseIf> so that's also an option).
Doop di do.
(More about the -T operator et al: http://httpd.apache.org/docs/current/expr.html)
Apache 2.4 introduced <If>, <Else>,<ElseIf> blocks in conjunction with a new expression syntax for more powerful programmatic control in .htaccess files, etc.
This is untested but ostensibly works:
<If "%{MY_VAR} == 'my result'">
…
</If>
Source: https://blogs.apache.org/httpd/entry/new_in_httpd_2_4
I gave description and .htaccess and PHP examples here: Set an environment variable in .htaccess and retrieve it in PHP
For just some examples in .htaccess, taken from my modifying the Perishable Press 5G Blacklist/Firewall http://perishablepress.com/5g-blacklist-2013/ to use environment variable reporting:
SetEnv myServerName %{SERVER_NAME}
RewriteCond %{QUERY_STRING} (base64_encode|localhost|mosconfig|open_basedir) [NC,OR]
RewriteCond %{QUERY_STRING} (boot\.ini|echo.*kae|etc/passwd) [NC,OR]
RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC]
RewriteRule .* - [E=badQueryString:%0--%1--%2,F,L]
SetEnvIfNoCase User-Agent ^$ noUserAgent
SetEnvIfNoCase User-Agent (binlar|casper|cmsworldmap|comodo|diavol|dotbot|feedfinder|flicky|ia_archiver|jakarta|kmccrew|nutch|planetwork|purebot|pycurl|skygrid|sucker|turnit|vikspider|zmeu) badUserAgent=$1
<limit GET POST PUT>
Order Allow,Deny
Allow from all
Deny from env=badUserAgent
</limit>
Notice the use of paramters. %0 gives the full string, %1 gives the match from the 1st parenthesized statement, %2 the 2nd. The hyphens are literal display characters, to visually separate (don't think is any way to put spaces in there).

Disable Track and Trace in apache

I have Apache 2.2.22 in suse Linux. I want to disable track & trace in Apache and use 1- TraceEnable Off and 2- RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F] .
but of 2 way don't work.
In Apache2 you can just add TraceEnable Off in httpd.conf (end of file)
TraceEnable Off
To check if Trace is On/Off you can use Curl:
curl -v -X TRACE http://www.yourserver.com
You need to put TraceEnable Off in httpd.conf
To disable these methods, add the following lines for each virtual
host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]
nessus said)))
For Apache HTTPD 2.4:
Require not method TRACE TRACK
see Require Directive
Unless a module is installed which supports TRACK, then TRACK is not supported by default by Apache, hence the only need to have the directive:
TraceEnable Off
However, for a belt-and-suspenders approach, also add:
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) [NC]
RewriteRule ^.* - [F]
This will disable both TRACE and TRACK.
View Demo Trace Using SSH Command
TRACE is enabled by default in an apache installation. There are two ways to remediate. The first can be used if you are running Apache 1.3.34, 2.0.55, or anything in the 2.2 release. Simply add the TraceEnable directive into your httpd.conf and set the value to Off.
TraceEnable Off
add this line in httpd.conf
The first thing to do is make sure that mod_rewrite is loaded. If mod_rewrite.so is missing from your apache configuration but you have it installed, (and your install location is /usr/local/apache), then add the following statement to your httpd.conf:
LoadModule rewrite_module "/usr/local/apache/modules/mod_rewrite.so"
Then add the following as well to your httpd.conf file:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
RewriteRule .* - [F]
Test With Curl Command
curl -v -X TRACE http://localhost
I know there's already a few answers here, but I thought I'd chime in and add some additional options.
Slipstream's approach is certainly the simplest approach here, so if you're seeking a quick and easy fix, there's your pot of gold.
TraceEnable directive
As mentioned by a few people here, in Apache2, you can append the TraceEnable directive to the end your httpd.conf or apache2.conf file:
TraceEnable Off
Rewrite Module
You can also add a rewrite configuration to your VirtualHost to explicitly block TRACK and TRACE requests:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCondition %{REQUEST_METHOD} ^(TRACE|TRACE)
RewriteRule . * - [F]
</IfModule>
With this configuration, Apache catches all TRACK and TRACE requests, and replies with a 403 Forbidden error. None of the original request's content is echoed back.
Rewrite Module (More Restrictive)
But, what I haven't seen anyone else suggest is explicitly passing the methods you want to allow. This is a slighly tighter fix, and is required for PCI compliance:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)
RewriteRule .* - [F]
</IfModule>
This will reject any request which is using a method not specified in the directive. Again, the original request content is not echoed back, and the server responds with a 403 Forbidden error.
Something to keep in mind is that for production systems is that RewriteEngine can be processor intensive. This is generally not much of an issue because the increase would be milliseconds (if not microseconds), but something to be mindful of if you have loads of rewrites.
Note: For the above rewrite configurations, you'll need to uncomment the LoadModule or AddModule (depending on your setup) directives in your Apache config for rewrite_module.
You can also use the mod_allowmethods found in apache 2.3+
<Location "/">
AllowMethods GET POST OPTIONS
</Location>
https://httpd.apache.org/docs/2.4/mod/mod_allowmethods.html

Apache 2.2 redirect to SSL *then* do auth (with solution < but is it crap?)

Seems to be the place for apache so here goes :)
Age old problem: how so I redirect HTTP->HTTPS, then and only if HTTPS, do an auth?
Oh - and I'd like most of it in a single snippet that can be Include-ed in multiple <directory> or <location> blocks, so no virtual host level random path based rewrites...
Well, here's what I have that does seem to work:
In the top of a VirtualHost block
# Set ssl_off environment variable
RewriteEngine on
RewriteCond %{HTTPS} =on
RewriteRule ^ - [E=ssl]
In the location or directory block
RewriteEngine on
# Case 1 redirect port 80 SSL
RewriteCond %{HTTPS} !=on
RewriteCond %{SERVER_PORT} =80
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [R=301]
AuthType Basic
AuthBasicProvider external
AuthExternal auth_pam
AuthName "My Underpants"
AuthzUnixgroup on
Order Deny,Allow
Deny from all
Allow from env=!ssl
Satisfy any
Require group nice-users
Pluses
All of that bar the Require's can be abstracted out to a snippet file to Include in one line on each location
It fixes forcing SSL and authentication together for each location, so less chance of mistakes
Minuses
Bloody hell, it is hardly intuitive! Might be fragile for all I know...
Is there a better way (not that I've found...)?
Comments would be very welcome on whether that has any serious flaws :)
Aside
Life would be so much easier if Apache had a sensible config syntax with a generic
<If expression> </If>
block that could be used anywhere. It has certain special case blocks such as IfModule, and then you have special case conditionals like RewriteCond (which is very hard to grok if you're not used to it).
Cheers,
Tim
If you're wanting to force the entire site to https, you can use the VirtualHost directives, and then it's quite simple:
<VirtualHost *:80>
ServerName example.com
RedirectMatch (.*) https://example.com$1
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
...
...
...
</VirtualHost>
Tim Watts' solution seems to work best for me but needed a bit of tweaking. Also my situation is slightly different in that I wish to allow certain IP addresses without HTTP auth but this just adds an extra line.
mod_rewrite won't inherit config from the VirtualHost by default.
See: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewriteoptions
I was going to make use of "RewriteOptions inherit" but it seems that this applies the parent rules AFTER the child ones. In any case, I thought of a different solution.
Within my SSL <VirtualHost> I have the line:
SetEnvIf Request_URI "/" using_ssl=yes
This sets the using_ssl environment variable if the request URI contains a forward slash (i.e. all the time.) It's a bit of hack as I'd prefer to use the unconditional SetEnv but apparently:
The internal environment variables set by this directive are set after most early request processing directives are run, such as access control and URI-to-filename mapping. If the environment variable you're setting is meant as input into this early phase of processing such as the RewriteRule directive, you should instead set the environment variable with SetEnvIf.
(source: http://httpd.apache.org/docs/2.2/mod/mod_env.html#setenv)
My config within my container looks like this:
# Require a basic HTTP auth user
AuthName "realm-name-goes-here"
AuthType Basic
AuthUserFile /var/www/etc/htpasswd
Require valid-user
# OR allow from non-SSL (which will be redirected due to mod_rewrite below!)
Order Allow,Deny
Allow from env=!using_ssl
# OR allow from a trusted IP range
# NB: This allows certain IPs without a username & password
Allow from 192.168.0.0/16
Satisfy Any
# Force a redirect to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=permanent]
You probably want to try with just 'R' instead of 'R=permanent' first for testing purposes.
Hope this is useful for others :)
I've tested your solution and it didn't work ...
After a loooong time searching the solution, googling too much and found always the same things which didn't work, I finally did this : I use SSLRequireSSL and an ErrorDocument 403 configured with a static page containing a JavaScript code (thanks to this blog page).
in /etc/apache2/conf.d.opt/redirect_if_not_https.conf :
SSLRequireSSL
ErrorDocument 403 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\
<html><head>\
<title>403 Forbidden</title>\
<script language=\"JavaScript\">\
window.location='https://'+window.location.hostname+window.location.pathname;\
</script>\
</head><body>\
<h1>Forbidden</h1>\
<p>You don't have permission to access that resource using simple HTTP. Please use HTTPS instead.</p>\
</body></html>"
(note that I created /etc/apache2/conf.d.opt/)
And in an app conf, include that file (for example in /etc/apache2/conf.d/trac.conf) :
<LocationMatch "/trac">
# All the classical configurations here
# ...
Include conf.d.opt/redirect_if_not_https.conf
</LocationMatch>

How can I implement a global RewriteCond / RewriteRule in Apache that applies to all virtual hosts?

The title pretty much says it all. :-) I have lots of virtual hosts and I want to put a single rewriting block at the top of the httpd.conf file that rewrites URLs no matter which virtual host the request might be directed to. How the heck do I do this?
I found this but my question is the same: how can I do this without resorting to .htaccess files and performing some other action for each virtual host?
OMGTIA!
Specify RewriteOptions InheritDown in the parent scope (such as httpd.conf) to get your rules applied in child Virtual Hosts without modifing them.
This will only work on Virtual Hosts where the RewriteEngine directive is set to on:
Note that rewrite configurations are not inherited by virtual hosts. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use rewrite rules.
(source)
Apache supports this since 2.4.8 (not available at the time of the original question).
From documentation for RewriteOptions:
InheritDown
If this option is enabled, all child configurations will inherit the configuration of the current configuration. It is equivalent to specifying RewriteOptions Inherit in all child configurations. See the Inherit option for more details on how the parent-child relationships are handled.
Available in Apache HTTP Server 2.4.8 and later.
InheritDownBefore
Like InheritDown above, but the rules from the current scope are applied before rules specified in any child's scope.
Available in Apache HTTP Server 2.4.8 and later.
IgnoreInherit
This option forces the current and child configurations to ignore all rules that would be inherited from a parent specifying InheritDown or InheritDownBefore.
Available in Apache HTTP Server 2.4.8 and later.
(http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteoptions)
By default, mod_rewrite configuration settings from the main server context are not inherited by virtual hosts. To make the main server settings apply to virtual hosts, you must place the following directives in each <VirtualHost> section:
RewriteEngine On
RewriteOptions Inherit
click http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html to find more information
Looks like the simplest possible solution is to add
RewriteOptions inherit
to each VirtualHost directive. This is at least a lot simpler than messing with .htaccess files. Apache is pretty clear on the fact that
by default, rewrite configurations are
not inherited. This means that you
need to have a RewriteEngine on
directive for each virtual host in
which you wish to use it.
(http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html)
and apparently the way to change the default is via RewriteOptions in the child (vhost or director), so you have to do something in each child.
I've never tested it, so it might not work, but I would try adding an include directive in all of the virtual host blocks to a single file. You would have to change each virtual host configuration block once, but after that, you should have a central place from which to make changes. YMMV.
If you're only trying to rewrite something in the domain part of the name, e.g. to fix a common misspelling, you don't even need the 'inherit' option. I setup a no-name virtual host to catch all invalid host names and respell them correctly before redirecting them.
Since this uses redirects, the appropriate virtual host will be found after the rewrites have been applied.
Options +Indexes +FollowSymLinks
RewriteEngine on
# If it begins with only domain.com, prepend www and send to www.domain.com
RewriteCond %{HTTP_HOST} ^domain [NC]
RewriteRule ^(.*) http://www.domain.com$1 [L,R=301]
# Correct misspelling in the domain name, applies to any VirtualHost in the domain
# Requires a subdomain, i.e. (serviceXXX.)domain.com, or the prepended www. from above
RewriteCond %{HTTP_HOST} ^([^.]+\.)dommmmmain\.com\.?(:[0-9]*)?$ [NC]
RewriteRule ^(.*) %{HTTP_HOST}$1 [C]
RewriteRule ^([^.]+\.)?domain.com(.*) http://$1domain.com$2 [L,R=301]
# No-name virtual host to catch all invalid hostnames and mod_rewrite and redirect them
<VirtualHost *>
RewriteEngine on
RewriteOptions inherit
</VirtualHost>
You may want to use InheritDownBefore to avoid having to add more junk to your vhosts.
An example of a global letsencrypt alias:
# letsencrypt
<IfModule alias_module>
Alias /.well-known/ /var/www/html/.well-known/
</IfModule>
<IfModule mod_rewrite.c>
# prevent vhost rewrites from killing the alias
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} ^/\.well\-known
RewriteRule . - [L,PT]
</IfModule>
Then you can do this in each of your vhosts, with no other directives:
<VirtualHost *:80>
....
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^/.* /index.php [L,PT]
</IfModule>
</VirtualHost>
Thanks to everyone to answered above. It helped me find my answer.
Question has been answered already, I just wanted to add an example in case you are using Google Compute Engine. It says it requires Apache HTTP Server 2.4.8 BUT it works with Apache/2.4.25 (Debian). Even when I try to upgrade, I cannot go past Apache/2.4.25. It says this version is the latest version.
Here's an example of how to implement.
RewriteOptions InheritDown
RewriteCond %{HTTP_HOST} ^www\. [NC,OR]
RewriteCond %{HTTP_HOST} !\.co$ [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)\.[^.]+$ [NC]
RewriteRule ^ https://%1.co%{REQUEST_URI} [L,NE,R=301]
<VirtualHost *:80>
RewriteEngine On
ServerAlias *.*
</VirtualHost>
ALSO OF NOTE (For Testing):
When you are testing your rewrite engine. It is really easy to get confused about if it is working or not because of cache and cookies. If you got it to work once on a browser, it will continue to work even if you delete the rewrite code. Testing rewrite is really annoying sometimes. You might think it works but then it stops or starts.
Best way to test rewrite code is to open an incognito tab in your browser, clear or cookies and cache. Open developer mode just in case. DO NOT JUST REFRESH. You need to click into the URL and refresh. Or open new tab. Or copy/paste URL into new window. If you use same window with refresh, it might be just redoing results from the past instead of renewing the new code.
I've always used a "catch-all" VHost for directives I wanted across the board, like......
Listen 80
NameVirtualHost *:80
<VirtualHost *:80>
ErrorLog "/var/log/apache2/error_log"
</VirtualHost>
<VirtualHost *:80>
ServerName alloftherestoftheVHosts.com
DocumentRoot "/ServiceData/.........
............
And it's always seemed to work... error logs were getting combined properly, etc...... but it IS possible that this was the result of an earlier / conflicting / like-minded directive.
Personal note.. Whoever dreamed up the Apache configuration schema and syntax was a dingbat, or a group of dingbats, who spent too much time in their cave.... The whole thing should be exorcised and XMLized, or something! Although they are both wildly different... the Hello-Kitty setup process of Cherokee.. to the viciously succinct NGinx config.... are both so much more logical..