Correct Laravel application directory structure for proper security

In our first tutorial about Laravel development on Ubuntu, I had recommended moving the contents of the public folder in the Laravel installation up to the Laravel “root” directory. As I’ve been working on my application and these tutorials, I’ve realized that this was a short-sighted approach in the interest of expediency for development, which will cause difficulty when we want to deploy our application later. In particular, we want to apply the principle of least privilege and, accordingly, only make the necessary files available to our users. In general, this would be the contents of the public folder of our Laravel project.

For this example, we are going to consider the common scenario where we are using shared hosting. In this situation, on the hosting provider server, we typically have a “public” directory, often named www or public_html or similar, and other folders which are “private”. We will configure our development environment similarly by putting the contents of the Laravel public folder in the Ubuntu standard Apache “public” site folder (/var/www/html) and the remainder of the Laravel application files in a folder (sub-directory) under our projects folder.

Let’s begin by assuming that we have a standard “clean” Laravel installation in ~/projects/laravel-project. By “clean”, we mean that the public folder is unchanged from the installation using composer create-project laravel/laravel laravel-project --prefer-dist. In the Terminal, run:

sudo mkdir /var/www/html/project
sudo chown -hR username:username /var/www/html/project
cp -R ~/projects/laravel-project/public/* /var/www/html/project
sudo chown www-data:www-data /var/www/html/project/.htaccess
rm -rf ~/projects/laravel-project/public

where username is your Linux user ID. We are simply copying the contents of the Laravel public folder to the new directory for this particular application (project) in the standard Apache “public” directory. I recommend using similar naming between the main (base) Laravel directory and the “public” directory with laravel in the name for the application directory and the “simple” name (without laravel) for the “public” directory. For example, in this case we have laravel-project and project, respectively. Also, note that we must set the ownership of the .htaccess file to the Apache account (www-data).

Next, we’ll set up a specific Apache named virtual host for this directory (/var/www/html/project), which we’ll call project.dev. Create (using sudo!) a new configuration file named /etc/apache2/sites-available/project.dev.conf and add the following to the file:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	ServerName project.dev
	DocumentRoot /var/www/html/project

	<Directory "/var/www/html/project/">
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
	</Directory>

	LogLevel warn
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Also, add project.dev as an alias for 127.0.0.1 to /etc/hosts so that we can use URL http://project.dev/ in the web browser. Finally, activate the new named virtual host and restart Apache server:

sudo a2ensite project.dev.conf
sudo service apache2 restart

Now, we need to update the paths in two of the files that are part of application:

  • ~/projects/laravel-project/bootstrap/paths.php
  • /var/www/html/project/index.php

In each of these files, we are going to set the fully-qualified path names for the relevant files. You can certainly use the __DIR__ PHP “magic” constant and relative path names, but it often gets tricky about the number of levels that you need to move.

In ~/projects/laravel-project/bootstrap/paths.php, change these attributes in the array to:

'app' => '/home/username/projects/laravel-project/app',
'public' => '/var/www/html/project',
'base' => '/home/username/projects/laravel-project',
'storage' => '/home/username/projects/laravel-project/app/storage',

Again, change username in these to your Linux user ID.

Similarly, in /var/www/html/project/index.php, change the require and require_once directives to:

require '/home/username/projects/laravel-project/bootstrap/autoload.php'; 
$app = require_once '/home/username/projects/laravel-project/bootstrap/start.php';

After you have made these changes, you should be able to successfully run the application by going to http://project.dev/ in the web browser. This should display the standard “You have arrived” Laravel page. It should NOT be necessary to include /index.php in the URL, since the .htaccess file in /var/www/html/project removes it.

If you have trouble, make sure that the Apache mod_rewrite extension is enabled:

sudo a2enmod rewrite
sudo service apache2 restart

Likewise, ensure that you have AllowOverall All set in your virtual host configuration (or globally via the /etc/apache2/apache.conf file in the <Directory /var/www/> section).

With these changes, you should now be able to update your Laravel application files in ~/projects/laravel-project and changes to the “public” files in /var/www/html/project should not be necessary. Each time you make a change to the application, just refresh http://project.dev/ in your browser to observe the change.

To confirm this, open the app/routes.php file and add a new route to the end of the file:

Route::get('test', function()
{
	echo 'This is the "test" route!';
});

In the web browser, enter the URL http://project.dev/test (without index.php or trailing slash). The browser should simply display the text This is the “test” route!.

In addition, you will need to update the debugging configuration in Aptana (or Eclipse) to reference the appropriate URL (http://project.dev/). You will probably want to create a new External Web Server Configuration and set the Base URL to http://project.dev and the Document Root to /home/username/projects/laravel-project. In your Debug Configuration, set the Initial Script to bootstrap/start.php. Likewise, you will want to uncheck (disable) URL Auto Generate and leave the URL with just the base URL of http://project.dev/.

References

Setup Laravel 4 in Shared Hosting While Securing Laravel base files
Ubuntu 12.04 Laravel and mod rewrite

Advertisements

2 thoughts on “Correct Laravel application directory structure for proper security

    • Thanks for the feedback…
      I’ve been reading a variety of resources online and just kind of practicing myself. As you can tell from the (in)frequency of posts, it takes a good bit of time to figure some of this stuff out. I want to be thorough, since most of the online tutorials and references that I find (seem to) assume a significant amount of experience.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s