.htaccess in Multiple Environments - apache

I know similar questions have been asked before but I haven't found any really specific answers for my situation.
I have an ExpressionEngine site running on multiple environments (local, dev, production), and each of those environments needs different .htaccess rules:
All Environments
Remove index.php
Set a 404 file
Set 301 Redirects
Development
Password Protect with .htpasswd
Force HTTPS protocol
Prevent search engine indexing with X-Robots-Tag
Production
Force HTTPS protocol
Redirect non-www subdomains to www
Local
No unique rules.
I've seen a lot of examples of how you can set specific environments per-module. Like RewriteCond %{REQUEST_HOST} ^dev.myurl.com for the mod_rewrite module, and tricks like this for .htpasswd requirements.
But what I would really prefer is some way to set global environment variables, then re-use those variables in the .htaccess file per-environment. To use pseudo-javascript as an example, something like:
var local = 'mysite.local';
var development = 'dev.mysite.com';
var production = 'www.mysite.com';
// Global .htaccess rules
if(environment == local){
// Local environment .htaccess rules
}
if(environment == development){
// Development environment .htaccess rules
}
if(environment == production){
//Production envirotnment .htaccess rules
}
This way all of the environment-specific rules are all grouped together, making a really clean file, and only one variable needs to be changed if an environment is changed.
I've seen a few references to altering settings in Apache's config files, but obviously that's not a viable option if I'm dealing with 3rd-party hosts.
So is this pie-in-the-sky wishful thinking, or can it be done?

Jon's answer is a good one. Unfortunately, not all web hosts will allow you to control that -D parameter for starting Apache.
Here's a way to use a single htaccess file on dev and production, but only have the dev site password protected:
# ----------------------------------------------------------------------
# Password protect staging server
# Use one .htaccess file across multiple environments
# (e.g. local, dev, staging, production)
# but only password protect a specific environment.
# ----------------------------------------------------------------------
SetEnvIf Host staging.domain.com passreq
AuthType Basic
AuthName "Password Required"
AuthUserFile /full/path/to/.htpasswd
Require valid-user
Order allow,deny
Allow from all
Deny from env=passreq
Satisfy any

So is this pie-in-the-sky wishful thinking, or can it be done?
IMO, yes. You're never going to be able to get predictable "scoping" of rules based on ENV variables or anything like that. There doesn't exist arbitrary if(something) { do everything in here } in apache. Lots of directives won't work inside certain scopes, and in later on, when you need to change how something works, you're more likely to break what you have than simply amending it.
The best way is to not use htaccess files at all:
You should avoid using .htaccess files completely if you have access to httpd main server config file. Using .htaccess files slows down your Apache http server. Any directive that you can include in a .htaccess file is better set in a Directory block, as it will have the same effect with better performance.
Create a separate vhost for local, dev, and production. Turn them on or off as needed, whatever global config they share, store that elsewhere (like in a file called global.includes) and then use the Include directive in all 3 vhosts. If you need to apply rules to specific directories, use the <Directory> block instead of htaccess files.
If you'd rather stick everything inside htaccess files, you could try putting everything in <IfDefine> blocks, it's probably the closest thing you'll have to your pseudo-code in your question. Essentially something like:
# Global htaccess rules
RewriteEngine On
RewriteRule ^foo$ /bar [L]
# Only local
<IfDefine LocalInstance>
RewriteRule ^local/foo /bar [L]
</IfDefine>
# Only dev
<IfDefine DevInstance>
RewriteRule ^dev/foo /bar [L]
</IfDefine>
# Only production
<IfDefine ProductionInstance>
RewriteRule ^dev/foo /bar [L]
</IfDefine>
Then when you start apache, you'd need to pass in -DLocalInstance, -DDevInstance, or -DProductionInstance as command line paramaeters or using the Define directive (with only one argument) somewhere in your vhost config. This isn't guaranteed to work as smoothly as it looks like it should, I've ran into unexplained issues with <IfDefine> before, especially if you try to get too fancy.

Related

Apache .htaccess <FilesMatch> // Setting as forbidden subfolder files

