This site is a static archive of the Aegir community site. Documentation has moved to http://docs.aegirproject.org. Other community resources can be found on the Contacting the community page.
Skip navigation

Revision of Injecting into site vhosts from Fri, 11/30/2012 - 21:17

Help

Injecting into site vhosts

Tagged:

Aegir provides some hook functions in its API, one of which allows you to inject extra configuration snippets into your Apache vhost files for sites.

When would I want to do this?

A good example for this is when you may need to inject a custom Rewrite rule that goes beyond what the Aegir Aliases 'redirection' feature provides.

Or, perhaps you have to inject some htpasswd mod_auth password protection for your site, or perhaps a CustomLog definition.

Typically you'd just add what you need to the vhost file, but the problem is that Aegir manages these vhosts, and on every Verify task, will rewrite the config from a template, blowing away your changes in the process. Ouch!

Fortunately there is a very easy and elegant solution to this problem to save your configurations persistently across Verify tasks and the like, by means of invoking the Provision hook provision_apache_vhost_config(), or, if you are using Nginx, provision_nginx_vhost_config() (and just replace the below examples with 'nginx' instead of 'apache' where necessary). Below "mig5" is just an example, you can replace this with anything as drush looks for all *.drush.inc files in ~aegir/.drush

A simple example

In this example I'll inject a simple 'ErrorLog' apache definition into a vhost to save the site error logs to a file.

  1. Create a file in ~aegir/.drush called mig5.drush.inc
  2. Add this snippet of PHP to the file:

    <?php
      function mig5_provision_apache_vhost_config($uri, $data) {
        return "ErrorLog /var/aegir/" . $uri . ".error.log";
      }
  3. Install a site or verify an existing one

Check your site's vhost config file (in /var/aegir/config/server_master/apache/vhost.d/) and you'll see the line has been injected into the '#Extra configuration' area of the vhost

<VirtualHost *:80>

  DocumentRoot /var/aegir/hostmaster-HEAD
   
  ServerName 1.mig5-forge.net
  SetEnv db_type  mysqli
  SetEnv db_name  1mig5forgenet
  SetEnv db_user  1mig5forgenet
  SetEnv db_passwd  X7KzsFhxhp
  SetEnv db_host  tardis
  SetEnv db_port  3306



# Extra configuration from modules:
  ErrorLog /var/aegir/1.mig5-forge.net.error.log
    # Error handler for Drupal > 4.6.7
    <Directory "/var/aegir/hostmaster-HEAD/sites/1.mig5-forge.net/files">
      SetHandler This_is_a_Drupal_security_line_do_not_remove
    </Directory>

</VirtualHost>

It's that simple! You can see that via the hook, we pass $uri and the drush data to the function, allowing me to abstract the site url so that each site will get its own error log. You could do extra PHP conditionals to ensure certain data only gets inserted into certain sites of a specific name.

To inject multiple lines instead of one, use an array, i.e

<?php
function mig5_provision_apache_vhost_config($uri, $data) {
    return array("ErrorLog /var/aegir/" . $uri . ".error.log", "LogLevel warn");
}

The key point of this is that the file ~aegir/.drush/mig5.drush.inc file will never be touched by Aegir, so you can rest assured your changes will be respected.

If you want to only inject code into a specific site, wrap your code with an if statement, i.e

<?php
function mig5_provision_apache_vhost_config($uri, $data) {
    if ($uri === "<site-name-in-aegir>") {
        return array("ErrorLog /var/aegir/" . $uri . ".error.log", "LogLevel warn");
    }
}

A more example

In this case we need to inject a rewrite notice to redirect all aliases to one canonical domain. While we could use the GUI option in Aegir, for our workflow, we found that to be unusable.

Our workflow sometimes creates an instance where we need to spin up a copy of the site into production and then switch which site the cname points to. For example. the site's name is Example, and the site url is example.com. In Aegir we have a site called d6.example.com and the new one called d7.example.com. Currently example.com is an alias for d6.example.com and when we are ready to switch over, we will move the "example.com" alias d7.example.com. We cannot redirect all d6.example.com traffic to example.com with the GUI since it would do the opposite, redirect example.com to d6.example.com. Inserting a redirect rule into the vhost will allow us to choose which alias is the canonical one. The code is added to a .drush.inc file. In this case I called it aliasredirects.druch.inc

<?php
function aliasredirects_provision_apache_vhost_config($uri, $data) {
    // the uri to check here is the name of the site in Aegir
    if ($uri === "d6.example.com") {
        $rval[] = "";
        $rval[] = "# Forces redirect to one uri";
        $rval[] = "RewriteEngine On";
        // if the host is not example.com
        $rval[] = "RewriteCond %{HTTP_HOST} !^example.com$ [NC]";
        // rewrite to example.com with a 301 redirect
        $rval[] = "RewriteRule ^(.*)$ http://example.com$1 [R=301,L]";
        $rval[] = "";
        return $rval;
    }
}

#1

Hello, I am trying to find a way to redirect all users of my website to https instead of http. I am trying to follow the "More Advanced example" at the bottom of the documentation, but I really don't have much php experience so I don't want to mess it up. Would this work to redirect all access from the http version to https instead? I have a feeling I might need something different in the $rval[] = "RewriteCond %{HTTPS_HOST} !^example.com$ [NC]"; line, to make it about the https instead of example.com, but I'm not sure. Any thoughts or help? Thank you!

<?php
function aliasredirects_provision_apache_vhost_config($uri, $data) {
   
// the uri to check here is the name of the site in Aegir
   
if ($uri === "example.com") {
       
$rval[] = "";
       
$rval[] = "# Forces redirect to one uri";
       
$rval[] = "RewriteEngine On";
       
// if not https
       
$rval[] = "RewriteCond %{HTTPS_HOST} !^example.com$ [NC]";
       
// rewrite to example.com with a 301 redirect
       
$rval[] = "RewriteRule ^(.*)$ https://example.com$1 [R=301,L]";
       
$rval[] = "";
        return
$rval;
    }
}
?>

#2

I think I've gotten closer with some more research. This is what i have now:

<?php
function aliasredirects_provision_apache_vhost_config($uri, $data) {
// the uri to check here is the name of the site in Aegir
if ($uri === "example.com") {
$rval[] = "";
$rval[] = "RewriteEngine On";
$rval[] = "RewriteCond %{HTTPS} !=on";
$rval[] = "RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]";
$rval[] = "";
return
$rval;
}
}
?>

#3

OK! This works now! Just make sure that your file is called aliasredirects.drush.inc (the first part needs to be the same as your function, at least that is what seemed to get it to work for me).

<?php
function aliasredirects_provision_apache_vhost_config($uri, $data) {
   
// the uri to check here is the name of the site in Aegir
   
if ($uri === "example.com") {
       
$rval[] = "";
       
$rval[] = "RewriteEngine On";
       
// check to see if https is not on first
       
$rval[] = "RewriteCond %{HTTPS} !=on";
       
// rewrite to https with a 301 redirect
       
$rval[] = "RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]";
       
$rval[] = "";
        return
$rval;
    }
}
?>

#4

We have (at the moment unstable) modules to allow custom entries in settings.php and vhosts from the site settings page.
See: Hosting injections
and: Provision hosting injections

Need help?

Documentation

The notebook section provides a way for you to store and share information with your group members. With the book feature you can:

  • Add book pages and organize them hierarchically into different books.
  • Attach files to pages to share them with others.
  • Track changes that others have made and revert changes as necessary.
  • Archive books that are no longer of interest to the group. Archived books can be reactivated later if needed.

The revisions let you track differences between multiple versions of a post.