CodeIgniter ships with URLs that look like example.com/index.php/products/view/42 by default. That index.php segment is the front controller, and every request is routed through it. On shared hosting this is harmless functionally, but it produces ugly URLs, weakens how search engines read your paths, and creates duplicate-content risk because the same page is reachable with and without the segment. The fix is a combination of correct application configuration and a small set of rewrite rules handled entirely from your hosting account, with no server-level access required.

This article assumes you are running CodeIgniter 3 or CodeIgniter 4 on a Managed Cloud Shared Hosting plan using LiteSpeed Web Server. LiteSpeed reads standard Apache .htaccess directives natively, so the rewrite syntax you would use on Apache works unchanged. Everything below is done through cPanel Jupiter or DirectAdmin Evolution File Manager, the application config files in your document root, and the local error_log.

Why index.php appears and what controls URL structure

CodeIgniter uses a single entry point. All traffic is meant to hit index.php, which bootstraps the framework and dispatches the request to the right controller and method. Without a rewrite rule, the web server has no way to know that /products/view/42 should be handed to index.php, so it looks for a literal folder named products and returns a 404 when it cannot find one. That is why removing index.php is not merely cosmetic: you must also tell the server to internally route non-file requests back to the front controller.

Two configuration values control how the framework builds and interprets URLs. In CodeIgniter 3 these live in application/config/config.php. The base_url setting defines the absolute root of your site and should be set explicitly rather than left blank, because an empty value forces the framework to guess based on request headers, which breaks behind proxies and causes mixed canonical signals. The index_page setting controls whether generated links include index.php. Set it as follows once your rewrite is in place:

$config['base_url'] = 'https://example.com/';
$config['index_page'] = '';
$config['uri_protocol'] = 'REQUEST_URI';

In CodeIgniter 4 the equivalent values are in app/Config/App.php as the $baseURL and $indexPage properties, or better, in the project .env file using app.baseURL and app.indexPage. Setting $indexPage = '' tells the URL helper to generate clean links. If you remove index.php from generated links but never add the rewrite rule, every internal link on your site will 404, so always change the config and the .htaccess together.

The uri_protocol value deserves attention on LiteSpeed. The default REQUEST_URI works for the vast majority of shared accounts. If you see controller segments being truncated or query strings behaving oddly, switching to PATH_INFO or QUERY_STRING can resolve it, but try REQUEST_URI first since it is the most predictable on LiteSpeed.

Writing the .htaccess rewrite to remove index.php

Open cPanel Jupiter and launch File Manager, or in DirectAdmin Evolution open the File Manager tile. Navigate to the folder that contains index.php for your installation. On most CodeIgniter 4 deployments the public entry point is in a public/ subdirectory, while CodeIgniter 3 typically places index.php directly in the web root. Make sure File Manager is showing hidden files (Settings, then enable “Show Hidden Files”), then create or edit .htaccess in that same directory.

For a standard CodeIgniter 3 install where index.php sits in the document root, use this rule set:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    # Block direct access to the application and system folders
    RewriteRule ^(application|system)/ - [F,L]

    # Serve real files and directories directly
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

The two RewriteCond lines are the important part. They tell LiteSpeed to only rewrite a request to index.php when the requested path is not an existing file (!-f) and not an existing directory (!-d). This keeps your real assets — images, CSS, JavaScript, robots.txt, and your sitemap — serving directly instead of being swallowed by the framework. The explicit block on application and system prevents anyone from requesting source files by path.

If your CodeIgniter 4 app lives in a subfolder but you want the site served from the domain root, the cleanest approach is to point the domain's document root at the public/ directory. In cPanel this is done through Domains, where you can set the document root for an addon or subdomain to /home/user/yourapp/public. CodeIgniter 4 already ships a working .htaccess inside public/, so once the document root points there, clean URLs work without further editing. Avoid the common workaround of rewriting the root to public/index.php from a parent .htaccess; pointing the document root is faster on LiteSpeed and avoids exposing the writable and app folders.

After saving, clear any LiteSpeed cache for the domain (in cPanel, the LiteSpeed Web Cache Manager, or simply append a cache-busting query string while testing) and load an internal URL without index.php. If it resolves, the rewrite is active. If you get a 500 error, the most common cause on shared hosting is a stray Options +FollowSymLinks line that the account policy disallows — remove it, because the rule set above does not need it.

Enforcing HTTPS, www, and trailing-slash canonicals

Search engines treat http and https, www and non-www, and trailing-slash variants as distinct URLs unless you redirect them. Pick one canonical form and enforce it with 301 redirects placed above your CodeIgniter rewrite block, so they run first. To force HTTPS and strip www:

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Force HTTPS
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    # Strip www
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
</IfModule>

Keep these rules in a single <IfModule> block above the index.php rewrite, and make sure base_url in your config matches the canonical form exactly (same scheme and host). A mismatch here is the top cause of redirect loops: if base_url says https://www.example.com but your rule strips www, the framework and the rewrite fight each other and the browser reports “too many redirects.”

For sitemaps, CodeIgniter does not generate one automatically. Create a controller that outputs XML with the correct Content-Type header, or generate a static sitemap.xml and place it in the document root — the !-f condition ensures it serves directly. Reference it in a robots.txt file in the same directory with a Sitemap: line pointing at the canonical absolute URL.

Diagnosing 404 and routing failures

When clean URLs 404 after setup, work through a short checklist. First confirm the request is actually reaching PHP: if the server shows a styled Apache or LiteSpeed 404 rather than CodeIgniter's own 404 page, the rewrite is not firing and the problem is in .htaccess placement or location. The file must be in the same directory as the index.php it references.

If you see CodeIgniter's own 404, the rewrite is working and the issue is routing. In CodeIgniter 3 check application/config/routes.php for the $route['default_controller'] value and verify controller filenames use an uppercase first letter (Products.php), since Linux filesystems are case-sensitive and a lowercase products.php will not load. CodeIgniter 4 route definitions live in app/Config/Routes.php. Watch for $routes->setAutoRoute(false), which disables automatic controller mapping and requires every path to be declared explicitly.

Your local error_log is the fastest diagnostic tool. In File Manager, look for error_log in the document root or the installation folder; LiteSpeed writes PHP fatals and 500-level errors there. To raise verbosity temporarily, set the environment to development in CodeIgniter 4's .env (CI_ENVIRONMENT = development) or in CodeIgniter 3's index.php, then revert to production once resolved so stack traces are never shown to visitors. If PHP throws a version error, use the MultiPHP Manager in cPanel or the PHP Selector in DirectAdmin to match the PHP version to your framework's requirement — CodeIgniter 4 needs PHP 7.4 or newer, with 8.1+ recommended. Per-directory PHP settings such as memory_limit can be adjusted through a .user.ini file in the same folder without touching any server-wide configuration.