How to install a Laravel site on InfinityFree

Laravel is one of the most popular PHP frameworks, but it was not designed with regular shared web hosting in mind. Some parts of Laravel work out of the box on InfinityFree, some need a bit of configuration, and some features cannot be used at all. This article walks you through what to do, what to watch out for, and what you’ll need to work around.

The document root problem

When you install Laravel, you get a folder structure that looks roughly like this:

my-laravel-app/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
│   └── index.php
├── resources/
├── routes/
├── storage/
├── vendor/
└── .env

The public folder is meant to be the web root. Everything outside of it is meant to be private: your .env file with database credentials, your application code, your logs, your dependencies, none of it should be reachable from the web. Only the public folder, which contains the front controller (index.php) and your CSS, JavaScript, and uploaded files, is supposed to be web-accessible.

Most web servers let you configure which folder is served as the web root, and Laravel expects you to point yours at public. On InfinityFree, the web root is always the htdocs folder of your hosting account, and there is no way to change that. If you upload your Laravel application into htdocs as-is, your application code, configuration, and database credentials become directly accessible over the web.

The solution

You can fix this with two .htaccess rules. The idea is simple: upload your entire Laravel application into htdocs, then use rewrite rules to make every request behave as if it came in through the public folder.

Step 1: Prepare and upload your Laravel application

Before uploading, you need to prepare your project locally because some things cannot be done on the server:

  • Install dependencies. Run composer install --no-dev locally so the vendor folder is populated with only the dependencies needed in production. This folder is usually excluded from version control, so it won’t be there if you cloned from Git. The --no-dev flag skips development tools like PHPUnit and debugging packages, which keeps the file count down and avoids uploading code that has no purpose on the server.
  • Compile your frontend assets. If your project uses Vite or Mix, run npm install and npm run build locally to compile your CSS and JavaScript. You cannot run npm commands on InfinityFree, so this must happen on your own machine.
  • Do not upload node_modules. This folder is only needed during asset compilation and serves no purpose on the server. It contains tens of thousands of files and will waste a significant chunk of your inode quota.

Once prepared, upload your complete Laravel project into the htdocs folder of your hosting account. After uploading, your file structure should look like this:

htdocs/
├── app/
├── bootstrap/
├── config/
├── public/
│   ├── index.php
│   └── .htaccess
├── storage/
├── vendor/
└── .env

Make sure your .env file is uploaded too. FTP clients sometimes hide dotfiles by default, so check your client’s settings if you don’t see it. You will also need to create one more file, .htaccess in the htdocs folder, which is covered in the next step.

Step 2: Create an .htaccess file in htdocs

Create a file called .htaccess directly in the htdocs folder (not inside public) with this content:

apache

RewriteEngine On
RewriteRule (.*) /public/$1 [L]

That is the entire file. This rule rewrites every incoming request to go through the public folder. A request for / becomes /public/, a request for /about becomes /public/about, and so on.

This works as a security measure too. Any request for a sensitive file like /.env or /storage/logs/laravel.log will be rewritten to /public/.env or /public/storage/logs/laravel.log, which do not exist, so visitors get a 404 instead of the actual file.

Note: Laravel ships with its own .htaccess file inside the public folder, which handles routing requests to index.php. Do not modify or delete it. The two files work together: the one in htdocs redirects requests into public, and the one in public hands them off to Laravel’s front controller. If for some reason the public/.htaccess file is missing, you can recreate it with Laravel’s standard content:

<IfModule mod_rewrite.c>
   <IfModule mod_negotiation.c>
       Options -MultiViews -Indexes
   </IfModule>

   RewriteEngine On

   # Handle X-XSRF-Token Header
   RewriteCond %{HTTP:x-xsrf-token} .
   RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}]

   # Redirect Trailing Slashes If Not A Folder...
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_URI} (.+)/$
   RewriteRule ^ %1 [L,R=301]

   # Send Requests To Front Controller...
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^ index.php [L]
</IfModule>

Handling file storage

If your application uses Laravel’s public disk to store user uploaded files (avatars, attachments, and so on), there is one more thing to set up. Laravel normally expects you to run php artisan storage:link, which creates a symlink from public/storage to storage/app/public. InfinityFree does not support symlinks, so you need an alternative.

The fix is another rewrite rule. Open the .htaccess file you created in htdocs and add a second rule before the catch-all:

RewriteEngine On
RewriteRule ^storage/(.*)$ /storage/app/public/$1 [L]
RewriteRule (.*) /public/$1 [L]

