{"id":1511,"date":"2017-05-25T17:11:58","date_gmt":"2017-05-25T11:41:58","guid":{"rendered":"https:\/\/pheonixsolutions.com\/blog\/?p=1511"},"modified":"2026-09-23T18:41:43","modified_gmt":"2026-09-23T13:11:43","slug":"codeigniter-404-error-nginx","status":"publish","type":"post","link":"https:\/\/pheonixsolutions.com\/blog\/codeigniter-404-error-nginx\/","title":{"rendered":"How to Fix CodeIgniter 404 Errors on Nginx"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>Date Posted:<\/strong> May 25, 2017<br><strong>Last Updated:<\/strong> September 23, 2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a CodeIgniter application is deployed on an Nginx web server, application routes such as <code>\/login<\/code>, <code>\/admin<\/code>, or <code>\/dashboard<\/code> may return a <strong>404 Not Found<\/strong> error even though the application works correctly on Apache. This usually happens because Nginx needs to be explicitly configured to route requests that do not match physical files or directories to CodeIgniter&#8217;s front controller, <code>index.php<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this guide, we will explain how to configure Nginx URL routing for a CodeIgniter application and resolve 404 errors for custom application routes. The guide also covers the required PHP-FPM configuration, Nginx configuration validation, subdirectory deployments, and common troubleshooting steps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before proceeding, ensure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A CodeIgniter application deployed on an Ubuntu server<\/li>\n\n\n\n<li>Nginx installed and running<\/li>\n\n\n\n<li>PHP-FPM installed and configured<\/li>\n\n\n\n<li>SSH or sudo access to the server<\/li>\n\n\n\n<li>The CodeIgniter application deployed under the configured Nginx document root<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact Nginx configuration may vary depending on your CodeIgniter version, PHP version, application directory structure, and server setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter uses a front controller architecture where application requests are generally processed through:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">index.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, a request such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">may not correspond to an actual <code>\/dashboard<\/code> file or directory on the server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx is configured to look only for physical files, it may return:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">404 Not Found\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, Nginx needs to pass unmatched requests to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Locate the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The default Nginx virtual host configuration is commonly located at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Open the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo vi \/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your application uses a separate virtual host configuration, edit the configuration file associated with your domain instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-available\/example.com\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Configure the <code>location \/<\/code> Block<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add or update the <code>location \/<\/code> block as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The important part is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">try_files $uri $uri\/ \/index.php?$query_string;\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This configuration tells Nginx to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Check whether the requested URI matches an existing file.<\/li>\n\n\n\n<li>Check whether the requested URI matches an existing directory.<\/li>\n\n\n\n<li>If neither exists, forward the request to CodeIgniter&#8217;s <code>index.php<\/code>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This allows CodeIgniter to process routes such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/login\n\/admin\n\/dashboard\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Verify the PHP-FPM Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure your Nginx configuration contains a PHP location block that points to the correct PHP-FPM socket.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location ~ \\.php$ {\n    include snippets\/fastcgi-php.conf;\n    fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The PHP-FPM socket depends on the PHP version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check the available PHP-FPM sockets with:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls \/run\/php\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, you may see:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">php8.1-fpm.sock\nphp8.2-fpm.sock\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use the socket corresponding to your installed PHP version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Verify the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before restarting Nginx, always test the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A successful configuration should return output similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax is ok\ntest is successful\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Reload Nginx<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the configuration test succeeds, reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A reload is generally preferred over a full restart because it applies the configuration without unnecessarily stopping the web server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If required, you can restart Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart nginx\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Test the CodeIgniter Routes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open your CodeIgniter application and test the routes that previously returned 404 errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\nhttps:\/\/example.com\/admin\nhttps:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The requests should now be routed through CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CodeIgniter Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx routing is configured correctly but the application still generates unexpected URLs, verify the CodeIgniter configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For CodeIgniter 3, check:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">application\/config\/config.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set the base URL appropriately:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['base_url'] = 'https:\/\/example.com\/';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you are using clean URLs, you may also configure:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['index_page'] = '';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This allows URLs such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">instead of:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/index.php\/login\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Deploying CodeIgniter in a Subdirectory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the CodeIgniter application is deployed under a subdirectory, the Nginx configuration must account for that path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, if the application is available at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/directory\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">the configuration can be:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/directory\/ {\n    try_files $uri $uri\/ \/directory\/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After making the change, verify the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact configuration for a subdirectory deployment depends on the application&#8217;s document root and PHP-FPM setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Still Returns 404<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify that the <code>try_files<\/code> directive is inside the correct <code>server<\/code> block.<\/li>\n\n\n\n<li>Confirm that the Nginx document root points to the correct CodeIgniter application directory.<\/li>\n\n\n\n<li>Verify that <code>index.php<\/code> exists in the expected location.<\/li>\n\n\n\n<li>Check the Nginx error log.<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo tail -f \/var\/log\/nginx\/error.log\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">PHP-FPM Is Not Working<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the PHP-FPM service:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl status php8.2-fpm\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>php8.2-fpm<\/code> with the PHP-FPM version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also verify the PHP-FPM socket:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls -l \/run\/php\/\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Configuration Test Fails<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Review the error message carefully and correct the configuration before reloading Nginx.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Static Files Are Not Loading<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If CSS, JavaScript, images, or other static files return 404 errors, verify that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The Nginx document root is correct.<\/li>\n\n\n\n<li>The files exist in the expected directories.<\/li>\n\n\n\n<li>File and directory permissions allow Nginx to read them.<\/li>\n\n\n\n<li>The application is generating the correct asset URLs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Recommended Nginx Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A basic CodeIgniter application configuration can look similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">server {\n    listen 80;\n    server_name example.com;\n\n    root \/var\/www\/html\/codeigniter;\n    index index.php index.html;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.php?$query_string;\n    }\n\n    location ~ \\.php$ {\n        include snippets\/fastcgi-php.conf;\n        fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n    }\n}\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> This is a basic example. Production environments should also include HTTPS, appropriate security headers, access controls, logging, and other server-hardening measures.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter 404 errors after migrating an application from Apache to Nginx are commonly related to URL routing and front-controller configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using the Nginx <code>try_files<\/code> directive allows requests that do not correspond to physical files or directories to be passed to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key configuration is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After updating the configuration, always run <code>nginx -t<\/code> before reloading the service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Why does CodeIgniter work on Apache but return 404 on Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Apache and Nginx handle URL rewriting and routing differently. Nginx requires the appropriate <code>try_files<\/code> configuration to forward application routes to CodeIgniter&#8217;s front controller.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What does <code>try_files<\/code> do in Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>try_files<\/code> directive checks whether the requested path corresponds to an existing file or directory. If neither exists, the request is forwarded to the specified fallback, which in this case is CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Do I need to restart Nginx after changing the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You should at least reload Nginx after making configuration changes:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Always test the configuration first:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Why is <code>$query_string<\/code> included in the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/index.php?$query_string\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">preserves the original query parameters when the request is forwarded to CodeIgniter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Can the same configuration be used for CodeIgniter 4?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The general Nginx front-controller approach is similar, but CodeIgniter 4 typically uses the <code>public<\/code> directory as the web root. The Nginx document root and configuration should therefore be adjusted according to the CodeIgniter 4 deployment structure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related Articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How Pheonix Solutions Can Help<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pheonix Solutins provides <strong>web application development, PHP and CodeIgniter development, Linux server administration, Nginx configuration, cloud infrastructure, DevOps, CI\/CD, security hardening, monitoring, and application deployment services<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our team can help deploy, troubleshoot, optimize, secure, and maintain PHP applications across development, staging, and production environments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Talk to our team:<\/strong><br><a href=\"https:\/\/pheonixsolutions.com\/contact-us\/\">https:\/\/pheonixsolutions.com\/contact-us\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When deploying a CodeIgniter application behind Nginx, you may encounter <strong>404 Not Found<\/strong> errors when accessing application routes such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\nhttps:\/\/example.com\/admin\nhttps:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The application may work correctly when hosted on Apache but return 404 errors when deployed on Nginx.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This commonly occurs when Nginx is not configured to forward requests for CodeIgniter routes to the application&#8217;s <code>index.php<\/code> front controller.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide explains how to configure Nginx to correctly handle CodeIgniter routes and resolve these 404 errors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before proceeding, ensure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A CodeIgniter application deployed on an Ubuntu server<\/li>\n\n\n\n<li>Nginx installed and running<\/li>\n\n\n\n<li>PHP-FPM installed and configured<\/li>\n\n\n\n<li>SSH or sudo access to the server<\/li>\n\n\n\n<li>The CodeIgniter application deployed under the configured Nginx document root<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact Nginx configuration may vary depending on your CodeIgniter version, PHP version, application directory structure, and server setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter uses a front controller architecture where application requests are generally processed through:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">index.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, a request such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">may not correspond to an actual <code>\/dashboard<\/code> file or directory on the server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx is configured to look only for physical files, it may return:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">404 Not Found\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, Nginx needs to pass unmatched requests to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Locate the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The default Nginx virtual host configuration is commonly located at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Open the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo vi \/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your application uses a separate virtual host configuration, edit the configuration file associated with your domain instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-available\/example.com\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Configure the <code>location \/<\/code> Block<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add or update the <code>location \/<\/code> block as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The important part is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">try_files $uri $uri\/ \/index.php?$query_string;\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This configuration tells Nginx to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Check whether the requested URI matches an existing file.<\/li>\n\n\n\n<li>Check whether the requested URI matches an existing directory.<\/li>\n\n\n\n<li>If neither exists, forward the request to CodeIgniter&#8217;s <code>index.php<\/code>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This allows CodeIgniter to process routes such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/login\n\/admin\n\/dashboard\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Verify the PHP-FPM Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure your Nginx configuration contains a PHP location block that points to the correct PHP-FPM socket.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location ~ \\.php$ {\n    include snippets\/fastcgi-php.conf;\n    fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The PHP-FPM socket depends on the PHP version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check the available PHP-FPM sockets with:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls \/run\/php\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, you may see:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">php8.1-fpm.sock\nphp8.2-fpm.sock\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use the socket corresponding to your installed PHP version.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> Do not blindly copy the PHP-FPM socket from this example. Verify the socket available on your server first.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Verify the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before restarting Nginx, always test the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A successful configuration should return output similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax is ok\ntest is successful\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Reload Nginx<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the configuration test succeeds, reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A reload is generally preferred over a full restart because it applies the configuration without unnecessarily stopping the web server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If required, you can restart Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart nginx\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Test the CodeIgniter Routes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open your CodeIgniter application and test the routes that previously returned 404 errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\nhttps:\/\/example.com\/admin\nhttps:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The requests should now be routed through CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CodeIgniter Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx routing is configured correctly but the application still generates unexpected URLs, verify the CodeIgniter configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For CodeIgniter 3, check:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">application\/config\/config.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set the base URL appropriately:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['base_url'] = 'https:\/\/example.com\/';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you are using clean URLs, you may also configure:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['index_page'] = '';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This allows URLs such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">instead of:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/index.php\/login\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Deploying CodeIgniter in a Subdirectory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the CodeIgniter application is deployed under a subdirectory, the Nginx configuration must account for that path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, if the application is available at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/directory\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">the configuration can be:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/directory\/ {\n    try_files $uri $uri\/ \/directory\/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After making the change, verify the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact configuration for a subdirectory deployment depends on the application&#8217;s document root and PHP-FPM setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Still Returns 404<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify that the <code>try_files<\/code> directive is inside the correct <code>server<\/code> block.<\/li>\n\n\n\n<li>Confirm that the Nginx document root points to the correct CodeIgniter application directory.<\/li>\n\n\n\n<li>Verify that <code>index.php<\/code> exists in the expected location.<\/li>\n\n\n\n<li>Check the Nginx error log.<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo tail -f \/var\/log\/nginx\/error.log\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">PHP-FPM Is Not Working<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the PHP-FPM service:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl status php8.2-fpm\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>php8.2-fpm<\/code> with the PHP-FPM version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also verify the PHP-FPM socket:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls -l \/run\/php\/\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Configuration Test Fails<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Review the error message carefully and correct the configuration before reloading Nginx.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Static Files Are Not Loading<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If CSS, JavaScript, images, or other static files return 404 errors, verify that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The Nginx document root is correct.<\/li>\n\n\n\n<li>The files exist in the expected directories.<\/li>\n\n\n\n<li>File and directory permissions allow Nginx to read them.<\/li>\n\n\n\n<li>The application is generating the correct asset URLs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Recommended Nginx Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A basic CodeIgniter application configuration can look similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">server {\n    listen 80;\n    server_name example.com;\n\n    root \/var\/www\/html\/codeigniter;\n    index index.php index.html;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.php?$query_string;\n    }\n\n    location ~ \\.php$ {\n        include snippets\/fastcgi-php.conf;\n        fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n    }\n}\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> This is a basic example. Production environments should also include HTTPS, appropriate security headers, access controls, logging, and other server-hardening measures.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter 404 errors after migrating an application from Apache to Nginx are commonly related to URL routing and front-controller configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using the Nginx <code>try_files<\/code> directive allows requests that do not correspond to physical files or directories to be passed to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key configuration is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After updating the configuration, always run <code>nginx -t<\/code> before reloading the service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Why does CodeIgniter work on Apache but return 404 on Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Apache and Nginx handle URL rewriting and routing differently. Nginx requires the appropriate <code>try_files<\/code> configuration to forward application routes to CodeIgniter&#8217;s front controller.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What does <code>try_files<\/code> do in Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>try_files<\/code> directive checks whether the requested path corresponds to an existing file or directory. If neither exists, the request is forwarded to the specified fallback, which in this case is CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Do I need to restart Nginx after changing the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You should at least reload Nginx after making configuration changes:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Always test the configuration first:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Why is <code>$query_string<\/code> included in the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/index.php?$query_string\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">preserves the original query parameters when the request is forwarded to CodeIgniter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Can the same configuration be used for CodeIgniter 4?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The general Nginx front-controller approach is similar, but CodeIgniter 4 typically uses the <code>public<\/code> directory as the web root. The Nginx document root and configuration should therefore be adjusted according to the CodeIgniter 4 deployment structure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related Articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How to Install Nginx on Ubuntu<\/li>\n\n\n\n<li>How to Configure PHP-FPM with Nginx<\/li>\n\n\n\n<li>How to Deploy a PHP Application on Nginx<\/li>\n\n\n\n<li>How to Configure SSL\/TLS with Nginx<\/li>\n\n\n\n<li>Nginx Server Security and Hardening Best Practices<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How Pheonix Solutions Can Help<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pheonix Solutions provides <strong>web application development, PHP and CodeIgniter development, Linux server administration, Nginx configuration, cloud infrastructure, DevOps, CI\/CD, security hardening, monitoring, and application deployment services<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our team can help deploy, troubleshoot, optimize, secure, and maintain PHP applications across development, staging, and production environments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Talk to our team:<\/strong><br><a href=\"https:\/\/pheonixsolutions.com\/contact-us\/\">https:\/\/pheonixsolutions.com\/contact-us\/<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">How to Fix CodeIgniter 404 Errors on Nginx<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Date Posted:<\/strong> May 25, 2017<br><strong>Last Updated:<\/strong> September 23, 2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When deploying a CodeIgniter application behind Nginx, you may encounter <strong>404 Not Found<\/strong> errors when accessing application routes such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\nhttps:\/\/example.com\/admin\nhttps:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The application may work correctly when hosted on Apache but return 404 errors when deployed on Nginx.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This commonly occurs when Nginx is not configured to forward requests for CodeIgniter routes to the application&#8217;s <code>index.php<\/code> front controller.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide explains how to configure Nginx to correctly handle CodeIgniter routes and resolve these 404 errors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before proceeding, ensure you have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A CodeIgniter application deployed on an Ubuntu server<\/li>\n\n\n\n<li>Nginx installed and running<\/li>\n\n\n\n<li>PHP-FPM installed and configured<\/li>\n\n\n\n<li>SSH or sudo access to the server<\/li>\n\n\n\n<li>The CodeIgniter application deployed under the configured Nginx document root<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact Nginx configuration may vary depending on your CodeIgniter version, PHP version, application directory structure, and server setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding the Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter uses a front controller architecture where application requests are generally processed through:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">index.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, a request such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">may not correspond to an actual <code>\/dashboard<\/code> file or directory on the server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx is configured to look only for physical files, it may return:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">404 Not Found\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, Nginx needs to pass unmatched requests to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Locate the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The default Nginx virtual host configuration is commonly located at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Open the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo vi \/etc\/nginx\/sites-enabled\/default\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your application uses a separate virtual host configuration, edit the configuration file associated with your domain instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/etc\/nginx\/sites-available\/example.com\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Configure the <code>location \/<\/code> Block<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add or update the <code>location \/<\/code> block as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The important part is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">try_files $uri $uri\/ \/index.php?$query_string;\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This configuration tells Nginx to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Check whether the requested URI matches an existing file.<\/li>\n\n\n\n<li>Check whether the requested URI matches an existing directory.<\/li>\n\n\n\n<li>If neither exists, forward the request to CodeIgniter&#8217;s <code>index.php<\/code>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This allows CodeIgniter to process routes such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/login\n\/admin\n\/dashboard\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Verify the PHP-FPM Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Make sure your Nginx configuration contains a PHP location block that points to the correct PHP-FPM socket.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location ~ \\.php$ {\n    include snippets\/fastcgi-php.conf;\n    fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The PHP-FPM socket depends on the PHP version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Check the available PHP-FPM sockets with:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls \/run\/php\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example, you may see:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">php8.1-fpm.sock\nphp8.2-fpm.sock\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use the socket corresponding to your installed PHP version.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> Do not blindly copy the PHP-FPM socket from this example. Verify the socket available on your server first.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Verify the Nginx Configuration<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before restarting Nginx, always test the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A successful configuration should return output similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">syntax is ok\ntest is successful\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Reload Nginx<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If the configuration test succeeds, reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A reload is generally preferred over a full restart because it applies the configuration without unnecessarily stopping the web server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If required, you can restart Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl restart nginx\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Test the CodeIgniter Routes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open your CodeIgniter application and test the routes that previously returned 404 errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\nhttps:\/\/example.com\/admin\nhttps:\/\/example.com\/dashboard\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The requests should now be routed through CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CodeIgniter Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If Nginx routing is configured correctly but the application still generates unexpected URLs, verify the CodeIgniter configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For CodeIgniter 3, check:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">application\/config\/config.php\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set the base URL appropriately:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['base_url'] = 'https:\/\/example.com\/';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you are using clean URLs, you may also configure:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$config['index_page'] = '';\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This allows URLs such as:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/login\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">instead of:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/index.php\/login\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Deploying CodeIgniter in a Subdirectory<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If the CodeIgniter application is deployed under a subdirectory, the Nginx configuration must account for that path.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, if the application is available at:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">https:\/\/example.com\/directory\/\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">the configuration can be:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/directory\/ {\n    try_files $uri $uri\/ \/directory\/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After making the change, verify the configuration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then reload Nginx:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note:<\/strong> The exact configuration for a subdirectory deployment depends on the application&#8217;s document root and PHP-FPM setup.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Still Returns 404<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Verify that the <code>try_files<\/code> directive is inside the correct <code>server<\/code> block.<\/li>\n\n\n\n<li>Confirm that the Nginx document root points to the correct CodeIgniter application directory.<\/li>\n\n\n\n<li>Verify that <code>index.php<\/code> exists in the expected location.<\/li>\n\n\n\n<li>Check the Nginx error log.<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo tail -f \/var\/log\/nginx\/error.log\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">PHP-FPM Is Not Working<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check the PHP-FPM service:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl status php8.2-fpm\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>php8.2-fpm<\/code> with the PHP-FPM version installed on your server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also verify the PHP-FPM socket:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ls -l \/run\/php\/\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Nginx Configuration Test Fails<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Review the error message carefully and correct the configuration before reloading Nginx.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Static Files Are Not Loading<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If CSS, JavaScript, images, or other static files return 404 errors, verify that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The Nginx document root is correct.<\/li>\n\n\n\n<li>The files exist in the expected directories.<\/li>\n\n\n\n<li>File and directory permissions allow Nginx to read them.<\/li>\n\n\n\n<li>The application is generating the correct asset URLs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Recommended Nginx Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A basic CodeIgniter application configuration can look similar to:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">server {\n    listen 80;\n    server_name example.com;\n\n    root \/var\/www\/html\/codeigniter;\n    index index.php index.html;\n\n    location \/ {\n        try_files $uri $uri\/ \/index.php?$query_string;\n    }\n\n    location ~ \\.php$ {\n        include snippets\/fastcgi-php.conf;\n        fastcgi_pass unix:\/run\/php\/php8.2-fpm.sock;\n    }\n}\n<\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> This is a basic example. Production environments should also include HTTPS, appropriate security headers, access controls, logging, and other server-hardening measures.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CodeIgniter 404 errors after migrating an application from Apache to Nginx are commonly related to URL routing and front-controller configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Using the Nginx <code>try_files<\/code> directive allows requests that do not correspond to physical files or directories to be passed to CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key configuration is:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">location \/ {\n    try_files $uri $uri\/ \/index.php?$query_string;\n}\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After updating the configuration, always run <code>nginx -t<\/code> before reloading the service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Why does CodeIgniter work on Apache but return 404 on Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Apache and Nginx handle URL rewriting and routing differently. Nginx requires the appropriate <code>try_files<\/code> configuration to forward application routes to CodeIgniter&#8217;s front controller.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. What does <code>try_files<\/code> do in Nginx?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>try_files<\/code> directive checks whether the requested path corresponds to an existing file or directory. If neither exists, the request is forwarded to the specified fallback, which in this case is CodeIgniter&#8217;s <code>index.php<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Do I need to restart Nginx after changing the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You should at least reload Nginx after making configuration changes:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo systemctl reload nginx\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Always test the configuration first:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nginx -t\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Why is <code>$query_string<\/code> included in the configuration?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/index.php?$query_string\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">preserves the original query parameters when the request is forwarded to CodeIgniter.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. Can the same configuration be used for CodeIgniter 4?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The general Nginx front-controller approach is similar, but CodeIgniter 4 typically uses the <code>public<\/code> directory as the web root. The Nginx document root and configuration should therefore be adjusted according to the CodeIgniter 4 deployment structure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Related Articles<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/pheonixsolutions.com\/blog\/how-to-debug-in-codeigniter\/\">How to debug in Codeigniter<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/pheonixsolutions.com\/blog\/how-to-add-google-recaptcha-in-php-codeigniter\/\">How to add Google ReCAPTCHA in PHP Codeigniter<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Talk to our experts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Have a technology challenge or looking for the right solution for your business? Our team can help you with <strong>cloud, DevOps, development, infrastructure, design, and more<\/strong>. Feel free to reach out to our experts <a href=\"https:\/\/pheonixsolutions.com\/contact\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Date Posted: May 25, 2017Last Updated: September 23, 2026 Introduction When a CodeIgniter application is deployed on an Nginx web [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[1022],"tags":[341,271],"class_list":["post-1511","post","type-post","status-publish","format-standard","hentry","category-web-architecture","tag-codeigniter","tag-nginx","psol-cat-web-architecture"],"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/phn2x7-on","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=1511"}],"version-history":[{"count":1,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1511\/revisions"}],"predecessor-version":[{"id":11897,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1511\/revisions\/11897"}],"wp:attachment":[{"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=1511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=1511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pheonixsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=1511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}