I'm going mad over Apache .htaccess
I'm trying to setting as protected my subfolders using relative address, but it seems impossible.
The path of Apache folder is structured like this:
/var/www/apachedir
now I want to protect
/var/www/apachedir/subfolder/*
What I tryied is putting in /var/www/apachedir/ an .htaccess file like this
<FilesMatch "subfolder\/.*">
Order Allow,Deny
Deny from all
</FilesMatch>
but it seems not woking good.
I don't want to use ModRewrite and I want to make this .htaccess reusable.
So, listen, if I put the site over an other server that has a direcory structure like /var/www/zzz it has to protect files in /var/www/zzz/subfolder/*.
Also the file .htaccess has to stay in the root folder /var/www/apachedir.
There's a way to do it?
Edit:
I don't want to use ModRewrite but also I don't want to use Redirectmatch.
I want to know if there's a way to set it up with FilesMatch without ModRewrite or Redirectmatch.
I don't want to use ModRewrite.
You can use RedirectMatch to block access to a known path:
Redirectmatch 403 ^/subfolder/
I want to know if there's a way to set it up with FilesMatch
No, because the FilesMatch (and the non-regex Files) directive(s) literally match against files only, not directories. eg. <Files "*.jpg"> matches all .jpg files in any subdirectory.
There are various methods to block access to that subdirectory...
Use a <Directory> section in the server config
If you have access to the server (virtual host) config then you can use the <Directory> (and <DirectoryMatch>) directive(s) to target specific directories. But this is not permitted in .htaccess. For example:
<Directory "/var/www/apachedir/subfolder">
Require all denied
</Directory>
Create an additional .htaccess file in that subdirectory
The equivalent userland .htaccess way of doing this is to create an additional .htaccess file in that subdirectory (ie. at /subfolder/.htaccess) with a single Require all denied directive. The .htaccess file itself is equivalent to the <Directory> directive in the server config.
Aside: Order, Deny and Allow are Apache 2.2 directives and formerly deprecated on Apache 2.4 (which you are far more likely to be using). You should be using the equivalent Require (mod_authz_core) directives instead, as used above.
Use Redirect 403 (mod_alias) - not a "redirect"
I don't want to use ModRewrite but also I don't want to use Redirectmatch
RedirectMatch (and Redirect) are part of mod_alias - this is a base module and compiled into Apache by default (unlike mod_rewrite), so using the prefix-matching Redirect directive (no need for the regex variant RedirectMatch) is a reasonable solution as #anubhava suggests in his answer, depending on the scenario and existing directives. For example:
Redirect 403 /subfolder/
Despite the use of the Redirect directive, this is not an external (HTTP) redirect. The 403 response is served via an internal subrequest.
Set an environment variable and check with mod_authz_....
Alternatively, you can set an environment variable when the /subfolder is requested (using SetEnvIf) and check for this using the Require directive. This allows you to keep the condition separate from the directives that actually permit access. For example (using Apache 2.4 mod_authz_core):
SetEnvIf Request_URI "^/subfolder/" BLOCK_ACCESS
<RequireAll>
Require all granted
Require not env BLOCK_ACCESS
</RequireAll>
NB: If you are doing any URL-rewriting with mod_rewrite then you might need to check for REDIRECT_BLOCK_ACCESS instead in the above Require directive.
<If> expression (Apache 2.4)
On Apache 2.4 you can also use an <If> expression to target that specific subfolder with a containing mod_authz_core directive. For example:
<If "%{REQUEST_URI} =~ m#^/subfolder/#">
Require all denied
</If>
Although, strictly speaking, these methods target the URL-path, not the file-path.

.htaccess file on localhost

I have a localhost on ubuntu 16. In the root localhost directory (/var/www/html/) i put this htaccess file.
AddDefaultCharset utf-8
RewriteEngine on
RewriteRule ^index?$ index.php
When I type localhost/index apache says me
The requested URL /index was not found on this server.
Is that an error in Apache configuration?
Basicly I want to make redirects to index.php in the root of my site and here I want to parse something like this localhost/cart/item/1 to array and then realize MVC. I am new in web dev and do not realy understand how can I do it, please help me.
You have to enable the interpretation of such dynamic configuration files (".htaccess" style files) first. They are disabled by default, since they slow down the server considerably. Usually it is preferable to place such rules directly in the servers static configuration files.
To enable them take a look at the AllowOverride command: https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride
<Directory "/var/www/html">
AllowOverride All
</Directory>
So since you have to modify that configuration anyway... why don't you place your rewrite rules in there too? Easier, more robust and faster too...
Apart from that it sometimes is a good idea to implement rewrite rules in such way that they work in both locations, the http servers (virtual) host configuration and dynamic configuration files:
RewriteEngine on
RewriteRule ^/?index/?$ index.php [L]
And a general hint: you should always prefer to place such rules inside the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only provided as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).
Maybe you need to create a folder, and then, work in your application inside there. Ex:
Create a var/www/html/project;
Put yout .htaccess inside;
Work with your application inside that folder.

What is .htaccess file?

I am a beginner to Zend framework and I want to know more about the .htaccess file and its uses. Can somebody help me?
I found an example like this:
.htacess file
AuthName "Member's Area Name"
AuthUserFile /path/to/password/file/.htpasswd
AuthType Basic
require valid-user
ErrorDocument 401 /error_pages/401.html
AddHandler server-parsed .html
It's not part of PHP; it's part of Apache.
http://httpd.apache.org/docs/2.2/howto/htaccess.html
.htaccess files provide a way to make configuration changes on a per-directory basis.
Essentially, it allows you to take directives that would normally be put in Apache's main configuration files, and put them in a directory-specific configuration file instead. They're mostly used in cases where you don't have access to the main configuration files (e.g. a shared host).
.htaccess is a configuration file for use on web servers running the
Apache Web Server software.
When a .htaccess file is placed in a directory which is in turn 'loaded via the Apache Web Server', then the .htaccess file is detected and executed by the Apache Web Server software.
These .htaccess files can be used to alter the configuration of the Apache Web Server software to enable/disable additional functionality and features that the Apache Web Server software has to offer.
These facilities include basic redirect functionality, for instance if a 404 file not found error occurs, or for more advanced functions such as content password protection or image hot link prevention.
Whenever any request is sent to the server it always passes through .htaccess file. There are some rules are defined to instruct the working.
Below are some usage of htaccess files in server:
1) AUTHORIZATION, AUTHENTICATION: .htaccess files are often used to specify the security restrictions for the particular directory, hence the filename "access". The .htaccess file is often accompanied by an .htpasswd file which stores valid usernames and their passwords.
2) CUSTOMIZED ERROR RESPONSES: Changing the page that is shown when a server-side error occurs, for example HTTP 404 Not Found.
Example : ErrorDocument 404 /notfound.html
3) REWRITING URLS: Servers often use .htaccess to rewrite "ugly" URLs to shorter and prettier ones.
4) CACHE CONTROL: .htaccess files allow a server to control User agent caching used by web browsers to reduce bandwidth usage, server load, and perceived lag.
More info : http://en.wikipedia.org/wiki/Htaccess
You are allow to use php_value to change php setting in .htaccess file. Same like how php.ini did.
Example:
php_value date.timezone Asia/Kuala_Lumpur
For other php setting, please read http://www.php.net/manual/en/ini.list.php
Htaccess is a configuration file of apache which is used to make changes in the configuration on a directory basis.
Htaccess file is used to do changes in functions and features of the apache server.
Htaccess is used to rewrite the URL.
It is used to make site address protected.
Also to restrict IP addresses so on particular IP address site will not be opened
You can think it like php.ini files sub files.. php.ini file stores most of the configuration about php like curl enable disable. Where .htaccess makes this setting only for perticular directory and php.ini file store settings for its server' all directory...
It is not so easy to give out specific addresses to people say for a conference or a specific project or product.
It could be more secure to prevent hacking such as SQL injection attacks etc.
.htaccess file create in directory /var/www/html/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
What
A settings file for the server
Cannot be accessed by end-user
There is no need to reboot the server, changes work immediately
It might serve as a bridge between your code and server
We can do
URL rewriting
Custom error pages
Caching
Redirections
Blocking ip's

Apache Mod_ReWrite Suddenly Stopped Working

I had mod_rewrite set on my server to rewrite a url like the following
http://www.example.com/1
to
http://www.example.com/index.php?show=1
In order words a URL shortern. Everything was working fine when the system was running under a sub-domain on my development site, but now it just generates a Not Found error, although if I manually enter the url /index.php?show=1 it works fine.
So the only changes is the urls switching from
http://www.site.example.com
to
http://www.site.com
however it's still running on the same server and the same sub-folder inside public_html on the server just the new domain name has been pointed to that folder.
The folder it's stored in is /public_html/paste
The full .htaccess file running in the directory is
# Set Default File
DirectoryIndex index.php
# Turn ReWrite Engine On
RewriteEngine on
# Create Rule To Write URLs To Shorter Versions
RewriteRule /([a-z0-9]+) /index.php?show=$1
I can't enable RewriteLog as the hosting doesn't allow it for some reason.
It sounds like the AllowOverride directive is not properly set for that folder. In your Apache configuration, you should make sure that the Directory or Vhost you're using for the primary domain has the AllowOverride set to All
http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride
You probably need to specify the RewriteBase directive.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
I'll also note that Options +FollowSymlinks would be good to have in there too in case you ever turn it off further up the config chain (rewrite wont work without it).

PHP: How to code .htaccess to make it work both on localhost & online without editing

I have a .htaccess file & I currently I am working on localhost. For a 404 page error, I have the following code in the .htaccess file:
ErrorDocument 404 /my_local_domain/404.php
But when I upload this file to my website online, the functionality of the file breaks. It no longer shows the 404.php page. It works if I modify the code in the .htaccess file of my online website to the following:
ErrorDocument 404 /404.php
Now all through the changes that I do in the .htaccess file, I would have to remember to remove the domain name before I upload it to the website or I risk breaking the functionality. So with this in mind, here are my questions:
1. How do I solve the above problem without needing to edit the .htaccess file each time (by stripping it off the my_local_domain) I make a change & upload it online?
2. How do I setup 404 page redirection for all the nested folders? (I don't want to setup a .htaccess file for each of the folders. A single .htaccess file that resides in the root folder of the website & controls all the redirection for all the sub-folders would be awesome)
All help is appreciated.
Thank you.
I believe you have two different issues here.
First of all, you should not need to have different paths in development and live site. It appears that you've configured your local Apache to host only one site and each actual sites goes in a subdirectory. It's not a good idea: you'll soon be mixing cookies and sessions between all your dev sites. Have a look at the name based virtual hosts feature: you can configure as many independent sites as you need. You don't even have to buy real domains in you set them in the hosts file.
Secondly, under certain circumstances it can be useful to have different Apache directives. I've been using the following trick.
Pick a keyword for the dev server, e.g. DEV_BOX.
Pass that keyword to Apache in the -D parameter. If you run it as service, you can run regedit and find the HKLM\SYSTEM\CurrentControlSet\Services\Apache2.2\Parameters key. Append -D DEV_BOX to the ConfigArgs value. Restart Apache.
Now, you can use the <IfDefine> directive to set local directives:
-
#
# Common stuff
#
AddDefaultCharset UTF-8
#
# Local-only stuff
#
<IfDefine DEV_BOX>
Options +Indexes
</IfDefine>
#
# Live-only stuff
#
<IfDefine !DEV_BOX>
Options -Indexes
</IfDefine>
First of all I suggest you setup local domains for development. For example if you are developing a website which will go under www.example.com, you can setup a local.example.com in your HOSTS file. You'll do a VirtualHost setup in your apache and the .htaccess will then be the same.
Also, you can setup a build process (e.g via Ant) which will allow you to prepare and generate a zip file with the files which go on the live server. This build will feature the correct configuration files (db configs, mail servers, htaccess etc).