The new rule maps any request for /storage/something.jpg to the actual file in storage/app/public/something.jpg. Order matters here: the storage rule must come before the catch-all, otherwise the request gets sent to /public/storage/... first and never reaches the right file.

If your application does not use file uploads or the public disk, you can skip this step.

Configuration tips

A few Laravel settings to check before going live:

  • Set APP_ENV=production and APP_DEBUG=false in your .env file. Leaving debug mode on in production exposes sensitive information whenever an error occurs.
  • Set APP_URL to your actual domain, including https:// if you have SSL enabled (which you should).
  • Set SESSION_DRIVER=file and CACHE_DRIVER=file, since InfinityFree does not provide Redis or Memcached.
  • Set QUEUE_CONNECTION=sync if your application uses queues. InfinityFree does not support background workers, so jobs need to run synchronously during the request.
  • For email, use MAIL_MAILER=smtp with an external SMTP provider. InfinityFree does not provide an email service, so you’ll need to bring your own (Gmail, Mailgun, Brevo, and similar services all work).

For the database, first create a MySQL database from your members area under MySQL Databases. Once created, use the credentials shown there in your .env file. The database host is not localhost, it is a specific hostname shown in the same section.

Things that won’t work

Laravel is a flexible framework, but free hosting does have its limits. A few features you should know about upfront:

  • Scheduled tasks. InfinityFree does not provide cron jobs or any other way to run scheduled tasks. Anything that relies on php artisan schedule:run cannot run on free hosting. If your application depends on scheduled tasks, premium hosting is the only real option.
  • Queue workers. InfinityFree does not allow long running background processes, so php artisan queue:work cannot run. You can still use queueable jobs, but only with the sync queue driver, which processes jobs immediately during the request that dispatches them. This works for simple cases but defeats the purpose of queues for slow operations.
  • WebSockets and real-time features. Laravel Echo, Reverb, and similar real-time features require a separate WebSocket server, which is not supported.
  • Artisan commands. You cannot run php artisan from a terminal because shell access is not available. This has practical consequences for setting up your database, since php artisan migrate and php artisan db:seed are the usual ways to populate it. Instead, you can either export your local database as a SQL dump and import it through phpMyAdmin, or use php artisan schema:dump locally to generate a SQL file and import that. After the initial setup, you’ll need to repeat this process for any future schema changes.
  • Large applications. Free hosting comes with strict limits on CPU, memory, and inodes (file count). Laravel applications, especially with a vendor folder containing tens of thousands of files, can hit the inode limit quickly. If your application is complex or has many dependencies, premium hosting is the more practical option.

Common problems

Stale cache after uploading

Laravel caches configuration, routes, and views in the bootstrap/cache and storage/framework folders. When you upload your project, these folders may contain cache files from your local environment that reference paths or settings that don’t match the server. The result is confusing errors that don’t seem to match your actual code.

If something is misbehaving and you can’t figure out why, delete the contents of bootstrap/cache (but keep the folder itself, and keep the .gitignore file inside if present). Laravel will regenerate the cache on the next request. The same applies to compiled views in storage/framework/views.

As a habit, run php artisan optimize:clear locally before uploading, or simply don’t upload the contents of these cache folders in the first place.

Missing files after upload

InfinityFree silently rejects PHP files larger than 1 MB. The file appears to upload successfully, but when you check the server, it is simply not there. This can cause confusing errors where Laravel complains about classes that should exist but suddenly don’t.

The usual culprit is the optimized Composer autoloader. Laravel’s composer.json enables autoloader optimization by default, which generates a class map file at vendor/composer/autoload_classmap.php. On larger projects, this file can easily exceed 1 MB.

If files seem to be missing after upload, regenerate the autoloader without optimization before uploading:

composer dump-autoload --no-dev --optimize=false

This produces a smaller autoloader at the cost of slightly slower class loading. For most Laravel sites on free hosting, the performance difference is not noticeable.

Summary

To setup Laravel on InfinityFree:

  1. Run composer install --no-dev and compile your frontend assets locally. Don’t upload node_modules.
  2. Upload your entire Laravel project into htdocs.
  3. Create an .htaccess file in htdocs with rewrite rules to redirect requests into public and, if needed, map /storage/ to storage/app/public/.
  4. Leave the public/.htaccess file as Laravel ships it.
  5. Configure your .env for production with file based sessions and cache.
  6. Import your database schema through phpMyAdmin, since artisan commands cannot be run on the server.

If you run into issues, create a support topic on the forum with details about what you tried and any error messages you see.

3 Likes