Single htaccess file with distinction between production and development - apache

I am currently using two .htaccess files for my website: one is the development version, and the other one is the production version. The difference is in absolute and some relative paths that are used for RedirectMatch, RewriteRule, and ErrorDocument directives, and that differ between development and production. I am using a git hook to remove the dev version and rename the production version, but this still means I have to maintain two versions of basically the same file. Also, I am encountering similar problems with other sites I manage, so this all means more work. I rather have one single file and some sort of condition in the .htaccess file that allows me to say if production -> use these, else -> use these. Can I do such thing in an .htaccess file?
I have found this:
.htaccess between developemt, staging, and production
But this is for rewrite rules and would not fix the different ErrorDocument paths.

If your servers are running Apache 2.3 or higher, you can use an <if expr> directive like this:
<if "%{HTTP_HOST} == 'dev.example.com'">
# dev directives
</if>
<if "%{HTTP_HOST} == 'www.example.com'">
# prod directives
</if>
Earlier versions of Apache will throw a 500 Server Error if you use <if>, be sure to check the Apache version before trying this.

I ran into an issue where I needed a similar solution but could not use <if expr> directive because I was running Apache 2.2
An alternative is to put password protect instruction in your apache config (vhost-conf in my case) file within the tag like below. Note that you still need a .hpasswd file
ServerAdmin xxx#lami.me
DocumentRoot "/doc/root/html"
ServerName dev.lami.me
ServerAlias dev.lami.me localhost
ErrorLog "/doc/root/logs/error_log"
CustomLog "/doc/root/logs/access_log" common
<Directory "/doc/root/html">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
AuthName "Restricted Area"
AuthType Basic
AuthUserFile /doc/root/.htpasswd
AuthGroupFile /dev/null
require valid-user
</Directory>

I rather have one single file and some sort of condition in the .htaccess file that allows me to say if production -> use these, else -> use these. Can I do such thing in an .htaccess file?
No. Sorry.
However you may construct your .htaccess to work on both with a bit of care. And I have done this for my test and prod systems.
IMO, the easiest way to do this is to make your development site mirror your production site in some key aspects and this is what I do. For example if your prod domain is mydomain.com and your test environment is on localhost, the add an alias of mydomain.home for localhost in your etc/hosts file. You can now add a vhost for mydomain.home and mirror the document roots and environment setting of prod in this. If you need to refer to the HTTP_HOST, you can now use mydomain.(com|home) and use %1 to distinguish which.
This assumes that you are running your dev env on a LAMP system. If not it's pretty easy to set up a VM to do this (as I describe here)
You can use RewriteRules instead of RedirectMatch directives and with Rewriterules you can use the [C],[OR],[E] and [S] flags to implement branch-style ladder-logic which can effectively mirror if/then/else constructs.
The main gotcha is DocumentRoot setting if you production is on a shared hosting environment and with impacts local ErrorDocument paths, but without knowing you environments, it is difficult to give more specifics

Related

Apache won't autoindex

