Drupal 8 doesn't have the base_url setting in settings.php anymore. What's the proper procedure for running Drupal 8 in a subdirectory?

I have some issues, please verify this is the proper procedure.
My root folder .htaccess has a bit about making all requests go to the drupal8 folder.

.htaccess in the root directory:
Options -Indexes
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{http_host} ^mysite\.com [NC]
RewriteRule ^(.*)$ http://www.mysite.com/$1 [L,R=301]
RewriteRule (.*) drupal8/$1 [L]

In the Drupal .htaccess that's in the drupal8 directory I uncommented and modified a line to be:
RewriteBase /drupal8

Comments

vimalabhi89’s picture

Hi vayu,

Any luck with this. The site redirects fine but the sub directory name still shows up in the url

intrafusion’s picture

After following lots of different posts and different ideas, the following solution worked for me. In case anybody else has a similar set-up to me, I am using Composer to manage Drupal and installed Drupal using the drupal-project Composer template which means you end up with vendor & web directories (plus some others), however the web folder is where Drupal is located, but I couldn't adjust my Apache configuration.

In the root folder I created a .htaccess file with the following contents:

RewriteEngine on
RewriteRule (.*) web/$1 [L]

In web/.htaccess I uncommented the RewriteBase line:

# Modify the RewriteBase if you are using Drupal in a subdirectory or in a
# VirtualDocumentRoot and the rewrite rules are not working properly.
# For example if your site is at http://example.com/drupal uncomment and
# modify the following line:
RewriteBase /web

After clearing all the caches everything worked OK apart from when I tried to access /user I got the following error:
Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.

I was then directed to the work-around at https://www.drupal.org/node/2612160#comment-11767977 and put the following in my settings.php:

if (isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}

Everything appears to be working successfully apart from completion of the database updates as the web element is returned to the URL
and fires a 404, but this is easily dealt with.

peezy’s picture

Thank you, @intrafusion! I've tried a few other things, but this worked perfectly for me.

the_meter413’s picture

