How to Use SetEnvIf to Set Environment Variables Based on HTTP Host in Apache


2 views

When working with Apache, you might need to set environment variables dynamically based on the HTTP Host header. This is particularly useful for:

  • Environment-specific configuration (DEV/STAGE/PROD)
  • Routing requests differently based on domains
  • Implementing domain-based feature flags

The proper way to achieve this is using SetEnvIf with the Host header:

# In your Apache config or .htaccess
SetEnvIf Host ^dev\.example\.com$ ENV=DEV
SetEnvIf Host ^prod\.example\.com$ ENV=PRD

Here's a full configuration example that covers multiple environments:

<IfModule mod_setenvif.c>
    # Development environment
    SetEnvIf Host ^dev\.example\.com$ ENV=DEV
    
    # Staging environment
    SetEnvIf Host ^stage\.example\.com$ ENV=STAGE
    
    # Production environment
    SetEnvIf Host ^(www\.)?example\.com$ ENV=PRD
    
    # Alternative domains
    SetEnvIf Host ^example\.net$ ENV=PRD
</IfModule>

After setting the environment variable, you can access it in PHP:

<?php
// Check the environment
if (getenv('ENV') === 'DEV') {
    // Development-specific code
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} elseif (getenv('ENV') === 'PRD') {
    // Production-specific code
    error_reporting(0);
    ini_set('display_errors', 0);
}
?>

Issue: Variables not being set
Solution: Ensure mod_setenvif is loaded. Check with:

apachectl -M | grep setenvif

Issue: Host matching not working
Solution: Use proper regex anchors. The pattern ^dev\.example\.com$ matches exactly "dev.example.com"

You can combine multiple conditions:

SetEnvIf Host ^dev\.example\.com$ ENV=DEV
SetEnvIf X-Forwarded-Proto https HTTPS=on

Or set multiple variables at once:

SetEnvIf Host ^dev\.example\.com$ ENV=DEV DEBUG=true

While SetEnvIf is powerful, remember:

  • Complex regex patterns can impact performance
  • Variables are set per-request
  • Consider caching environment detection if used frequently

When configuring Apache web servers, developers often need to set environment variables dynamically based on the incoming HTTP Host header. This is particularly useful for:

  • Environment detection (DEV/STAGE/PROD)
  • Multi-tenant applications
  • Domain-specific configuration

The proper way to use SetEnvIf with the Host header is:

SetEnvIfNoCase Host ^dev\.example\.com$ ENV=DEV
SetEnvIfNoCase Host ^prd\.example\.com$ ENV=PRD

Here's a full virtual host configuration example:

<VirtualHost *:80>
    ServerName dev.example.com
    ServerAlias prd.example.com
    
    # Environment detection
    SetEnvIfNoCase Host ^dev\.example\.com$ ENV=DEV
    SetEnvIfNoCase Host ^prd\.example\.com$ ENV=PRD
    
    # Fallback for other domains
    SetEnvIfNoCase Host ^.*$ ENV=UNKNOWN
    
    DocumentRoot /var/www/html
</VirtualHost>

In your PHP application, you can access this variable through:

<?php
$environment = $_SERVER['ENV'] ?? 'UNKNOWN';

if ($environment === 'DEV') {
    // Development-specific logic
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} elseif ($environment === 'PRD') {
    // Production-specific logic
    error_reporting(0);
    ini_set('display_errors', 0);
}
?>

Problem: Variables not appearing in $_SERVER
Solution: Ensure mod_setenvif is enabled with:
a2enmod setenvif && service apache2 restart

Problem: Host header matching fails
Solution: Use regex anchors properly and escape dots:
SetEnvIfNoCase Host ^sub\.domain\.com$

For more complex scenarios, you can combine multiple conditions:

# For staging subdomains
SetEnvIfNoCase Host ^staging-[0-9]+\.example\.com$ ENV=STAGE

# For IP-based access
SetEnvIf Remote_Addr ^192\.168\.1\. ENV=LOCAL