Oracle Linux 7.3 (RHEL derivative)
Apache 2.4.6
I'm setting up a repository in /srv/www for yum, scripts, and kickstart files, served via httpd. I want an auto-index, so I don't have any index.html. And, this is the only thing this internal server will do. So, httpd.conf:
DocumentRoot "/srv/www"
<Directory "/srv/www">
AllowOverride all
Options Indexes FollowSymLinks
Require all granted
</Directory>
However, I still get the error message:
[autoindex:error] [pid 12345] [client <IP address>:<port>] AH01276: Cannot serve directory /srv/www: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive.
Except that the Options directive allows auto-indexing! I've tried Options All. I've tried Options +Indexes +FollowSymLinks. I've looked at 7 or 8 Google hits. Nothing is working.
Setting LogLevel debug doesn't increase messaging.
What have I missed?
As noted here, in the absence of an index.html (or other configured index file), the welcome page configured at /etc/httpd/conf.d/welcome.conf will take precedence over other configurations via its LocationMatch directive. Rename the file so it doesn't end in .conf and auto-indexing works.
Obviously landing in another virtualhost or Directory without indexes enabled, or a .htaccess getting in the way.
Set "AllowOverride none" first, since it is absurd to have it active if you are not using any .htaccess file (and since you have access to the main server you don't need it). Once you set AllowOverride, restart the server in case you added Indexes recently and didn't restart to apply changes.
If the issue persists, run apachectl -S and make sure you are landing in the correct virtualhost.
I just want to add that, after updating my mac to Catalina, my apache stopped working with that same error.
I had to:
uncomment the required modules (php7, rewrite, directory, etc...)
add a + sign to the Options (Options +FollowSymLinks +Multiviews +Indexes)
This worked for me.
Solution:
Ensure two apache modules are running:
mod_autoindex.so
mod_dir.so
In your case, mod_autoindex.so is running. Now enable the second one.
PS: Keep Options -Indexes. It's important. It makes sure that directory listings are disabled, as you shouldn't allow anyone to pay a visit to every directory on your server (some with rather private content such as CMS's directories).

How to add .htaccess rules inside <VirtualHost> or inside the httpd.conf file

A short explanation of what I'm doing is: I need to automatically create virtualhosts for each ip address on my machine, make it point to the vsftpd user directory (/home/xxx) and deny any kind of scripts from being executed.
I want to stop any kind of webpages and especially PHP scripts from being executed, because it would post a huge security risk(apache is sudo). The purpose of this virtualhost is purely to serve game resource files, extentions like .wav , .mdl , .tga , .spr and so on.
I searched around and found this
deny from all
<filesmatch "\.(avi¦wmv¦mpg¦mov)$">
Allow from all
</filesmatch>
But this is .htaccess content. How can I implement this functionality of only allowing certain extentions inside my httpd.conf file? It would be a pain to make it use .htaccess, and a risk because users might edit them.
Please refrain from any comments unrelated to my question, such as "sudo apache? you're a dumbass" and so on.
There is no such thing as .htaccess only content. The is a huge misconception. Most of time you do NOT want to use .htaccess and Apache recommends that you not use it unless necessary. Apache rules can always be put in the server config.
When not to use .htaccess
Now you can put that in your VirtualHost directive. The same location where your document root is defined.
The FilesMatch directive can be used in these context.
Context: server config, virtual host, directory, .htaccess
http://httpd.apache.org/docs/current/mod/core.html#filesmatch
So in your vhost file you can add a Directory directive like this example.
<Directory /path/to/documentroot/>
Deny from all
<FilesMatch "\.(avi|wmv|mpg|mov)$">
Allow from all
</FilesMatch>
</Directory>
If you are using Apache 2.4 then you need to use Require.
<Directory /path/to/documentroot/>
Require all denied
<FilesMatch "\.(avi|wmv|mpg|mov)$">
Require all granted
</FilesMatch>
</Directory>

Apache: <Directory> directive with no path specified

I have a local server environment running on my OS X machine using MAMP, and I am currently setting up a few virtual hosts. I found that, in order for one of my virtual hosts to recognize my site's .htaccess file, I needed to add a <Directory> directive within the <VirtualHost> directive.
Here is an example of what I am using to configure one of my virtual hosts:
<VirtualHost *>
DocumentRoot "/path/to/mysite"
ServerName mysite.local
<Directory "/path/to/mysite">
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
Now, I would like to avoid redundancy by removing the path from that <Directory> directive. I tried doing so and it seems to work, although I am not familiar with Apache enough to know the potential consequences of doing this. Furthermore, I could not find an explanation of this case in the Apache Documentation.
This is what I would like to do:
<VirtualHost *>
DocumentRoot "/path/to/mysite"
ServerName mysite.local
<Directory>
AllowOverride All
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
Therefore, my question is this: what happens when I omit the path from the <Directory> directive (in this case)?
Directory is a directive targeting a file system directory, and should always have a path (waildcards allowed).
Using some instructions targetd to no directory may be discarded silently, or maybe with an error (you could test it), but is would certainly be useless.
Why would you write some configuration instructions targeted to no directory at all?
But there's maybe more things in your question.
Ususally a Virtualhost should contains at least one Directory instruction, the DocumentRoot directory, and usually we also add one targeting the root of the filesystem, this way:
<Directory />
(instructions to deny access and avoid .htaccess reads)
</Directory>
<Directory /my/document/root/>
(instructions to allow access and still avoid .htaccess reads or to allow them if you are lazy and feel over confident that .htaccess are useful in any way and you do not need speed)
</Directory>
And you could add more, especially to avoid usage of .htaccess files as such file stored in /path/to/somewhere is the same thing as a <Directory /path/to/somewhere> section, but slower.
Now you do not like to repeat yourself in your VH configuration, so you coud maybe use .htaccess files or global level instructions for things that are usually set there. And you could also use another magical keyword, which is Location.
You can use a lot of Apache instruction in a <Location /foo> directive. Locations works on url, not on filesystem paths.
So <Location /> is your documentRoot, and <Location /foo> is maybe the subdirectory 'foo' under you DocumentRoot. This could help you write things in your VH without reusing the documentroot prefix everywhere. But be careful, urls are not file-system paths. Any protection applied on the url level may be weaker or stronger compared to a protection applied on a directory level. It depends on your alias, the way you use urls, etc.
Update:
If you use the new Apache 2.4 version you can now use mod_macro or even easier, built-in variables support:
Define docroot "/path/to/mysite"
DocumentRoot ${docroot}
<Directory ${docroot}>
(...)

Change path chiliproject

I want to use a subdirectory for a chiliproject instance. Using apache passenger, I was thinking of using rewrites + alias, but then it gives me a 404. Adding a RailsBaseURI i get connection reset.
Is it routes.rb I should adapt or am I looking at the wrong place? It is working right now on https://mydomain.com but I'd like to have it on https://mydomain.com/tracker
You can use passenger directly without having to use an alias or redirection. However, Passenger requires some special configuration for that. Please see one of our guides for a complete installation example.
Generally you need to configure similar to this (cited from the linked guide):
At first, we assume you have installed ChiliProject to /srv/www/chiliproject. This is not your DocumentRoot.
You need to hint Passenger a bit here so that it correctly finds your ChiliProject. So we create a symlink from the existing DocumentRoot directory to out ChiliProject installation.
ln -s /srv/www/chiliproject/public DOCUMENTROOT/chiliproject
Now add the following directives into your existing virtual host:
# TODO: Remember to replace DOCUMENTROOT with your actual path
<Directory DOCUMENTROOT>
Options +SymLinksIfOwnerMatch
</Directory>
RailsBaseURI /chiliproject
# TODO: Remember to replace DOCUMENTROOT with your actual path
<Directory DOCUMENTROOT/chiliproject>
Options -MultiViews
Order deny,allow
Allow from all
</Directory>

Apache local configuration to resolve files correctly

I have just configured Apache and PHP to work on my local Mac OS X computer. Now PHP works fine, except when I try to load the files for my live sites. The live sites have separate directories and are sorted by client name etc.
I've created symlinks in the default root for the local web server documents. My issue is that Apache doesn't seem to want to load any of the relative paths that are found in the HTML pages. For example, I have src="/css/main.css" but Apache doesn't load the file, similarly for images, it just resolves as a file not found 404 error. I then thought it might be the symlinks so I copied the full directory into the Apache document root, and still had the same result.
I would really love to setup my local development environment to run Apache, PHP, MySQL to develop locally then publish when ready. I also tried the MAMP installation, and had the same issues.
First you might want to try using src="./css/main.css".
When dealing with multiple live sites I like to setup a single configuration file for each site with apache and then load them all together in the httpd.conf file.
for my setup it looks like this:
in
/etc/apache2/httpd.conf
I have:
# Begin virtual host directives.
Include conf/bortreb.conf
Include conf/rlmcintyre.conf
Include conf/laserkard.conf
Include conf/judyates.conf
and then in
/etc/apache2/conf/judyates.conf
I have:
<VirtualHost *:80>
#localhost site
ServerAdmin email#example.com
DocumentRoot "/home/r/Desktop/web/judyates"
ServerName localhost
ServerAlias judyates.localhost
ErrorLog "/home/r/Desktop/web/judyates/log/error_log.log"
ScriptAlias /cgi-bin/ "/home/r/Desktop/web/judyates/cgi-bin/"
<Directory "/home/r/Desktop/web/judyates">
Options Indexes FollowSymLinks
Options +ExecCGI
AddHandler cgi-script cgi pl py
AllowOverride Options
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
#live site
ServerAdmin email#example.com
DocumentRoot "/home/r/Desktop/web/judyates"
ServerName judyates.com
ServerAlias *.judyates.com
ErrorLog "/home/r/Desktop/web/judyates/log/error_log.log"
ScriptAlias /cgi-bin/ "/home/r/Desktop/web/judyates/cgi-bin/"
<Directory "/home/r/Desktop/web/judyates">
Options Indexes FollowSymLinks
Options +ExecCGI
AddHandler cgi-script cgi pl py
AllowOverride Options
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
This way works really well, because you can set the subdomain yoursite.localhost
to loop back to your home ip address.
With this setup, when I work on judyates.com on my computer and want to test anythig, I just go to judyates.localhost in my web browser.
I have about 5 other sites all set up this way in their own *.conf file, so they can each live in their own directories on my computer that exactly match the directories they'll be in on the server.
The key is to use virtual hosts to go to different sites based on the subdomain.
You can learn how to configure subdomains that point to yourself here:
http://digitalpbk.blogspot.com/2007/01/making-subdomains-on-localhost.html
My setup goes even one step further because I setup the server too. Whenever I want to update I load both the webfiles AND the apache config files, and that way the server exactly mirrors my local setup. The only difference is that the real judyates.com points to the server and not my home computer, so when people try to visit the site they get everything from the server.
Have you tried src="css/main.css"? That is, without the leading slash? If you have a leading slash there your files would have to be in a directory named css that was in the root directory of the webserver, and if I understand you correctly that's not the case.
EDIT: OK, from reading your comments it seems like you are not quite clear on how relative urls work. "/css/main.css" is not relative to the page's location in the directory tree. It means a file named "main.css" in a directory named "css" in the root directory of the webserver. When you put your files on the deployment server your css directory is at the webserver's root directory. But it sounds like you are currently putting the css directory in a subdirectory named for the client... so your css file is now living at "/clientname/css/main.css".
If I understand you correctly, you can do what you want by using relative urls. If your html file is in the same directory as the css directory you would need "css/main.css". If it's in a subdirectory of the directory that contains the css directory you would need "../css/main.css"- the ".." means the parent directory of the current directory. If you use relative urls they will continue to work as long as the relationship between the files doesn't change.
Here's a page on the subject that explains it adequately, I think: http://www.webreference.com/html/tutorial2/3.html. Was pretty much the first thing I found in Google though, so there are likely better explanations out there.
There are a number of Apache directives that you could use to do this, but if using relative urls would work for you (and if I understand you correctly it would) then that's likely to be a lot simpler and less likely to cause you further trouble.