Everything in your above comment works except when I get to installing modules. I get a 403 error when trying to install a module, and I see that the URL includes the subdirectory (e.g. https://www.example.com/web/core/authorize.php/). Have you experienced this? Do you have a suggested fix? Thanks again for the above!

vayu’s picture

I don't know how good or safe of a fix this is, I got it from some thread I can't remember where. I've been using it on every new Drupal update that comes out for well over a year now. I always do a compare to the old file to see if it's been changed, so far not. Along with the .htaccess fixes I listed above, I've been using a modified PHP file in Drupal core: /core/lib/Drupal/core/EventSubscriber/RedirectResponseSubscriber.php
There are two lines in the file where LocalRedirectResponse is replaced with trustedRedirectResponse.
At the top of the file I replace the commented line with the one following:
// use Drupal\Core\Routing\LocalRedirectResponse;
use Drupal\Core\Routing\TrustedRedirectResponse;
And in the function public function checkRedirectUrl, I change this commented line with the one following:
// $safe_response = LocalRedirectResponse::createFromRedirectResponse($response);
$safe_response = TrustedRedirectResponse::createFromRedirectResponse($response);

This fix has worked in all cases for me. Like I said I don't know how safe it is, I worry that it might not be because after all this time it's not been changed. But it works for me. So every Drupal update I untar the update, check if those two lines have been changed, replace them, then retar it up and install it.

* Update,  The post above by @intrafusion has been working well for me, I haven't found any case where it doesn't and it doesn't mess with core.

intrafusion’s picture

I've not experienced this personally, but this set-up is only on our live site and all the config is imported/exported.

To give a broader explanation the modules are enabled, plus any additional set-up is exported from our development machine using Drush drush config-export --destination=../config/base which allows the config to be added into source control, the config directory is at the same level as the web directory. Once the new config has been deployed to the live server we run drush config-import --source=../config/base and it keeps the config in sync.

There are more details about this at https://www.drupal.org/docs/8/configuration-management/managing-your-sit...

andpet’s picture

Hello, guys. Everything works perfect, thanks! But it doesn't if I'm trying to access site without "www" (I have those lines in .htaccess uncommented to redirect from without www to with www). If I'm trying to access site like http://example.com, I got redirect to http://www.example.com/web.

Any ideas?

gmaxwelled’s picture

A pain-free solution, if your shared hosting setup allows for it, is:

  1. Rename your web root folder to 'drupal'
  2. Create a symlink with the name of your original web root (mine is public_html), pointing to '/drupal/web'
jmoruzi’s picture

I know it's been a while since anyone commented, but can someone please explain ho to set up the symlink?

vayu’s picture

To answer your direct question: You need to have shell/ssh access.  With that then from the command line with root access:

ln -s public_html drupal/web

you would have had to first created the folders drupal/web before that.

I've been having success using .htaccess the way I showed up top combined with intrafusion's bit added to settings.php.

if (isset($GLOBALS['request']) && '/web/index.php' === $GLOBALS['request']->server->get('SCRIPT_NAME')) {
  $GLOBALS['request']->server->set('SCRIPT_NAME', '/index.php');
}
lindaweb’s picture

This works, but now I am unable to upload images.

getting the following error :

The upload directory public://2019-11 for the file field field_page could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.

lindaweb’s picture

Fixed by editing :

 * Public file path:
 *
 * A local file system path where public files will be stored. This directory
 * must exist and be writable by Drupal. This directory must be relative to
 * the Drupal installation directory and be accessible over the web.
 */
$settings['file_public_path'] = '***/sites/default/files';

finabluma’s picture

Hi everyone!

I experience an issue when I installed drupal in a subdirectory. Everything works fine but It doesn't when it's time to run updates. The system fires the following message ...

In order to run update.php you need to either have "Administer software updates" permission or have set $settings['update_free_access'] in your settings.php.

 I have installed drupal using drupal-recommend composer. I have been searching around and I have not found anything that could give some light in order to solve this issue. Everytime I have to run updates I have to go to my settings.php. Any idea to solve this?

vayu’s picture

I never thought that's because of running in a sub directory.  Seems like you know how to fix it but in case not,

What I do is go to the settings file; update the file's permissions to read/write; then search for "free". That brings me to the line:
 

$settings['update_free_access'] = FALSE;

Change the FALSE to TRUE; Run the update; When it's done change the TRUE back to FALSE. Save the file and adjust the file permission back to read only.

Maybe it's because of the directory issue but I've imagined that that process makes it safer that the update is run by intentional and authorized means.

winkflo’s picture

I followed the instructions of @intrafusion to run my Drupal 8.7.10-Site with my Shared-Host-Provider. Everything runs fine except the Database Update.

I changed the update_free_access to TRUE in settings.php as said by @vayu. It is then possible to start MYSITE/update.php. But when I click 'Continue' I can see that the URL is changing in MYSITE/web/update.php/selection. The process of updating the database stops here because Drupal returns only one option: Front page. This ends in MYSITE/web and this of course shows 'Site not found'.

So it seems that I can start the update-process but Drupal changes the URL during the process and adds the name of the subfolder /web to the URL.

vayu’s picture

DId you make the .htaccess changes from the very first post?  Also are you sure the update didn't complete successfully?  For me the update completes and I then get the URL in my browser replaced with the /web directory but I ignore it. After I delete the /web part in the browser URL, I can refresh my browser and everything is fine from then on.

winkflo’s picture

Thank you @vayu. I did not notice that the update completed correctly anyway. I've tested it again and the behavior is as described by you.

AMV007’s picture

Hi all,
Through web interface after downloading module (token in my case) and click continue: 

Access denied
You are not allowed to access this page.

if trying with composer and drush, after drush updatedb got:

In ProcessBase.php line 188:                                                   
  Unable to decode output into JSON: Syntax error

don't know how to solve it, may be some one else know ?