@title Configuring a Preamble Script
@group config

Adjust environmental settings (SSL, remote IPs) using a preamble script.

Overview
========

If Phabricator is deployed in an environment where HTTP headers behave oddly
(usually, because it is behind a load balancer), it may not be able to detect
some environmental features (like the client's IP, or the presence of SSL)
correctly.

You can use a special preamble script to make arbitrary adjustments to the
environment and some parts of Phabricator's configuration in order to fix these
problems and set up the environment which Phabricator expects.

NOTE: This is an advanced feature. Most installs should not need to configure
a preamble script.

= Creating a Preamble Script =

To create a preamble script, write a file to:

  phabricator/support/preamble.php

(This file is in Phabricator's `.gitignore`, so you do not need to worry about
colliding with `git` or interacting with updates.)

This file should be a valid PHP script. If you aren't very familiar with PHP,
you can check for syntax errors with `php -l`:

  phabricator/ $ php -l support/preamble.php
  No syntax errors detected in support/preamble.php

If present, this script will be executed at the very beginning of each web
request, allowing you to adjust the environment. For common adjustments and
examples, see the next sections.

Adjusting Client IPs
====================

If your install is behind a load balancer, Phabricator may incorrectly detect
all requests as originating from the load balancer, rather than from the
correct client IPs.

If this is the case and some other header (like `X-Forwarded-For`) is known to
be trustworthy, you can read the header and overwrite the `REMOTE_ADDR` value
so Phabricator can figure out the client IP correctly.

You should do this //only// if the `X-Forwarded-For` header is known to be
trustworthy. In particular, if users can make requests to the web server
directly, they can provide an arbitrary `X-Forwarded-For` header, and thereby
spoof an arbitrary client IP.

The `X-Forwarded-For` header may also contain a list of addresses if a request
has been forwarded through multiple loadbalancers. Using a snippet like this
will usually handle most situations correctly:

```
name=Overwrite REMOTE_ADDR with X-Forwarded-For
<?php

// Overwrite REMOTE_ADDR with the value in the "X-Forwarded-For" HTTP header.

// Only do this if you're certain the request is coming from a loadbalancer!
// If the request came directly from a client, doing this will allow them to
// them spoof any remote address.

// The header may contain a list of IPs, like "1.2.3.4, 4.5.6.7", if the
// request the load balancer received also had this header.

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  $forwarded_for = $_SERVER['HTTP_X_FORWARDED_FOR'];
  if ($forwarded_for) {
    $forwarded_for = explode(',', $forwarded_for);
    $forwarded_for = end($forwarded_for);
    $forwarded_for = trim($forwarded_for);
    $_SERVER['REMOTE_ADDR'] = $forwarded_for;
  }
}
```

Adjusting SSL
=============

If your install is behind an SSL terminating load balancer, Phabricator may
detect requests as HTTP when the client sees them as HTTPS. This can cause
Phabricator to generate links with the wrong protocol, issue cookies without
the SSL-only flag, or reject requests outright.

To fix this, you can set `$_SERVER['HTTPS']` explicitly:

```
name=Explicitly Configure SSL Availability
<?php

$_SERVER['HTTPS'] = true;
```

You can also set this value to `false` to explicitly tell Phabricator that a
request is not an SSL request.


Next Steps
==========

Continue by:

  - returning to the @{article:Configuration Guide}.
