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-devlocally so thevendorfolder 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-devflag 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 installandnpm run buildlocally 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
.htaccessfile inside thepublicfolder, which handles routing requests toindex.php. Do not modify or delete it. The two files work together: the one inhtdocsredirects requests intopublic, and the one inpublichands them off to Laravel’s front controller. If for some reason thepublic/.htaccessfile 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=productionandAPP_DEBUG=falsein your.envfile. Leaving debug mode on in production exposes sensitive information whenever an error occurs. - Set
APP_URLto your actual domain, includinghttps://if you have SSL enabled (which you should). - Set
SESSION_DRIVER=fileandCACHE_DRIVER=file, since InfinityFree does not provide Redis or Memcached. - Set
QUEUE_CONNECTION=syncif your application uses queues. InfinityFree does not support background workers, so jobs need to run synchronously during the request. - For email, use
MAIL_MAILER=smtpwith 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:runcannot 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:workcannot run. You can still use queueable jobs, but only with thesyncqueue 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 artisanfrom a terminal because shell access is not available. This has practical consequences for setting up your database, sincephp artisan migrateandphp artisan db:seedare the usual ways to populate it. Instead, you can either export your local database as a SQL dump and import it through phpMyAdmin, or usephp artisan schema:dumplocally 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
vendorfolder 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:
- Run
composer install --no-devand compile your frontend assets locally. Don’t uploadnode_modules. - Upload your entire Laravel project into
htdocs. - Create an
.htaccessfile inhtdocswith rewrite rules to redirect requests intopublicand, if needed, map/storage/tostorage/app/public/. - Leave the
public/.htaccessfile as Laravel ships it. - Configure your
.envfor production with file based sessions and cache. - 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.