When setting up a server get your root folder config right

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the web-development category.

Last Updated: 2024-03-28

When setting up a web-server (apache/nginx), the most likely thing to be broken is the root folder setting.

I deployed a Laravel app to Heroku and every URL gave weird errors

$ curl https://myapp-staging.herokuapp.com/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body></html>

or

$ curl -H 'Accept: application/json' -H 'Authorization: Bearer jjkljkljlk' https://myapp-staging.herokuapp.com/users
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>

I fixed it with a Procfile specifying arguments to pass to apache - specifically where the root folder was (public)

web: vendor/bin/heroku-php-apache2 public

SO what is this "root directory"?

"The document root is the directory where the application will begin looking for your .php files. To change the document root, you may supply the path to the directory (relative to your application root directory) as an argument to the boot script. It is not necessary to change configuration files or rewrite rules to define the document root. For example, if you’re using Apache with PHP, and you'd like your document root to be set to the public sub-directory of your application (because that’s where your index.php and all images, CSS and JavaScript reside), your Procfile would look point to public folder like above " - https://devcenter.heroku.com/articles/custom-php-settings#setting-the-document-root

But wait, why is public useful for Laravel? Well, you'll notice that public/index.php contains the entry point for the whole application. Its code:

<?php

define('LARAVEL_START', microtime(true));

require __dir__.'/../vendor/autoload.php';

$app = require_once __dir__.'/../bootstrap/app.php';

$kernel = $app->make(illuminate\contracts\http\kernel::class);

$response = $kernel->handle(
    $request = illuminate\http\request::capture()
);

$response->send();

$kernel->terminate($request, $response);