Using apache config and htaccess to dynamically set config vars for dev and production
Asked Answered
D

1

13

Short Summary

I need to be able to set an environment variable in the Apache site config that defines if the site is dev, beta or production.

The htaccess file in the web root will define config variables for the website (database credentials, domain, etc) based on the entry in the Apache configuration

ALSO I need to use one of the variables defined in the web roots htaccess in another htaccess located in another directory.

Site Configuration

Apache config (dev/beta)

I would like to set an environment variable for my dev and beta environments in their Apache site config files

Something like this:

(Im sure its not the correct syntax)

SetEnv environment_type dev

- or -

SetEnv environment_type beta


Apache Config (Production)

The production sites apache config could either not set it at all, or it could do:

SetEnv environment_type prod

But this would be optional


.htaccess (Set site config vars)

The configuration variables used for database connection, domain name and so on, would then be set in the .htaccess file in the public webroot like so:

(Again, just mockup syntax)

<If (environment_type exists) && (environment_type == dev)>
    SetEnv base_dir /www/example.com/dev/
    SetEnv db_host localhost
    SetEnv db_name devdb
    SetEnv db_user devuser
    SetEnv db_password devpass
    SetEnv web_domain www.devdomain.com
    SetEnv cookie_domain .devdomain.com
<elseif (environment_type exists) && (environment_type == beta)>
    SetEnv base_dir /www/example.com/beta/
    SetEnv db_host localhost
    SetEnv db_name betadb
    SetEnv db_user betauser
    SetEnv db_password betapass
    SetEnv web_domain www.betadomain.com
    SetEnv cookie_domain .betadomain.com
<else>
    SetEnv base_dir /www/example.com/www/
    SetEnv db_host localhost
    SetEnv db_name proddb
    SetEnv db_user produser
    SetEnv db_password prodpass
    SetEnv web_domain www.proddomain.com
    SetEnv cookie_domain .proddomain.com
</If>


Using Defined Settings

I need to be able to use these new config variables, not only in my php scripts, but also within another .htaccess file in a subdirectory


Other .htaccess File

I have another .htaccess file that resides in a sub-directory, and its purpose is to enforce basic http authentication for that area.

The Problem

The AuthUserFile entry that points to the .htpasswd file must be dynamic based on the environment variables.

What I need:

AuthName "Admin Area"
AuthType "Basic"
AuthUserFile base_dir + "/web/sam/.htpasswd"
AuthGroupFile "/dev/null"
ErrorDocument 404 /sam/error.shtml    
<Limit GET POST>
require valid-user
</Limit>

Current .htaccess:

AuthName "Admin Area"
AuthType "Basic"
AuthUserFile "/www/example.com/beta/web/sam/.htpasswd"
AuthGroupFile "/dev/null"
ErrorDocument 404 /sam/error.shtml    
<Limit GET POST>
require valid-user
</Limit>


config.php

I already know that this works
My php config files could then get the config values like so

<?php
    $db['default']['hostname'] = getenv('db_host');
    $db['default']['username'] = getenv('db_user');
    $db['default']['password'] = getenv('db_password');
    $db['default']['database'] = getenv('db_name');
?>
Daves answered 19/12, 2013 at 0:9 Comment(0)
A
15

You're basically right. You can set an environment variable using SetEnv:

SetEnv ENVIRONMENT_TYPE "DEV"

Additionally, given that htaccess is parsed from server configuration down through the relevant directories until the directory that Apache thinks the request can be served from, you can use previously defined environment variables in other htaccess files.

However, you can't combine/concatenate environment variables, you can only use the SetEnvIf directive to generate environment variables based on the value of other environment variables.

Additionally, within a SetEnvIf directive, you can only inspect environment variables that have also been created by SetEnvIf:

E.g. /etc/apache2/sites-enabled/001-project

# This has to be created by SetEnvIf, I've set the regex to match
# anything as we want the environment variable set always
SetEnvIf Host .* ENVIRONMENT_TYPE "Prod"

# Alternatively you could do:
SetEnvIf Host prod\.domain\.com ENVIRONMENT_TYPE "Prod"
SetEnvIf Host dev\.domain\.com ENVIRONMENT_TYPE "Dev"
SetEnvIf Host (www\.)?domain\.com ENVIRONMENT_TYPE "Live"

And in /www/example.com/.htaccess

SetEnvIf ENVIRONMENT_TYPE "Prod" DB_USER="test"
SetEnvIf ENVIRONMENT_TYPE "Prod" DB_NAME="database"
SetEnvIf ENVIRONMENT_TYPE "Prod" DB_PASS="passwd"
SetEnvIf ENVIRONMENT_TYPE "Live" DB_USER="live"
SetEnvIf ENVIRONMENT_TYPE "Live" DB_NAME="database"
SetEnvIf ENVIRONMENT_TYPE "Live" DB_PASS="passwd"

And in /www/example.com/prod/web/sam/.htaccess you can use the IF, Else and ElseIf directives:

AuthName "Admin Area"
AuthType "Basic"
<If "env('ENVIRONMENT_TYPE') == 'Prod'">
    AuthUserFile "/www/example.com/prod/web/sam/.htpasswd"
</If>
<Else>
    AuthUserFile "/www/example.com/beta/web/sam/.htpasswd"
</Else>
AuthGroupFile "/dev/null"
ErrorDocument 404 /sam/error.shtml    
<Limit GET POST>
    Require valid-user
</Limit>

Then in your PHP you can access the environment variables using getenv() or:

echo $_SERVER['ENVIRONMENT_TYPE'], "\n";
$db_user = $_SERVER['DB_USER'];
Acronym answered 19/12, 2013 at 10:34 Comment(3)
Wow! Thank you for giving me such a well explained and detailed answer!Daves
No worries, it was a cool question and I learnt something in the process of answering it :)Acronym
Perfect. I was having trouble figuring out how to use the value set with SetEnvIf in an If statement and this helped clear it up.Distaff

© 2022 - 2024 — McMap. All rights reserved.