How can I read the local IP address into an .htaccess file? - apache

I am planning to use a single .htaccess file which may be deployed on multiple servers. In the process I am setting environment variables in the .htaccess file and there are a couple of cases where I would like to read the IP address into the settings. For instance, in one case I am setting an environment variable for the local database connection:
SetEnv DBL "mysql:dbname=oars;host=192.168.101.1;port=3306"
Then in PHP I would read the variable for use by the database interactions:
define('DBL', getenv('DBL'));
Since I am planning to deploy on multiple servers is there a way to get the IP address automagically rather than maintaining separate .htaccess files for each server?

You can use a Rule to set the Env variable:
RewriteEngine on
RewriteRule ^ - [E=DBL:mysql\:dbname=oars\;host=%{SERVER_ADDR}\;port=3306]
print getenv("DBL");
mysql:dbname=oars;host=1.2.3.4.5;port=3306

Related

Howto use path/directory outside the domain root via symlink without access to domain config?

I am working an a shared hosting plattform which does not allow to edit or access the Apache config file.
The goal is to access the same files from two different domains which point to different domain roots:
test.example.com ---> /test_root/web
public.example.com ---> /public_root/web
Now I would like to access the same files using test.example.com/some/files/... and public.example.com/some/files/...
Of course I could simply copy the files to /test_root/web/some/files/... and to /public_root/web/some/files/... but this obviously just an example. In reality the files are a helpdesk system which should be integreated both into the test- and public-site. Copying the files would include maintaining two different systems, etc.
The goal is, to place the the files somewhere outside the two domain roots and make them available from both domains:
/test_root/web/some/files ---> /path/to/some/files
/public_root/web/some/files ---> /path/to/some/files
I created symlink to achive this (ln -s ...) but this does not work out. When I access on of the domains (e.g. test.example.com/some/files) I only get a blank page without any information what whent wrong.
I assume that the Apache is not configured to follow the symlinks. Without access to the Apache config I can neither check nor fix it.
Adding Symlinks to .../web/.htacess does not make any difference:
// test_root/web/.htaccess
Options +FollowSymLinks
So the question is: How can I make files outside the domain root available within a domain? Is this even possible? Is this possible using symlinks?
Add this in you .htaccess file.
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} test.example.com/path/to/files [NC]
RewriteRule ^(.*)$ http://public.example.com/path/to/files [R=301,NC]
Test out this code. /path/to/files must be under /public_root/web/.
Something like /public_root/web/path/to/files/

Rewrite with multiple symfony projects under same directory

