Part 3 of Laravel in Production.
You uploaded your Laravel project, the home page opens, and every other page shows 404. I have seen this exact fault on shared hosting, on a cloud server, and on my own laptop server. In most cases the code is fine. The server is looking in the wrong folder. Laravel expects requests to reach public/index.php. If the web root points at the project folder instead, the home page can load by luck while the rest fail, or the whole site breaks in a way that looks like a routing bug. I will also show the two log lines that tell you the server hit the wrong folder, so you can prove the cause. This tutorial walks through the check I run first, how to set the document root on cPanel and on a plain Apache or Nginx server, and how to confirm the fix in a private browser window before you touch any route file.
The 2 minute check
Do not edit any code yet. Open two addresses in a private browser window:
- Your home page:
https://your-site.com/ - One inner route:
https://your-site.com/login(or any page that works on your laptop)
Then open a third address: https://your-site.com/index.php/login
The third address tells you almost everything:
-
/index.php/loginworks,/loginshows 404 — your routes are fine. The server is not rewriting inner requests toindex.php. That is the.htaccess/ rewrite problem, covered in step 2 below. - Both fail, and the home page also fails or shows a folder listing — the web root is pointing at the wrong folder. That is step 1.
- Everything works in the private window — you were logged in locally or your browser cached the old site. Log out, hard refresh, and test again before changing anything.
One more piece of proof, from two logs. First open storage/logs/laravel.log, then load the failing route again. If no new line appears in Laravel's log, Laravel never saw the request — the fault is in the server setup, not in your routes. Then check the web server's error log (on cPanel: Metrics, then Errors). A wrong web root leaves a line like this:
[error] [client 203.0.113.8] File does not exist: /home/youruser/public_html/login That path is the giveaway. The server looked for a real file called login inside public_html, found nothing, and answered 404 itself. It never passed the request to Laravel, so no route file edit will fix it.
Step 1: Point the web root at the public folder
Laravel's only public folder is public/. Every request has to enter through public/index.php. If the server's document root is the project folder itself, the app is exposed in the wrong way and inner routes break.
cPanel. Go to Domains, find your domain, and set the Document Root to the public folder inside your project, for example /home/youruser/public_html/public if the project sits in public_html. Two warnings from my own deploys:
- Set the document root inside
public_htmlwhen you create the domain or subdomain. On some cPanel setups, a document root outsidepublic_htmlmakes the server quietly ignore your.htaccessfile, and then every route 404s even though the file is correct. - If your plan does not let you change the document root, use the shim method instead: copy
public/index.phpandpublic/.htaccessintopublic_html, then edit the two paths inindex.phpso they point at the real project folder:
require __DIR__.'/../project-folder/vendor/autoload.php'; $app = require_once __DIR__.'/../project-folder/bootstrap/app.php'; Plain Apache. In the virtual host:
DocumentRoot /var/www/your-app/public <Directory /var/www/your-app/public> AllowOverride All Require all granted </Directory> AllowOverride All matters: without it, Apache ignores the .htaccess in step 2. Restart Apache after the change.
Nginx. In the server block:
root /var/www/your-app/public; location / { try_files $uri $uri/ /index.php?$query_string; } Reload Nginx, then repeat the 2 minute check.
Step 2: Check .htaccess and index.php placement
Inside public/ there must be two files: index.php and .htaccess. After an FTP upload, the .htaccess is the file most often missing, because some FTP clients hide dotfiles. Turn on "show hidden files" in your client and check.
The standard Laravel .htaccess is short:
<IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews -Indexes </IfModule> RewriteEngine On # Handle Authorization Header RewriteCond %{HTTP:Authorization} . RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # 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> Also check permissions. Folders should be 755 and files 644. This sounds basic until it bites you: I have seen uploads land with files at 660 and folders at 770, owned in a way the web server cannot read. The server then cannot read .htaccess at all, the rewrite rules never apply, and every route 404s while the files look "present" in the file manager. If your static files (CSS, images) also return 404, permissions are the first suspect:
find /var/www/your-app -type d -exec chmod 755 {} \; find /var/www/your-app -type f -exec chmod 644 {} \; On shared hosting without SSH, fix permissions from the file manager, one folder at a time, or ask support to reset them.
Step 3: Clear the cached routes and config
Laravel caches routes and config into bootstrap/cache/. If you uploaded a cache built on your laptop, the server can run routes from your local machine's paths. Clear it on the server:
php artisan route:clear php artisan config:clear php artisan cache:clear No SSH on your plan? Delete these files through the file manager and Laravel rebuilds them on the next request:
bootstrap/cache/config.php bootstrap/cache/routes-v7.php (the name varies slightly by version) With SSH, one more proof: php artisan route:list should show the route you are testing. If the route is missing from that list, the problem is inside the app (see the last section). If it is listed and the document root is right, the server side is done.
Then repeat the 2 minute check, logged out, in a private window. Testing while logged in hides this class of bug, because your session can carry you past a broken login route.
If the main fix fails: three less common causes
1. Wrong APP_URL. Open .env on the server and check APP_URL. It should be the real address, for example APP_URL=https://your-site.com. A wrong value usually does not 404 the page itself — it breaks the links, redirects, and asset URLs the app generates, which looks like random broken pages. Fix the value and run php artisan config:clear again.
2. Case-sensitive file names. Your laptop (Windows or macOS) does not care about letter case in file names. A Linux server does. If routes/web.php calls DashboardController but the uploaded file is dashboardController.php, that one route fails on the server while it worked at home. Symptom to recognise: one or two routes fail, the rest work. Match the file name's case to the class name exactly.
3. An incomplete upload. If the upload stopped halfway, later routes in routes/web.php or a controller file may simply not be on the server. The routes that did upload still work, and the missing ones return a real 404 — because as far as the server knows, they do not exist. Compare the file count and sizes in your FTP client on both sides, and re-upload anything that differs.
Deploy checklist: save this for next time
- Document root points at
public/(or the shim files are in place). -
public/.htaccessexists on the server, and hidden files were shown during upload. - Permissions: folders
755, files644. -
route:clearandconfig:clearrun on the server after upload. -
APP_URLin the server.envmatches the real domain. -
route:liston the server shows the routes you are about to test. - Test
/, one inner route, and/index.php/that-routein a private window, logged out. - Both logs checked once: Laravel's log for new lines, the server error log for
File does not exist.
If you are setting a Laravel site up from zero, my earlier walkthrough covers the full deployment in order: How to put a Laravel website online, step by step.
If your site is stuck on this error and you need it fixed today, I fix Laravel deployment errors through Upwork. Send me the error page and your hosting type and I will tell you the cost before I start: Upwork profile
You can also find my services on Fiverr.

