Running behind reverse proxy

Copied from GitHub: https://github.com/farmOS/farmOS.org/issues/62

Pre install, how can I configure the base url so that I can correctly run FarmOS behind a reverse proxy. My only option at the moment is to use IIS as the reverse proxy but some resources are being blocked because they’re not served over the secure endpoint.

farmOS is built on Drupal, and running Drupal behind a reverse proxy is well established (I also run farmOS behind Nginx proxy which terminates the SSL for Farmier servers).

Here are a few resources - but googling “Drupal reverse proxy” should put you on the right track!

Hi,
thank you for the information provided. However I’m quite new to farmOS and hosting and I’m struggling to setup SSL for my farmOS installation. I’ve set up a server running various tools that I need for managing my farm. So I decided to go with various docker containers, traefik as a reverse proxy and use letsencrypt certificates.
I’m using the docker-compose-production.yml with some modifications. Now if I understand correctly I would have to modify the settings.php (and apache configuration) in my farmOS container. Would that not mean that this configuration gets overwritten every time I recreate the container? Is there any (easy) way to make this modification persistent?

I support viktorsmari’s idea for providing a docker-compose variable if it would be possible in any way.

Thank you for creating and providing farmOS!

1 Like
I’m using the docker-compose-production.yml with some modifications. Now if I understand correctly I would have to modify the settings.php (and apache configuration) in my farmOS container. Would that not mean that this configuration gets overwritten every time I recreate the container?

If you’re using the docker-compose.production.yml file that is included in the farmOS repo (https://github.com/farmOS/farmOS/blob/7.x-1.x/docker/docker-compose.production.yml), then the entire sites directory is being mounted as a volume, which includes your settings.php file. The settings.php file is explicitly not included in the Docker image itself, because it will be customized for your specific instance. So editing it to add your reverse proxy configuration is perfectly OK. :slight_smile:

I support [viktorsmari’s idea](https://github.com/farmOS/farmOS/issues/186#issuecomment-503579931) for providing a docker-compose variable if it would be possible in any way.

This would be tricky (for the same reason: the settings.php file is in a mounted volume), so I think it’s best to leave this up to the host to configure.

Perhaps the best thing to do would be to provide more documentation for setting up SSL on farmOS in general. We can point to the Drupal docs, but having a specific working example would be really nice.

1 Like

Thank you for pointing this out! I wasnt aware of this.

I managed to get the thing working by setting the $base_url in settings.php to ‘https://farmos.myDomain.de’. I added this line:
$base_url = 'https://farmos.myDomain.de';

I’m not 100% sure why this works and if there would be a nicer solution, but it works :slight_smile:

What I have tried before:
On this Drupal Site there are 2 solutions listed as far as I understand:
a) modify .hta access by adding

#1 
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
      
# 2 Redirect to HTTPS
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] 

b) adding one of the following to your settings.php

for specific URL:

// Force HTTPS
// PHP_SAPI command line (cli) check prevents drush commands from giving a
// "Drush command terminated abnormally due to an unrecoverable error"
if ( (!array_key_exists('HTTPS', $_SERVER)) && (PHP_SAPI !== 'cli') ) {
  header('HTTP/1.1 301 Moved Permanently');
  header('Location: https://example.org'. $_SERVER['REQUEST_URI']);
  exit();
}

// Remove www
if ($_SERVER['HTTP_HOST'] == 'www.example.org') {
  header('HTTP/1.0 301 Moved Permanently');
  header('Location: https://example.org'. $_SERVER['REQUEST_URI']);
  exit();
}

…or this for generic URL

if ( (!array_key_exists('HTTPS', $_SERVER)) && (PHP_SAPI !== 'cli') ) {
  if (substr($_SERVER['HTTP_HOST'], 0, 4) <> 'www.') {
    $new_url = 'www.' . $_SERVER['HTTP_HOST'];
  } else {
    $new_url = $_SERVER['HTTP_HOST'];
  }
  $new_url .= $_SERVER['REQUEST_URI'];

  header('HTTP/1.1 301 Moved Permanently');
  header('Location: https://'. $new_url);
  exit();
}

In my case neither a) nor b) worked. May be my case is special, since my reverse proxy (traefik) already enforces redirects to https. Secondly my drupal url is https://farmos.myDomain.de (not https://www.myDomain.de

As @mstenta said the settings.php and .htaccess are not in the container but in the volume. In my case the volume is located in the same directory as the docker-compose.yml file which is /home/myUser/docker/farmos/sites
I tried above modifications with .../sites/default/files/.htaccess
and .../sites/default/settings.php

For me it works now with $base_url being set. I wanted to give more details for other users facing the same issue. Maybe someone with better understanding can explain how to solve in a generic manner.

1 Like

Great! Yea setting $base_url in settings.php tells Drupal “all links displayed in the site should use this base URL”. As described in the links posted above, this fixes “mixed content” warnings you might get from Drupal creating http links internally.

On this Drupal Site there are 2 solutions listed as far as I understand:

Both of those chunks of code seem to be specifically for: "redirecting users to https automatically if they come in via http". So that’s slightly different from the $base_url setting above, but also useful.

Personally, I wouldn’t use either of those approaches in your case, though, because you are using a reverse proxy that terminates the SSL and then forwards traffic to the Drupal site via HTTPS. Those redirects would be better configured in the reverse proxy itself, if you can. But they aren’t critical - they just automate the redirect to https. You could also just be sure you’re always visiting the site via https yourself, or use a browser plugin like HTTPS Everywhere. (Personally I would prefer to automate it in the reverse proxy though.)

May be my case is special, since my reverse proxy (traefik) already enforces redirects to https.

Oh I just read this part! Then yes you don’t need to worry about it! :smiley:

As @mstenta said the settings.php and .htaccess are not in the container but in the volume.

Small correction to this: settings.php is in the volume, but .htaccess is NOT! It’s in the webroot, which is one directory up from the sites volume directory.

I tried above modifications with .../sites/default/files/.htaccess

Ah… so there are actually multiple .htaccess files in a Drupal setup… there is the “root” one which is in the root Drupal directory (webroot). That’s where you would need to make changes to redirects (if you needed to).

The .htaccess in sites/default/files is SPECIFICALLY for adding additional security access controls to the files directory, which is where uploaded files are stored. This prevents things like executing malicious code that may have been uploaded.

For me it works now with $base_url being set. I wanted to give more details for other users facing the same issue.

Thanks @PDorfFarm - it sounds like you found the right solution! Thanks so much for documenting your process here! It will certainly be helpful to others.

And if anyone is interested in helping to write a “how to” on farmOS.org for setting up your own SSL, let me know!

FYI there is a related thread on GitHub here with a lot of debugging information: https://github.com/farmOS/farmOS-client/issues/281

2 Likes