I'm trying to make some personal projects in my development server, like some sort of intranet.
If I divide each project in a different virtualhost, I set in each computer the host file to each server name and I don't have problems with the rewrite rule and the app.php. But the problem is that I can't modify the host file in an android device so I can't access those webs.
What I have in mind is something like this:
I have three symfony projects under my home folder
/home/user/projects/project1
/home/user/projects/project2
/home/user/projects/project3
Then, under the default folder of apache I make soft links to the web folder to every project:
ln -s /home/user/projects/project1/web /var/www/html/project1
ln -s /home/user/projects/project2/web /var/www/html/project2
ln -s /home/user/projects/project3/web /var/www/html/project3
So I can access them this way:
http://server-ip/project1
http://server-ip/project2
http://server-ip/project3
The problem is that I use those url I need to add the default app.php. I've been trying to modify the .htaccess file of each project, but I don't what to modify. I'm using the default virtualhost configuration and the default .htaccess file of each project.
I think that I need to modify the RewriteCond line, but I don't know what to do.
Thanks
I've got a local development environment (it's actually running on a linux server, under my desk, but the same setup would apply to any other configuration of server).
The webserver has a local IP address, reachable from elsewhere on the local network, including from my phone over WiFi.
All the development sites have their own Vhost configured on the server, with a common DNS prefix - something like *.devserver.domain.com.
The DNS is configured so that devserver.domain.com and the wildcard *.devserver.domain.com return 192.168.1.75 (or whatever the internal, static IP address is). This is a public domain name that has an A record to a local-range IP address, but it's entirely valid.
If you don't have a domain name that you can add wildcard DNSs to, you can use a service such as http://nip.io/ - and so the vhost Servername would be something like:
project1.192.168.1.75.nip.io
project2.192.168.1.75.nip.io
... etc
You may end up regularly editing the apache vhost if you internal IP changes at all, and maybe finding alternate wildcard DNS servers (my go-to was xip.io, but that isn't diffcult to do).
You may also be able to use an internal wildcard for an Apache ServerName/serverAlias: ServerAlias mysite.*.xip.io.

Apache ElseIf block entered even though condition is false

Back Story:
I have a copy of all my website files located on two different file servers. I have a two web servers, mimir2 and mimir4, with maps to access the files from either of these file servers. The unique value in the file path to these file servers is either dtg_devel_ah or dtg_devel_nr.
What I am trying to do:
I am editing my httpd.conf file to dynamically set, on server start, which file server to use based on the web servers name. I am doing this by using Apaches Define directive to create the variable dtg_devel_path which will get used in directory paths throughout the rest of the httpd.conf file.
My Code to accomplish this (Note: There are SetEnv declrations scattered throughout only for my debugging purposes):
# Define which dtg_devel_xx to use based on server name. This is so that
# the server is accessing its local files instead of across the country
# Default to dtg_devel which will point to which ever server site is active
Define dtg_devel_path dtg_devel
# If running on mimir2 use dtg_devel_nr
# else if run on mimir4 use dtg_devel_ah
<If "env('HOSTNAME') =~ /mimir2/i">
Define dtg_devel_path dtg_devel_nr
SetEnv dtg_devel_m2 ${dtg_devel_path}
SetEnv dtg_devel_hostname_m2 ${HOSTNAME}
</If>
<ElseIf "env('HOSTNAME') =~ /mimir4/i">
Define dtg_devel_path dtg_devel_ah
SetEnv dtg_devel_m4 ${dtg_devel_path}
SetEnv dtg_devel_hostname_m4 ${HOSTNAME}
</ElseIf>
SetEnv dtg_devel_final_set_path ${dtg_devel_path}
SetEnv dtg_devel_hostname ${HOSTNAME}
When I run this the values getting set are:
My Problem:
The value of dtg_devel_path should be dtg_devel_nr. I am running this on server mimir2 which you can see is confirmed from the above picture. The if part of the if/elseif statement is returning true (HOSTNAME equals mimir2) and in turn setting dtg_devel_path, dtg_devel_hostname_m2, and dtg_devel_m2. Strangely though somehow dtg_devel_path then gets changed to the value dtg_devel_ah even though the elseif block never gets entered. This is confirmed by the value of the dtg_devel_final_set_path variable and the lack of values for dtg_devel_m4 and dtg_devel_hostname_m4. This code block is the only location that the string dtg_devel_ah appears so this has to be where it is getting set.
Does anyone see the mistake that I have in my code? Does anyone have any suggestions? Any help would be greatly appreciated!! If any additional information is needed please let me know.
I could not figure out how to solve this completely through Apache so I ended up going a slightly different path. My web server is running on a RHEL 6.4 machine fyi.
I basically pulled the if/else function that I had in the http.conf file and put it into three places; /etc/profile.d/dtg_deve_path.<sh,csh> and /etc/init.d/httpd. These files check the host name and create a DTG_DEVEL_PATH environment variable based on that value. I then access that value in httpd.conf with a Define dtg_devel_path ${DTG_DEVEL_PATH} which then lets me accomplish what I was trying to do, use ${dtg_devel_path} through the rest of the httpd.conf file to dynamically specify which file server to use.

.htaccess in Multiple Environments

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.

How can I transparently rewrite an old host url to a new host url?

I have two apache virtual hosts within the same domain (and on same physical system):
old.example.com
new.example.com
I'd like to be able to transparently rewrite or map certain old url's to new. Example:
A request for http://old.example.com/foo would actually result in a request for http://new.example.com/foo
I want the http client (browser) to be unaware of the rewrite...in other words, I'm not looking to redirect. And, I only want to rewrite specific url's.
What can I add to either the virtual host or htaccess file(s) to accomplish this?
I guess you could set up your virtual hosts via mod_rewrite and then simply add those rewriting steps to the configuration.
If, however, all you are trying to do is to re-use some things you have in the file system, without any magic in your config files, I would use symbolic links instead. (I have no idea if there are any equivalents for windows servers, though.)
I found the answer here: http://httpd.apache.org/docs/2.0/misc/rewriteguide.html in the section titled Dynamic Mirror. I added this to my htaccess on http://old.example.com :
RewriteEngine on
RewriteBase /
RewriteRule ^foo http://new.example.com/foo [P]
The feature flag P tells the rule to use Proxy Throughput.